An modern, free, and fully-featured language learning platform built with Next.js 16, React 19, TypeScript, Prisma ORM, and Tailwind CSS. Learn new languages through eleven content types: videos, flashcards, interactive drag-drop exercises, reading comprehension with glossary support, audio-visual diagnostic quizzes, writing expression challenges, timed mental agility challenges, unit closing exams, grammar guides with color-coded schemas, listening comprehension, and icebreaker dynamics.
This repository is open source and distributed under the terms described in the LICENSE file.
MaltTalk is a comprehensive language learning platform implementing proven pedagogical frameworks:
- Motivation/Diagnosis Phase - Engaging landing page, course selection, audio-visual diagnostic quizzes
- Information Processing - Multiple content delivery methods (video, reading, flashcards)
- Reinforcement - Interactive exercises (drag-drop, writing challenges) and spaced repetition
- Systematization/Closure - Progress tracking, completion feedback, vocabulary validation
- β Eleven Content Types - Video, Flashcards, Drag-Drop Exercises, Reading Comprehension, Audio-Visual Quizzes, Writing Challenges, Mental Agility Games, Closing Exams, Grammar Guides, Listening, Icebreaker
- β Interactive Glossary - Click-to-define vocabulary with images
- β Real-time Video Duration - Actual duration tracking (not hardcoded)
- β Audio-Visual Diagnostic System - Associating sounds with visual elements (gestures/images)
- β Writing Expression Challenges - Text composition with vocabulary validation
- β Grammar Guides - Sentence structure visualization with color-coded schemas
- β Listening Comprehension - Audio exercises with image-based answer selection
- β Icebreaker Dynamics - Real-world expressions in contextual situations
- β Modern UI/UX - Light/dark mode, responsive design, gamification elements
- β Complete Admin Panel - CRUD operations for all content types (8+ tabs)
- β Spaced Repetition - Flashcard system for optimal vocabulary retention
- β Progress Dashboard - Visual progress tracking with statistics
- Framework: Next.js 16.2.6 (App Router, Turbopack)
- UI Library: React 19 with TypeScript
- Styling: Tailwind CSS 3.x with full dark mode support
- Interactive: @dnd-kit for drag-and-drop exercises
- Media: react-player for video content, react-markdown for reading
- API: Next.js API Routes (RESTful pattern)
- Server Actions: Server-side data fetching with Next.js
- ORM: Prisma 7.8.0 with PostgreSQL adapter
- Database: PostgreSQL at maltloor.com:5432 with connection pooling
- Language: TypeScript with strict mode
- Linting: ESLint for code quality
- Build: Turbopack for ultra-fast compilation
- Deployment: Vercel-ready
malttalk/
βββ src/
β βββ app/
β β βββ layout.tsx # Root layout component
β β βββ page.tsx # Landing page with hero section
β β βββ globals.css # Global styles and Tailwind setup
β β βββ admin/
β β β βββ page.tsx # Admin panel (~1900 lines, 5 tabs)
β β βββ module/
β β β βββ [course]/
β β β β βββ page.tsx # Course detail/listing page
β β β β βββ [lesson]/
β β β β β βββ page.tsx # Lesson content renderer
β β β β βββ dashboard/
β β β β βββ page.tsx # Student course dashboard
β β βββ cursos/
β β β βββ page.tsx # Courses listing page
β β βββ api/
β β β βββ admin/ # Admin CRUD endpoints (17 routes)
β β β β βββ courses/
β β β β βββ topics/
β β β β βββ lessons/
β β β β βββ tags/
β β β β βββ video-contents/
β β β β βββ reading-contents/
β β β β βββ reading-contents/list/
β β β β βββ flashcard-contents/
β β β β βββ drag-drop-contents/
β β β β βββ visio-acoustic-contents/
β β β β βββ writing-challenges/
β β β β βββ mental-agility/
β β β β βββ closing-exam/
β β β β βββ grammar-guides/
β β β β βββ listening-contents/
β β β β βββ icebreaker-contents/
β β β β βββ glossary-items/
β β β β βββ debug/
β β β βββ lessons/
β β β β βββ [uuid]/ # Public lesson endpoint
β β β βββ debug/
β β β βββ lessons/ # Debug endpoint
β β βββ actions/
β β β βββ modules.ts # Server actions (7 functions, documented)
β β βββ components/
β β βββ landing-page/ # 9 landing page components
β β β βββ Hero.tsx
β β β βββ Card.tsx
β β β βββ Features.tsx
β β β βββ Level.tsx
β β β βββ Start.tsx
β β β βββ Boxes/
β β β β βββ Box.tsx
β β β β βββ Feature.tsx
β β β β βββ Skill.tsx
β β β βββ titles/
β β β βββ BorderedTitle.tsx
β β βββ ui/
β β β βββ Footer.tsx
β β β βββ ModuleList.tsx (with real video duration)
β β β βββ SidebarModuleToggle.tsx
β β βββ video/
β β β βββ VideoDiv.tsx # Video player with duration tracking
β β βββ reading/
β β β βββ ReadingDiv.tsx # Reading with interactive glossary
β β βββ flashcards/
β β β βββ FlashcardsDiv.tsx # Spaced repetition system
β β βββ drag-drop/
β β β βββ DragDropDiv.tsx # Interactive grammar exercises
β β βββ visio-acoustic/
β β β βββ VisioAcousticDiv.tsx # Audio-visual diagnostic quizzes
β β βββ writing-challenges/
β β β βββ WritingChallengesDiv.tsx # Text composition exercises
β β βββ mental-agility/
β β β βββ MentalAgilityDiv.tsx # Timed mental agility challenges
β β βββ closing-exam/
β β βββ ClosingExamDiv.tsx # Unit closing assessments
β β βββ grammar-guides/
β β βββ GrammarGuidesDiv.tsx # Sentence structure with color-coded schemas
β β βββ listening/
β β βββ ListeningDiv.tsx # Audio comprehension with image selection
β β βββ icebreaker/
β β βββ IcebreakerDiv.tsx # Real-world expressions in context
β βββ lib/
β β βββ prisma.ts # Prisma singleton with PostgreSQL adapter
β βββ data/
β β βββ lessons.ts # Sample data/constants
β βββ generated/
β βββ prisma/ # Auto-generated Prisma types
βββ prisma/
β βββ schema.prisma # Database schema (fully documented)
β βββ migrations/ # Database migration history
β βββ migration_lock.toml
βββ public/
β βββ flashcards/ # 15 flashcard images (fruits)
β βββ logo.ico
β βββ favicon.ico
βββ Configuration Files
β βββ next.config.ts # Next.js configuration
β βββ tsconfig.json # TypeScript configuration
β βββ tailwind.config.ts # Tailwind CSS configuration
β βββ postcss.config.mjs # PostCSS configuration
β βββ eslint.config.mjs # ESLint configuration
β βββ prisma.config.ts # Prisma configuration
β βββ package.json # Dependencies and scripts
βββ AGENTS.md # AI agent customization rules
βββ CLAUDE.md # Claude AI instructions
βββ README.md # Project documentation
Key Statistics:
- Source Files: ~75 custom source files (105+ total with generated)
- Components: 27 React components with JSDoc comments
- API Routes: 18 REST endpoints with full documentation
- Database Models: 17 Prisma models with comprehensive field documentation
- Content Types: 11 unique learning content types (video, flashcards, drag-drop, reading, audio-visual, writing, mental-agility, closing-exam, grammar-guides, listening, icebreaker)
- Code Coverage: All source files optimized with English comments
- TypeScript: 100% type-safe with strict mode enabled
MaltTalk uses PostgreSQL with 17 core models and 1 junction table for relationships. All models are fully documented in prisma/schema.prisma.
- Timed challenges with countdown timer
- Pattern recognition and categorization exercises
- Multiple difficulty levels (beginner, intermediate, advanced)
- Immediate feedback with custom messages
- Score tracking and completion percentage
- Visual timer with red warning when β€5 seconds
- Unit-level comprehensive assessments
- Timed exams with MM:SS format countdown
- Point-based scoring system
- Passing score validation (default 70%)
- Per-question points allocation
- Pass/fail status with detailed feedback
- Sequential question progression
- Sentence structure visualization with color-coded parts
- Interactive example carousel with navigation
- Difficulty levels (beginner, intermediate, advanced)
- Progress tracking through multiple guides
- Visual JSON-based schema system
- Complete example sentences for each rule
- Audio-based comprehension exercises
- Image-based multiple choice answers (4 options)
- Real-time audio player with controls
- Immediate feedback (correct/incorrect)
- Score accumulation tracking
- Completion screen with retry option
- Audio URL and image option management
- Real-world expression learning in context
- Situation illustrations with descriptions
- Mark-as-learned progress tracking
- Expression carousel navigation
- Visual progress indicators
- Completion screen showing learned count
- Contextual usage scenarios
model courses {
slug String @id // URL identifier (e.g., "english")
id Int @default(autoincrement())
title String // Display name
description String? // Course description
topics topics[] // Related topics (1:N)
}- Purpose: Represents a language course (English, Spanish, etc.)
- Relationships: One-to-many with
topics
model topics {
id Int @id @default(autoincrement())
slug String @unique // URL identifier
title String // Module name
course_slug String // Foreign key to courses
lessons lessons[] // Related lessons (1:N)
courses courses @relation(...)
}- Purpose: Organizes lessons within a course (Greetings, Numbers, etc.)
- Relationships: Many-to-one with
courses, one-to-many withlessons
model lessons {
id Int @id @default(autoincrement())
uuid String? @unique @default(dbgenerated("gen_random_uuid()"))
topic_id Int // Foreign key to topics
type lesson_type // Content type: video|flashcards|drag_drop|reading
title String // Lesson name
description String? // Lesson description
slug String? // URL identifier
// Content relationships
topics topics @relation(...)
video_contents video_contents[]
reading_contents reading_contents[]
flashcard_contents flashcard_contents[]
drag_drop_contents drag_drop_contents[]
visio_acoustic_contents visio_acoustic_contents[]
writing_challenge_contents writing_challenge_contents[]
lesson_tag lesson_tag[]
}- Purpose: Individual learning units with specific content types
- Features: UUID for public sharing, type discrimination for content routing
- Relationships: Many-to-one with
topics, one-to-many with all content types
enum lesson_type {
video // Video content
flashcards // Vocabulary practice
drag_drop // Interactive exercises
reading // Reading comprehension
visio_acoustic // Audio-visual diagnostic quizzes
writing_challenges // Text composition exercises
mental_agility // Timed mental agility challenges
closing_exam // Unit closing assessment tests
}model video_contents {
id Int @id @default(autoincrement())
lesson_id Int // Foreign key to lessons
url String // Video URL/source
description String? // Transcript or description
duration Int? @default(600) // Duration in seconds (default: 10 min)
lessons lessons @relation(...)
}- Features: Real-time video duration tracking (added July 2026)
- Default: 600 seconds (10 minutes) for new entries
- Usage: ModuleList displays actual duration instead of hardcoded time
model reading_contents {
id Int @id @default(autoincrement())
lesson_id Int // Foreign key to lessons
text String // Full reading material
glossary_items glossary_items[] // Related vocabulary
lessons lessons @relation(...)
}model glossary_items {
id Int @id @default(autoincrement())
reading_id Int // Foreign key to reading_contents
word String // Target word/phrase
definition String // Definition in learning language
image_url String? // Visual reference (optional)
synonym_english String? // English translation (optional)
reading_contents reading_contents @relation(...)
}- Purpose: Interactive glossary for reading comprehension
- Features: Click-to-define with images, definitions, and English synonyms
model flashcard_contents {
id Int @id @default(autoincrement())
lesson_id Int // Foreign key to lessons
front_image String? // Card front image (optional)
back_title String // Card back text (word/translation)
back_pronunciation String? // Phonetic pronunciation guide
lang String // Language code (e.g., "es", "fr")
lessons lessons @relation(...)
}- Purpose: Vocabulary cards with images and pronunciation
- Optimization: Supports multiple cards per lesson
model drag_drop_contents {
id Int @id @default(autoincrement())
lesson_id Int // Foreign key to lessons
text String // Item to be dragged
category String // Target category
feedback_message_wrong String? // Custom error feedback message
lessons lessons @relation(...)
}model visio_acoustic_contents {
id Int @id @default(autoincrement())
lesson_id Int // Foreign key to lessons
question_text String // Question prompt
sound_url String // URL to audio file
image_url String // URL to gesture/image
correct_answer String // Correct answer option
option_b String // Alternative answer option
option_c String // Alternative answer option
option_d String? // Optional fourth answer
feedback_correct String? // Positive feedback message
feedback_incorrect String? // Negative feedback message
question_order Int // Order within lesson
difficulty_level String // beginner|intermediate|advanced
lessons lessons @relation(...)
}- Purpose: Audio-visual association exercises for pronunciation and gesture recognition
- Features: Real-time feedback, difficulty levels, multiple choice options
- Usage: Students listen to audio and select corresponding visual element
model writing_challenge_contents {
id Int @id @default(autoincrement())
lesson_id Int // Foreign key to lessons
title String // Challenge title
prompt String // Writing task prompt
min_words Int // Minimum word count
max_words Int // Maximum word count
required_vocabulary String? // Comma-separated required words
example_answer String? // Model answer
difficulty_level String // beginner|intermediate|advanced
challenge_order Int // Order within lesson
evaluation_criteria String? // JSON evaluation rubric
hint String? // Optional hint
lessons lessons @relation(...)
}- Purpose: Guided writing exercises with vocabulary validation
- Features: Word count validation, required vocabulary checking, example answers
- Validation: Students must meet min/max word requirements to submit
model mental_agility_contents {
id Int @id @default(autoincrement())
lesson_id Int // Foreign key to lessons
title String // Challenge title
prompt String // Challenge prompt/question
time_limit Int // Time limit in seconds
correct_answer String // Correct answer option
option_b String // Alternative answer (B)
option_c String // Alternative answer (C)
option_d String? // Optional answer (D)
image_url String? // Optional visual element
feedback_correct String? // Positive feedback message
feedback_incorrect String? // Negative feedback message
challenge_type String? // Challenge category (sequence, categorization, etc.)
difficulty_level String // beginner|intermediate|advanced
challenge_order Int // Order within lesson
lessons lessons @relation(...)
}- Purpose: Rapid-fire timed challenges for pattern recognition and quick thinking
- Features: Per-challenge timer, difficulty progression, instant feedback
- Scoring: Tracks correct answers and displays completion percentage
model closing_exam_contents {
id Int @id @default(autoincrement())
lesson_id Int // Foreign key to lessons
title String // Question title
description String? // Question context/description
time_limit Int // Exam time limit in seconds
question String // Exam question text
correct_answer String // Correct answer option
option_b String // Alternative answer (B)
option_c String // Alternative answer (C)
option_d String? // Optional answer (D)
passing_score Int // Minimum percentage to pass (default: 70)
difficulty_level String // beginner|intermediate|advanced
question_order Int // Order within exam
points_value Int // Points awarded for correct answer
feedback_correct String? // Positive feedback message
feedback_incorrect String? // Negative feedback message
lessons lessons @relation(...)
}- Purpose: Comprehensive unit assessments with passing criteria
- Features: Point-based scoring, overall time limit, cumulative scoring
- Assessment: Displays pass/fail status and percentage score
model tags {
id Int @id @default(autoincrement())
slug String @unique
name String // Display name
lesson_tag lesson_tag[] // Many-to-many with lessons
}model lesson_tag {
lesson_id Int
tag_id Int
lessons lessons @relation(...)
tags tags @relation(...)
@@id([lesson_id, tag_id]) // Composite primary key
}courses (1) ββββ (N) topics
β β
(N) lessons (1)
βββ (N) video_contents
βββ (N) reading_contents
β βββ (N) glossary_items
βββ (N) flashcard_contents
βββ (N) drag_drop_contents
βββ (N) lesson_tag ββββ (N) tags
erDiagram
COURSES ||--o{ TOPICS : has
TOPICS ||--o{ LESSONS : contains
LESSONS ||--o{ VIDEO_CONTENTS : includes
LESSONS ||--o{ READING_CONTENTS : includes
LESSONS ||--o{ FLASHCARD_CONTENTS : includes
LESSONS ||--o{ DRAG_DROP_CONTENTS : includes
LESSONS ||--o{ VISIO_ACOUSTIC_CONTENTS : includes
LESSONS ||--o{ WRITING_CHALLENGE_CONTENTS : includes
LESSONS ||--o{ MENTAL_AGILITY_CONTENTS : includes
LESSONS ||--o{ CLOSING_EXAM_CONTENTS : includes
LESSONS ||--o{ LESSON_TAG : "is tagged"
READING_CONTENTS ||--o{ GLOSSARY_ITEMS : defines
TAGS ||--o{ LESSON_TAG : "tagged by"
COURSES {
string slug PK
int id
string title
string description
}
TOPICS {
int id PK
string slug UK
string title
string course_slug FK
}
LESSONS {
int id PK
string uuid UK
int topic_id FK
string type "enum: video|flashcards|drag_drop|reading|visio_acoustic|writing_challenges|mental_agility|closing_exam"
string title
string description
string slug
}
VIDEO_CONTENTS {
int id PK
int lesson_id FK
string url
string description
int duration "in seconds"
}
READING_CONTENTS {
int id PK
int lesson_id FK
string text "full reading material"
}
GLOSSARY_ITEMS {
int id PK
int reading_id FK
string word
string definition
string image_url
string synonym_english
}
FLASHCARD_CONTENTS {
int id PK
int lesson_id FK
string front_image
string back_title
string back_pronunciation
string lang "e.g., 'es', 'fr'"
}
DRAG_DROP_CONTENTS {
int id PK
int lesson_id FK
string text
string category
string feedback_message_wrong
}
VISIO_ACOUSTIC_CONTENTS {
int id PK
int lesson_id FK
string question_text
string sound_url
string image_url
string correct_answer
string difficulty_level
}
WRITING_CHALLENGE_CONTENTS {
int id PK
int lesson_id FK
string title
string prompt
int min_words
int max_words
string difficulty_level
}
MENTAL_AGILITY_CONTENTS {
int id PK
int lesson_id FK
string title
string prompt
int time_limit "in seconds"
string correct_answer
string challenge_type
string difficulty_level
}
CLOSING_EXAM_CONTENTS {
int id PK
int lesson_id FK
string title
string question
int time_limit "in seconds"
string correct_answer
int passing_score "percentage"
int points_value
string difficulty_level
}
TAGS {
int id PK
string slug UK
string name
}
LESSON_TAG {
int lesson_id PK_FK
int tag_id PK_FK
}
- Node.js 18+ (recommend 20+)
- PostgreSQL 12+ (or Prisma-hosted database)
- npm or yarn package manager
- .env.local file with
DATABASE_URL
# 1. Install dependencies
npm install
# 2. Configure environment
echo "DATABASE_URL=postgresql://user:password@localhost:5432/malttalk" > .env.local
# 3. Setup database
npx prisma migrate dev --name init
npx prisma generate
# 4. Start development server
npm run devOpen: http://localhost:3000
Populate your database with example data including an English course with all 8 content types:
# Seed database with example data
npx tsx ./prisma/seedRaw.ts
# Or reset database and seed
npx prisma migrate reset --force
npx tsx ./prisma/seedRaw.tsExample Data Created:
- 1 Course: English (Complete English course from beginner to advanced level)
- 1 Tag: General
- 6 Topics: Greetings, Daily Vocabulary, Pronunciation, Grammar, Writing, Review
- 8 Lessons: One lesson for each content type with representative data
This provides a fully functional demo with:
- πΉ Video Lesson
- π΄ Flashcards (3 cards)
- π― Drag-Drop Exercise (3 items)
- π Reading with Glossary (3 vocabulary items)
- π¬ Visio-Acoustic Quiz (2 questions)
- βοΈ Writing Challenges (2 prompts)
- π§ Mental Agility (2 timed challenges)
- π Closing Exam (3 assessment questions)
# Production build
npm run build
# Start production server
npm start
# TypeScript check
npm run type-check
# Lint code
npm run lintnpm run dev # Start dev server with Turbopack
npm run build # Build for production
npm run start # Run production server
npm run prisma:studio # Open Prisma Studio (visual DB browser)
npm run prisma:migrate # Create/apply migrations
npm run prisma:generate # Regenerate Prisma types
npm run db:seed # Seed database with example data
npm run db:reset # Reset database and seed with examples
npm run type-check # Run TypeScript compiler
npm run lint # Run ESLintComplete CRUD management with 5 organized tabs:
- Create new courses with slug and title
- View all courses
- Edit course metadata
- Delete courses (cascades to topics/lessons)
- Create topics within courses
- Associate lessons by topic
- Edit/delete topics
- Filter topics by course
- Create lessons with 4 content types
- Select lesson type (video, flashcards, drag-drop, reading)
- Manage lesson metadata
- Real-time lesson list display
- Create reusable tags/keywords
- Tag lessons for organization
- Manage tag categories
- Full CRUD operations
- Add/edit video content (with duration tracking)
- Create flashcard decks
- Build drag-drop exercises
- Manage reading materials with glossary
- Create mental agility challenges with timers
- Build closing exam assessments
- Mental agility challenges management
- Closing exam questions management
- Writing challenges administration
All endpoints follow REST conventions with comprehensive error handling and validation.
| Endpoint | Method | Purpose |
|---|---|---|
/api/admin/courses |
GET | List all courses |
/api/admin/courses |
POST | Create new course |
/api/admin/courses |
PUT | Update course |
/api/admin/courses?slug=X |
DELETE | Delete course |
/api/admin/topics |
GET|POST|PUT|DELETE | Topic CRUD |
/api/admin/lessons |
GET|POST|PUT|DELETE | Lesson CRUD |
/api/admin/tags |
GET|POST|PUT|DELETE | Tag CRUD |
/api/admin/video-contents |
GET|POST|PUT|DELETE | Video CRUD |
/api/admin/reading-contents |
GET|POST|PUT|DELETE | Reading CRUD |
/api/admin/flashcard-contents |
GET|POST|PUT|DELETE | Flashcard CRUD |
/api/admin/drag-drop-contents |
GET|POST|PUT|DELETE | Exercise CRUD |
/api/admin/glossary-items |
GET|POST|PUT|DELETE | Glossary CRUD |
/api/admin/visio-acoustic-contents |
GET|POST|PUT|DELETE | Audio-visual quiz CRUD |
/api/admin/writing-challenges |
GET|POST|PUT|DELETE | Writing challenge CRUD |
/api/admin/mental-agility |
GET|POST|PUT|DELETE | Mental agility challenge CRUD |
/api/admin/closing-exam |
GET|POST|PUT|DELETE | Closing exam question CRUD |
# Fetch lesson by UUID (for sharing)
GET /api/lessons/{uuid}
# Get all lessons with metadata
GET /api/debug/lessonsSuccess (200/201):
{
"id": 1,
"slug": "greeting",
"title": "Hello Lesson",
"type": "video"
}Error (400/404/500):
{
"error": "slug and title are required"
}Page Structure:
layout.tsx (Root)
βββ page.tsx (Landing Page)
β βββ Hero section
β βββ Features showcase
β βββ Skills display
β βββ Levels tiers
β βββ Call-to-action
βββ admin/page.tsx (Admin Panel)
β βββ 5-tab navigation
β βββ Course management
β βββ Topic organization
β βββ Lesson creation
β βββ Tag management
β βββ Content CRUD
βββ module/[course]/
βββ page.tsx (Course catalog)
βββ dashboard/page.tsx (Student dashboard with progress)
βββ [lesson]/page.tsx (Content player)
βββ VideoDiv component
βββ FlashcardsDiv component
βββ DragDropDiv component
βββ ReadingDiv component
API Request
β
Next.js API Route (/api/*)
β
Input Validation & Type Checking
β
Prisma ORM Query Builder
β
PostgreSQL Database
β
Response Formatting & JSON
β
Client Application
- Landing Page - Static marketing content
- Course Listing - Server action fetches courses from database
- Dashboard - Real-time progress tracking with Prisma queries
- Lesson Player - Dynamic content rendering based on lesson type
- Admin Panel - CRUD operations through typed API routes
- Database - PostgreSQL with connection pooling
- Singleton Pattern: Prisma client initialized once per app
- Type Safety: Full TypeScript with strict mode
- Error Handling: Consistent error logging with timestamps
- Validation: Input validation on all API routes
- Performance: Server-side rendering where applicable
- Caching: Optimized Prisma queries with intelligent includes
Light Mode:
- Background: White/Blue-50
- Text: Gray-900
- Primary: Blue-600/Cyan-500
- Borders: Blue-200/Gray-200
Dark Mode (via dark: classes):
- Background: Slate-950/Slate-900
- Text: White
- Primary: Blue-400/Cyan-300
- Borders: Blue-950/Slate-800
- Responsive: Mobile-first design
- Accessible: WCAG 2.1 AA compliant
- Interactive: Smooth transitions and hover effects
- Modern: Glassmorphism and gradient effects
- Consistent: Design system across all pages
- Gamified: Progress bars, color coding, motivational elements
- Adapter: @prisma/adapter-pg for connection pooling
- Pooling: Managed connection reuse
- Migrations: Versioned schema changes with rollback support
- Includes: Strategic use of Prisma
includefor nested data - Filtering: Client-side filtering where appropriate
- Ordering: Consistent sorting for pagination
- Caching: Leverage browser/server cache headers
- Environment variables for sensitive data
- PostgreSQL with secure connection strings
- API route validation and sanitization
- TypeScript for type safety
- Error message obfuscation in production
- Implement authentication middleware
- Add rate limiting to API routes
- Use CORS properly for cross-origin requests
- Enable HTTPS/TLS encryption
- Implement API key or JWT authentication
- Regular security audits