A ChatGPT-style book recommendation chatbot. Describe your reading tastes and Shelf's multi-agent pipeline queries a seeded vector database, live book APIs, and the web in parallel to find personalized recommendations — streamed back token by token.
Each chat message is processed by a 5-stage LangGraph pipeline:
normalize_query
│
▼
┌─────────────────────────────────────────┐
│ parallel_personas │
│ │
│ The Librarian The Trend Watcher The Web Curator │
│ (vector DB + (Google Books + (Tavily web │
│ Open Library) NYT Bestsellers) search) │
└─────────────────────────────────────────┘
│
▼
synthesizer (LLM ranks & writes prose)
│
▼
filter_books (extracts final book list)
- normalize_query — an LLM parses the user's request and generates optimized search queries for each source
- parallel_personas — three specialist agents run concurrently, each querying different data sources
- synthesizer — an LLM picks the 3–6 best matches, writes recommendation prose, and streams it back token-by-token via SSE
- filter_books — the final book list is extracted from the LLM output and sent to the frontend as a structured JSON event
Conversation state (session ID, search angles, previously shown books) is preserved across turns using LangGraph's MemorySaver, enabling follow-ups like "give me 3 more".
Next.js (Vercel) ──SSE──► FastAPI + LangGraph (Railway)
│
┌───────────────────┼──────────────────────┐
▼ ▼ ▼
Supabase pgvector Google Books API Tavily MCP
(semantic search) + NYT Bestsellers API (web search)
│
Open Library API
- Python 3.13+
- Node.js 20+
- A Supabase project with the pgvector extension enabled and the
match_booksRPC function created (seebackend/ingestion/) - API keys for OpenAI, Google Books, and NYT Books
- Optionally: a Tavily API key (enables the Web Curator persona)
cd backend
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # fill in your keys
uvicorn app.main:app --reloadAPI docs available at http://localhost:8000/docs (development only; disabled in production).
cd backend
python -m ingestion.seed_booksThis fetches ~5,600 books across 28 genres from Open Library, embeds them via OpenAI text-embedding-3-small, and upserts them into Supabase pgvector. Expect 10–20 minutes depending on network and API quota.
cd frontend
npm install
cp .env.example .env.local # set NEXT_PUBLIC_API_URL=http://localhost:8000
npm run dev| Variable | Required | Description |
|---|---|---|
OPENAI_API_KEY |
✅ | OpenAI API key (LLM chat + embeddings) |
SUPABASE_URL |
✅ | Supabase project URL |
SUPABASE_SERVICE_KEY |
✅ | Supabase service role key |
GOOGLE_BOOKS_API_KEY |
✅ | Google Books API key |
NYT_API_KEY |
✅ | NYT Books API key |
TAVILY_API_KEY |
❌ | Tavily web search key (Web Curator disabled if blank) |
ALLOWED_ORIGINS |
✅ | Comma-separated CORS origins (e.g. https://yourapp.vercel.app) |
ENVIRONMENT |
✅ | development or production (disables /docs in production) |
| Variable | Required | Description |
|---|---|---|
NEXT_PUBLIC_API_URL |
✅ | FastAPI backend base URL |
# Chat (returns a Server-Sent Events stream)
curl -N -X POST http://localhost:8000/api/chat \
-H "Content-Type: application/json" \
-d '{"message": "I loved The Martian, what should I read next?", "session_id": "test-123"}'
# Health check
curl http://localhost:8000/health- Create a new project at railway.app → Deploy from GitHub repo
- In the service Settings → Source, set Root Directory to
backend/ - Railway auto-detects the
Dockerfile - In the Variables tab, add all 8 environment variables listed above
- After deploy, verify:
curl https://your-railway-url/health→{"status":"ok"}
- Create a new project at vercel.com → Import from GitHub
- Set Root Directory to
frontend/ - Add environment variable:
NEXT_PUBLIC_API_URL= your Railway URL (withhttps://) - Deploy → copy the Vercel URL
- Go back to Railway → update
ALLOWED_ORIGINSto your Vercel URL → Railway auto-redeploys
Note:
NEXT_PUBLIC_variables are baked in at build time. Changing them in Vercel requires a redeploy.
GitHub Actions runs automatically on pushes to main and develop:
| Workflow | Scope | Checks |
|---|---|---|
backend-ci |
backend/** |
ruff, mypy, bandit, pytest |
frontend-ci |
frontend/** |
eslint, tsc, next build |
codeql |
All PRs + weekly | Security scanning (Python + JS/TS) |
See CONTRIBUTING.md.