rspace-online/docs/MIGRATION-PLAN.md

173 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 | ✅ Done |
| usePinnedToView | PinnedViewManager class | ✅ Done |
| 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)