Gluk is an AI-powered research assistant you can chat with. Unlike a standard chatbot, Gluk can:
- π Search the web in real time and cite its sources
- π Read your files β upload a PDF, CSV, Word doc, or text file and ask questions about it
- π§ Run deep research β automatically breaks complex questions into sub-queries, fetches full pages, ranks sources by credibility, and synthesises a structured answer with inline citations
- π¬ Remember your conversation β persistent multi-turn memory across sessions
- π Secure by default β Google & GitHub login via NextAuth
| Feature | Description |
|---|---|
| Multi-step research pipeline | Plan β Search β Deep-read β Rerank β Synthesise |
| RAG (document Q&A) | Upload files; Gluk stores them in Pinecone and answers from them |
| Live web search | Tavily API with advanced depth, 8 results, published dates |
| Source ranking | TF-IDF relevance + domain credibility scoring |
| Hybrid vector search | 70% vector similarity + 30% keyword overlap, MMR deduplication |
| Streaming responses | Token-by-token streaming, no page reload |
| Conversation history | Stored in Turso (LibSQL), synced per user |
| Image attachments | Upload images via Cloudinary, passed to the agent |
| Auth | Google and GitHub OAuth via NextAuth |
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (App Router, Turbopack) |
| AI orchestration | Mastra + @mastra/core |
| LLM | OpenRouter β nvidia/nemotron-3-nano-30b-a3b:free by default |
| Embeddings | HuggingFace sentence-transformers/all-MiniLM-L6-v2 |
| Vector DB | Pinecone |
| Database | Turso (LibSQL) β conversations + research sessions |
| File storage | Cloudinary |
| Auth | NextAuth v4 β Google + GitHub |
| UI | React 19, Tailwind CSS v4, shadcn/ui, Lucide icons |
| Language | TypeScript 5 |
- Node.js 18+
- Accounts (all have free tiers): OpenRouter, Pinecone, Turso, Cloudinary, Tavily
- Google and/or GitHub OAuth app credentials
git clone https://github.com/daviddozie/gluk.git
cd gluknpm installCopy the example file and fill in your keys:
cp .env.example .env.local| Variable | Where to get it |
|---|---|
OPENROUTER_API_KEY |
openrouter.ai/keys |
TAVILY_API_KEY |
tavily.com |
PINECONE_API_KEY |
app.pinecone.io |
PINECONE_INDEX |
Your index name in Pinecone (e.g. gluk) |
PINECONE_HOST |
Your index host URL from the Pinecone dashboard |
TURSO_DATABASE_URL |
libsql://your-db.turso.io |
TURSO_AUTH_TOKEN |
From your Turso dashboard |
CLOUDINARY_CLOUD_NAME |
cloudinary.com/console |
CLOUDINARY_API_KEY |
Cloudinary dashboard |
CLOUDINARY_API_SECRET |
Cloudinary dashboard |
NEXTAUTH_SECRET |
Run openssl rand -base64 32 |
NEXTAUTH_URL |
http://localhost:3000 (dev) or your production URL |
GOOGLE_CLIENT_ID |
console.cloud.google.com |
GOOGLE_CLIENT_SECRET |
Google Cloud Console |
GITHUB_CLIENT_ID |
github.com/settings/developers |
GITHUB_CLIENT_SECRET |
GitHub Developer Settings |
npm run devOpen http://localhost:3000 in your browser.
Tip: To also run the Mastra Studio UI (agent inspector at
localhost:4111), usenpm run dev:allinstead.
src/
βββ app/
β βββ page.tsx # Main chat UI
β βββ login/page.tsx # Auth screen
β βββ api/
β βββ chat/route.ts # Streaming chat endpoint (RAG + agent + research)
β βββ ingest/route.ts # Document β Pinecone embedding pipeline
β βββ upload/route.ts # File β Cloudinary upload
β βββ conversations/ # CRUD for conversation history
β βββ auth/ # NextAuth handler
βββ components/
β βββ chat-window.tsx # Message list renderer
β βββ chat-input.tsx # Input bar with file attachment support
β βββ message-bubble.tsx # Per-message component (markdown + citations)
β βββ sidebar.tsx # Conversation history sidebar
βββ lib/
β βββ auth.ts # NextAuth config
β βββ db.ts # Turso/LibSQL client
β βββ embeddings.ts # HuggingFace embedding wrapper (soft-fail on errors)
β βββ vector-store.ts # Pinecone store + hybrid search + MMR deduplication
β βββ document-processor.ts # PDF/CSV/DOCX/TXT parser + semantic chunker
β βββ research-store.ts # Research session persistence (Turso)
βββ mastra/
βββ index.ts # Mastra config β agent + workflow registration
βββ agents/
β βββ gluk-agent.ts # Main AI agent (tools, memory, system prompt)
βββ tools/
β βββ web-search-tool.tsx # Tavily web search
β βββ web-fetch-tool.ts # Full-page HTML extractor
β βββ source-rerank-tool.ts # TF-IDF + domain credibility ranker
βββ workflows/
βββ research-workflow.ts # 5-step deep research pipeline
When Gluk detects a research-type question, it runs a 5-step Mastra workflow instead of a single agent call:
1. Plan β Break the question into 2β3 focused sub-queries
2. Gather β Run Tavily search for each sub-query (with rate-limit courtesy delays)
3. Deep-fetch β Fetch the top 3 URLs in full β strip boilerplate, extract prose
4. Rerank β Score every source by TF-IDF relevance + domain credibility
5. Synthesise β Write a structured answer with inline [Title](URL) citations
For document questions (e.g. "list the orders in the file"), the research workflow is skipped. Gluk answers directly from Pinecone RAG β one LLM call, no web search.
| Type | Extension(s) |
|---|---|
.pdf |
|
| Word | .docx |
| Spreadsheet | .csv |
| Plain text | .txt, .md |
| Images | .jpg, .jpeg, .png, .gif, .webp |
Documents are semantically chunked (paragraph β sentence boundaries) and stored in Pinecone. Images are uploaded to Cloudinary and passed directly to the agent.
The default model (nvidia/nemotron-3-nano-30b-a3b:free) allows 50 requests/day on OpenRouter's free tier. The limit resets at midnight UTC.
To increase this:
- Add $10 credits on OpenRouter β unlocks 1 000 req/day
- Or switch model: set
OPENROUTER_MODELin.env.localto any slug from openrouter.ai/models
| Script | Description |
|---|---|
npm run dev |
Start Next.js dev server (Turbopack) |
npm run dev:all |
Start Next.js + Mastra Studio concurrently |
npm run mastra |
Start Mastra Studio only (localhost:4111) |
npm run build |
Build for production |
npm run start |
Run the production build |
npm run lint |
Run ESLint |
Contributions are welcome! Please read CONTRIBUTING.md for guidelines on how to get involved.
MIT β see LICENSE for details.