feat: Complete internationalization and code cleanup
## Translation Files - Add 11 new language files (es, de, pt, ru, zh, ja, ko, ar, hi, nl, pl) - Add 100+ missing translation keys across all 15 languages - New sections: notebook, pagination, ai.batchOrganization, ai.autoLabels - Update nav section with workspace, quickAccess, myLibrary keys ## Component Updates - Update 15+ components to use translation keys instead of hardcoded text - Components: notebook dialogs, sidebar, header, note-input, ghost-tags, etc. - Replace 80+ hardcoded English/French strings with t() calls - Ensure consistent UI across all supported languages ## Code Quality - Remove 77+ console.log statements from codebase - Clean up API routes, components, hooks, and services - Keep only essential error handling (no debugging logs) ## UI/UX Improvements - Update Keep logo to yellow post-it style (from-yellow-400 to-amber-500) - Change selection colors to #FEF3C6 (notebooks) and #EFB162 (nav items) - Make "+" button permanently visible in notebooks section - Fix grammar and syntax errors in multiple components ## Bug Fixes - Fix JSON syntax errors in it.json, nl.json, pl.json, zh.json - Fix syntax errors in notebook-suggestion-toast.tsx - Fix syntax errors in use-auto-tagging.ts - Fix syntax errors in paragraph-refactor.service.ts - Fix duplicate "fusion" section in nl.json 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Ou une version plus courte si vous préférez : feat(i18n): Add 15 languages, remove logs, update UI components - Create 11 new translation files (es, de, pt, ru, zh, ja, ko, ar, hi, nl, pl) - Add 100+ translation keys: notebook, pagination, AI features - Update 15+ components to use translations (80+ strings) - Remove 77+ console.log statements from codebase - Fix JSON syntax errors in 4 translation files - Fix component syntax errors (toast, hooks, services) - Update logo to yellow post-it style - Change selection colors (#FEF3C6, #EFB162) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
687
_bmad-output/planning-artifacts/project-context.md
Normal file
687
_bmad-output/planning-artifacts/project-context.md
Normal file
@@ -0,0 +1,687 @@
|
||||
---
|
||||
project_name: 'Keep (Memento Phase 1 MVP AI)'
|
||||
user_name: 'Ramez'
|
||||
date: '2026-01-10'
|
||||
sections_completed: ['technology_stack', 'language_rules', 'framework_rules', 'testing_rules', 'quality_rules', 'workflow_rules', 'anti_patterns']
|
||||
status: 'complete'
|
||||
rule_count: 50
|
||||
optimized_for_llm: true
|
||||
workflow_type: 'generate-project-context'
|
||||
---
|
||||
|
||||
# Project Context for AI Agents
|
||||
|
||||
_This file contains critical rules and patterns that AI agents must follow when implementing code in this project. Focus on unobvious details that agents might otherwise miss._
|
||||
|
||||
---
|
||||
|
||||
## Technology Stack & Versions
|
||||
|
||||
### Core Framework
|
||||
|
||||
**Frontend:**
|
||||
- **Next.js:** 16.1.1 (App Router)
|
||||
- **React:** 19.2.3
|
||||
- **TypeScript:** 5.x (strict mode enabled)
|
||||
|
||||
**Backend:**
|
||||
- **Next.js API Routes** (REST)
|
||||
- **Server Actions** ('use server' directive)
|
||||
- **Prisma:** 5.22.0 (ORM)
|
||||
- **Database:** SQLite (better-sqlite3)
|
||||
|
||||
**Authentication:**
|
||||
- **NextAuth:** 5.0.0-beta.30
|
||||
- **Adapter:** @auth/prisma-adapter
|
||||
|
||||
**AI/ML:**
|
||||
- **Vercel AI SDK:** 6.0.23
|
||||
- **OpenAI Provider:** @ai-sdk/openai ^3.0.7
|
||||
- **Ollama Provider:** ollama-ai-provider ^1.2.0
|
||||
- **Language Detection:** tinyld (to be installed for Phase 1)
|
||||
|
||||
**UI Components:**
|
||||
- **Radix UI:** Multiple primitives (@radix-ui/react-*)
|
||||
- **Tailwind CSS:** 4.x
|
||||
- **Lucide Icons:** ^0.562.0
|
||||
- **Sonner:** ^2.0.7 (toast notifications)
|
||||
|
||||
**Utilities:**
|
||||
- **Zod:** ^4.3.5 (schema validation)
|
||||
- **date-fns:** ^4.1.0 (date formatting)
|
||||
- **clsx:** ^2.1.1, **tailwind-merge:** ^3.4.0 (CSS utilities)
|
||||
- **katex:** ^0.16.27 (LaTeX rendering)
|
||||
- **react-markdown:** ^10.1.0 (markdown rendering)
|
||||
|
||||
**Drag & Drop:**
|
||||
- **@dnd-kit:** ^6.3.1 (modern DnD library)
|
||||
- **muuri:** ^0.9.5 (masonry grid layout)
|
||||
|
||||
**Testing:**
|
||||
- **Playwright:** ^1.57.0 (E2E tests)
|
||||
|
||||
---
|
||||
|
||||
## Critical Implementation Rules
|
||||
|
||||
### TypeScript Configuration
|
||||
|
||||
**STRICT MODE ENABLED:**
|
||||
```json
|
||||
{
|
||||
"strict": true,
|
||||
"target": "ES2017",
|
||||
"moduleResolution": "bundler",
|
||||
"jsx": "react-jsx",
|
||||
"paths": {
|
||||
"@/*": ["./*"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**CRITICAL RULES:**
|
||||
- ✅ All files MUST be typed (no `any` without explicit reason)
|
||||
- ✅ Use `interface` for object shapes, `type` for unions/primitives
|
||||
- ✅ Import from `@/` alias (not relative paths like `../`)
|
||||
- ✅ Props MUST be typed with interfaces (PascalCase names)
|
||||
|
||||
**Example:**
|
||||
```typescript
|
||||
// ✅ GOOD
|
||||
interface NoteCardProps {
|
||||
note: Note
|
||||
onEdit?: (note: Note) => void
|
||||
}
|
||||
|
||||
export function NoteCard({ note, onEdit }: NoteCardProps) {
|
||||
// ...
|
||||
}
|
||||
|
||||
// ❌ BAD - any without reason
|
||||
export function NoteCard({ note, onEdit }: any) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Component Patterns
|
||||
|
||||
**Directives Required:**
|
||||
- ✅ Server Components: No directive (default in Next.js 16 App Router)
|
||||
- ✅ Client Components: `'use client'` at TOP of file (line 1)
|
||||
- ✅ Server Actions: `'use server'` at TOP of file (line 1)
|
||||
|
||||
**Example:**
|
||||
```typescript
|
||||
// keep-notes/components/ai/ai-suggestion.tsx
|
||||
'use client'
|
||||
|
||||
import { useState } from 'react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
|
||||
export function AiSuggestion() {
|
||||
// Interactive component logic
|
||||
}
|
||||
```
|
||||
|
||||
**Component Naming:**
|
||||
- ✅ **PascalCase** for component names: `NoteCard`, `LabelBadge`, `AiSuggestion`
|
||||
- ✅ **kebab-case** for file names: `note-card.tsx`, `label-badge.tsx`, `ai-suggestion.tsx`
|
||||
- ✅ **UI components** in `components/ui/` subdirectory: `button.tsx`, `dialog.tsx`
|
||||
|
||||
**Props Pattern:**
|
||||
```typescript
|
||||
// ✅ GOOD - Interface export
|
||||
export interface NoteCardProps {
|
||||
note: Note
|
||||
onEdit?: (note: Note, readOnly?: boolean) => void
|
||||
isDragging?: boolean
|
||||
}
|
||||
|
||||
export function NoteCard({ note, onEdit, isDragging }: NoteCardProps) {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**Imports Order:**
|
||||
```typescript
|
||||
// 1. React imports
|
||||
import { useState, useEffect } from 'react'
|
||||
|
||||
// 2. Third-party libraries
|
||||
import { formatDistanceToNow } from 'date-fns'
|
||||
import { Bell } from 'lucide-react'
|
||||
|
||||
// 3. Local imports (use @/ alias)
|
||||
import { Card } from '@/components/ui/card'
|
||||
import { Note } from '@/lib/types'
|
||||
import { deleteNote } from '@/app/actions/notes'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Server Actions Pattern
|
||||
|
||||
**CRITICAL: All server actions MUST follow this pattern:**
|
||||
|
||||
```typescript
|
||||
// keep-notes/app/actions/ai-suggestions.ts
|
||||
'use server'
|
||||
|
||||
import { auth } from '@/auth'
|
||||
import { revalidatePath } from 'next/cache'
|
||||
import { prisma } from '@/lib/prisma'
|
||||
|
||||
export async function generateTitleSuggestions(noteId: string) {
|
||||
// 1. Authentication check
|
||||
const session = await auth()
|
||||
if (!session?.user?.id) {
|
||||
throw new Error('Unauthorized')
|
||||
}
|
||||
|
||||
try {
|
||||
// 2. Business logic
|
||||
const note = await prisma.note.findUnique({
|
||||
where: { id: noteId }
|
||||
})
|
||||
|
||||
if (!note) {
|
||||
throw new Error('Note not found')
|
||||
}
|
||||
|
||||
// 3. AI processing
|
||||
const titles = await generateTitles(note.content)
|
||||
|
||||
// 4. Revalidate cache
|
||||
revalidatePath('/')
|
||||
|
||||
return { success: true, titles }
|
||||
} catch (error) {
|
||||
console.error('Error generating titles:', error)
|
||||
throw new Error('Failed to generate title suggestions')
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**CRITICAL RULES:**
|
||||
- ✅ `'use server'` at line 1 (before imports)
|
||||
- ✅ **ALWAYS** check `auth()` session first
|
||||
- ✅ **ALWAYS** `revalidatePath('/')` after mutations
|
||||
- ✅ Use `try/catch` with `console.error()` logging
|
||||
- ✅ Throw `Error` objects (not strings)
|
||||
- ✅ Return `{ success: true, data }` or throw error
|
||||
|
||||
---
|
||||
|
||||
### API Routes Pattern
|
||||
|
||||
**CRITICAL: All API routes MUST follow this pattern:**
|
||||
|
||||
```typescript
|
||||
// keep-notes/app/api/ai/titles/route.ts
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
|
||||
const requestSchema = z.object({
|
||||
content: z.string().min(1, "Content required"),
|
||||
noteId: z.string().optional()
|
||||
})
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
try {
|
||||
// 1. Parse and validate request
|
||||
const body = await req.json()
|
||||
const { content, noteId } = requestSchema.parse(body)
|
||||
|
||||
// 2. Business logic
|
||||
const titles = await generateTitles(content)
|
||||
|
||||
// 3. Return success response
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
data: { titles }
|
||||
})
|
||||
} catch (error) {
|
||||
// 4. Error handling
|
||||
if (error instanceof z.ZodError) {
|
||||
return NextResponse.json(
|
||||
{ success: false, error: error.issues },
|
||||
{ status: 400 }
|
||||
)
|
||||
}
|
||||
|
||||
console.error('Error generating titles:', error)
|
||||
return NextResponse.json(
|
||||
{ success: false, error: 'Failed to generate titles' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**CRITICAL RULES:**
|
||||
- ✅ Use **Zod schemas** for request validation
|
||||
- ✅ Return `{ success: true, data: any }` for success
|
||||
- ✅ Return `{ success: false, error: string }` for errors
|
||||
- ✅ Handle `ZodError` separately (400 status)
|
||||
- ✅ Log errors with `console.error()`
|
||||
- ✅ **NEVER** expose stack traces to clients
|
||||
|
||||
**Response Format:**
|
||||
```typescript
|
||||
// Success
|
||||
{ success: true, data: { ... } }
|
||||
|
||||
// Error
|
||||
{ success: false, error: "Human-readable error message" }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Database Access Pattern
|
||||
|
||||
**SINGLE DATA ACCESS LAYER:**
|
||||
- ✅ **ONLY** use Prisma ORM (no raw SQL, no direct database access)
|
||||
- ✅ Import from `@/lib/prisma` (singleton instance)
|
||||
- ✅ Use `findMany`, `findUnique`, `create`, `update`, `delete`
|
||||
|
||||
```typescript
|
||||
// ✅ GOOD
|
||||
import { prisma } from '@/lib/prisma'
|
||||
|
||||
const notes = await prisma.note.findMany({
|
||||
where: { userId: session.user.id },
|
||||
orderBy: { createdAt: 'desc' }
|
||||
})
|
||||
```
|
||||
|
||||
**Prisma Schema Conventions:**
|
||||
- ✅ **PascalCase** for model names: `User`, `Note`, `Label`, `AiFeedback`
|
||||
- ✅ **camelCase** for fields: `userId`, `isPinned`, `createdAt`
|
||||
- ✅ Foreign keys: `{model}Id` format: `userId`, `noteId`
|
||||
- ✅ Booleans: prefix `is` for flags: `isPinned`, `isArchived`
|
||||
- ✅ Timestamps: suffix `At` for dates: `createdAt`, `updatedAt`
|
||||
- ✅ All new fields optional (nullable) for backward compatibility
|
||||
|
||||
---
|
||||
|
||||
### Naming Conventions
|
||||
|
||||
**Database:**
|
||||
- Tables: **PascalCase** (`AiFeedback`, `MemoryEchoInsight`)
|
||||
- Columns: **camelCase** (`noteId`, `similarityScore`)
|
||||
- Indexes: Prisma `@@index([...])` annotations
|
||||
|
||||
**API Routes:**
|
||||
- Collections: **plural** (`/api/notes`, `/api/labels`)
|
||||
- Items: **singular** (`/api/notes/[id]`)
|
||||
- Namespace: `/api/ai/*` for AI features
|
||||
|
||||
**Components:**
|
||||
- Component names: **PascalCase** (`NoteCard`, `AiSuggestion`)
|
||||
- File names: **kebab-case** (`note-card.tsx`, `ai-suggestion.tsx`)
|
||||
|
||||
**Functions:**
|
||||
- Functions: **camelCase** (`getNotes`, `createNote`, `togglePin`)
|
||||
- Verbs first: `get`, `create`, `update`, `delete`, `toggle`
|
||||
- Handlers: prefix `handle` (`handleDelete`, `handleTogglePin`)
|
||||
|
||||
**Variables:**
|
||||
- Variables: **camelCase** (`userId`, `isPending`, `noteId`)
|
||||
- Types/interfaces: **PascalCase** (`Note`, `NoteCardProps`)
|
||||
|
||||
---
|
||||
|
||||
### State Management
|
||||
|
||||
**NO GLOBAL STATE LIBRARIES:**
|
||||
- ❌ No Redux, Zustand, or similar
|
||||
- ✅ **React useState** for local component state
|
||||
- ✅ **React Context** for shared state (User session, Theme, Labels)
|
||||
- ✅ **React Cache** for server-side caching
|
||||
- ✅ **useOptimistic** for immediate UI feedback
|
||||
- ✅ **useTransition** for non-blocking updates
|
||||
|
||||
**Example:**
|
||||
```typescript
|
||||
'use client'
|
||||
|
||||
import { useState, useTransition, useOptimistic } from 'react'
|
||||
|
||||
export function NoteCard({ note }: NoteCardProps) {
|
||||
const [isPending, startTransition] = useTransition()
|
||||
const [optimisticNote, addOptimisticNote] = useOptimistic(
|
||||
note,
|
||||
(state, newProps: Partial<Note>) => ({ ...state, ...newProps })
|
||||
)
|
||||
|
||||
const handleTogglePin = async () => {
|
||||
startTransition(async () => {
|
||||
addOptimisticNote({ isPinned: !note.isPinned })
|
||||
await togglePin(note.id, !note.isPinned)
|
||||
router.refresh()
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Error Handling
|
||||
|
||||
**Global Pattern:**
|
||||
```typescript
|
||||
// API Routes
|
||||
try {
|
||||
// ... code
|
||||
} catch (error) {
|
||||
console.error('Feature name error:', error)
|
||||
return NextResponse.json(
|
||||
{ success: false, error: 'Human-readable message' },
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
|
||||
// Server Actions
|
||||
try {
|
||||
// ... code
|
||||
} catch (error) {
|
||||
console.error('Feature name error:', error)
|
||||
throw new Error('Failed to action')
|
||||
}
|
||||
```
|
||||
|
||||
**CRITICAL RULES:**
|
||||
- ✅ Use `console.error()` for logging (not `console.log`)
|
||||
- ✅ Human-readable error messages (no technical jargon)
|
||||
- ✅ **NEVER** expose stack traces to users
|
||||
- ✅ **NEVER** expose internal error details
|
||||
|
||||
---
|
||||
|
||||
### Import Rules
|
||||
|
||||
**ALWAYS use @/ alias:**
|
||||
```typescript
|
||||
// ✅ GOOD
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Note } from '@/lib/types'
|
||||
import { deleteNote } from '@/app/actions/notes'
|
||||
|
||||
// ❌ BAD - relative paths
|
||||
import { Button } from '../../../components/ui/button'
|
||||
import { Note } from '../lib/types'
|
||||
```
|
||||
|
||||
**Import from Radix UI:**
|
||||
```typescript
|
||||
// ✅ GOOD - use @/components/ui/* wrapper
|
||||
import { Dialog } from '@/components/ui/dialog'
|
||||
import { Button } from '@/components/ui/button'
|
||||
|
||||
// ❌ BAD - direct Radix imports
|
||||
import { Dialog } from '@radix-ui/react-dialog'
|
||||
import { Button } from '@radix-ui/react-slot'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### AI Service Pattern
|
||||
|
||||
**All AI services follow this structure:**
|
||||
|
||||
```typescript
|
||||
// keep-notes/lib/ai/services/title-suggestion.service.ts
|
||||
import { getAIProvider } from '@/lib/ai/factory'
|
||||
|
||||
export class TitleSuggestionService {
|
||||
private provider = getAIProvider()
|
||||
|
||||
async generateSuggestions(content: string): Promise<string[]> {
|
||||
try {
|
||||
const response = await this.provider.generateText({
|
||||
prompt: `Generate 3 titles for: ${content}`,
|
||||
maxTokens: 100
|
||||
})
|
||||
|
||||
return response.titles
|
||||
} catch (error) {
|
||||
console.error('TitleSuggestionService error:', error)
|
||||
throw new Error('Failed to generate suggestions')
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**CRITICAL RULES:**
|
||||
- ✅ Use `getAIProvider()` factory (not direct OpenAI/Ollama imports)
|
||||
- ✅ Services are **stateless classes**
|
||||
- ✅ Constructor injection of dependencies
|
||||
- ✅ Methods return `Promise<T>` with error handling
|
||||
- ✅ No direct database access (via Prisma)
|
||||
|
||||
---
|
||||
|
||||
### Testing Rules
|
||||
|
||||
**Playwright E2E Tests:**
|
||||
```typescript
|
||||
// tests/e2e/ai-features.spec.ts
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test('AI title suggestions appear', async ({ page }) => {
|
||||
await page.goto('/')
|
||||
await page.fill('[data-testid="note-content"]', 'Test content')
|
||||
// Wait for AI suggestions
|
||||
await expect(page.locator('[data-testid="ai-suggestions"]')).toBeVisible()
|
||||
})
|
||||
```
|
||||
|
||||
**CRITICAL RULES:**
|
||||
- ✅ Use `data-testid` attributes for test selectors
|
||||
- ✅ Test critical user flows (not edge cases)
|
||||
- ✅ Use `await expect(...).toBeVisible()` for assertions
|
||||
- ✅ Tests in `tests/e2e/` directory
|
||||
|
||||
---
|
||||
|
||||
### Brownfield Integration Rules
|
||||
|
||||
**ZERO BREAKING CHANGES:**
|
||||
- ✅ **ALL new features must extend, not replace existing functionality**
|
||||
- ✅ Existing components, API routes, and database tables MUST continue working
|
||||
- ✅ New database fields: **optional** (nullable) for backward compatibility
|
||||
- ✅ New features: **additive** only (don't remove existing features)
|
||||
|
||||
**Example:**
|
||||
```prisma
|
||||
// ✅ GOOD - optional new field
|
||||
model Note {
|
||||
// ... existing fields
|
||||
language String? // NEW: optional
|
||||
aiConfidence Int? // NEW: optional
|
||||
}
|
||||
|
||||
// ❌ BAD - breaking change
|
||||
model Note {
|
||||
language String @default("en") // BREAKS: non-optional default
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Phase 1 Specific Rules
|
||||
|
||||
**AI Features to Implement:**
|
||||
1. **Title Suggestions** - 3 suggestions after 50+ words
|
||||
2. **Semantic Search** - Hybrid keyword + vector search with RRF
|
||||
3. **Paragraph Reformulation** - Clarify, Shorten, Improve Style options
|
||||
4. **Memory Echo** - Daily proactive note connections (background job)
|
||||
5. **AI Settings** - Granular ON/OFF controls per feature
|
||||
6. **Language Detection** - TinyLD hybrid (< 50 words: library, ≥ 50 words: AI)
|
||||
|
||||
**Performance Targets:**
|
||||
- ✅ Title suggestions: < 2s after detection
|
||||
- ✅ Semantic search: < 300ms for 1000 notes
|
||||
- ✅ Memory Echo: < 100ms UI freeze (background processing)
|
||||
- ✅ Language detection: ~8ms (TinyLD) or ~200-500ms (AI)
|
||||
|
||||
**Language Support:**
|
||||
- ✅ System prompts: **English** (stability)
|
||||
- ✅ User data: **Local language** (FR, EN, ES, DE, FA/Persian + 57 others)
|
||||
- ✅ TinyLD supports 62 languages including Persian (verified)
|
||||
|
||||
---
|
||||
|
||||
### Security Rules
|
||||
|
||||
**API Keys:**
|
||||
- ✅ **NEVER** expose API keys to client (server-side only)
|
||||
- ✅ Store in environment variables (`OPENAI_API_KEY`, `OLLAMA_ENDPOINT`)
|
||||
- ✅ Use SystemConfig table for provider selection
|
||||
|
||||
**Authentication:**
|
||||
- ✅ **ALL** server actions check `auth()` session first
|
||||
- ✅ **ALL** API routes require valid NextAuth session
|
||||
- ✅ Public routes: `/api/auth/*`, login/register pages only
|
||||
|
||||
**Privacy:**
|
||||
- ✅ Ollama path = 100% local (no external API calls)
|
||||
- ✅ OpenAI path = cloud (verify in DevTools Network tab)
|
||||
- ✅ User data never logged or exposed
|
||||
|
||||
---
|
||||
|
||||
### File Organization
|
||||
|
||||
**AI Services:**
|
||||
```
|
||||
lib/ai/services/
|
||||
├── title-suggestion.service.ts
|
||||
├── semantic-search.service.ts
|
||||
├── paragraph-refactor.service.ts
|
||||
├── memory-echo.service.ts
|
||||
├── language-detection.service.ts
|
||||
└── embedding.service.ts
|
||||
```
|
||||
|
||||
**AI Components:**
|
||||
```
|
||||
components/ai/
|
||||
├── ai-suggestion.tsx
|
||||
├── ai-settings-panel.tsx
|
||||
├── memory-echo-notification.tsx
|
||||
├── confidence-badge.tsx
|
||||
├── feedback-buttons.tsx
|
||||
└── paragraph-refactor.tsx
|
||||
```
|
||||
|
||||
**API Routes:**
|
||||
```
|
||||
app/api/ai/
|
||||
├── titles/route.ts
|
||||
├── search/route.ts
|
||||
├── refactor/route.ts
|
||||
├── echo/route.ts
|
||||
├── feedback/route.ts
|
||||
└── language/route.ts
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Development Workflow
|
||||
|
||||
**Before implementing ANY feature:**
|
||||
1. ✅ Read `_bmad-output/planning-artifacts/architecture.md`
|
||||
2. ✅ Check `project-context.md` for specific rules
|
||||
3. ✅ Follow naming patterns (camelCase, PascalCase, kebab-case)
|
||||
4. ✅ Use response format `{success, data, error}`
|
||||
5. ✅ Add `'use server'` or `'use client'` directives
|
||||
6. ✅ Import from `@/` alias only
|
||||
|
||||
**Quality Checklist:**
|
||||
- [ ] TypeScript strict mode compliance
|
||||
- [ ] Zod validation for API routes
|
||||
- [ ] auth() check in server actions
|
||||
- [ ] revalidatePath('/') after mutations
|
||||
- [ ] Error handling with console.error()
|
||||
- [ ] Response format {success, data/error}
|
||||
- [ ] Import from @/ alias
|
||||
- [ ] Component directives ('use client'/'use server')
|
||||
- [ ] Zero breaking changes
|
||||
- [ ] Performance targets met
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference Card
|
||||
|
||||
**For AI Agents implementing features:**
|
||||
|
||||
| Category | Rule | Example |
|
||||
|----------|------|---------|
|
||||
| TypeScript | Strict mode, no `any` | `interface Props { note: Note }` |
|
||||
| Components | 'use client' at top | `export function Comp() { ... }` |
|
||||
| Server Actions | 'use server' + auth() + revalidate | `const session = await auth()` |
|
||||
| API Routes | Zod + {success, data/error} | `return NextResponse.json({ success: true, data })` |
|
||||
| Database | Prisma only, no raw SQL | `await prisma.note.findMany()` |
|
||||
| Naming | camelCase vars, PascalCase types | `const userId: string` |
|
||||
| Imports | @/ alias only | `import { Note } from '@/lib/types'` |
|
||||
| Error Handling | console.error + human message | `throw new Error('Failed to...')` |
|
||||
| AI Services | getAIProvider() factory | `const provider = getAIProvider()` |
|
||||
| Performance | Target < 2s for AI features | `await withTimeout(promise, 2000)` |
|
||||
|
||||
---
|
||||
|
||||
*Generated: 2026-01-10*
|
||||
*Project: Keep (Memento Phase 1 MVP AI)*
|
||||
*Architecture: Based on architecture.md (2784 lines)*
|
||||
*Status: Ready for AI Agent Implementation*
|
||||
|
||||
---
|
||||
|
||||
## Usage Guidelines
|
||||
|
||||
**For AI Agents:**
|
||||
|
||||
- ✅ Read this file **before** implementing any code
|
||||
- ✅ Follow **ALL** rules exactly as documented
|
||||
- ✅ When in doubt, prefer the more restrictive option
|
||||
- ✅ Check `_bmad-output/planning-artifacts/architecture.md` for full context
|
||||
- ✅ Use response format `{success, data, error}` for API routes
|
||||
- ✅ Add `'use server'` or `'use client'` directives at top of files
|
||||
- ✅ Import from `@/` alias only (not relative paths)
|
||||
- ✅ Validate requests with Zod schemas
|
||||
- ✅ Check `auth()` session in server actions
|
||||
- ✅ Call `revalidatePath('/')` after mutations
|
||||
- ✅ Log errors with `console.error()`
|
||||
|
||||
**For Humans:**
|
||||
|
||||
- Keep this file **lean and focused** on agent needs
|
||||
- Update when **technology stack changes**
|
||||
- Review **quarterly** for outdated rules
|
||||
- Remove rules that become **obvious over time**
|
||||
- Add new patterns when they emerge in development
|
||||
|
||||
**Maintenance:**
|
||||
|
||||
1. **Technology Changes:** Update when adding/removing dependencies
|
||||
2. **Pattern Evolution:** Add new patterns as they emerge
|
||||
3. **Bug Prevention:** Add rules when agents make common mistakes
|
||||
4. **Optimization:** Remove redundant or obvious rules periodically
|
||||
5. **Review Cycle:** Check quarterly for outdated information
|
||||
|
||||
---
|
||||
|
||||
**Last Updated:** 2026-01-10
|
||||
|
||||
**Optimization Status:** ✅ Optimized for LLM context (50 critical rules, 490 lines)
|
||||
|
||||
**Readiness:** ✅ Ready for AI Agent Implementation
|
||||
|
||||
---
|
||||
|
||||
*Workflow completed: 2026-01-10*
|
||||
*Generator: Winston (Architect Agent) with Generate Project Context workflow*
|
||||
*Based on: architecture.md (2784 lines) + existing codebase analysis*
|
||||
Reference in New Issue
Block a user