Outsync is a full-stack AI web application that generates personalized academic outreach emails using a stateful LangGraph pipeline and Gemini 2.5 Flash. The system takes a user’s resume and research/professor URLs to produce tailored drafts based on tone and length preferences.
Academic outreach emails are hard to get right:
- they need to be short but specific,
- personalized without sounding generic,
- and aligned with your actual background.
Outsync solves this by combining:
- agentic multi-step generation (LangGraph),
- Retrieval-Augmented Generation (RAG) over your resume,
- and structured refinement to improve the final draft.
- Resume-grounded personalization (RAG)
- Upload a resume and retrieve relevant experience/projects during generation.
- URL-based context extraction
- Provide professor/research URLs and extract key information to ground the email.
- Stateful multi-step workflow
- LangGraph pipeline supports structured drafting + refinement.
- Tone and length controls
- Configure the output style (e.g., formal vs casual, short vs detailed).
- Draft improvement loop
- Generates an initial draft, then refines for clarity, relevance, and alignment.
- Secure authentication
- Google OAuth with secure sessions.
- Persistent user data
- MongoDB stores user preferences and configuration state.
- Export-ready drafts
- Copy/export the final email from the UI.
- LangGraph (stateful agent workflow)
- Gemini 2.5 Flash (generation + refinement)
- ChromaDB (vector store)
- Embeddings
sentence-transformers/all-MiniLM-L6-v2(Hugging Face)- (Resume version notes: Cohere embeddings were also tested/used depending on configuration) :contentReference[oaicite:0]{index=0}
- FastAPI
- MongoDB
- Google OAuth
- Deployed on Render (backend hosting)
- Next.js + Tailwind (generated via V0.dev)
- Deployed on Vercel
- Firecrawl (scraping professor/research pages)
Outsync is designed as a modular LLM application with three core layers:
-
Frontend UI
- Handles resume upload and configuration inputs (tone/length)
- Displays generated drafts and supports export
-
Backend API
- Auth + session management
- Stores user configuration state in MongoDB
- Executes LangGraph workflow and returns results
-
LangGraph Workflow
- Multi-step pipeline that produces higher-quality outputs than a single prompt call
Outsync uses a multi-node LangGraph pipeline with a state object passed through each stage.
Example workflow stages:
- Extract Professor/Research Context
- Scrape URLs and summarize relevant details (lab focus, publications, keywords)
- Resume Retrieval (RAG)
- Embed resume content and retrieve top relevant chunks for personalization
- Draft Generation
- Create an initial outreach email draft using retrieved resume context + professor info
- Refinement
- Improve clarity, conciseness, tone alignment, and specificity
- Final Output
- Return export-ready email draft
To prevent generic emails and improve personalization, Outsync uses RAG over the user’s resume:
- Resume is parsed into chunks
- Chunks are embedded using:
sentence-transformers/all-MiniLM-L6-v2(Hugging Face)
- Embedded chunks are stored in ChromaDB
- At generation time, the system retrieves the most relevant resume sections using cosine similarity
- Retrieved context is injected into the prompt to ground the output
This improves:
- factual accuracy (no made-up experiences),
- relevance to the professor’s work,
- and overall specificity.
Outsync supports user accounts via Google OAuth.
Persisted data includes:
- user profile info (basic identity)
- saved prompt configurations
- generation preferences (tone, length)
- session state and prior drafts (optional depending on deployment config)
MongoDB is used to persist user data and configuration state.
Outsync is deployed as two services:
- Hosted on Render
- Responsible for:
- OAuth/session handling
- RAG + LangGraph execution
- MongoDB persistence
- Hosted on Vercel
- Responsible for:
- UI + upload workflows
- configuration controls
- displaying and exporting drafts
- Python 3.10+
- Node.js 18+
- MongoDB (local or cloud)
- API keys:
- Gemini API key
- Google OAuth credentials
# create environment
python -m venv venv
source venv/bin/activate
# install dependencies
pip install -r requirements.txt
# run backend
uvicorn app.main:app --reloadFrontend Setup (Next.js)
npm install
npm run devEnvironment Variables
Example backend .env:
GEMINI_API_KEY=your_key_here
GOOGLE_CLIENT_ID=your_google_client_id GOOGLE_CLIENT_SECRET=your_google_client_secret OAUTH_REDIRECT_URI=http://localhost:8000/auth/callback
MONGODB_URI=your_mongodb_connection_string
CHROMA_PERSIST_DIR=./chroma_store
Example frontend .env.local:
NEXT_PUBLIC_API_BASE_URL=http://localhost:8000 NEXT_PUBLIC_GOOGLE_CLIENT_ID=your_google_client_id
Example Usage
Sign in with Google
Upload your resume
Paste professor/research URLs
Select tone and length preferences
Generate draft
Refine/export final email
What I Learned
Building Outsync reinforced a few key lessons:
Multi-step workflows outperform single-prompt generation for quality and consistency
RAG is essential for grounding personalization in real user data
Production LLM apps require good state handling, not just model calls
A strong UI for configuration and iteration is critical for usability
Future Improvements
Add multi-professor batching (generate outreach emails for multiple targets at once)
Add evaluation harness (quality scoring, hallucination checks)
Support more document types (CV, cover letter, transcript)
Add prompt versioning + draft history
Add stronger citation grounding from extracted professor pages