Skip to Content
πŸ“š MyStoryFlow Docs β€” Your guide to preserving family stories
System ArchitectureUnified Story Canvas

Unified Story Canvas

Status: Planned (Phase 0) Priority: Critical Estimated Effort: 3-4 weeks Related: Product Roadmap, v1.1 UX Roadmap


Overview

The Unified Story Canvas transforms the story editor into the primary creative workspace, with Voice Recording and AI Conversation as integrated side-panel tools rather than separate pages requiring a conversion step.

Key Principle: The story is the destination; voice and AI are tools to help create it.


Problem Statement

Current Flow (Fragmented)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ CURRENT FLOW β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ /books/[id]/record /books/[id]/conversations β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Voice Record β”‚ β”‚ AI Converse β”‚ β”‚ β”‚ β”‚ Page β”‚ β”‚ Page β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β–Ό β–Ό β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ "Convert to Story" β”‚ β”‚ β”‚ β”‚ (Separate Step) β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β–Ό β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ Story Editor β”‚ β”‚ β”‚ β”‚ /stories/[id]/edit β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Problems with Current Flow

  1. Tool-first, not goal-first - Users start with tools (voice/AI) instead of the goal (story)
  2. Conversion friction - Extra step creates cognitive load and drop-off
  3. Disconnected context - Voice recordings and conversations lack story context
  4. Multiple entry points - Confuses new users about where to start
  5. Hard to iterate - Difficult to combine methods (record, refine with AI, edit)

Target State (Unified Canvas)

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ UNIFIED STORY CANVAS β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ STORY EDITOR (Primary) β”‚ β”‚ β”‚ β”‚ /stories/[id]/edit or /stories/new β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ Story Content Area β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ (TipTap Editor Canvas) β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ [User types, or content appears from β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ voice/AI tools in side panels] β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β”‚ β”‚ 🎀 Voice β”‚ β”‚ πŸ€– AI Chat β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ Panel β”‚ β”‚ Panel β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ (Slide-in) β”‚ β”‚ (Slide-in) β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β€’ Record β”‚ β”‚ β€’ Ask Elena β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β€’ Transcribe β”‚ β”‚ β€’ Get ideas β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β€’ Add to β”‚ β”‚ β€’ Generate β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ Story ─────┼──────────────┼─► Add to β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ Story β”‚ β”‚ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Benefits

  1. Story is the destination - Tools are helpers, not separate workflows
  2. No conversion step - Content flows directly into story
  3. Maintained context - Voice and AI understand what’s already written
  4. Single entry point - Reduces confusion for new users
  5. Easy method combination - Record, then refine with AI, then edit manually

Architecture Decisions

Data Ownership: Dual Access

Recordings and AI conversations are:

  • Linked to a story via story_id foreign key
  • Also visible in global library for browsing all content

This gives users the best of both worlds - content is organized by story but still accessible from a central library.

Content Reuse: 1-to-1 Simple

Each recording or conversation belongs to ONE story at a time.

  • Simple mental model for users
  • Clear data ownership
  • To use content in another story, copy the text
  • Avoids complex many-to-many relationships

The global library (Recordings, AI Conversations) shows:

  • Badges: β€œUsed in: [Story Name]” for linked content
  • Quick Actions: β€œAdd to Story” button for unlinked content
  • Filters: All | Linked | Unlinked

Database Schema

Current State

-- recordings table already has story_id recordings ( id UUID PRIMARY KEY, story_id UUID REFERENCES stories(id), -- βœ“ Already exists book_id UUID, ... ) -- ai_conversations table lacks story_id ai_conversations ( id UUID PRIMARY KEY, book_id UUID, campaign_id UUID, -- story_id is MISSING ... )

Required Migration

-- Add story_id to ai_conversations (matching recordings pattern) ALTER TABLE ai_conversations ADD COLUMN story_id UUID REFERENCES stories(id) ON DELETE SET NULL; CREATE INDEX idx_ai_conversations_story_id ON ai_conversations(story_id);

Data Flow

Scenariostory_id ValueLibrary Badge
Created from Story EditorSet to current story”Used in: [Story]β€œ
Created from standalone pageNULL”Add to Story” button
Orphan contentNULL”Add to Story” button

Implementation Plan

Phase 1: Side Panel Architecture

Extend EditorRightPanel to support new panel types:

// Current types type RightPanelContent = 'comments' | 'ai' | 'grammar' | 'spellcheck' | 'refinement' // Extended types type RightPanelContent = | 'comments' | 'ai' | 'grammar' | 'spellcheck' | 'refinement' | 'voice-record' // NEW: Voice recording panel | 'ai-conversation' // NEW: AI chat panel (enhanced)

Tasks:

  • Add voice-record panel type to EditorRightPanel
  • Add ai-conversation panel type (enhanced from current ai)
  • Create quick-access buttons in toolbar
  • Implement panel slide-in animation
  • Support simultaneous panels on desktop
  • Mobile: bottom sheet or full-screen modal

Phase 2: Voice Recording Panel

Create VoiceRecordPanel.tsx:

interface VoiceRecordingPanelProps { storyId: string bookId?: string onTranscriptReady: (transcript: string) => void onInsertToStory: (content: string, position: 'cursor' | 'end') => void }

Features:

  • Compact recording interface in side panel
  • Real-time transcription display
  • β€œInsert at Cursor” button
  • β€œInsert at End” button
  • Recording history for this story
  • Playback of previous recordings

UX Flow:

  1. User clicks 🎀 in toolbar
  2. Voice panel slides in from right
  3. User records their story segment
  4. Transcription appears in panel
  5. User clicks β€œAdd to Story” β†’ text inserted at cursor
  6. Panel stays open for additional recordings

Phase 3: AI Conversation Panel

Create AIConversationPanel.tsx:

interface AIConversationPanelProps { storyId: string bookId?: string storyContent: string // Current editor content for context storyTitle: string onInsertToStory: (content: string, position: 'cursor' | 'end' | 'replace') => void onResumeConversation?: (conversationId: string) => void }

Features:

  • Chat interface in side panel
  • Story-aware context (AI knows what’s already written)
  • Quick actions: β€œContinue this story”, β€œAdd more detail”, β€œSuggest memories”
  • β€œInsert Response” button
  • Conversation history for this story
  • Resume previous conversations

UX Flow:

  1. User clicks πŸ€– in toolbar
  2. AI panel slides in from right
  3. User asks: β€œWhat else might grandma remember about the farm?”
  4. AI responds with suggestions based on story context
  5. User clicks β€œInsert” on a suggestion β†’ added to story
  6. User can continue conversation or close panel

Phase 4: Empty State Enhancement

When story is empty, show creation options:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ How would you like to start? β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ ✍️ β”‚ β”‚ 🎀 β”‚ β”‚ πŸ€– β”‚ β”‚ β”‚ β”‚ Just Write β”‚ β”‚ Record Your β”‚ β”‚ Chat with β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ Voice β”‚ β”‚ Elena β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ All methods can be combined at any time β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Phase 5: Library Enhancement

Update library views to show story linkage:

Recordings Page:

  • Badge: β€œUsed in: [Story Name]” with link
  • Quick action: β€œAdd to Story” dropdown for unlinked
  • Filter tabs: All | Linked | Unlinked

AI Conversations Page:

  • Same badge and quick action pattern
  • Show which story each conversation belongs to

Content Insertion Logic

Handle inserting voice/AI content into TipTap editor:

const insertContent = (content: string, position: 'cursor' | 'end' | 'replace') => { if (!editor) return switch (position) { case 'cursor': editor.chain().focus().insertContent(content).run() break case 'end': editor.chain() .focus() .setTextSelection(editor.state.doc.content.size) .insertContent('\n\n' + content) .run() break case 'replace': editor.chain().focus().deleteSelection().insertContent(content).run() break } }

Critical Files

CategoryFile Path
Databasesupabase/migrations/xxx_add_story_id_to_ai_conversations.sql
Editor Shellapps/web-app/app/components/editor/EnhancedEditorShell.tsx
Right Panelapps/web-app/app/components/editor/EditorRightPanel.tsx
Voice Panelapps/web-app/app/components/editor/panels/VoiceRecordPanel.tsx (new)
AI Panelapps/web-app/app/components/editor/panels/AIConversationPanel.tsx (new)
Recordings APIapps/web-app/app/api/recordings/route.ts
Conversations APIapps/web-app/app/api/ai/conversations/route.ts
Recordings Libraryapps/web-app/app/recordings/page.tsx
Conversations Libraryapps/web-app/app/ai-conversations/page.tsx
TypeScript Typesapps/web-app/types/database.ts

Priority Matrix

TaskImpactEffortPriority
Side panel architectureHighLowP0
Voice panel integrationHighMediumP0
”Add to Story” flowHighLowP0
AI panel integrationHighMediumP1
Empty state enhancementMediumLowP1
Toolbar quick actionsMediumLowP1
Mobile responsivenessMediumHighP2
Context preservationMediumMediumP2
Library enhancementsMediumMediumP2

Risk Areas

RiskMitigation
Panel state management complexityUse existing EditorRightPanel patterns
Transcription flow in embedded contextReuse VoiceRecorder component as-is
AI context maintenancePass storyContent prop to AI panel
Mobile UX for side panelsBottom sheet or full-screen modal approach
Migration of orphan contentBackwards compatible (NULL story_id allowed)

Success Metrics

MetricCurrentTarget
Steps to create story from voice4+2
Conversion step drop-off~20%0%
Stories using multiple input methods5%30%
Time from record to published story10+ min5 min

Document History

VersionDateChanges
1.02025-12-05Initial documentation