Update canvas skill with Tailscale integration details and architecture
This commit is contained in:
@@ -9,24 +9,84 @@ The canvas tool lets you present web content on any connected node's canvas view
|
|||||||
- Showing generated HTML content
|
- Showing generated HTML content
|
||||||
- Interactive demos
|
- Interactive demos
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
### Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────┐ ┌──────────────────┐ ┌─────────────┐
|
||||||
|
│ Canvas Host │────▶│ Node Bridge │────▶│ Node App │
|
||||||
|
│ (HTTP Server) │ │ (TCP Server) │ │ (Mac/iOS/ │
|
||||||
|
│ Port 18793 │ │ Port 18790 │ │ Android) │
|
||||||
|
└─────────────────┘ └──────────────────┘ └─────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
1. **Canvas Host Server**: Serves static HTML/CSS/JS files from `canvasHost.root` directory
|
||||||
|
2. **Node Bridge**: Communicates canvas URLs to connected nodes
|
||||||
|
3. **Node Apps**: Render the content in a WebView
|
||||||
|
|
||||||
|
### Tailscale Integration
|
||||||
|
|
||||||
|
The canvas host server binds based on `gateway.bind` setting:
|
||||||
|
|
||||||
|
| Bind Mode | Server Binds To | Canvas URL Uses |
|
||||||
|
|-----------|-----------------|-----------------|
|
||||||
|
| `loopback` | 127.0.0.1 | localhost (local only) |
|
||||||
|
| `lan` | LAN interface | LAN IP address |
|
||||||
|
| `tailnet` | Tailscale interface | Tailscale hostname |
|
||||||
|
| `auto` | Best available | Tailscale > LAN > loopback |
|
||||||
|
|
||||||
|
**Key insight:** The `canvasHostHostForBridge` is derived from `bridgeHost`. When bound to Tailscale, nodes receive URLs like:
|
||||||
|
```
|
||||||
|
http://<tailscale-hostname>:18793/__clawdbot__/canvas/<file>.html
|
||||||
|
```
|
||||||
|
|
||||||
|
This is why localhost URLs don't work - the node receives the Tailscale hostname from the bridge!
|
||||||
|
|
||||||
## Actions
|
## Actions
|
||||||
|
|
||||||
| Action | Description |
|
| Action | Description |
|
||||||
|--------|-------------|
|
|--------|-------------|
|
||||||
| `present` | Show the canvas with optional URL |
|
| `present` | Show canvas with optional target URL |
|
||||||
| `hide` | Hide the canvas |
|
| `hide` | Hide the canvas |
|
||||||
| `navigate` | Navigate to a new URL |
|
| `navigate` | Navigate to a new URL |
|
||||||
| `eval` | Execute JavaScript in the canvas |
|
| `eval` | Execute JavaScript in the canvas |
|
||||||
| `snapshot` | Capture screenshot of canvas |
|
| `snapshot` | Capture screenshot of canvas |
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
In `~/.clawdbot/clawdbot.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"canvasHost": {
|
||||||
|
"enabled": true,
|
||||||
|
"port": 18793,
|
||||||
|
"root": "/Users/you/clawd/canvas",
|
||||||
|
"liveReload": true
|
||||||
|
},
|
||||||
|
"gateway": {
|
||||||
|
"bind": "auto"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Live Reload
|
||||||
|
|
||||||
|
When `liveReload: true` (default), the canvas host:
|
||||||
|
- Watches the root directory for changes (via chokidar)
|
||||||
|
- Injects a WebSocket client into HTML files
|
||||||
|
- Automatically reloads connected canvases when files change
|
||||||
|
|
||||||
|
Great for development!
|
||||||
|
|
||||||
## Workflow
|
## Workflow
|
||||||
|
|
||||||
### 1. Create HTML content
|
### 1. Create HTML content
|
||||||
|
|
||||||
Place HTML files in the canvas directory (configured in `canvasHost.root`, typically `~/clawd/canvas/`):
|
Place files in the canvas root directory (default `~/clawd/canvas/`):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Write your HTML file
|
|
||||||
cat > ~/clawd/canvas/my-game.html << 'HTML'
|
cat > ~/clawd/canvas/my-game.html << 'HTML'
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
@@ -38,26 +98,34 @@ cat > ~/clawd/canvas/my-game.html << 'HTML'
|
|||||||
HTML
|
HTML
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Find a connected node
|
### 2. Find your canvas host URL
|
||||||
|
|
||||||
|
Check how your gateway is bound:
|
||||||
|
```bash
|
||||||
|
cat ~/.clawdbot/clawdbot.json | jq '.gateway.bind'
|
||||||
|
```
|
||||||
|
|
||||||
|
Then construct the URL:
|
||||||
|
- **loopback**: `http://127.0.0.1:18793/__clawdbot__/canvas/<file>.html`
|
||||||
|
- **lan/tailnet/auto**: `http://<hostname>:18793/__clawdbot__/canvas/<file>.html`
|
||||||
|
|
||||||
|
Find your Tailscale hostname:
|
||||||
|
```bash
|
||||||
|
tailscale status --json | jq -r '.Self.DNSName' | sed 's/\.$//'
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Find connected nodes
|
||||||
|
|
||||||
List available nodes:
|
|
||||||
```bash
|
```bash
|
||||||
clawdbot nodes list
|
clawdbot nodes list
|
||||||
```
|
```
|
||||||
|
|
||||||
Look for nodes with canvas capability (Mac/iOS/Android apps).
|
Look for Mac/iOS/Android nodes with canvas capability.
|
||||||
|
|
||||||
### 3. Present the content
|
### 4. Present content
|
||||||
|
|
||||||
```
|
```
|
||||||
canvas action:present node:<node-id> target:<url>
|
canvas action:present node:<node-id> target:<full-url>
|
||||||
```
|
|
||||||
|
|
||||||
**Important:** The canvas host server binds to the Tailscale hostname, not localhost!
|
|
||||||
|
|
||||||
**Correct URL format:**
|
|
||||||
```
|
|
||||||
http://<tailscale-hostname>:18793/__clawdbot__/canvas/<filename>.html
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Example:**
|
**Example:**
|
||||||
@@ -65,94 +133,57 @@ http://<tailscale-hostname>:18793/__clawdbot__/canvas/<filename>.html
|
|||||||
canvas action:present node:mac-63599bc4-b54d-4392-9048-b97abd58343a target:http://peters-mac-studio-1.sheep-coho.ts.net:18793/__clawdbot__/canvas/snake.html
|
canvas action:present node:mac-63599bc4-b54d-4392-9048-b97abd58343a target:http://peters-mac-studio-1.sheep-coho.ts.net:18793/__clawdbot__/canvas/snake.html
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. Navigate to different content
|
### 5. Navigate, snapshot, or hide
|
||||||
|
|
||||||
```
|
```
|
||||||
canvas action:navigate node:<node-id> url:<new-url>
|
canvas action:navigate node:<node-id> url:<new-url>
|
||||||
```
|
|
||||||
|
|
||||||
### 5. Take a screenshot
|
|
||||||
|
|
||||||
```
|
|
||||||
canvas action:snapshot node:<node-id>
|
canvas action:snapshot node:<node-id>
|
||||||
```
|
|
||||||
|
|
||||||
### 6. Hide when done
|
|
||||||
|
|
||||||
```
|
|
||||||
canvas action:hide node:<node-id>
|
canvas action:hide node:<node-id>
|
||||||
```
|
```
|
||||||
|
|
||||||
## Configuration
|
## Debugging
|
||||||
|
|
||||||
In `~/.clawdbot/clawdbot.json`:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"canvasHost": {
|
|
||||||
"enabled": true,
|
|
||||||
"port": 18793,
|
|
||||||
"root": "/Users/you/clawd/canvas"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Common Issues
|
|
||||||
|
|
||||||
### White screen / content not loading
|
### White screen / content not loading
|
||||||
|
|
||||||
**Problem:** Canvas shows white/blank screen.
|
**Cause:** URL mismatch between server bind and node expectation.
|
||||||
|
|
||||||
**Solution:** The canvas host server binds to Tailscale hostname. Use the full URL:
|
**Debug steps:**
|
||||||
```
|
1. Check server bind: `cat ~/.clawdbot/clawdbot.json | jq '.gateway.bind'`
|
||||||
http://<tailscale-hostname>:18793/__clawdbot__/canvas/<file>.html
|
2. Check what port canvas is on: `lsof -i :18793`
|
||||||
```
|
3. Test URL directly: `curl http://<hostname>:18793/__clawdbot__/canvas/<file>.html`
|
||||||
|
|
||||||
NOT:
|
**Solution:** Use the full hostname matching your bind mode, not localhost.
|
||||||
```
|
|
||||||
http://127.0.0.1:18793/... ❌
|
|
||||||
http://localhost:18793/... ❌
|
|
||||||
```
|
|
||||||
|
|
||||||
### "node required" error
|
### "node required" error
|
||||||
|
|
||||||
**Solution:** Always specify the `node` parameter with a valid node ID from `clawdbot nodes list`.
|
Always specify `node:<node-id>` parameter.
|
||||||
|
|
||||||
### "node not connected" error
|
### "node not connected" error
|
||||||
|
|
||||||
**Solution:** The specified node is offline. Choose a different node that's currently connected.
|
Node is offline. Use `clawdbot nodes list` to find online nodes.
|
||||||
|
|
||||||
### A2UI formats not working
|
### Content not updating
|
||||||
|
|
||||||
A2UI JSON push formats are WIP. Use HTML files instead.
|
If live reload isn't working:
|
||||||
|
1. Check `liveReload: true` in config
|
||||||
|
2. Ensure file is in the canvas root directory
|
||||||
|
3. Check for watcher errors in logs
|
||||||
|
|
||||||
|
## URL Path Structure
|
||||||
|
|
||||||
|
The canvas host serves from `/__clawdbot__/canvas/` prefix:
|
||||||
|
|
||||||
|
```
|
||||||
|
http://<host>:18793/__clawdbot__/canvas/index.html → ~/clawd/canvas/index.html
|
||||||
|
http://<host>:18793/__clawdbot__/canvas/games/snake.html → ~/clawd/canvas/games/snake.html
|
||||||
|
```
|
||||||
|
|
||||||
|
The `/__clawdbot__/canvas/` prefix is defined by `CANVAS_HOST_PATH` constant.
|
||||||
|
|
||||||
## Tips
|
## Tips
|
||||||
|
|
||||||
- Keep HTML self-contained (inline CSS/JS) for best results
|
- Keep HTML self-contained (inline CSS/JS) for best results
|
||||||
- Test your HTML locally first before presenting
|
- Use the default index.html as a test page (has bridge diagnostics)
|
||||||
- Use `snapshot` to capture what the canvas is showing
|
|
||||||
- The canvas persists until you `hide` it or navigate away
|
- The canvas persists until you `hide` it or navigate away
|
||||||
|
- Live reload makes development fast - just save and it updates!
|
||||||
## Example: Quick Game Display
|
- A2UI JSON push is WIP - use HTML files for now
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. Create game HTML
|
|
||||||
cat > ~/clawd/canvas/game.html << 'HTML'
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>Quick Game</title>
|
|
||||||
<style>
|
|
||||||
body { background: #1a1a2e; color: #fff; font-family: sans-serif; }
|
|
||||||
h1 { text-align: center; color: #00f3ff; }
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>🎮 Game Time!</h1>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
HTML
|
|
||||||
|
|
||||||
# 2. Present it (replace with your node ID and hostname)
|
|
||||||
canvas action:present node:mac-xxx target:http://your-hostname:18793/__clawdbot__/canvas/game.html
|
|
||||||
```
|
|
||||||
|
|||||||
Reference in New Issue
Block a user