## 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>
688 lines
18 KiB
Markdown
688 lines
18 KiB
Markdown
---
|
|
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*
|