Some checks failed
CI / Lint (push) Has been cancelled
CI / TypeCheck (push) Has been cancelled
CI / Test (push) Has been cancelled
Deploy / Docker Build & Push (map[context:. dockerfile:apps/api/Dockerfile name:api]) (push) Has been cancelled
Deploy / Docker Build & Push (map[context:. dockerfile:apps/cms/Dockerfile name:cms]) (push) Has been cancelled
Deploy / Docker Build & Push (map[context:. dockerfile:apps/web/Dockerfile name:web]) (push) Has been cancelled
CI / Build (push) Has been cancelled
Deploy / Deploy (push) Has been cancelled
- Monorepo: Turborepo + pnpm workspaces with 7 apps/packages - Backend: NestJS scaffold with 9 modules (auth, tenant, curriculum, simulation, portfolio, ai-coach, analytics, classroom, gamification) - Frontend: React 18 + Vite + TailwindCSS + shadcn/ui with 10 pages, 14 UI primitives, 3 Zustand stores - Database: Prisma schema with 19 models, 13 enums, seed script, multi-tenant ready - Docker: Dev, production, and Portainer Compose files with Traefik reverse proxy - Configuration: .env.example (47 vars), Zod validation, frontend-safe env exposure - i18n: English + Greek locale files (10 files), ICU MessageFormat, react-i18next - Shared packages: @investplay/types, @investplay/ui, @investplay/i18n, @investplay/utils - CI/CD: GitHub Actions (lint, typecheck, test, build, deploy, PR checks) - Documentation: CONTEXT.md, ARCHITECTURE.md (10 Mermaid diagrams), API.md, LOCALIZATION.md, DEVELOPMENT-ROADMAP.md - Infrastructure: Dockerfiles (dev + prod), nginx configs, backup/healthcheck scripts - Security: JWT auth guards, role-based access, rate limiting, Helmet, CORS, PII sanitization
390 lines
14 KiB
Markdown
390 lines
14 KiB
Markdown
# InvestPlay — Development Roadmap
|
|
|
|
> **Status:** Phase 1 — Foundation
|
|
> **Last Updated:** 2026-06-12
|
|
> **Target:** Production-grade, multi-tenant, multi-platform financial literacy platform
|
|
|
|
---
|
|
|
|
## Architecture Decisions
|
|
|
|
| Decision | Choice | Rationale |
|
|
|----------|--------|-----------|
|
|
| Monorepo Tool | **Turborepo** | Better DX than Nx for this scale; native ESM support |
|
|
| Package Manager | **pnpm** | Disk-efficient, strict dependency resolution |
|
|
| Backend Framework | **NestJS** | Modular, DI, GraphQL native, WebSocket integrated |
|
|
| Frontend Framework | **React + Vite** | Fast HMR, modern tooling, Capacitor/Tauri compatible |
|
|
| CMS | **Payload CMS** (self-hosted) | Code-first, TypeScript-native, block-based content, i18n built-in |
|
|
| Database ORM | **Prisma** | Type-safe, migration-first, multi-schema for tenant isolation |
|
|
| Cache | **Redis** | BullMQ queues + session store + rate limiting |
|
|
| Auth | **Clerk** (initial) → **Auth0** (B2B SSO) | Fast B2C start, SAML SSO for institutions |
|
|
| i18n Framework | **next-intl / react-i18next** | ICU message format, locale-aware routing |
|
|
| CSS Framework | **TailwindCSS** + **shadcn/ui** | Design tokens, accessible components |
|
|
| Containerization | **Docker Compose** (dev) + **Portainer** (prod) | Consistent local/remote, easy management |
|
|
| CI/CD | **GitHub Actions** | Free for public repos, Docker layer caching |
|
|
|
|
---
|
|
|
|
## Development Phases
|
|
|
|
### PHASE 1 — Foundation ✅ COMPLETED (2026-06-12)
|
|
**Goal:** Running monorepo, Docker dev environment, auth, basic API, empty UI shell
|
|
|
|
- [x] Project documentation and roadmap
|
|
- [x] Monorepo structure (Turborepo + pnpm workspaces)
|
|
- [x] Docker Compose for local dev (PostgreSQL, Redis, MinIO, Payload CMS)
|
|
- [x] Docker Compose for Contabo/Portainer production deployment
|
|
- [x] Environment variable system (.env per service, validation via Zod)
|
|
- [x] NestJS backend scaffold with core modules (75 files, 9 modules)
|
|
- [x] Prisma schema — 19 models, 13 enums, users, tenants, roles, classrooms
|
|
- [x] Auth module (JWT + SSO ready)
|
|
- [x] Tenant module (multi-tenancy, feature flags)
|
|
- [x] React + Vite frontend scaffold (55+ files, 10 pages, 14 UI primitives)
|
|
- [x] TailwindCSS + shadcn/ui design system
|
|
- [x] i18n infrastructure (EN + EL, 10 locale files, ICU MessageFormat)
|
|
- [x] Shared packages: `@investplay/types`, `@investplay/ui`, `@investplay/i18n`, `@investplay/utils`
|
|
- [x] Payload CMS scaffold with Docker support
|
|
- [x] ESLint + Prettier + Husky pre-commit hooks
|
|
- [x] CI pipeline (lint, typecheck, test, build) + deploy + PR checks
|
|
- [x] Comprehensive documentation (CONTEXT.md, ARCHITECTURE.md, API.md, LOCALIZATION.md)
|
|
|
|
### PHASE 2 — Core Learning (MVP B2C)
|
|
**Goal:** Self-guided learner can complete lessons and earn XP
|
|
|
|
- [ ] CMS block renderer in frontend (Hero, Text, Quiz, Calculator blocks)
|
|
- [ ] Lesson progression engine (track → module → lesson → block)
|
|
- [ ] XP and leveling system
|
|
- [ ] Badges and achievements
|
|
- [ ] Quiz/assessment engine
|
|
- [ ] User dashboard with progress visualization
|
|
- [ ] Streak tracking
|
|
- [ ] B2C auth flow (email + social)
|
|
|
|
### PHASE 3 — Simulations & Gamification
|
|
**Goal:** Interactive simulations and mini-games work end-to-end
|
|
|
|
- [ ] Blind Scenario engine (historical CSV → WebSocket tick stream)
|
|
- [ ] Synthetic market generator
|
|
- [ ] Portfolio management (virtual trades, ROI calculation)
|
|
- [ ] Budget Game (50/30/20 drag-and-drop)
|
|
- [ ] Debt Snowball mini-game
|
|
- [ ] Hype Trap narrative challenge
|
|
- [ ] Anti-cheat mechanisms
|
|
- [ ] Simulation leaderboards
|
|
|
|
### PHASE 4 — AI Coach
|
|
**Goal:** Context-aware educational AI with cost controls
|
|
|
|
- [ ] AI proxy service (NestJS → OpenAI/Gemini)
|
|
- [ ] Context injection pipeline
|
|
- [ ] Token bucket rate limiting (per user, per tenant)
|
|
- [ ] BYOK (Bring Your Own Key) mode
|
|
- [ ] Socratic prompt engineering
|
|
- [ ] Audit logging
|
|
- [ ] PII sanitization before LLM calls
|
|
- [ ] Graceful fallback when quota exhausted
|
|
|
|
### PHASE 5 — Classroom & Institutions (B2B MVP)
|
|
**Goal:** Teachers can manage classrooms and institutions can deploy
|
|
|
|
- [ ] Teacher dashboard
|
|
- [ ] Classroom creation with invite codes
|
|
- [ ] Assignment system
|
|
- [ ] Live "Time Machine" classroom simulation
|
|
- [ ] Cohort analytics and heatmaps
|
|
- [ ] Intervention alerts
|
|
- [ ] PDF/CSV report generation
|
|
- [ ] Institution admin panel
|
|
- [ ] White-label configuration
|
|
- [ ] Stripe Connect B2B billing
|
|
- [ ] SSO integration (SAML/OIDC)
|
|
|
|
### PHASE 6 — Mobile & Desktop
|
|
**Goal:** Native app wrappers for iOS, Android, Windows, macOS, Linux
|
|
|
|
- [ ] Capacitor wrapper (iOS + Android)
|
|
- [ ] Push notifications (FCM)
|
|
- [ ] Offline lesson caching
|
|
- [ ] Tauri v2 wrapper (Windows, macOS, Linux)
|
|
- [ ] Desktop-specific features (offline mode, system tray)
|
|
|
|
### PHASE 7 — Analytics & Reporting
|
|
**Goal:** Data-driven insights for institutions and platform operators
|
|
|
|
- [ ] Behavioral telemetry pipeline
|
|
- [ ] Aggregated materialized views (nightly rollups)
|
|
- [ ] Teacher analytics dashboard
|
|
- [ ] PDF/CSV automated report generation
|
|
- [ ] GDPR anonymization pipeline
|
|
- [ ] Opt-out mechanism for research aggregation
|
|
- [ ] "Gen Z Financial Behavior Index" report templates
|
|
|
|
### PHASE 8 — Localization Expansion
|
|
**Goal:** Full EU language support
|
|
|
|
- [ ] Add DE, FR, ES, IT, PT, NL locales
|
|
- [ ] CMS content localization workflow
|
|
- [ ] Locale-specific financial examples (taxes, regulations)
|
|
- [ ] RTL support readiness
|
|
- [ ] Locale-aware currency and number formatting
|
|
|
|
### PHASE 9 — Production Hardening
|
|
**Goal:** Enterprise-grade security, performance, and reliability
|
|
|
|
- [ ] Load testing (k6 / Artillery)
|
|
- [ ] Penetration testing
|
|
- [ ] Database backup/restore automation
|
|
- [ ] Disaster recovery plan
|
|
- [ ] Multi-region deployment (EU data residency)
|
|
- [ ] SOC 2 / ISO 27001 readiness
|
|
- [ ] SLA monitoring and alerting
|
|
|
|
---
|
|
|
|
## i18n Strategy
|
|
|
|
### Implementation
|
|
- **UI Strings:** `react-i18next` with ICU MessageFormat in JSON files per locale
|
|
- **Educational Content:** Payload CMS localized collections (each lesson has locale variants)
|
|
- **Currency/Number Formatting:** `Intl.NumberFormat` (browser-native, no extra library)
|
|
- **Date Formatting:** `Intl.DateTimeFormat` with locale-aware relative time
|
|
|
|
### Locale File Structure
|
|
```
|
|
packages/i18n/src/locales/
|
|
en/
|
|
common.json # Buttons, nav, errors
|
|
finance.json # Financial terms, instrument names
|
|
gamification.json # XP, badges, achievement names
|
|
classroom.json # Teacher dashboard, assignments
|
|
ai-coach.json # AI chat UI strings
|
|
gr/
|
|
common.json
|
|
finance.json
|
|
...
|
|
```
|
|
|
|
### Initial Languages (Phase 1)
|
|
- English (en) — Primary development language
|
|
- Greek (el) — Market entry requirement
|
|
|
|
### Expansion Languages (Phase 8)
|
|
- German (de), French (fr), Spanish (es), Italian (it), Portuguese (pt), Dutch (nl)
|
|
- All EU official languages eventually
|
|
|
|
---
|
|
|
|
## Deployment Architecture
|
|
|
|
### Local Development (Windows)
|
|
```
|
|
docker compose -f docker-compose.dev.yml up
|
|
```
|
|
Services:
|
|
- `api` — NestJS backend (hot-reload via tsx watch)
|
|
- `web` — Vite React frontend (HMR on port 5173)
|
|
- `cms` — Payload CMS (port 3000)
|
|
- `postgres` — PostgreSQL 16 (port 5432)
|
|
- `redis` — Redis 7 (port 6379)
|
|
- `minio` — S3-compatible storage (ports 9000/9001)
|
|
|
|
### Contabo Production (via Portainer)
|
|
```
|
|
docker compose -f docker-compose.prod.yml up -d
|
|
```
|
|
Portainer stack deployment with:
|
|
- Traefik reverse proxy (auto-SSL via Let's Encrypt)
|
|
- Multi-stage Docker builds (CI → GHCR → Portainer pull)
|
|
- Health checks on all containers
|
|
- Log rotation via Docker logging drivers
|
|
- Database backup sidecar container
|
|
|
|
---
|
|
|
|
## Environment Variables
|
|
|
|
All configuration through environment variables. No hardcoded secrets.
|
|
|
|
### Required ENV Files
|
|
```
|
|
.env.example # Template for all vars (committed)
|
|
.env # Local overrides (gitignored)
|
|
.env.production.example # Production template (committed)
|
|
```
|
|
|
|
### Key Variable Categories
|
|
| Category | Variables |
|
|
|----------|-----------|
|
|
| Database | `DATABASE_URL`, `DATABASE_POOL_MIN`, `DATABASE_POOL_MAX` |
|
|
| Redis | `REDIS_URL`, `REDIS_PASSWORD` |
|
|
| Auth | `JWT_SECRET`, `JWT_EXPIRES_IN`, `CLERK_SECRET_KEY` |
|
|
| AI | `OPENAI_API_KEY`, `GEMINI_API_KEY`, `AI_DEFAULT_DAILY_LIMIT` |
|
|
| Storage | `S3_ENDPOINT`, `S3_ACCESS_KEY`, `S3_SECRET_KEY`, `S3_BUCKET` |
|
|
| Email | `RESEND_API_KEY`, `EMAIL_FROM` |
|
|
| Billing | `STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET` |
|
|
| Tenant | `TENANT_DEFAULT_AI_MODE`, `TENANT_MAX_TOKENS_MONTHLY` |
|
|
| i18n | `DEFAULT_LOCALE`, `SUPPORTED_LOCALES` |
|
|
|
|
---
|
|
|
|
## Repository Structure
|
|
|
|
```
|
|
investplay/
|
|
├── apps/
|
|
│ ├── api/ # NestJS backend
|
|
│ │ ├── src/
|
|
│ │ │ ├── modules/
|
|
│ │ │ │ ├── auth/
|
|
│ │ │ │ ├── tenant/
|
|
│ │ │ │ ├── curriculum/
|
|
│ │ │ │ ├── simulation/
|
|
│ │ │ │ ├── portfolio/
|
|
│ │ │ │ ├── ai-coach/
|
|
│ │ │ │ ├── analytics/
|
|
│ │ │ │ ├── classroom/
|
|
│ │ │ │ └── gamification/
|
|
│ │ │ ├── common/
|
|
│ │ │ │ ├── guards/
|
|
│ │ │ │ ├── decorators/
|
|
│ │ │ │ ├── filters/
|
|
│ │ │ │ └── interceptors/
|
|
│ │ │ ├── config/
|
|
│ │ │ └── main.ts
|
|
│ │ ├── prisma/
|
|
│ │ │ ├── schema.prisma
|
|
│ │ │ └── migrations/
|
|
│ │ ├── test/
|
|
│ │ ├── Dockerfile
|
|
│ │ └── package.json
|
|
│ ├── web/ # React + Vite frontend
|
|
│ │ ├── src/
|
|
│ │ │ ├── components/
|
|
│ │ │ ├── pages/
|
|
│ │ │ ├── hooks/
|
|
│ │ │ ├── stores/
|
|
│ │ │ ├── lib/
|
|
│ │ │ ├── styles/
|
|
│ │ │ └── i18n/
|
|
│ │ ├── public/
|
|
│ │ ├── index.html
|
|
│ │ ├── vite.config.ts
|
|
│ │ ├── Dockerfile
|
|
│ │ └── package.json
|
|
│ ├── cms/ # Payload CMS
|
|
│ │ ├── src/
|
|
│ │ │ └── collections/
|
|
│ │ ├── package.json
|
|
│ │ └── Dockerfile
|
|
│ ├── mobile/ # Capacitor wrapper
|
|
│ └── desktop/ # Tauri v2 wrapper
|
|
├── packages/
|
|
│ ├── types/ # @investplay/types
|
|
│ │ ├── src/
|
|
│ │ │ ├── user.ts
|
|
│ │ │ ├── tenant.ts
|
|
│ │ │ ├── curriculum.ts
|
|
│ │ │ ├── simulation.ts
|
|
│ │ │ ├── portfolio.ts
|
|
│ │ │ └── analytics.ts
|
|
│ │ └── package.json
|
|
│ ├── ui/ # @investplay/ui
|
|
│ │ ├── src/
|
|
│ │ │ ├── components/
|
|
│ │ │ └── lib/
|
|
│ │ └── package.json
|
|
│ ├── i18n/ # @investplay/i18n
|
|
│ │ ├── src/
|
|
│ │ │ └── locales/
|
|
│ │ └── package.json
|
|
│ └── utils/ # @investplay/utils
|
|
│ ├── src/
|
|
│ └── package.json
|
|
├── docker/
|
|
│ ├── docker-compose.dev.yml
|
|
│ ├── docker-compose.prod.yml
|
|
│ ├── traefik/
|
|
│ │ ├── traefik.yml
|
|
│ │ └── dynamic.yml
|
|
│ └── nginx/
|
|
│ └── nginx.conf
|
|
├── scripts/
|
|
│ ├── setup.sh
|
|
│ ├── seed.ts
|
|
│ └── backup.sh
|
|
├── docs/
|
|
│ ├── DEVELOPMENT-ROADMAP.md
|
|
│ ├── CONTEXT.md
|
|
│ ├── API.md
|
|
│ └── ARCHITECTURE.md
|
|
├── .github/
|
|
│ └── workflows/
|
|
│ ├── ci.yml
|
|
│ └── deploy.yml
|
|
├── .env.example
|
|
├── .env.production.example
|
|
├── turbo.json
|
|
├── pnpm-workspace.yaml
|
|
├── package.json
|
|
├── tsconfig.base.json
|
|
├── .eslintrc.js
|
|
├── .prettierrc
|
|
└── README.md
|
|
```
|
|
|
|
---
|
|
|
|
## Database Schema (Core Entities)
|
|
|
|
```
|
|
User — id, email, role, locale, tenantId, xp, level
|
|
Tenant — id, name, domain, branding, featureFlags, aiMode
|
|
Classroom — id, name, tenantId, teacherId, inviteCode
|
|
ClassroomStudent — id, classroomId, userId, joinedAt
|
|
Module — id, cmsId, track, order, tenantId
|
|
Lesson — id, cmsId, moduleId, order, estimatedMins
|
|
UserProgress — id, userId, lessonId, status, score, completedAt
|
|
QuizAttempt — id, userId, quizId, answers, score, timestamp
|
|
Trade — id, userId, simulationId, asset, amount, timestamp
|
|
Portfolio — id, userId, simulationId, cashBalance, holdings
|
|
Badge — id, name, description, icon, criteria
|
|
UserBadge — id, userId, badgeId, earnedAt
|
|
AILog — id, tenantId, userId, tokensUsed, timestamp
|
|
AnalyticsEvent — id, userId, eventType, metadata, timestamp
|
|
```
|
|
|
|
---
|
|
|
|
## Key Technical Decisions
|
|
|
|
### Multi-Tenancy Strategy
|
|
**Schema-level isolation** via PostgreSQL schemas (one per tenant) for maximum data isolation. Tenant-specific connection pooling via Prisma's multi-schema preview feature.
|
|
|
|
### API Design
|
|
- **Primary:** GraphQL for all CRUD operations (type-safe, no over-fetching)
|
|
- **Real-time:** WebSockets (Socket.io) for live simulations and leaderboards
|
|
- **Webhooks:** REST endpoints for Stripe, Resend, third-party integrations
|
|
|
|
### AI Cost Control
|
|
Backend-side hard enforcement (not reliant on OpenAI budget alerts):
|
|
- Redis token bucket per user (daily) and per tenant (monthly)
|
|
- Hard cutoff at quota exhaustion (no grace period)
|
|
- Admin alert when approaching 80% of monthly quota
|
|
|
|
### Security
|
|
- JWT with RS256 (asymmetric) for service-to-service auth
|
|
- GraphQL query depth limiting (max depth 7)
|
|
- Rate limiting on all public endpoints
|
|
- CORS whitelist per tenant domain
|
|
- Helmet.js for HTTP security headers
|
|
- Input validation via Zod on every endpoint
|
|
- Prompt injection defense in AI proxy
|
|
|
|
---
|
|
|
|
## Tracking
|
|
|
|
Progress tracked via this file. Each completed task gets `[x]`.
|
|
Git commits follow Conventional Commits format.
|
|
CI badges added once pipelines are running.
|