htmlboard 0.4.0 → 0.6.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.
@@ -1,12 +1,14 @@
1
1
  ---
2
2
  name: htmlboard
3
- description: Design UI in plain HTML files and show them side by side on an infinite, live-reloading canvas with the htmlboard CLI. Use when the user asks for mockups, screens, design variants or explorations, components, flyers or any visual proposal, or mentions htmlboard, artboards or designs.json.
3
+ description: Design UI in plain HTML files and show them side by side on an infinite, live-reloading canvas with the htmlboard CLI. Use when the user asks for mockups, screens, design variants or explorations, flyers or any visual proposal, or mentions htmlboard or artboards.
4
4
  ---
5
5
 
6
6
  # HtmlBoard
7
7
 
8
8
  HtmlBoard serves a folder of HTML files as artboards on a zoomable canvas, like a Figma page. Every design is one ordinary HTML file that says its own name and size, so you design by writing HTML and CSS, and the user sees the result update live while you work.
9
9
 
10
+ Two more skills cover the rest when you need it: **htmlboard-components** to write or change a component, **htmlboard-designs-json** when the designs folder has a `designs.json`.
11
+
10
12
  ## Start the canvas
11
13
 
12
14
  Run it in the background, pointed at the designs folder (it is created if missing):
@@ -19,11 +21,11 @@ npx htmlboard designs --open
19
21
  - `-p <port>` picks the port. `--init` adds sample designs; skip it unless the user wants a starter.
20
22
  - If the artboards link to files above the designs folder (`../css/theme.css`), serve from the project root: `npx htmlboard design --root .`
21
23
  - An empty folder gets the samples automatically, so write your first artboard before starting the server.
22
- - If a server is already running for this folder, reuse it. `GET /api/health` answers `{"status":"ok","dir":…}`.
24
+ - Running it again for a folder that already has a canvas doesn't start another: it prints that canvas's URL.
23
25
 
24
26
  ## Write an artboard
25
27
 
26
- One design per file, with its facts in the `<head>`, linking the shared stylesheet (see below):
28
+ One design per file, with its facts in the `<head>`, linking the shared stylesheet and components (see below):
27
29
 
28
30
  ```html
29
31
  <!DOCTYPE html>
@@ -33,7 +35,8 @@ One design per file, with its facts in the `<head>`, linking the shared styleshe
33
35
  <title>Checkout · one page</title> <!-- its name on the canvas -->
34
36
  <meta name="description" content="Address and payment on one screen">
35
37
  <meta name="htmlboard" content="width=390, height=844"> <!-- its size -->
36
- <link rel="stylesheet" href="../styles.css"> <!-- shared tokens and components -->
38
+ <link rel="stylesheet" href="../styles.css"> <!-- shared tokens and classes -->
39
+ <script type="module" src="../components.js"></script> <!-- shared components -->
37
40
  <style>
38
41
  .screen { height: 844px; /* only what this design needs */ }
39
42
  </style>
@@ -47,54 +50,46 @@ One design per file, with its facts in the `<head>`, linking the shared styleshe
47
50
  - Always give the `width`: it is the frame's viewport, and the page's CSS needs it. Give the `height` for fixed sizes (a phone screen, a flyer: the frame cuts at it); leave it out for pages that should grow with their content.
48
51
  - Design at the real size of the target: phone 390×844, tablet 768×1024, desktop 1280×800 (or 1440×900), and the exact size for print or social formats (e.g. 1080×1350).
49
52
  - Use real content in the user's language, not lorem ipsum.
50
- - Relative links to CSS, images, scripts and fonts work (`assets/logo.svg`; `../css/theme.css` with `--root`).
51
- - No build step: plain HTML, CSS and browser JavaScript (ES modules and CDN scripts work).
53
+ - Relative links to CSS, images, scripts and fonts work (`assets/logo.svg`; `../css/theme.css` with `--root`). No build step: plain HTML, CSS and browser JavaScript (ES modules and CDN scripts work).
54
+
55
+ More tags, all optional:
56
+
57
+ - `<meta name="htmlboard:variant" content="?theme=dark · dark">` shows the same file again with that query string, named "<title> · dark": for states the page builds from its URL (themes, empty or error states, data). A variant can also change the size: `content="width=390, height=844 · mobile"` shows a responsive page at a phone's size too, from the same file (`?theme=dark width=390 · dark mobile` does both). One tag per variant; they follow the file.
58
+ - `<meta name="htmlboard:label" content="light">` adds a label to the name of the file's own frame ("Checkout · light"), to tell it from its variants.
59
+ - `category=…` in the `htmlboard` tag sets the explorer's filter (`mobile`, `components`, your own word) when the path and size don't say it.
60
+ - `<meta name="htmlboard" content="skip">` leaves a file out (partials, templates, a page that isn't a design).
52
61
 
53
62
  ## Shared styles
54
63
 
55
64
  Put what the designs share in one stylesheet instead of repeating it in every file: it keeps the designs consistent and spares writing the same CSS again.
56
65
 
57
- - The designs folder has a `styles.css` at its top (sample projects start with one). Read it before writing a design and use its tokens (`var(--accent)`) and classes (`.btn`, `.card`, …).
58
- - If there is none and the project already has a stylesheet or design tokens, link those. Otherwise create `styles.css` with your first design: colors, type and spacing as custom properties, the base styles, and the components you'll repeat.
66
+ - The designs folder has a `styles.css` at its top (sample projects start with one). Before writing a design, see what the designs already share: `npx htmlboard catalog <designs folder>` prints it in a few lines, read from the files (each stylesheet's variables and classes, the scripts, the components with their attributes and an example). Use what fits (`var(--accent)`, `.btn`, `<tx-item>`) and add what's missing; open a file only for what the list doesn't say.
67
+ - If there is none and the project already has a stylesheet or design tokens, link those. Otherwise create `styles.css` with your first design: colors, type and spacing as custom properties, the base styles, and the classes you'll repeat.
59
68
  - Link it with a relative path: `styles.css` from the top of the folder, `../styles.css` from a section folder.
60
- - A design's own `<style>` holds only what is specific to it. When a second design needs the same thing, move it to `styles.css`.
61
- - Split it when it grows (`components/forms.css`, `charts.css`) and link the extra files where they are used.
69
+ - A design's own `<style>` holds only what is specific to it. When a second design needs the same thing, move it to `styles.css`. Split it when it grows (`forms.css`, `charts.css`) and link the extra files where they are used.
62
70
  - Editing `styles.css` restyles every design that links it, which is the point for a product's screens. For one-off explorations that should keep their look (a different style, logo options), style them in their own file instead.
63
71
 
64
- More tags, all optional:
72
+ ## Components
65
73
 
66
- - `category=…` in the `htmlboard` tag files the design under the explorer's filters: `mobile`, `tablet`, `desktop`, `components` or your own word. Usually not needed: it comes from words in the path, then from the size when it is a screen's.
67
- - `<meta name="htmlboard:variant" content="?theme=dark · dark">` shows the same file again with that query string, named "<title> · dark". Use it for states the page builds from its URL (themes, empty or error states, data). Add one tag per variant; they follow the file.
68
- - `<meta name="htmlboard:label" content="light">` adds a label to the name of the file's own frame ("Checkout · light"), to tell it from its variants.
69
- - `<meta name="htmlboard" content="skip">` leaves a file out (partials, templates, a page that isn't a design).
74
+ Markup that designs repeat (a sidebar, a tab bar, a list row, a card with content) goes in a component, a file in `components/` that designs use as one tag instead of the block: `<tx-item icon="☕" name="Blue Bottle" amount="-$6.75"></tx-item>`.
75
+
76
+ - The catalog lists the project's components with their attributes, an example and the designs that use them. Use them; don't copy their markup into designs.
77
+ - Make one when a second design repeats a block (or a design repeats it three times); not for what a `styles.css` class already does, nor in one-off explorations. To write or change one, use the htmlboard-components skill.
70
78
 
71
79
  ## Group and order
72
80
 
73
81
  - **A folder is a section** (a row on the canvas), named after the folder. Put related designs in a folder: `designs/03-checkout/`.
74
82
  - **Number prefixes set the order** of files and folders: `01-one-page.html`, `02-steps.html`. They don't show in names or links, so you can renumber freely. Files at the top of the designs folder form a first row without a title.
75
83
  - New files and folders show up on the canvas by themselves; you don't register them anywhere.
76
-
77
- **`designs.json`** is optional. When a project has one (in the designs folder), it curates: sections with titles (accents, capitals, an order across folders), and values that win over the files'. Designs it doesn't list still show after the ones it lists, in their folder's section, unless it says `"unlisted": "hide"`. If the project's designs.json groups designs by hand, add a new design to the right section there:
78
-
79
- ```json
80
- {
81
- "sections": [
82
- { "title": "Checkout · mobile", "designs": ["03-checkout/01-one-page.html", "03-checkout/02-steps.html"] },
83
- { "title": "Launch flyers", "folder": "04-flyers" }
84
- ]
85
- }
86
- ```
87
-
88
- An entry is a file name (its variants follow it), or `{ "file", "title", "width", "height", "category", "description" }` to override the file. `"folder"` brings a whole folder. `npx htmlboard migrate <folder>` moves an old designs.json's sizes, names and variants into the files (`--write` to apply; without it, it only shows the plan).
84
+ - A `designs.json` in the designs folder, when there is one, curates the canvas (section titles, an order across folders, designs it hides): use the htmlboard-designs-json skill before adding, moving or renaming designs there.
89
85
 
90
86
  ## Live reload
91
87
 
92
- - Saving an artboard's HTML reloads just that frame; the user's view stays put. A new name or size in its `<head>` updates in place.
93
- - Saving a file artboards use (a stylesheet, a script, an image, data) reloads the artboards that loaded it.
94
- - Adding, removing or moving artboards, or saving `designs.json`, rebuilds the canvas.
88
+ Saving a design reloads its frame, saving a file designs use (a stylesheet, a component, an image) reloads the designs that loaded it, and new or removed designs show up by themselves. The user's view stays put: there is nothing to refresh.
95
89
 
96
90
  ## Working with the user
97
91
 
98
92
  - Put variants in separate files next to each other (`01-hero-a.html`, `02-hero-b.html`) instead of overwriting the current design, so they can be compared on the canvas. Keep the current one as the reference until the user picks.
99
- - Say which files you created or changed and what to look at; the user is watching the canvas, not the code. Link straight to an artboard with `http://localhost:3000/#<id>`: the id is the file's path without prefixes and `.html`, other symbols turned into `-` (`03-checkout/02-steps.html` → `checkout-steps`; a variant adds its query: `checkout-steps-theme-dark`).
100
- - If you can browse or take screenshots, open the artboard directly (`http://localhost:3000/<file>`) to check it at its real size before reporting back. Fix overflow, clipped text and broken images first.
93
+ - Say which files you created or changed and what to look at; the user is watching the canvas, not the code. Link straight to a design with its file after the `#`: `http://localhost:3000/#03-checkout/02-steps.html`.
94
+ - Before reporting back, run `npx htmlboard check <designs folder>` (or a design's file): the canvas open in the user's browser loads each design again and lists what went wrong (script errors, missing files and components, fonts that didn't load, content cut at the frame's edge, text cut off or spilling out). Fix it and run it again. A note about content below a fixed-height frame is fine for a screen that scrolls, not for a flyer. If it says the canvas isn't open, ask the user to open its URL.
95
+ - The check can't judge looks (colors, spacing, alignment). If you can take screenshots, also look at the design at its real size (`http://localhost:3000/<file>`).
@@ -0,0 +1,36 @@
1
+ ---
2
+ name: htmlboard-components
3
+ description: Write or change an htmlboard component, a file in components/ that designs use as a custom element (components/tx-item.html is <tx-item>). Use when a block repeats across htmlboard designs, or before creating or editing a file in components/.
4
+ ---
5
+
6
+ # HtmlBoard components
7
+
8
+ A component is markup that designs repeat (a sidebar, a tab bar, a list row, a card with content), written once and used as one tag: `<tx-item icon="☕" name="Blue Bottle" amount="-$6.75"></tx-item>`. The htmlboard skill covers the designs themselves.
9
+
10
+ - `components/tx-item.html`, at the top of the designs folder, is `<tx-item>`: the file name is the tag, with a hyphen and no number prefix.
11
+ - Designs load `components.js` once, after their stylesheet: `<script type="module" src="../components.js"></script>`. If the designs folder has no `components.js`, run `npx htmlboard components <designs folder>`.
12
+ - See what exists first: `npx htmlboard catalog <designs folder>` lists the components with their attributes, an example and the designs that use them.
13
+
14
+ A component file is a piece of HTML (no `<!DOCTYPE>`, `<html>`, `<head>` or `<body>`):
15
+
16
+ ```html
17
+ <!-- <tx-item icon="💼" name="Invoice #1042" meta="Yesterday" amount="+$3,450.00" positive></tx-item> -->
18
+ <div class="icon">{{icon}}</div>
19
+ <div class="what"><b>{{name}}</b> <span class="muted">{{meta}}</span></div>
20
+ <div class="amount">{{amount}}</div>
21
+
22
+ <style>
23
+ & { display: flex; align-items: center; gap: 14px; } /* & is the element itself */
24
+ .icon { width: 40px; height: 40px; border-radius: 12px; background: var(--surface-2); }
25
+ &[positive] .amount { color: var(--emerald); }
26
+ </style>
27
+ ```
28
+
29
+ - First line: a comment with an example of use, with real values, every attribute and its variants side by side. The catalog shows it, and it is the component's preview on the canvas.
30
+ - `{{name}}` is the element's `name="…"` attribute, as text. Content goes in slots: `<slot></slot>` takes the element's children, `<slot name="actions"></slot>` its children with `slot="actions"`, and what a slot holds shows when nothing fills it.
31
+ - No logic in the markup: variants are attributes styled in CSS (`&[positive]`), and a list is several elements.
32
+ - Its `<style>` only reaches inside the element, which is a block box unless `&` says otherwise. `styles.css` applies inside too: build with its classes (`card`, `btn`, `muted`) and name the component's own parts with names it doesn't use. A design's own `<style>` comes after and can restyle one element, but its selectors reach inside components too, so keep them specific.
33
+ - `<script>` runs for each element once it is built, with `this` as the element. Use it sparingly, a few lines for what markup and CSS can't do, like marking the current link (`<app-sidebar active="Customers">`) or a toggle. No fetching, data or frameworks.
34
+ - Relative links in a component start from its file (`../01-screens/02-customers.html`).
35
+ - Close the tag: `<tx-item …></tx-item>`, never `<tx-item />`. A component can't be a table's row or cell itself (the browser moves it out of the `<table>`), but it works inside a cell: `<td><org-cell …></org-cell></td>`. Where it sits (fixed, margins, the grid around it) belongs to the design.
36
+ - Editing a component changes every design that uses it, like `styles.css`. Afterwards, `npx htmlboard check <designs folder>` lists components that weren't built and errors in their scripts.
@@ -0,0 +1,25 @@
1
+ ---
2
+ name: htmlboard-designs-json
3
+ description: Curate an htmlboard canvas with designs.json (section titles and order, a design's name or size, hiding unlisted designs, showing components). Use when the designs folder has a designs.json, or the user wants sections named or ordered beyond what folders give.
4
+ ---
5
+
6
+ # HtmlBoard designs.json
7
+
8
+ Without one, folders are the canvas's sections and number prefixes set the order (the htmlboard skill covers the designs themselves). A `designs.json` in the designs folder curates on top of that: sections with titles (accents, capitals, an order across folders), and values that win over the files'. The files still say the rest: their name, size and variants in their `<head>`.
9
+
10
+ ```json
11
+ {
12
+ "title": "Wallet app",
13
+ "sections": [
14
+ { "title": "Checkout · mobile", "designs": ["03-checkout/01-one-page.html", "03-checkout/02-steps.html"] },
15
+ { "title": "Launch flyers", "folder": "04-flyers" }
16
+ ]
17
+ }
18
+ ```
19
+
20
+ - Sections come in their order, designs in theirs. An entry is a file name (its variants follow it; with a query string, it places one variant), or `{ "file", "title", "width", "height", "category", "description" }` to override the file's values.
21
+ - `"folder"` brings a whole folder, in prefix order.
22
+ - Designs it doesn't list still show after the ones it lists, in the section that holds their folder (or a section of their own), unless it says `"unlisted": "hide"`. When it groups designs by hand, add a new design to the right section.
23
+ - Components aren't on the canvas unless it says `"components": "show"` (or lists `components/<tag>.html`): each shows alone, from its first-line example, 480 wide unless its file has `<meta name="htmlboard" content="width=…">`.
24
+ - Saving it rebuilds the canvas.
25
+ - `npx htmlboard migrate <designs folder>` moves an old designs.json's sizes, names and variants into the files and keeps only what they can't say (`--write` to apply; without it, it only shows the plan).
@@ -0,0 +1,38 @@
1
+ import http from 'node:http';
2
+
3
+ // The htmlboard canvases running on this machine, found by asking ports for /api/health: for
4
+ // `htmlboard check`, and so that starting htmlboard again for a folder points at the running one.
5
+
6
+ /** Where htmlboard listens unless told otherwise: 3000, or the next free port */
7
+ export const PORTS = Array.from({ length: 21 }, (_, i) => 3000 + i);
8
+
9
+ /** GET a URL: its status and body */
10
+ export function get(url, { timeout = 0 } = {}) {
11
+ return new Promise((resolve, reject) => {
12
+ const req = http.get(url, (res) => {
13
+ const chunks = [];
14
+ res.on('data', (chunk) => chunks.push(chunk));
15
+ res.on('end', () => resolve({ status: res.statusCode, body: Buffer.concat(chunks).toString('utf8') }));
16
+ res.on('error', reject);
17
+ });
18
+ req.on('error', reject);
19
+ if (timeout) req.setTimeout(timeout, () => req.destroy(new Error('timeout')));
20
+ });
21
+ }
22
+
23
+ /**
24
+ * The htmlboard servers listening on these ports: each its health (dir, root, version) with its
25
+ * port and url.
26
+ */
27
+ export async function findCanvases(ports = PORTS) {
28
+ const found = await Promise.all([...new Set(ports)].map(async (port) => {
29
+ try {
30
+ const { status, body } = await get(`http://127.0.0.1:${port}/api/health`, { timeout: 1500 });
31
+ const health = JSON.parse(body);
32
+ return status === 200 && health.status === 'ok' && health.dir ? { ...health, port, url: `http://localhost:${port}` } : null;
33
+ } catch {
34
+ return null;
35
+ }
36
+ }));
37
+ return found.filter(Boolean);
38
+ }