AI-powered, multi-tradition astrology platform. Vedic + Western + Chinese + Hellenistic + Horary + Medical astrology, palmistry, tarot, numerology, vastu, daily briefings, and an admin operations console — all wired together with multi-provider LLM failover, credit-metered billing, and GDPR-grade audit logging.
Production: www.jyotron.com · API: api.jyotron.com · Repo: xploroshan/jyotryx
- Repository layout
- Tech stack
- Features
- Knowledge base, AI, and how each feature uses them
- Local development
- Deployment
- API surface
- Database
- Background jobs
- Observability
- Admin dashboard
- Pricing & credits
- Project conventions
jyotryx/
├── apps/
│ ├── api/ # NestJS backend (port 4000)
│ └── web/ # Next.js 15 web app (port 3000, App Router)
├── k8s/base/ # Kubernetes manifests (api/web/worker/HPA/ingress)
├── scripts/ # Operational shell scripts
├── tests/ # Cross-app test helpers
├── docs/ # DEPLOYMENT.md and other long-form docs
├── docker-compose.yml
├── turbo.json
└── vercel.json
The repo is intentionally apps-only — no mobile app, no packages/shared. Web ↔ API contracts live in TypeScript types kept in step manually (or asserted by apps/web/src/__tests__/admin-url-contract.test.ts for the admin surface).
| Layer | Technology |
|---|---|
| Web | Next.js 15 (App Router, RSC), TypeScript, Tailwind CSS v4, Zustand |
| API | NestJS 11, TypeScript, Node 20 |
| ORM | Prisma 7 (@prisma/adapter-pg) |
| Database | PostgreSQL 16 + pgvector (via Supabase in prod) |
| Cache / queue | Redis 7 (Upstash in prod) |
| Background jobs | BullMQ |
| LLM providers | OpenAI · Google Gemini · Anthropic (failover chain) |
| Vector search | pgvector (no external Pinecone) |
| Vision (palmistry) | OpenAI Vision API (no on-prem CV libs) |
| Object storage | Cloudflare R2 |
| Astronomy engine | Swiss Ephemeris (swisseph C++ binding) |
| Payments | Razorpay (UPI / cards / subscriptions) |
| Auth | Email+password, SMS OTP, Google, Apple, Firebase |
| Observability | Prometheus (/api/metrics), OpenTelemetry, Sentry |
| Web hosting | Vercel |
| API hosting | Railway (or self-hosted K8s using k8s/base/) |
- Vedic: kundli (rasi/navamsa/bhava), divisional charts D9–D60, KP Paddhati, Ashtakoota guna milan matching, doshas (Manglik, Kaal Sarp, Pitra, Nadi), Sade Sati, dashas (Vimshottari, Ashtottari, Yogini), panchang (tithi/nakshatra/yoga/karana/vara), muhurat finder.
- Western: tropical natal, synastry, transits, aspects, progressions.
- Chinese: BaZi (Four Pillars), 12-animal × 5-element zodiac, Feng Shui flying stars.
- Hellenistic: sect determination, planetary joys, annual profections, zodiacal releasing.
- Horary & medical: horary judgment, decumbiture (illness chart), zodiac-body correspondences.
- Daily briefing: personalized "My Day" + planetary hours + offline pack.
- AI chat with category-specialized agents (career / relationships / finance / health / spiritual). Sync and SSE-streamed responses, OpenAI moderation on every message.
- Palmistry: photo upload → BullMQ vision queue → AI palm reading.
- Tarot: single / three-card / Celtic-cross spreads with LLM interpretation.
- Numerology: personal name, business/brand, personal year theme.
- Vastu: directional analysis with deity / element / planet mapping.
- PDF reports: Life, Career, Marriage, Wealth, Palm, Annual — queued generation, R2 delivery.
- Knowledge base: 18 structured i18n tables (planets, nakshatras, doshas, etc.) plus pgvector embeddings for grounded LLM responses.
- i18n: en, hi, ta, bn, te, kn, ml, gu, or, as.
- Multi-tab admin dashboard (Users, Activity, Analytics, LLM, Content, Cost, Funnel, Ops, Safety, GDPR, Settings).
- Per-feature credit-spend breakdowns, MRR/ARR, weekly cohort retention.
- LLM kill-switch per provider, runtime model + cost overrides without redeploy, capacity forecasting.
- Activity audit log with one-click undo on credit grants and role changes.
- Admin "Grant credits" with typed
ADMIN_GRANTtransactions. - Auto-refund: every credit-spending feature refunds on downstream failure.
- Content moderation queue with admin review.
- GDPR export + delete with 30-day SLA tracking.
Most features compute their answers deterministically from Swiss Ephemeris plus the structured Knowledge Base. Only a handful of features actually call an LLM. This is intentional: it keeps astrology mathematically accurate, dramatically cheaper, faster, and lets every chart be reproduced byte-for-byte for the same inputs.
| Feature | Computation engine | KB tables consumed | LLM? |
|---|---|---|---|
| Kundli (Vedic birth chart) | Swiss Ephemeris | kb_planets, kb_nakshatras, kb_zodiac_signs, kb_yogas |
No |
| Kundli matching (Ashtakoota) | Swiss Ephemeris | kb_doshas, kb_briefing_phrases (dosha templates) |
No |
| Divisional charts (D9–D60) | Swiss Ephemeris | kb_zodiac_signs, kb_planets |
No |
| KP Paddhati | Swiss Ephemeris | kb_planets, kb_nakshatras |
No |
| Western natal / synastry / transits | Swiss Ephemeris | kb_zodiac_signs, kb_briefing_phrases |
No |
| Hellenistic (profections, ZR) | Swiss Ephemeris | kb_hellenistic_planets, kb_briefing_phrases |
No |
| Horary judgment | Swiss Ephemeris | kb_zodiac_signs, kb_briefing_phrases (horary templates) |
No |
| Decumbiture (medical) | Swiss Ephemeris | kb_zodiac_signs (body parts), kb_briefing_phrases |
No |
| BaZi (Four Pillars) | Pure calc | kb_chinese_animals |
No |
| Chinese flying stars | Pure calc | kb_flying_stars |
No |
| Panchang | Swiss Ephemeris | kb_tithis, kb_nakshatras, kb_yogas, kb_varas, kb_karanas, kb_pakshas |
No |
| Sade Sati | Swiss Ephemeris | kb_briefing_phrases (sade-sati templates) |
No |
| Dosha detection | Swiss Ephemeris | kb_doshas |
No |
| Daily briefing / My Day | Swiss Ephemeris | kb_planets, kb_briefing_phrases, kb_profession_insights |
Optional (personalization) |
| Numerology (name / brand / personal year) | Pure calc | kb_number_meanings, kb_business_sectors, kb_personal_year_themes |
No |
Public horoscope (/horoscope/:sign) |
Pure calc | kb_zodiac_signs, kb_briefing_phrases |
No |
| Muhurat finder | Swiss Ephemeris | kb_briefing_phrases (muhurat templates) |
No |
| Medical body-zodiac map | Static lookup | kb_zodiac_signs |
No |
| Chat | LLM | knowledge_documents (pgvector RAG) |
Yes |
| Tarot draw | Random shuffle | knowledge_documents (vector context) |
Yes (interpretation) |
| Vastu analysis | Deterministic scoring | knowledge_documents |
Yes (narrative) |
| Palmistry | — | knowledge_documents (palmistry KB) |
Yes (OpenAI Vision) |
| PDF reports | Mixed | kb_report_sections (fallback) + knowledge_documents |
Yes (long-form generation) |
The KB has two complementary halves.
Structured tables (18 of them, all i18n). Each row carries an i18n JSON blob keyed by locale (en, hi, ta, bn, te, kn, ml, gu, or, as):
kb_planets— 9 grahas × { name, color, remedy, mantra, doList[], avoidList[] }kb_nakshatras— 27 lunar mansions × name + qualitykb_tithis— 16 tithis (15 lunar days + Amavasya)kb_yogas— 27 yogas (Sun + Moon longitude combinations)kb_varas— 7 weekday lordskb_karanas— 11-half-lunar-day cycle nameskb_pakshas— Shukla / Krishna lunar phaseskb_zodiac_signs— 12 signs × element / modality / body parts / guidance, multi-traditionkb_chinese_animals— 12 animals × traitskb_flying_stars— 9 Feng Shui palace meaningskb_hellenistic_planets— 7 classical planets × sect, joy house, sect rolekb_doshas— Manglik / Kaal Sarp / Pitra / Nadi with remedy listskb_number_meanings— 1–9 plus master numbers 11/22/33kb_business_sectors— numerology-aligned suitable / avoid industrieskb_personal_year_themes— 1–9 yearly themes (career, finance, relationships, health)kb_profession_insights— 10 professions × 7 planets = 70 transit guidance rowskb_briefing_phrases— templated phrases for greetings, transits, dosha narratives, sade-sati, horary, BaZi, Western/Hellenistic, decumbiturekb_report_sections— 6 report types × 6 sections = 36 fallback templates
Vector index (knowledge_documents). A flat document store with:
text— the chunkcategory—kundli/horoscope/dosha/remedy/matching/panchang/numerology/palmistry/tarot/vastu/generalembedding— 1536-dimvector(OpenAItext-embedding-3-small)keywords[]— extracted for fast text search
Used by chat and the AI-narrative features for cosine-similarity RAG (<=> operator on pgvector) before the prompt is sent to the LLM.
To be honest about provenance: the KB tables were lifted from hardcoded maps inside the service code, then i18n-ed. Each seed file in apps/api/prisma/seed-kb/data/*.json carries an inline _source field documenting exactly which file/function the rows came from — e.g. planets.json's rows came from daily-briefing.service.ts's PLANET_ACTIVITIES / mantras / remedies tables, with Hindi names mined from apps/web/src/i18n/panchang-terms.ts. The other 11 locales are filled by npm run kb:backfill, which uses the LLM to translate English rows into the target locales (one-shot; results are reviewed before merging).
The seed comments cite the canonical references the data was checked against. These are the traditions the rows align with, not literal sources we ingested:
| Tradition | Canon |
|---|---|
| Vedic (Jyotish) | Brihat Parashara Hora Shastra (BPHS) — planet attributes, sattvic / rajasic / tamasic temperament, the 27-nakshatra cycle, 16-tithi cycle, 27-yoga cycle, dosha definitions |
| Vedic ayanamsa | Lahiri ayanamsa — canonical sidereal zero point used for all Swiss Ephemeris sidereal calls |
| Western | Ptolemy — Tetrabiblos — tropical zodiac signs, four elements, three modalities |
| Hellenistic | Vettius Valens — Anthology; Dorotheus of Sidon — Carmen Astrologicum — sect, planetary joys, profections, zodiacal releasing |
| Modern Hellenistic revival | Chris Brennan — Hellenistic Astrology; Robert Hand; Demetra George — Ancient Astrology — sect-role labels, joy interpretations |
| Numerology | Chaldean / Pythagorean synthesis — single-digit 1–9 plus master numbers 11/22/33 |
| Chinese | Standard 12-animal × 5-element zodiac; classical Feng Shui flying-stars 9-palace grid |
For RAG-style features (chat, palmistry, tarot, vastu, reports), the long-form content in knowledge_documents is operator-curated and embedded at insert time. Each row's source column records its provenance for licensing and re-translation purposes.
┌────────────────────────────────────────┐
request ───▶ │ feature service (chat / palmistry / │
│ tarot / vastu / report) │
└─────────────────┬──────────────────────┘
│ optional: pgvector top-K from
│ knowledge_documents → system prompt
▼
┌────────────────────────────────────────┐
│ LlmService.chatCompletion(...) │
│ 1. Redis cache GET (60-min TTL) │
│ └─► hit? return, log cacheHit=true │
│ 2. Try OpenAI │
│ 3. On 4xx / 5xx / timeout → Gemini │
│ 4. On 4xx / 5xx / timeout → Anthropic │
│ 5. Record to llm_usage (partitioned): │
│ provider, model, feature, tokens, │
│ USD cost, durationMs, errorCode, │
│ retryCount, cacheHit │
│ 6. Cache SET on success │
└─────────────────┬──────────────────────┘
▼
response to user
(refunded credit on any throw)
Provider availability is gated by site_settings:
llm.provider.openai.enabled— admin kill-switch (true / false)llm.provider.<n>.enabled— same per providerllm.<feature>.model— per-feature model override (e.g.llm.chat.model = gpt-4o-mini)llm.<feature>.temperature— per-feature creativity dialllm.cost.<model>.promptand.completion— USD per 1M tokens (admin overrides without redeploy)
The settings are reloaded every 30 seconds, so an admin can flip a provider off mid-incident from the LLM tab without restarting the API. Every call lands in llm_usage and feeds the Cost / Ops admin tabs, which is how MTD spend, error rate, p50/p95/p99 latency, cache hit %, and the Holt-Winters cost forecast are computed.
Configured in site_settings (overridable from the admin LLM tab):
| Feature | Default model | Rationale |
|---|---|---|
| Chat | gpt-4o-mini |
High-volume, cheap, fast |
| Palmistry (vision) | gpt-4o-mini |
Vision-capable + cheap |
| Tarot interpretation | gpt-4o-mini |
Short narrative |
| Vastu narrative | gpt-4o-mini |
Short narrative |
| Briefing personalization | gpt-4o-mini |
Short narrative |
| Report generation | gpt-4o |
Long-form, multi-section, higher precision |
| Embeddings | text-embedding-3-small |
1536-dim, $0.02/1M tokens |
The deterministic features (kundli, matching, panchang, etc.) never call an LLM — they're a Swiss Ephemeris computation joined with KB rows, which is why their cost-per-request is effectively zero and they always return identical results for identical inputs.
- Node.js 20+
- Docker Desktop / docker compose
- A few dollars of OpenAI / Gemini credits (optional — chat falls back to KB if no LLM key is set)
git clone https://github.com/xploroshan/jyotryx.git
cd jyotryx
# Bring up Postgres 16 + pgvector, Redis 7, pgbouncer, pgAdmin
docker compose up -d postgres redis pgbouncer pgadmin
# Install monorepo deps
npm install
# Configure environment
cp apps/api/.env.example apps/api/.env
cp apps/web/.env.example apps/web/.env
# Edit apps/api/.env — fill in JWT_SECRET / JWT_REFRESH_SECRET (any 32+ chars for dev),
# OPENAI_API_KEY (or leave blank to use KB fallback), and confirm DATABASE_URL points
# to the local pgbouncer (port 6432).
# Run migrations + seed
cd apps/api
npx prisma migrate deploy
npx prisma db seed # optional — populates KB tables
cd ../..
# Start everything via turbo
npm run devThe web app comes up on http://localhost:3000, the API on http://localhost:4000, with Swagger docs at http://localhost:4000/api/docs.
npm run dev # Run web + api concurrently (turbo)
npm run dev:web # Just the Next.js app
npm run dev:api # Just the NestJS API
npm run build # Build all apps
npm run lint # Lint all apps
cd apps/api
npm run build # nest build
npm test # Jest unit tests
npm run test:int # Integration tests (spawns its own pg/redis)
npm run test:k6:all # k6 load test suite
npx prisma migrate deploy # Apply pending migrations
npx prisma studio # Browse DB
cd apps/web
npm run lint # ESLint flat config (Next 16)
npm test # Vitest unit + RTL
npm run test:e2e # Playwright E2E (chromium)| Path | Purpose |
|---|---|
http://localhost:4000/api/docs |
Swagger / OpenAPI |
http://localhost:4000/api/health/ready |
DB + Redis readiness |
http://localhost:4000/api/metrics |
Prometheus metrics |
http://localhost:5050 |
pgAdmin (creds in .env) |
http://localhost:3000/admin |
Admin dashboard (after promoting a user to ADMIN) |
To promote your local user to admin:
psql $DATABASE_URL -c "UPDATE users SET role='ADMIN' WHERE email='[email protected]';"…or set [email protected] in apps/api/.env before booting — the bootstrap service runs at every API start and promotes any matching email.
| Surface | Provider | Notes |
|---|---|---|
| Web | Vercel | Auto-deploys main from GitHub. vercel.json at repo root sets the install command for the monorepo. |
| API | Railway | Watches apps/api/**. Builds from apps/api/Dockerfile. Healthcheck /api/health/ready. |
| Postgres | Supabase (ap-south-1) |
Pooler URL on :6543 for runtime, direct URL on :5432 for migrations. pgvector extension required. |
| Redis | Upstash (ap-south-1) |
TLS (rediss://). noeviction policy required by BullMQ. |
| Storage | Cloudflare R2 | Palm uploads, PDF reports. Custom domain uploads.jyotron.com. |
| DNS / CDN | Cloudflare | www.jyotron.com proxied; api.jyotron.com DNS-only. |
| LLM | OpenAI · Gemini · Anthropic | Failover order configurable in site_settings table. |
| Errors | Sentry | Both API and web instrumented. |
- Push to
main(or merge a PR). - Vercel auto-builds the web app and rolls forward.
- Railway sees the change under
apps/api/**, builds the Dockerfile, runsnpx prisma migrate deploy && node dist/main. .github/workflows/publish-api.ymlindependently pushes a tagged container to GHCR (ghcr.io/xploroshan/jyotryx-api:latestand:sha-<commit>) for K8s deploys.
For the long-form deployment guide — Supabase + Upstash + Railway setup, custom-domain wiring, K8s migration plan, monitoring hookup, and cost summary — see docs/DEPLOYMENT.md.
Required for production (full list in apps/api/.env.example):
DATABASE_URL # Supabase pooler URL (port 6543, ?pgbouncer=true)
DIRECT_URL # Supabase direct URL (port 5432) — for migrations
REDIS_URL / REDIS_HOST / REDIS_PORT
JWT_SECRET / JWT_REFRESH_SECRET
OPENAI_API_KEY · GEMINI_API_KEY · ANTHROPIC_API_KEY
LLM_FAILOVER_ENABLED=true
RAZORPAY_KEY_ID / RAZORPAY_KEY_SECRET / RAZORPAY_WEBHOOK_SECRET
R2_ACCOUNT_ID / R2_ACCESS_KEY_ID / R2_SECRET_ACCESS_KEY / R2_BUCKET_NAME / R2_PUBLIC_URL
GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET
FIREBASE_PROJECT_ID / FIREBASE_SERVICE_ACCOUNT_JSON
SENTRY_DSN
CORS_ORIGIN=https://www.jyotron.com
# Optional / tunable:
FREE_MONTHLY_CREDITS=10
KUNDLI_CREDIT_COST=2
CHAT_CREDIT_COST=1
PALMISTRY_CREDIT_COST=3
REPORT_CREDIT_COST=5
Numeric env vars (anything *_CREDIT_COST, PORT, OTP_LENGTH, etc.) are parsed via parseIntEnv() — non-numeric values fall back to the documented default and emit a [config] warning at boot. This is deliberate: a typo in Railway shouldn't silently break a paid feature (a real bug we hit and fixed — see commit ea1be1f).
All routes are mounted under /api (via NestJS global prefix). Auth-required routes use JwtAuthGuard; admin routes additionally use AdminGuard.
| Method | Path | Purpose |
|---|---|---|
POST |
/api/auth/register |
Email + password signup |
POST |
/api/auth/login |
Returns { accessToken, refreshToken } |
POST |
/api/auth/otp/send · /verify |
SMS OTP flow |
POST |
/api/auth/google · /apple · /firebase |
OAuth providers |
POST |
/api/auth/refresh |
Refresh-token rotation (family-tracked) |
GET |
/api/astrology/horoscope/:sign · /multi |
Daily/weekly/monthly/yearly |
GET |
/api/astrology/panchang |
Hindu calendar |
GET |
/api/astrology/chinese-zodiac/:year |
Animal + element |
GET |
/api/astrology/traditions |
List of supported traditions |
GET |
/api/payments/pricing |
Pricing config (subs + credit packs + reports) |
GET |
/api/health/live · /ready |
Liveness + readiness |
GET |
/api/metrics |
Prometheus |
| Method | Path | Cost (default) |
|---|---|---|
POST |
/api/chat/message · /stream |
1 |
POST |
/api/astrology/kundli |
2 |
POST |
/api/astrology/matching |
2 |
POST |
/api/astrology/divisional/:type · /kp-chart · /bazi · /western/* · /hellenistic/* · /horary/ask · /medical/decumbiture |
2 |
POST |
/api/palmistry/analyze |
3 |
POST |
/api/tarot/draw |
per-spread (1–5) |
POST |
/api/vastu/analyze |
2 |
POST |
/api/reports/generate |
5 |
POST |
/api/numerology/name · /brand |
free |
Every credit deduction goes through UserService.deductWithRefund(userId, cost, description, work) which atomically debits, runs the work, and refunds on any thrown error (typed as ADMIN_GRANT so the user sees the refund in their Credits sub-tab).
A 35+ endpoint surface under /api/admin/*. Highlights:
GET /admin/dashboard·/users·/users/:id·/payments·/chatsPUT /admin/users/:id·POST /admin/users/:id/credits/grant·/impersonate·/force-logoutGET /admin/funnel·/cohorts·/mrr·/churn-risk·/payment-failuresGET /admin/ops/llm-health·/queues·/health·/forecast/capacityGET /admin/cost/summary·/by-feature·/by-provider·/daily·/forecast/costGET /admin/safety/flagged·POST /admin/safety/flagged/:id/resolveGET /admin/gdpr/requests·POST /admin/gdpr/requests·/:id/fulfill·/:id/rejectPOST /admin/llm/provider/:name/disable·/enable·/keys/:provider/rotate·/admin/broadcastGET /admin/activity·POST /admin/activity/:id/undoGET /admin/settings·PUT /admin/settings(allowed prefixes:pricing.*,feature.*,display.*,notification.*,llm.*)
Full Swagger at ${API}/api/docs in non-production environments.
37 Prisma models in apps/api/prisma/schema.prisma. Highlights:
- Core:
User,Subscription,CreditTransaction,Payment,SiteSetting. - Astrology:
KundliChart,MatchingResult,TarotReading,PalmistryReading,Report,Notification. - Chat:
ChatSession,ChatMessage(partitioned bycreatedAt, monthly). - Knowledge base: 17
Kb*tables (planets, nakshatras, tithis, yogas, varas, doshas, zodiac signs, Chinese animals, Hellenistic planets, business sectors, personal-year themes, report sections, briefing phrases, …) — every row carries ani18nJSON keyed by locale. PlusKnowledgeDocumentwith a 1536-dim pgvector embedding column. - Operations:
LlmUsage(partitioned),ActivityLog(partitioned),StatDailyrollups. - Compliance:
FlaggedMessage,GdprRequest.
Partitioned tables (chat_messages, notifications, llm_usage, activity_logs) are partitioned monthly on createdAt so retention pruning is a partition drop, not a DELETE.
Migrations live in apps/api/prisma/migrations/ and run automatically at container start (prisma migrate deploy in the Dockerfile CMD).
BullMQ on the same Redis instance. Three queues:
| Queue | Processor | Behavior |
|---|---|---|
report-generation |
ReportProcessor |
LLM-generated PDF, uploaded to R2. 3 retries, exp backoff 5s. |
palmistry-analysis |
PalmistryProcessor |
OpenAI Vision palm reading. 3 retries. |
broadcast |
BroadcastProcessor |
Admin notification fan-out (audience filters: all / premium / locale). 2 retries, 10s backoff. |
Queue depth is exposed at GET /api/admin/ops/queues and rendered in the Ops admin tab.
- Prometheus at
GET /api/metrics(request latency histograms, status-code counts, queue depths). - OpenTelemetry wired in
apps/api/src/tracing.ts— setOTEL_EXPORTER_OTLP_ENDPOINTto forward (Grafana Cloud OTLP works on the free tier). - Sentry on both apps via
SENTRY_DSN. - Activity audit log captures every admin mutation (
previousData/newDatasnapshots) with one-click undo for credit grants and role changes. - LLM usage is recorded per call: provider, model, feature, tokens, USD cost, duration, cache-hit, error-code, retry-depth — feeds the Cost and Ops tabs.
- Healthcheck
GET /api/health/readychecks DB + Redis;GET /api/health/liveis a heartbeat.
Eleven lazy-loaded tabs under /admin:
| Tab | What's there |
|---|---|
| Dashboard | KPIs (users, premium, MRR, sessions, credits used) |
| Users | Paginated list with Usage column (used / given). Inline role change. Per-user detail panel with overview / subscriptions / payments / chats / credits / reports tabs. Grant Credits button. Impersonate. Force logout. |
| Activity | Filterable audit log. Undo. |
| Analytics | Revenue trend, feature usage, Credits Spent by Feature (7d), retention, conversion. |
| LLM | Provider toggles, cost overrides, key rotation. |
| Content | Knowledge-base counts. |
| Cost | MTD spend, daily series, by-feature/provider, Holt-Winters cost forecast with ±1σ band. |
| Funnel | Acquisition funnel, weekly cohorts, payment failures. |
| Ops | LLM error rate, p50/p95/p99 latency, cache hit, queue depths, capacity forecast. |
| Safety | OpenAI moderation queue. Approve / hide / actioned. |
| GDPR | Export and delete requests with SLA tracker. |
Defaults shipped in apps/api/src/config/configuration.ts. All overridable from Railway env vars or, for runtime tuning, from the site_settings table.
| Plan | Price | What you get |
|---|---|---|
| Free | ₹0 | 10 credits on signup |
| Monthly | ₹499 | Unlimited |
| Annual | ₹4,999 | Unlimited (2 months free) |
Credit packs (one-time): 25 / 75 / 200 credits at ₹99 / ₹249 / ₹599. PDF reports run ₹599–₹999.
Default credit costs:
| Feature | Credits |
|---|---|
| Chat message | 1 |
| Kundli / matching / divisional / KP / BaZi / synastry / etc. | 2 |
| Vastu | 2 |
| Palmistry | 3 |
| Tarot (single / three / Celtic) | 1 / 2 / 5 |
| PDF report | 5 |
| Numerology | 0 (free) |
- Migrations are append-only — never edit a merged migration. Add a new file under
apps/api/prisma/migrations/<TIMESTAMP>_name/migration.sql. - Numeric env vars must go through
parseIntEnv()(config layer) so a typo doesn't produceNaN. - Credit-spending features must use
UserService.deductWithRefund(userId, cost, description, work)so failures auto-refund. - Raw SQL on
llm_usageuses mixed casing because the table was created in two stages — original columns are"createdAt"/"userId"(camelCase, quoted), the four ops-telemetry columns added later are"cache_hit"/"error_code"/"duration_ms"/"retry_count"(snake_case). Prisma model fields carry@map(...)for the snake_case ones. - Partitioned tables can't have inbound foreign keys; integrity is application-level.
- Admin mutations must write an
ActivityLogentry withpreviousData+newData.
Proprietary — all rights reserved.
Jyotron is for entertainment and spiritual-guidance purposes only and is not a substitute for professional medical, legal, or financial advice.