A full-stack AI research workspace. Ask a question, get a web-grounded answer streamed into chat, and keep the thread. For longer jobs, Deep Search queues work on Redis and a background worker so the UI stays responsive.
The live demo is for chatting and auth. Deep Search needs Redis + a worker, so it runs in a local clone.
deepquery.mp4
- Streamed AI chat with Gemini
- Live web context from Tavily
- Google and GitHub sign-in via Supabase
- Conversation history in Postgres
- Deep Search: async research jobs on Redis + BullMQ
- Worker that writes completed answers back into the thread
- Dark mode, markdown answers, and source links
| Layer | Tools |
|---|---|
| Frontend | React, TypeScript, Tailwind, Bun |
| Backend | Bun, Express, TypeScript |
| Database | PostgreSQL, Prisma |
| Auth | Supabase (Google + GitHub) |
| Models | Google Gemini |
| Search | Tavily |
| Queue | Redis, BullMQ |
Browser
React UI
Supabase OAuth
Polls Deep Search status
API :3001
/ask Tavily + Gemini stream
/research Enqueue job (local only)
Prisma Users, chats, jobs
Worker
Pulls BullMQ jobs
Searches + generates
Saves the answer
Redis job queue
Postgres durable historyNormal chat:
message → /ask → Tavily → Gemini stream → save conversationDeep Search (local):
message → /research → ResearchJob + BullMQ
worker → Tavily → Gemini → save result → UI polls status| Live site | Local clone | |
|---|---|---|
| Google / GitHub login | Yes | Yes |
| Skip-login test user | Hidden | http://localhost:3000/local |
| Streamed chat | Yes | Yes |
| Deep Search | Shows a “clone the repo” note | Full worker pipeline |
The skip-login button and /local route only appear on localhost. Production visitors only see Google and GitHub.
git clone https://github.com/Khizarshah01/deepquery.git
cd deepquery
cd backend && bun install
cd ../frontend && bun installFrom the repo root:
docker compose up -dThis starts:
- Postgres at
postgresql://deepquery:deepquery@127.0.0.1:5462/deepquery - Redis at
redis://127.0.0.1:6382
Those ports avoid clashing with other local Docker apps.
cp backend/.env.example backend/.env
cp frontend/.env.example frontend/.envbackend/.env:
DATABASE_URL="postgresql://deepquery:deepquery@127.0.0.1:5462/deepquery"
REDIS_URL="redis://127.0.0.1:6382"
PUBLIC_SUPABASE_URL="https://your-project.supabase.co"
SECRET_KEY_BASE="your-supabase-service-role-key"
GEMINI_API_KEY="your-gemini-api-key"
TAVILY_API_KEY="your-tavily-api-key"frontend/.env:
BUN_PUBLIC_SUPABASE_URL="https://your-project.supabase.co"
BUN_PUBLIC_SUPABASE_PUBLISHABLE_KEY="your-supabase-anon-key"
BUN_PUBLIC_BACKEND_URL="http://localhost:3001"In Supabase → Authentication → URL Configuration, add:
http://localhost:3000
http://localhost:3000/**plus your live site URLs. Google’s callback stays:
https://YOUR-PROJECT.supabase.co/auth/v1/callbackcd backend
bunx prisma generate
bunx prisma db push# terminal 1
cd backend && bun run start
# terminal 2
cd backend && bun run worker
# terminal 3
cd frontend && bun run devThen open http://localhost:3000.
- Sign in with Google/GitHub, or
- Click Skip login / open http://localhost:3000/local to test without OAuth
Free-tier Supabase pauses after about 7 days of inactivity. A cheap SELECT 1 is not enough.
DeepQuery follows supabase-pause-prevention:
/healthand/keep-aliveinsert or delete a row in akeep_alivetable- They also ping the Supabase Auth API
.github/workflows/keep-alive.ymlhits the live/healthURL every 10 minutes
After deploy, run bunx prisma db push on the hosted database so the keep_alive table exists.
frontend/ React app (Bun)
backend/ Express API + BullMQ worker
prisma/ schema + migrations (under backend/)
docker-compose.ymlMIT. See LICENSE.