- Add brainstorm feature with collaborative canvas, AI idea generation, live cursors, playback, and export - Add PDF upload/extraction/ingestion pipeline with pgvector document search (RAG) - Add document Q&A overlay with streaming chat and PDF preview - Add note attachments UI with status polling, grid layout, and auto-scroll - Add task extraction AI tool and agent executor improvements - Fix NoteEmbedding missing updatedAt column, re-index 66 notes with 1536-dim embeddings - Fix brainstorm 'Create Note' button: add success toast and redirect to created note - Fix memory echo notification infinite polling - Fix chat route to always include document_search tool - Add brainstorm i18n keys across all 14 locales - Add socket server for real-time brainstorm collaboration - Add hierarchical notebook selector and organize notebook dialog improvements - Add sidebar brainstorm section with session management - Update prisma schema with brainstorm tables, attachments, and document chunks
6.9 KiB
Brainstorm Canvas — Feature Spec for OpenCode
PROJECT CONTEXT
- Stack: Next.js 15 + Prisma + PostgreSQL (pgvector)
- Location: ~/dev/Momento/memento-note/
- Existing models: User, Note, Notebook, Canvas (Excalidraw), Agent, Conversation, Workflow, etc.
- Existing API routes: /app/api/notes, /notebooks, /ai, /canvas, /chat, /agents, etc.
- UI lib: Radix UI + Tailwind CSS + shadcn components
- State: @tanstack/react-query
- Auth: NextAuth (auth.ts, auth.config.ts)
⚠️ CRITICAL RULES
- DO NOT modify existing models or API routes — only ADD new ones
- DO NOT touch prisma/schema.prisma without creating a migration — use
npx prisma migrate dev --name add_brainstorm - Study the existing code patterns before writing new code — match the project conventions
- Look at how existing API routes are structured (e.g., /app/api/notes/route.ts) and follow the same pattern
- Look at how existing components use React Query and follow the same pattern
- Use existing UI components from /components/ui/ (shadcn) — don't install new UI libs
- The project uses TypeScript — maintain strict typing
- Do NOT run npm build — only dev server if needed for testing
FEATURE: Brainstorm Canvas (Wave Brainstorming)
Concept
A temporary workspace for brainstorming ideas using AI-generated "waves" of ideas, displayed as a radial graph. The output feeds back into the notes system.
Data Model — ADD these 2 models to prisma/schema.prisma:
model BrainstormSession {
id String @id @default(cuid())
seedIdea String
sourceNoteId String?
contextNoteIds String? // JSON array of note IDs
exportedNoteId String?
userId String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
ideas BrainstormIdea[]
sourceNote Note? @relation(fields: [sourceNoteId], references: [id])
exportedNote Note? @relation(fields: [exportedNoteId], references: [id])
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([userId])
@@index([userId, createdAt])
}
model BrainstormIdea {
id String @id @default(cuid())
sessionId String
waveNumber Int // 1, 2, or 3
title String
description String
connectionToSeed String?
noveltyScore Int?
parentIdeaId String? // for "dig deeper" sub-brainstorms
convertedToNoteId String?
relatedNoteIds String? // JSON array
status String @default("active") // active, dismissed, converted
positionX Float?
positionY Float?
createdAt DateTime @default(now())
session BrainstormSession @relation(fields: [sessionId], references: [id], onDelete: Cascade)
parentIdea BrainstormIdea? @relation("IdeaTree", fields: [parentIdeaId], references: [id])
children BrainstormIdea[] @relation("IdeaTree")
convertedNote Note? @relation(fields: [convertedToNoteId], references: [id])
@@index([sessionId])
@@index([waveNumber])
@@index([status])
@@index([parentIdeaId])
}
Also add relations to User model:
brainstormSessions BrainstormSession[]
And to Note model — add these two relations:
sourceBrainstormSessions BrainstormSession[] @relation via sourceNoteId
exportedBrainstormSessions BrainstormSession[] @relation via exportedNoteId
convertedBrainstormIdeas BrainstormIdea[] @relation via convertedToNoteId
API Routes — Create /app/api/brainstorm/
-
POST /api/brainstorm/wave — Create new brainstorm session
- Input: { seedIdea, sourceNoteId?, contextNoteIds? }
- Uses existing AI setup (check how /api/ai/ routes call LLM)
- Generates 3 waves of ~3 ideas each (9 total)
- For each idea, does an embedding search to find related notes (check how semantic search works in existing code)
- Saves session + ideas to DB
- Returns: { sessionId, ideas: [...] }
-
POST /api/brainstorm/[sessionId]/expand — Dig deeper on an idea
- Input: { ideaId }
- Uses the clicked idea as new seed
- Generates 3 more waves, linked as children
- Returns new ideas with parentIdeaId set
-
POST /api/brainstorm/[sessionId]/dismiss — Mark idea as not relevant
- Input: { ideaId }
- Sets status = "dismissed"
-
POST /api/brainstorm/[sessionId]/convert — Convert idea to a real Note
- Input: { ideaId }
- Creates a Note with pre-filled content
- Auto-tags: "brainstorm", "idée"
- Links to source note if exists
- Sets idea.status = "converted", idea.convertedToNoteId = newNote.id
- Returns the created note
-
POST /api/brainstorm/[sessionId]/export — Export session as summary note
- Generates a Markdown summary note
- Groups by waves, shows which ideas were converted
- Links to all converted notes
- Returns the created note
-
GET /api/brainstorm — List user's brainstorm sessions
- Returns sessions ordered by date, with idea counts
-
GET /api/brainstorm/[sessionId] — Get full session with ideas
- Returns session + all ideas + their status
Frontend — Canvas Component
Use react-force-graph-2d (install it: npm install react-force-graph-2d).
It's a React wrapper around d3-force — declarative API, same physics engine.
Layout:
- Center node = seed idea (large, white)
- Ring 1 (radius ~150px) = Wave 1 ideas (orange)
- Ring 2 (radius ~300px) = Wave 2 ideas (blue)
- Ring 3 (radius ~450px) = Wave 3 ideas (purple)
- Use d3.forceRadial for ring constraint
- Dismissed nodes = opacity 0.3, smaller
- Converted nodes = green border + icon
- Click node = side panel with details + 3 action buttons
Side Panel (when clicking a node):
- Show: title, description, connection to seed, related notes
- 3 buttons: Dig Deeper, Create Note, Dismiss
- Uses existing shadcn Sheet or Dialog component
Sidebar Integration:
- Add "Brainstorms" section in the existing sidebar
- List sessions with preview (seed idea + count)
- Click to reopen saved canvas state
Entry Points:
- From a note: Brainstorm button in note toolbar/editor
- From sidebar: "+ New Brainstorm" button
AI Prompt for Wave Generation
The LLM prompt should generate 3 waves:
- Wave 1 — Variations: Direct variations/expansions of the seed (sous-aspects, reformulations, variations)
- Wave 2 — Analogies: Cross-domain analogies (autres domaines, biologie, technologie, etc.)
- Wave 3 — Disruptions: Inversions, provocations, ideas that challenge assumptions
Each idea should have:
- title (short)
- description (1-2 sentences)
- connectionToSeed (how it relates to the seed)
- noveltyScore (1-10)
Implementation Order
- Prisma schema + migration
- API routes (start with /wave and /convert)
- Brainstorm canvas component (react-force-graph-2d)
- Sidebar integration
- Note toolbar button
- Export functionality