# 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)*
