The production backend of Ansari — an Islamic AI assistant that answers questions with evidence from the Quran, Hadith, and classical scholarship.
Ansari Backend is a Next.js API service. At its core is a facilitator: a Gemini-powered agent that answers Islamic questions by calling specialized search tools and citing what it finds.
- Quran search — ayat with Arabic text and translation (Kalemat API)
- Hadith search — narrations with source references (Kalemat API)
- Mawsuah search — the Kuwaiti Encyclopedia of Islamic Jurisprudence (Usul vector search)
- Tafsir search — Quranic exegesis (Usul vector search)
Responses stream over SSE, threads and messages persist to Postgres, and the search tools degrade gracefully when a provider is unavailable — the assistant says what it couldn't consult rather than failing the request.
| Area | Endpoints |
|---|---|
| Health | GET /api/health |
| Auth & users | POST /api/v2/users/register, login, logout, refresh_token, GET /api/v2/users/me, password reset (request_password_reset, reset_password) |
| Chat | POST /api/v2/threads (create), POST /api/v2/threads/{id} (send message, SSE stream), thread naming, sharing |
| Sources | GET /api/v2/threads/{id}/documents (owner-scoped, derived from stored tool records), GET /api/v2/share/{id}/documents (public, from the share snapshot): citable sources per answer, joined to the matching GET's messages by message_index |
| Feedback & prefs | POST /api/v2/feedback, GET/POST /api/v2/preferences |
| App support | GET /api/v2/app-check (version/maintenance gate) |
| OpenAI-compat | POST /api/v1/chat/completions (bearer-token gated, for evaluation harnesses) |
| MCP-style | POST /api/v2/mcp-complete (stateless completion for AI-skill integrations) |
| Admin | GET /api/v2/admin/stats, /admin/analytics dashboard |
Auth is owned by apps/auth (Better Auth, spec 300): this service verifies its short-lived JWTs against the JWKS, and the /v2/users/* and password-reset routes are a compatibility layer over it with the legacy response shapes. No password, session or signing secret lives here.
- Runtime: Next.js 15 (App Router, API routes), Node ≥ 22, TypeScript
- AI: Google Gemini via Vertex AI (preferred) or the public Gemini API, with model fallback on capacity errors
- Database: PostgreSQL with Drizzle ORM (migrations in
drizzle/) - Validation: Zod (strict env + request validation)
- Observability: Sentry (optional — disabled when
SENTRY_DSNis unset; no user content is logged) - Tests: Vitest (unit/integration)
# Install at the REPO ROOT (pnpm workspace; Node >= 22, pnpm via corepack)
cd ../.. && pnpm install && cd apps/api
# Configure — see .env.example for the full contract
cp .env.example .env
# Required: DATABASE_URL, KALEMAT_API_KEY, USUL_API_TOKEN,
# the AUTH_* settings in production (apps/auth),
# and one Gemini path (GEMINI_API_KEY or GOOGLE_CLOUD_PROJECT + credentials).
# NOTE: Kalemat and Usul keys are not self-serve — request them from the providers.
# Database
pnpm db:migrate
# Run
pnpm devVerify: pnpm typecheck && pnpm test && pnpm build.
lib/ Engine: facilitator agent, Gemini client, tools, auth, db helpers
ai/prompts/ The facilitator system prompt ("the soul")
tools/ Quran / Hadith / Mawsuah / Tafsir search + resilience wrapper
src/app/api/ HTTP surface (v1, v2 routes)
db/schema/ Drizzle schema (users, threads, messages, deleted_users, ...)
drizzle/ Generated SQL migrations
tests/ Vitest suites
Deployed on Railway (railway.toml: dockerfile builder using apps/api/Dockerfile, built from the repo root, healthcheck /api/health), but any host that runs a Next.js server works. See the self-hosting guide in the monorepo docs/ for the full environment contract.
MIT