Add migration plan and backlog tasks for canvas-website to FolkJS transition

This commit is contained in:
Jeff Emmett 2026-01-02 17:13:54 +01:00
parent 0df7cd04af
commit 00db0d4f63
8 changed files with 470 additions and 0 deletions

View File

@ -0,0 +1,37 @@
---
id: task-2
title: 'Phase 1: FolkJS Foundation - Port Simple Shapes'
status: To Do
assignee: []
created_date: '2026-01-02 14:42'
labels:
- foundation
- migration
- shapes
dependencies: []
priority: high
---
## Description
<!-- SECTION:DESCRIPTION:BEGIN -->
Port the 4 simplest shapes from canvas-website to FolkJS web components:
- SlideShapeUtil (passive display)
- ChatBoxShapeUtil (real-time chat)
- GoogleItemShapeUtil (data display)
- SharedPianoShapeUtil (interactive music)
Key simplifications vs tldraw:
- No BaseBoxShapeUtil inheritance, use FolkShape directly
- No React - pure web components with lit-style templates
- Hooks become class methods or standalone utilities
- StandardizedToolWrapper already ported as FolkWrapper
<!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria
<!-- AC:BEGIN -->
- [ ] #1 folk-slide component created
- [ ] #2 folk-chat component created
- [ ] #3 folk-google-item component created
- [ ] #4 folk-piano component created
<!-- AC:END -->

View File

@ -0,0 +1,46 @@
---
id: task-3
title: 'Phase 2: Core Data Shapes - Embed, Markdown, Calendar, Map'
status: To Do
assignee: []
created_date: '2026-01-02 14:42'
labels:
- migration
- shapes
- core
dependencies: []
priority: high
---
## Description
<!-- SECTION:DESCRIPTION:BEGIN -->
Port medium-complexity shapes that form the core data visualization layer:
1. **folk-embed** (565 LOC) - URL embeds (YouTube, Maps, Twitter)
- URL transformation patterns
- Interaction state management
2. **folk-calendar** (644 LOC) - Unified calendar widget
- Browser/widget/year views
- Event detection from CalendarPanel/YearViewPanel
3. **folk-map** (2,168 LOC - LARGEST) - Collaborative Mapbox/MapLibre
- Real-time presence cursors
- Drawing annotations (markers, lines, areas)
- Search via Nominatim, routing via OSRM
- GPS location sharing
Simplifications:
- Replace React state with reactive properties
- Replace context providers with event-based communication
- Calendar/Map can be separate packages imported as needed
<!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria
<!-- AC:BEGIN -->
- [ ] #1 folk-embed component with URL detection
- [ ] #2 folk-calendar with month/year views
- [ ] #3 folk-map with MapLibre integration
- [ ] #4 Real-time presence on map working
<!-- AC:END -->

View File

@ -0,0 +1,52 @@
---
id: task-4
title: 'Phase 3: AI Integration Shapes'
status: To Do
assignee: []
created_date: '2026-01-02 15:54'
labels:
- migration
- shapes
- ai
dependencies: []
priority: medium
---
## Description
<!-- SECTION:DESCRIPTION:BEGIN -->
Port AI-powered shapes using existing MCP servers and APIs:
1. **folk-image-gen** - Image generation (fal.ai Flux)
- Prompt input, image history thread
- Loading states, error handling
- Uses: mcp__fal-ai__fal_generate_image
2. **folk-video-gen** - Video generation (WAN 2.1)
- Image-to-video, text-to-video
- Duration control, queue polling
- Uses: mcp__fal-ai__fal_generate_video
3. **folk-prompt** - LLM prompt executor
- Agent binding, multiple personalities
- Output streaming
- Uses: mcp__gemini__gemini_generate or direct Anthropic API
4. **folk-transcription** - Audio transcription (Whisper)
- Real-time transcription, pause/resume
- Speaker diarization
- Uses: Web Speech API fallback + Whisper API
Simplifications:
- Use MCP tools directly instead of custom API clients
- Simplify loading states to CSS classes
- Remove complex React hooks, use async/await patterns
<!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria
<!-- AC:BEGIN -->
- [ ] #1 folk-image-gen with fal.ai integration
- [ ] #2 folk-video-gen with video generation
- [ ] #3 folk-prompt with LLM streaming
- [ ] #4 folk-transcription with Whisper
<!-- AC:END -->

View File

@ -0,0 +1,53 @@
---
id: task-5
title: 'Phase 4: Advanced Shapes - Video Chat, Notes, Workflows'
status: To Do
assignee: []
created_date: '2026-01-02 16:04'
labels:
- migration
- shapes
- advanced
dependencies: []
priority: medium
---
## Description
<!-- SECTION:DESCRIPTION:BEGIN -->
Port remaining complex shapes:
1. **folk-video-chat** - Video conferencing (Daily.co)
- Meeting creation, recording, permissions
- WebRTC integration
2. **folk-obs-note** - Rich markdown from Obsidian
- MDX editing, vault sync
- Change detection, save/sync
3. **folk-holon** - Holosphere node with H3 geo-indexing
- Hierarchical geospatial indexing
- Connection management
4. **folk-workflow-block** - Visual workflow automation
- Typed input/output ports
- Connection support via folk-arrow
- Execution state visualization
5. **folk-zine-generator** - AI zine creation
- 5-phase workflow
- Page generation with feedback loop
Simplifications:
- Use existing folk-arrow for connections
- Workflows use event-based execution instead of complex state machines
- Obsidian sync can be optional/pluggable
<!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria
<!-- AC:BEGIN -->
- [ ] #1 folk-video-chat with Daily.co
- [ ] #2 folk-obs-note with markdown editing
- [ ] #3 folk-workflow-block with typed ports
- [ ] #4 Workflow execution via folk-arrow connections
<!-- AC:END -->

View File

@ -0,0 +1,34 @@
---
id: task-6
title: Mobile touch support for canvas
status: To Do
assignee: []
created_date: '2026-01-02 16:07'
labels:
- feature
- mobile
- ux
dependencies: []
priority: medium
---
## Description
<!-- SECTION:DESCRIPTION:BEGIN -->
Enable touch interactions on mobile devices:
- Touch drag for moving shapes
- Pinch-to-zoom for canvas
- Two-finger pan for canvas navigation
- Touch-friendly resize handles (larger hit areas)
- Long-press for context menu
FolkShape already has touchmove handler, needs enhancement for multi-touch gestures.
<!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria
<!-- AC:BEGIN -->
- [ ] #1 Single touch drag works on shapes
- [ ] #2 Pinch-to-zoom works on canvas
- [ ] #3 Two-finger pan works
- [ ] #4 Tested on iOS Safari and Android Chrome
<!-- AC:END -->

View File

@ -0,0 +1,34 @@
---
id: task-7
title: Real-time presence cursors
status: To Do
assignee: []
created_date: '2026-01-02 16:08'
labels:
- feature
- collaboration
- sync
dependencies: []
priority: medium
---
## Description
<!-- SECTION:DESCRIPTION:BEGIN -->
Show other users cursors and selections in real-time:
- Broadcast cursor position via WebSocket presence messages
- Display colored cursor with username label
- Show selection highlight when user has shape selected
- Fade out cursors after inactivity
- Different cursor colors per user
WebSocket already handles presence messages (see server/index.ts line 221-235), needs client-side rendering.
<!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria
<!-- AC:BEGIN -->
- [ ] #1 Cursor position broadcasts on mousemove
- [ ] #2 Other users cursors visible with name labels
- [ ] #3 Selection state shared between users
- [ ] #4 Cursors fade after 5s inactivity
<!-- AC:END -->

View File

@ -0,0 +1,42 @@
---
id: task-8
title: Port shared hooks as FolkJS utilities
status: To Do
assignee: []
created_date: '2026-01-02 16:10'
labels:
- foundation
- utilities
- migration
dependencies: []
priority: high
---
## Description
<!-- SECTION:DESCRIPTION:BEGIN -->
Convert canvas-website React hooks to FolkJS-compatible utilities:
1. **useMaximize** → maximizeShape(shape) utility
- Store original dimensions
- Animate to viewport fill
- Restore on toggle
2. **usePinnedToView** → PinnedViewManager class
- Keep shape fixed as camera moves
- Support multiple pin positions
- Zero-lag with requestAnimationFrame
3. **Shape serialization** - toJSON/fromJSON pattern
- Already implemented in folk-markdown
- Standardize across all shapes
These utilities enable the StandardizedToolWrapper features (maximize, pin, close) across all FolkJS shapes.
<!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria
<!-- AC:BEGIN -->
- [ ] #1 maximizeShape utility working
- [ ] #2 PinnedViewManager class working
- [ ] #3 All shapes have consistent toJSON/fromJSON
<!-- AC:END -->

172
docs/MIGRATION-PLAN.md Normal file
View File

@ -0,0 +1,172 @@
# Canvas-Website to FolkJS Migration Plan
## Overview
This document outlines the transition from canvas-website (React + tldraw) to rspace-online (FolkJS web components). The goal is to simplify the architecture while preserving core functionality.
## Architecture Comparison
| Aspect | canvas-website (tldraw) | rspace-online (FolkJS) |
|--------|------------------------|------------------------|
| **Framework** | React 18 + tldraw v3 | Web Components (Lit-style) |
| **State** | tldraw store + Jotai atoms | Reactive properties + Automerge |
| **Sync** | Cloudflare Durable Objects | WebSocket + Automerge CRDT |
| **Shapes** | BaseBoxShapeUtil classes | FolkShape subclasses |
| **Styling** | CSS-in-JS / CSS modules | CSS in template literals |
| **Hooks** | React hooks (9 shared) | Class methods + utilities |
## Key Simplifications
### 1. No React
- **Before**: JSX, useState, useEffect, useCallback, useMemo
- **After**: Template literals, reactive properties, event listeners
### 2. No tldraw Abstraction Layer
- **Before**: BaseBoxShapeUtil, editor.updateShape(), shape migrations
- **After**: FolkShape base class, direct property updates, Automerge patches
### 3. Simpler State Management
- **Before**: tldraw store → Automerge → tldraw store (bidirectional sync)
- **After**: FolkShape → Automerge → FolkShape (direct sync via CommunitySync)
### 4. Web-Native APIs
- **Before**: React context providers for auth, notifications, file system
- **After**: Custom events, localStorage, native browser APIs
## Shape Porting Pattern
### tldraw Shape (Before)
```tsx
export class MyShapeUtil extends BaseBoxShapeUtil<MyShape> {
static type = 'my-shape'
getDefaultProps(): MyShape['props'] {
return { w: 300, h: 200, content: '' }
}
component(shape: MyShape) {
const { content } = shape.props
const handleChange = useCallback((e) => {
this.editor.updateShape({ id: shape.id, props: { content: e.target.value } })
}, [shape.id])
return (
<StandardizedToolWrapper shape={shape}>
<textarea value={content} onChange={handleChange} />
</StandardizedToolWrapper>
)
}
}
```
### FolkJS Shape (After)
```typescript
export class FolkMyShape extends FolkShape {
static tagName = 'folk-my-shape'
#content = ''
get content() { return this.#content }
set content(value: string) {
this.#content = value
this.requestUpdate('content')
this.dispatchEvent(new CustomEvent('content-change', { detail: { content: value } }))
}
override createRenderRoot() {
const root = super.createRenderRoot()
// Add UI to shadow DOM
const wrapper = document.createElement('div')
wrapper.innerHTML = `
<div class="header" data-drag>
<span>My Shape</span>
<button class="close-btn">×</button>
</div>
<div class="content">
<textarea></textarea>
</div>
`
// Event listeners...
return root
}
}
```
## Migration Phases
### Phase 1: Foundation (4 shapes)
**Status**: To Do
- folk-slide (passive display)
- folk-chat (real-time chat)
- folk-google-item (data display)
- folk-piano (interactive music)
### Phase 2: Core Data (4 shapes)
**Status**: To Do
- folk-embed (URL embeds)
- folk-markdown (already done!)
- folk-calendar (date picker + events)
- folk-map (Mapbox/MapLibre collaborative maps)
### Phase 3: AI Integration (4 shapes)
**Status**: To Do
- folk-image-gen (fal.ai Flux)
- folk-video-gen (WAN 2.1)
- folk-prompt (LLM execution)
- folk-transcription (Whisper)
### Phase 4: Advanced (5+ shapes)
**Status**: To Do
- folk-video-chat (Daily.co)
- folk-obs-note (Obsidian sync)
- folk-holon (H3 geo-indexing)
- folk-workflow-block (visual workflows)
- folk-zine-generator (AI zine creation)
## Shared Utilities to Port
| React Hook | FolkJS Equivalent | Status |
|------------|-------------------|--------|
| useMaximize | maximizeShape() utility | To Do |
| usePinnedToView | PinnedViewManager class | To Do |
| useCalendarEvents | CalendarService class | To Do |
| useWhisperTranscription | WhisperService class | To Do |
| useLiveImage | LiveImageService class | To Do |
## Already Completed
- [x] FolkShape base class with drag/resize/rotate
- [x] FolkMarkdown (markdown editing)
- [x] FolkWrapper (standardized header/actions)
- [x] FolkArrow (shape connections)
- [x] CommunitySync (Automerge integration)
- [x] Server with WebSocket sync
- [x] Subdomain routing for communities
## External Dependencies
### Keep (MCP or direct API)
- fal.ai (image/video gen) - via MCP
- Gemini (text gen) - via MCP
- MapLibre GL (maps)
- Daily.co (video chat)
- Whisper API (transcription)
### Replace/Simplify
- MDXEditor → simpler markdown renderer (already done)
- tldraw → FolkJS (in progress)
- React contexts → custom events + services
### Remove (tldraw-specific)
- BaseBoxShapeUtil
- Shape migrations
- tldraw editor commands
- tldraw store subscriptions
## Success Criteria
1. All 28 shapes ported to FolkJS web components
2. Real-time collaboration working via Automerge
3. Mobile touch support
4. Presence cursors showing other users
5. No React dependencies in runtime
6. Bundle size < 500KB (vs ~2MB current)