How I Built 80+ Psychological Tests in Next.js Architecture, i18n, and Lessons Learned

Building a psychology testing platform sounds straightforward — until you try to support 20 languages, 7 different scoring systems, and 80+ assessments with zero page reloads. Here's how I did it with PrismaTest.
The Challenge
I wanted to create a platform where anyone in the world could take scientifically validated personality tests — in their native language, for free, with beautiful visual results. No registration, no paywalls, no clunky multi-page forms.
The requirements were ambitious:
80+ tests covering personality (Big Five, MBTI, Enneagram), career (Holland RIASEC, DISC), IQ (Raven's matrices, spatial reasoning), relationships (attachment styles, love languages), and mental health (depression, anxiety, burnout)
20 languages: English, Spanish, German, French, Portuguese, Russian, Japanese, Korean, Arabic, and 11 more
Instant results with charts, radar diagrams, and detailed interpretations
Single-page app feel — no reloads between questions
Architecture: One Test = One JSON File
The core insight that made everything manageable: each test is a single JSON file containing everything — all 20 translations, questions, answer options, scoring logic, and result descriptions.
{
"slug": "mbti",
"scoring": { "type": "dichotomy", ... },
"display": { "type": "type", ... },
"translations": {
"en": { "title": "MBTI Personality Test", ... },
"es": { "title": "Test de Personalidad MBTI", ... },
"ja": { "title": "MBTI性格診断テスト", ... }
},
"questions": [ ... ]
}
Adding a new test = creating one file. No database migrations, no code changes, no deployment needed. The app automatically discovers and registers new tests from the content/tests/ directory.
7 Universal Scoring Types
Instead of writing custom scoring logic for each test, I built 7 universal scoring engines:
| Type | Used By | How It Works |
|---|---|---|
likert-scales |
Big Five, 16PF | Sum answers per scale |
likert-levels |
BDI, anxiety tests | Total score → severity level |
dichotomy |
MBTI, socionics | Binary dimensions (E/I, T/F) |
forced-choice |
Belbin, Love Languages | Distribute points among options |
color-sequence |
Lüscher test | Analyze color ordering |
formula |
EQ, IQ tests | Custom formulas per scale |
custom |
Special cases | Fully custom scoring function |
Every test JSON declares its scoring type, and the engine handles the rest. This means I can add a new Big Five variant in 10 minutes — just create the JSON with "scoring": { "type": "likert-scales" }.
i18n at Scale: 20 Languages Without Going Insane
The localization layer was the hardest part. Some lessons:
RTL support for Arabic required special layout logic — not just CSS
direction: rtl, but also mirroring charts and progress barsCJK languages (Japanese, Korean) need specialized fonts (Noto Sans JP/KR) loaded conditionally to avoid bloating the initial bundle
Pluralization varies wildly between languages — Russian has 3 plural forms, Arabic has 6. I use ICU MessageFormat via
next-intlQuestion length differs dramatically — a 5-word English question might be 15 words in German. The UI had to be flexible enough to handle this without breaking
All UI strings live in separate message files per locale. Test content lives in the JSON files. The two systems are independent, which keeps things clean.
The Result
PrismaTest now serves thousands of daily users. The most popular tests:
MBTI Personality Type — the classic
Big Five (IPIP-NEO-300) — the most comprehensive personality assessment
Enneagram — 9 personality types
Holland Career Test (RIASEC) — career aptitude
Dark/Light Triad — the one everyone shares with friends
Tech Stack
Next.js 14 (App Router, server + client components)
TypeScript end-to-end
Tailwind CSS for responsive design
PostgreSQL for user data and statistics
Redis for caching test metadata
Docker + Traefik for production deployment
next-intl for internationalization
Key Takeaways
Data-driven architecture wins. Keeping tests as JSON files instead of database records made everything simpler — version control, deployment, and adding new tests.
Build universal engines, not custom code. 7 scoring types cover 80+ tests. The abstraction pays for itself after the 3rd test.
i18n is a multiplier. Supporting 20 languages 10x'd the addressable audience with relatively little extra work per test.
Speed matters for engagement. SPA-style navigation with no page reloads means users complete more tests per session.
If you're building something similar, I'm happy to chat about the architecture. And if you're curious about your personality, try any test on PrismaTest — it's all free. 🧠
