KidLisp.com Live Reload Implementation Plan #
Context Analysis #
The aesthetic computer stack has three main interop methods for live communication:
1. Code Channel System (Recommended ✅) #
- How it works: WebSocket-based pub/sub through session-server
- Location:
system/public/aesthetic.computer/lib/disk.mjs(line 2377) - Flow:
- Editor subscribes to a unique channel via
code.channel(channelId) - Server broadcasts code updates to all subscribers on that channel
- Clients receive
type: "code"messages with{piece, source, codeChannel} - Socket handler in
lib/socket.mjstriggers reload automatically
- Editor subscribes to a unique channel via
- Used by: VSCode extension for live piece editing
- Pros:
- Already built into the system
- Handles multiple concurrent editors/viewers
- Server-side filtering and routing
- Persistent connections with auto-reconnect
- Cons:
- Requires WebSocket connection (already used by preview iframe)
- Need to coordinate channel IDs
2. Window postMessage (Simple but Limited - ACTUALLY VIABLE!) #
- How it works: Direct iframe ↔ parent communication
- Flow:
- Parent:
iframe.contentWindow.postMessage({type, data}, '*') - Iframe:
window.addEventListener('message', handler)
- Parent:
- Pros:
- ✅ No server/networking required - completely client-side!
- ✅ Synchronous, immediate (no network latency)
- ✅ Simple implementation
- ✅ Works offline
- ✅ No WebSocket connection overhead
- Cons:
- Only works for single parent-child relationships
- No pub/sub or multi-viewer support
- Security concerns with '*' origin (mitigated by origin checking)
UPDATE: This is actually the better choice for kidlisp.com because:
- We have direct parent→child iframe relationship
- No need for multi-viewer sync (single user editing)
- Zero network dependency = faster, more reliable
- Simpler architecture
3. Session Server Reload Endpoint (Development Only) #
- How it works: HTTP POST to
/reloadendpoint - Location:
session-server/session.mjs(line 197) - Flow:
- POST to
https://localhost:8889/reloadwith{piece, source} - Server broadcasts to all connected clients
- Used by chokidar file watchers
- POST to
- Pros:
- Works without maintaining WebSocket in editor
- Simple HTTP request
- Cons:
- Development mode only (
if (dev)) - Broadcasts to ALL connected clients (no targeting)
- Requires CORS configuration
- Not suitable for production
- Development mode only (
Recommended Solution: postMessage (Revised!) #
Why postMessage is better for kidlisp.com:
- ✅ No networking = instant updates
- ✅ Works offline
- ✅ Simpler implementation (no WebSocket management)
- ✅ No server dependency
- ✅ Lower latency
- ✅ We only need single-editor-to-single-preview communication
When to use Code Channel instead:
- Multiple viewers need to sync (like collaborative editing)
- Remote/distributed scenarios
- Need persistence across page reloads
- Building a "watch party" feature
For kidlisp.com's use case (single user, local editing), postMessage is the clear winner.
Alternative: Code Channel System (for reference) #
Architecture #
┌─────────────────────────┐
│ kidlisp.com Editor │
│ (Monaco) │
│ │
│ WebSocket Connection │
│ wss://aesthetic.computer
└───────────┬─────────────┘
│
│ 1. Subscribe to channel
│ code-channel:sub
│
▼
┌─────────────────────────┐
│ Session Server │
│ (WebSocket Hub) │
│ │
│ Manages subscriptions │
└───────────┬─────────────┘
│
│ 2. Broadcast code updates
│ type: "code"
│
▼
┌─────────────────────────┐
│ Preview Iframe │
│ aesthetic.computer │
│ │
│ Receives & auto-reloads│
└─────────────────────────┘
Implementation Steps #
Phase 1: Setup WebSocket Connection in Editor #
- Create WebSocket connection to
wss://aesthetic.computer(or localhost:8889 for dev) - Generate unique channel ID:
kidlisp-editor-${Date.now()}-${Math.random()} - Subscribe to channel: Send
{type: "code-channel:sub", content: channelId} - Store channel ID in preview iframe URL as query param
Phase 2: Modify Preview Iframe #
- Add channel ID to iframe URL:
?channel=${channelId} - Iframe auto-subscribes to same channel on load
- Iframe receives code updates via existing socket infrastructure
- Code updates trigger piece reload without full page refresh
Phase 3: Send Code Updates from Editor #
- On "run" button or Cmd+Enter, send code via WebSocket:
ws.send(JSON.stringify({ type: "code", content: JSON.stringify({ piece: encodedCode, source: editorCode, codeChannel: channelId }) })) - Session server routes to all channel subscribers
- Preview iframe receives and executes new code
Phase 4: Handle Edge Cases #
- Reconnection logic if WebSocket drops
- Channel cleanup on page unload
- Error handling for malformed code
- Visual feedback in editor (connection status indicator)
Code Changes Required #
kidlisp.com/index.html #
- Add WebSocket connection setup
- Generate and store channel ID
- Send code updates through WebSocket
- Add connection status indicator
Preview Iframe URL #
- Add
?channel=${channelId}parameter - Iframe will auto-subscribe via existing
code.channel()system
Session Server (Already Works!) #
- ✅ Code channel subscription handling exists
- ✅ Message routing exists
- ✅ Broadcast to channel subscribers exists
- No changes needed!
Alternative: Hybrid Approach #
If code-channel feels too heavy, could use postMessage for immediate feedback + code-channel for multi-viewer sync:
- Editor sends code via postMessage for instant local preview
- Also broadcasts via code-channel for other viewers
- Best of both worlds: speed + flexibility
Actually, postMessage DOES Work Here! #
Correction: The aesthetic.computer piece structure is:
kidlisp.com (parent)
└─ iframe src="aesthetic.computer/[code]?nogap=true" (direct child)
└─ piece renders directly in this iframe
It's only ONE iframe layer! We have direct access:
// In kidlisp.com:
const iframe = document.getElementById('preview-iframe');
iframe.contentWindow.postMessage({
type: 'reload-kidlisp',
code: editorCode
}, 'https://aesthetic.computer');
The iframe can listen and reload without full page refresh!
Why NOT HTTP Polling? #
- Inefficient (repeated requests)
- Higher latency
- More server load
- Worse UX than WebSocket push
Conclusion #
Use postMessage because:
- ✅ Zero network overhead = instant feedback
- ✅ Simpler implementation (< 20 lines of code)
- ✅ No WebSocket management/reconnection logic
- ✅ Works offline
- ✅ Direct parent-child communication (no layers to traverse)
- ✅ Perfect for single-user editing scenario
Implementation (Super Simple!) #
In kidlisp.com editor:
const iframe = document.getElementById('preview-iframe');
function updatePreview() {
const code = editor.getValue();
iframe.contentWindow.postMessage({
type: 'kidlisp-update',
code: code
}, 'https://aesthetic.computer');
}
In aesthetic.computer (would need to add listener):
window.addEventListener('message', (event) => {
if (event.origin !== 'https://kidlisp.com') return; // Security
if (event.data.type === 'kidlisp-update') {
// Reload piece with new code without full page refresh
reloadPiece(event.data.code);
}
});
Estimated implementation time: 30 minutes including testing.
Future enhancement: Could add code-channel later for multi-viewer "watch party" feature.