# Epics & User Stories - Notebooks & Labels Contextuels **Project:** Keep - Notebooks & Labels Contextuels **Date:** 2026-01-11 **Status:** READY FOR DEVELOPMENT **Based on:** PRD, Architecture (validated), Tech Specs (complete) --- ## Table of Contents 1. [Epic 1: Database Migration & Schema](#epic-1-database-migration--schema) 2. [Epic 2: State Management & Server Actions](#epic-2-state-management--server-actions) 3. [Epic 3: Notebooks Sidebar UI](#epic-3-notebooks-sidebar-ui) 4. [Epic 4: Advanced Drag & Drop](#epic-4-advanced-drag--drop) 5. [Epic 5: Contextual AI Features](#epic-5-contextual-ai-features) 6. [Epic 6: Undo/Redo System](#epic-6-undoredo-system) --- ## Epic 1: Database Migration & Schema **ID:** EPIC-1 **Priority:** CRITICAL (Blocker) **Phase:** Foundation (Week 1) **Story Points:** 13 **Dependencies:** None ### Description Migrate the existing flat tags system to a contextual notebooks model without breaking changes. This epic creates the foundation for the entire feature. ### User Stories #### Story 1.1: Create Prisma Schema Migration **ID:** US-1.1 **Points:** 3 **Priority:** Critical **As a** Developer **I want** to extend the Prisma schema with Notebook and Label models **So that** the database supports the new notebooks feature **Acceptance Criteria:** - [ ] `Notebook` model created with fields: id, name, icon, color, order, userId - [ ] `Label` model updated with required `notebookId` field - [ ] `Note` model updated with optional `notebookId` field (null = Inbox) - [ ] Many-to-many relation between Note and Label via junction table - [ ] Cascade delete configured: Notebook → Labels (deleted), Notes (become general) - [ ] Unique constraint on `Label.notebookId + name` - [ ] Indexes created for performance: `Note(userId, notebookId)`, `Notebook(userId, order)` - [ ] Migration script runs successfully: `npx prisma migrate dev` - [ ] Zero data loss (all existing notes preserved) **Technical Notes:** - See tech specs section 5.1 for complete schema - Use `onDelete: SetNull` for Note.notebookId to preserve data - Use `onDelete: Cascade` for Label.notebookId to clean up orphaned labels **Definition of Done:** - Migration tested locally - Migration file committed to Git - No breaking changes to existing queries --- #### Story 1.2: Create Data Migration Script **ID:** US-1.2 **Points:** 5 **Priority:** Critical **As a** Developer **I want** to migrate existing labels to a default "Labels Migrés" notebook **So that** users don't lose any existing data **Acceptance Criteria:** - [ ] Migration script created: `scripts/migrate-to-notebooks.ts` - [ ] Creates "Labels Migrés" notebook for each user - [ ] Assigns all existing labels to this notebook - [ ] Leaves all notes without notebook (they go to Inbox) - [ ] Script logs progress and statistics - [ ] Script can be run multiple times safely (idempotent) - [ ] Rollback script created: `scripts/rollback-notebooks.ts` - [ ] Tested with sample data (100+ notes, 20+ labels) - [ ] Execution time < 5s for 1000 notes **Technical Notes:** - See tech specs section 5.2, 5.3 - Use transactions to prevent partial migration - Add console.log for progress monitoring **Definition of Done:** - Migration runs successfully in development - Rollback tested and working - Documentation written for running migration --- #### Story 1.3: Create Migration Tests **ID:** US-1.3 **Points:** 2 **Priority:** High **As a** Developer **I want** to test the migration script thoroughly **So that** I'm confident no data is lost in production **Acceptance Criteria:** - [ ] Test suite created: `__tests__/migration.test.ts` - [ ] Test: Migration notebook created for each user - [ ] Test: All labels migrated to migration notebook - [ ] Test: No notes moved to notebooks (stay in Inbox) - [ ] Test: Rollback restores original state - [ ] Test: Migration is idempotent (can run twice) - [ ] Test: Handles edge case (user with no labels) - [ ] All tests passing **Definition of Done:** - Test coverage > 90% for migration code - All tests passing consistently - Tests run in CI/CD pipeline --- #### Story 1.4: Document Migration Process **ID:** US-1.4 **Points:** 1 **Priority:** Medium **As a** Developer/Ops **I want** clear documentation for running the migration **So that** anyone can safely deploy the migration **Acceptance Criteria:** - [ ] Migration checklist created (pre-migration steps) - [ ] Migration checklist created (post-migration verification) - [ ] Rollback procedure documented - [ ] Estimated downtime documented (should be < 1min) - [ ] Backup requirements documented - [ ] Troubleshooting guide for common issues **Definition of Done:** - Documentation reviewed by another developer - Documentation tested in staging environment --- ### Epic 1 Summary **Total Stories:** 4 **Total Points:** 13 **Estimated Time:** 1-2 days **Risks:** - Data loss if migration fails (mitigated by rollback) - Performance issues with large datasets (mitigated by batch processing) **Success Metrics:** - Zero data loss - Migration time < 5s for 1000 notes - All existing functionality still works --- ## Epic 2: State Management & Server Actions **ID:** EPIC-2 **Priority:** CRITICAL (Blocker) **Phase:** Foundation (Week 1-2) **Story Points:** 21 **Dependencies:** EPIC-1 (Database schema must exist) ### Description Implement the global state management layer using React Context and create all server actions for notebooks, labels, and note operations. ### User Stories #### Story 2.1: Create NotebooksContext **ID:** US-2.1 **Points:** 5 **Priority:** Critical **As a** Developer **I want** a global context for managing notebooks state **So that** all components can access and update notebooks data **Acceptance Criteria:** - [ ] `NotebooksContext` created with TypeScript interface - [ ] `NotebooksProvider` wraps the application - [ ] Context provides: notebooks, currentNotebook, currentLabels, error, isLoading - [ ] Context provides actions: createNotebook, updateNotebook, deleteNotebook - [ ] Context provides actions: setCurrentNotebook, updateNotebookOrder - [ ] Uses `useOptimistic` for instant UI feedback on create/delete - [ ] Loads initial notebooks data on mount - [ ] Handles errors gracefully with error state - [ ] Context TypeScript types exported for reuse **Technical Notes:** - See tech specs section 1.2 for complete implementation - File location: `app/context/notebooks-context.tsx` - Use `useMemo` and `useCallback` for performance **Definition of Done:** - TypeScript compilation with no errors - Context works with test data - Provider integrated in `app/providers.tsx` --- #### Story 2.2: Create Notebook Server Actions **ID:** US-2.2 **Points:** 5 **Priority:** Critical **As a** Developer **I want** server actions for notebook CRUD operations **So that** the UI can create, update, delete notebooks **Acceptance Criteria:** - [ ] `createNotebook(data)` action created - [ ] Validates user is authenticated - [ ] Calculates next order value automatically - [ ] Returns created notebook - [ ] Calls `revalidatePath('/')` - [ ] `updateNotebook(id, data)` action created - [ ] Validates ownership before updating - [ ] Updates name, icon, or color - [ ] Returns updated notebook - [ ] `deleteNotebook(id)` action created - [ ] Validates ownership before deleting - [ ] Registers undo action before deleting - [ ] Deletes notebook (notes become general) - [ ] Calls `revalidatePath('/')` - [ ] `updateNotebookOrder(ids)` action created - [ ] Updates order for all notebooks in transaction - [ ] Optimized for performance (bulk update) - [ ] All actions have error handling with try/catch - [ ] All actions validate input with Zod schemas **Technical Notes:** - See tech specs section 6.1 - File location: `app/actions/notebooks.ts` - Use Prisma transactions for order update **Definition of Done:** - All actions tested manually with Postman/curl - Error cases tested (unauthorized, not found) - TypeScript types exported for client usage --- #### Story 2.3: Create Label Server Actions **ID:** US-2.3 **Points:** 3 **Priority:** High **As a** Developer **I want** server actions for label CRUD operations **So that** the UI can manage labels within notebooks **Acceptance Criteria:** - [ ] `createLabel(data)` action created - [ ] Validates notebook ownership - [ ] Enforces unique constraint (name + notebookId) - [ ] Returns created label - [ ] `updateLabel(id, data)` action created - [ ] Validates ownership via notebook - [ ] Returns updated label - [ ] `deleteLabel(id)` action created - [ ] Validates ownership before deleting - [ ] Cascade delete removes label from all notes - [ ] Returns success - [ ] All actions validate with Zod schemas - [ ] All actions call `revalidatePath('/')` **Technical Notes:** - Labels belong to notebooks (contextual) - Must verify notebook ownership before operations **Definition of Done:** - All actions tested - Unique constraint enforced (duplicate names rejected) --- #### Story 2.4: Create Note-Notebook Server Actions **ID:** US-2.4 **Points:** 3 **Priority:** High **As a** Developer **I want** server actions to move notes between notebooks **So that** users can organize their notes **Acceptance Criteria:** - [ ] `moveNoteToNotebook(noteId, notebookId)` action created - [ ] Validates note ownership - [ ] Accepts `null` for notebookId (move to Inbox) - [ ] Registers undo action before moving - [ ] Returns updated note - [ ] `attachLabel(noteId, labelId)` action created - [ ] Validates note and label exist - [ ] Creates many-to-many relation - [ ] Prevents duplicate attachments - [ ] `detachLabel(noteId, labelId)` action created - [ ] Validates relation exists - [ ] Removes relation - [ ] All actions call `revalidatePath('/')` **Technical Notes:** - Use Prisma's `connect`/`disconnect` for many-to-many - See tech specs section 6.1 **Definition of Done:** - Tested moving notes between notebooks - Tested attaching/detaching labels - Undo/redo registered correctly --- #### Story 2.5: Create AI Server Actions (Stub) **ID:** US-2.5 **Points:** 2 **Priority:** Medium **As a** Developer **I want** placeholder server actions for AI features **So that** the UI can integrate AI later (Epic 5) **Acceptance Criteria:** - [ ] `suggestNotebook(noteContent)` action created (returns null for now) - [ ] `suggestLabels(noteContent, notebookId)` action created (returns [] for now) - [ ] `organizeInbox(noteIds)` action created (returns empty map for now) - [ ] Actions accept correct parameters - [ ] Actions have correct return types - [ ] Actions marked with TODO comments for Epic 5 **Definition of Done:** - Actions callable from UI - TypeScript types correct - No runtime errors --- #### Story 2.6: Write Tests for Context & Actions **ID:** US-2.6 **Points:** 3 **Priority:** High **As a** Developer **I want** tests for state management and server actions **So that** I'm confident the core logic works **Acceptance Criteria:** - [ ] Context tests created: `__tests__/notebooks-context.test.tsx` - [ ] Test: Loads notebooks on mount - [ ] Test: Creates notebook optimistically - [ ] Test: Updates current notebook - [ ] Test: Derives current labels correctly - [ ] Action tests created: `__tests__/notebooks-actions.test.ts` - [ ] Test: Creates notebook successfully - [ ] Test: Rejects unauthorized access - [ ] Test: Validates input with Zod - [ ] Test: Handles errors gracefully - [ ] Test coverage > 80% - [ ] All tests passing **Definition of Done:** - Tests run in CI/CD - Tests run locally with `npm test` - No flaky tests --- ### Epic 2 Summary **Total Stories:** 6 **Total Points:** 21 **Estimated Time:** 2-3 days **Risks:** - Context performance issues with many notebooks (mitigated by useMemo) - Server action rate limiting (not an issue for single-user) **Success Metrics:** - All CRUD operations working - Optimistic UI feels instant - No TypeScript errors --- ## Epic 3: Notebooks Sidebar UI **ID:** EPIC-3 **Priority:** HIGH **Phase:** Core UI (Week 2-3) **Story Points:** 21 **Dependencies:** EPIC-1, EPIC-2 ### Description Create the sidebar UI for displaying and managing notebooks. This includes the notebook list, labels display, and basic navigation. ### User Stories #### Story 3.1: Create NotebooksSidebar Component **ID:** US-3.1 **Points:** 5 **Priority:** High **As a** User **I want** to see all my notebooks in a sidebar **So that** I can navigate between them **Acceptance Criteria:** - [ ] Sidebar component created: `components/notebooks-sidebar.tsx` - [ ] Displays "Notes générales" (Inbox) at the top - [ ] Displays all notebooks in list - [ ] Shows notebook icon and name - [ ] Shows note count for each notebook - [ ] Highlights currently selected notebook - [ ] Clicking notebook switches current notebook - [ ] Loading state shown while fetching notebooks - [ ] Error state shown if fetch fails - [ ] Empty state shown if no notebooks exist - [ ] Responsive sidebar width (desktop: 256px, mobile: collapsible) **Technical Notes:** - See tech specs section 2.2 - Uses `useNotebooks()` hook - CSS modules for styling **Definition of Done:** - Sidebar displays correctly with test data - Navigation works (clicking notebook updates grid) - Styled to match existing Keep design --- #### Story 3.2: Add Notebook Creation UI **ID:** US-3.2 **Points:** 3 **Priority:** High **As a** User **I want** to create new notebooks from the sidebar **So that** I can organize my notes **Acceptance Criteria:** - [ ] "+ New" button in sidebar header - [ ] Clicking opens modal/dialog - [ ] Modal contains: Name input, Icon picker, Color picker - [ ] Icon picker shows common emojis (📚, 📝, 💼, 🏠, etc.) - [ ] Color picker shows preset colors - [ ] Name required, icon/color optional - [ ] "Create" button creates notebook - [ ] "Cancel" button closes modal - [ ] Modal closes on successful creation - [ ] New notebook appears in sidebar immediately (optimistic) - [ ] Form validation (max 50 chars for name) **Technical Notes:** - Modal component: `components/create-notebook-modal.tsx` - Uses `createNotebookOptimistic` action - Zod validation on client and server **Definition of Done:** - Can create notebook - Notebook appears instantly in sidebar - Modal accessible (keyboard navigation) --- #### Story 3.3: Add Notebook Management Actions **ID:** US-3.3 **Points:** 3 **Priority:** Medium **As a** User **I want** to edit and delete notebooks **So that** I can manage my organization **Acceptance Criteria:** - [ ] Hovering notebook shows "⋯" menu button - [ ] Clicking menu shows: Edit, Delete options - [ ] "Edit" opens modal with current values - [ ] "Edit" modal allows changing name, icon, color - [ ] "Delete" shows confirmation dialog - [ ] Delete dialog explains: "Notes will become general" - [ ] Confirming deletes notebook - [ ] Notes from deleted notebook become general (Inbox) - [ ] Can cancel both edit and delete operations **Technical Notes:** - Context menu or dropdown menu component - Uses `updateNotebook` and `deleteNotebook` actions - Undo toast appears after delete (Epic 6) **Definition of Done:** - Can rename notebook - Can delete notebook (with confirmation) - Notes preserved after deletion --- #### Story 3.4: Display Labels in Sidebar **ID:** US-3.4 **Points:** 3 **Priority:** Medium **As a** User **I want** to see labels for the current notebook **So that** I know what labels are available **Acceptance Criteria:** - [ ] Labels shown under selected notebook in sidebar - [ ] Labels appear when notebook is selected - [ ] Labels appear when hovering notebook - [ ] Each label shown as chip with name and color - [ ] Label count shown (if > 0 notes have label) - [ ] Labels hidden when switching to another notebook - [ ] Animation when showing/hiding labels (slide down) - [ ] Max 10 labels shown (scrollable if more) - [ ] Empty state: "No labels yet" message **Technical Notes:** - Labels derived from `currentLabels` in context - Sub-component: `components/label-chip.tsx` - CSS animation for show/hide **Definition of Done:** - Labels display correctly - Animation smooth - Performance OK with 50+ labels --- #### Story 3.5: Add Label Creation UI **ID:** US-3.5 **Points:** 3 **Priority:** Medium **As a** User **I want** to create labels for my notebook **So that** I can categorize notes within the notebook **Acceptance Criteria:** - [ ] "+ Label" button shown when notebook selected - [ ] Clicking opens compact inline form or modal - [ ] Form contains: Name input, Color picker - [ ] Name required (max 30 chars) - [ ] Color optional (random if not selected) - [ ] "Create" button creates label - [ ] New label appears immediately in sidebar - [ ] Duplicate names rejected (within notebook) - [ ] Form clears after creation **Technical Notes:** - Uses `createLabel` action - Validation: unique constraint on notebookId + name **Definition of Done:** - Can create label - Label appears instantly - Duplicates prevented --- #### Story 3.6: Add Label Management Actions **ID:** US-3.6 **Points:** 2 **Priority:** Low **As a** User **I want** to edit and delete labels **So that** I can fix mistakes or remove unused labels **Acceptance Criteria:** - [ ] Right-click label shows context menu - [ ] Menu options: Edit name, Change color, Delete - [ ] "Edit" opens inline edit or modal - [ ] "Delete" shows confirmation (if label used on notes) - [ ] Delete confirmation shows note count - [ ] Confirming removes label from all notes - [ ] Can cancel operations **Technical Notes:** - Context menu component - Uses `updateLabel` and `deleteLabel` actions - Cascade delete handled by Prisma **Definition of Done:** - Can rename label - Can delete label (with confirmation) - Notes no longer have deleted label --- #### Story 3.7: Implement Note Filtering by Notebook **ID:** US-3.7 **Points:** 5 **Priority:** Critical **As a** User **I want** to see only notes from the selected notebook **So that** I can focus on one topic at a time **Acceptance Criteria:** - [ ] Selecting notebook filters notes in main grid - [ ] Selecting "Notes générales" shows notes without notebook - [ ] Note count updates correctly in sidebar - [ ] Grid updates instantly when switching notebooks - [ ] URL updates with notebook ID (optional, for sharing) - [ ] Page title updates with notebook name - [ ] Breadcrumb shows: Home > Notebook Name - [ ] Can navigate back to "All notes" view - [ ] Pagination works correctly (if implemented) - [ ] Search works within filtered notes **Technical Notes:** - Modify `app/page.tsx` to filter notes by `currentNotebook` - Pass `notebookId` to note query - Update document title **Definition of Done:** - Switching notebooks works smoothly - Note counts accurate - Search respects notebook filter --- #### Story 3.8: Style Sidebar to Match Keep Design **ID:** US-3.8 **Points:** 2 **Priority:** Medium **As a** User **I want** the sidebar to look consistent with Keep's design **So that** the UI feels polished **Acceptance Criteria:** - [ ] Sidebar uses Keep color scheme (grays, blues) - [ ] Fonts match existing UI - [ ] Spacing consistent (8px grid) - [ ] Hover states smooth (150ms transition) - [ ] Active state clearly visible - [ ] Icons align correctly - [ ] Scrollbar styled (custom webkit scrollbar) - [ ] Dark mode supported (if Keep has dark mode) - [ ] Mobile responsive (sidebar collapses) - [ ] Accessibility: ARIA labels, keyboard nav **Definition of Done:** - Design approved by UX review - Matches Keep design system - Accessibility audit passed --- ### Epic 3 Summary **Total Stories:** 8 **Total Points:** 21 **Estimated Time:** 3-4 days **Risks:** - Sidebar performance with many notebooks (mitigated by virtual scrolling if needed) - Mobile UX challenges (sidebar takes too much space) **Success Metrics:** - Sidebar navigation feels smooth - Users can create and manage notebooks - Design consistent with Keep --- ## Epic 4: Advanced Drag & Drop **ID:** EPIC-4 **Priority:** HIGH **Phase:** Drag & Drop (Week 3-4) **Story Points:** 13 **Dependencies:** EPIC-1, EPIC-2, EPIC-3 ### Description Implement Muuri-based drag & drop for reordering notebooks and moving notes between notebooks. This provides the core interaction model for organizing content. ### User Stories #### Story 4.1: Implement Notebook Reordering **ID:** US-4.1 **Points:** 5 **Priority:** High **As a** User **I want** to drag notebooks to reorder them **So that** I can organize my sidebar the way I want **Acceptance Criteria:** - [ ] Notebooks can be dragged in sidebar - [ ] Drag handle appears on hover (visual indicator) - [ ] Other notebooks shift smoothly while dragging - [ ] Placeholder shows where notebook will drop - [ ] Drop updates order immediately (optimistic) - [ ] Order saved to database via `updateNotebookOrder` - [ ] Works on touch devices (mobile) - [ ] Dragging disabled while "Notes générales" (always first) - [ ] Drag feels smooth (60fps) - [ ] Can't drag into invalid positions **Technical Notes:** - See tech specs section 2.2 - Uses Muuri library (same as masonry-grid) - Configuration synced with masonry-grid for consistency - Touch support via `dragHandle` option **Definition of Done:** - Can reorder notebooks smoothly - Order persists after page refresh - Works on mobile --- #### Story 4.2: Add Visual Drag Feedback **ID:** US-4.2 **Points:** 2 **Priority:** Medium **As a** User **I want** visual feedback while dragging **So that** I know what's happening **Acceptance Criteria:** - [ ] Dragged item shows shadow - [ ] Dragged item slightly transparent (0.5 opacity) - [ ] Other items shift smoothly with animation - [ ] Placeholder shows drop target clearly - [ ] Cursor changes to "grabbing" - [ ] Drop target highlighted on hover - [ ] Animation duration: 150-200ms - [ ] No jank or stuttering **Technical Notes:** - Muuri's `dragPlaceholder` config - CSS transitions for smooth animations **Definition of Done:** - Drag feels polished - Animations smooth at 60fps --- #### Story 4.3: Implement Drag Notes to Sidebar **ID:** US-4.3 **Points:** 5 **Priority:** High **As a** User **I want** to drag notes from the grid to notebooks in sidebar **So that** I can quickly organize notes **Acceptance Criteria:** - [ ] Can drag note from masonry grid - [ ] Can drop note onto notebook in sidebar - [ ] Notebook highlights when note dragged over it - [ ] "Notes générales" accepts dropped notes - [ ] Drop moves note to target notebook - [ ] Note disappears from current view (if filtered) - [ ] Success animation/toast confirms move - [ ] Works with multiple selected notes (if selection implemented) - [ ] Drag cancelled if dropped outside valid target - [ ] Undo button appears after move (Epic 6) **Technical Notes:** - Cross-container drag & drop - Detect drop target via `elementFromPoint` - Calls `moveNoteToNotebook` action - See tech specs section 2.2 **Definition of Done:** - Can drag notes to notebooks - Notes move correctly - Visual feedback clear --- #### Story 4.4: Add Context Menu Move Alternative **ID:** US-4.4 **Points:** 3 **Priority:** Medium **As a** User **I want** to move notes via right-click menu **So that** I have an alternative to drag & drop **Acceptance Criteria:** - [ ] Right-clicking note shows context menu - [ ] Menu has "Move to" submenu - [ ] Submenu lists all notebooks - [ ] Submenu has "Notes générales" option - [ ] Clicking notebook moves note there - [ ] Menu closes after selection - [ ] Note disappears from current view - [ ] Works with keyboard (accessibility) - [ ] Menu positioned correctly (no overflow) **Technical Notes:** - Context menu component or native browser menu - Fallback for users who can't use drag & drop **Definition of Done:** - Context menu works - Keyboard accessible - Alternative to drag & drop --- #### Story 4.5: Add Drag Performance Optimizations **ID:** US-4.5 **Points:** 2 **Priority**: Low **As a** Developer **I want** drag & drop to perform well **So that** the UI feels smooth even with many items **Acceptance Criteria:** - [ ] Drag operations run at 60fps - [ ] No layout thrashing during drag - [ ] Uses `requestAnimationFrame` for updates - [ ] Debounces rapid drag events - [ ] Lazy loads heavy components during drag - [ ] Profiled with 100+ notebooks/notes - [ ] No memory leaks after drag operations **Technical Notes:** - Use React.memo for notebook items - Avoid expensive computations during drag - Clean up event listeners **Definition of Done:** - Performance test passed (100 items) - No jank in profiler - Memory stable after extended use --- ### Epic 4 Summary **Total Stories:** 5 **Total Points:** 13 **Estimated Time:** 2-3 days **Risks:** - Cross-container drag & drop complexity (mitigated by existing Muuri knowledge) - Touch device support (mitigated by Muuri's built-in touch support) **Success Metrics:** - Drag & drop feels intuitive - Users can organize notes easily - Performance smooth (60fps) --- ## Epic 5: Contextual AI Features **ID:** EPIC-5 **Priority:** MEDIUM **Phase:** AI Integration (Week 4-5) **Story Points:** 21 **Dependencies:** EPIC-1, EPIC-2, EPIC-3 ### Description Implement the 6 AI features that make notebooks intelligent. All AI features are contextual to the current notebook. ### User Stories #### Story 5.1: Implement Notebook Suggestion (IA1) **ID:** US-5.1 **Points:** 3 **Priority:** High **As a** User **I want** AI to suggest which notebook a note belongs to **So that** I can quickly file notes from my Inbox **Acceptance Criteria:** - [ ] When note created in Inbox, suggestion appears - [ ] Suggestion shown as: "Move to [Notebook Name]?" - [ ] Clicking suggestion moves note immediately - [ ] Dismissing suggestion hides it - [ ] Only suggests when confident (>70%) - [ ] No suggestion if no good match - [ ] Suggestion disappears after 30 seconds - [ ] Works for notes with > 20 words of content - [ ] Can manually trigger via button **Technical Notes:** - Implements `NotebookSuggestionService` (tech specs 4.1) - Uses OpenAI API with optimized prompt - Server action: `suggestNotebookForNote` - Confidence threshold configurable **Definition of Done:** - Suggestions accurate (>70% user acceptance rate) - Performance: < 2s for suggestion - No annoying false positives --- #### Story 5.2: Implement Label Suggestions (IA2) **ID:** US-5.2 **Points:** 3 **Priority:** High **As a** User **I want** AI to suggest labels from my current notebook **So that** I can quickly tag my notes **Acceptance Criteria:** - [ ] When editing note, label suggestions appear - [ ] Suggestions filtered to current notebook's labels - [ ] Shows top 3 suggested labels - [ ] Clicking suggestion adds label to note - [ ] Label appears in note's label list - [ ] Can dismiss suggestions - [ ] Only suggests if notebook has labels - [ ] No suggestions if note too short (< 10 words) - [ ] Suggestions update as note content changes **Technical Notes:** - Implements `ContextualAutoTagService` (tech specs 3.1) - Uses existing auto-tagging infrastructure - Filters suggestions by `notebookId` - Server action: `suggestContextualLabels` **Definition of Done:** - Suggestions relevant (>60% user acceptance) - Performance: < 1s for suggestions - Doesn't annoy users --- #### Story 5.3: Implement Batch Inbox Organization (IA3) **ID:** US-5.3 **Points:** 5 **Priority:** Medium **As a** User **I want** AI to organize multiple notes from my Inbox **So that** I can quickly clean up my Inbox **Acceptance Criteria:** - [ ] "Organize Inbox" button in Inbox view - [ ] Button shows count of notes to organize - [ ] Clicking opens confirmation dialog - [ ] Dialog shows preview of planned organization - [ ] Each note shows suggested notebook - [ ] Can review/edit suggestions before confirming - [ ] Confirming moves all notes in batch - [ ] Progress bar shows organization progress - [ ] Success message shows X notes moved - [ ] Can undo batch operation (Epic 6) **Technical Notes:** - Server action: `organizeInbox` - Batch AI calls (optimized) - Updates all notes in transaction - Uses `NotebookSuggestionService` **Definition of Done:** - Can organize 50 notes in < 30s - Suggestions reasonable (>50% accuracy) - Clear UI for review/edit --- #### Story 5.4: Implement Auto Label Creation (IA4) **ID:** US-5.4 **Points:** 3 **Priority:** Low **As a** User **I want** AI to automatically create labels for recurring themes **So that** I don't have to manually create them **Acceptance Criteria:** - [ ] Background job detects recurring themes - [ ] Creates label if theme appears in 3+ notes - [ ] New label shown in sidebar - [ ] Notification: "Created label: [Name]" - [ ] Can delete auto-created labels - [ ] Only runs if notebook has < 50 labels - [ ] Runs once per day (not real-time) - [ ] Respects unique constraint - [ ] Uses random color for new label **Technical Notes:** - Implements `createLabelIfRecurring` (tech specs 3.1) - Could be cron job or triggered action - Threshold configurable (default: 3 occurrences) **Definition of Done:** - Creates useful labels (>50% kept by users) - Doesn't create spam - Performance: < 10s for 100 notes --- #### Story 5.5: Implement Contextual Semantic Search (IA5) **ID:** US-5.5 **Points:** 5 **Priority:** High **As a** User **I want** semantic search limited to my current notebook **So that** I find relevant notes without noise **Acceptance Criteria:** - [ ] Search box shows notebook context - [ ] Placeholder: "Search in [Notebook Name]" - [ ] Search only returns notes from current notebook - [ ] Search in "Notes générales" searches only Inbox - [ ] Results ranked by semantic similarity - [ ] Shows top 20 results - [ ] Results highlight matching terms - [ ] Search < 300ms for 1000 notes - [ ] Can opt-out to "Search All Notebooks" - [ ] Search respects label filters (if implemented) **Technical Notes:** - Server action: `contextualSemanticSearch` - Filters Prisma query by `notebookId` - Uses existing embedding search - Tech specs section 7 (architecture decision 7) **Definition of Done:** - Search results relevant - Performance acceptable - Context clear in UI --- #### Story 5.6: Implement Notebook Summary (IA6) **ID:** US-5.6 **Points:** 4 **Priority:** Low **As a** User **I want** an AI summary of my notebook **So that** I can quickly understand what's in it **Acceptance Criteria:** - [ ] "Summarize" button in notebook menu - [ ] Clicking generates summary of all notes - [ ] Summary shows key themes (5-10 bullets) - [ ] Summary lists top labels by usage - [ ] Summary shows note count - [ ] Summary generation takes < 5s - [ ] Can copy summary to clipboard - [ ] Summary cached for 1 hour - [ ] Shows loading state while generating - [ ] Error message if generation fails **Technical Notes:** - New service: `NotebookSummaryService` - Aggregates all note content - Uses OpenAI summarization - Could use map-reduce for large notebooks **Definition of Done:** - Summaries useful (>70% satisfaction) - Performance acceptable - Works with notebooks up to 500 notes --- #### Story 5.7: Add AI Settings and Controls **ID:** US-5.7 **Points:** 2 **Priority:** Medium **As a** User **I want** to control AI features **So that** they don't annoy me **Acceptance Criteria:** - [ ] Settings page for AI features - [ ] Toggle for each IA feature (IA1-IA6) - [ ] Toggle for all AI features - [ ] Sensitivity slider (how aggressive suggestions are) - [ ] "Never suggest for this notebook" option - [ ] Clear explanation of each feature - [ ] Privacy note: "AI runs on your content" **Definition of Done:** - Users can disable annoying features - Settings easy to understand - Privacy addressed --- #### Story 5.8: Add AI Performance Monitoring **ID:** US-5.8 **Points:** 2 **Priority:** Low **As a** Developer **I want** to monitor AI feature performance **So that** I can improve them **Acceptance Criteria:** - [ ] Track suggestion acceptance rate - [ ] Track suggestion rejection rate - [ ] Track AI API costs - [ ] Track average response time - [ ] Dashboard shows metrics - [ ] Alerts for unusual patterns - [ ] Export logs for analysis **Definition of Done:** - Metrics collected - Dashboard usable - Costs tracked --- ### Epic 5 Summary **Total Stories:** 8 **Total Points:** 21 **Estimated Time:** 3-4 days **Risks:** - OpenAI API costs (mitigated by caching, limits) - Poor suggestions annoy users (mitigated by confidence thresholds) - Performance issues with large notebooks (mitigated by batching) **Success Metrics:** - >60% user acceptance of suggestions - < 2s average response time - AI features helpful, not annoying --- ## Epic 6: Undo/Redo System **ID:** EPIC-6 **Priority:** MEDIUM **Phase:** Polish (Week 5) **Story Points:** 8 **Dependencies:** EPIC-2, EPIC-3, EPIC-4 ### Description Implement an undo/redo system for destructive actions so users can explore without fear. ### User Stories #### Story 6.1: Implement Undo History **ID:** US-6.1 **Points:** 3 **Priority:** High **As a** Developer **I want** an undo history system **So that** users can undo their actions **Acceptance Criteria:** - [ ] `UndoHistory` class created (tech specs 8.1) - [ ] Stores last 20 actions - [ ] Actions: MOVE_NOTE, DELETE_NOTEBOOK, DELETE_LABEL, REORDER - [ ] Each action has: type, timestamp, undo function, description - [ ] `add(action)` adds to history - [ ] `undo()` executes last action's undo function - [ ] `getLastAction()` returns most recent action - [ ] History persists in memory (session only) - [ ] History cleared on page refresh **Technical Notes:** - Tech specs section 8 (architecture decision 8) - File: `lib/undo-history.ts` - In-memory storage (not persistent) **Definition of Done:** - History class working - Unit tests passing - Integrated with server actions --- #### Story 6.2: Register Undo Actions **ID:** US-6.2 **Points:** 2 **Priority:** High **As a** Developer **I want** destructive actions to register undo **So that** users can undo them **Acceptance Criteria:** - [ ] `moveNoteToNotebook` registers undo - [ ] `deleteNotebook` registers undo - [ ] `deleteLabel` registers undo - [ ] `updateNotebookOrder` registers undo - [ ] Undo function restores previous state - [ ] Undo function calls `revalidatePath('/')` - [ ] Error handling if undo fails - [ ] Only one undo level deep (no redo for MVP) **Technical Notes:** - Modify actions from Epic 2 - Add `undoHistory.add()` calls - Store previous state for rollback **Definition of Done:** - All destructive actions register undo - Undo works correctly - Tested manually --- #### Story 6.3: Create Undo Toast UI **ID:** US-6.3 **Points:** 2 **Priority:** Medium **As a** User **I want** to see an undo notification after actions **So that** I can undo if I made a mistake **Acceptance Criteria:** - [ ] Toast appears after destructive action - [ ] Toast shows action description - [ ] Toast has "Undo" button - [ ] Clicking "Undo" reverts action - [ ] Toast auto-dismisses after 10 seconds - [ ] Hovering toast keeps it visible - [ ] Can manually dismiss toast (× button) - [ ] Toast positioned bottom-right - [ ] Animation smooth (slide in/fade out) - [ ] Only one toast at a time **Technical Notes:** - Component: `components/undo-toast.tsx` - Tech specs section 8.1 - Uses `getLastAction()` from history **Definition of Done:** - Toast appears after actions - Undo button works - UX polished --- #### Story 6.4: Add Undo Keyboard Shortcut **ID:** US-6.4 **Points:** 1 **Priority:** Low **As a** User **I want** to undo with keyboard shortcut **So that** I can quickly fix mistakes **Acceptance Criteria:** - [ ] Ctrl+Z (or Cmd+Z on Mac) triggers undo - [ ] Works globally (not just when toast visible) - [ ] Shows feedback: "Undo: [action description]" - [ ] Does nothing if no history - [ ] Does not interfere with browser undo - [ ] Documented in help **Definition of Done:** - Keyboard shortcut works - Doesn't conflict with browser - Feedback clear --- ### Epic 6 Summary **Total Stories:** 4 **Total Points:** 8 **Estimated Time:** 1-2 days **Risks:** - Undo state management complexity (mitigated by simple in-memory history) - Undo conflicts with concurrent updates (rare in single-user) **Success Metrics:** - Users can undo actions - Undo works correctly - UX feels safe --- ## Overall Summary ### All Epics | Epic | Points | Phase | Dependencies | |------|--------|-------|--------------| | EPIC-1: Database Migration | 13 | Week 1 | None | | EPIC-2: State Management | 21 | Week 1-2 | EPIC-1 | | EPIC-3: Sidebar UI | 21 | Week 2-3 | EPIC-1, EPIC-2 | | EPIC-4: Drag & Drop | 13 | Week 3-4 | EPIC-1, EPIC-2, EPIC-3 | | EPIC-5: AI Features | 21 | Week 4-5 | EPIC-1, EPIC-2, EPIC-3 | | EPIC-6: Undo/Redo | 8 | Week 5 | EPIC-2, EPIC-3, EPIC-4 | **Total Story Points:** 97 **Estimated Time:** 5-6 weeks **Total Stories:** 34 ### Implementation Priority **Must Have (MVP):** - EPIC-1: Database Migration - EPIC-2: State Management & Actions - EPIC-3: Sidebar UI (stories 3.1, 3.2, 3.7) - EPIC-4: Drag & Drop (stories 4.1, 4.3) **Should Have:** - EPIC-3: Remaining stories - EPIC-4: Remaining stories - EPIC-5: AI features (stories 5.1, 5.2, 5.5) - EPIC-6: Undo/Redo (stories 6.1, 6.2, 6.3) **Could Have:** - EPIC-5: Advanced AI (stories 5.3, 5.4, 5.6) - EPIC-6: Keyboard undo **Won't Have (Future):** - Multi-notebook search - Notebook sharing - Note templates ### Risk Register | Risk | Impact | Probability | Mitigation | |------|--------|-------------|------------| | Data loss during migration | CRITICAL | LOW | Backup, rollback, testing | | Poor AI suggestions | MEDIUM | MEDIUM | Confidence thresholds, user feedback | | Performance with 1000+ notes | HIGH | MEDIUM | Indexes, pagination, profiling | | Drag & drop bugs | MEDIUM | LOW | Extensive testing, fallback menus | | OpenAI API costs | MEDIUM | LOW | Caching, rate limits | ### Success Criteria **Technical:** - [ ] All 34 stories completed - [ ] Zero data loss - [ ] < 2s AI response time - [ ] < 300ms search time - [ ] 60fps drag & drop - [ ] 80%+ test coverage **User:** - [ ] Users can create notebooks - [ ] Users can organize notes - [ ] AI suggestions helpful (>60% acceptance) - [ ] Undo works reliably - [ ] Performance acceptable **Business:** - [ ] Migration successful - [ ] No breaking changes - [ ] User adoption > 70% - [ ] Support tickets decreased --- **Document Status:** ✅ COMPLETE **Ready for Sprint Planning:** YES **Total Epics:** 6 **Total Stories:** 34 **Total Story Points:** 97 --- *This Epic & User Story document was created based on validated Architecture and complete Tech Specs.* *Date: 2026-01-11* *Author: Winston (Architect AI Agent)*