sepehr 7fb486c9a4 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>
2026-01-11 22:26:13 +01:00

93 KiB

stepsCompleted inputDocuments workflowType lastStep project_name user_name date completedAt communication_language document_output_language status focusArea
1
2
3
4
5
6
7
8
_bmad-output/analysis/brainstorming-session-2026-01-09.md
_bmad-output/planning-artifacts/prd-phase1-mvp-ai.md
_bmad-output/planning-artifacts/ux-design-specification.md
docs/architecture-keep-notes.md
docs/data-models.md
docs/component-inventory.md
docs/integration-architecture.md
architecture 8 Keep Ramez 2026-01-10 2026-01-10 French English complete Phase 1 MVP AI - AI-Powered Note Taking Features

Architecture Decision Document

This document builds collaboratively through step-by-step discovery. Sections are appended as we work through each architectural decision together.


Project Context Analysis

Requirements Overview

Functional Requirements:

Le projet Keep (Memento Phase 1 MVP AI) est une application brownfield qui étend une solution existante de prise de notes avec des fonctionnalités d'IA contextuelle. Les exigences fonctionnelles architecturales significatives incluent :

  1. Intelligent Title Suggestions - Déclenchement automatique après 50+ mots sans titre, avec toast non-intrusif et 3 suggestions IA. Implication architecturale : Nécessite un système de détection en temps réel, débounce, et génération de titres via IA avec latence < 2s.

  2. Hybrid Semantic Search - Recherche unifiée combinant mots-clés exacts et correspondance sémantique avec badges distinctifs. Implication architecturale : Vector search sur embeddings existants + indexation texte traditionnelle, fusion transparente des résultats, latence < 300ms pour 1000 notes.

  3. Paragraph-Level Reformulation - Menu contextuel pour réécrire des paragraphes avec options (Clarifier, Raccourcir, Améliorer style). Implication architecturale : Composants modaux réutilisables, gestion d'état pour sélection de texte, appels IA à la demande.

  4. Memory Echo (Proactive Connections) - Analyse en arrière-plan des embeddings pour identifier des connexions entre notes (max 1 insight/jour). Implication architecturale : Traitement asynchrone non-bloquant (< 100ms UI freeze), système de scoring cosine similarity > 0.75, notification contextuelle.

  5. AI Settings Panel - Page /settings/ai avec contrôles granulaires ON/OFF par feature et slider de fréquence. Implication architecturale : Persistance des préférences utilisateur, architecture de configuration extensible.

Non-Functional Requirements:

Les NFRs critiques qui façonneront l'architecture :

Performance:

  • Recherche sémantique < 300ms (1000 notes)
  • Suggestions titres < 2s après détection
  • Memory Echo: traitement background avec UI freeze < 100ms
  • Auto-tagging suggestions < 1.5s après fin de saisie

Privacy & Security:

  • Support Ollama 100% local (zéro appel API externe)
  • Support OpenAI cloud avec chiffrage des clés API
  • Données utilisateur never quittent l'infrastructure locale avec Ollama
  • Vérifiable dans DevTools (Max's use case)

Multilingual Architecture:

  • Prompts système en anglais (stabilité des modèles)
  • Détection automatique langue par note (FR, EN, ES, DE minimum)
  • Données utilisateur en langue locale
  • Architecture prête pour expansion internationale

Compatibility & Maintainability:

  • Zero Breaking Changes : Toutes features existantes doivent continuer à fonctionner
  • Multi-provider support via factory pattern (existant)
  • Extensions Prisma schema (pas de réécriture)
  • API Routes namespace /api/ai/ (respect structure existante)

Scalability Constraints:

  • Zéro DevOps (hosting managé Vercel/Netlify)
  • SQLite en prod (pas de vector DB séparée)
  • Modèles locaux via Ollama ou API externes
  • Rate limiting par utilisateur (Léa's admin use case)

Scale & Complexity:

  • Primary domain: Full-stack web application with AI integration (brownfield extension)
  • Complexity level: Medium
  • Estimated architectural components: 12-15 major components

Complexity Drivers:

  • Real-time features (détection contextuelle 50+ mots, toast notifications)
  • Multi-provider AI abstraction (Ollama local + OpenAI cloud)
  • Vector search + traditional search fusion
  • Background processing without UI blocking
  • Granular per-feature ON/OFF settings
  • Multilingual detection and processing
  • Privacy-first architecture (local vs cloud)

Technical Constraints & Dependencies

Existing Stack (Must Preserve):

  • Next.js 16.1.1 (App Router) + React 19.2.3 + TypeScript 5
  • Prisma 5.22.0 ORM + SQLite (better-sqlite3)
  • Vercel AI SDK 6.0.23 + OpenAI/Ollama providers
  • NextAuth 5.0.0-beta.30 (authentication)

Current AI Capabilities (Already Implemented):

  • Auto-tagging with embeddings
  • Multi-provider support (OpenAI, Ollama)
  • Factory pattern for AI providers

Phase 1 Must Integrate With:

  • API Routes in /api/ai/ namespace
  • Components in shared structure
  • Prisma schema extensions (not rewrites)
  • Existing user authentication system
  • Current note storage (SQLite)

Technical Constraints:

  • No native mobile apps (web responsive only)
  • Offline mode: None for MVP (Phase 2: PWA)
  • SQLite with embeddings in same DB (no separate vector DB)
  • No dedicated infrastructure (Vercel/Netlify hosting)

External Dependencies:

  • Ollama (local installation optional for users)
  • OpenAI API (cloud option for non-technical users)
  • Embeddings models (multi-language support)
  • Next.js 16+ (App Router patterns)

Cross-Cutting Concerns Identified

1. Privacy & Data Protection

  • Impact: Toute l'architecture IA doit supporter deux modes : local (Ollama, 0 data exfiltration) et cloud (OpenAI)
  • Requirement: Vérifiable dans DevTools, indicateurs de connexion clairs, chiffrage des clés API
  • Affected Components: AI provider factory, settings UI, connection status indicators

2. Performance & Non-Blocking AI

  • Impact: Les appels IA ne doivent jamais bloquer l'UI
  • Requirement: Traitement asynchrone pour Memory Echo, debounce pour suggestions, loading states clairs
  • Affected Components: Title suggestions (debounce), Memory Echo (background job), search (optimistic UI)

3. Multilingual Processing

  • Impact: Architecture doit supporter prompts système anglais + données utilisateur multi-langues
  • Requirement: Détection automatique par note, embeddings multi-langues, respect des langues (FR, EN, ES, DE)
  • Affected Components: AI service layer, embedding generation, language detection service

4. User Control & Transparency

  • Impact: Chaque feature IA doit être contrôlable indépendamment
  • Requirement: Settings granulaires ON/OFF, feedback 👍👎 pour apprentissage, indicateurs visuels (badges)
  • Affected Components: Settings panel, all AI UI components, feedback tracking system

5. Extensibility for Future Phases

  • Impact: Architecture Phase 1 ne doit pas bloquer Phase 2/3 (score confiance, feedback généralisé, mode conservateur)
  • Requirement: Factory pattern existant, schema extensible, préparation pour système de confiance 3 couches
  • Affected Components: AI provider factory, Prisma schema design, feedback collection (préparer pour généralisation)

6. Brownfield Integration

  • Impact: Toutes nouvelles features doivent coexister avec features existantes sans breaking changes
  • Requirement: Respect patterns existants, extensions pas réécritures, tests de non-régression
  • Affected Components: Toutes les nouvelles routes API, components, Prisma migrations

7. Analytics & Monitoring

  • Impact: Nécessité de tracker l'adoption et l'efficacité des features IA
  • Requirement: Métriques temps réel (usage, coûts, feedback), dashboard admin (Léa's use case)
  • Affected Components: Analytics service, admin dashboard, cost tracking per user

Existing Architecture Review

Primary Technology Domain

Application Type: Full-stack brownfield web application with AI integration Current Stack: Next.js 16.1.1 (App Router) + React 19.2.3 + Prisma 5.22.0 + SQLite

Architecture Overview

Current Foundation - Keep Notes (Memento Web App):

Le projet dispose d'une architecture JAMstack mature avec :

Frontend:

  • React 19.2.3 avec Server Components (App Router)
  • Tailwind CSS 4 pour le styling
  • Radix UI pour les primitives accessibles
  • 20+ composants métier organisés par domaine
  • Masonry grid layout (Muuri) avec drag-and-drop (@dnd-kit)

Backend (Integrated):

  • Next.js API Routes (REST)
  • Server Actions pour les mutations
  • Prisma 5.22.0 ORM avec better-sqlite3
  • NextAuth 5.0.0-beta.30 (authentification)
  • Vercel AI SDK 6.0.23 (OpenAI + Ollama providers)

Database:

  • SQLite (prisma/dev.db)
  • 7 modèles : User, Account, Session, VerificationToken, Note, Label, SystemConfig
  • Embeddings vectoriels stockés en JSON dans Note.embedding
  • 13 migrations déjà appliquées

Architectural Patterns Established

1. Factory Pattern pour AI Providers (DÉJÀ IMPLÉMENTÉ)

Localisation : lib/ai/providers/

// Factory existant
export function createProvider(provider: string) {
  switch (provider) {
    case 'openai': return new OpenAIProvider()
    case 'ollama': return new OllamaProvider()
  }
}

Implication pour Phase 1 : Ce pattern est déjà en place et doit être étendu, pas remplacé. Les nouveaux endpoints IA (titles, refactor, echo) s'intégreront dans cette architecture.

2. State Management Strategy

  • Aucune librairie d'état global (Pas de Redux, Zustand)
  • React Cache pour le cache serveur
  • Server Actions pour les mutations
  • Context pour session utilisateur et thème
  • URL State pour les filtres/recherche

Implication pour Phase 1 : Maintenir cette approche légère. Les features IA utiliseront React Query ou équivalent si nécessaire pour le cache client.

3. Component Architecture

Hiérarchie existante :

Layout Components (Header, Sidebar, MasonryGrid)
  └── NoteCard
      ├── NoteEditor
      │   ├── NoteChecklist
      │   ├── NoteImages
      │   └── EditorImages
      └── NoteActions

Label Management
  ├── LabelBadge, LabelFilter, LabelSelector
  ├── LabelManager → LabelManagementDialog
  └── GhostTags (floating tags)

20+ composants métier documentés dans docs/component-inventory.md

Implication pour Phase 1 : Les nouveaux composants IA (<AiSuggestion />, <AiSettingsPanel />, <MemoryEchoNotification />) doivent suivre les mêmes patterns de composition et de styling.

4. API Architecture

Routes existantes :

  • /api/notes (CRUD)
  • /api/labels (CRUD)
  • /api/auth/[...nextauth] (auth)
  • /api/ai/tags (auto-tagging DÉJÀ implémenté)
  • /api/upload (file upload)
  • /api/admin/* (admin endpoints)

Response Format standardisé :

{
  "success": true|false,
  "data": any,
  "error": string  // seulement quand success: false
}

Implication pour Phase 1 : Les nouveaux endpoints IA doivent suivre ce format :

  • POST /api/ai/titles (suggestions de titres)
  • POST /api/ai/search (recherche sémantique)
  • POST /api/ai/refactor (reformulation)
  • POST /api/ai/echo (Memory Echo)

5. Database Schema Extensions

Modèle Note existant :

model Note {
  id                  String    @id
  title               String?
  content             String
  embedding           String?   // DÉJÀ EXISTE pour auto-tagging
  userId              String?
  isPinned            Boolean   @default(false)
  isArchived          Boolean   @default(false)
  // ... autres champs
}

Implication pour Phase 1 : Extensions nécessaires (PAS de réécriture) :

// Extensions proposées pour Phase 1
model Note {
  // ... champs existants

  // Nouveaux champs Phase 1
  autoGenerated       Boolean   @default(false)  // True si titre/tags par IA
  aiConfidence        Int?                        // Score 0-100 si généré par IA
  language            String?                     // Langue détectée: 'fr', 'en', etc.
  lastAiAnalysis      DateTime?                   // Timestamp dernière analyse IA
}

// Nouveau modèle pour feedback utilisateur
model AiFeedback {
  id                String    @id @default(cuid())
  noteId            String
  userId            String?
  feedbackType      String    // thumbs_up, thumbs_down, correction
  feature           String    // title_suggestion, memory_echo, search
  originalContent   String
  correctedContent  String?
  createdAt         DateTime  @default(now())

  note              Note      @relation(fields: [noteId], references: [id], onDelete: Cascade)
  user              User?     @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@index([noteId])
  @@index([userId])
  @@index([feature])
}

6. Data Flow Pattern

Pattern actuel :

User Action
    ↓
Server Action / API Call
    ↓
Prisma Mutation
    ↓
Database Update
    ↓
Revalidate / Refetch
    ↓
UI Update

Implication pour Phase 1 : Les features IA asynchrones (Memory Echo, suggestions en arrière-plan) nécessiteront une variante :

Background Trigger
    ↓
Async Job (Cron ou Server Action)
    ↓
AI Processing (non-blocking)
    ↓
Database Update
    ↓
Revalidate + Optimistic UI
    ↓
Toast Notification / Badge Update

What Must Be Preserved

Constraints Non-Negotiables :

  1. Zero Breaking Changes - Toutes les features existantes doivent continuer à fonctionner
  2. Factory Pattern AI - Conserver lib/ai/providers/ et l'abstraction
  3. API Namespace /api/ai/ - Respecter la structure existante
  4. Response Format - Maintenir {success, data, error}
  5. Component Patterns - Suivre les conventions existantes (controlled components, compound components)
  6. SQLite + Prisma - Pas de migration vers une autre DB pour Phase 1
  7. Authentification NextAuth - Utiliser la session existante pour les endpoints IA

⚠️ Technical Debt à Conserver Temporairement :

  • Labels: Label.userId optional (migration artifact)
  • Note.labels JSON array + Label table (deux approches coexistent)
  • Images: Base64 dans Note.images (considérer migration vers CDN plus tard)

What Can Be Extended

🚀 Extensions pour Phase 1 MVP AI :

1. Nouveaux Services

  • lib/ai/services/title-suggestion.service.ts
  • lib/ai/services/semantic-search.service.ts
  • lib/ai/services/paragraph-refactor.service.ts
  • lib/ai/services/memory-echo.service.ts
  • lib/ai/services/language-detection.service.ts
  • lib/ai/services/embedding.service.ts (extension du code existant)

2. Nouveaux Composants

  • components/ai/ai-suggestion.tsx
  • components/ai/ai-settings-panel.tsx
  • components/ai/memory-echo-notification.tsx
  • components/ai/confidence-badge.tsx
  • components/ai/feedback-buttons.tsx

3. Nouvelles API Routes

  • app/api/ai/titles/route.ts
  • app/api/ai/search/route.ts
  • app/api/ai/refactor/route.ts
  • app/api/ai/echo/route.ts
  • app/api/ai/feedback/route.ts

4. Nouvelles Server Actions

  • app/actions/ai-suggestions.ts
  • app/actions/ai-feedback.ts

5. Extension Settings

  • app/(main)/settings/ai/page.tsx (nouveau)
  • Préférences utilisateur stockées dans SystemConfig ou nouvelle table UserSettings

Integration Points Identified

Point 1: Auto-Tagging Existant

L'auto-tagging est déjà implémenté avec embeddings. Phase 1 doit :

  • Réutiliser le même système d'embeddings
  • Étendre pour la recherche sémantique hybride
  • Partager le même embedding.service.ts

Point 2: Multi-Provider Pattern

OpenAI (cloud) et Ollama (local) sont déjà supportés. Phase 1 doit :

  • Utiliser la même factory pour tous les nouveaux features IA
  • Respecter la configuration utilisateur existante
  • Indicateurs de connexion (local vs cloud) pour Max's use case

Point 3: Component Library

Radix UI + Tailwind + Lucide Icons. Phase 1 doit :

  • Utiliser Radix Dialog pour modaux IA
  • Utiliser Radix Toast pour notifications
  • Suivre les conventions Tailwind existantes
  • Utiliser Lucide Icons pour badges/buttons IA

Point 4: Database Constraints

SQLite avec embeddings en JSON. Phase 1 doit :

  • Stocker les nouveaux embeddings dans le même champ Note.embedding
  • Ajouter des indexes pour les requêtes Memory Echo
  • ⚠️ Surveiller la taille DB avec beaucoup d'embeddings
  • ⚠️ Pas de vector DB séparée pour Phase 1

Development Experience Features

Outils existants :

  • Hot reloading (Next.js dev server)
  • TypeScript 5 (type safety)
  • Playwright (E2E testing)
  • Prisma Migrate (13 migrations déjà appliquées)
  • ESLint + Prettier (probablement configuré)

Implication pour Phase 1 :

  • Maintenir la configuration TypeScript stricte
  • Ajouter des tests Playwright pour les features IA
  • Utiliser Zod pour valider les inputs IA (déjà en place)

Scalability & Performance

Limitations actuelles identifiées :

  • SQLite: Single writer limitation
  • Embeddings JSON: Pas de vector DB optimisée
  • Base64 images: Peut augmenter taille DB rapidement

Implication pour Phase 1 :

  • Acceptable pour MVP (single-user/small teams)
  • ⚠️ Surveillance taille DB requise
  • ⚠️ Performance Memory Echo doit être optimisée (background jobs)
  • 📝 Préparer la migration vers PostgreSQL pour Phase 2+

Security & Privacy

Posture actuelle :

  • NextAuth (password hashing bcrypt)
  • HTTP-only cookies
  • Prisma (SQL injection protection)
  • ⚠️ Pas de rate limiting
  • mcp-server sans auth (OK pour local, pas pour prod)

Implication pour Phase 1 :

  • Utiliser NextAuth session pour tous les endpoints IA
  • Ne jamais exposer les clés API au client
  • Vérifier que Ollama = 0 appels externes (Max's use case)
  • ⚠️ Ajouter rate limiting pour endpoints IA (Léa's admin use case)

Deployment Architecture

Current: Local development avec npm run dev Production Plan: Docker + Docker Compose

Implication pour Phase 1 :

  • Conserver la simplicité (zéro DevOps)
  • Hosting managé (Vercel/Netlify) pour le frontend
  • SQLite file-based (pas d'infrastructure DB séparée)
  • ⚠️ Monitoring/analytics à implémenter pour Léa's use case

Summary

Keep dispose d'une architecture mature et bien documentée :

Fondations solides : Next.js 16 + Prisma + SQLite + Radix UI Factory Pattern AI : Déjà implémenté pour multi-provider 20+ Composants : Architecture cohérente à étendre 13 Migrations : Database schema stable Documentation complète : architecture, data models, components, integration

Pour Phase 1 MVP AI :

🎯 Strategy: Extension brownfield (PAS réécriture) 🎯 Approche: Extensions Prisma schema (PAS breaking changes) 🎯 Pattern: Respecter factory pattern existant + nouveaux services 🎯 Integration: /api/ai/* namespace + composants React conformes 🎯 Performance: Background jobs pour Memory Echo (non-blocking UI) 🎯 Privacy: Ollama local = 0 data exfiltration (vérifiable)

Risque principal : Taille database SQLite avec embeddings Mitigation : Surveillance active + préparation migration PostgreSQL Phase 2

Core Architectural Decisions

Decision Priority Analysis

Critical Decisions (Block Implementation):

  1. Database Schema Extensions - Prisma schema extensions for Phase 1 AI features (Note model extensions + AiFeedback table + MemoryEchoInsight table + UserAISettings table)
  2. Language Detection Strategy - Hybrid approach using TinyLD library (TypeScript native, 62 languages including Persian)

Important Decisions (Shape Architecture):

  1. Memory Echo Architecture - Server Action + Queue in DB pattern with background processing
  2. AI Settings Storage - Dedicated UserAISettings table with typed fields

Deferred Decisions (Post-MVP):

  • Trust Score System (Phase 3) - Schema prepared but UI deferred
  • Advanced Feedback Analytics - Basic feedback collection in Phase 1, advanced analytics Phase 2+

Phase 1 Specific Architectural Decisions

Decision 1: Database Schema Extensions

Status: APPROVED

Rationale: Extend existing Note model and add new models for AI features while maintaining zero breaking changes.

Implementation:

// Extensions to existing Note model
model Note {
  // ... existing fields (title, content, embedding, etc.)

  // Phase 1 AI Extensions
  autoGenerated       Boolean?    @default(false)
  aiProvider          String?                      // 'openai' | 'ollama' | null
  aiConfidence        Int?                         // 0-100 (collected Phase 1, UI Phase 3)
  language            String?                      // ISO 639-1: 'fr', 'en', 'es', 'de', 'fa', etc.
  languageConfidence  Float?                       // 0.0-1.0 (detection confidence)
  lastAiAnalysis      DateTime?                    // timestamp of last AI analysis

  // ... existing indexes
}

// New model for AI feedback collection
model AiFeedback {
  id                String    @id @default(cuid())
  noteId            String
  userId            String?
  feedbackType      String    // 'thumbs_up' | 'thumbs_down' | 'correction'
  feature           String    // 'title_suggestion' | 'memory_echo' | 'semantic_search' | 'paragraph_refactor'
  originalContent   String    // original AI-generated content
  correctedContent  String?   // user-corrected content (if applicable)
  metadata          String?   // JSON: { aiProvider, confidence, model, timestamp, etc. }
  createdAt         DateTime  @default(now())

  note              Note      @relation(fields: [noteId], references: [id], onDelete: Cascade)
  user              User?     @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@index([noteId])
  @@index([userId])
  @@index([feature])
  @@index([createdAt])
}

// New model for Memory Echo insights storage
model MemoryEchoInsight {
  id              String    @id @default(cuid())
  userId          String?
  note1Id         String    // first connected note
  note2Id         String    // second connected note
  similarityScore Float     // cosine similarity score
  insightDate     DateTime  @default(now())
  viewed          Boolean   @default(false)
  feedback        String?   // 'thumbs_up' | 'thumbs_down' | null

  note1           Note      @relation("EchoNote1", fields: [note1Id], references: [id], onDelete: Cascade)
  note2           Note      @relation("EchoNote2", fields: [note2Id], references: [id], onDelete: Cascade)
  user            User?     @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@unique([userId, insightDate])  // max 1 insight per user per day
  @@index([userId, insightDate])
}

// Dedicated table for AI user settings
model UserAISettings {
  userId                String    @id

  // Feature Flags (granular ON/OFF)
  titleSuggestions      Boolean   @default(true)
  semanticSearch        Boolean   @default(true)
  paragraphRefactor     Boolean   @default(true)
  memoryEcho            Boolean   @default(true)

  // Configuration
  memoryEchoFrequency   String    @default("daily")  // 'daily' | 'weekly' | 'custom'
  aiProvider            String    @default("auto")    // 'auto' | 'openai' | 'ollama'

  // Relation
  user                  User      @relation(fields: [userId], references: [id], onDelete: Cascade)

  // Indexes for analytics
  @@index([memoryEcho])
  @@index([aiProvider])
  @@index([memoryEchoFrequency])
}

Cascading Implications:

  • Prisma migration required (npx prisma migrate dev)
  • AI feedback tracking system ready for Phase 3 trust scoring
  • Analytics queries enabled for admin dashboard (Léa's use case)

Affected Components:

  • All AI service layer services
  • /settings/ai page
  • Admin analytics dashboard

Decision 2: Memory Echo Implementation Strategy

Status: APPROVED - Option B (Server Action + Queue in DB)

Rationale: Balance scalability, UX, and simplicity without external dependencies or cron jobs.

Architecture Pattern:

User logs in → Check if insight available today
                    ↓
              If NO insight and < 1 today:
              Trigger background server action (non-blocking)
                    ↓
              Analyze embeddings (cosine similarity > 0.75)
                    ↓
              Store result in MemoryEchoInsight table
                    ↓
              Next user login → Display toast with insight
                    ↓
              User clicks 👍/👎 → Update feedback field

Implementation Details:

Server Action: app/actions/ai-memory-echo.ts

'use server'

import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'

export async function generateMemoryEcho() {
  const session = await auth()
  if (!session?.user) return { success: false }

  // Check if already generated today
  const today = new Date()
  today.setHours(0, 0, 0, 0)

  const existing = await prisma.memoryEchoInsight.findFirst({
    where: {
      userId: session.user.id,
      insightDate: { gte: today }
    }
  })

  if (existing) {
    return { success: true, insight: existing }
  }

  // Generate new insight (async, non-blocking)
  const notes = await prisma.note.findMany({
    where: { userId: session.user.id },
    select: { id: true, embedding: true, content: true }
  })

  // Calculate cosine similarity between all pairs
  const insights = calculateSimilarities(notes)
  const topInsight = insights[0] // highest similarity > 0.75

  if (topInsight && topInsight.score > 0.75) {
    const insight = await prisma.memoryEchoInsight.create({
      data: {
        userId: session.user.id,
        note1Id: topInsight.note1Id,
        note2Id: topInsight.note2Id,
        similarityScore: topInsight.score
      }
    })

    return { success: true, insight }
  }

  return { success: true, insight: null }
}

Performance Characteristics:

  • UI blocking: < 100ms (only checks DB, no computation)
  • Background processing: Runs asynchronously after check
  • Max frequency: 1 insight per user per day (enforced via DB constraint)

Cascading Implications:

  • Requires cosine similarity calculation utility
  • Toast notification component for insight display
  • Feedback collection UI (thumbs up/down buttons)

Decision 3: Language Detection Strategy

Status: APPROVED - Hybrid Approach with TinyLD

Technology Choice: TinyLD (TypeScript-native language detection)

Rationale for Choosing TinyLD:

Criteria TinyLD ELD CLD3 Franc
TypeScript Native Yes No No No
Persian Support Yes Unclear Probable Yes
Bundle Size ~10KB ~30KB ~2MB ~30KB
Speed Fast Fastest Fastest Slow
Languages 62 60 95 300+
Build Complexity Simple Simple Complex (native) Simple

Sources:

Hybrid Strategy:

// lib/ai/services/language-detection.service.ts

import { tinyld } from 'tinyld'
import { generateText } from 'ai'

export class LanguageDetectionService {
  private readonly MIN_WORDS_FOR_AI = 50
  private readonly MIN_CONFIDENCE = 0.7

  async detectLanguage(content: string): Promise<{
    language: string      // 'fr' | 'en' | 'es' | 'de' | 'fa' | 'unknown'
    confidence: number   // 0.0-1.0
    method: 'tinyld' | 'ai' | 'manual'
  }> {
    const wordCount = content.split(/\s+/).length

    // Short notes: TinyLD (fast, TypeScript native)
    if (wordCount < this.MIN_WORDS_FOR_AI) {
      const result = tinyld(content)
      return {
        language: this.mapToISO(result.language),
        confidence: result.confidence || 0.8,
        method: 'tinyld'
      }
    }

    // Long notes: AI for better accuracy
    const response = await generateText({
      model: openai('gpt-4o-mini'), // or ollama/llama3.2
      prompt: `Detect the language of this text. Respond ONLY with ISO 639-1 code (fr, en, es, de, fa):\n\n${content.substring(0, 500)}`
    })

    return {
      language: response.text.toLowerCase().trim(),
      confidence: 0.9,
      method: 'ai'
    }
  }

  private mapToISO(code: string): string {
    const mapping = {
      'fra': 'fr', 'eng': 'en', 'spa': 'es', 'deu': 'de',
      'fas': 'fa', 'pes': 'fa',  // Persian (Farsi)
      'por': 'pt', 'ita': 'it', 'rus': 'ru', 'zho': 'zh'
    }
    return mapping[code] || code.substring(0, 2)
  }
}

Installation:

npm install tinyld

Supported Languages (Phase 1 Focus):

  • French (fr)
  • English (en)
  • Spanish (es)
  • German (de)
  • Persian/Farsi (fa) confirmed support
    • 57 other languages via TinyLD

Performance:

  • TinyLD detection: ~8ms for 50 words
  • AI detection: ~200-500ms (only for notes ≥ 50 words)
  • Overall impact: Negligible for UX

Cascading Implications:

  • Language detection called on note creation/update
  • Results stored in Note.language and Note.languageConfidence
  • Used for multilingual prompt engineering (system prompts in English, user data in local language)

Decision 4: AI Settings Architecture

Status: APPROVED - Dedicated UserAISettings Table

Rationale: Type-safe, analytics-ready, and optimized for queries.

Why Not SystemConfig (JSON blob):

  • No type safety
  • No validation at database level
  • Difficult to query for analytics
  • No indexes on individual fields

Why Dedicated Table:

  • Type-safe - Prisma validates types
  • Analytics-ready - Simple SQL queries for admin dashboard
  • Performance - Indexes on queried fields
  • Clarity - Explicit structure in schema

Schema: (See Decision 1 for full schema)

Example Analytics Queries for Léa:

// How many users have Memory Echo enabled?
const echoEnabled = await prisma.userAISettings.count({
  where: { memoryEcho: true }
})

// AI Provider distribution
const providerDist = await prisma.userAISettings.groupBy({
  by: ['aiProvider'],
  _count: true
})

// Users with selective feature adoption
const selectiveUsers = await prisma.userAISettings.findMany({
  where: {
    titleSuggestions: true,
    semanticSearch: true,
    memoryEcho: true,
    paragraphRefactor: false
  },
  include: { user: { select: { name: true, email: true } } }
})

// Memory Echo frequency preferences
const frequencyStats = await prisma.userAISettings.groupBy({
  by: ['memoryEchoFrequency'],
  where: { memoryEcho: true },
  _count: true
})

Frontend Implementation:

Route: app/(main)/settings/ai/page.tsx

// Settings UI with granular controls
export default function AISettingsPage() {
  const { data: settings } = useAISettings()

  return (
    <div className="space-y-6">
      <h2>AI Settings</h2>

      {/* Feature toggles */}
      <FeatureToggle
        name="titleSuggestions"
        label="Title Suggestions"
        description="Suggest titles for untitled notes after 50+ words"
        checked={settings?.titleSuggestions}
        onChange={(checked) => updateSetting('titleSuggestions', checked)}
      />

      <FeatureToggle
        name="semanticSearch"
        label="Semantic Search"
        description="Find notes by meaning, not just keywords"
        checked={settings?.semanticSearch}
        onChange={(checked) => updateSetting('semanticSearch', checked)}
      />

      {/* Memory Echo with frequency slider */}
      <div className="space-y-2">
        <FeatureToggle
          name="memoryEcho"
          label="Memory Echo"
          description="Daily proactive connections between your notes"
          checked={settings?.memoryEcho}
          onChange={(checked) => updateSetting('memoryEcho', checked)}
        />

        {settings?.memoryEcho && (
          <FrequencySlider
            value={settings.memoryEchoFrequency}
            onChange={(value) => updateSetting('memoryEchoFrequency', value)}
            options={['daily', 'weekly', 'custom']}
          />
        )}
      </div>

      {/* AI Provider selection */}
      <ProviderSelector
        value={settings?.aiProvider}
        onChange={(value) => updateSetting('aiProvider', value)}
        options={[
          { value: 'auto', label: 'Auto (Recommended)', description: 'Ollama when available, OpenAI fallback' },
          { value: 'ollama', label: 'Ollama (Local)', description: '100% private, runs locally' },
          { value: 'openai', label: 'OpenAI (Cloud)', description: 'Most accurate, requires API key' }
        ]}
      />
    </div>
  )
}

Cascading Implications:

  • Server action for updating settings: app/actions/ai-settings.ts
  • Settings validation using Zod
  • Default settings on first user signup
  • Settings sync with AI provider factory

Decision Impact Analysis

Implementation Sequence

Phase 1 - Foundation (Week 1-2):

  1. Prisma schema extensions (all 4 tables)
  2. Database migration
  3. Base AI service layer structure

Phase 2 - Core Features (Week 3-6): 4. Language detection service (TinyLD integration) 5. UserAISettings table + /settings/ai page 6. AI provider factory extensions

Phase 3 - AI Features (Week 7-10): 7. Title suggestions feature 8. Semantic search hybrid 9. Paragraph refactor 10. Memory Echo (background processing)

Phase 4 - Polish & Analytics (Week 11-12): 11. Feedback collection UI 12. Admin analytics dashboard 13. Performance optimization 14. Testing & validation

Cross-Component Dependencies

Critical Path:

Prisma Schema → Migration → AI Services → UI Components → Testing

Parallel Development Opportunities:

  • Language detection service (independent)
  • Settings UI (independent of AI features)
  • Individual AI features (can be developed in parallel)

Integration Points:

  • All AI services → Language detection (for multilingual prompts)
  • All AI features → UserAISettings (for feature flags)
  • Memory Echo → Existing embeddings system
  • Admin dashboard → All AI tables (analytics)

Technology Stack Summary

Selected Libraries & Versions:

Component Technology Version Rationale
Language Detection TinyLD Latest TypeScript native, Persian support, 62 languages, fast
AI SDK Vercel AI SDK 6.0.23 Already integrated, multi-provider support
AI Providers OpenAI + Ollama Latest Factory pattern existing, extend for Phase 1
Database SQLite + Prisma 5.22.0 Existing infrastructure, zero DevOps
Backend Next.js 16 16.1.1 Existing App Router, server actions
Frontend React 19 19.2.3 Existing server components, Radix UI
Already Decided (Existing Stack):
  • Next.js 16.1.1 (App Router)
  • React 19.2.3
  • Prisma 5.22.0 + SQLite
  • NextAuth 5.0.0-beta.30
  • Vercel AI SDK 6.0.23
  • Radix UI components
  • Tailwind CSS 4

No changes to existing stack - pure brownfield extension approach.


Deferred Decisions

Explicitly Deferred to Phase 2/3:

  1. Trust Score UI - Schema fields ready (aiConfidence), but Phase 3 for UI exposure
  2. Advanced Feedback Analytics - Basic collection Phase 1, ML-based analysis Phase 2
  3. PostgreSQL Migration - When SQLite limits reached (planned Phase 2)
  4. Vector DB (Pinecone/Weaviate) - Phase 2 if embeddings size becomes problematic
  5. Real-time Collaboration - Phase 3 (WebSocket/CRDT)
  6. Mobile Apps - Phase 3 (React Native or PWA Phase 2)

Implementation Patterns & Consistency Rules

Pattern Categories Defined

Critical Conflict Points Identified: 38 areas where AI agents could make different choices, documented from existing brownfield codebase

Naming Patterns

Database Naming Conventions:

Table Naming:

  • PascalCase pour les tables Prisma : User, Note, Label, NoteShare
  • Tables de jointure composées : NoteShare (pas Note_Shares)

Column Naming:

  • camelCase pour les colonnes Prisma : userId, isPinned, checkItems, createdAt
  • Clés étrangères : {table}Id format (ex: userId, noteId)
  • Booléens : préfixe is pour les flags (isPinned, isArchived, isMarkdown)
  • Timestamps : suffixe At pour les dates (createdAt, updatedAt, respondedAt)

Index Naming:

  • Prisma gère automatiquement via annotations @@index
  • Exemple : @@index([userId, insightDate])

API Naming Conventions:

REST Endpoint Structure:

  • Plural pour les collections : /api/notes, /api/labels, /api/ai/tags
  • Singular pour les items individuels : /api/notes/[id], /api/labels/[id]
  • Namespace par domaine : /api/ai/* pour AI features, /api/admin/* pour admin

Route Parameter Format:

  • Next.js App Router format : [id], [...nextauth]
  • Query params : camelCase (?archived=true, ?search=query)

Example AI Endpoints to Follow:

/api/ai/titles/route.ts
/api/ai/search/route.ts
/api/ai/refactor/route.ts
/api/ai/echo/route.ts
/api/ai/feedback/route.ts

Code Naming Conventions:

Component Naming:

  • PascalCase pour les composants React : NoteCard, LabelBadge, NoteEditor
  • kebab-case pour les fichiers composants : note-card.tsx, label-badge.tsx
  • UI components dans sous-dossier : components/ui/button.tsx
  • Composants métiers à la racine : components/note-card.tsx

File Naming:

  • kebab-case pour tous les fichiers : note-card.tsx, label-selector.tsx
  • Server actions : notes.ts, auth.ts, profile.ts
  • API routes : route.ts dans chaque dossier endpoint

Function Naming:

  • camelCase pour les fonctions : getNotes, createNote, togglePin
  • Verbs d'abord : get, create, update, delete, toggle
  • Handler functions : handleDelete, handleTogglePin, handleSubmit

Variable Naming:

  • camelCase pour les variables : userId, noteId, isPinned
  • Types/interfaces : PascalCase : Note, CheckItem, NoteCardProps

Structure Patterns

Project Organization:

keep-notes/
├── app/
│   ├── (main)/          # Route groups pour layout
│   ├── (auth)/          # Routes authentifiées
│   ├── actions/         # Server actions (kebab-case filenames)
│   ├── api/             # API routes
│   │   ├── notes/       # REST endpoints
│   │   ├── labels/      # REST endpoints
│   │   ├── ai/          # AI endpoints (NAMESPACE)
│   │   └── admin/       # Admin endpoints
│   └── auth/            # NextAuth routes
├── components/
│   ├── ui/              # Radix UI primitives (réutilisables)
│   └── *.tsx            # Composants métiers (root level)
├── lib/
│   ├── ai/              # AI services et providers
│   ├── prisma.ts        # Prisma client singleton
│   ├── utils.ts         # Utilitaires généraux
│   └── config.ts        # Configuration système
└── prisma/
    └── schema.prisma    # Database schema

Test Organization:

  • Tests co-localisés avec le fichier testé : notes.test.ts à côté de notes.ts
  • Tests E2E dans dossier séparé : keep-notes/tests/e2e/ (Playwright)

Shared Utilities Location:

  • lib/utils.ts - Utilitaires généraux (cn(), calculateRRFK(), etc.)
  • lib/ai/ - Services IA spécifiques
  • lib/types.ts - Types TypeScript partagés

Format Patterns

API Response Formats:

Success Response:

{
  success: true,
  data: any,           // Les données retournées
  // optionnel: message
}

Error Response:

{
  success: false,
  error: string        // Message d'erreur humainement lisible
}

Status Codes:

  • 200 - Success (GET, PUT)
  • 201 - Created (POST)
  • 400 - Bad Request (validation error)
  • 401 - Unauthorized (missing auth)
  • 500 - Server Error

Example from existing code:

// Success
return NextResponse.json({
  success: true,
  data: notes.map(parseNote)
})

// Error
return NextResponse.json(
  { success: false, error: 'Failed to fetch notes' },
  { status: 500 }
)

Data Exchange Formats:

JSON Field Naming:

  • camelCase pour tous les champs JSON : userId, checkItems, isPinned
  • Prisma convertit automatiquement camelCase ↔ snake_case en DB

Boolean Representations:

  • true/false (JavaScript booleans) - PAS 1/0

Null Handling:

  • null pour les champs optionnels vides
  • Empty string "" pour les champs texte requis vides
  • Empty array [] pour les tableaux vides

Array vs Object:

  • Toujours retourner un array pour les collections : data: Note[]
  • Objects pour les items individuels

Communication Patterns

Event Naming Convention:

  • Pas de système d'événements custom - utilisez React state ou server actions

State Update Patterns:

  • Immutable updates avec spread operator : { ...state, newProp: value }
  • useOptimistic pour les mises à jour immédiates : addOptimisticNote({ isPinned: !note.isPinned })
  • useTransition pour les mises à jour non-bloquantes : startTransition(async () => { ... })

Action Naming Conventions:

  • Server actions : verbe + nommage explicite : getNotes, createNote, togglePin, updateColor
  • Handler functions : préfixe handle : handleDelete, handleTogglePin
  • Toggle functions : préfixe toggle : togglePin, toggleArchive

Process Patterns

Error Handling Patterns:

Global Error Handling:

// API Routes
try {
  // ... code
} catch (error) {
  console.error('GET /api/notes error:', error)
  return NextResponse.json(
    { success: false, error: 'Failed to fetch notes' },
    { status: 500 }
  )
}

// Server Actions
try {
  // ... code
} catch (error) {
  console.error('Error creating note:', error)
  throw new Error('Failed to create note')
}

User-Facing Error Messages:

  • Messages clairs et humains : "Failed to fetch notes"
  • PAS de stack traces exposées aux utilisateurs
  • Log en console pour debugging (console.error)

Loading State Patterns:

Loading State Naming:

  • Préfixe is pour les états booléens : isPending, isDeleting, isLoading
  • useTransition hook : const [isPending, startTransition] = useTransition()

Global vs Local Loading:

  • Local loading states (par composant) - PAS de loading state global
  • Optimistic UI pour feedback immédiat : useOptimistic hook

Loading UI Patterns:

  • Spinners ou skeletons pendant chargement
  • Disabled buttons pendant mutations
  • Toast notifications après completion (PAS pendant)

AI-Specific Patterns

AI Service Architecture:

Service Layer Organization:

lib/ai/
├── factory.ts              # Provider factory (EXISTING)
├── providers/              # Provider implementations
│   ├── openai.ts
│   └── ollama.ts
└── services/               # NEW: Feature-specific 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 Component Organization:

components/ai/              # NEW: AI-specific components
├── ai-suggestion.tsx       # Title suggestions UI
├── ai-settings-panel.tsx   # Settings page
├── memory-echo-notification.tsx
├── confidence-badge.tsx
└── feedback-buttons.tsx

API Route Pattern for AI:

// 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"),
})

export async function POST(req: NextRequest) {
  try {
    const body = await req.json()
    const { content } = requestSchema.parse(body)

    // ... AI processing

    return NextResponse.json({
      success: true,
      data: { titles: [...] }
    })
  } catch (error: any) {
    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 }
    )
  }
}

Server Action Pattern for AI:

// keep-notes/app/actions/ai-suggestions.ts
'use server'

import { auth } from '@/auth'
import { TitleSuggestionService } from '@/lib/ai/services/title-suggestion.service'

export async function generateTitleSuggestions(noteId: string) {
  const session = await auth()
  if (!session?.user?.id) throw new Error('Unauthorized')

  try {
    const service = new TitleSuggestionService()
    const titles = await service.generateSuggestions(noteId)

    return { success: true, titles }
  } catch (error) {
    console.error('Error generating titles:', error)
    throw new Error('Failed to generate title suggestions')
  }
}

Enforcement Guidelines

All AI Agents MUST:

  • Suivre les patterns de nommage existants (camelCase pour variables, PascalCase pour composants)
  • Utiliser le format de réponse API existant : {success: true|false, data: any, error: string}
  • Créer des fichiers AI dans les dossiers appropriés : app/api/ai/*, lib/ai/services/*, components/ai/*
  • Utiliser 'use server' pour les server actions et 'use client' pour les composants interactifs
  • Authentification via auth() dans toutes les server actions
  • Validation avec Zod pour les inputs API
  • Error handling avec try/catch et logging via console.error
  • RevalidatePath après mutations dans les server actions
  • TypeScript strict - tous les fichiers doivent avoir des types
  • Importer depuis les alias (@/components/ui/*, @/lib/*, @/app/*)

Pattern Enforcement:

Comment vérifier les patterns:

  1. Linter configuré (ESLint + Prettier)
  2. TypeScript strict mode activé
  3. Review du code avant merge
  4. Tests pour valider les formats d'API

Où documenter les violations de patterns:

  • Commentaires inline avec // FIXME: Pattern violation - should be ...
  • GitHub issues pour les violations systématiques
  • docs/pattern-decisions.md pour les décisions d'exception

Process pour mettre à jour les patterns:

  1. Proposer le changement via GitHub issue
  2. Discuter avec l'équipe
  3. Mettre à jour ce document (architecture.md)
  4. Appliquer le changement à tout le code existant

Pattern Examples

Good Examples:

API Route (Correct):

// app/api/ai/titles/route.ts
import { NextRequest, NextResponse } from 'next/server'
import { z } from 'zod'

const schema = z.object({ content: z.string().min(1) })

export async function POST(req: NextRequest) {
  try {
    const { content } = schema.parse(await req.json())
    const titles = await generateTitles(content)
    return NextResponse.json({ success: true, data: { titles } })
  } catch (error) {
    return NextResponse.json(
      { success: false, error: 'Failed to generate titles' },
      { status: 500 }
    )
  }
}

Server Action (Correct):

// app/actions/ai-suggestions.ts
'use server'

import { auth } from '@/auth'
import { revalidatePath } from 'next/cache'

export async function generateTitleSuggestions(noteId: string) {
  const session = await auth()
  if (!session?.user?.id) throw new Error('Unauthorized')

  const titles = await titleService.generate(noteId)
  revalidatePath('/')
  return { success: true, titles }
}

Component (Correct):

// components/ai/ai-suggestion.tsx
'use client'

import { Card } from '@/components/ui/card'
import { Button } from '@/components/ui/button'
import { useState, useTransition } from 'react'

interface AiSuggestionProps {
  noteId: string
  onAccept: (title: string) => void
}

export function AiSuggestion({ noteId, onAccept }: AiSuggestionProps) {
  const [suggestions, setSuggestions] = useState<string[]>([])
  const [isPending, startTransition] = useTransition()

  // ... component logic
}

Anti-Patterns (À éviter):

MAUVAIS - Response format incorrect:

// NE PAS FAIRE - Format non-standard
return NextResponse.json({ titles: [...] })
// MANQUE: success field, error handling

MAUVAIS - Pas d'authentification:

// NE PAS FAIRE - Server action sans auth
export async function generateTitles(noteId: string) {
  // MANQUE: const session = await auth()
  // ...
}

MAUVAIS - Pas de validation:

// NE PAS FAIRE - API sans validation
export async function POST(req: NextRequest) {
  const { content } = await req.json()
  // MANQUE: Zod validation
}

MAUVAIS - Erreur exposée:

// NE PAS FAIRE - Expose stack trace
return NextResponse.json({
  success: false,
  error: error.message  // Expose internal details
})

MAUVAIS - RevalidatePath oublié:

// NE PAS FAIRE - Mutation sans revalidation
export async function updateNote(id: string, data: any) {
  await prisma.note.update({ where: { id }, data })
  // MANQUE: revalidatePath('/')
}

MAUVAIS - Composant sans 'use client':

// NE PAS FAIRE - Client component sans directive
export function InteractiveComponent() {
  const [count, setCount] = useState(0)
  // MANQUE: 'use client' au début du fichier
}

Quick Reference Card

Pour implémenter une nouvelle feature IA :

  1. API Routeapp/api/ai/{feature}/route.ts

    • Import NextRequest, NextResponse
    • Valider avec Zod
    • Return {success, data} ou {success, error}
    • Log errors avec console.error
  2. Server Actionapp/actions/ai-{feature}.ts

    • 'use server' directive
    • Auth via auth()
    • revalidatePath('/') après mutations
    • Throw Error pour les failures
  3. AI Servicelib/ai/services/{feature}-service.ts

    • Class exportée : export class {Feature}Service
    • Méthodes nommées : async generate(), async process()
    • Error handling complet
  4. Componentcomponents/ai/{feature}.tsx

    • 'use client' directive
    • PascalCase pour composant
    • Props en interface TypeScript
    • useOptimistic pour feedback immédiat
    • Import depuis @/components/ui/*
  5. Typeslib/types.ts

    • Exporter interfaces/types
    • PascalCase pour les types

Project Structure & Boundaries

Complete Project Directory Structure

Keep (Memento) - Phase 1 MVP AI Structure:

Keep/
├── README.md
├── package.json
├── next.config.js
├── tailwind.config.js
├── tsconfig.json
├── .env.local
├── .env.example
├── .gitignore
├── .github/
│   └── workflows/
│       └── ci.yml
│
├── docs/                           # EXISTING - Project documentation
│   ├── index.md                    # Main guide
│   ├── project-overview.md
│   ├── architecture-keep-notes.md
│   ├── architecture-mcp-server.md
│   ├── integration-architecture.md
│   ├── data-models.md
│   ├── component-inventory.md
│   ├── development-guide-keep-notes.md
│   ├── deployment-guide.md
│   ├── api-contracts-keep-notes.md
│   ├── api-contracts-mcp-server.md
│   └── source-tree-analysis.md
│
├── keep-notes/                     # MAIN APPLICATION
│   ├── app/
│   │   ├── (main)/                 # Main routes (authenticated)
│   │   │   ├── layout.tsx
│   │   │   ├── page.tsx            # Dashboard
│   │   │   └── settings/
│   │   │       ├── layout.tsx
│   │   │       ├── page.tsx        # General settings
│   │   │       └── ai/
│   │   │           └── page.tsx    # NEW: AI settings page
│   │   │
│   │   ├── (auth)/                 # Auth routes (public)
│   │   │   ├── login/
│   │   │   └── register/
│   │   │
│   │   ├── actions/                # Server actions
│   │   │   ├── auth.ts             # EXISTING
│   │   │   ├── notes.ts            # EXISTING
│   │   │   ├── profile.ts          # EXISTING
│   │   │   ├── admin.ts            # EXISTING
│   │   │   ├── ai-suggestions.ts   # NEW: Title suggestions
│   │   │   ├── ai-feedback.ts      # NEW: Feedback collection
│   │   │   └── ai-memory-echo.ts   # NEW: Memory Echo
│   │   │
│   │   ├── api/                    # API routes
│   │   │   ├── notes/
│   │   │   │   ├── route.ts        # EXISTING: GET/POST/PUT/DELETE notes
│   │   │   │   └── [id]/route.ts   # EXISTING: Individual note
│   │   │   ├── labels/
│   │   │   │   ├── route.ts        # EXISTING: GET/POST labels
│   │   │   │   └── [id]/route.ts   # EXISTING: Individual label
│   │   │   ├── ai/                 # EXISTING + NEW: AI endpoints
│   │   │   │   ├── tags/
│   │   │   │   │   └── route.ts    # EXISTING: Auto-tagging
│   │   │   │   ├── test/
│   │   │   │   │   └── route.ts    # EXISTING: AI provider test
│   │   │   │   ├── config/
│   │   │   │   │   └── route.ts    # EXISTING: AI config
│   │   │   │   ├── models/
│   │   │   │   │   └── route.ts    # EXISTING: AI models
│   │   │   │   ├── titles/
│   │   │   │   │   └── route.ts    # NEW: Title suggestions
│   │   │   │   ├── search/
│   │   │   │   │   └── route.ts    # NEW: Semantic search
│   │   │   │   ├── refactor/
│   │   │   │   │   └── route.ts    # NEW: Paragraph refactor
│   │   │   │   ├── echo/
│   │   │   │   │   └── route.ts    # NEW: Memory Echo
│   │   │   │   ├── feedback/
│   │   │   │   │   └── route.ts    # NEW: AI feedback
│   │   │   │   └── language/
│   │   │   │       └── route.ts    # NEW: Language detection
│   │   │   ├── upload/
│   │   │   │   └── route.ts        # EXISTING: File upload
│   │   │   ├── admin/
│   │   │   │   ├── randomize-labels/route.ts
│   │   │   │   ├── sync-labels/route.ts
│   │   │   │   ├── embeddings/
│   │   │   │   │   └── validate/route.ts
│   │   │   │   └── ...
│   │   │   ├── auth/
│   │   │   │   └── [...nextauth]/route.ts
│   │   │   └── cron/
│   │   │       └── reminders/route.ts
│   │   │
│   │   ├── auth.ts                 # EXISTING: NextAuth config
│   │   ├── globals.css
│   │   └── layout.tsx
│   │
│   ├── components/
│   │   ├── ui/                      # EXISTING: Radix UI primitives
│   │   │   ├── button.tsx
│   │   │   ├── card.tsx
│   │   │   ├── dialog.tsx
│   │   │   ├── toast.tsx
│   │   │   ├── dropdown-menu.tsx
│   │   │   ├── avatar.tsx
│   │   │   ├── badge.tsx
│   │   │   └── ...
│   │   │
│   │   ├── ai/                     # NEW: AI-specific components
│   │   │   ├── ai-suggestion.tsx           # Title suggestions UI
│   │   │   ├── ai-settings-panel.tsx       # Settings controls
│   │   │   ├── memory-echo-notification.tsx # Insight display
│   │   │   ├── confidence-badge.tsx         # Confidence score badge
│   │   │   ├── feedback-buttons.tsx         # 👍👎 buttons
│   │   │   ├── semantic-search-results.tsx  # Search results with badges
│   │   │   └── paragraph-refactor.tsx       # Refactor UI
│   │   │
│   │   ├── note-card.tsx           # EXISTING
│   │   ├── note-editor.tsx         # EXISTING
│   │   ├── note-actions.tsx       # EXISTING
│   │   ├── label-badge.tsx         # EXISTING
│   │   ├── label-filter.tsx        # EXISTING
│   │   ├── label-manager.tsx       # EXISTING
│   │   ├── ghost-tags.tsx          # EXISTING
│   │   ├── masonry-grid.tsx        # EXISTING
│   │   ├── header.tsx             # EXISTING
│   │   ├── sidebar.tsx            # EXISTING
│   │   └── ... (20+ components)
│   │
│   ├── lib/
│   │   ├── ai/                     # AI Layer
│   │   │   ├── factory.ts                    # EXISTING: Provider factory
│   │   │   ├── providers/                    # EXISTING
│   │   │   │   ├── openai.ts
│   │   │   │   └── ollama.ts
│   │   │   │
│   │   │   └── services/                     # NEW: Feature services
│   │   │       ├── title-suggestion.service.ts
│   │   │       ├── semantic-search.service.ts
│   │   │       ├── paragraph-refactor.service.ts
│   │   │       ├── memory-echo.service.ts
│   │   │       ├── language-detection.service.ts
│   │   │       └── embedding.service.ts       # Extended
│   │   │
│   │   ├── prisma.ts               # EXISTING: Prisma client
│   │   ├── config.ts               # EXISTING: System config
│   │   ├── utils.ts                # EXISTING: Utilities
│   │   └── types.ts                # EXISTING: TypeScript types
│   │
│   ├── prisma/
│   │   ├── schema.prisma           # EXISTING + EXTENDED for Phase 1
│   │   └── migrations/             # EXISTING + NEW migrations
│   │       ├── 013_*
│   │       ├── 014_add_ai_feedback.ts          # NEW
│   │       ├── 015_add_memory_echo_insights.ts # NEW
│   │       └── 016_add_user_ai_settings.ts     # NEW
│   │
│   └── tests/
│       ├── e2e/                    # EXISTING: Playwright E2E tests
│       │   └── ai-features.spec.ts            # NEW: AI E2E tests
│       └── __mocks__/
│
├── mcp-server/                     # EXISTING: MCP server (separate)
│
├── _bmad/                          # BMAD framework (dev workflow)
│   └── ...
│
└── _bmad-output/                   # BMAD artifacts
    ├── analysis/
    │   └── brainstorming-session-2026-01-09.md
    └── planning-artifacts/
        ├── prd-phase1-mvp-ai.md
        ├── ux-design-specification.md
        ├── architecture.md          # THIS DOCUMENT
        └── epics.md                # TO BE RECREATED

Architectural Boundaries

API Boundaries:

External API Boundaries:

Internal Service Boundaries:

  • /api/notes → Note CRUD operations
  • /api/labels → Label CRUD operations
  • /api/ai/* → AI feature operations (namespace isolation)

Authentication Boundaries:

  • All server actions require auth() session check
  • All API routes under /api/ai/* require valid NextAuth session
  • Public routes: /api/auth/*, login/register pages

Data Access Layer Boundaries:

  • Prisma ORM as single data access point
  • No direct SQL queries (use Prisma Query API)
  • Database connection via singleton lib/prisma.ts

Component Boundaries:

Frontend Component Communication:

  • Server Components → Data fetching via Prisma
  • Client Components → Interactions via Server Actions
  • Parent → Child: Props (downward flow)
  • Child → Parent: Callback props (upward flow)

State Management Boundaries:

  • Local state: useState per component
  • Shared state: React Context (User session, Theme, Labels)
  • Server state: React Cache + revalidatePath()
  • Optimistic UI: useOptimistic hook

Service Communication Patterns:

  • Server Actions → Direct function calls from client components
  • API Routes → fetch() from client or server components
  • AI Services → Factory pattern → Provider abstraction

Event-Driven Integration Points:

  • No custom event system (React state preferred)
  • Real-time updates: revalidatePath() + router.refresh()
  • Toast notifications: Radix Toast from Sonner

Service Boundaries:

AI Service Architecture:

lib/ai/services/
    ├── TitleSuggestionService
    ├── SemanticSearchService
    ├── ParagraphRefactorService
    ├── MemoryEchoService
    ├── LanguageDetectionService
    └── EmbeddingService (extension)

All services use:
- getAIProvider() factory
- OpenAI or Ollama provider instances
- Consistent error handling
- Logging via console.error()

Service Integration Patterns:

  • Services are stateless classes
  • Constructor injection of dependencies
  • Methods return promises with consistent error handling
  • No direct database access (via Prisma)

Data Boundaries:

Database Schema Boundaries:

  • Prisma schema.prisma as single source of truth
  • Migrations as version control for schema changes
  • Foreign keys enforce referential integrity
  • Indexes optimize query performance

Data Access Patterns:

  • Read operations: Prisma findMany() with where clauses
  • Write operations: Prisma create/update/delete with transaction support
  • Embeddings: Stored as JSON string in Note.embedding field
  • JSON arrays: checkItems, labels, images stored as JSON strings

Caching Boundaries:

  • React Cache: Server-side data caching
  • No Redis: Phase 1 uses direct database queries
  • Optimistic UI: useOptimistic for immediate feedback
  • Revalidation: revalidatePath() after mutations

External Data Integration Points:

  • OpenAI API: Used via Vercel AI SDK (text + embeddings)
  • Ollama API: Used via Vercel AI SDK (local inference)
  • No external file storage: Images stored as Base64 in DB

Requirements to Structure Mapping

Feature/Epic Mapping:

Epic 1: Title Suggestions

  • API: app/api/ai/titles/route.ts
  • Service: lib/ai/services/title-suggestion.service.ts
  • Server Action: app/actions/ai-suggestions.ts
  • Component: components/ai/ai-suggestion.tsx
  • Database: Uses existing Note table + new AiFeedback table

Epic 2: Semantic Search

  • API: app/api/ai/search/route.ts
  • Service: lib/ai/services/semantic-search.service.ts
  • Component: components/ai/semantic-search-results.tsx
  • Database: Uses existing Note.embedding field

Epic 3: Paragraph Reformulation

  • API: app/api/ai/refactor/route.ts
  • Service: lib/ai/services/paragraph-refactor.service.ts
  • Component: components/ai/paragraph-refactor.tsx
  • Database: Uses Note.content (no schema change)

Epic 4: Memory Echo

  • API: app/api/ai/echo/route.ts
  • Service: lib/ai/services/memory-echo.service.ts
  • Server Action: app/actions/ai-memory-echo.ts
  • Component: components/ai/memory-echo-notification.tsx
  • Database: New MemoryEchoInsight table

Epic 5: AI Settings

  • Page: app/(main)/settings/ai/page.tsx
  • Component: components/ai/ai-settings-panel.tsx
  • Server Action: app/actions/ai-settings.ts
  • Database: New UserAISettings table

Epic 6: Language Detection

  • Service: lib/ai/services/language-detection.service.ts
  • Integration: Called by all AI services
  • Database: Note.language + Note.languageConfidence fields

Cross-Cutting Concerns:

Authentication System

  • Middleware: app/auth.ts (NextAuth configuration)
  • Guards: Server actions check auth() session
  • Session: NextAuth JWT in HTTP-only cookies
  • Components: components/session-provider-wrapper.tsx

Error Handling

  • API Routes: try/catch with {success, error} response
  • Server Actions: try/catch with thrown Error objects
  • Client: Toast notifications for user feedback
  • Logging: console.error() for debugging

AI Provider Abstraction

  • Factory: lib/ai/factory.ts (EXISTING)
  • Providers: lib/ai/providers/openai.ts, lib/ai/providers/ollama.ts (EXISTING)
  • Config: SystemConfig table stores active provider
  • UI: Settings page for provider selection

Feedback Collection

  • API: app/api/ai/feedback/route.ts
  • Database: AiFeedback table (NEW)
  • Components: components/ai/feedback-buttons.tsx (NEW)
  • Analytics: Admin dashboard queries AiFeedback table

Multi-language Support

  • Service: lib/ai/services/language-detection.service.ts (NEW)
  • Storage: Note.language field (NEW)
  • Processing: System prompts in English, user data in local language
  • Supported: FR, EN, ES, DE, FA (Persian) + 57 others via TinyLD

Integration Points

Internal Communication:

Component → Server Action → Database Flow:

Client Component (use client)
    ↓ Server Action call
Server Action ('use server')
    ↓ auth() check
Prisma Query
    ↓ Database operation
revalidatePath()
    ↓ Cache invalidation
Client Component update
    ↓ router.refresh() or optimistic update
UI reflects new state

Component → API Route → AI Service Flow:

Client Component
    ↓ fetch() call
API Route (POST /api/ai/*)
    ↓ Zod validation
AI Service
    ↓ getAIProvider() call
Provider (OpenAI/Ollama)
    ↓ API call
AI Response
    ↓ Process result
NextResponse.json({success, data})
    ↓ JSON response
Client Component
    ↓ Update state
UI reflects AI result

Background Processing Flow (Memory Echo):

User Login
    ↓ Check if insight today
Server Action: generateMemoryEcho()
    ↓ Query MemoryEchoInsight table
If exists → Return cached insight
If none → Background processing:
    ↓ Fetch all user notes
    ↓ Calculate cosine similarities
    ↓ Store top result in MemoryEchoInsight
    ↓ Return insight
Toast Notification display
    ↓ User views insight
User feedback (👍/👎)
    ↓ Update MemoryEchoInsight.feedback

External Integrations:

OpenAI Integration:

  • SDK: Vercel AI SDK 6.0.23
  • Models: gpt-4o-mini (titles, refactor, language), text-embedding-3-small
  • API Key: Stored in SystemConfig (encrypted)
  • Usage: Pay-per-use (cost tracking via AiFeedback metadata)

Ollama Integration:

  • SDK: Vercel AI SDK with Ollama provider
  • Models: llama3.2, mistral, etc.
  • Endpoint: http://localhost:11434 (configurable)
  • Usage: 100% free, 100% local (Max's use case)

TinyLD Integration:

  • Package: tinyld (npm)
  • Purpose: Language detection for notes
  • Supported: 62 languages including Persian
  • Usage: Called by AI services before AI processing

NextAuth Integration:

  • Package: next-auth@5.0.0-beta.30
  • Providers: Credentials (email/password)
  • Session: JWT in HTTP-only cookies
  • Database: Prisma User/Account/Session models

Data Flow:

Note Creation with AI:

User types note content
    ↓ Real-time character count
50+ words reached
    ↓ Trigger detection
Background call to TitleSuggestionService
    ↓ getAIProvider() → OpenAI or Ollama
Generate 3 title suggestions
    ↓ Store in memory
Toast notification appears
    ↓ User sees "Title suggestions available"
User clicks toast or continues typing
    ↓ If user clicks: Show suggestions
User accepts/rejects suggestions
    ↓ If accepted: Update note title via updateNote()
    ↓ Log feedback to AiFeedback

Search Flow (Hybrid):

User types search query
    ↓ Debounce 300ms
searchNotes() called
    ↓ Load query embedding
Semantic Search Service
    ↓ getAIProvider() → OpenAI/Ollama
Generate query embedding
    ↓ Fetch all user notes
Calculate scores:
    ↓ Keyword matching (title/content/labels)
    ↓ Semantic similarity (cosine similarity)
    ↓ Reciprocal Rank Fusion (RRF)
Return ranked results
    ↓ Sort by combined score
Display results with badges:
    ↓ "Exact Match" badge (keyword)
    ↓ "Related" badge (semantic)
User clicks result
    ↓ Open note in editor

Memory Echo Background Flow:

User logs in
    ↓ Check MemoryEchoInsight for today
If insight exists:
    ↓ Show notification immediately
If no insight:
    ↓ Trigger background job
MemoryEchoService
    ↓ Load all user notes with embeddings
Calculate pairwise cosine similarities
    ↓ Filter by threshold (> 0.75)
    ↓ Sort by similarity score
Store top result in MemoryEchoInsight
    ↓ Generate insight (note1Id, note2Id, similarityScore)
Next user login
    ↓ Fetch insight
Display toast with connection details
    ↓ "Note X relates to Note Y (85% match)"
User views connection
    ↓ Mark insight as viewed
User clicks 👍/👎
    ↓ Update MemoryEchoInsight.feedback

File Organization Patterns

Configuration Files:

Root Level:

  • package.json - Dependencies (Next.js 16, React 19, Prisma, etc.)
  • next.config.js - Next.js configuration
  • tailwind.config.js - Tailwind CSS 4 configuration
  • tsconfig.json - TypeScript strict mode
  • .env.local - Local environment variables (gitignored)
  • .env.example - Template for environment variables
  • .gitignore - Git ignore rules
  • README.md - Project documentation

AI-Specific Configuration:

  • lib/config.ts - SystemConfig access (getAIProvider, etc.)
  • Prisma SystemConfig table - Stores AI provider selection
  • Environment variables: OPENAI_API_KEY, OLLAMA_ENDPOINT

Source Organization:

App Router Structure:

  • (main)/ - Main application routes (authenticated)
  • (auth)/ - Authentication routes (public)
  • actions/ - Server actions ('use server' directive)
  • api/ - API routes (REST endpoints)

Component Organization:

  • components/ui/ - Radix UI primitives (reusable, generic)
  • components/ai/ - AI-specific components (feature-specific)
  • components/*.tsx - Domain components (notes, labels, etc.)

Library Organization:

  • lib/ai/services/ - AI feature services
  • lib/ai/providers/ - AI provider implementations
  • lib/ai/factory.ts - Provider factory
  • lib/prisma.ts - Database client
  • lib/utils.ts - General utilities
  • lib/types.ts - TypeScript types

Test Organization:

Unit Tests:

  • Co-located with source files: notes.test.ts alongside notes.ts
  • Focus: Business logic, utilities, services
  • Framework: Jest or Vitest

E2E Tests:

  • tests/e2e/ directory
  • Framework: Playwright (already configured)
  • AI Features: ai-features.spec.ts (NEW)
  • Coverage: Critical user flows (create note, search, etc.)

Asset Organization:

Static Assets:

  • public/ - Static files (favicon, robots.txt, etc.)
  • Images stored as Base64 in Note.images field
  • No external CDN for Phase 1

Documentation Assets:

  • docs/ - Markdown documentation
  • _bmad-output/planning-artifacts/ - Generated artifacts (PRD, UX, Architecture)

Development Workflow Integration

Development Server Structure:

Local Development:

  • Command: npm run dev
  • Port: 3000 (default Next.js)
  • Hot reload: Enabled for all file changes
  • Database: SQLite at prisma/dev.db

AI Development Workflow:

  1. Create feature service in lib/ai/services/
  2. Create API route in app/api/ai/{feature}/route.ts
  3. Create server action in app/actions/ai-{feature}.ts
  4. Create UI component in components/ai/
  5. Add Prisma migration if needed
  6. Test with OpenAI (cloud) or Ollama (local)
  7. Run E2E tests with Playwright

Build Process Structure:

Production Build:

  • Command: npm run build
  • Output: .next/ directory
  • Optimization: Automatic code splitting, tree shaking
  • Database: Prisma migrations run via npx prisma migrate deploy

Environment-Specific Builds:

  • Development: npm run dev (with hot reload)
  • Production: npm run build + npm start
  • Staging: Same as production with staging env vars

Deployment Structure:

Hosting:

  • Frontend: Vercel (recommended) or Netlify
  • Backend: Integrated with frontend (Next.js API routes)
  • Database: SQLite file (Vercel supports via @prisma/adapter-sqlite)

Environment Variables:

OPENAI_API_KEY=sk-...          # OpenAI API key (if using OpenAI)
OLLAMA_ENDPOINT=http://...     # Ollama endpoint (if using Ollama)
DATABASE_URL=file:./dev.db     # SQLite database URL
NEXTAUTH_URL=...                # NextAuth URL
NEXTAUTH_SECRET=...            # NextAuth secret

Deployment Commands:

npx prisma generate             # Generate Prisma client
npx prisma migrate deploy       # Run migrations
npm run build                   # Build production bundle
npm start                       # Start production server

Quick Reference: File Creation Checklist

For Each New AI Feature:

  1. Service Layerlib/ai/services/{feature}-service.ts

    • Create class: export class {Feature}Service
    • Inject AI provider via factory
    • Implement methods with error handling
  2. API Routeapp/api/ai/{feature}/route.ts

    • Import NextRequest, NextResponse
    • Add Zod validation schema
    • Return {success, data} or {success, error}
  3. Server Actionapp/actions/ai-{feature}.ts

    • Add 'use server' directive
    • Auth via auth()
    • revalidatePath('/') after mutations
  4. Componentcomponents/ai/{feature}.tsx

    • Add 'use client' directive
    • Use TypeScript interfaces for props
    • Import from @/components/ui/*
    • Use useOptimistic for feedback
  5. Typeslib/types.ts (if needed)

    • Export interfaces/types
    • Use PascalCase for type names
  6. Teststests/e2e/{feature}.spec.ts

    • E2E tests with Playwright
    • Test critical user flows
  7. Migrationprisma/migrations/{timestamp}_{description}.ts

    • Create if schema changes needed
    • Run npx prisma migrate dev

Architecture Validation

Validation Summary

Date: 2026-01-10 Validator: Winston (Architect Agent) Scope: Phase 1 MVP AI - Complete Architecture Document Status: VALIDATED - READY FOR IMPLEMENTATION


Coherence Validation

Decision Compatibility Analysis

Decision 1 (Database Schema) ↔ Decision 2 (Memory Echo):

  • Status: COHERENT
  • Analysis: MemoryEchoInsight table properly references Note.id with foreign keys and cascade deletion
  • Verification: Schema uses proper Prisma relations
  • Impact: No conflicts, cascading deletes prevent orphaned insights

Decision 1 (Database Schema) ↔ Decision 3 (Language Detection):

  • Status: COHERENT
  • Analysis: Note.language and Note.languageConfidence fields support TinyLD hybrid approach
  • Impact: Language detection results can be stored and queried efficiently

Decision 1 (Database Schema) ↔ Decision 4 (AI Settings):

  • Status: COHERENT
  • Analysis: UserAISettings table provides granular feature flags for all AI services
  • Impact: Clean separation of user preferences from feature implementation

Decision 2 (Memory Echo) ↔ Existing Embeddings System:

  • Status: COHERENT
  • Analysis: Memory Echo reuses existing Note.embedding field (JSON-stored vectors)
  • Impact: Zero duplication, efficient background processing

Decision 3 (Language Detection) ↔ Multi-Provider Pattern:

  • Status: COHERENT
  • Analysis: TinyLD is library-agnostic, no conflicts with OpenAI/Ollama provider factory
  • Impact: Clean separation of concerns, no provider coupling

Decision 4 (AI Settings) ↔ Factory Pattern:

  • Status: COHERENT
  • Analysis: UserAISettings.aiProvider maps to existing factory.getAIProvider()
  • Impact: Seamless integration with existing provider abstraction

Pattern Consistency Validation

Naming Pattern Consistency:

  • Status: CONSISTENT across all documented patterns
  • Database: PascalCase tables, camelCase columns
  • API Routes: /api/ai/* namespace maintained
  • Components: PascalCase components, kebab-case files
  • Services: PascalCase classes, kebab-case files

Response Format Consistency:

  • Status: CONSISTENT with existing brownfield patterns
  • Verification: All API routes return {success: true|false, data: any, error: string}
  • Impact: Zero breaking changes for frontend integration

Error Handling Consistency:

  • Status: CONSISTENT across all proposed code examples
  • API Routes: try/catch with {success, error} response
  • Server Actions: try/catch with thrown Error objects
  • Client: Toast notifications for user feedback

Authentication Consistency:

  • Status: CONSISTENT with existing NextAuth implementation
  • Verification: All server actions include auth() check
  • Impact: Maintains security posture of existing application

Structure Alignment Validation

Directory Structure Alignment:

  • Status: ALIGNED with existing brownfield structure
  • New AI services in lib/ai/services/
  • New AI components in components/ai/
  • New API routes in app/api/ai/*
  • New server actions in app/actions/ai-*.ts

Prisma Schema Alignment:

  • Status: ALIGNED with existing schema patterns
  • All new tables use @default(cuid())
  • All new tables use @relation with proper foreign keys
  • All new tables include @@index
  • All new fields optional (backward compatibility)

Component Architecture Alignment:

  • Status: ALIGNED with React 19 Server Components patterns
  • New AI components use 'use client' directive
  • Components import from @/components/ui/*
  • Components use TypeScript interfaces for props
  • Components use useOptimistic and useTransition hooks

Requirements Coverage Validation

Epic/Feature Coverage

Epic 1: Title Suggestions

  • Database, Service, API, Component, Integration, Feedback: 100% covered

Epic 2: Semantic Search

  • Database, Service, API, Component, Integration, Performance: 100% covered

Epic 3: Paragraph Reformulation

  • Database, Service, API, Component, Integration, Options: 100% covered

Epic 4: Memory Echo

  • Database, Service, API, Server Action, Component, Background, Feedback, Performance: 100% covered

Epic 5: AI Settings

  • Database, Page, Component, Server Action, Features, Providers, Frequency: 100% covered

Epic 6: Language Detection

  • Library, Service, Database, Integration, Strategy: 100% covered

Functional Requirements Coverage

FR1-FR5 (Foundation): ALREADY IMPLEMENTED FR6-FR13 (AI Features): FULLY COVERED by Phase 1 epics FR14-FR16 (Offline PWA): DEFERRED to Phase 2 FR17-FR19 (Configuration): FULLY COVERED by Epic 5


Non-Functional Requirements Coverage

Performance - IA Responsiveness: ADDRESSED Performance - Search Latency: ADDRESSED (< 300ms target) Security - API Key Isolation: ADDRESSED (server-side only) Security - Local-First Privacy: ADDRESSED (Ollama verified) Reliability - Vector Integrity: ADDRESSED (auto-updates) Portability - Efficiency: ADDRESSED (Zero DevOps)


Implementation Readiness Validation

Decision Completeness

Decision 1 (Database Schema): 100% COMPLETE - READY Decision 2 (Memory Echo): 100% COMPLETE - READY Decision 3 (Language Detection): 100% COMPLETE - READY Decision 4 (AI Settings): 100% COMPLETE - READY

Structure Completeness

Directory Structure: 100% COMPLETE - READY API Boundaries: 100% COMPLETE - READY Component Boundaries: 100% COMPLETE - READY Service Boundaries: 100% COMPLETE - READY

Pattern Completeness

Naming Patterns: 100% COMPLETE - READY Format Patterns: 100% COMPLETE - READY Communication Patterns: 100% COMPLETE - READY Error Handling Patterns: 100% COMPLETE - READY AI-Specific Patterns: 100% COMPLETE - READY


Gap Analysis

Critical Gaps: NONE IDENTIFIED

Important Gaps: NONE IDENTIFIED

Nice-to-Have Gaps (Deferred to Phase 2/3):

  1. Trust Score UI (Phase 3)
  2. Advanced Feedback Analytics (Phase 2+)
  3. PostgreSQL Migration (Phase 2)
  4. Vector DB (Phase 2+)
  5. PWA Offline Mode (Phase 2)
  6. Real-Time Collaboration (Phase 3)
  7. Mobile Apps (Phase 3)

Architecture Completeness Checklist

Foundations: [x] Context, [x] Architecture Review, [x] Stack, [x] Concerns Decisions: [x] Schema, [x] Memory Echo, [x] Language Detection, [x] Settings Patterns: [x] Naming, [x] Structure, [x] Format, [x] Communication, [x] Process, [x] AI Structure: [x] Directory Tree, [x] Boundaries, [x] Mapping, [x] Integration, [x] Organization Documentation: [x] Rationale, [x] Implications, [x] Choices, [x] Targets, [x] Security Readiness: [x] Migrations, [x] API Routes, [x] Server Actions, [x] Services, [x] Components, [x] Tests Validation: [x] Coherence, [x] Coverage, [x] Readiness, [x] Gap Analysis


Readiness Assessment

🎯 Readiness Level: PRODUCTION READY

Confidence Score: 95%

Breakdown:

  • Decision Completeness: 100%
  • Structure Completeness: 100%
  • Pattern Completeness: 100%
  • Requirements Coverage: 100%
  • Documentation Quality: 95%
  • Implementation Clarity: 95%

Reasoning for 95%:

  • All architectural decisions made and validated
  • All patterns documented with good/anti-patterns
  • Complete directory structure with epic mappings
  • Comprehensive requirements coverage validated
  • Only minor deduction: Some implementation details will emerge during development (normal for brownfield projects)

Risk Assessment

🎯 Overall Risk Level: LOW

Risk Categories:

  1. Technical Risks: LOW

    • SQLite vector storage acceptable for MVP
    • TinyLD hybrid approach mitigates accuracy risk
    • Memory Echo background processing ensures performance
  2. Integration Risks: LOW

    • Zero-breaking-change approach enforced
    • Provider factory extended, not replaced
    • NextAuth integration unchanged
  3. Performance Risks: LOW

    • In-memory cosine similarity < 300ms achievable
    • Debounce + background processing ensures non-blocking UI
    • Language detection within targets
  4. Scope Risks: LOW

    • Clear PRD scoping, Phase 2/3 features explicitly deferred
    • Medium complexity well-managed through patterns
  5. Security Risks: LOW

    • Server-side only pattern enforced
    • Ollama local-only path verified
    • Existing NextAuth maintained

Implementation Blockers

🎯 Blockers: NONE IDENTIFIED

Critical Path Clear:

  • Prisma migrations can be created immediately
  • AI services can be implemented independently
  • API routes follow existing patterns
  • UI components integrate cleanly

Final Validation Statement

🎯 Architecture Status: VALIDATED AND READY FOR IMPLEMENTATION

This architecture document provides a complete, coherent, and implementation-ready blueprint for Keep (Memento) Phase 1 MVP AI features.

Confidence Level: 95% - PRODUCTION READY

Recommended Next Steps:

  1. Present validation to product owner for approval
  2. Proceed to implementation following recommended sequence
  3. Create epics.md (recreate from PRD + Architecture mapping)
  4. Begin Phase 1 Foundation (Prisma migrations + base service layer)

Validation completed: 2026-01-10 Validated by: Winston (Architect Agent) Architecture version: 1.0.0 - Phase 1 MVP AI

Architecture Completion Summary

Workflow Completion

Architecture Decision Workflow: COMPLETED Total Steps Completed: 8 Date Completed: 2026-01-10 Document Location: _bmad-output/planning-artifacts/architecture.md


Final Architecture Deliverables

📋 Complete Architecture Document (2800+ lines)

  • All architectural decisions documented with specific versions
  • Implementation patterns ensuring AI agent consistency
  • Complete project structure with all files and directories
  • Requirements to architecture mapping (6 epics → files)
  • Validation confirming coherence and completeness (95% confidence)

🏗️ Implementation Ready Foundation

  • 4 architectural decisions made (Database Schema, Memory Echo, Language Detection, AI Settings)
  • 6 implementation patterns defined (Naming, Structure, Format, Communication, Process, AI-Specific)
  • 38 conflict points identified and resolved with consistency rules
  • 100% requirements coverage (6 epics, all FRs, all NFRs)
  • 6 AI services architected (Title Suggestion, Semantic Search, Paragraph Refactor, Memory Echo, Language Detection, Embedding)
  • 6 AI components specified (AiSuggestion, SemanticSearchResults, ParagraphRefactor, MemoryEchoNotification, AiSettingsPanel, FeedbackButtons)
  • 7 new API routes documented (/api/ai/titles, search, refactor, echo, feedback, language + existing tags/test)

📚 AI Agent Implementation Guide

  • Technology stack with verified versions (Next.js 16.1.1, React 19.2.3, Prisma 5.22.0, TinyLD)
  • Consistency rules that prevent implementation conflicts
  • Project structure with clear boundaries (2260-line directory tree)
  • Integration patterns and communication standards
  • Good patterns and anti-patterns documented with examples

Implementation Handoff

For AI Agents: This architecture document is your complete guide for implementing Keep (Memento) Phase 1 MVP AI features. Follow all decisions, patterns, and structures exactly as documented.

First Implementation Priority:

Phase 1 - Foundation (Week 1-2):

# 1. Create Prisma migrations
npx prisma migrate dev --name add_ai_feedback
npx prisma migrate dev --name add_memory_echo_insights
npx prisma migrate dev --name add_user_ai_settings

# 2. Generate Prisma client
npx prisma generate

# 3. Create base AI service layer structure
mkdir -p keep-notes/lib/ai/services
# Create empty service classes for all 6 services

Development Sequence:

  1. Initialize - Create Prisma migrations and base service layer
  2. Infrastructure - Implement LanguageDetectionService (TinyLD integration) + UserAISettings page
  3. AI Features - Implement 4 core features (Title Suggestions, Semantic Search, Paragraph Refactor, Memory Echo)
  4. Polish - Create E2E tests, performance testing, multi-language testing
  5. Deploy - Verify deployment to Vercel/Netlify, monitor performance

Critical Success Factors:

  • Zero breaking changes to existing features
  • Ollama users verify no external API calls (DevTools Network tab)
  • All AI services < 2s response time
  • Semantic search < 300ms for 1000 notes
  • Memory Echo < 100ms UI freeze

Quality Assurance Checklist

Architecture Coherence

  • All decisions work together without conflicts
  • Technology choices are compatible (brownfield extension approach)
  • Patterns support the architectural decisions
  • Structure aligns with all choices (Next.js 16 + React 19 patterns)

Requirements Coverage

  • All functional requirements are supported (FR1-FR19)
  • All non-functional requirements are addressed (Performance, Security, Reliability, Portability)
  • Cross-cutting concerns are handled (Privacy, Multilingual, User Control, Extensibility)
  • Integration points are defined (6 epics mapped to files)

Implementation Readiness

  • Decisions are specific and actionable (4 decisions with implementation details)
  • Patterns prevent agent conflicts (38 conflict points resolved)
  • Structure is complete and unambiguous (2260-line directory tree)
  • Examples are provided for clarity (good patterns + anti-patterns)

Project Success Factors

🎯 Clear Decision Framework Every technology choice was made collaboratively with clear rationale:

  • Database Schema Extensions: Extended Note model + 3 new tables with zero breaking changes
  • Memory Echo: Server Action + Queue in DB pattern (background processing, < 100ms UI freeze)
  • Language Detection: TinyLD hybrid approach (62 languages including Persian verified)
  • AI Settings: Dedicated UserAISettings table (type-safe, analytics-ready)

🔧 Consistency Guarantee Implementation patterns and rules ensure that multiple AI agents will produce compatible, consistent code:

  • Naming: PascalCase tables, camelCase columns, /api/ai/* namespace
  • Format: {success, data, error} response format across all API routes
  • Authentication: auth() check in all server actions
  • Error Handling: try/catch with console.error() logging

📋 Complete Coverage All project requirements are architecturally supported:

  • 6 Epics mapped to specific files and components (100% coverage)
  • 19 Functional Requirements addressed (FR1-FR13 implemented, FR14-FR16 deferred Phase 2, FR17-FR19 implemented)
  • 6 Non-Functional Categories validated (Performance, Security, Reliability, Portability, PWA deferred)

🏗️ Solid Foundation The architectural patterns provide a production-ready foundation:

  • Brownfield Extension: Zero breaking changes, respects existing patterns
  • Multi-Provider Support: OpenAI (cloud) + Ollama (local) via factory pattern
  • Privacy-First: Ollama = 100% local, zero data exfiltration (verifiable in DevTools)
  • Zero DevOps: SQLite file-based, Vercel/Netlify hosting, no dedicated infrastructure

Architecture Document Statistics

Document Size:

  • Total Lines: ~2800 lines
  • Sections: 7 major sections + validation + completion
  • Decisions: 4 architectural decisions with full rationale
  • Patterns: 6 pattern categories with 38 conflict points resolved
  • Structure: 2260-line project directory tree
  • Epic Mapping: 6 epics mapped to 50+ files

Technology Stack:

  • Frontend: Next.js 16.1.1, React 19.2.3, Tailwind CSS 4, Radix UI
  • Backend: Next.js API Routes, Server Actions, Prisma 5.22.0
  • Database: SQLite (better-sqlite3)
  • AI: Vercel AI SDK 6.0.23, OpenAI, Ollama, TinyLD
  • Auth: NextAuth 5.0.0-beta.30

Validation Results:

  • Coherence: PASS (all decisions compatible)
  • Coverage: PASS (100% requirements coverage)
  • Readiness: PASS (95% confidence)
  • Risk: LOW (5 categories assessed)
  • Blockers: NONE

Recommendations for Implementation Phase

For Development Team:

  1. Read the complete architecture document before writing any code
  2. Follow patterns strictly - they prevent conflicts between AI agents
  3. Test with both providers - verify Ollama (local) and OpenAI (cloud) paths
  4. Monitor performance metrics - search latency, AI response times, Memory Echo UI freeze
  5. Collect user feedback - thumbs up/down for quality assessment

For Product Owner (Ramez):

  1. Review validation section - confirm all requirements are addressed
  2. Verify technology choices - TinyLD for Persian, hybrid language detection, Memory Echo approach
  3. Approve implementation sequence - 4 phases (Foundation, Infrastructure, AI Features, Polish)
  4. Create epics.md - recreate from PRD + Architecture mapping (referenced in structure)
  5. Begin story creation - use "create-story" workflow to generate implementation-ready user stories

For AI Agents:

  1. Load architecture.md before implementing any feature
  2. Follow naming patterns - camelCase variables, PascalCase components, kebab-case files
  3. Use response format - {success: true|false, data: any, error: string}
  4. Add 'use server' to all server actions, 'use client' to interactive components
  5. Import from aliases - @/components/ui/, @/lib/, @/app/*
  6. Validate with Zod for all API route inputs
  7. Call auth() in all server actions for authentication
  8. Use revalidatePath('/') after mutations in server actions
  9. Log errors with console.error(), never expose stack traces to users

Architecture Maintenance

When to Update This Document:

  • Major technology version changes (Next.js 17, React 20, etc.)
  • New architectural decisions (Phase 2/3 features like PWA, PostgreSQL)
  • Pattern changes (breaking changes to naming or structure conventions)
  • Performance optimizations (algorithm changes, new caching strategy)

When NOT to Update:

  • Bug fixes (temporary workarounds don't belong in architecture)
  • Minor refactoring (structure remains the same)
  • Implementation details (code belongs in files, not architecture)

Update Process:

  1. Discuss architectural change with team
  2. Document decision with rationale
  3. Update relevant sections
  4. Re-validate coherence
  5. Communicate change to all AI agents

Architecture Status: READY FOR IMPLEMENTATION

Next Phase: Begin implementation using the architectural decisions and patterns documented herein.

Recommended Next Steps:

  1. Review architecture document - _bmad-output/planning-artifacts/architecture.md
  2. Create project context - Optional: project-context.md for AI agent optimization
  3. Recreate epics.md - Map PRD requirements to architecture structure
  4. Generate user stories - Use "create-story" workflow for implementation-ready stories
  5. Begin Phase 1 Foundation - Prisma migrations + base service layer

Architecture workflow completed: 2026-01-10 Architect: Winston (Architect Agent) Architecture version: 1.0.0 - Phase 1 MVP AI Status: VALIDATED AND READY FOR IMPLEMENTATION