Build fast, reply faster. Generate concise, context‑aware email replies using Google Gemini.
email-writer-sb/— Spring Boot backend APIemail-writer-react/— React UI (Vite)email-writer-extension/— Gmail content‑script extensionhello-world-ext/— Minimal example extension
- Java 21, Spring Boot Web + WebFlux
- Node.js (Vite, React, MUI)
- Chrome Extension (Manifest v3)
- Java 21
- Maven (or use the included Maven Wrapper
mvnw/mvnw.cmd) - Node.js 18+ and npm
- Google Chrome (for the extension)
- A Google Gemini API key
Location: email-writer-sb/
Configure environment variables for Gemini before running:
GEMINI_URLshould be the base endpoint including the?key=suffix, e.g.https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=GEMINI_KEYis your API key
On Windows PowerShell:
setx GEMINI_URL "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key="
setx GEMINI_KEY "<YOUR_API_KEY>"
# Open a new terminal after setx, or for the current session:
$Env:GEMINI_URL = "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key="
$Env:GEMINI_KEY = "<YOUR_API_KEY>"On macOS/Linux (bash/zsh):
export GEMINI_URL="https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key="
export GEMINI_KEY="<YOUR_API_KEY>"Run the API:
cd email-writer-sb
# macOS/Linux
./mvnw spring-boot:run
# Windows
mvnw.cmd spring-boot:runBy default the server starts at http://localhost:8080.
- POST
/api/email/generate- Request headers:
Content-Type: application/json - Request body:
{ "emailContent": "<paste the original email text>", "tone": "professional" // optional: professional | friendly | casual | formal } - Response:
text/plain— generated reply body only (no subject/greetings/sign-off)
- Request headers:
Example cURL:
curl -s -X POST http://localhost:8080/api/email/generate \
-H "Content-Type: application/json" \
-d '{
"emailContent": "Thanks for your update on the project timeline...",
"tone": "professional"
}'Location: email-writer-react/
Start the UI:
cd email-writer-react
npm install
npm run devThe app runs on Vite’s dev server (e.g., http://localhost:5173) and calls the backend at http://localhost:8080.
Location: email-writer-extension/
Load the extension locally:
- Open
chrome://extensionsin Chrome - Enable “Developer mode” (top right)
- Click “Load unpacked” and select the
email-writer-extension/folder - Open Gmail; when the compose window appears, an “AI Reply” button should be injected in the toolbar. Clicking it calls the backend and inserts the generated reply into the compose box
Tip: Ensure the backend is running at http://localhost:8080 when testing the extension.
Location: hello-world-ext/
This is a minimal MV3 extension example. Load it via “Load unpacked” the same way as above.
- Controller:
EmailGeneratorControllerexposesPOST /api/email/generate - Request model:
EmailRequestwith fieldsemailContentandtone - Service:
EmailGeneratorServicebuilds a prompt and posts to Gemini using WebClient - Config:
application.propertiesmapsgemini.api.urlandgemini.api.keyto the environment variablesGEMINI_URLandGEMINI_KEY
- Gemini 401/403 or 404: Double-check
GEMINI_URLincludes the?key=suffix and thatGEMINI_KEYis correct. Ensure your model name and path are valid for your key/region. - CORS errors in the React app: The backend enables CORS for all origins on the controller. Make sure the API is reachable at
http://localhost:8080. - Gmail button not appearing: Gmail’s DOM changes often. Try opening a new compose window, or refresh Gmail. Open DevTools Console to see logs from
content.js. - Extension host permissions: If network calls are blocked, verify the extension manifest has correct
host_permissionsforhttp://localhost:8080/*and Gmail.
- Backend:
mvnw spring-boot:run,mvnw clean package - Frontend:
npm run dev,npm run build,npm run preview
- Do not commit API keys. Use environment variables (
GEMINI_URL,GEMINI_KEY). - In production, restrict CORS and place the API behind proper authentication and rate limits.
No license specified yet.