🧪 Skills

WonderDash

--- name: wonderdash-widgets description: Create and manage widgets on the user's WonderDash mobile dashboard via GitHub version: 5.0.0 user-invocable: false metadata: openclaw: requires:

v1.0.0
❤️ 0
⬇️ 169
👁 1
Share

Description


name: wonderdash-widgets description: Create and manage widgets on the user's WonderDash mobile dashboard via GitHub version: 5.0.0 user-invocable: false

metadata: openclaw: requires: bins: - git - ssh os: - darwin - linux emoji: "\U0001F4F1"

WonderDash Widget Skill (v5 — WebView + Index + File-Per-Widget)

You manage widgets on the user's WonderDash mobile dashboard by writing individual JSON files to a GitHub repository, with a dashboard.json index that controls visibility and order.

Setup

WonderDash sends you a setup message containing:

  • Repo URL: git@github.com:{username}/wonderdash-widgets.git
  • SSH Private Key: An Ed25519 key in OpenSSH PEM format

Save the SSH key and configure access:

# Save the key
cat > ~/.ssh/wonderdash_deploy << 'KEYEOF'
<paste the key here>
KEYEOF
chmod 600 ~/.ssh/wonderdash_deploy

# Add SSH config
cat >> ~/.ssh/config << 'EOF'
Host wonderdash-github
  HostName github.com
  User git
  IdentityFile ~/.ssh/wonderdash_deploy
  IdentitiesOnly yes
EOF

# Clone the repo
git clone wonderdash-github:{username}/wonderdash-widgets.git

Repo Structure

wonderdash-widgets/
├── dashboard.json          ← Index: controls which widgets are visible and their order
├── widgets/
│   ├── weather.json        ← Widget content
│   ├── portfolio.json
│   ├── tasks.json
│   └── old-widget.json     ← Archived: file exists but not listed in index

Dashboard Index (dashboard.json)

The index file at the repo root controls which widgets appear and in what order:

{
  "widgets": ["weather", "portfolio", "tasks"]
}
  • Array order = display order on the dashboard
  • Each entry is a widget ID referencing widgets/{id}.json
  • Widgets not in the array are hidden (archived) — their files are kept
  • If dashboard.json doesn't exist, all widgets in widgets/ are shown (unordered)

Widget Format

Each widget file (widgets/{id}.json) contains a single widget object:

{
  "id": "weather",
  "size": "S",
  "renderer": "webview",
  "html": "<div>...</div>"
}

Fields:

  • id (string): Unique slug identifier — must match the filename (e.g., weatherwidgets/weather.json)
  • size ("S" | "M" | "L"): Widget display size
  • renderer ("webview" | "html", optional): Rendering engine. Default is "html" (native). Use "webview" for rich visuals.
  • html (string): Self-contained HTML with inline styles

Renderers

"webview" — Rich widgets (recommended for most widgets)

Renders in a full browser engine. Supports:

  • CSS gradients, shadows, border-radius, backdrop-filter
  • CSS animations (@keyframes, transition)
  • SVG (charts, icons, sparklines)
  • Canvas
  • JavaScript (live clocks, counters, data formatting)
  • Base64 inline images (<img src="data:image/png;base64,...">)
  • Full CSS flexbox and grid

The app wraps your HTML in a document with dark theme defaults (background: #1f2937, color: #fff, system font). You just provide the body content.

"html" — Lightweight widgets (default)

Renders via native components (no browser). Faster and lighter, but limited to basic HTML elements and inline styles. No JS, no animations, no gradients, no SVG. Good for simple text/number displays.

Use "webview" for anything visual. Use "html" only for the simplest text-only widgets where performance matters more than appearance.

Widget Sizes

Modeled after Apple's iOS widget system:

Size Dimensions Layout Best for
S (Small) 174 × 174 px Square, 1 column Single metric, status, icon
M (Medium) 361 × 174 px Full width, short Info card, sparkline, summary
L (Large) 361 × 382 px Full width, tall Chart, table, calendar, feed

Two small widgets fit side-by-side. Medium and large span the full width.

Creating a Widget

Two steps: create the widget file, then add it to the index.

cd wonderdash-widgets
mkdir -p widgets

# 1. Create the widget file
cat > widgets/weather.json << 'EOF'
{
  "id": "weather",
  "size": "S",
  "renderer": "webview",
  "html": "..."
}
EOF

# 2. Add to dashboard.json index
# If dashboard.json doesn't exist yet, create it:
echo '{ "widgets": ["weather"] }' > dashboard.json
# If it already exists, read it, append the new ID to the widgets array, and write it back.

git add widgets/weather.json dashboard.json
git commit -m "Add weather widget"
git push

Updating a Widget

Edit the widget file and push. No change to dashboard.json needed unless reordering.

git add widgets/weather.json
git commit -m "Update weather widget"
git push

Reordering / Archiving / Deleting

  • Reorder: Rearrange the array in dashboard.json, commit, push.
  • Archive: Remove the ID from dashboard.json — widget file stays in repo.
  • Restore: Add the ID back to the array.
  • Delete permanently: Remove from dashboard.json + git rm widgets/{id}.json, commit, push.

The user pulls down on their dashboard to refresh. Changes appear after a manual refresh.

Design Guidelines

  • Dark theme. Background: #1f2937 (gray-800). Text: #ffffff. Secondary: #9ca3af (gray-400). Accent: #3b82f6 (blue-500). Success: #22c55e. Warning: #eab308. Error: #ef4444.
  • Self-contained. No external resources (CDNs, APIs, remote images). Everything inline.
  • JSON escaping. Escape quotes in HTML when inside JSON strings. Use \" for double quotes inside style attributes, or use single quotes in HTML (style='...').
  • Fit the size. Content must fit within the widget dimensions without scrolling. WebView has overflow: hidden by default.
  • Subtle animation. Use gentle transitions and animations to add polish — avoid flashy or distracting effects.

Examples

Small — Gradient metric (widgets/temperature.json)

A temperature display with gradient background and subtle glow.

{
  "id": "temperature",
  "size": "S",
  "renderer": "webview",
  "html": "<div style='display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;background:linear-gradient(135deg,#1e3a5f,#1f2937);padding:16px'><div style='font-size:11px;color:#60a5fa;text-transform:uppercase;letter-spacing:2px;font-weight:600'>Temperature</div><div style='font-size:52px;font-weight:bold;margin:8px 0;background:linear-gradient(180deg,#fff,#93c5fd);-webkit-background-clip:text;-webkit-text-fill-color:transparent'>72°</div><div style='font-size:13px;color:#9ca3af'>☀️ Sunny</div></div>"
}

Small — Animated status (widgets/api-status.json)

A pulsing status indicator with CSS animation.

{
  "id": "api-status",
  "size": "S",
  "renderer": "webview",
  "html": "<style>@keyframes pulse{0%,100%{opacity:1}50%{opacity:.5}}.pulse{animation:pulse 2s ease-in-out infinite}</style><div style='display:flex;flex-direction:column;align-items:center;justify-content:center;height:100%;padding:16px'><div style='font-size:11px;color:#9ca3af;text-transform:uppercase;letter-spacing:2px;margin-bottom:12px'>API Status</div><div class='pulse' style='width:48px;height:48px;border-radius:50%;background:radial-gradient(circle,#22c55e,#15803d);box-shadow:0 0 20px rgba(34,197,94,0.4);margin-bottom:12px'></div><div style='font-size:15px;font-weight:600;color:#22c55e'>Operational</div><div style='font-size:12px;color:#6b7280;margin-top:4px'>99.9% uptime</div></div>"
}

Medium — SVG sparkline chart (widgets/revenue.json)

A revenue card with an inline SVG sparkline.

{
  "id": "revenue",
  "size": "M",
  "renderer": "webview",
  "html": "<div style='display:flex;align-items:center;height:100%;padding:16px;gap:20px'><div style='flex:1'><div style='font-size:11px;color:#9ca3af;text-transform:uppercase;letter-spacing:1px'>Monthly Revenue</div><div style='font-size:32px;font-weight:bold;margin:6px 0'>$48.2k</div><div style='font-size:13px;color:#22c55e;font-weight:500'>↑ 12.5% vs last month</div></div><div style='width:140px;height:60px'><svg viewBox='0 0 140 60' style='width:100%;height:100%'><defs><linearGradient id='g' x1='0' y1='0' x2='0' y2='1'><stop offset='0%' stop-color='#3b82f6' stop-opacity='0.3'/><stop offset='100%' stop-color='#3b82f6' stop-opacity='0'/></linearGradient></defs><path d='M0,45 L20,40 L40,42 L60,30 L80,35 L100,20 L120,18 L140,10 L140,60 L0,60Z' fill='url(#g)'/><polyline points='0,45 20,40 40,42 60,30 80,35 100,20 120,18 140,10' fill='none' stroke='#3b82f6' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/></svg></div></div>"
}

Medium — Gradient info card (widgets/next-meeting.json)

A meeting card with gradient accent border.

{
  "id": "next-meeting",
  "size": "M",
  "renderer": "webview",
  "html": "<div style='display:flex;align-items:center;height:100%;padding:16px;gap:16px'><div style='width:4px;height:80%;border-radius:2px;background:linear-gradient(180deg,#8b5cf6,#3b82f6)'></div><div style='flex:1'><div style='font-size:11px;color:#9ca3af;text-transform:uppercase;letter-spacing:1px'>Next Meeting</div><div style='font-size:18px;font-weight:bold;margin:6px 0'>Sprint Planning</div><div style='font-size:13px;color:#9ca3af'>2:00 PM — 3:00 PM</div><div style='display:flex;gap:6px;margin-top:8px'><span style='font-size:11px;background:#374151;color:#d1d5db;padding:2px 8px;border-radius:10px'>Team Alpha</span><span style='font-size:11px;background:#374151;color:#d1d5db;padding:2px 8px;border-radius:10px'>Zoom</span></div></div></div>"
}

Large — Price chart with SVG (widgets/btc-price.json)

A Bitcoin price chart with gradient fill, grid lines, and price labels.

{
  "id": "btc-price",
  "size": "L",
  "renderer": "webview",
  "html": "<div style='display:flex;flex-direction:column;height:100%;padding:16px'><div style='display:flex;justify-content:space-between;align-items:baseline;margin-bottom:4px'><div><div style='font-size:11px;color:#9ca3af;text-transform:uppercase;letter-spacing:1px'>Bitcoin</div><div style='font-size:28px;font-weight:bold;margin-top:4px'>$67,432</div></div><div style='text-align:right'><div style='font-size:14px;color:#22c55e;font-weight:600'>+2.4%</div><div style='font-size:12px;color:#6b7280'>24h</div></div></div><div style='flex:1;margin-top:8px;position:relative'><svg viewBox='0 0 330 240' style='width:100%;height:100%' preserveAspectRatio='none'><defs><linearGradient id='cg' x1='0' y1='0' x2='0' y2='1'><stop offset='0%' stop-color='#f59e0b' stop-opacity='0.25'/><stop offset='100%' stop-color='#f59e0b' stop-opacity='0'/></linearGradient></defs><line x1='0' y1='60' x2='330' y2='60' stroke='#374151' stroke-width='0.5'/><line x1='0' y1='120' x2='330' y2='120' stroke='#374151' stroke-width='0.5'/><line x1='0' y1='180' x2='330' y2='180' stroke='#374151' stroke-width='0.5'/><text x='325' y='58' fill='#6b7280' font-size='10' text-anchor='end'>69k</text><text x='325' y='118' fill='#6b7280' font-size='10' text-anchor='end'>67k</text><text x='325' y='178' fill='#6b7280' font-size='10' text-anchor='end'>65k</text><path d='M0,180 C30,175 50,160 80,140 C110,120 130,90 160,100 C190,110 210,130 230,80 C250,40 270,55 300,30 C310,25 320,28 330,20 L330,240 L0,240Z' fill='url(#cg)'/><path d='M0,180 C30,175 50,160 80,140 C110,120 130,90 160,100 C190,110 210,130 230,80 C250,40 270,55 300,30 C310,25 320,28 330,20' fill='none' stroke='#f59e0b' stroke-width='2.5' stroke-linecap='round'/><circle cx='330' cy='20' r='4' fill='#f59e0b'/><circle cx='330' cy='20' r='8' fill='#f59e0b' opacity='0.2'/></svg></div><div style='display:flex;justify-content:space-between;font-size:11px;color:#6b7280;margin-top:4px'><span>6h ago</span><span>4h</span><span>2h</span><span>Now</span></div></div>"
}

Large — Calendar grid (widgets/calendar.json)

A monthly calendar with CSS grid and highlighted dates.

{
  "id": "calendar",
  "size": "L",
  "renderer": "webview",
  "html": "<style>.day{display:flex;align-items:center;justify-content:center;height:36px;border-radius:50%;font-size:13px;color:#d1d5db}.today{background:#3b82f6;color:#fff;font-weight:bold}.event{position:relative}.event::after{content:'';position:absolute;bottom:2px;left:50%;transform:translateX(-50%);width:4px;height:4px;background:#f59e0b;border-radius:50%}.muted{color:#4b5563}</style><div style='display:flex;flex-direction:column;height:100%;padding:16px'><div style='display:flex;justify-content:space-between;align-items:center;margin-bottom:12px'><div style='font-size:16px;font-weight:bold'>March 2026</div><div style='font-size:12px;color:#9ca3af'>3 events</div></div><div style='display:grid;grid-template-columns:repeat(7,1fr);gap:2px;text-align:center'><div style='font-size:11px;color:#6b7280;padding:4px 0'>Su</div><div style='font-size:11px;color:#6b7280;padding:4px 0'>Mo</div><div style='font-size:11px;color:#6b7280;padding:4px 0'>Tu</div><div style='font-size:11px;color:#6b7280;padding:4px 0'>We</div><div style='font-size:11px;color:#6b7280;padding:4px 0'>Th</div><div style='font-size:11px;color:#6b7280;padding:4px 0'>Fr</div><div style='font-size:11px;color:#6b7280;padding:4px 0'>Sa</div><div class='day'>1</div><div class='day today'>2</div><div class='day'>3</div><div class='day event'>4</div><div class='day'>5</div><div class='day'>6</div><div class='day'>7</div><div class='day'>8</div><div class='day'>9</div><div class='day event'>10</div><div class='day'>11</div><div class='day'>12</div><div class='day'>13</div><div class='day'>14</div><div class='day'>15</div><div class='day'>16</div><div class='day'>17</div><div class='day event'>18</div><div class='day'>19</div><div class='day'>20</div><div class='day'>21</div><div class='day'>22</div><div class='day'>23</div><div class='day'>24</div><div class='day'>25</div><div class='day'>26</div><div class='day'>27</div><div class='day'>28</div><div class='day'>29</div><div class='day'>30</div><div class='day'>31</div></div></div>"
}

Example dashboard.json

{
  "widgets": ["temperature", "api-status", "revenue", "next-meeting", "btc-price", "calendar"]
}

Reviews (0)

Sign in to write a review.

No reviews yet. Be the first to review!

Comments (0)

Sign in to join the discussion.

No comments yet. Be the first to share your thoughts!

Compatible Platforms

Pricing

Free

Related Configs