# Architecture - keep-notes (Memento Web App) ## Overview Complete system architecture for the Memento web application, a Next.js 16 full-stack application using the App Router architecture pattern. **Architecture Pattern:** Full-stack JAMstack with Server-Side Rendering (SSR) **Framework:** Next.js 16.1.1 (App Router) **Language:** TypeScript 5 **Database:** SQLite via Prisma ORM --- ## Technology Stack ### Frontend | Technology | Version | Purpose | |------------|---------|---------| | React | 19.2.3 | UI library | | Next.js | 16.1.1 | Full-stack framework | | TypeScript | 5.x | Type safety | | Tailwind CSS | 4.x | Styling | | Radix UI | Multiple | Component primitives | | Lucide React | 0.562.0 | Icons | ### Backend (Integrated) | Technology | Version | Purpose | |------------|---------|---------| | Next.js API Routes | Built-in | REST API | | Prisma | 5.22.0 | ORM | | better-sqlite3 | 12.5.0 | SQLite driver | | @libsql/client | 0.15.15 | Alternative DB client | | NextAuth | 5.0.0-beta.30 | Authentication | ### AI/LLM | Technology | Version | Purpose | |------------|---------|---------| | Vercel AI SDK | 6.0.23 | AI integration | | OpenAI Provider | 3.0.7 | GPT models | | Ollama Provider | 1.2.0 | Local models | ### Additional - @dnd-kit (drag and drop) - Muuri (masonry grid) - react-markdown (markdown rendering) - nodemailer (email) - bcryptjs (password hashing) - Zod (validation) - Playwright (testing) --- ## Architecture Pattern: JAMstack with App Router ### Request Flow ``` User Browser ↓ Next.js App Router ↓ ├─────────────────┬─────────────────┐ │ │ │ React Server API Routes Server Actions Components (REST) (Mutations) │ │ │ └─────────────────┴─────────────────┘ ↓ Prisma ORM ↓ SQLite Database ``` ### Rendering Strategy - **Server Components:** Default (faster initial load, SEO friendly) - **Client Components:** Interactive features (drag-drop, forms) - **Streaming:** Progressive rendering with Suspense - **ISR:** Not used (dynamic content) --- ## Directory Structure (App Router) ``` app/ ├── (auth)/ # Auth route group │ ├── layout.tsx # Auth layout │ ├── login/page.tsx # Login page │ ├── register/page.tsx # Register page │ └── [reset flows]/ # Password reset │ ├── (main)/ # Main app route group │ ├── layout.tsx # Main layout │ ├── page.tsx # Home/dashboard │ ├── admin/ # Admin panel │ ├── archive/ # Archived notes │ └── settings/ # User settings │ ├── actions/ # Server actions │ ├── notes.ts # Note mutations │ ├── register.ts # User registration │ └── [other actions] # Additional mutations │ ├── api/ # REST API │ ├── auth/[...nextauth]/ # NextAuth handler │ ├── notes/ # Note CRUD │ ├── labels/ # Label CRUD │ ├── ai/ # AI endpoints │ ├── admin/ # Admin endpoints │ └── [other routes] # Additional endpoints │ ├── globals.css # Global styles └── layout.tsx # Root layout ``` --- ## Component Architecture ### Component Hierarchy ``` layout.tsx (Root) ├── HeaderWrapper │ ├── Header │ │ ├── Logo/Title │ │ └── UserNav │ └── [Auth providers] │ ├── Sidebar (collapsible) │ ├── Navigation │ └── Filters │ └── Page Content └── MasonryGrid └── NoteCard[n] ├── NoteEditor ├── NoteChecklist ├── NoteImages └── NoteActions ``` ### State Management **No Global State Library** (Redux, Zustand, etc.) **State Strategies:** 1. **Server State:** Fetched from API, cached with React Cache 2. **URL State:** Search params, route params 3. **Form State:** Controlled components with useState 4. **Context:** User session, theme preference 5. **Server Actions:** Mutations that update DB **Data Flow:** ``` User Action ↓ Server Action / API Call ↓ Prisma Mutation ↓ Database Update ↓ Revalidate / Refetch ↓ UI Update ``` --- ## API Architecture ### REST Endpoints **Base URL:** `/api` **Authentication:** NextAuth session (most endpoints) **Endpoints:** | Method | Endpoint | Purpose | Auth | |--------|----------|---------|------| | GET | `/api/notes` | List notes | No (currently) | | POST | `/api/notes` | Create note | No (currently) | | PUT | `/api/notes` | Update note | No (currently) | | DELETE | `/api/notes` | Delete note | No (currently) | | GET | `/api/labels` | List labels | Yes | | POST | `/api/labels` | Create label | Yes | | DELETE | `/api/labels/{id}` | Delete label | Yes | | GET/POST | `/api/auth/[...nextauth]` | Auth handler | No (this is auth) | | POST | `/api/ai/tags` | Auto-tagging | TBD | | POST | `/api/upload` | File upload | TBD | | POST | `/api/admin/*` | Admin ops | Yes (admin) | **Response Format:** ```json { "success": true|false, "data": any, "error": string // only when success: false } ``` --- ## Server Actions Architecture **Location:** `app/actions/` **Purpose:** Mutations that bypass REST, direct server-side execution **Examples:** - `notes.ts`: Create, update, delete notes - `register.ts`: User registration - `scrape.ts`: Web scraping for link previews **Benefits:** - Type-safe (from schema) - No API layer needed - Direct database access - Form validation (Zod) **Usage:** ```tsx // Client component import { createNote } from '@/app/actions/notes' function NoteForm() { async function handleSubmit(data) { await createNote(data) // Server action } } ``` --- ## Database Architecture ### ORM: Prisma **Schema Location:** `prisma/schema.prisma` **Migrations:** `prisma/migrations/` (13 migrations) **Database File:** `prisma/dev.db` **Models:** - User (authentication, profile) - Account (OAuth providers) - Session (active sessions) - VerificationToken (email verification) - Note (core data model) - Label (tags/categories) - SystemConfig (key-value store) **Connection:** ```typescript // lib/prisma.ts import { PrismaClient } from '@prisma/client' import { PrismaLibSQL } from '@prisma/adapter-libsql' const prisma = new PrismaClient() ``` **Adapters:** - `@prisma/adapter-better-sqlite3` (primary - local dev) - `@prisma/adapter-libsql` (alternative - Turso cloud) --- ## Authentication Architecture ### NextAuth.js v5 **Configuration:** `auth.config.ts` **Implementation:** `auth.ts` **Providers:** - Credentials (email/password) - OAuth options (Google, GitHub, etc.) **Strategy:** 1. User submits credentials 2. NextAuth validates against database 3. Session created in `Session` table 4. JWT token issued 5. Session stored in HTTP-only cookie **Session Management:** - Server-side sessions in database - HTTP-only cookies for security - Automatic token refresh **Password Security:** - bcryptjs hashing (cost factor: default) - Password reset flow with tokens - Reset token stored in `User.resetToken` **User Roles:** - `USER` (default) - `ADMIN` (elevated permissions) - Role-based access control in API routes --- ## AI Integration Architecture ### Provider Pattern **Location:** `lib/ai/providers/` **Providers:** - OpenAI (`ollama.ts` is misnamed, should be `openai.ts` or separate) - Ollama (`ollama.ts` - local models) **Factory Pattern:** ```typescript // lib/ai/factory.ts export function createProvider(provider: string) { switch (provider) { case 'openai': return new OpenAIProvider() case 'ollama': return new OllamaProvider() } } ``` **Features:** - Auto-tagging (suggest labels for notes) - Semantic search (vector embeddings) - Content summarization (future) - Smart categorization (future) **AI SDK Usage:** ```typescript import { generateText } from 'ai' import { openai } from '@ai-sdk/openai' const response = await generateText({ model: openai('gpt-4'), prompt: note.content }) ``` --- ## Feature Architecture ### Note Management **Data Flow:** 1. User creates note → `NoteInput` component 2. Server action → `app/actions/notes.ts` 3. Prisma create → `Note` table 4. Revalidate → UI updates 5. Real-time → No WebSocket currently **Search:** - Text search: SQL `LIKE` queries (case-insensitive) - Semantic search: Vector embeddings (JSON field) - Filtering: By labels, archived status, pinned status **Organization:** - Pinning: `isPinned` boolean - Archiving: `isArchived` boolean - Ordering: `order` field (drag-drop) - Colors: `color` string - Size: `size` (small, medium, large) ### Label System **Two Approaches:** 1. **Label Table:** `Label` model with user ownership 2. **Note Labels:** JSON array in `Note.labels` **Current State:** Both exist (migration artifact) - `Label` table: User-managed labels - `Note.labels`: JSON array of label names **Future:** Consolidate to one approach ### Reminder System **Fields:** - `reminder`: DateTime for reminder - `isReminderDone`: Completed flag - `reminderRecurrence`: none, daily, weekly, monthly, custom - `reminderLocation`: Location-based (future) **Cron Job:** - Route: `/api/cron/reminders` - Triggered by external cron service - Checks due reminders - Sends notifications (nodemailer) ### Image Handling **Storage Options:** 1. Base64 encoded in `Note.images` JSON array 2. File uploads to `public/uploads/notes/` **Current:** Both supported - Base64 for small images - File uploads for larger images **Future:** Move to CDN (S3, Cloudinary, etc.) --- ## Performance Architecture ### Server-Side Rendering (SSR) - Faster initial page load - SEO friendly - Progressive enhancement ### Code Splitting - Route-based splitting (automatic) - Dynamic imports for heavy components ### Data Fetching - React Cache for deduplication - Server Actions for mutations - Streaming responses ### Database Optimization - Indexed fields (isPinned, isArchived, order, reminder, userId) - Efficient queries with Prisma - Connection pooling (limited in SQLite) --- ## Security Architecture ### Authentication - NextAuth session management - HTTP-only cookies - CSRF protection (NextAuth built-in) - Password hashing (bcrypt) ### Authorization - Role-based access control (USER, ADMIN) - Session validation in API routes - Protected routes (middleware) ### Data Validation - Zod schemas for input validation - TypeScript for type safety - SQL injection prevention (Prisma) - XSS protection (React escaping) ### Future Security Enhancements - Rate limiting - CSRF tokens for forms - Content Security Policy (CSP) - HTTPS enforcement in production --- ## Deployment Architecture ### Current: Local Development ```bash npm run dev # Next.js dev server # Runs on http://localhost:3000 ``` ### Production Deployment (Planned) **Container:** Docker **Orchestration:** Docker Compose **Process:** 1. Build Next.js app: `npm run build` 2. Start production server: `npm start` 3. Serve with Node.js or Docker **Environment Variables:** - `DATABASE_URL`: SQLite file path - `NEXTAUTH_SECRET`: Session secret - `NEXTAUTH_URL`: Application URL - Email configuration (SMTP) - AI provider API keys --- ## Monitoring & Observability ### Current: Basic - Console logging - Playwright test reports - Prisma query logging (development) ### Future Needs - Application monitoring (Sentry, LogRocket) - Error tracking - Performance monitoring - Database query analysis - User analytics --- ## Scalability Considerations ### Current Limitations (SQLite) - Single writer (concurrent writes limited) - File-based storage - No automatic replication - Manual backups needed ### Future Scaling Options 1. **PostgreSQL:** Replace SQLite with Postgres 2. **Connection Pooling:** PgBouncer 3. **Caching:** Redis for sessions and cache 4. **CDN:** CloudFlare, AWS CloudFront 5. **Object Storage:** S3 for images 6. **Load Balancing:** Multiple app instances --- ## Testing Architecture ### E2E Testing: Playwright **Location:** `tests/search-quality.spec.ts` **Coverage:** Search functionality **Commands:** - `npm test` - Run all tests - `npm run test:ui` - UI mode - `npm run test:headed` - Headed mode ### Test Reports **Location:** `playwright-report/index.html` **Results:** `test-results/.last-run.json` --- ## Web Vitals & Performance ### Core Web Vitals - **LCP (Largest Contentful Paint):** Target < 2.5s - **FID (First Input Delay):** Target < 100ms - **CLS (Cumulative Layout Shift):** Target < 0.1 ### Optimizations - Next.js Image optimization - Code splitting - Server components (reduce JS bundle) - Streaming responses - Lazy loading images --- ## PWA Architecture ### Progressive Web App Features **Package:** `@ducanh2912/next-pwa` **Manifest:** `public/manifest.json` **Features:** - Offline support (future) - Install as app (future) - Push notifications (future) - App shortcuts (future) --- ## Integration Points ### MCP Server **Connection:** Database-mediated (shared SQLite) **Location:** `../mcp-server/index.js` **Protocol:** MCP (Model Context Protocol) ### Third-Party Services - **Email:** nodemailer (SMTP) - **AI:** OpenAI API, Ollama (local) - **Future:** N8N workflows via MCP --- ## Development Workflow ### Local Development ```bash cd keep-notes npm install npm run db:generate # Generate Prisma client npm run dev # Start dev server ``` ### Database Migrations ```bash npx prisma migrate dev npx prisma migrate deploy # Production ``` ### Type Checking ```bash npx tsc --noEmit # Type check only ``` --- ## Configuration Files | File | Purpose | |------|---------| | `next.config.ts` | Next.js configuration | | `tsconfig.json` | TypeScript configuration | | `tailwind.config.ts` | Tailwind CSS (if present) | | `playwright.config.ts` | E2E test configuration | | `auth.config.ts` | NextAuth configuration | | `.env` | Environment variables | --- ## Architecture Decision Records ### Why Next.js App Router? - Modern React features (Server Components) - Built-in API routes - File-based routing - Excellent performance - Strong community ### Why Prisma? - Type-safe database access - Excellent migration system - Multiple database support - Great developer experience ### Why SQLite? - Zero configuration - Portable (single file) - Sufficient for single-user/small teams - Easy local development ### Why No Redux/Zustand? - Server Components reduce need for global state - React Context sufficient for app state - Server Actions simplify mutations - Reduced bundle size --- ## Future Architecture Enhancements ### Short Term 1. Add Redis for caching 2. Implement rate limiting 3. Add error boundaries 4. Improve error logging 5. Add request tracing ### Long Term 1. Migrate to PostgreSQL 2. Add read replicas 3. Implement event sourcing 4. Add real-time features (WebSocket) 5. Microservices architecture --- ## Summary The keep-notes application uses a modern JAMstack architecture with: - **Next.js 16** for full-stack development - **App Router** for routing and server components - **Prisma** for type-safe database access - **SQLite** for embedded database - **NextAuth** for authentication - **Radix UI** for accessible components - **Vercel AI SDK** for AI features - **Playwright** for E2E testing This architecture provides a solid foundation for the Memento note-taking application with room for scaling and enhancement.