Write2Learn GitHub Copilot Instructions
Coding guidelines for Write2Learn, a Next.js 15 (App Router) application for English writing improvement through journaling, vocabulary building, and roleplay features.
Architecture Overview
Write2Learn uses Next.js 15 with App Router, TypeScript, Supabase for backend, and Tailwind CSS for styling. The app helps users improve English writing through structured journaling, vocabulary practice with spaced repetition, and interactive roleplay scenarios.
Core Coding Style
**Critical Rule**: Delete all unused and unnecessary code. When adjusting existing code, delete the old code instead of commenting it out. Never turn old code into fallbacks or leave it as dead code.
Service Architecture Patterns
Feature-First Organization
Code is organized by domain (`auth/`, `journal/`, `vocab/`) rather than by technical layerEach feature has its own directory containing services, components, and related utilitiesSingleton Services
Each service exports a single instance using the pattern: ```typescript
export const vocabularyService = new VocabularyService();
export const journalService = new JournalService();
```
Service Boundaries
**Services**: Handle API calls and database operations**Stores**: Manage application state (Zustand)**Hooks**: Contain component-specific logic and side effectsAuthentication & Middleware
Session Management
`middleware.ts` implements session caching to redirect unauthenticated users`AuthProvider` context wraps the application with user state and onboarding statusAPI Authentication
API routes use `authenticateUser()` from `utils/api-helpers.ts` for validationProtected routes automatically redirect to `/onboarding` if `profiles.onboarding_completed` is falseAPI Route Patterns
All API routes must follow this structure:
```typescript
export async function POST(request: Request) {
try {
const user = await authenticateUser();
const { field } = await parseRequestBody<Type>(request);
const result = await service.method(user.id, data);
return createSuccessResponse(result, 'Success message');
} catch (error) {
return handleApiError(error);
}
}
```
**Key Requirements**:
Always use `authenticateUser()` for protected endpointsParse request bodies with type safety using `parseRequestBody<T>()`Return standardized responses via `createSuccessResponse()`Handle errors exclusively through `handleApiError()`, never throw raw errorsDatabase Schema (Supabase)
**Core Tables**:
`profiles` - User information with `onboarding_completed` flag`journals` - Journal entries with optional template linking`vocabulary` - User vocabulary with FSRS spaced repetition data`journal_templates` - Reusable writing prompts**Type Generation**:
Auto-generated types live in `types/database.types.ts`Never manually edit database typesProject ID: `eqhldzwiymtcyxyxezos`UI Component Standards
Component Library
Use Radix UI primitives with Tailwind CSSCustom variants defined using `class-variance-authority` (CVA)Base components in `components/ui/` (Button, Dialog, etc.)Feature-specific components in `components/{feature}/`Styling Utilities
Always use `cn()` utility from `utils/ui.ts` for conditional classesFollow Tailwind best practices for responsive designMaintain consistent spacing and typography scalesState Management Strategy
State Layers
1. **Zustand Stores** (`stores/`) - Global application state
2. **React Context** - Authentication state via `AuthProvider`
3. **Server State** - Direct API calls through services (no React Query)
When to Use Each
Use Zustand for cross-component state (auth, user profile)Use React Context for deeply nested read-heavy stateUse local component state for UI-only concernsDevelopment Commands
```bash
npm run dev # Start dev server with Turbopack
npm run build # Production build with Turbopack
npm run run:fsrs # Run FSRS spaced repetition tests
```
Critical Implementation Patterns
1. Service Instantiation
Always export singleton instances:
```typescript
// ✅ Correct
export const vocabularyService = new VocabularyService();
// ❌ Incorrect
export class VocabularyService { }
```
2. File Naming
**Components**: kebab-case (`vocabulary-card.tsx`)**TypeScript Types**: PascalCase (`VocabularyItem.ts`)**Services**: kebab-case (`vocabulary-service.ts`)3. Error Handling
API routes MUST use `handleApiError()`Never throw raw errors in API routesLog errors appropriately for debugging4. Authentication Flow
Always check `onboarding_completed` in middlewareRedirect incomplete onboarding to `/onboarding`Use `authenticateUser()` in all protected API routes5. Markdown Editing
Uses custom markdown editor with task list support**Do NOT use TipTap** for journal contentPrefer lightweight markdown solutionsIntegration Points
Supabase
Client creation via `@supabase/auth-helpers-nextjs`Use typed clients for compile-time safetyLeverage Supabase Edge Functions where appropriateFSRS Spaced Repetition
Uses `ts-fsrs` library for vocabulary schedulingImplement FSRS algorithms in vocabulary serviceTest spaced repetition logic with `npm run run:fsrs`Dynamic Imports
Use dynamic imports for client-only components (e.g., markdown editor)Pattern: `const Editor = dynamic(() => import('./editor'), { ssr: false })`Feature Implementation Checklist
When implementing new features:
1. ✅ Create feature directory under appropriate domain
2. ✅ Implement singleton service with typed methods
3. ✅ Build API routes following standard pattern
4. ✅ Create UI components in `components/{feature}/`
5. ✅ Add Zustand store if cross-component state needed
6. ✅ Update middleware if authentication rules change
7. ✅ Test with actual Supabase project (ID: `eqhldzwiymtcyxyxezos`)
8. ✅ Delete all unused code from previous iterations
Common Pitfalls to Avoid
❌ Commenting out old code instead of deleting it❌ Creating fallback logic for deprecated features❌ Throwing raw errors in API routes❌ Using class exports instead of singleton instances❌ Manually editing `database.types.ts`❌ Using TipTap for journal markdown editing❌ Skipping authentication checks in protected routes❌ Ignoring `onboarding_completed` flag in routing logicFollow these guidelines consistently to maintain code quality and architectural integrity across the Write2Learn codebase.