Live site: https://sandhi-ninja.vercel.app
Sandhi Ninja is a Sanskrit sandhi practice app built with React, Phaser, Vite, and a same-repo TypeScript backend. The current live app centers on three game modes, family-based word filters, campaign graduation, and multilingual sandhi explanations.
It also includes baseline SEO setup so the site is easier to discover and preview in search engines and social links:
- canonical URL metadata
- search title and description metadata
- Open Graph and Twitter preview tags
- schema.org structured data
robots.txtsitemap.xmlsite.webmanifest
Sandhi Splitting: choose the correct sandhi, then split at the correct akshara boundarySandhi Joining: choose the correct sandhi and join adjacent padani back into a compoundNinja Slice: a speed-focused split mode that shows the target sandhi directly and tests placement/timingLearn,Practice, andChallengesession presets- advanced controls for
With clock/No clock, answer reveal duration, andAuto next/Stay here Mixed,Svara,Vyanjana, andVisargafamily filters- campaign mastery and graduation across built-in
Sandhi SplittingandSandhi Joining - feedback that distinguishes:
- correct place + correct sandhi
- correct place + wrong sandhi
- wrong place + sandhi valid elsewhere in the word
- both wrong
- red/shake wrong-attempt feedback on board interactions
- answer reveal after repeated misses, including sandhi name, split place, sutra number, nimittam, and explanation
- randomized word flow with stable per-word rule ordering in the dock
- responsive desktop and mobile layout
- UI in
English,Sanskrit, andTelugu
The built-in gameplay bank currently covers three sandhi families:
SvaraVyanjanaVisarga
Current built-in playable pool:
Mixed:392unique gameplay-eligible root wordsSvara:160words containing at least one svara-sandhi stepVyanjana:168words containing at least one vyanjana-sandhi stepVisarga:69words containing at least one visarga-sandhi step
Important counting note:
Mixedis the unique playable pool- family counts are membership counts, not disjoint buckets
- a multi-step word may belong to more than one family, so
160 + 168 + 69is expected to be greater than392
Gameplay currently teaches 23 rule types:
Svara: Savarṇa Dīrgha, Guṇa, Vṛddhi, Yaṇ, Ayavāyāva, Pūrvarūpa, PararūpaVyanjana: Jaśtva, Charva, Anunāsika, Anusvāra, Pūrvasavarṇa, Parasavarṇa, Chhatva, Tugāgama, Ścutva, Ṣṭutva, N-Final Satva, YavalopaVisarga: Visarga-Satva, Visarga-Repha, Visarga-Lopa, Visarga-Ootvam
The same-repo analyzer backend currently supports deterministic svara-sandhi reversal for:
Savarna DirghaGunaVrddhiYanAyavayavaPurvarupaPararupa
The explorer returns normalized forms, ranked candidate analyses, split steps, sutra metadata, nimitta, and multilingual explanations.
Sandhi Splitting: choose the sandhi, then split at the shown gold boundary guideSandhi Joining: choose sandhi and join valid neighboring piecesNinja Slice: falling-word style split mode with direct target-sandhi display
Learn: full help, no clock, answer reveal allowed, manual next, no campaign masteryPractice: teaching help visible, no clock by default, manual next, clean solves count toward masteryChallenge: lighter help, 4 lives, clock on by default, auto-next by default, clean solves count toward mastery
- guided hints after repeated misses
- reveal after repeated failures
- clear distinction between boundary mistakes and rule mistakes
- red/shake wrong-attempt feedback on the active word or join boundary
splits leftindicator during play
- graduation depends on mastering the built-in word bank in both
Sandhi SplittingandSandhi Joining Learnmode never grants masteryPracticeandChallengegrant mastery only for clean solves withoutShow answerNinja Sliceis optional in v1 and does not affect graduation- endless review stays available after graduation
- same-repo API via
POST /api/sandhi/analyze - normalization across
IAST,Devanagari, andTelugu - ranked candidate analyses with step-by-step metadata
- current analyzer scope is
svara-first, narrower than the gameplay bank
React 19TypeScriptVitePhaser 4Framer MotionNode.jsHTTP server for same-origin production serving- Vercel-compatible serverless route wrappers in
api/
src/
components/ React UI
data/ sandhi bank, rules, and UI copy
game/ Phaser runtime and scene logic
styles/ global styling and responsive layout
types/ gameplay and content types
utils/ client helpers and explorer adapter
server/
engine/ recursive sandhi analyzer
routes/ API route logic shared by local server and Vercel wrappers
shared/
contracts/ request/response types
core/ rules, normalization, transliteration helpers
api/
health.ts Vercel health route
sandhi/analyze.ts Vercel analyzer route
public/
robots.txt crawler rules
sitemap.xml search sitemap
site.webmanifest install/share metadata
social-preview.svg social preview image
tests/
engine.test.mjs analyzer and API tests
Install dependencies:
npm installRun frontend and backend together:
npm run devRun them separately:
npm run dev:client
npm run dev:serverUseful scripts:
npm run build
npm run build:client
npm run build:server
npm run test
npm run preview
npm startDuring local development, Vite proxies /api/* to http://127.0.0.1:3001.
Build:
npm run buildStart:
npm startThe Node server:
- serves the built frontend from
dist/ - serves
/api/sandhi/analyze - serves
/api/health
Current production:
Deploy from the repo root:
npx vercel@latest deploy --prod --yesThis repo already includes:
vercel.jsonfor frontend + API rewritesapi/serverless entrypoints for Vercel- SEO metadata and structured data in
index.html - search/share assets in
public/
This repo includes render.yaml for a single Node service deploy.
Manual settings:
Build Command: npm install && npm run build
Start Command: npm startHealth check:
/api/health
Request:
{
"input": "शिवालयः",
"script": "auto",
"maxResults": 10
}Accepted script values:
autoiastdevanagaritelugu
Response includes:
- normalized forms in
IAST,Devanagari, andTelugu - ranked candidate analyses
- final split words
- step-by-step rule applications
- sutra, nimitta, and explanation metadata
Response:
{
"status": "ok"
}Run the analyzer and API tests:
npm test- gameplay support is broader than analyzer support; the analyzer is still
svara-first - family counts overlap by design because one built-in word may carry more than one sandhi family in its full split chain
- the analyzer is rule-based and does not yet validate against a lexical or morphology database
- custom entries live in browser storage
- the explorer and the game share the same rule definitions, but only the explorer depends on the analyzer API path