# Migration Guide: Tags → Notebooks **Project:** Keep - Notebooks & Labels Contextuels **Date:** 2026-01-11 **Status:** READY FOR EXECUTION **Version:** 1.0 --- ## Table of Contents 1. [Overview](#overview) 2. [Pre-Migration Checklist](#pre-migration-checklist) 3. [Migration Process](#migration-process) 4. [Post-Migration Verification](#post-migration-verification) 5. [Rollback Procedure](#rollback-procedure) 6. [Troubleshooting](#troubleshooting) --- ## Overview ### What This Migration Does This migration transforms Keep's **flat tags system** into a **contextual notebooks system**: ✅ **Creates** a new `Notebook` model for organizing notes ✅ **Updates** the `Label` model to belong to notebooks (contextual) ✅ **Updates** the `Note` model to optionally belong to a notebook ✅ **Preserves** all existing data (zero data loss) ✅ **Maintains** backward compatibility (existing features still work) ### What Changes | Before | After | |--------|-------| | Labels are **global** (shared across all notes) | Labels are **contextual** to notebooks | | Labels belong to users | Labels belong to notebooks | | No concept of notebooks | Notes can be organized into notebooks | | All labels in one flat list | Labels isolated per notebook | ### What Doesn't Change - ✅ All existing notes are preserved - ✅ All existing labels are preserved - ✅ Notes remain accessible (in "Notes générales" / Inbox) - ✅ No breaking changes to the UI - ✅ Existing features continue to work --- ## Pre-Migration Checklist ### 1. Backup Database **CRITICAL:** Always backup before migration! ```bash # Navigate to project directory cd D:\dev_new_pc\Keep # Backup SQLite database cp keep-notes/prisma/dev.db keep-notes/prisma/dev.db.backup-$(date +%Y%m%d) # Verify backup exists ls -lh keep-notes/prisma/dev.db.backup-* ``` ### 2. Stop Application Stop the development server to prevent conflicts: ```bash # Stop Next.js dev server if running # Press Ctrl+C in the terminal or run: pkill -f "next dev" ``` ### 3. Review Migration Plan Understand what will happen: - [ ] I have a database backup - [ ] I understand that labels will be moved to a "Labels Migrés" notebook - [ ] I understand that notes will remain in "Notes générales" (Inbox) - [ ] I know how to rollback if needed - [ ] I have 5-10 minutes of downtime scheduled ### 4. Check Prisma Status Ensure Prisma is properly installed: ```bash cd keep-notes npx prisma --version # Should show: 5.22.0 or higher # Generate Prisma client (if not already done) npx prisma generate ``` --- ## Migration Process ### Step 1: Apply Prisma Schema Changes The Prisma schema has already been updated with the new models. Generate and apply the migration: ```bash cd keep-notes # Create migration npx prisma migrate dev --name add_notebooks # This will: # 1. Update the database schema # 2. Create the Notebook table # 3. Add notebookId to Label and Note tables # 4. Create indexes for performance ``` **Expected Output:** ``` ✔ Generated Prisma Client ✔ The following migration has been created and applied from new schema changes: migrations/ └─ 20260111XXXXXX_add_notebooks/ └─ migration.sql Applying migration `20260111XXXXXX_add_notebooks` The following migration(s) have been created and applied from new schema changes: migrations/ └─ 20260111XXXXXX_add_notebooks/ └─ migration.sql ``` ### Step 2: Verify Schema Applied Check that the new tables exist: ```bash # Open SQLite database sqlite3 keep-notes/prisma/dev.db # List tables .tables # You should see: # - Notebook (NEW) # - Label (MODIFIED) # - Note (MODIFIED) # - _NoteToLabel (NEW - junction table) # Exit SQLite .quit ``` ### Step 3: Run Data Migration Script Migrate the existing labels to the default notebook: ```bash # From project root npx tsx scripts/migrate-to-notebooks.ts ``` **Expected Output:** ``` 🚀 Starting migration to notebooks... 📊 Fetching users... ✅ Found 1 user(s) 👤 Processing user: ramez@example.com (user-123) 📁 Creating "Labels Migrés" notebook... ✅ Created notebook: migrate-user-123 🏷️ Migrating labels... ✅ Migrated 15 label(s) ℹ️ User has 47 note(s) (will remain in "Notes générales") ============================================================ ✅ Migration complete! 📊 Summary: Users processed: 1 Notebooks created: 1 Labels migrated: 15 Notes affected: 47 (all remain in Inbox) ✨ Migration successful! 📌 Next steps: 1. Test the application to ensure everything works 2. Users can now organize their notes into notebooks 3. Users can move labels from "Labels Migrés" to new notebooks 4. Consider deleting old labels field from Note model after verification ``` ### Step 4: Verify Migration Success Run the verification queries: ```bash sqlite3 keep-notes/prisma/dev.db # Check notebooks exist SELECT COUNT(*) FROM "Notebook"; # Should be: 1 (or more if multiple users) # Check labels have notebookId SELECT COUNT(*) FROM "Label" WHERE notebookId != ''; # Should match your label count # Check notes are still accessible SELECT COUNT(*) FROM "Note"; # Should match your note count # Verify notes are in Inbox (notebookId is NULL) SELECT COUNT(*) FROM "Note" WHERE notebookId IS NULL; # Should be all notes .quit ``` --- ## Post-Migration Verification ### 1. Start Development Server ```bash cd keep-notes npm run dev ``` ### 2. Test Application Functionality Open `http://localhost:3000` and verify: #### Core Functionality - [ ] Homepage loads without errors - [ ] All notes are visible (in "Notes générales") - [ ] Can create new notes - [ ] Can edit existing notes - [ ] Can delete notes - [ ] Search works #### Labels - [ ] Labels are still visible on notes - [ ] Can add labels to notes - [ ] Can remove labels from notes - [ ] Labels show the correct colors #### Notebooks (NEW) - [ ] "Labels Migrés" notebook exists in sidebar - [ ] Can create a new notebook - [ ] Can rename notebooks - [ ] Can delete notebooks - [ ] Can move notes between notebooks ### 3. Check Console for Errors Open browser DevTools (F12) and check: ``` Console: No errors Network: All requests return 200 ``` ### 4. Verify Data Integrity ```bash sqlite3 keep-notes/prisma/dev.db # No orphaned labels (all labels have notebookId) SELECT COUNT(*) FROM "Label" WHERE notebookId = '' OR notebookId IS NULL; # Should be: 0 # No orphaned notebook references (all notebookIds reference existing notebooks) SELECT COUNT(*) FROM "Note" WHERE notebookId IS NOT NULL AND notebookId NOT IN (SELECT id FROM "Notebook"); # Should be: 0 .quit ``` --- ## Rollback Procedure ### When to Rollback Rollback if you encounter: - ❌ Data corruption - ❌ Application crashes - ❌ Critical functionality broken - ❌ Performance severe degradation ### How to Rollback **Step 1: Stop Application** ```bash pkill -f "next dev" ``` **Step 2: Run Rollback Script** ```bash # DRY RUN FIRST (see what will happen) npx tsx scripts/rollback-notebooks.ts --dry-run # ACTUAL ROLLBACK (requires --confirm) npx tsx scripts/rollback-notebooks.ts --confirm ``` **Step 3: Restore Database Backup** ```bash cd keep-notes/prisma # Find your backup ls -lh dev.db.backup-* # Restore from backup cp dev.db.backup-YYYYMMDD dev.db ``` **Step 4: Restart Application** ```bash cd keep-notes npm run dev ``` ### Verify Rollback Success - [ ] Application starts without errors - [ ] All notes are accessible - [ ] Labels work as before (flat list) - [ ] No notebooks exist in database --- ## Troubleshooting ### Issue: "Prisma migrate fails with foreign key error" **Cause:** Old data conflicts with new schema constraints **Solution:** ```bash # 1. Check for data that violates constraints sqlite3 keep-notes/prisma/dev.db # Find labels without userId SELECT * FROM "Label" WHERE userId IS NULL; # 2. Fix data manually UPDATE "Label" SET userId = 'YOUR_USER_ID' WHERE userId IS NULL; # 3. Re-run migration npx prisma migrate dev --name add_notebooks ``` ### Issue: "Migration script hangs" **Cause:** Large dataset or database lock **Solution:** ```bash # 1. Check database is not locked sqlite3 keep-notes/prisma/dev.db "PRAGMA database_list;" # 2. Kill any hanging processes pkill -f "node" pkill -f "prisma" # 3. Try again npx tsx scripts/migrate-to-notebooks.ts ``` ### Issue: "Labels disappear after migration" **Cause:** Labels migrated to "Labels Migrés" notebook but UI doesn't show them **Solution:** 1. Check that "Labels Migrés" notebook exists 2. Verify labels have correct notebookId 3. Refresh the page (hard refresh: Ctrl+Shift+R) 4. Check browser console for errors ### Issue: "Performance degradation after migration" **Cause:** Missing indexes or inefficient queries **Solution:** ```bash # Rebuild indexes sqlite3 keep-notes/prisma/dev.db "REINDEX;" # Analyze database for query optimization sqlite3 keep-notes/prisma/dev.db "ANALYZE;" # If still slow, check slow queries # Add more indexes if needed ``` ### Issue: "Cannot create notebook - 'notebookId' is required" **Cause:** Label table has NOT NULL constraint on notebookId **Solution:** This is expected behavior. Labels must belong to a notebook. 1. Create a notebook first 2. Then create labels within that notebook --- ## Post-Migration Cleanup (Optional) After verifying everything works, you can clean up deprecated fields: ### 1. Remove Deprecated Label.userId Field **⚠️ ONLY DO THIS AFTER VERIFICATION (1-2 weeks later)** ```prisma // prisma/schema.prisma model Label { id String @id @default(cuid()) name String color String @default("gray") notebookId String notebook Notebook @relation(fields: [notebookId], references: [id], onDelete: Cascade) notes Note[] // REMOVE THESE TWO LINES: // userId String? // user User? @relation(fields: [userId], references: [id], onDelete: Cascade) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@unique([notebookId, name]) @@index([notebookId]) } ``` Then run: ```bash npx prisma migrate dev --name remove_label_user_id ``` ### 2. Remove Deprecated Note.labels Field **⚠️ ONLY DO THIS AFTER MIGRATING ALL LABEL-NOTE RELATIONS** ```prisma // prisma/schema.prisma model Note { // ... other fields // REMOVE THIS LINE: // labels String? // DEPRECATED: Array of label names stored as JSON string // Keep the new relation: labelRelations Label[] } ``` --- ## Summary ### Migration Checklist **Before Migration:** - [ ] Database backed up - [ ] Application stopped - [ ] Migration plan reviewed - [ ] Prisma client generated **During Migration:** - [ ] Prisma schema applied - [ ] Data migration script run - [ ] No errors in console - [ ] Statistics verified **After Migration:** - [ ] Application tested - [ ] All notes accessible - [ ] Labels work correctly - [ ] Notebooks functional - [ ] No performance issues ### Success Metrics - ✅ Zero data loss - ✅ All existing functionality works - ✅ New notebooks feature works - ✅ No errors in console - ✅ Performance acceptable (< 300ms queries) ### Support If you encounter issues not covered in this guide: 1. Check the browser console for errors 2. Check the server logs for stack traces 3. Verify database integrity with SQLite queries 4. Try rollback if critical 5. Contact the development team --- **Document Status:** ✅ COMPLETE **Ready for Migration:** YES **Estimated Downtime:** 5-10 minutes **Rollback Time:** 2-5 minutes --- *Last Updated: 2026-01-11* *Author: Winston (Architect AI Agent)*