AI-powered Vedic astrology — accurate Kundali charts, Dasha timelines, and a chatbot that actually reads your chart.
Live App · Features · Quick Start · Architecture · API · Roadmap
Most Vedic astrology apps are either static PDF generators or black-box chat wrappers. Astrova is different:
- Every calculation runs in your browser. No backend phones home for planetary positions — the chart math is fully client-side via
astronomy-engineusing Lahiri ayanamsha. - The AI actually reads your chart. The astrologer is context-aware — it sees your current Dasha period, active transits, and nakshatras before it answers. No generic horoscopes.
- Built for builders. Typed schema, auto-migrating Postgres, Edge Functions, Vitest coverage on the astrology engine. Fork it, self-host it, extend it.
Unlike generic astrology chatbots, Astrova grounds every AI reply in your live chart state — Dasha, transits, shadbala, and an admin-curated knowledge base searched with Postgres full-text ranking.
You could build an astrology chatbot on LangChain. I chose not to — because a general-purpose RAG framework is the wrong shape for this domain. Astrova's context pipeline is purpose-built for Vedic astrology, and the proof is in the code, not a leaderboard.
Here's how the two approaches actually differ when the question is "what's happening in my chart right now?":
| Capability | 🌙 Astrova (purpose-built) | 🦜 LangChain (general-purpose) |
|---|---|---|
| Chart context | Structured Kundali object injected into the prompt — always exact |
Retrieved as text chunks by similarity — lossy and approximate |
| Dasha / transits | Computed deterministically client-side in vedic-engine.ts (2 K LOC), zero round trips |
Would require LLM tool-calling round trips with hallucination risk on parameters |
| KB retrieval ranking | Postgres tsvector weighted title > category > content — matches Jyotisha taxonomy (e.g. "Mangal Dosha" as a category, not a phrase) |
Cosine similarity over embeddings — surfaces paragraphs that mention a term over canonical articles titled with it |
| Where the math runs | Browser (astronomy-engine, Lahiri ayanamsha) — server never touches ephemerides |
Server-only Python/JS SDK — cannot offload to the client |
| Runtime target | Vercel Edge Functions (~1 MB bundle budget) — SSE from the nearest PoP | LangChain JS + transitive deps blow past the Edge bundle limit; forces Node.js serverless with cold starts |
| Prompt size | Surgically scoped: only the active Mahadasha/Antardasha + top-k KB hits, nothing else | Default stuff chain dumps every retrieved doc into the prompt, inflating tokens per reply |
| Agent loop | None — context is precomputed before the LLM runs | AgentExecutor decides when to call each tool, adding latency and failure modes |
MMLU scores and LangChain leaderboards don't measure the thing that matters here: does the reply correctly reference your actual current Dasha lord? That's a domain-specific ground truth that only a Jyotisha-aware harness can verify.
Astrova's evaluation is therefore built around astrology-specific fixtures, not generic QA:
- Dasha accuracy — for a fixture chart with a known Mahadasha/Antardasha on a given date, does the reply name the correct lord? Structured context injection makes this deterministic; similarity-retrieved context does not.
- Jyotisha term recall — when the user asks about Kemadruma Yoga, does the reply cite the canonical KB article titled "Kemadruma Yoga"? This is where
tsvectortitle-weighting beats cosine similarity for domain taxonomy. - Time-to-first-token on a chart-grounded question — measured against an identical OpenRouter call routed through an agent executor. No agent loop = fewer steps = lower TTFT. The gap is architectural, not tunable.
- Cold start on the Edge — a direct, falsifiable measurement. If LangChain cannot deploy to Vercel Edge at all within the bundle budget, that is the benchmark.
- Tokens per reply — input token count on identical questions. Surgical context scoping wins here by construction.
Honest trade-offs. LangChain is the right choice if you're building a general-purpose agent across many domains, need a huge plugin ecosystem, or want drop-in swappable retrievers. Astrova is the right choice if your domain has structured ground truth (Dasha periods, nakshatras, yogas) that deserves to be computed rather than retrieved.
Click to expand
- North Indian diamond chart — D1 Rasi + D9 Navamsa
- 9 Grahas with sidereal longitudes (Lahiri ayanamsha)
- Full planetary metadata — nakshatra, pada, retrograde, exaltation/debilitation
- Realtime transit chart with live planetary positions
- Vimshottari Dasha — Mahadasha → Antardasha → Pratyantardasha with exact date ranges
- Shadbala — 6-fold strength (Sthana, Dig, Kaala, Cheshta, Naisargika, Drik)
- Bhava Bala — house-level strength
- Sarvashtakavarga — 12-house point totals
- Ashtakoot Milan — 36-point compatibility scoring across 8 koots
- Varna · Vashya · Tara · Yoni · Graha Maitri · Gana · Bhakoot · Nadi
- Dedicated match page with score banner
- SSE chat via OpenRouter (multi-model, swap in admin panel) — incremental fetch, full-string re-render (not true delta append)
- Chart-aware context — reads your current chart, Dasha period, and transits before each reply
- RAG over knowledge base — Postgres
tsvectorfull-text search with weighted ranking - Credit-based usage with Stripe checkout + webhook fulfillment
- Firebase Google sign-in with cross-subdomain
magnova_sessioncookie - Unlimited saved charts per user
- First-time onboarding wizard (
BirthDataWizard) - Admin dashboard — KB editor, model manager, credit config, user manager
- SEO-ready — Open Graph, robots.txt, sitemap
| Layer | Technology |
|---|---|
| Frontend | React 19 · TypeScript · Vite 7 · Tailwind CSS v4 · shadcn/ui |
| Astrology Engine | astronomy-engine — 2K LOC, client-side, Lahiri ayanamsha |
| Backend | Vercel Edge Functions (/api/*.ts, runtime: 'edge') |
| Database | Neon Postgres via @neondatabase/serverless with auto-schema init |
| Auth | Firebase Authentication — Google popup, magnova_session httpOnly cookie |
| AI | OpenRouter — streaming, model-agnostic |
| Payments | Stripe Checkout + webhook credit fulfillment |
| Testing | Vitest — 17 tests covering the vedic engine |
| Deployment | Vercel (auto-deploy from main) |
Browser Vercel Edge Functions Neon Postgres
┌─────────────────────┐ ┌───────────────────┐ ┌────────────────┐
│ React SPA │ fetch │ /api/*.ts │ sql │ users │
│ ├─ vedic-engine.ts │────────>│ ├─ _lib/db.ts │──────────> │ knowledge_base │
│ ├─ api.ts (client) │<────────│ ├─ _lib/auth.ts │<────────── │ chat_sessions │
│ └─ Firebase Auth │ JSON │ └─ _lib/stripe.ts │ rows │ saved_charts │
└─────────────────────┘ └───────────────────┘ │ credit_trans │
│ │ │ enabled_models │
│ Firebase popup │ magnova_session │ admin_config │
▼ ▼ cookie └────────────────┘
Google OAuth Session management
Key design decisions
- 🔒 Frontend never touches the DB directly — all queries route through Edge Functions.
- 🍪 Auth flow: Firebase ID token →
/api/auth/session→ httpOnly cookie → all subsequent requests. - 🛡 Admin role is DB-driven (
users.role = 'admin') — no client-side bypass. - 🧬 Schema auto-initializes via
ensureSchema()on first query. Zero manual migrations. - 🔎 KB search uses PostgreSQL
tsvectorwith weighted ranking (title > category > content).
- Node.js 20+ and pnpm 10+
- Vercel CLI —
npm i -g vercel - Neon Postgres database
- Firebase project with Google provider enabled
- OpenRouter API key
git clone https://github.com/omkarbhad/astrova.git
cd astrova
pnpm install
cp .env.example .env.local
# fill in .env.local — see "Environment Variables" belowpnpm dev # Full local dev (vercel dev) → http://localhost:3000
pnpm dev:vite # Frontend only — proxies /api to production
pnpm test # Run Vitest suite (17 tests)
pnpm build # TypeScript check + production build💡
pnpm devrunsvercel dev, which serves both the Vite frontend and API functions locally. Auth, admin, KB saves — everything works because themagnova_sessioncookie is set on localhost.
pnpm dev:viteruns plain Vite with a proxy to production. Good for quick frontend iteration, but auth-protected writes won't work (cookies don't cross domains).
# Database (server-only — never prefix with VITE_)
DATABASE_URL=postgresql://user:pass@your-neon-host/neondb?sslmode=require
FIREBASE_PROJECT_ID=your-firebase-project-id
# Firebase (frontend)
VITE_FIREBASE_API_KEY=...
VITE_FIREBASE_AUTH_DOMAIN=your-project.firebaseapp.com
VITE_FIREBASE_PROJECT_ID=your-firebase-project-id
VITE_FIREBASE_STORAGE_BUCKET=your-project.firebasestorage.app
VITE_FIREBASE_MESSAGING_SENDER_ID=...
VITE_FIREBASE_APP_ID=...
# OpenRouter (frontend — used for AI chat)
VITE_OPENROUTER_API_KEY=sk-or-v1-...
# Stripe (server-only, optional — for credit purchases)
STRIPE_SECRET_KEY=sk_...
STRIPE_WEBHOOK_SECRET=whsec_...Push to main on GitHub — Vercel auto-deploys. Set these in the Vercel dashboard:
| Variable | Scope |
|---|---|
DATABASE_URL |
Server |
FIREBASE_PROJECT_ID |
Server |
STRIPE_SECRET_KEY |
Server |
STRIPE_WEBHOOK_SECRET |
Server |
VITE_* |
Build-time |
astrova/
├── api/ # Vercel Edge Functions
│ ├── _lib/ # db, auth, firebaseAdmin, stripe
│ ├── auth/ # session + signout
│ ├── credits/ # balance, tiers, free claim
│ ├── webhooks/ # Stripe fulfillment
│ ├── kb/ # knowledge base + tsvector search
│ ├── charts/ # saved charts CRUD
│ ├── sessions/ # chat persistence
│ ├── models/ # AI model management
│ ├── users/ # profile + admin user mgmt
│ └── admin/ # admin config key-value
├── src/
│ ├── components/
│ │ ├── auth/ # AuthGuard, UserMenu
│ │ ├── common/ # ErrorBoundary, SEOHead, LoadingSkeleton
│ │ ├── landing/ # HomePage, LandingHeader, LandingFooter
│ │ └── ui/ # shadcn/ui + BirthDataWizard, BentoCard
│ ├── contexts/ # AuthContext, CreditsContext
│ ├── lib/
│ │ ├── vedic-engine.ts # Client-side astrology (2035 LOC)
│ │ ├── api.ts # Frontend API client
│ │ ├── firebase.ts # Firebase init + Google sign-in
│ │ └── __tests__/ # Vitest suite
│ ├── pages/ # ChartPage, MatchPage, AdminPage
│ ├── constants/ # styles, chart constants
│ └── types/ # TypeScript definitions
├── public/ # Logo, robots.txt, sitemap.xml
├── vercel.json # Vite framework + SPA rewrites
└── vitest.config.ts
| Endpoint | Method | Description |
|---|---|---|
/api/credit-costs |
GET |
Current credit costs |
/api/kb |
GET |
List or search KB (?search=query) |
/api/models |
GET |
List models (?enabled=1 for user-facing) |
/api/admin/config |
GET |
Public config values |
| Endpoint | Method | Description |
|---|---|---|
/api/auth/session |
POST |
Exchange Firebase token for session cookie |
/api/auth/signout |
DELETE |
Clear session cookie |
/api/users |
GET/POST |
Get or create current user |
/api/charts |
GET/POST |
List or save charts |
/api/charts/[id] |
PATCH/DELETE |
Update or delete chart |
/api/sessions |
GET/POST |
List or save chat sessions |
/api/sessions/[id] |
DELETE |
Delete chat session |
/api/credits |
POST |
Deduct (user) or add (admin) |
/api/credits/claim-free |
POST |
One-time +20 free credits |
/api/credits/purchase |
GET/POST |
Tiers or Stripe checkout |
/api/settings |
GET/POST |
User preferences |
| Endpoint | Method | Description |
|---|---|---|
/api/kb |
POST |
Create/update KB article |
/api/kb/[id] |
DELETE |
Delete KB article |
/api/models |
POST |
Add model |
/api/models/[id] |
PATCH/DELETE |
Toggle or delete |
/api/users/all |
GET |
List all users |
/api/users/[id] |
PATCH |
Update role / credits / ban |
/api/admin/config |
POST |
Set config value |
| Endpoint | Method | Description |
|---|---|---|
/api/webhooks/stripe |
POST |
Stripe payment webhook (signature-verified) |
8 tables, auto-created by ensureSchema() on first query:
| Table | Purpose |
|---|---|
users |
Firebase UID, email, role, credits, ban status |
credit_transactions |
Audit log — atomic CTEs prevent race conditions |
knowledge_base |
Articles with JSONB tags + tsvector search |
admin_config |
Key-value JSONB config |
chat_sessions |
AI chat history (JSONB messages array) |
saved_charts |
Birth charts (JSONB birth_data + kundali_data) |
user_settings |
Per-user preferences (timezone, style, ayanamsa) |
enabled_models |
OpenRouter model registry |
| Action | Cost |
|---|---|
| AI chat message | 2 credits |
| Chart generation | 1 credit |
| Kundali matching | 3 credits |
- New users: 10 credits on signup
- One-time free claim: +20 credits
- Stripe checkout tiers: 20 / 50 / 120 / 300
- All costs configurable via the admin panel
Accessible at /admin for users with role='admin'.
| Tab | What you can do |
|---|---|
| Articles | Sidebar + preview KB editor, AI article assistant, full-text search |
| Models | Import from OpenRouter, toggle, set default |
| Credits | Per-action cost and default new-user credits |
| Users | Adjust credits, toggle ban, set roles |
| Config | Raw admin key-value editor |
pnpm test # Run all tests
pnpm test:watch # Watch mode17 tests cover the vedic engine: planet positions · Rahu-Ketu opposition · nakshatra assignment · dasha periods · shadbala · ashtakavarga totals · ashtakoot matching · timezone estimation.
- Client-side Kundali generation (D1 + D9)
- Vimshottari Dasha timeline
- AI astrologer with chart context
- Ashtakoot matching
- Stripe credits
- More varga charts (D10, D7, D12)
- Yogas detection (Raja, Dhana, Pancha Mahapurusha)
- PDF export of full chart report
- Mobile-first chat UX polish
- Multilingual KB (Hindi, Sanskrit)
Have an idea? Open an issue or start a discussion.
Contributions are what make open source amazing. Any contribution you make is greatly appreciated.
- Fork the project
- Create a feature branch —
git checkout -b feature/amazing-feature - Commit your changes —
git commit -m 'Add amazing feature' - Push the branch —
git push origin feature/amazing-feature - Open a Pull Request
👉 New here? Look for good first issue labels.
astronomy-engine— the math that makes this possible- shadcn/ui — component primitives
- Neon — serverless Postgres
- OpenRouter — unified LLM gateway
- Every classical Jyotisha text this project leans on 🙏
Live: astrova.magnova.ai · Built with ❤️ by Omkar Bhad

