The school we wished existed. Now it does.
Following ISE Engineering Fundamentals (personal project, no Microsoft affiliation)
MirrorBuddy complies with EU AI Act (2024/1689), Italian Law 132/2025, GDPR, and COPPA requirements. Production Vercel compute is pinned to EU region fra1 via vercel.json. See our compliance documentation for details.
Every child deserves an education that fits them—not the other way around.
Traditional schools were designed for the "average" student. But there is no average student. There are children with dyslexia who think in pictures. Children with ADHD who need movement and variety. Children with autism who thrive on structure and clarity. Children with cerebral palsy who need adaptive interfaces.
These children are not broken. The system is.
MirrorBuddy is our answer: a school that adapts to each student, not students who must adapt to school.
Every student in MirrorBuddy has access to three types of AI support:
STUDENT
|
+-------------+-------------+
| | |
v v v
+-----------+ +-----------+ +-----------+
| COACH | | BUDDY | | MAESTRI |
| (6 AI) | | (6 AI) | | (26 AI) |
| | | | | |
| Method | | Peer | | Content |
| Support | | Support | | Experts |
+-----------+ +-----------+ +-----------+
| Type | Characters | Relationship | Goal |
|---|---|---|---|
| Maestri | 26 historical & modern figures | Mentor (vertical) | Teach subjects with passion |
| Coaches | Melissa, Roberto, Chiara, Andrea, Favij, Laura | Learning coach (vertical) | Develop METHOD and autonomy |
| Buddies | Mario, Noemi, Enea, Bruno, Sofia, Marta | Peer friend (horizontal) | Emotional support, shared struggles |
Instead of reading about Euclid in a textbook, students learn mathematics with Euclid himself. Instead of memorizing dates about Darwin, they explore evolution alongside Darwin. Instead of watching a video about Marie Curie, they discuss chemistry with Curie.
Each Maestro is an AI tutor embodying a legendary figure from history:
26 Maestri: Euclide (Math), Leonardo (Art), Darwin (Biology), Curie (Chemistry), Feynman (Physics), Galileo (Astronomy), Lovelace (CS), Shakespeare (English), Mozart (Music), Socrate (Philosophy), Erodoto (History), Manzoni (Italian), Cicerone (Civic Ed), Humboldt (Geography), Ippocrate (Health), Smith (Economics), Chris (PE), Omero (Storytelling), Alex Pina (Spanish), Mascetti (Supercazzola), Simone (Sport), Cassese (International Law), Moliere (French), Goethe (German), Cervantes (Spanish), Levi-Montalcini (Biology)
This project was born for Mario.
Mario survived a pediatric stroke at birth. It left him with cerebral palsy. Like millions of children with learning differences, Mario faced a school system that wasn't built for him: rigid schedules, inflexible methods, one-size-fits-all teaching.
In 2013, his parents founded FightTheStroke to fight for children like Mario. After a decade of advocacy, research, and watching AI transform what's possible, they built what they always wanted: the school Mario deserved.
"A birth accident should not dictate a child's future."
Watch their story: TED Talk - In our baby's illness, a life lesson
- 🎤 Voice Sessions — Natural voice conversations with AI Maestri (Azure OpenAI Realtime API)
- 🗺️ Mind Maps — Auto-generated, interactive visualizations with voice commands
- 🎴 FSRS Flashcards — Spaced repetition backed by cognitive science
- 📝 Quizzes — Adaptive assessments with instant feedback
- ⚖️ Adaptive Difficulty — Multi-signal difficulty tuning (chat/voice/quiz/flashcard)
- 📸 Homework Help — Photo capture + AI-powered step-by-step guidance (no direct answers)
- 🎮 Gamification — XP, levels, badges, streaks, leaderboards
- ⏱️ Pomodoro Timer — ADHD-friendly focus sessions
- 📊 Progress Tracking — Subject mastery, session history, analytics
- ♿ Accessibility — WCAG 2.1 AA, 7 specialized profiles for neurodiversity
- 📱 Mobile App — Native iOS/Android via Capacitor (same codebase)
- 🔐 Enterprise SSO — Google Workspace + Microsoft 365 OIDC with PKCE
- 🤖 Multi-AI — Azure OpenAI primary, Claude fallback, Ollama local dev
- 🛡️ SOC 2 Ready — Audit logging, access control, vendor risk assessment
- 🏫 School Plans — Registration, admin dashboard, SSO config, bulk invite
- 🔑 Password Reset — Self-service password recovery with secure tokens
- 📴 Offline Support — PWA with native Service Worker, cache-first strategy
- 🎖️ Achievements — Unlock badges, streak tracking, gamified progress
- 📱 Mobile Build — Capacitor-based iOS/Android with CI validation
- ✅ CI Hardening — E2E and accessibility tests blocking deployments
→ See detailed feature documentation in docs/claude/
graph LR
Student["🧑🎓 Student"] --> Input["Chat or Voice"]
Input --> AI["🤖 AI Engine<br/>Azure OpenAI"]
AI --> Safety["🛡️ Safety Layer<br/>5-layer protection"]
Safety --> Character["🎭 38 Characters<br/>Maestri, Coaches, Buddies"]
Character --> Tools["🧰 14 Tools<br/>Quiz, Mindmap, Flashcard..."]
Tools --> Response["📚 Personalized<br/>Response"]
Response --> Student
AI --> RAG["📖 RAG<br/>Student Materials"]
RAG --> AI
WCAG 2.1 AA: Dyslexia (OpenDyslexic, spacing, TTS) | ADHD (focus mode, breaks) | Visual Impairment (high contrast, screen reader) | Motor Impairment (large targets, keyboard, voice) | Autism (predictable layouts) | Auditory Impairment (captions, visual cues) | Cerebral Palsy (adaptive interfaces)
Instant Accessibility (ADR 0060): Floating button for quick profile switching with 90-day cookie persistence and automatic OS preference detection.
MirrorBuddy implements Microsoft's Ethical Design Hacker security mindsets, designed specifically for protecting children with learning differences.
| Feature | Protection |
|---|---|
| PII Detection | Auto-detects Italian fiscal codes, names, emails, phones |
| Anonymization | Replaces sensitive data before AI processing |
| Data Retention | Configurable TTL (365d conversations, 730d progress) |
| Right to Erasure | GDPR Article 17 deletion with audit trail |
| Indicator | Meaning |
|---|---|
| 🟢 Green | High confidence, knowledge-base backed |
| 🟡 Yellow | Medium confidence, partial sources |
| 🟠 Orange | Low confidence, AI-generated |
| 🔴 Red | Hallucination risk detected |
- Content Filtering: Age-appropriate responses with Italian messaging
- Jailbreak Detection: Pattern matching for prompt injection attempts
- Session Throttling: Gradual escalation from warnings to timeouts
- Audit Trail: Anonymized logging for safety monitoring
- OAuth PKCE: RFC 7636 code_verifier/code_challenge with SHA-256
- Token Encryption: AES-256-GCM encryption at rest for OAuth tokens
- Rate Limiting: Auth-specific (5/15min login, 3/15min password change)
- SVG Sanitization: DOMPurify for Mermaid diagram output
- COPPA Verification: 6-digit email codes for parental consent
- Unicode Normalization: Prevents Cyrillic/Greek homoglyph attacks
- Configuration Versioning: Rollback safety settings with history
- Knowledge Base Auditing: Content validation before embedding
→ Technical details: docs/adr/0004-safety-guardrails.md | docs/adr/0008-parent-dashboard-gdpr.md | docs/adr/0080-security-audit-hardening.md
# Clone and install (pnpm required; see below)
git clone https://github.com/FightTheStroke/MirrorBuddy.git
cd MirrorBuddy
pnpm install # npm install still works during W1–W3 transition
# Configure environment
cp .env.example .env
# Edit .env with your Azure OpenAI or Ollama credentials
# Initialize database
pnpm prisma generate
pnpm prisma migrate dev
# Start development server
pnpm devPrerequisites: Node ≥ 20, pnpm ≥ 10.33.0 (pinned via the packageManager field).
Turborepo handles cross-package task orchestration; pnpm dev / pnpm build / pnpm lint run through Turbo automatically.
Open http://localhost:3000 and start learning.
→ See full setup guide: SETUP.md → Having issues? Check: TROUBLESHOOTING.md
MirrorBuddy ships as native iOS and Android apps using Capacitor, sharing the same codebase as the web platform.
Supported Platforms:
- iOS 14+ — iPhone, iPad
- Android 8+ — Phones, tablets
Building Mobile Apps:
# Install Capacitor
pnpm add @capacitor/cli @capacitor/core
# Add iOS/Android platforms
pnpm cap add ios
pnpm cap add android
# Build for mobile
pnpm build:mobile
# Open native IDE to build & deploy
npx cap open ios # Opens Xcode
npx cap open android # Opens Android Studio→ Complete mobile build guide: docs/mobile/BUILD-GUIDE.md
Try MirrorBuddy instantly without creating an account. Trial mode provides limited access to evaluate the platform:
| Resource | Limit | Description |
|---|---|---|
| Chat messages | 10 | Text conversations with Maestri |
| Voice time | 5 minutes | Voice sessions with AI tutors |
| Tool calls | 10 | Mind maps, summaries, flashcards, quizzes |
| Documents | 1 | PDF/image upload for homework help |
| Maestri | 3 | Randomly assigned AI tutors |
Trial limits are configurable via TierService in the database. Admins can adjust trial tier limits in the admin panel without code changes.
Anti-abuse protection: Trial sessions are tracked by IP hash + cookie to prevent repeated trials via incognito browsing.
Admin Features (ADR 0061): Collapsible sidebar, bulk invite actions, direct invite creation, real-time KPI dashboard.
→ Technical details: docs/adr/0056-trial-mode-architecture.md | docs/adr/0061-admin-section-redesign.md
MirrorBuddy offers three tiers to meet different needs:
| Feature | Trial | Base (Free) | Pro |
|---|---|---|---|
| Account | Anonymous | Free signup | Paid |
| Chat messages/day | 10 | 50 | Unlimited |
| Voice time/day | 5 min | 30 min | Unlimited |
| Tools/day (mind maps, etc) | 10 | 30 | Unlimited |
| Maestri access | 3 random | 25 | All 26 |
| Flashcards (FSRS) | ✓ | ✓ | ✓ |
| Progress analytics | — | ✓ | ✓ |
| Homework help (PDF/photos) | — | ✓ | ✓ |
| Parental dashboard | — | ✓ | ✓ |
| Video Vision | — | — | ✓ |
| Priority support | — | — | ✓ |
→ See detailed tier comparison: Tier Rules
MirrorBuddy is a fully multilingual platform supporting 5 languages with dynamic locale detection, language-specific maestri, and localized content delivery.
| Language | Code | Primary Region | Status |
|---|---|---|---|
| Italian | it | Italy | Primary |
| English | en | Global | Supported |
| French | fr | France/Belgium | Supported |
| German | de | Germany/Austria | Supported |
| Spanish | es | Spain/Latin America | Supported |
- Dynamic Locale Detection: Browser language → user profile → IP geolocation → Italian fallback
- Language-Specific Maestri: Molière (French), Goethe (German), Cervantes (Spanish) teach their own language
- Bilingual Learning: Grammar lessons grounded in authentic literature and cultural context
- Real-Time Translation: All UI text, tool responses, and educational content translated
- Voice Localization: Azure OpenAI voices support all 5 languages
- FSRS Flashcards: Spaced repetition works across all languages
- Accessibility: All 7 DSA profiles work in every supported language
- User Selection: Explicit language choice (stored in
mirrorbuddy-localecookie) - Profile Setting: User's preferred language from database
- Browser Locale:
navigator.language(Italian/English/French/German/Spanish) - IP Geolocation: Inferred from Vercel Analytics geo data
- Fallback: Italian if unsupported locale
To add a new language (e.g., Portuguese):
# 1. Create translation file (next-intl namespace-based structure)
cp -r messages/it/ messages/pt/
# 2. Update config
# Edit src/lib/i18n/config.ts
export const SUPPORTED_LOCALES = ['it', 'en', 'fr', 'de', 'es', 'pt'];
# 3. Validate translations
npm run i18n:validate
# 4. Deploy
git add messages/pt/ src/lib/i18n/config.ts
git commit -m "i18n: add Portuguese language support"
git pushDashboard: https://mirrorbuddy.grafana.net/d/dashboard/ → i18n Metrics
Key Metrics:
- Missing translations (count)
- Locale detection success rate (%)
- Translation load time (ms, P95)
- Language pack CDN hit ratio (%)
- Fallback language usage (%)
Alerts:
- Missing translations > 5 → SEV3 incident
- Locale detection < 95% → SEV3 incident
- Translation load time > 500ms → SEV3 incident
For i18n-specific incidents:
- INC-005: Missing translations or broken language packs
- INC-006: Locale detection failures, wrong language displayed
- Troubleshooting locale mapping, cache clearing, deployment verification
Stack: Next.js 16 App Router → Zustand State → API Routes → Azure OpenAI (chat+voice+embeddings) / Claude (fallback) / Ollama (local) → Prisma ORM → PostgreSQL + pgvector
- Voice transport now defaults to Azure Realtime GA (
voice_ga_protocol=enabled) - Calling overlay UX and transcript safety are both enabled by default
- Chat and voice share a unified conversation shell/store for consistent handoff and memory
Key Decisions:
- ADR 0015: Zustand syncs with backend via REST APIs. User data NEVER in localStorage—only database.
- ADR 0033: RAG (Retrieval-Augmented Generation) using Azure OpenAI embeddings + pgvector for semantic search of user materials.
- ADR 0064: Language-specific maestri with bilingual teaching patterns for foreign language learning
- ADR 0068: Multilingual platform architecture with dynamic locale detection and real-time translation
→ Full architecture & diagram: ARCHITECTURE.md
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (App Router) |
| Language | TypeScript 5 (strict mode) |
| Styling | Tailwind CSS 4 |
| State | Zustand |
| AI | Azure OpenAI / Claude / Ollama |
| RAG | pgvector (semantic search) |
| Mind Maps | MarkMap |
| Database | Prisma + PostgreSQL + pgvector |
| Testing | Playwright E2E (API-focused) + Vitest unit |
| Observability | Grafana Cloud + Prometheus metrics |
| Monorepo | pnpm workspaces + Turborepo (see ADR 0164) |
Dashboard: https://mirrorbuddy.grafana.net/d/dashboard/
Metrics Exported (V1Plan compliance):
- Session Health: success rate, drop-off rate, stuck loop rate
- Safety: refusal precision, jailbreak block rate, incidents S0-S3
- Performance: HTTP latency P95, error rates by route
- Cost: per-session cost (text/voice), cost spikes
Setup:
# .env
GRAFANA_CLOUD_PROMETHEUS_URL=https://prometheus-prod-XX.grafana.net/api/v1/push/influx/write
GRAFANA_CLOUD_PROMETHEUS_USER=your-instance-id
GRAFANA_CLOUD_API_KEY=glc_your_token
# Test push
npx tsx scripts/test-grafana-push.tsEndpoints:
GET /api/health— Load balancer health checkGET /api/health/detailed— Full system metricsGET /api/metrics— Prometheus format (Grafana scrape)
Health Status Values:
| Status | Meaning | HTTP Status |
|---|---|---|
healthy |
All checks passed | 200 |
degraded |
One or more checks warning (high latency, etc.) | 200 |
unhealthy |
One or more checks failed (database down, AI unavailable) | 503 |
Example Response:
{
"status": "healthy",
"version": "0.15.0",
"timestamp": "2025-01-26T21:50:00.000Z",
"uptime": 3600,
"checks": {
"database": {
"status": "pass",
"message": "Connected",
"latency_ms": 45
},
"ai_provider": {
"status": "pass",
"message": "Azure OpenAI configured"
},
"memory": {
"status": "pass",
"message": "128MB / 512MB (25%)"
}
}
}Monitor Azure spending with the included Python backend:
# Setup
cd backend
cp .env.example .env
# Edit .env with your Azure subscription ID
# Install dependencies
pip install -r requirements.txt
# Run API server
uvicorn api.main:app --reloadEndpoints:
GET /api/v1/costs?days=30— Cost summary by serviceGET /api/v1/costs/forecast— Monthly forecastGET /api/v1/costs/drilldown?days=30— Detailed breakdown with AI model usage
Configuration (all from .env, never hardcoded):
AZURE_SUBSCRIPTION_ID=your-subscription-id # Required
AZURE_SUBSCRIPTION_NAME=My Subscription # Optional display name
# Optional - for service principal auth (if not using az login)
AZURE_TENANT_ID=...
AZURE_CLIENT_ID=...
AZURE_CLIENT_SECRET=...Quick test (requires az login):
cd backend && python3 -c "
from api.azure_costs import AzureCostService
import asyncio
result = asyncio.run(AzureCostService().get_cost_summary(7))
print(f'Last 7 days: \${result.total_cost:.2f}')
"| Document | Description |
|---|---|
| docs/claude/ | Comprehensive feature documentation |
| SETUP.md | Installation and configuration guide |
| SETUP-PRODUCTION.md | Production deployment guide |
| TROUBLESHOOTING.md | Common issues and solutions |
| ARCHITECTURE.md | Technical architecture details |
| ARCHITECTURE-DIAGRAMS.md | Visual architecture (24 Mermaid diagrams) |
| CONTRIBUTING.md | Contribution guidelines |
| CLAUDE.md | Developer quick reference |
| backend/.env.example | Azure Cost API configuration |
We welcome contributions! See CONTRIBUTING.md.
Important: All PRs must follow the Execution Checklist. PRs without a completed checklist will be rejected.
This project was born for inclusion. Every contribution must be:
- Keyboard accessible
- Screen reader compatible
- Color-blind friendly
- Available to everyone
- Email: roberdan@fightthestroke.org
- Organization: FightTheStroke
- TED Talk: In our baby's illness, a life lesson
Apache 2.0 — See LICENSE
Chosen for patent protection (critical for AI/ML projects) and institutional trust.
MirrorBuddy is Apache 2.0 in product proof mode. The competitive advantage is the governed system around the repository, not the code itself.
See LICENSE-STRATEGY.md for:
- Why Apache 2.0 (not MIT or Commons Clause)
- What constitutes "open-core" vs proprietary value
- Trigger points for license revision
Every child can learn. We just need to teach them differently.

