Firmware design-system handoff (skill)
Use this skill when a user has an existing firmware repo with a
hand-rolled web UI (LittleFS / SPIFFS / similar partition, no build
step on the device) and wants the design layer rebuilt as a real,
token-driven design system that:
- ships as a drop-in package, not a refactor PR,
- backs up the existing
data/ before touching anything,
- leaves behavior untouched (no JS rewrites beyond minimum hooks),
- comes with a visual regression page hosted on the device itself,
- is applyable on Windows with a double-click.
Inputs to gather (questions_v2 first)
Always ask these before writing anything:
- Repo + screen list. Which firmware (path / repo URL), and which
pages/screens does the UI have? Need: home, settings, log/monitor,
one or more device-specific control panels, file explorer, etc.
- Existing CSS state. Are there hand-rolled stylesheets per page,
or one global CSS, and is there a dark-mode variant? Get the file
names — they show up in the apply script's plan.
- Theme toggle mechanism.
body.dark class? [data-theme] attr?
localStorage key? Match the existing convention so the toggle keeps
working.
- Chart library. ECharts? Chart.js? None? CDN or self-host? If
CDN: which version is pinned. The skill emits a chart-theme
helper that reads CSS vars regardless of library.
- Fonts. Self-hosted WOFF2 (preferred for offline devices) or
system stack? File-size budget if relevant — embedded partitions
are usually 1-2 MB.
- Variations to expose as Tweaks. Optional — usually no, this is
production output, not a design exploration.
- Scope. Just the design layer, or also a list of bugs/issues
that need to be fixed alongside (e.g. "the X panel is broken").
- Branding constraints. Which colors are "the brand"? What can
be changed and what is sacred?
- Iconography. Self-host PNG/SVG, icon font, or no icons?
- Apply target. Windows / macOS / Linux for the script. Default
to Windows since most firmware-flashing flows are Windows.
Package structure to emit
<project_name>_design_package/
├── README.md
├── handoff.md
├── SKILL.md <-- this file, for next time
├── apply.ps1
├── apply.bat
├── data/ <-- mirrors firmware data/ structure
│ ├── ds-tokens.css
│ ├── components.css
│ ├── theme-toggle.js
│ ├── <chart>-theme.js
│ ├── design.html
│ └── fonts/
└── templates/
├── index.html.template
└── <each-page>.html.template
Hard rules
- One tokens file. All color, type, space, radius, shadow, motion.
Light + dark via the existing convention (
body.dark AND
[data-theme="dark"] for safety). No second source of truth.
- components.css uses var(--*) only. Zero raw hex outside
ds-tokens.css. Search for
#[0-9a-f] after writing — should match
zero lines.
- Match existing class names. components.css must shadow the
legacy CSS without markup changes for as many components as
possible. The user removes the legacy CSS in the final patch, not
the first.
- Sentinels in templates. Every patch block in
templates/*.template
is wrapped in <!-- DS:NAME:BEGIN --> … <!-- DS:NAME:END -->
comments so the receiver knows exactly what to paste.
- Idempotent JS hooks. Use a
data-bound="1" attribute on each
bound element so re-running on a re-rendered DOM doesn't double-bind.
Listen for a project-specific <page>:rendered event for re-binding.
- Chart theme reads tokens. Helper function calls
getComputedStyle(document.body).getPropertyValue('--…') so theme
swap is one chart.setOption(theme(), true) call.
- Backup before copy. apply.ps1 always writes a timestamped zip
unless
-NoBackup. Default mode is interactive (y/n/q per file);
-Force skips prompts; -WhatIf is a dry run.
- No git, no build, no flash. Script copies files. handoff.md
documents what's left for the receiver (Claude Code).
- /design.html lives on the device. Renders every component in
light and dark side-by-side. Hosting it from the firmware means
visual regression after each flash is one URL away.
Output discipline
- ds-tokens.css opens with a comment block explaining the dual-selector
convention and the apply order.
- components.css has a numbered table-of-contents at the top.
- Each template's leading comment names the file it patches and the
scope (full replace vs. block replace vs. append).
- handoff.md is structured as Patch A/B/C/D/E with explicit commit
messages. The receiver should be able to land each as a separate
PR if they want.
- README.md has Quick Start, Apply Order, Smoke Test, Rollback,
"What the script does/doesn't do" — in that order.
- apply.ps1 uses
[CmdletBinding(SupportsShouldProcess=$true)] so
-WhatIf works without extra code.
Anti-patterns to avoid
- Self-hosting a chart library "for offline use" without checking
with the user — it bloats the partition and is rarely worth it.
Default to CDN, document the fallback.
- Hand-rolled icons. Use what's already in the firmware's
assets/
or text labels. Don't invent SVG icons.
- Adding routes/handlers to the firmware's HTTP server. The design
layer is files-only; routes are out of scope.
- Aggressive markup refactors. If a class name already exists, match
it. The receiver should be able to land the package without
rewriting partials.
When NOT to use this skill
- One-off styling tweaks (use a single PATCH.md instead).
- The user wants to explore design directions (use design_canvas).
- A from-scratch new firmware UI (build with the standard frontend
design skill; this skill is for retrofitting an existing repo).
Source: rvdbreemen/OTGW-firmware — distributed by TomeVault.
1---2name: rvdbreemen-otgw-firmware-otgw-firmware3description: Firmware design-system handoff (skill)4---56# Firmware design-system handoff (skill)78Use this skill when a user has an existing firmware repo with a9hand-rolled web UI (LittleFS / SPIFFS / similar partition, no build10step on the device) and wants the design layer rebuilt as a real,11token-driven design system that:1213- ships as a drop-in package, not a refactor PR,14- backs up the existing `data/` before touching anything,15- leaves behavior untouched (no JS rewrites beyond minimum hooks),16- comes with a visual regression page hosted on the device itself,17- is applyable on Windows with a double-click.1819## Inputs to gather (questions_v2 first)2021Always ask these before writing anything:22231. **Repo + screen list.** Which firmware (path / repo URL), and which24 pages/screens does the UI have? Need: home, settings, log/monitor,25 one or more device-specific control panels, file explorer, etc.262. **Existing CSS state.** Are there hand-rolled stylesheets per page,27 or one global CSS, and is there a dark-mode variant? Get the file28 names — they show up in the apply script's plan.293. **Theme toggle mechanism.** `body.dark` class? `[data-theme]` attr?30 localStorage key? Match the existing convention so the toggle keeps31 working.324. **Chart library.** ECharts? Chart.js? None? CDN or self-host? If33 CDN: which version is pinned. The skill emits a chart-theme34 helper that reads CSS vars regardless of library.355. **Fonts.** Self-hosted WOFF2 (preferred for offline devices) or36 system stack? File-size budget if relevant — embedded partitions37 are usually 1-2 MB.386. **Variations to expose as Tweaks.** Optional — usually no, this is39 production output, not a design exploration.407. **Scope.** Just the design layer, or also a list of bugs/issues41 that need to be fixed alongside (e.g. "the X panel is broken").428. **Branding constraints.** Which colors are "the brand"? What can43 be changed and what is sacred?449. **Iconography.** Self-host PNG/SVG, icon font, or no icons?4510. **Apply target.** Windows / macOS / Linux for the script. Default46 to Windows since most firmware-flashing flows are Windows.4748## Package structure to emit4950```51<project_name>_design_package/52├── README.md53├── handoff.md54├── SKILL.md <-- this file, for next time55├── apply.ps156├── apply.bat57├── data/ <-- mirrors firmware data/ structure58│ ├── ds-tokens.css59│ ├── components.css60│ ├── theme-toggle.js61│ ├── <chart>-theme.js62│ ├── design.html63│ └── fonts/64└── templates/65 ├── index.html.template66 └── <each-page>.html.template67```6869## Hard rules7071- **One tokens file.** All color, type, space, radius, shadow, motion.72 Light + dark via the existing convention (`body.dark` AND73 `[data-theme="dark"]` for safety). No second source of truth.74- **components.css uses var(--*) only.** Zero raw hex outside75 ds-tokens.css. Search for `#[0-9a-f]` after writing — should match76 zero lines.77- **Match existing class names.** components.css must shadow the78 legacy CSS without markup changes for as many components as79 possible. The user removes the legacy CSS in the final patch, not80 the first.81- **Sentinels in templates.** Every patch block in `templates/*.template`82 is wrapped in `<!-- DS:NAME:BEGIN -->` … `<!-- DS:NAME:END -->`83 comments so the receiver knows exactly what to paste.84- **Idempotent JS hooks.** Use a `data-bound="1"` attribute on each85 bound element so re-running on a re-rendered DOM doesn't double-bind.86 Listen for a project-specific `<page>:rendered` event for re-binding.87- **Chart theme reads tokens.** Helper function calls88 `getComputedStyle(document.body).getPropertyValue('--…')` so theme89 swap is one `chart.setOption(theme(), true)` call.90- **Backup before copy.** apply.ps1 always writes a timestamped zip91 unless `-NoBackup`. Default mode is interactive (y/n/q per file);92 `-Force` skips prompts; `-WhatIf` is a dry run.93- **No git, no build, no flash.** Script copies files. handoff.md94 documents what's left for the receiver (Claude Code).95- **/design.html lives on the device.** Renders every component in96 light and dark side-by-side. Hosting it from the firmware means97 visual regression after each flash is one URL away.9899## Output discipline100101- ds-tokens.css opens with a comment block explaining the dual-selector102 convention and the apply order.103- components.css has a numbered table-of-contents at the top.104- Each template's leading comment names the file it patches and the105 scope (full replace vs. block replace vs. append).106- handoff.md is structured as Patch A/B/C/D/E with explicit commit107 messages. The receiver should be able to land each as a separate108 PR if they want.109- README.md has Quick Start, Apply Order, Smoke Test, Rollback,110 "What the script does/doesn't do" — in that order.111- apply.ps1 uses `[CmdletBinding(SupportsShouldProcess=$true)]` so112 `-WhatIf` works without extra code.113114## Anti-patterns to avoid115116- Self-hosting a chart library "for offline use" without checking117 with the user — it bloats the partition and is rarely worth it.118 Default to CDN, document the fallback.119- Hand-rolled icons. Use what's already in the firmware's `assets/`120 or text labels. Don't invent SVG icons.121- Adding routes/handlers to the firmware's HTTP server. The design122 layer is files-only; routes are out of scope.123- Aggressive markup refactors. If a class name already exists, match124 it. The receiver should be able to land the package without125 rewriting partials.126127## When NOT to use this skill128129- One-off styling tweaks (use a single PATCH.md instead).130- The user wants to explore design directions (use design_canvas).131- A from-scratch new firmware UI (build with the standard frontend132 design skill; this skill is for retrofitting an existing repo).133134---135> Source: [rvdbreemen/OTGW-firmware](https://github.com/rvdbreemen/OTGW-firmware) — distributed by [TomeVault](https://tomevault.io).136<!-- tomevault:4.0:skill_md:2026-06-30 -->