@limeade-labs/sparkui 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +9 -0
- package/CONTRIBUTING.md +63 -0
- package/LICENSE +21 -0
- package/README.md +232 -0
- package/SKILL.md +242 -0
- package/bin/deploy +23 -0
- package/bin/sparkui.js +390 -0
- package/docs/README.md +51 -0
- package/docs/api-reference.md +428 -0
- package/docs/chatgpt-setup.md +206 -0
- package/docs/components.md +432 -0
- package/docs/getting-started.md +179 -0
- package/docs/mcp-setup.md +195 -0
- package/docs/openclaw-setup.md +177 -0
- package/docs/templates.md +289 -0
- package/lib/components.js +474 -0
- package/lib/store.js +193 -0
- package/lib/templates.js +48 -0
- package/lib/ws-client.js +197 -0
- package/mcp-server/README.md +189 -0
- package/mcp-server/index.js +174 -0
- package/mcp-server/package.json +15 -0
- package/package.json +52 -0
- package/server.js +620 -0
- package/templates/base.js +82 -0
- package/templates/checkout.js +271 -0
- package/templates/feedback-form.js +140 -0
- package/templates/macro-tracker.js +205 -0
- package/templates/workout-timer.js +510 -0
- package/templates/ws-test.js +136 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# MCP Setup
|
|
2
|
+
|
|
3
|
+
Use SparkUI from AI clients like Claude Desktop, Cursor, and Windsurf via the [Model Context Protocol (MCP)](https://modelcontextprotocol.io/).
|
|
4
|
+
|
|
5
|
+
## What is MCP?
|
|
6
|
+
|
|
7
|
+
MCP (Model Context Protocol) is an open standard that lets AI applications connect to external tools and data sources. Instead of writing custom integrations, any MCP-compatible client can use SparkUI tools through a standard protocol.
|
|
8
|
+
|
|
9
|
+
The SparkUI MCP server exposes tools like `sparkui_push` and `sparkui_compose` that AI clients can call to create ephemeral web pages.
|
|
10
|
+
|
|
11
|
+
## Prerequisites
|
|
12
|
+
|
|
13
|
+
1. SparkUI server running (see [Getting Started](./getting-started.md))
|
|
14
|
+
2. Your push token from `.env`
|
|
15
|
+
3. An MCP-compatible client (Claude Desktop, Cursor, Windsurf, Cline, etc.)
|
|
16
|
+
|
|
17
|
+
## Install the MCP Server
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
cd mcp-server
|
|
21
|
+
npm install
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The MCP server is a lightweight Node.js process that communicates with your SparkUI server over HTTP.
|
|
25
|
+
|
|
26
|
+
## Claude Desktop Setup
|
|
27
|
+
|
|
28
|
+
Edit your Claude Desktop config file:
|
|
29
|
+
|
|
30
|
+
- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
31
|
+
- **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"mcpServers": {
|
|
36
|
+
"sparkui": {
|
|
37
|
+
"command": "node",
|
|
38
|
+
"args": ["/absolute/path/to/sparkui/mcp-server/index.js"],
|
|
39
|
+
"env": {
|
|
40
|
+
"SPARKUI_URL": "http://localhost:3457",
|
|
41
|
+
"SPARKUI_TOKEN": "your-push-token"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Restart Claude Desktop after saving. You should see "sparkui" in the MCP tools list (🔨 icon).
|
|
49
|
+
|
|
50
|
+
> **Tip:** Use an absolute path for the `args` value. Relative paths may not resolve correctly.
|
|
51
|
+
|
|
52
|
+
## Cursor Setup
|
|
53
|
+
|
|
54
|
+
Add to `.cursor/mcp.json` in your project root (or global config):
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"mcpServers": {
|
|
59
|
+
"sparkui": {
|
|
60
|
+
"command": "node",
|
|
61
|
+
"args": ["/absolute/path/to/sparkui/mcp-server/index.js"],
|
|
62
|
+
"env": {
|
|
63
|
+
"SPARKUI_URL": "http://localhost:3457",
|
|
64
|
+
"SPARKUI_TOKEN": "your-push-token"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Windsurf Setup
|
|
72
|
+
|
|
73
|
+
Add to `.windsurf/mcp.json` in your project root:
|
|
74
|
+
|
|
75
|
+
```json
|
|
76
|
+
{
|
|
77
|
+
"mcpServers": {
|
|
78
|
+
"sparkui": {
|
|
79
|
+
"command": "node",
|
|
80
|
+
"args": ["/absolute/path/to/sparkui/mcp-server/index.js"],
|
|
81
|
+
"env": {
|
|
82
|
+
"SPARKUI_URL": "http://localhost:3457",
|
|
83
|
+
"SPARKUI_TOKEN": "your-push-token"
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Environment Variables
|
|
91
|
+
|
|
92
|
+
| Variable | Required | Default | Description |
|
|
93
|
+
|----------|----------|---------|-------------|
|
|
94
|
+
| `SPARKUI_URL` | No | `http://localhost:3457` | Base URL of the SparkUI server |
|
|
95
|
+
| `SPARKUI_TOKEN` | Yes | — | Push token for API authentication |
|
|
96
|
+
|
|
97
|
+
## Available MCP Tools
|
|
98
|
+
|
|
99
|
+
### `sparkui_list_templates`
|
|
100
|
+
|
|
101
|
+
List available page templates.
|
|
102
|
+
|
|
103
|
+
**Parameters:** None
|
|
104
|
+
|
|
105
|
+
**Returns:**
|
|
106
|
+
|
|
107
|
+
```json
|
|
108
|
+
{ "templates": ["macro-tracker", "ws-test", "feedback-form", "checkout", "workout-timer"] }
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### `sparkui_list_components`
|
|
112
|
+
|
|
113
|
+
List available components for page composition.
|
|
114
|
+
|
|
115
|
+
**Parameters:** None
|
|
116
|
+
|
|
117
|
+
**Returns:**
|
|
118
|
+
|
|
119
|
+
```json
|
|
120
|
+
{ "components": ["header", "button", "timer", "checklist", "progress", "stats", "form", "tabs"] }
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### `sparkui_push`
|
|
124
|
+
|
|
125
|
+
Create a page from a template.
|
|
126
|
+
|
|
127
|
+
| Parameter | Type | Required | Description |
|
|
128
|
+
|-----------|------|----------|-------------|
|
|
129
|
+
| `template` | string | Yes | Template name |
|
|
130
|
+
| `data` | object | Yes | Template data |
|
|
131
|
+
| `ttl` | number | No | Time-to-live in seconds |
|
|
132
|
+
| `og` | object | No | Open Graph overrides (`title`, `description`, `image`) |
|
|
133
|
+
|
|
134
|
+
### `sparkui_compose`
|
|
135
|
+
|
|
136
|
+
Compose a page from individual components.
|
|
137
|
+
|
|
138
|
+
| Parameter | Type | Required | Description |
|
|
139
|
+
|-----------|------|----------|-------------|
|
|
140
|
+
| `title` | string | Yes | Page title |
|
|
141
|
+
| `sections` | array | Yes | Array of `{ type, config }` component sections |
|
|
142
|
+
| `ttl` | number | No | Time-to-live in seconds |
|
|
143
|
+
|
|
144
|
+
### `sparkui_page_status`
|
|
145
|
+
|
|
146
|
+
Check if a page is still active.
|
|
147
|
+
|
|
148
|
+
| Parameter | Type | Required | Description |
|
|
149
|
+
|-----------|------|----------|-------------|
|
|
150
|
+
| `id` | string | Yes | Page UUID |
|
|
151
|
+
|
|
152
|
+
## Example Usage
|
|
153
|
+
|
|
154
|
+
Once configured, you can ask your AI client naturally:
|
|
155
|
+
|
|
156
|
+
> "Create a feedback form asking about the new feature"
|
|
157
|
+
|
|
158
|
+
The AI client will call `sparkui_push` with the feedback-form template and return a URL you can open.
|
|
159
|
+
|
|
160
|
+
> "Make a dashboard showing my project stats: 42 tasks done, 8 in progress, 3 blocked"
|
|
161
|
+
|
|
162
|
+
The AI will use `sparkui_compose` with header, stats, and progress components.
|
|
163
|
+
|
|
164
|
+
> "Build me a workout timer: 3 rounds of push-ups, squats, and planks with 60-second rest"
|
|
165
|
+
|
|
166
|
+
The AI calls `sparkui_push` with the workout-timer template.
|
|
167
|
+
|
|
168
|
+
## Architecture
|
|
169
|
+
|
|
170
|
+
```
|
|
171
|
+
Claude Desktop / Cursor / Windsurf
|
|
172
|
+
↓ (MCP stdio)
|
|
173
|
+
SparkUI MCP Server (Node.js)
|
|
174
|
+
↓ (HTTP)
|
|
175
|
+
SparkUI Server (localhost:3457)
|
|
176
|
+
↓
|
|
177
|
+
Ephemeral web pages
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
The MCP server is a thin client — it translates MCP tool calls into SparkUI HTTP API requests. It doesn't import SparkUI internals or require being co-located with the SparkUI server.
|
|
181
|
+
|
|
182
|
+
## Troubleshooting
|
|
183
|
+
|
|
184
|
+
**"Tool not found" in Claude Desktop:**
|
|
185
|
+
- Ensure you restarted Claude Desktop after editing the config
|
|
186
|
+
- Check that the path to `index.js` is absolute and correct
|
|
187
|
+
- Verify the MCP server starts: `node /path/to/mcp-server/index.js` (it should wait for stdin)
|
|
188
|
+
|
|
189
|
+
**"SparkUI API error: 401":**
|
|
190
|
+
- Your `SPARKUI_TOKEN` doesn't match the `PUSH_TOKEN` in your SparkUI `.env`
|
|
191
|
+
- Check for trailing whitespace in the token
|
|
192
|
+
|
|
193
|
+
**"Connection refused":**
|
|
194
|
+
- SparkUI server isn't running — start it with `sparkui start`
|
|
195
|
+
- Check that `SPARKUI_URL` matches your server's actual port
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# OpenClaw Setup
|
|
2
|
+
|
|
3
|
+
Integrate SparkUI as an [OpenClaw](https://github.com/openclaw/openclaw) agent skill so your AI agent can automatically generate interactive web pages during conversations.
|
|
4
|
+
|
|
5
|
+
## What is OpenClaw?
|
|
6
|
+
|
|
7
|
+
OpenClaw is an AI agent runtime that connects language models to tools, channels (Slack, Discord, Telegram), and external services. Skills are modular capabilities the agent can invoke — SparkUI is one such skill.
|
|
8
|
+
|
|
9
|
+
When SparkUI is installed as a skill, the agent can detect when a visual UI would be better than text (dashboards, forms, trackers) and automatically generate a page without being explicitly asked.
|
|
10
|
+
|
|
11
|
+
## Install SparkUI as an OpenClaw Skill
|
|
12
|
+
|
|
13
|
+
### 1. Clone SparkUI into your skills directory
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
cd ~/your-openclaw-workspace/skills/
|
|
17
|
+
git clone https://github.com/Limeade-Labs/sparkui.git
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Or symlink if SparkUI is already installed elsewhere:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
ln -s /path/to/sparkui ~/your-openclaw-workspace/skills/sparkui
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 2. Verify the SKILL.md
|
|
27
|
+
|
|
28
|
+
SparkUI includes a `SKILL.md` file that tells the agent how to use it. The key sections are:
|
|
29
|
+
|
|
30
|
+
- **When to Use** — triggers (dashboards, trackers, forms, rich content)
|
|
31
|
+
- **Server Location** — directory, port, config file location
|
|
32
|
+
- **Step-by-step instructions** — check server, get token, push content
|
|
33
|
+
- **Available templates** — template names and data shapes
|
|
34
|
+
- **Composable components** — component types and configs
|
|
35
|
+
|
|
36
|
+
The agent reads this file automatically when it determines SparkUI is relevant to the task.
|
|
37
|
+
|
|
38
|
+
### 3. Configure Environment
|
|
39
|
+
|
|
40
|
+
Ensure the SparkUI server is accessible from the OpenClaw host. The `.env` file should include:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
PUSH_TOKEN=spk_your_token_here
|
|
44
|
+
SPARKUI_PORT=3457
|
|
45
|
+
SPARKUI_BASE_URL=http://localhost:3457
|
|
46
|
+
|
|
47
|
+
# For round-trip event callbacks to OpenClaw
|
|
48
|
+
OPENCLAW_HOOKS_URL=http://127.0.0.1:18789/hooks/agent
|
|
49
|
+
OPENCLAW_HOOKS_TOKEN=your_openclaw_hooks_token
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 4. Start the SparkUI Server
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
cd /path/to/sparkui
|
|
56
|
+
node server.js &
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Or use the CLI:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
sparkui start
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## How the Agent Uses It
|
|
66
|
+
|
|
67
|
+
Once configured, the agent automatically detects opportunities to use SparkUI:
|
|
68
|
+
|
|
69
|
+
1. **Agent reads SKILL.md** — on startup or when a relevant task is detected
|
|
70
|
+
2. **Agent checks server health** — `curl http://localhost:3457/`
|
|
71
|
+
3. **Agent loads push token** — `source /path/to/sparkui/.env`
|
|
72
|
+
4. **Agent pushes a page** — via `curl` to the push or compose API
|
|
73
|
+
5. **Agent shares the URL** — sends the `fullUrl` to the user in chat
|
|
74
|
+
|
|
75
|
+
The agent decides when to use SparkUI based on the "When to Use" section in SKILL.md:
|
|
76
|
+
|
|
77
|
+
- ✅ Dashboards, nutrition trackers, fitness stats
|
|
78
|
+
- ✅ Data displays, tables, comparisons
|
|
79
|
+
- ✅ Interactive forms, feedback collection
|
|
80
|
+
- ✅ Anything with progress bars, colors, layouts
|
|
81
|
+
- ❌ Simple text answers, yes/no questions, quick lists
|
|
82
|
+
|
|
83
|
+
## Example: Macro Tracking Flow
|
|
84
|
+
|
|
85
|
+
Here's how the agent handles a nutrition tracking request end-to-end:
|
|
86
|
+
|
|
87
|
+
**User says:** "Log my lunch — chicken salad, 480 cal, 35g protein, 20g fat, 15g carbs"
|
|
88
|
+
|
|
89
|
+
**Agent does:**
|
|
90
|
+
|
|
91
|
+
1. Updates the nutrition spreadsheet with the new meal
|
|
92
|
+
2. Reads today's totals from the sheet
|
|
93
|
+
3. Pushes a macro-tracker page:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
curl -s -X POST http://localhost:3457/api/push \
|
|
97
|
+
-H "Authorization: Bearer $PUSH_TOKEN" \
|
|
98
|
+
-H "Content-Type: application/json" \
|
|
99
|
+
-d '{
|
|
100
|
+
"template": "macro-tracker",
|
|
101
|
+
"data": {
|
|
102
|
+
"date": "2026-03-14",
|
|
103
|
+
"calories": {"current": 1250, "target": 1900},
|
|
104
|
+
"protein": {"current": 62, "target": 86},
|
|
105
|
+
"fat": {"current": 45, "target": 95},
|
|
106
|
+
"carbs": {"current": 15, "target": 25},
|
|
107
|
+
"meals": [
|
|
108
|
+
{"name": "Eggs & bacon", "calories": 450, "time": "6:30 AM"},
|
|
109
|
+
{"name": "Chicken salad", "calories": 480, "time": "12:00 PM"}
|
|
110
|
+
]
|
|
111
|
+
},
|
|
112
|
+
"ttl": 7200
|
|
113
|
+
}'
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
4. Shares the link: "Logged! Here's your updated dashboard: http://..."
|
|
117
|
+
|
|
118
|
+
## Round-Trip Events (OpenClaw Callbacks)
|
|
119
|
+
|
|
120
|
+
SparkUI can forward user interactions back to the agent via OpenClaw's webhook system. This closes the loop: **agent pushes page → user interacts → agent gets notified**.
|
|
121
|
+
|
|
122
|
+
### Enable OpenClaw Forwarding
|
|
123
|
+
|
|
124
|
+
Add `openclaw` config when pushing a page:
|
|
125
|
+
|
|
126
|
+
```json
|
|
127
|
+
{
|
|
128
|
+
"template": "feedback-form",
|
|
129
|
+
"data": { "title": "Quick Feedback" },
|
|
130
|
+
"openclaw": {
|
|
131
|
+
"enabled": true,
|
|
132
|
+
"channel": "slack",
|
|
133
|
+
"to": "C0AKMF5E0KD",
|
|
134
|
+
"eventTypes": ["completion"]
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Config Fields
|
|
140
|
+
|
|
141
|
+
| Field | Type | Description |
|
|
142
|
+
|-------|------|-------------|
|
|
143
|
+
| `enabled` | boolean | Enable event forwarding |
|
|
144
|
+
| `channel` | string | Delivery channel (default: `"slack"`) |
|
|
145
|
+
| `to` | string | Target channel/user ID |
|
|
146
|
+
| `eventTypes` | string[] | Events to forward: `["completion"]`, `["event"]`, or both |
|
|
147
|
+
| `sessionKey` | string | Optional session key for routing |
|
|
148
|
+
|
|
149
|
+
### How It Works
|
|
150
|
+
|
|
151
|
+
1. Agent pushes a page with `openclaw` config
|
|
152
|
+
2. User opens the page and interacts (fills form, clicks buttons)
|
|
153
|
+
3. Browser sends events via WebSocket to SparkUI server
|
|
154
|
+
4. SparkUI forwards matching events to OpenClaw's `/hooks/agent` endpoint
|
|
155
|
+
5. OpenClaw delivers the message to the specified channel
|
|
156
|
+
6. Agent receives the notification and can respond
|
|
157
|
+
|
|
158
|
+
### Use Cases
|
|
159
|
+
|
|
160
|
+
- **Feedback forms** — get notified when user submits a rating
|
|
161
|
+
- **Approval workflows** — user clicks approve/reject buttons
|
|
162
|
+
- **Data collection** — form submissions with structured data
|
|
163
|
+
- **Checklist completion** — notified when all items are checked
|
|
164
|
+
|
|
165
|
+
## SKILL.md Reference
|
|
166
|
+
|
|
167
|
+
The full `SKILL.md` is located at the root of the SparkUI directory. It contains:
|
|
168
|
+
|
|
169
|
+
- Server location and configuration details
|
|
170
|
+
- Step-by-step instructions for the agent
|
|
171
|
+
- Template data schemas
|
|
172
|
+
- Component reference
|
|
173
|
+
- OpenClaw round-trip configuration
|
|
174
|
+
|
|
175
|
+
The agent reads this file automatically — you don't need to configure it separately.
|
|
176
|
+
|
|
177
|
+
> **Tip:** If you modify the SKILL.md (e.g., to add custom templates or change defaults), the agent will pick up the changes on its next invocation.
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
# Templates
|
|
2
|
+
|
|
3
|
+
SparkUI includes 5 built-in templates for common use cases. Each generates a complete, interactive HTML page with dark theme, responsive layout, and WebSocket connectivity.
|
|
4
|
+
|
|
5
|
+
Use templates via `POST /api/push` with a `template` name and `data` object.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## macro-tracker
|
|
10
|
+
|
|
11
|
+
Daily nutrition and macro tracking dashboard with animated progress bars, macro cards, and a meal log.
|
|
12
|
+
|
|
13
|
+
### Data Schema
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
interface MacroTrackerData {
|
|
17
|
+
date: string; // e.g. "2026-03-14"
|
|
18
|
+
calories: { current: number; target: number };
|
|
19
|
+
protein: { current: number; target: number };
|
|
20
|
+
fat: { current: number; target: number };
|
|
21
|
+
carbs: { current: number; target: number };
|
|
22
|
+
meals?: Array<{
|
|
23
|
+
name: string; // e.g. "Grilled chicken salad"
|
|
24
|
+
calories: number;
|
|
25
|
+
time: string; // e.g. "12:00 PM"
|
|
26
|
+
}>;
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Example
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"template": "macro-tracker",
|
|
35
|
+
"data": {
|
|
36
|
+
"date": "2026-03-14",
|
|
37
|
+
"calories": { "current": 1250, "target": 1900 },
|
|
38
|
+
"protein": { "current": 62, "target": 86 },
|
|
39
|
+
"fat": { "current": 45, "target": 95 },
|
|
40
|
+
"carbs": { "current": 15, "target": 25 },
|
|
41
|
+
"meals": [
|
|
42
|
+
{ "name": "Eggs & bacon", "calories": 450, "time": "6:30 AM" },
|
|
43
|
+
{ "name": "Grilled chicken salad", "calories": 480, "time": "12:00 PM" },
|
|
44
|
+
{ "name": "Greek yogurt with almonds", "calories": 320, "time": "3:00 PM" }
|
|
45
|
+
]
|
|
46
|
+
},
|
|
47
|
+
"ttl": 7200
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Features
|
|
52
|
+
|
|
53
|
+
- Animated progress bars with percentage labels
|
|
54
|
+
- Color-coded macro cards (Calories, Protein, Fat, Carbs)
|
|
55
|
+
- Meal log with times and calorie counts
|
|
56
|
+
- Auto-refreshes every 30 seconds
|
|
57
|
+
- Over-target warnings
|
|
58
|
+
|
|
59
|
+
> **Screenshot:** [screenshots/macro-tracker.png](../screenshots/macro-tracker.png)
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## checkout
|
|
64
|
+
|
|
65
|
+
Stripe-inspired checkout page with product display, quantity selector, promo code field, and payment form. **Demo only — no real payment processing.**
|
|
66
|
+
|
|
67
|
+
### Data Schema
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
interface CheckoutData {
|
|
71
|
+
product: {
|
|
72
|
+
name: string; // Product name
|
|
73
|
+
description: string; // Short description
|
|
74
|
+
price: number; // Unit price
|
|
75
|
+
image?: string; // Emoji (e.g. "⚡") or URL
|
|
76
|
+
imageUrl?: string; // Product image URL (overrides image)
|
|
77
|
+
};
|
|
78
|
+
shipping?: number; // Shipping cost (default: 0)
|
|
79
|
+
tax?: number; // Tax amount (default: 0)
|
|
80
|
+
currency?: string; // Currency code (default: "USD")
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Example
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"template": "checkout",
|
|
89
|
+
"data": {
|
|
90
|
+
"product": {
|
|
91
|
+
"name": "SparkUI Pro",
|
|
92
|
+
"description": "Unlimited ephemeral UIs for your agent",
|
|
93
|
+
"price": 29.99,
|
|
94
|
+
"image": "⚡"
|
|
95
|
+
},
|
|
96
|
+
"shipping": 0,
|
|
97
|
+
"tax": 2.40,
|
|
98
|
+
"currency": "USD"
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Features
|
|
104
|
+
|
|
105
|
+
- "DEMO MODE" banner (no real charges)
|
|
106
|
+
- Quantity selector with live price updates
|
|
107
|
+
- Promo code input
|
|
108
|
+
- Simulated payment form (card number, expiry, CVC)
|
|
109
|
+
- Order summary with subtotal, shipping, tax, and total
|
|
110
|
+
- Sends `completion` event with order data on "Pay" click
|
|
111
|
+
|
|
112
|
+
> **Screenshot:** [screenshots/checkout.png](../screenshots/checkout.png)
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## workout-timer
|
|
117
|
+
|
|
118
|
+
Fitness-app-quality workout page with exercise rounds, rest timer, warmup/cooldown checklists, and progress tracking.
|
|
119
|
+
|
|
120
|
+
### Data Schema
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
interface WorkoutTimerData {
|
|
124
|
+
title: string; // Workout name
|
|
125
|
+
subtitle?: string; // e.g. "Day 3 — Push"
|
|
126
|
+
warmup?: Array<{ text: string }>;
|
|
127
|
+
exercises: Array<{
|
|
128
|
+
name: string; // Exercise name
|
|
129
|
+
reps: string; // e.g. "12 reps" or "30 sec"
|
|
130
|
+
notes?: string; // Form tips, etc.
|
|
131
|
+
}>;
|
|
132
|
+
rounds?: number; // Number of rounds (default: 3)
|
|
133
|
+
restSeconds?: number; // Rest between rounds (default: 60)
|
|
134
|
+
cooldown?: Array<{ text: string }>;
|
|
135
|
+
estimatedMinutes?: number;
|
|
136
|
+
estimatedCalories?: number;
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Example
|
|
141
|
+
|
|
142
|
+
```json
|
|
143
|
+
{
|
|
144
|
+
"template": "workout-timer",
|
|
145
|
+
"data": {
|
|
146
|
+
"title": "Upper Body Blast",
|
|
147
|
+
"subtitle": "Day 1 — Push",
|
|
148
|
+
"warmup": [
|
|
149
|
+
{ "text": "Arm circles — 30 sec" },
|
|
150
|
+
{ "text": "Band pull-aparts — 15 reps" }
|
|
151
|
+
],
|
|
152
|
+
"exercises": [
|
|
153
|
+
{ "name": "Push-ups", "reps": "15 reps", "notes": "Full range of motion" },
|
|
154
|
+
{ "name": "Dumbbell press", "reps": "12 reps", "notes": "Slow negatives" },
|
|
155
|
+
{ "name": "Lateral raises", "reps": "12 reps" }
|
|
156
|
+
],
|
|
157
|
+
"rounds": 3,
|
|
158
|
+
"restSeconds": 60,
|
|
159
|
+
"cooldown": [
|
|
160
|
+
{ "text": "Chest stretch — 30 sec each side" },
|
|
161
|
+
{ "text": "Shoulder stretch — 30 sec each side" }
|
|
162
|
+
],
|
|
163
|
+
"estimatedMinutes": 35,
|
|
164
|
+
"estimatedCalories": 280
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Features
|
|
170
|
+
|
|
171
|
+
- Stats bar: rounds, exercises, estimated time and calories
|
|
172
|
+
- Interactive warmup/cooldown checklists
|
|
173
|
+
- Round tracker with exercise completion
|
|
174
|
+
- Built-in rest timer with start/skip controls
|
|
175
|
+
- Progress tracking across all rounds
|
|
176
|
+
- Sends `completion` event when workout finishes
|
|
177
|
+
|
|
178
|
+
> **Screenshot:** [screenshots/workout-timer.png](../screenshots/workout-timer.png)
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## feedback-form
|
|
183
|
+
|
|
184
|
+
Simple feedback form with star rating, text input, and optional extra questions. Sends completion event with all form data.
|
|
185
|
+
|
|
186
|
+
### Data Schema
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
interface FeedbackFormData {
|
|
190
|
+
title?: string; // Form title (default: "Feedback")
|
|
191
|
+
subtitle?: string; // Subtitle text
|
|
192
|
+
questions?: string[]; // Optional extra text input fields
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Example
|
|
197
|
+
|
|
198
|
+
```json
|
|
199
|
+
{
|
|
200
|
+
"template": "feedback-form",
|
|
201
|
+
"data": {
|
|
202
|
+
"title": "How was your experience?",
|
|
203
|
+
"subtitle": "We'd love to hear from you",
|
|
204
|
+
"questions": [
|
|
205
|
+
"What did you like most?",
|
|
206
|
+
"What could be improved?"
|
|
207
|
+
]
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Features
|
|
213
|
+
|
|
214
|
+
- 5-star rating selector
|
|
215
|
+
- Free-text feedback textarea
|
|
216
|
+
- Optional extra question fields
|
|
217
|
+
- Success animation on submit
|
|
218
|
+
- Sends `completion` event with `{ rating, feedback, ...extraFields }`
|
|
219
|
+
|
|
220
|
+
> **Screenshot:** [screenshots/feedback-form.png](../screenshots/feedback-form.png)
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## ws-test
|
|
225
|
+
|
|
226
|
+
WebSocket connectivity test page for debugging and development. Tests all WS bridge features.
|
|
227
|
+
|
|
228
|
+
### Data Schema
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
interface WsTestData {
|
|
232
|
+
// No required data — this template works with defaults
|
|
233
|
+
}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Example
|
|
237
|
+
|
|
238
|
+
```json
|
|
239
|
+
{
|
|
240
|
+
"template": "ws-test",
|
|
241
|
+
"data": {}
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Features
|
|
246
|
+
|
|
247
|
+
- Live connection status indicator
|
|
248
|
+
- Send click events and custom events
|
|
249
|
+
- Test form that sends completion events
|
|
250
|
+
- Real-time message log showing all WebSocket traffic
|
|
251
|
+
- Useful for verifying WebSocket connectivity and event forwarding
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## Using Templates
|
|
256
|
+
|
|
257
|
+
### Push a template page
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
curl -X POST http://localhost:3457/api/push \
|
|
261
|
+
-H "Authorization: Bearer $PUSH_TOKEN" \
|
|
262
|
+
-H "Content-Type: application/json" \
|
|
263
|
+
-d '{
|
|
264
|
+
"template": "TEMPLATE_NAME",
|
|
265
|
+
"data": { ... },
|
|
266
|
+
"ttl": 3600
|
|
267
|
+
}'
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Update a template page
|
|
271
|
+
|
|
272
|
+
```bash
|
|
273
|
+
curl -X PATCH http://localhost:3457/api/pages/PAGE_ID \
|
|
274
|
+
-H "Authorization: Bearer $PUSH_TOKEN" \
|
|
275
|
+
-H "Content-Type: application/json" \
|
|
276
|
+
-d '{
|
|
277
|
+
"data": { ... }
|
|
278
|
+
}'
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
When updating, you can just send `data` — SparkUI re-renders using the page's original template.
|
|
282
|
+
|
|
283
|
+
### List available templates
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
curl http://localhost:3457/ | jq .templates
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
> **Tip:** For custom layouts that don't fit a template, use the [compose API](./components.md) to build pages from individual components.
|