Initial Commit
This commit is contained in:
391
CLAUDE.md
Normal file
391
CLAUDE.md
Normal file
@@ -0,0 +1,391 @@
|
|||||||
|
# Instructions for Claude Code
|
||||||
|
|
||||||
|
## Critical: Specification Adherence
|
||||||
|
|
||||||
|
**YOU MUST READ AND FOLLOW THE SPECIFICATION DOCUMENT FIRST.**
|
||||||
|
|
||||||
|
Before implementing ANY feature, you MUST:
|
||||||
|
1. Read the relevant section in `HANZI-LEARNING-APP-SPECIFICATION.md`
|
||||||
|
2. Follow the specification EXACTLY as written
|
||||||
|
3. Do NOT make up alternatives or "improvements" without explicit approval
|
||||||
|
4. Do NOT skip steps or combine milestones without explicit approval
|
||||||
|
5. Do NOT change the technology stack
|
||||||
|
6. Do NOT modify the data models without approval
|
||||||
|
|
||||||
|
**The specification is the single source of truth. Deviations require explicit user approval.**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
This is **MemoHanzi** (记汉字 - "Remember Hanzi"), a self-hosted Hanzi (Chinese character) learning application using spaced repetition (SM-2 algorithm).
|
||||||
|
|
||||||
|
**Tech Stack (DO NOT CHANGE):**
|
||||||
|
- Next.js 16 with TypeScript and App Router
|
||||||
|
- PostgreSQL 18 with Prisma ORM
|
||||||
|
- NextAuth.js v5 for authentication
|
||||||
|
- Tailwind CSS for styling
|
||||||
|
- Docker Compose for deployment with Nginx reverse proxy
|
||||||
|
- Vitest for unit/integration tests
|
||||||
|
- Playwright for E2E tests
|
||||||
|
|
||||||
|
**Key Files to Reference:**
|
||||||
|
- `/HANZI-LEARNING-APP-SPECIFICATION.md` - Complete specification (READ THIS FIRST)
|
||||||
|
- Note: Project name is **MemoHanzi**, use `memohanzi` for directory/database names
|
||||||
|
- `/prisma/schema.prisma` - Database schema (once created)
|
||||||
|
- `/src/actions/*` - Server Actions
|
||||||
|
- `/src/lib/learning/sm2.ts` - SM-2 algorithm (critical implementation)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Implementation Rules
|
||||||
|
|
||||||
|
### Rule 1: Follow the Milestones Sequentially
|
||||||
|
|
||||||
|
The specification defines 12 milestones (weeks). You MUST:
|
||||||
|
- Complete milestones in order (1 → 2 → 3 → ...)
|
||||||
|
- Finish all tasks in a milestone before moving to the next
|
||||||
|
- Ask for approval before starting each new milestone
|
||||||
|
- Report completion status for each milestone
|
||||||
|
|
||||||
|
**Current Milestone:** 1
|
||||||
|
|
||||||
|
### Rule 2: Database Schema is Fixed
|
||||||
|
|
||||||
|
The Prisma schema in the specification is FINAL. You MUST:
|
||||||
|
- Implement the schema EXACTLY as specified
|
||||||
|
- Include ALL models: Language, Hanzi, HanziForm, HanziTranscription, HanziMeaning, HanziHSKLevel, HanziPOS, HanziClassifier, User, UserPreference, Account, Session, VerificationToken, Collection, CollectionItem, UserHanziProgress, LearningSession, SessionReview
|
||||||
|
- Include ALL enums: UserRole, CharacterDisplay, Difficulty
|
||||||
|
- Include ALL fields and relations as specified
|
||||||
|
- Do NOT add extra fields without approval
|
||||||
|
- Do NOT simplify or "optimize" the schema
|
||||||
|
|
||||||
|
### Rule 3: SM-2 Algorithm Must Be Exact
|
||||||
|
|
||||||
|
The SM-2 algorithm implementation is critical. You MUST:
|
||||||
|
- Use the EXACT formulas from Section 5 of the specification
|
||||||
|
- Initial values: easeFactor=2.5, interval=1, consecutiveCorrect=0
|
||||||
|
- Implement correct answer logic EXACTLY as specified
|
||||||
|
- Implement incorrect answer logic EXACTLY as specified
|
||||||
|
- Implement card selection algorithm EXACTLY as specified
|
||||||
|
- Write comprehensive unit tests (90%+ coverage)
|
||||||
|
|
||||||
|
**Do NOT:**
|
||||||
|
- Use a different spaced repetition algorithm
|
||||||
|
- "Improve" or "simplify" the algorithm
|
||||||
|
- Skip any calculation steps
|
||||||
|
|
||||||
|
### Rule 4: Server Actions Only (No REST API)
|
||||||
|
|
||||||
|
All data operations use Next.js Server Actions. You MUST:
|
||||||
|
- Implement Server Actions as specified in Section 4
|
||||||
|
- Return the standard `ActionResult<T>` type
|
||||||
|
- Validate with Zod schemas
|
||||||
|
- Check authentication/authorization
|
||||||
|
- Use `revalidatePath()` after mutations
|
||||||
|
- Do NOT create REST API endpoints (except for NextAuth)
|
||||||
|
|
||||||
|
### Rule 5: Follow the UI/UX Specification
|
||||||
|
|
||||||
|
Page structure is defined in Section 6. You MUST:
|
||||||
|
- Create pages at the EXACT routes specified
|
||||||
|
- Implement the specified components
|
||||||
|
- Use the specified layouts (mobile-first, responsive)
|
||||||
|
- Include ALL specified features per page
|
||||||
|
- Do NOT create pages not in the specification
|
||||||
|
|
||||||
|
### Rule 6: Testing is Mandatory
|
||||||
|
|
||||||
|
For each feature you implement:
|
||||||
|
- Write unit tests for business logic (70% coverage minimum)
|
||||||
|
- Write integration tests for Server Actions
|
||||||
|
- Write E2E tests for critical user flows
|
||||||
|
- All tests must pass before moving to next milestone
|
||||||
|
|
||||||
|
### Rule 7: Security Requirements are Non-Negotiable
|
||||||
|
|
||||||
|
You MUST implement ALL security measures:
|
||||||
|
- Password hashing with bcrypt (10 rounds) and salt
|
||||||
|
- NextAuth.js session management
|
||||||
|
- Middleware for route protection
|
||||||
|
- Role-based access control in Server Actions
|
||||||
|
- Input validation with Zod (client AND server)
|
||||||
|
- No sensitive data in logs or error messages
|
||||||
|
- Follow the security checklist in Section 11
|
||||||
|
|
||||||
|
### Rule 8: Docker Configuration is Fixed
|
||||||
|
|
||||||
|
Use the EXACT Docker setup from Section 10:
|
||||||
|
- Three containers: nginx, app, postgres
|
||||||
|
- PostgreSQL 18 (not other versions)
|
||||||
|
- Nginx for reverse proxy with rate limiting
|
||||||
|
- Do NOT change the docker-compose.yml structure without approval
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## When You're Unsure
|
||||||
|
|
||||||
|
If you encounter ANY of these situations:
|
||||||
|
|
||||||
|
❌ The specification is unclear
|
||||||
|
❌ You think there's a better approach
|
||||||
|
❌ You want to add a feature not in the spec
|
||||||
|
❌ You want to change the tech stack
|
||||||
|
❌ You want to simplify something
|
||||||
|
❌ You're not sure how to implement something
|
||||||
|
|
||||||
|
**STOP and ASK THE USER first. Do NOT proceed with assumptions.**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Milestone Checklist Template
|
||||||
|
|
||||||
|
Before claiming a milestone is complete, verify:
|
||||||
|
|
||||||
|
**Milestone [N]: [Name]**
|
||||||
|
- [ ] All tasks from specification completed
|
||||||
|
- [ ] Code follows specification exactly
|
||||||
|
- [ ] No deviations from specified approach
|
||||||
|
- [ ] Tests written and passing
|
||||||
|
- [ ] Codebase builds with docker compose
|
||||||
|
- [ ] Security requirements met
|
||||||
|
- [ ] Documentation updated
|
||||||
|
- [ ] User approval obtained
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Common Mistakes to Avoid
|
||||||
|
|
||||||
|
### ❌ DON'T DO THIS:
|
||||||
|
|
||||||
|
1. **"I'll use a simpler data model"** → NO. Use the exact schema specified.
|
||||||
|
2. **"I'll implement REST API instead of Server Actions"** → NO. Server Actions only.
|
||||||
|
3. **"I'll use a different algorithm"** → NO. SM-2 as specified.
|
||||||
|
4. **"I'll skip tests for now"** → NO. Tests are mandatory.
|
||||||
|
5. **"I'll use Next.js 15 instead"** → NO. Next.js 16 as specified.
|
||||||
|
6. **"I'll combine these two milestones"** → NO. Follow the sequence.
|
||||||
|
7. **"I'll add this nice feature"** → NO. Only spec features in MVP.
|
||||||
|
|
||||||
|
### ✅ DO THIS:
|
||||||
|
|
||||||
|
1. Read the specification section before implementing
|
||||||
|
2. Ask for clarification if unclear
|
||||||
|
3. Implement exactly as specified
|
||||||
|
4. Write tests as you go
|
||||||
|
5. Report progress and completion
|
||||||
|
6. Ask before deviating
|
||||||
|
7. Don't be overly friendly
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Startup Checklist
|
||||||
|
|
||||||
|
When starting implementation:
|
||||||
|
|
||||||
|
1. [ ] Read the complete specification document
|
||||||
|
2. [ ] Confirm understanding of the tech stack
|
||||||
|
3. [ ] Confirm understanding of the milestone approach
|
||||||
|
4. [ ] Ask user which milestone to start with
|
||||||
|
5. [ ] Review that milestone's tasks in detail
|
||||||
|
6. [ ] Begin implementation following the specification
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Data Import Reference
|
||||||
|
|
||||||
|
When implementing import (Milestone 3), remember:
|
||||||
|
|
||||||
|
**HSK JSON Source:** https://github.com/drkameleon/complete-hsk-vocabulary/
|
||||||
|
|
||||||
|
**Required Fields:**
|
||||||
|
- simplified (required)
|
||||||
|
- forms[].traditional (required)
|
||||||
|
- forms[].transcriptions.pinyin (required)
|
||||||
|
- forms[].meanings[] (required, at least one)
|
||||||
|
|
||||||
|
**Optional Fields:**
|
||||||
|
- radical, level[], frequency, pos[], classifiers[]
|
||||||
|
- Additional transcriptions (numeric, wadegiles, etc.)
|
||||||
|
|
||||||
|
**CSV Format:**
|
||||||
|
```
|
||||||
|
simplified,traditional,pinyin,meaning,hsk_level,radical,frequency,pos,classifiers
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## SM-2 Algorithm Quick Reference
|
||||||
|
|
||||||
|
**CRITICAL: Use these EXACT formulas**
|
||||||
|
|
||||||
|
### On Correct Answer:
|
||||||
|
```javascript
|
||||||
|
if (consecutiveCorrect === 0) {
|
||||||
|
interval = 1
|
||||||
|
} else if (consecutiveCorrect === 1) {
|
||||||
|
interval = 6
|
||||||
|
} else {
|
||||||
|
interval = Math.round(interval * easeFactor)
|
||||||
|
}
|
||||||
|
easeFactor = easeFactor + 0.1
|
||||||
|
consecutiveCorrect++
|
||||||
|
nextReviewDate = now + interval days
|
||||||
|
```
|
||||||
|
|
||||||
|
### On Incorrect Answer:
|
||||||
|
```javascript
|
||||||
|
interval = 1
|
||||||
|
consecutiveCorrect = 0
|
||||||
|
nextReviewDate = now + 1 day
|
||||||
|
easeFactor = Math.max(1.3, easeFactor - 0.2)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Test this thoroughly with unit tests!**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Progress Reporting Format
|
||||||
|
|
||||||
|
When reporting progress, use this format:
|
||||||
|
|
||||||
|
```
|
||||||
|
## Milestone [N] Progress
|
||||||
|
|
||||||
|
**Status:** [In Progress / Completed / Blocked]
|
||||||
|
|
||||||
|
**Completed Tasks:**
|
||||||
|
- [x] Task 1
|
||||||
|
- [x] Task 2
|
||||||
|
|
||||||
|
**In Progress:**
|
||||||
|
- [ ] Task 3 (50% done)
|
||||||
|
|
||||||
|
**Remaining:**
|
||||||
|
- [ ] Task 4
|
||||||
|
- [ ] Task 5
|
||||||
|
|
||||||
|
**Questions/Issues:**
|
||||||
|
- [List any blockers or questions]
|
||||||
|
|
||||||
|
**Deviations from Spec:**
|
||||||
|
- [List any deviations - should be NONE without approval]
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## File Naming Conventions
|
||||||
|
|
||||||
|
Follow these conventions:
|
||||||
|
- Server Actions: `src/actions/[domain].ts` (e.g., `auth.ts`, `learning.ts`)
|
||||||
|
- Components: `src/components/[category]/[ComponentName].tsx`
|
||||||
|
- Tests: Co-located with source as `[filename].test.ts`
|
||||||
|
- E2E tests: `e2e/[feature].spec.ts`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Prisma Workflow
|
||||||
|
|
||||||
|
When working with the database:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create migration
|
||||||
|
npx prisma migrate dev --name descriptive_name
|
||||||
|
|
||||||
|
# Generate Prisma Client (after schema changes)
|
||||||
|
npx prisma generate
|
||||||
|
|
||||||
|
# Seed database
|
||||||
|
npx prisma db seed
|
||||||
|
|
||||||
|
# View data
|
||||||
|
npx prisma studio
|
||||||
|
```
|
||||||
|
|
||||||
|
**IMPORTANT:** Never edit migration files manually after they're created.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Testing Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Unit tests
|
||||||
|
npm run test:unit
|
||||||
|
|
||||||
|
# Integration tests
|
||||||
|
npm run test:integration
|
||||||
|
|
||||||
|
# E2E tests
|
||||||
|
npm run test:e2e
|
||||||
|
|
||||||
|
# All tests
|
||||||
|
npm run test:ci
|
||||||
|
|
||||||
|
# Watch mode (during development)
|
||||||
|
npm run test:watch
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Communication Guidelines
|
||||||
|
|
||||||
|
## Avoid Sycophantic Language
|
||||||
|
- **NEVER** use phrases like "You're absolutely right!", "You're absolutely correct!", "Excellent point!", or similar flattery
|
||||||
|
- **NEVER** validate statements as "right" when the user didn't make a factual claim that could be evaluated
|
||||||
|
- **NEVER** use general praise or validation as conversational filler
|
||||||
|
- **NEVER** state that the code works now or a fix has been successfully implemented without building and verifying it first
|
||||||
|
|
||||||
|
## Appropriate Acknowledgments
|
||||||
|
Use brief, factual acknowledgments only to confirm understanding of instructions:
|
||||||
|
- "Got it."
|
||||||
|
- "Ok, that makes sense."
|
||||||
|
- "I understand."
|
||||||
|
- "I see the issue."
|
||||||
|
|
||||||
|
These should only be used when:
|
||||||
|
1. You genuinely understand the instruction and its reasoning
|
||||||
|
2. The acknowledgment adds clarity about what you'll do next
|
||||||
|
3. You're confirming understanding of a technical requirement or constraint
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### ❌ Inappropriate (Sycophantic)
|
||||||
|
User: "Yes please."
|
||||||
|
Assistant: "You're absolutely right! That's a great decision."
|
||||||
|
|
||||||
|
User: "Let's remove this unused code."
|
||||||
|
Assistant: "Excellent point! You're absolutely correct that we should clean this up."
|
||||||
|
|
||||||
|
### ✅ Appropriate (Brief Acknowledgment)
|
||||||
|
User: "Yes please."
|
||||||
|
Assistant: "Got it." [proceeds with the requested action]
|
||||||
|
|
||||||
|
User: "Let's remove this unused code."
|
||||||
|
Assistant: "I'll remove the unused code path." [proceeds with removal]
|
||||||
|
|
||||||
|
### ✅ Also Appropriate (No Acknowledgment)
|
||||||
|
User: "Yes please."
|
||||||
|
Assistant: [proceeds directly with the requested action]
|
||||||
|
|
||||||
|
## Rationale
|
||||||
|
- Maintains professional, technical communication
|
||||||
|
- Avoids artificial validation of non-factual statements
|
||||||
|
- Focuses on understanding and execution rather than praise
|
||||||
|
- Prevents misrepresenting user statements as claims that could be "right" or "wrong"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Final Reminder
|
||||||
|
|
||||||
|
**The specification document is LAW.**
|
||||||
|
|
||||||
|
If something in this CLAUDE.md file conflicts with the specification, the specification wins.
|
||||||
|
|
||||||
|
When in doubt:
|
||||||
|
1. Check the specification
|
||||||
|
2. If still unclear, ASK THE USER
|
||||||
|
3. Do NOT make assumptions
|
||||||
|
4. Do NOT deviate without approval
|
||||||
|
|
||||||
|
Your goal is to implement the specification accurately, not to improve it or take shortcuts.
|
||||||
|
|
||||||
|
**Good luck, and stick to the spec!** 🎯
|
||||||
594
HANZI-LEARNING-APP-SPECIFICATION.md
Normal file
594
HANZI-LEARNING-APP-SPECIFICATION.md
Normal file
@@ -0,0 +1,594 @@
|
|||||||
|
# MemoHanzi - Implementation Specification
|
||||||
|
|
||||||
|
**Version:** 1.0
|
||||||
|
**Status:** Ready for Implementation
|
||||||
|
**Target:** Claude Code
|
||||||
|
**Application Name:** MemoHanzi (记汉字 - "Remember Hanzi")
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Quick Start Summary
|
||||||
|
|
||||||
|
**What:** MemoHanzi is a self-hosted web app for learning Chinese characters (hanzi) using spaced repetition (SM-2 algorithm)
|
||||||
|
|
||||||
|
**Tech Stack:**
|
||||||
|
- Next.js 16 (TypeScript, App Router, Server Actions)
|
||||||
|
- PostgreSQL 18 + Prisma ORM
|
||||||
|
- NextAuth.js v5 for authentication
|
||||||
|
- Docker Compose deployment with Nginx reverse proxy
|
||||||
|
- Tailwind CSS, React Hook Form, Zod validation, Recharts
|
||||||
|
|
||||||
|
**MVP Timeline:** 10-12 weeks
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. Core Features (MVP)
|
||||||
|
|
||||||
|
### User Features
|
||||||
|
- ✅ Registration/Login with email & password
|
||||||
|
- ✅ Create and manage personal hanzi collections
|
||||||
|
- ✅ Browse and use global HSK-level collections
|
||||||
|
- ✅ Learning sessions with 4-choice pinyin quiz
|
||||||
|
- ✅ SM-2 spaced repetition algorithm
|
||||||
|
- ✅ Progress tracking & statistics dashboard
|
||||||
|
- ✅ Search hanzi database (by character, pinyin, meaning)
|
||||||
|
- ✅ User preferences (language, display options, learning settings)
|
||||||
|
|
||||||
|
### Admin Features
|
||||||
|
- ✅ Import hanzi data (JSON/CSV from HSK vocabulary source)
|
||||||
|
- ✅ Manage global collections
|
||||||
|
- ✅ User management (roles, activation)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. System Architecture
|
||||||
|
|
||||||
|
### Deployment Stack
|
||||||
|
```
|
||||||
|
[Nginx Reverse Proxy:80/443]
|
||||||
|
↓ HTTPS/Rate Limiting/Caching
|
||||||
|
[Next.js App:3000]
|
||||||
|
↓ Prisma ORM
|
||||||
|
[PostgreSQL:5432]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Project Structure
|
||||||
|
```
|
||||||
|
memohanzi/
|
||||||
|
├── src/
|
||||||
|
│ ├── app/ # Next.js App Router
|
||||||
|
│ │ ├── (auth)/ # Login, register
|
||||||
|
│ │ ├── (app)/ # Dashboard, learn, collections, hanzi, progress, settings
|
||||||
|
│ │ └── (admin)/ # Admin pages
|
||||||
|
│ ├── actions/ # Server Actions (auth, collections, hanzi, learning, etc.)
|
||||||
|
│ ├── components/ # React components
|
||||||
|
│ ├── lib/ # Utils (SM-2 algorithm, parsers, validation)
|
||||||
|
│ └── types/ # TypeScript types
|
||||||
|
├── prisma/
|
||||||
|
│ └── schema.prisma # Database schema
|
||||||
|
├── docker/
|
||||||
|
│ ├── Dockerfile
|
||||||
|
│ └── nginx.conf
|
||||||
|
└── docker-compose.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. Database Schema (Prisma)
|
||||||
|
|
||||||
|
### Core Models
|
||||||
|
|
||||||
|
**Language** - Stores supported translation languages
|
||||||
|
- Fields: code (ISO 639-1), name, nativeName, isActive
|
||||||
|
|
||||||
|
**Hanzi** - Base hanzi information
|
||||||
|
- Fields: simplified (unique), radical, frequency
|
||||||
|
- Relations: forms, hskLevels, partsOfSpeech, userProgress, collectionItems
|
||||||
|
|
||||||
|
**HanziForm** - Traditional variants
|
||||||
|
- Fields: hanziId, traditional, isDefault
|
||||||
|
- Relations: transcriptions, meanings, classifiers
|
||||||
|
|
||||||
|
**HanziTranscription** - Multiple transcription types
|
||||||
|
- Fields: formId, type (pinyin/numeric/wadegiles/etc), value
|
||||||
|
|
||||||
|
**HanziMeaning** - Multi-language meanings
|
||||||
|
- Fields: formId, languageId, meaning, orderIndex
|
||||||
|
|
||||||
|
**HanziHSKLevel** - HSK level tags
|
||||||
|
- Fields: hanziId, level (e.g., "new-1", "old-3")
|
||||||
|
|
||||||
|
**HanziPOS** - Parts of speech
|
||||||
|
- Fields: hanziId, pos (n/v/adj/etc)
|
||||||
|
|
||||||
|
**HanziClassifier** - Measure words
|
||||||
|
- Fields: formId, classifier
|
||||||
|
|
||||||
|
### User & Auth Models
|
||||||
|
|
||||||
|
**User**
|
||||||
|
- Fields: email, password (hashed), name, role (USER/ADMIN/MODERATOR), isActive
|
||||||
|
- Relations: collections, hanziProgress, preferences, sessions
|
||||||
|
|
||||||
|
**UserPreference**
|
||||||
|
- Fields: preferredLanguageId, characterDisplay (SIMPLIFIED/TRADITIONAL/BOTH), transcriptionType, cardsPerSession, dailyGoal, removalThreshold, allowManualDifficulty
|
||||||
|
|
||||||
|
**Account, Session, VerificationToken** - NextAuth.js standard models
|
||||||
|
|
||||||
|
### Learning Models
|
||||||
|
|
||||||
|
**Collection**
|
||||||
|
- Fields: name, description, isGlobal, createdBy, isPublic
|
||||||
|
- Relations: items (CollectionItem join table)
|
||||||
|
|
||||||
|
**CollectionItem** - Join table
|
||||||
|
- Fields: collectionId, hanziId, orderIndex
|
||||||
|
|
||||||
|
**UserHanziProgress** - Tracks learning per hanzi
|
||||||
|
- Fields: userId, hanziId, correctCount, incorrectCount, consecutiveCorrect
|
||||||
|
- SM-2 fields: easeFactor (default 2.5), interval (default 1), nextReviewDate
|
||||||
|
- Manual override: manualDifficulty (EASY/MEDIUM/HARD/SUSPENDED)
|
||||||
|
|
||||||
|
**LearningSession** - Track study sessions
|
||||||
|
- Fields: userId, startedAt, endedAt, cardsReviewed, correctAnswers, incorrectAnswers, collectionId
|
||||||
|
- Relations: reviews (SessionReview)
|
||||||
|
|
||||||
|
**SessionReview** - Individual card reviews
|
||||||
|
- Fields: sessionId, hanziId, isCorrect, responseTime
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Server Actions API
|
||||||
|
|
||||||
|
All actions return: `{ success: boolean, data?: T, message?: string, errors?: Record<string, string[]> }`
|
||||||
|
|
||||||
|
### Authentication (`src/actions/auth.ts`)
|
||||||
|
- `register(email, password, name)` - Create account
|
||||||
|
- `login(email, password)` - Authenticate
|
||||||
|
- `logout()` - End session
|
||||||
|
- `updatePassword(current, new)` - Change password
|
||||||
|
- `updateProfile(name, email, image)` - Update user
|
||||||
|
|
||||||
|
### Collections (`src/actions/collections.ts`)
|
||||||
|
- `createCollection(name, description, isPublic)` - New collection
|
||||||
|
- `updateCollection(id, data)` - Modify (owner/admin only)
|
||||||
|
- `deleteCollection(id)` - Remove (owner/admin only)
|
||||||
|
- `getCollection(id)` - Get with hanzi
|
||||||
|
- `getUserCollections()` - List user's collections
|
||||||
|
- `getGlobalCollections()` - List HSK collections
|
||||||
|
- `addHanziToCollection(collectionId, hanziIds[])` - Add hanzi
|
||||||
|
- `removeHanziFromCollection(collectionId, hanziId)` - Remove hanzi
|
||||||
|
|
||||||
|
### Hanzi (`src/actions/hanzi.ts`)
|
||||||
|
- `searchHanzi(query, hskLevel?, limit, offset)` - Search database (public)
|
||||||
|
- `getHanzi(id)` - Get details (public)
|
||||||
|
- `getHanziBySimplified(char)` - Lookup by character (public)
|
||||||
|
|
||||||
|
### Learning (`src/actions/learning.ts`)
|
||||||
|
- `startLearningSession(collectionId?, cardsCount)` - Begin session, returns cards
|
||||||
|
- `submitAnswer(sessionId, hanziId, selected, correct, time)` - Record answer, updates SM-2
|
||||||
|
- `endSession(sessionId)` - Complete, return summary
|
||||||
|
- `getDueCards()` - Get counts (now, today, week)
|
||||||
|
- `updateCardDifficulty(hanziId, difficulty)` - Manual override
|
||||||
|
- `removeFromLearning(hanziId)` - Stop learning card
|
||||||
|
|
||||||
|
### Progress (`src/actions/progress.ts`)
|
||||||
|
- `getUserProgress(dateRange?)` - Overall stats & charts
|
||||||
|
- `getHanziProgress(hanziId)` - Individual hanzi stats
|
||||||
|
- `getLearningSessions(limit?)` - Session history
|
||||||
|
- `getStatistics()` - Dashboard stats
|
||||||
|
- `resetHanziProgress(hanziId)` - Reset card
|
||||||
|
|
||||||
|
### Preferences (`src/actions/preferences.ts`)
|
||||||
|
- `getPreferences()` - Get settings
|
||||||
|
- `updatePreferences(data)` - Update settings
|
||||||
|
- `getAvailableLanguages()` - List languages
|
||||||
|
|
||||||
|
### Admin (`src/actions/admin.ts`)
|
||||||
|
- `createGlobalCollection(name, description, hskLevel)` - HSK collection
|
||||||
|
- `importHanzi(fileData, format)` - Bulk import (JSON/CSV)
|
||||||
|
- `getImportHistory()` - Past imports
|
||||||
|
- `getUserManagement(page, pageSize)` - List users
|
||||||
|
- `updateUserRole(userId, role)` - Change role
|
||||||
|
- `toggleUserStatus(userId)` - Activate/deactivate
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. SM-2 Algorithm Implementation
|
||||||
|
|
||||||
|
### Initial Values
|
||||||
|
- easeFactor: 2.5
|
||||||
|
- interval: 1 day
|
||||||
|
- consecutiveCorrect: 0
|
||||||
|
|
||||||
|
### On Correct Answer
|
||||||
|
```javascript
|
||||||
|
if (consecutiveCorrect === 0) {
|
||||||
|
interval = 1
|
||||||
|
} else if (consecutiveCorrect === 1) {
|
||||||
|
interval = 6
|
||||||
|
} else {
|
||||||
|
interval = Math.round(interval * easeFactor)
|
||||||
|
}
|
||||||
|
|
||||||
|
easeFactor = easeFactor + 0.1 // Can adjust based on quality
|
||||||
|
consecutiveCorrect++
|
||||||
|
nextReviewDate = now + interval days
|
||||||
|
```
|
||||||
|
|
||||||
|
### On Incorrect Answer
|
||||||
|
```javascript
|
||||||
|
interval = 1
|
||||||
|
consecutiveCorrect = 0
|
||||||
|
nextReviewDate = now + 1 day
|
||||||
|
easeFactor = Math.max(1.3, easeFactor - 0.2)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Card Selection
|
||||||
|
1. Query: `WHERE nextReviewDate <= now AND userId = currentUser`
|
||||||
|
2. Apply manual difficulty (SUSPENDED = exclude, HARD = priority, EASY = depriority)
|
||||||
|
3. Sort: nextReviewDate ASC, incorrectCount DESC, consecutiveCorrect ASC
|
||||||
|
4. Limit to user's cardsPerSession
|
||||||
|
5. If not enough, add new cards from collections
|
||||||
|
|
||||||
|
### Wrong Answer Generation
|
||||||
|
- Select 3 random incorrect pinyin from same HSK level
|
||||||
|
- Ensure no duplicates
|
||||||
|
- Randomize order (Fisher-Yates shuffle)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. UI/UX Pages
|
||||||
|
|
||||||
|
### Public
|
||||||
|
- `/` - Landing page
|
||||||
|
- `/login` - Login form
|
||||||
|
- `/register` - Registration form
|
||||||
|
|
||||||
|
### Authenticated
|
||||||
|
- `/dashboard` - Due cards, progress widgets, recent activity, quick start
|
||||||
|
- `/learn/[collectionId]` - Learning session with cards
|
||||||
|
- `/collections` - List all collections (global + user's)
|
||||||
|
- `/collections/[id]` - Collection detail, hanzi list, edit
|
||||||
|
- `/collections/new` - Create collection
|
||||||
|
- `/hanzi` - Search hanzi (filters, pagination)
|
||||||
|
- `/hanzi/[id]` - Hanzi detail (all transcriptions, meanings, etc)
|
||||||
|
- `/progress` - Charts, stats, session history
|
||||||
|
- `/settings` - User preferences
|
||||||
|
|
||||||
|
### Admin
|
||||||
|
- `/admin/collections` - Manage global collections
|
||||||
|
- `/admin/hanzi` - Manage hanzi database
|
||||||
|
- `/admin/import` - Import data (JSON/CSV upload)
|
||||||
|
- `/admin/users` - User management
|
||||||
|
|
||||||
|
### Key UI Components
|
||||||
|
- **LearningCard**: Large hanzi, 4 pinyin options in 2x2 grid, progress bar
|
||||||
|
- **AnswerFeedback**: Green/red feedback, show correct answer, streak, removal suggestion
|
||||||
|
- **CollectionCard**: Name, count, progress, quick actions
|
||||||
|
- **DashboardWidgets**: Due cards, daily progress, streak, recent activity
|
||||||
|
- **Charts**: Activity heatmap, accuracy line chart, HSK breakdown bar chart
|
||||||
|
|
||||||
|
### Design
|
||||||
|
- Mobile-first responsive
|
||||||
|
- Dark mode support
|
||||||
|
- Tailwind CSS
|
||||||
|
- Keyboard shortcuts (1-4 for answers, Space to continue)
|
||||||
|
- WCAG 2.1 AA accessibility
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. Data Import Formats
|
||||||
|
|
||||||
|
### HSK JSON (from github.com/drkameleon/complete-hsk-vocabulary)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"simplified": "爱好",
|
||||||
|
"radical": "爫",
|
||||||
|
"level": ["new-1", "old-3"],
|
||||||
|
"frequency": 4902,
|
||||||
|
"pos": ["n", "v"],
|
||||||
|
"forms": [{
|
||||||
|
"traditional": "愛好",
|
||||||
|
"transcriptions": {
|
||||||
|
"pinyin": "ài hào",
|
||||||
|
"numeric": "ai4 hao4"
|
||||||
|
},
|
||||||
|
"meanings": ["to like; hobby"],
|
||||||
|
"classifiers": ["个"]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### CSV Format
|
||||||
|
```csv
|
||||||
|
simplified,traditional,pinyin,meaning,hsk_level,radical,frequency,pos,classifiers
|
||||||
|
爱好,愛好,ài hào,"to like; hobby",new-1,爫,4902,"n,v",个
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. Testing Strategy
|
||||||
|
|
||||||
|
### Unit Tests (70% coverage target)
|
||||||
|
- **SM-2 algorithm** - All calculation paths
|
||||||
|
- **Card selection logic** - Sorting, filtering, limits
|
||||||
|
- **Parsers** - JSON/CSV parsing, error handling
|
||||||
|
- **Validation schemas** - Zod schemas
|
||||||
|
|
||||||
|
### Integration Tests (80% of Server Actions)
|
||||||
|
- Auth actions with database
|
||||||
|
- Learning flow (start session, submit answers, end session)
|
||||||
|
- Collection CRUD
|
||||||
|
- Import process
|
||||||
|
|
||||||
|
### E2E Tests (Critical paths)
|
||||||
|
- Complete learning session
|
||||||
|
- Create collection and add hanzi
|
||||||
|
- Search hanzi
|
||||||
|
- Admin import
|
||||||
|
- Auth flow
|
||||||
|
|
||||||
|
**Tools:** Vitest (unit/integration), Playwright (E2E)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. Development Milestones
|
||||||
|
|
||||||
|
### Week 1: Foundation
|
||||||
|
- Setup Next.js 16 project
|
||||||
|
- Configure Prisma + PostgreSQL
|
||||||
|
- Setup Docker Compose
|
||||||
|
- Create all data models
|
||||||
|
- Configure NextAuth.js
|
||||||
|
|
||||||
|
### Week 2: Authentication
|
||||||
|
- Registration/login pages
|
||||||
|
- Middleware protection
|
||||||
|
- User preferences
|
||||||
|
- Integration tests
|
||||||
|
|
||||||
|
### Week 3-4: Data Import
|
||||||
|
- Admin role middleware
|
||||||
|
- HSK JSON parser
|
||||||
|
- CSV parser
|
||||||
|
- Import UI and actions
|
||||||
|
- Test with real HSK data
|
||||||
|
|
||||||
|
### Week 5: Collections
|
||||||
|
- Collections CRUD
|
||||||
|
- Add/remove hanzi
|
||||||
|
- Global HSK collections
|
||||||
|
|
||||||
|
### Week 5: Hanzi Search
|
||||||
|
- Search page
|
||||||
|
- Filters (HSK level)
|
||||||
|
- Hanzi detail view
|
||||||
|
- Pagination
|
||||||
|
|
||||||
|
### Week 6: SM-2 Algorithm
|
||||||
|
- Implement algorithm
|
||||||
|
- Card selection logic
|
||||||
|
- Progress tracking
|
||||||
|
- Unit tests (90%+ coverage)
|
||||||
|
|
||||||
|
### Week 7-8: Learning Interface
|
||||||
|
- Learning session pages
|
||||||
|
- Card component
|
||||||
|
- Answer submission
|
||||||
|
- Feedback UI
|
||||||
|
- Session summary
|
||||||
|
- Keyboard shortcuts
|
||||||
|
- E2E tests
|
||||||
|
|
||||||
|
### Week 9: Dashboard & Progress
|
||||||
|
- Dashboard widgets
|
||||||
|
- Progress page
|
||||||
|
- Charts (Recharts)
|
||||||
|
- Statistics calculations
|
||||||
|
|
||||||
|
### Week 10: UI Polish
|
||||||
|
- Responsive layouts
|
||||||
|
- Mobile navigation
|
||||||
|
- Dark mode
|
||||||
|
- Loading/empty states
|
||||||
|
- Toast notifications
|
||||||
|
- Accessibility improvements
|
||||||
|
|
||||||
|
### Week 11: Testing & Docs
|
||||||
|
- Complete test coverage
|
||||||
|
- E2E tests for all critical flows
|
||||||
|
- README and documentation
|
||||||
|
- Security audit
|
||||||
|
|
||||||
|
### Week 12: Deployment
|
||||||
|
- Production environment
|
||||||
|
- Docker deployment
|
||||||
|
- SSL certificates
|
||||||
|
- Database backup
|
||||||
|
- Import HSK data
|
||||||
|
- Final testing
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 10. Docker Configuration
|
||||||
|
|
||||||
|
### docker-compose.yml
|
||||||
|
```yaml
|
||||||
|
version: '3.8'
|
||||||
|
services:
|
||||||
|
nginx:
|
||||||
|
image: nginx:alpine
|
||||||
|
ports: ["80:80", "443:443"]
|
||||||
|
volumes:
|
||||||
|
- ./docker/nginx.conf:/etc/nginx/nginx.conf:ro
|
||||||
|
- ./docker/ssl:/etc/nginx/ssl:ro
|
||||||
|
depends_on: [app]
|
||||||
|
|
||||||
|
app:
|
||||||
|
build: .
|
||||||
|
expose: ["3000"]
|
||||||
|
environment:
|
||||||
|
- DATABASE_URL=postgresql://memohanzi_user:password@postgres:5432/memohanzi_db
|
||||||
|
- NEXTAUTH_URL=https://yourdomain.com
|
||||||
|
- NEXTAUTH_SECRET=${NEXTAUTH_SECRET}
|
||||||
|
depends_on:
|
||||||
|
postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
|
||||||
|
postgres:
|
||||||
|
image: postgres:18-alpine
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: memohanzi_user
|
||||||
|
POSTGRES_PASSWORD: password
|
||||||
|
POSTGRES_DB: memohanzi_db
|
||||||
|
volumes:
|
||||||
|
- postgres-data:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "pg_isready -U hanzi_user"]
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres-data:
|
||||||
|
```
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
```bash
|
||||||
|
# .env.local
|
||||||
|
DATABASE_URL="postgresql://memohanzi_user:password@localhost:5432/memohanzi_db"
|
||||||
|
NEXTAUTH_URL="http://localhost:3000"
|
||||||
|
NEXTAUTH_SECRET="generate-with-openssl-rand-base64-32"
|
||||||
|
NODE_ENV="development"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 11. Security Checklist
|
||||||
|
|
||||||
|
- [ ] Passwords hashed with bcrypt (10 rounds)
|
||||||
|
- [ ] Session tokens httpOnly, sameSite
|
||||||
|
- [ ] CSRF protection (NextAuth.js)
|
||||||
|
- [ ] Rate limiting (Nginx)
|
||||||
|
- [ ] Input validation (Zod, server-side)
|
||||||
|
- [ ] SQL injection prevented (Prisma)
|
||||||
|
- [ ] XSS prevention (React escaping)
|
||||||
|
- [ ] HTTPS enforced (Nginx)
|
||||||
|
- [ ] Secure headers (Nginx)
|
||||||
|
- [ ] Role-based access enforced server-side
|
||||||
|
- [ ] No sensitive data in logs
|
||||||
|
- [ ] Environment variables for secrets
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 12. Phase 2 Features
|
||||||
|
|
||||||
|
1. **Additional Languages** - Multi-language support for meanings
|
||||||
|
2. **Learning Modes** - Radical identification, hanzi-to-meaning, meaning-to-hanzi, tone practice
|
||||||
|
3. **Autocomplete Data** - Auto-fill missing hanzi info from APIs
|
||||||
|
4. **User Suggestions** - Allow users to report/suggest corrections
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 13. Phase 3 Ideas
|
||||||
|
|
||||||
|
- Writing practice (stroke order validation)
|
||||||
|
- Social features (public collections, sharing)
|
||||||
|
- Gamification (streaks, badges, leaderboards)
|
||||||
|
- Mobile apps (React Native)
|
||||||
|
- Audio pronunciation
|
||||||
|
- Example sentences
|
||||||
|
- Advanced SRS algorithms
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 14. Quick Reference Commands
|
||||||
|
|
||||||
|
**Development:**
|
||||||
|
```bash
|
||||||
|
# Start
|
||||||
|
docker-compose up
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# Database
|
||||||
|
npx prisma migrate dev
|
||||||
|
npx prisma db seed
|
||||||
|
npx prisma studio
|
||||||
|
|
||||||
|
# Testing
|
||||||
|
npm run test
|
||||||
|
npm run test:e2e
|
||||||
|
```
|
||||||
|
|
||||||
|
**Production:**
|
||||||
|
```bash
|
||||||
|
# Deploy
|
||||||
|
docker-compose up -d --build
|
||||||
|
|
||||||
|
# Monitor
|
||||||
|
docker-compose logs -f
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 15. Success Criteria (MVP)
|
||||||
|
|
||||||
|
**Technical:**
|
||||||
|
- [ ] All tests passing (70%+ coverage)
|
||||||
|
- [ ] Can import complete HSK vocabulary (5000+ hanzi)
|
||||||
|
- [ ] Page load <2s
|
||||||
|
- [ ] Learning session responsive (<100ms)
|
||||||
|
- [ ] Mobile responsive
|
||||||
|
|
||||||
|
**Functional:**
|
||||||
|
- [ ] Complete learning session works end-to-end
|
||||||
|
- [ ] SM-2 algorithm calculates correctly
|
||||||
|
- [ ] Progress tracking accurate
|
||||||
|
- [ ] Collections management works
|
||||||
|
- [ ] Search works efficiently
|
||||||
|
|
||||||
|
**User Experience:**
|
||||||
|
- [ ] Can learn 20+ cards in 5-10 minutes
|
||||||
|
- [ ] Interface intuitive
|
||||||
|
- [ ] Daily use sustainable
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Implementation Notes
|
||||||
|
|
||||||
|
### Priority Order
|
||||||
|
1. Authentication (foundational)
|
||||||
|
2. Data import (need data)
|
||||||
|
3. Collections (organize learning)
|
||||||
|
4. Search (browse data)
|
||||||
|
5. Learning algorithm (core logic)
|
||||||
|
6. Learning interface (user interaction)
|
||||||
|
7. Progress tracking (motivation)
|
||||||
|
8. Polish & deploy
|
||||||
|
|
||||||
|
### Critical Paths to Test
|
||||||
|
1. Register → Login → Create Collection → Add Hanzi → Start Learning → Complete Session → View Progress
|
||||||
|
2. Admin → Import HSK Data → Create Global Collection → User uses global collection
|
||||||
|
3. Search Hanzi → View Detail → Add to Collection → Learn
|
||||||
|
|
||||||
|
### Key Implementation Files
|
||||||
|
- `prisma/schema.prisma` - All data models
|
||||||
|
- `src/lib/learning/sm2.ts` - SM-2 algorithm
|
||||||
|
- `src/lib/learning/card-selector.ts` - Card selection
|
||||||
|
- `src/lib/import/hsk-parser.ts` - Parse HSK JSON
|
||||||
|
- `src/actions/learning.ts` - Learning Server Actions
|
||||||
|
- `src/app/(app)/learn/[collectionId]/page.tsx` - Learning UI
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
- **HSK Data Source**: https://github.com/drkameleon/complete-hsk-vocabulary
|
||||||
|
- **Next.js Docs**: https://nextjs.org/docs
|
||||||
|
- **Prisma Docs**: https://www.prisma.io/docs
|
||||||
|
- **NextAuth Docs**: https://authjs.dev
|
||||||
|
- **SM-2 Algorithm**: https://www.supermemo.com/en/archives1990-2015/english/ol/sm2
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**This specification is complete and ready for implementation with Claude Code.**
|
||||||
|
|
||||||
|
Start with Milestone 1 (Week 1: Foundation) and proceed sequentially through the milestones.
|
||||||
147
PROJECT-NAMING.md
Normal file
147
PROJECT-NAMING.md
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
# MemoHanzi - Project Naming Conventions
|
||||||
|
|
||||||
|
## Application Name
|
||||||
|
**MemoHanzi** (记汉字)
|
||||||
|
- **Meaning:** "Remember Hanzi" or "Memorize Hanzi"
|
||||||
|
- **Chinese:** 记汉字
|
||||||
|
- **Pronunciation:** Jì Hànzì
|
||||||
|
|
||||||
|
## Usage Guidelines
|
||||||
|
|
||||||
|
### Display Names (User-Facing)
|
||||||
|
- **Full name:** MemoHanzi
|
||||||
|
- **Tagline:** "Remember Hanzi, effortlessly"
|
||||||
|
- **Description:** Spaced repetition for Chinese characters
|
||||||
|
|
||||||
|
### Technical Names (Code/Infrastructure)
|
||||||
|
|
||||||
|
**Project Directory:**
|
||||||
|
```
|
||||||
|
memohanzi/
|
||||||
|
```
|
||||||
|
|
||||||
|
**Database:**
|
||||||
|
- Database name: `memohanzi_db`
|
||||||
|
- Database user: `memohanzi_user`
|
||||||
|
|
||||||
|
**Connection String:**
|
||||||
|
```
|
||||||
|
postgresql://memohanzi_user:password@localhost:5432/memohanzi_db
|
||||||
|
```
|
||||||
|
|
||||||
|
**Docker Container Names:**
|
||||||
|
- nginx: `memohanzi-nginx`
|
||||||
|
- app: `memohanzi-app`
|
||||||
|
- postgres: `memohanzi-postgres`
|
||||||
|
|
||||||
|
**NPM Package Name (if publishing):**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "memohanzi",
|
||||||
|
"description": "Self-hosted spaced repetition app for learning Chinese characters"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Domain Names:**
|
||||||
|
- Primary: memohanzi.com
|
||||||
|
- Alternative: memohanzi.io / memohanzi.app
|
||||||
|
|
||||||
|
**Email Domains (Development):**
|
||||||
|
- Admin: admin@memohanzi.local
|
||||||
|
- Test user: user@memohanzi.local
|
||||||
|
|
||||||
|
### Code/Variable Naming
|
||||||
|
|
||||||
|
**Constants:**
|
||||||
|
```typescript
|
||||||
|
const APP_NAME = "MemoHanzi"
|
||||||
|
const APP_NAME_CN = "记汉字"
|
||||||
|
const APP_TAGLINE = "Remember Hanzi, effortlessly"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Environment Variables:**
|
||||||
|
```bash
|
||||||
|
NEXTAUTH_URL="https://memohanzi.com"
|
||||||
|
DATABASE_URL="postgresql://memohanzi_user:password@localhost:5432/memohanzi_db"
|
||||||
|
```
|
||||||
|
|
||||||
|
**File Names:**
|
||||||
|
- Use lowercase with hyphens: `memohanzi-config.ts`
|
||||||
|
- Or camelCase for TypeScript: `memohanziConfig.ts`
|
||||||
|
|
||||||
|
## Branding (Future Reference)
|
||||||
|
|
||||||
|
### Logo Concepts
|
||||||
|
- Focus on the concept of memory/remembering
|
||||||
|
- Incorporate Chinese character elements
|
||||||
|
- Clean, modern design
|
||||||
|
|
||||||
|
### Color Palette Suggestions
|
||||||
|
- **Primary:** Red (#E63946) - Traditional Chinese color, attention/memory
|
||||||
|
- **Secondary:** Blue (#457B9D) - Trust, learning, calmness
|
||||||
|
- **Accent:** Gold (#FFD60A) - Achievement, success
|
||||||
|
- **Background:** White/Light gray - Clarity, simplicity
|
||||||
|
|
||||||
|
### Typography
|
||||||
|
- **Hanzi Display:** Noto Sans CJK SC (Google Fonts)
|
||||||
|
- **English UI:** Inter or System fonts
|
||||||
|
- **Headings:** Bold, clean sans-serif
|
||||||
|
|
||||||
|
## Consistency Rules
|
||||||
|
|
||||||
|
1. **Always capitalize "MemoHanzi"** in user-facing content
|
||||||
|
2. **Always use lowercase "memohanzi"** in code/technical contexts
|
||||||
|
3. **Use "Hanzi" not "hanzi"** when referring to characters in documentation
|
||||||
|
4. **Include Chinese characters (记汉字)** in about/landing pages
|
||||||
|
5. **Never use "Hanzi Learning App"** as the name (old placeholder)
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### ✅ Correct Usage
|
||||||
|
|
||||||
|
**User-facing:**
|
||||||
|
- "Welcome to MemoHanzi!"
|
||||||
|
- "MemoHanzi helps you remember Hanzi effortlessly"
|
||||||
|
- "Start learning with MemoHanzi (记汉字)"
|
||||||
|
|
||||||
|
**Technical:**
|
||||||
|
```typescript
|
||||||
|
// File: src/lib/memohanziConfig.ts
|
||||||
|
export const config = {
|
||||||
|
appName: "MemoHanzi",
|
||||||
|
dbName: "memohanzi_db"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# docker-compose.yml
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
container_name: memohanzi-app
|
||||||
|
```
|
||||||
|
|
||||||
|
### ❌ Incorrect Usage
|
||||||
|
|
||||||
|
**Don't:**
|
||||||
|
- "Welcome to memohanzi!" (lowercase in UI)
|
||||||
|
- "MemoHanzi_DB" (mixed case in technical)
|
||||||
|
- "Hanzi Learning App" (old name)
|
||||||
|
- "Memo-Hanzi" or "Memo Hanzi" (hyphenated or separated)
|
||||||
|
|
||||||
|
## README/Documentation Template
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
# MemoHanzi (记汉字)
|
||||||
|
|
||||||
|
**Remember Hanzi, effortlessly**
|
||||||
|
|
||||||
|
MemoHanzi is a self-hosted web application for learning Chinese characters (Hanzi)
|
||||||
|
using spaced repetition (SM-2 algorithm).
|
||||||
|
|
||||||
|
## Features
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**This file should be referenced whenever naming anything in the project.**
|
||||||
229
README.md
229
README.md
@@ -1,2 +1,229 @@
|
|||||||
# memohanzi
|
# MemoHanzi - Implementation Package
|
||||||
|
|
||||||
|
Welcome! This package contains everything needed to implement MemoHanzi (记汉字 - "Remember Hanzi"), a self-hosted Chinese character learning application.
|
||||||
|
|
||||||
|
## 📦 What's Included
|
||||||
|
|
||||||
|
### 1. **HANZI-LEARNING-APP-SPECIFICATION.md** (Main Spec)
|
||||||
|
Complete technical specification including:
|
||||||
|
- ✅ System architecture
|
||||||
|
- ✅ Complete database schema (Prisma)
|
||||||
|
- ✅ All Server Actions API
|
||||||
|
- ✅ SM-2 algorithm implementation
|
||||||
|
- ✅ UI/UX specifications
|
||||||
|
- ✅ Testing strategy
|
||||||
|
- ✅ 12-week milestone plan
|
||||||
|
- ✅ Docker configuration
|
||||||
|
- ✅ Phase 2 & 3 roadmaps
|
||||||
|
|
||||||
|
### 2. **CLAUDE.md** (Instructions for Claude Code)
|
||||||
|
Strict implementation guidelines to prevent deviation from spec:
|
||||||
|
- Critical rules for following the specification
|
||||||
|
- Milestone approach
|
||||||
|
- Common mistakes to avoid
|
||||||
|
- Progress reporting format
|
||||||
|
|
||||||
|
### 3. **PROJECT-NAMING.md** (Naming Conventions)
|
||||||
|
All naming conventions for the MemoHanzi project:
|
||||||
|
- Application naming (display vs technical)
|
||||||
|
- Database naming
|
||||||
|
- Code conventions
|
||||||
|
- Branding guidelines
|
||||||
|
|
||||||
|
## 🚀 Quick Start
|
||||||
|
|
||||||
|
### For Claude Code:
|
||||||
|
1. Read `CLAUDE.md` first
|
||||||
|
2. Read `HANZI-LEARNING-APP-SPECIFICATION.md`
|
||||||
|
3. Read `PROJECT-NAMING.md` for naming conventions
|
||||||
|
4. Start with Milestone 1 (Week 1: Foundation)
|
||||||
|
|
||||||
|
### For Human Developers:
|
||||||
|
1. Read `HANZI-LEARNING-APP-SPECIFICATION.md` - this is your blueprint
|
||||||
|
2. Check `PROJECT-NAMING.md` for naming consistency
|
||||||
|
3. Follow the 12-week milestone plan
|
||||||
|
4. Use the testing strategy throughout
|
||||||
|
|
||||||
|
## 📋 Project Overview
|
||||||
|
|
||||||
|
**Name:** MemoHanzi (记汉字)
|
||||||
|
**Tagline:** Remember Hanzi, effortlessly
|
||||||
|
**Type:** Self-hosted web application
|
||||||
|
**Purpose:** Learn Chinese characters using spaced repetition (SM-2 algorithm)
|
||||||
|
|
||||||
|
**Tech Stack:**
|
||||||
|
- Next.js 16 (TypeScript, App Router)
|
||||||
|
- PostgreSQL 18 + Prisma
|
||||||
|
- NextAuth.js v5
|
||||||
|
- Docker Compose + Nginx
|
||||||
|
- Tailwind CSS
|
||||||
|
|
||||||
|
**Timeline:** 10-12 weeks for MVP
|
||||||
|
|
||||||
|
## 🎯 Key Features (MVP)
|
||||||
|
|
||||||
|
**For Users:**
|
||||||
|
- Learn Hanzi with spaced repetition
|
||||||
|
- Multiple choice pinyin quiz (4 options)
|
||||||
|
- Create custom collections or use HSK levels
|
||||||
|
- Track progress with charts and statistics
|
||||||
|
- Search complete Hanzi database
|
||||||
|
|
||||||
|
**For Admins:**
|
||||||
|
- Import HSK vocabulary (JSON/CSV)
|
||||||
|
- Manage global collections
|
||||||
|
- User administration
|
||||||
|
|
||||||
|
## 📁 Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
memohanzi/ # Your project root
|
||||||
|
├── src/
|
||||||
|
│ ├── app/ # Next.js App Router
|
||||||
|
│ ├── actions/ # Server Actions
|
||||||
|
│ ├── components/ # React components
|
||||||
|
│ ├── lib/ # Utils (SM-2, parsers, etc)
|
||||||
|
│ └── types/ # TypeScript types
|
||||||
|
├── prisma/
|
||||||
|
│ └── schema.prisma # Database schema
|
||||||
|
├── docker/
|
||||||
|
│ ├── Dockerfile
|
||||||
|
│ └── nginx.conf
|
||||||
|
├── docker-compose.yml
|
||||||
|
└── README.md
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔑 Critical Implementation Notes
|
||||||
|
|
||||||
|
### 1. Follow the Specification EXACTLY
|
||||||
|
The specification is the single source of truth. Do not deviate without approval.
|
||||||
|
|
||||||
|
### 2. Implement Milestones Sequentially
|
||||||
|
Complete Week 1 → Week 2 → Week 3... in order.
|
||||||
|
|
||||||
|
### 3. SM-2 Algorithm is Critical
|
||||||
|
Use the EXACT formulas provided in Section 5 of the spec.
|
||||||
|
|
||||||
|
### 4. Testing is Mandatory
|
||||||
|
Write tests as you implement. Target: 70%+ coverage.
|
||||||
|
|
||||||
|
### 5. Database Schema is Fixed
|
||||||
|
Implement ALL models exactly as specified in the Prisma schema.
|
||||||
|
|
||||||
|
## 📊 Development Milestones
|
||||||
|
|
||||||
|
| Week | Milestone | Focus |
|
||||||
|
|------|-----------|-------|
|
||||||
|
| 1 | Foundation | Setup project, Docker, Prisma schema |
|
||||||
|
| 2 | Authentication | User registration, login, preferences |
|
||||||
|
| 3-4 | Data Import | Admin imports HSK data (JSON/CSV) |
|
||||||
|
| 5 | Collections | User collections + global HSK collections |
|
||||||
|
| 5 | Hanzi Search | Search interface and detail views |
|
||||||
|
| 6 | SM-2 Algorithm | Core learning algorithm + tests |
|
||||||
|
| 7-8 | Learning UI | Learning session interface |
|
||||||
|
| 9 | Dashboard | Progress tracking and visualizations |
|
||||||
|
| 10 | UI Polish | Responsive design, dark mode |
|
||||||
|
| 11 | Testing & Docs | Complete test coverage |
|
||||||
|
| 12 | Deployment | Production deployment + data import |
|
||||||
|
|
||||||
|
## 🎨 Naming Conventions
|
||||||
|
|
||||||
|
**User-Facing:**
|
||||||
|
- Always: "MemoHanzi" (capitalized)
|
||||||
|
- Tagline: "Remember Hanzi, effortlessly"
|
||||||
|
- Include Chinese: 记汉字
|
||||||
|
|
||||||
|
**Technical:**
|
||||||
|
- Directory: `memohanzi/`
|
||||||
|
- Database: `memohanzi_db`
|
||||||
|
- User: `memohanzi_user`
|
||||||
|
- Container: `memohanzi-app`, `memohanzi-postgres`
|
||||||
|
|
||||||
|
See `PROJECT-NAMING.md` for complete guidelines.
|
||||||
|
|
||||||
|
## 📚 Data Source
|
||||||
|
|
||||||
|
HSK Vocabulary: https://github.com/drkameleon/complete-hsk-vocabulary/
|
||||||
|
|
||||||
|
This repository contains comprehensive HSK (Chinese proficiency test) vocabulary data that will be imported into MemoHanzi.
|
||||||
|
|
||||||
|
## 🔐 Security Highlights
|
||||||
|
|
||||||
|
- ✅ Passwords hashed with bcrypt
|
||||||
|
- ✅ NextAuth.js session management
|
||||||
|
- ✅ HTTPS via Nginx
|
||||||
|
- ✅ Rate limiting
|
||||||
|
- ✅ Input validation (Zod)
|
||||||
|
- ✅ SQL injection prevention (Prisma)
|
||||||
|
|
||||||
|
## 🧪 Testing Strategy
|
||||||
|
|
||||||
|
- **Unit Tests (70%):** Business logic, SM-2 algorithm, parsers
|
||||||
|
- **Integration Tests (20%):** Server Actions, database operations
|
||||||
|
- **E2E Tests (10%):** Critical user flows
|
||||||
|
|
||||||
|
**Tools:** Vitest (unit/integration), Playwright (E2E)
|
||||||
|
|
||||||
|
## 📖 Additional Resources
|
||||||
|
|
||||||
|
- **Next.js Docs:** https://nextjs.org/docs
|
||||||
|
- **Prisma Docs:** https://www.prisma.io/docs
|
||||||
|
- **NextAuth Docs:** https://authjs.dev
|
||||||
|
- **SM-2 Algorithm:** https://www.supermemo.com/en/archives1990-2015/english/ol/sm2
|
||||||
|
|
||||||
|
## 🎯 Success Criteria (MVP)
|
||||||
|
|
||||||
|
**Technical:**
|
||||||
|
- [ ] All tests passing (70%+ coverage)
|
||||||
|
- [ ] Can import complete HSK vocabulary
|
||||||
|
- [ ] Page load <2s
|
||||||
|
- [ ] Mobile responsive
|
||||||
|
|
||||||
|
**Functional:**
|
||||||
|
- [ ] Complete learning session works end-to-end
|
||||||
|
- [ ] SM-2 algorithm accurate
|
||||||
|
- [ ] Progress tracking working
|
||||||
|
- [ ] Collections management functional
|
||||||
|
- [ ] Search efficient
|
||||||
|
|
||||||
|
**User Experience:**
|
||||||
|
- [ ] Can learn 20+ cards in 5-10 minutes
|
||||||
|
- [ ] Interface intuitive
|
||||||
|
- [ ] Daily use sustainable
|
||||||
|
|
||||||
|
## 🚦 Getting Started Checklist
|
||||||
|
|
||||||
|
Before beginning implementation:
|
||||||
|
|
||||||
|
- [ ] Read complete specification document
|
||||||
|
- [ ] Understand the tech stack
|
||||||
|
- [ ] Review the milestone approach
|
||||||
|
- [ ] Check naming conventions
|
||||||
|
- [ ] Set up development environment
|
||||||
|
- [ ] Confirm understanding of SM-2 algorithm
|
||||||
|
|
||||||
|
## 💡 Important Reminders
|
||||||
|
|
||||||
|
1. **Read the spec before implementing anything**
|
||||||
|
2. **Ask questions if anything is unclear**
|
||||||
|
3. **Don't make up alternatives or "improvements"**
|
||||||
|
4. **Write tests as you go**
|
||||||
|
5. **Follow the milestone sequence**
|
||||||
|
6. **Use consistent naming (check PROJECT-NAMING.md)**
|
||||||
|
|
||||||
|
## 📞 Next Steps
|
||||||
|
|
||||||
|
**For Claude Code:**
|
||||||
|
Start by saying: "I've read CLAUDE.md and HANZI-LEARNING-APP-SPECIFICATION.md. Ready to begin Milestone 1: Project Foundation."
|
||||||
|
|
||||||
|
**For Human Developers:**
|
||||||
|
1. Set up your development environment
|
||||||
|
2. Create project directory: `memohanzi/`
|
||||||
|
3. Begin Milestone 1 tasks
|
||||||
|
4. Reference the specification frequently
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Good luck building MemoHanzi! 🎯**
|
||||||
|
|
||||||
|
记汉字 - Remember Hanzi, effortlessly.
|
||||||
|
|||||||
Reference in New Issue
Block a user