htmlboard 0.0.0-stage → 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 HtmlBoard Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,290 @@
1
- # Temporary Holding Version
1
+ # ✦ HtmlBoard
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ > **Infinite canvas and design explorer for HTML artboards — designed for humans and LLMs.**
4
+
5
+ [![npm version](https://img.shields.io/npm/v/htmlboard.svg?style=flat-square&color=6366f1)](https://www.npmjs.com/package/htmlboard)
6
+ [![license](https://img.shields.io/npm/l/htmlboard.svg?style=flat-square&color=10b981)](LICENSE)
7
+ [![node version](https://img.shields.io/node/v/htmlboard.svg?style=flat-square)](https://nodejs.org)
8
+ [![zero dependencies](https://img.shields.io/badge/dependencies-0-brightgreen.svg?style=flat-square)](package.json)
9
+
10
+ **HtmlBoard** turns any folder of HTML files into a Figma-like interactive infinite canvas. Inspect responsive variants, mobile and desktop layouts, design system components, and full application flows side-by-side with instant live reload.
11
+
12
+ ---
13
+
14
+ ## 💡 Why HtmlBoard?
15
+
16
+ Modern AI agents and developers generate dozens of HTML mockups, layout variations, and prototypes in seconds. But previewing them has always been awkward:
17
+ - **Tabs upon tabs:** Flipping between dozens of browser tabs breaks context and comparison.
18
+ - **Figma is locked down:** Exporting code into proprietary design tools is slow and out of sync.
19
+ - **Traditional dev servers only show one page:** You lose the holistic bird's-eye view of your product's flow.
20
+
21
+ **HtmlBoard bridges this gap.** It gives you an infinite 2D canvas for HTML artboards — zero config, zero external dependencies, blazing fast, and purpose-built for AI-driven frontend prototyping.
22
+
23
+ ---
24
+
25
+ ## ✨ Features
26
+
27
+ - 🛸 **Infinite Canvas**: Smoothly pan, zoom (from 5% to 300%), and fly across dozens of artboards with trackpad or mouse.
28
+ - ⚡ **Zero Dependencies**: Pure native Node.js ES modules. Runs instantly with `npx htmlboard` without installing heavy packages.
29
+ - 🔄 **State-Preserving Live Reload**: Automatically watches files via Server-Sent Events (SSE). When you or an LLM edit an HTML file, the corresponding artboard updates instantly without resetting your canvas pan/zoom position; editing a shared CSS, script or image reloads them all.
30
+ - 🔍 **Auto-Discovery**: Point HtmlBoard at any folder. It automatically discovers all HTML files, extracts their titles, classifies them by device type, and renders them onto the canvas.
31
+ - 📐 **Declarative Manifest (`designs.json`)**: Optional structured schema to organize artboards into sections, define custom viewports (iPhone, iPad, MacBook, 4K), and attach metadata.
32
+ - 📱 **Multi-Device Categories**: One-click filters for Mobile (390×844), Desktop (1280×820), Tablet (768×1024), and Component kits.
33
+ - 🎯 **Focus & Zoom-to-Fit**: Instantly center any artboard with a click in the sidebar, or hit <kbd>F</kbd> to fit all designs on screen.
34
+ - 🔗 **Deep Links**: The URL follows the focused artboard (`http://localhost:3000/#checkout-b`), so you can share or reload a view of one design.
35
+ - ⌨️ **Keyboard-First Workflow**: Full suite of intuitive shortcuts matching design industry standards.
36
+
37
+ ---
38
+
39
+ ## 🚀 Quick Start
40
+
41
+ Run instantly in any project containing HTML files:
42
+
43
+ ```bash
44
+ npx htmlboard
45
+ ```
46
+
47
+ Or install globally:
48
+
49
+ ```bash
50
+ npm install -g htmlboard
51
+ htmlboard
52
+ ```
53
+
54
+ ### Scaffold a Starter Project
55
+
56
+ To create a new workspace with starter templates (mobile screen, desktop dashboard, and component library):
57
+
58
+ ```bash
59
+ npx htmlboard --init
60
+ ```
61
+
62
+ ---
63
+
64
+ ## 🛠️ CLI Usage
65
+
66
+ ```text
67
+ Usage:
68
+ htmlboard [directory] [options]
69
+ npx htmlboard [directory] [options]
70
+ htmlboard skills <install|uninstall> [options] Teach your AI agent to use HtmlBoard
71
+
72
+ Options:
73
+ -p, --port <number> Port to listen on (default: 3000)
74
+ -d, --dir <path> Directory to serve HTML artboards from (default: .)
75
+ -r, --root <path> Serve files from this parent folder, so artboards can link to
76
+ shared files outside the designs folder (default: the designs folder)
77
+ -o, --open Open the explorer automatically in default browser
78
+ --init Scaffold starter designs.json and sample artboards
79
+ -v, --version Display HtmlBoard version
80
+ -h, --help Display help message
81
+ ```
82
+
83
+ ### Examples
84
+
85
+ ```bash
86
+ # Serve current directory on port 3000
87
+ htmlboard
88
+
89
+ # Open in browser automatically
90
+ htmlboard --open
91
+
92
+ # Serve a specific designs directory on port 8080
93
+ htmlboard ./src/designs -p 8080
94
+
95
+ # Artboards in ./design that link to the site's own ../css and ../js
96
+ htmlboard design --root .
97
+
98
+ # Initialize sample templates in a new folder
99
+ htmlboard ./my-new-ui --init --open
100
+ ```
101
+
102
+ ---
103
+
104
+ ## 🤖 Working with LLMs (AI-Assisted Prototyping)
105
+
106
+ HtmlBoard is built from the ground up to pair with AI coding agents (Claude, Gemini, Codex, ChatGPT, Antigravity, Cursor).
107
+
108
+ ### Install the agent skill
109
+
110
+ HtmlBoard ships an [Agent Skill](https://agentskills.io) that teaches your agent how to use it: where to put artboards, how to size and name them, how `designs.json` works and how to start the canvas. Install it in your project:
111
+
112
+ ```bash
113
+ npx htmlboard skills install
114
+ ```
115
+
116
+ This writes `.claude/skills/htmlboard/` (Claude Code) and `.agents/skills/htmlboard/` (Codex and other agents that read `.agents/skills`). Commit them so everyone working on the project gets the skill. Then start a new agent session and just ask for a design.
117
+
118
+ ```bash
119
+ npx htmlboard skills install --global # for your user (~/.claude/skills, ~/.agents/skills), all projects
120
+ npx htmlboard skills install --agent claude # only one agent: claude | agents | all (default)
121
+ npx htmlboard skills install --force # update a copy you edited locally
122
+ npx htmlboard skills uninstall # remove it (accepts the same --global / --agent)
123
+ ```
124
+
125
+ Running `install` again after upgrading HtmlBoard updates the skill; a copy you edited is kept unless you pass `--force`.
126
+
127
+ ### The workflow
128
+
129
+ 1. **Ask your LLM to generate artboards:**
130
+ > *"Create 3 design explorations for our checkout flow in `artboards/checkout-v1.html`, `artboards/checkout-v2.html`, and `artboards/checkout-v3.html`."*
131
+
132
+ 2. **Run HtmlBoard in the background:**
133
+ ```bash
134
+ npx htmlboard
135
+ ```
136
+
137
+ 3. **Watch the canvas update live:**
138
+ As the LLM writes or refines each HTML file, HtmlBoard detects the file change and reloads the iframe on the canvas immediately. You never have to refresh your browser or hunt for file URLs.
139
+
140
+ ---
141
+
142
+ ## 📋 The `designs.json` Manifest
143
+
144
+ While HtmlBoard automatically discovers HTML files, you can add a `designs.json` file in your designs folder for custom layout and organization. Only `sections[].designs[].file` is required; the short form is enough:
145
+
146
+ ```json
147
+ {
148
+ "sections": [
149
+ {
150
+ "title": "Home",
151
+ "designs": [
152
+ { "file": "home-mobile.html", "title": "Home · phone", "width": 390, "height": 844 },
153
+ { "file": "home-mobile.html?theme=dark", "title": "Home · phone · dark", "width": 390, "height": 844 },
154
+ { "file": "home-desktop.html", "title": "Home · desktop", "width": 1440 }
155
+ ]
156
+ }
157
+ ]
158
+ }
159
+ ```
160
+
161
+ Sections are rows (top to bottom) and designs run left to right. A `file` may carry a query string, so one HTML file can show several states. Leave `height` out to let the frame grow with its page. `id` and `category` are derived from the file when left out.
162
+
163
+ The full form adds ids, descriptions, categories (for the toolbar filters) and searchable tags (`name`/`artboards` are synonyms of `title`/`designs`):
164
+
165
+ ```json
166
+ {
167
+ "title": "Fintech Mobile & Web App",
168
+ "description": "Exploration of screen flows, responsive layouts, and UI components",
169
+ "sections": [
170
+ {
171
+ "id": "screens",
172
+ "name": "Screen Layouts",
173
+ "description": "Full page layouts across mobile and desktop viewports",
174
+ "artboards": [
175
+ {
176
+ "id": "desktop-dashboard",
177
+ "title": "Desktop Dashboard",
178
+ "file": "artboards/desktop.html",
179
+ "width": 1280,
180
+ "height": 820,
181
+ "category": "desktop",
182
+ "tags": ["desktop", "dashboard", "analytics"]
183
+ },
184
+ {
185
+ "id": "mobile-app",
186
+ "title": "Mobile App Feed",
187
+ "file": "artboards/mobile.html",
188
+ "width": 390,
189
+ "height": 844,
190
+ "category": "mobile",
191
+ "tags": ["mobile", "ios", "finance"]
192
+ }
193
+ ]
194
+ },
195
+ {
196
+ "id": "components",
197
+ "name": "Component Library",
198
+ "artboards": [
199
+ {
200
+ "id": "ui-primitives",
201
+ "title": "UI Kit Elements",
202
+ "file": "artboards/components.html",
203
+ "width": 780,
204
+ "height": 720,
205
+ "category": "components",
206
+ "tags": ["design-system", "buttons", "inputs"]
207
+ }
208
+ ]
209
+ }
210
+ ]
211
+ }
212
+ ```
213
+
214
+ ---
215
+
216
+ ## ⌨️ Keyboard Shortcuts
217
+
218
+ | Shortcut | Action |
219
+ | :--- | :--- |
220
+ | <kbd>Space</kbd> + <kbd>Drag</kbd> | Pan the canvas freely |
221
+ | <kbd>Ctrl</kbd> / <kbd>⌘</kbd> + <kbd>Wheel</kbd> | Zoom in/out anchored to cursor |
222
+ | <kbd>+</kbd> / <kbd>-</kbd> | Zoom in / Zoom out |
223
+ | <kbd>0</kbd> | Reset zoom to 100% |
224
+ | <kbd>F</kbd> or <kbd>Shift</kbd> + <kbd>1</kbd> | Fit all artboards in viewport |
225
+ | <kbd>/</kbd> or <kbd>⌘</kbd> + <kbd>K</kbd> | Search artboards by title, tag, or path |
226
+ | <kbd>[</kbd> or <kbd>]</kbd> | Toggle navigation sidebar |
227
+ | <kbd>1</kbd> – <kbd>5</kbd> | Quick filter by device category |
228
+ | <kbd>?</kbd> | Show keyboard shortcuts modal |
229
+ | <kbd>Esc</kbd> | Close modals or blur search |
230
+
231
+ ---
232
+
233
+ ## 🔌 Programmatic API
234
+
235
+ You can also embed HtmlBoard into your own build tools, testing pipelines, or dev environments:
236
+
237
+ ```javascript
238
+ import { startServer } from 'htmlboard';
239
+
240
+ const instance = await startServer({
241
+ dir: './designs',
242
+ port: 3000
243
+ });
244
+
245
+ console.log(`HtmlBoard running at ${instance.url}`);
246
+
247
+ // Later, when done:
248
+ // await instance.close();
249
+ ```
250
+
251
+ The skill installer is exported too:
252
+
253
+ ```javascript
254
+ import { installSkills } from 'htmlboard';
255
+
256
+ installSkills({ dir: process.cwd(), agent: 'all' });
257
+ // → [{ skill: 'htmlboard', path: '…/.claude/skills/htmlboard', status: 'installed' }, …]
258
+ ```
259
+
260
+ ---
261
+
262
+ ## 📂 Project Structure
263
+
264
+ ```text
265
+ htmlboard/
266
+ ├── bin/
267
+ │ └── htmlboard.js # CLI executable
268
+ ├── src/
269
+ │ ├── index.js # Library entry point & API exports
270
+ │ ├── server.js # HTTP server, SSE live reload, auto-discovery
271
+ │ ├── skills.js # `htmlboard skills` installer
272
+ │ ├── client/ # The infinite canvas frontend
273
+ │ │ ├── index.html # Explorer shell & canvas DOM
274
+ │ │ ├── explorer.css # Dark theme styles & canvas grid
275
+ │ │ └── explorer.js # Pan/zoom engine, SSE listener, auto-measure
276
+ │ └── templates/ # Starter scaffold templates
277
+ │ ├── designs.json # Starter manifest
278
+ │ └── artboards/ # Sample mobile, desktop, & component screens
279
+ ├── skills/
280
+ │ └── htmlboard/ # Agent skill (SKILL.md) copied by `htmlboard skills install`
281
+ ├── package.json
282
+ ├── README.md
283
+ └── LICENSE
284
+ ```
285
+
286
+ ---
287
+
288
+ ## 📄 License
289
+
290
+ MIT © Luiz Carlos & Contributors
@@ -0,0 +1,297 @@
1
+ #!/usr/bin/env node
2
+
3
+ import path from 'node:path';
4
+ import fs from 'node:fs';
5
+ import { exec } from 'node:child_process';
6
+ import { fileURLToPath } from 'node:url';
7
+ import { startServer } from '../src/server.js';
8
+ import { installSkills, uninstallSkills } from '../src/skills.js';
9
+
10
+ const __filename = fileURLToPath(import.meta.url);
11
+ const __dirname = path.dirname(__filename);
12
+ const PKG_PATH = path.join(__dirname, '..', 'package.json');
13
+ const pkg = JSON.parse(fs.readFileSync(PKG_PATH, 'utf8'));
14
+
15
+ // Parse command line arguments
16
+ function parseArgs(args) {
17
+ const options = {
18
+ port: 3000,
19
+ dir: process.cwd(),
20
+ root: null,
21
+ open: false,
22
+ init: false,
23
+ help: false,
24
+ version: false
25
+ };
26
+
27
+ for (let i = 0; i < args.length; i++) {
28
+ const arg = args[i];
29
+
30
+ if (arg === '--help' || arg === '-h') {
31
+ options.help = true;
32
+ } else if (arg === '--version' || arg === '-v') {
33
+ options.version = true;
34
+ } else if (arg === '--open' || arg === '-o') {
35
+ options.open = true;
36
+ } else if (arg === '--init') {
37
+ options.init = true;
38
+ } else if (arg === '--port' || arg === '-p') {
39
+ const next = args[++i];
40
+ if (next && !next.startsWith('-')) {
41
+ options.port = parseInt(next, 10);
42
+ }
43
+ } else if (arg.startsWith('--port=')) {
44
+ options.port = parseInt(arg.split('=')[1], 10);
45
+ } else if (arg === '--dir' || arg === '-d') {
46
+ const next = args[++i];
47
+ if (next && !next.startsWith('-')) {
48
+ options.dir = next;
49
+ }
50
+ } else if (arg.startsWith('--dir=')) {
51
+ options.dir = arg.split('=')[1];
52
+ } else if (arg === '--root' || arg === '-r') {
53
+ const next = args[++i];
54
+ if (next && !next.startsWith('-')) {
55
+ options.root = next;
56
+ }
57
+ } else if (arg.startsWith('--root=')) {
58
+ options.root = arg.split('=')[1];
59
+ } else if (!arg.startsWith('-')) {
60
+ // Positional directory argument e.g. `htmlboard ./my-designs`
61
+ options.dir = arg;
62
+ }
63
+ }
64
+
65
+ return options;
66
+ }
67
+
68
+ function showHelp() {
69
+ console.log(`
70
+ HtmlBoard v${pkg.version}
71
+ Infinite canvas and design explorer for HTML artboards — designed for humans and LLMs
72
+
73
+ Usage:
74
+ htmlboard [directory] [options]
75
+ npx htmlboard [directory] [options]
76
+ htmlboard skills <install|uninstall> [options] Teach your AI agent to use HtmlBoard
77
+
78
+ Options:
79
+ -p, --port <number> Port to listen on (default: 3000)
80
+ -d, --dir <path> Directory to serve HTML artboards from (default: .)
81
+ -r, --root <path> Serve files from this parent folder, so artboards can link to
82
+ shared files outside the designs folder (default: the designs folder)
83
+ -o, --open Open the explorer automatically in your default browser
84
+ --init Scaffold starter designs.json and sample artboards in target directory
85
+ -v, --version Display HtmlBoard version
86
+ -h, --help Display this help message
87
+
88
+ Examples:
89
+ htmlboard # Run in current directory on http://localhost:3000
90
+ htmlboard --open # Run and launch browser automatically
91
+ htmlboard ./designs -p 8080 # Serve ./designs on port 8080
92
+ htmlboard design --root . # Artboards in ./design that link to ../css/…
93
+ htmlboard --init # Initialize starter templates in current folder
94
+ htmlboard skills install # Add the HtmlBoard skill to this project's agents
95
+
96
+ Keyboard Shortcuts in Canvas:
97
+ Space + Drag Pan canvas
98
+ Ctrl/Cmd + Wheel Zoom into focal point
99
+ + / - Zoom in / Zoom out
100
+ 0 Reset zoom to 100%
101
+ F Zoom to fit all artboards
102
+ / or Cmd+K Search artboards
103
+ [ or ] Toggle navigation sidebar
104
+ ? Show shortcuts help dialog
105
+ `);
106
+ }
107
+
108
+ function openBrowser(url) {
109
+ const startCmd = process.platform === 'darwin'
110
+ ? 'open'
111
+ : process.platform === 'win32'
112
+ ? 'start'
113
+ : 'xdg-open';
114
+
115
+ exec(`${startCmd} ${url}`, (err) => {
116
+ if (err) {
117
+ console.warn(`[htmlboard] Unable to auto-launch browser: ${err.message}`);
118
+ }
119
+ });
120
+ }
121
+
122
+ function scaffoldProject(targetDir) {
123
+ const templatesDir = path.join(__dirname, '..', 'src', 'templates');
124
+ const targetConfig = path.join(targetDir, 'designs.json');
125
+ const targetArtboardsDir = path.join(targetDir, 'artboards');
126
+
127
+ console.log(`[htmlboard] Scaffolding starter project in ${targetDir}...`);
128
+
129
+ if (!fs.existsSync(targetDir)) {
130
+ fs.mkdirSync(targetDir, { recursive: true });
131
+ }
132
+
133
+ if (!fs.existsSync(targetArtboardsDir)) {
134
+ fs.mkdirSync(targetArtboardsDir, { recursive: true });
135
+ }
136
+
137
+ // Copy designs.json if not present
138
+ if (!fs.existsSync(targetConfig)) {
139
+ const srcConfig = path.join(templatesDir, 'designs.json');
140
+ if (fs.existsSync(srcConfig)) {
141
+ fs.copyFileSync(srcConfig, targetConfig);
142
+ console.log(` ✓ Created designs.json`);
143
+ }
144
+ } else {
145
+ console.log(` ℹ designs.json already exists (skipped)`);
146
+ }
147
+
148
+ // Copy starter artboards
149
+ const starterFiles = ['mobile.html', 'desktop.html', 'components.html'];
150
+ for (const file of starterFiles) {
151
+ const srcFile = path.join(templatesDir, 'artboards', file);
152
+ const destFile = path.join(targetArtboardsDir, file);
153
+ if (!fs.existsSync(destFile) && fs.existsSync(srcFile)) {
154
+ fs.copyFileSync(srcFile, destFile);
155
+ console.log(` ✓ Created artboards/${file}`);
156
+ }
157
+ }
158
+
159
+ console.log(`\n🎉 Starter templates created successfully!`);
160
+ }
161
+
162
+ function showSkillsHelp() {
163
+ console.log(`
164
+ Usage:
165
+ htmlboard skills install [options] Copy the HtmlBoard skill into your agents' skill folders
166
+ htmlboard skills uninstall [options] Remove it
167
+
168
+ Options:
169
+ -g, --global Install for your user (~/.claude/skills, ~/.agents/skills) instead of this project
170
+ -a, --agent <name> claude (.claude/skills), agents (.agents/skills: Codex and other agents), or all (default)
171
+ -d, --dir <path> Project root (default: current directory)
172
+ -f, --force Replace a skill that was changed locally
173
+ -h, --help Display this help message
174
+ `);
175
+ }
176
+
177
+ function runSkills(args) {
178
+ const [action, ...rest] = args;
179
+ const options = { agent: 'all', global: false, dir: process.cwd(), force: false };
180
+
181
+ for (let i = 0; i < rest.length; i++) {
182
+ const arg = rest[i];
183
+ if (arg === '--global' || arg === '-g') options.global = true;
184
+ else if (arg === '--force' || arg === '-f') options.force = true;
185
+ else if (arg === '--agent' || arg === '-a') options.agent = rest[++i];
186
+ else if (arg.startsWith('--agent=')) options.agent = arg.split('=')[1];
187
+ else if (arg === '--dir' || arg === '-d') options.dir = rest[++i];
188
+ else if (arg.startsWith('--dir=')) options.dir = arg.split('=')[1];
189
+ else if (arg === '--help' || arg === '-h') return showSkillsHelp();
190
+ else {
191
+ console.error(`[htmlboard] Unknown option: ${arg}`);
192
+ showSkillsHelp();
193
+ process.exit(1);
194
+ }
195
+ }
196
+
197
+ if (action !== 'install' && action !== 'uninstall') {
198
+ showSkillsHelp();
199
+ process.exit(action && action !== '--help' && action !== '-h' ? 1 : 0);
200
+ }
201
+
202
+ let results;
203
+ try {
204
+ results = action === 'install' ? installSkills(options) : uninstallSkills(options);
205
+ } catch (err) {
206
+ console.error(`[htmlboard] ${err.message}`);
207
+ process.exit(1);
208
+ }
209
+
210
+ const labels = {
211
+ installed: '\x1b[32m✓ installed\x1b[0m',
212
+ updated: '\x1b[32m✓ updated\x1b[0m',
213
+ unchanged: '\x1b[90m= up to date\x1b[0m',
214
+ skipped: '\x1b[33m! changed locally, kept (use --force to replace)\x1b[0m',
215
+ removed: '\x1b[32m✓ removed\x1b[0m',
216
+ absent: '\x1b[90m- not installed\x1b[0m'
217
+ };
218
+ for (const { path: dest, status } of results) {
219
+ console.log(` ${labels[status]} ${path.relative(process.cwd(), dest) || dest}`);
220
+ }
221
+ if (action === 'install' && results.some((r) => r.status === 'installed' || r.status === 'updated')) {
222
+ console.log(`\n Restart your agent session to load the skill, then ask it for a design.`);
223
+ }
224
+ }
225
+
226
+ async function main() {
227
+ const args = process.argv.slice(2);
228
+
229
+ if (args[0] === 'skills') {
230
+ runSkills(args.slice(1));
231
+ return;
232
+ }
233
+
234
+ const options = parseArgs(args);
235
+
236
+ if (options.help) {
237
+ showHelp();
238
+ process.exit(0);
239
+ }
240
+
241
+ if (options.version) {
242
+ console.log(`htmlboard v${pkg.version}`);
243
+ process.exit(0);
244
+ }
245
+
246
+ const targetDir = path.resolve(options.dir);
247
+
248
+ if (options.init) {
249
+ scaffoldProject(targetDir);
250
+ }
251
+
252
+ // If directory is empty, auto-prompt or auto-scaffold
253
+ let entries = [];
254
+ try {
255
+ entries = fs.readdirSync(targetDir);
256
+ } catch (_) {
257
+ fs.mkdirSync(targetDir, { recursive: true });
258
+ }
259
+
260
+ const hasHtml = entries.some((e) => e.endsWith('.html')) ||
261
+ (fs.existsSync(path.join(targetDir, 'artboards')) &&
262
+ fs.readdirSync(path.join(targetDir, 'artboards')).some((e) => e.endsWith('.html')));
263
+ const hasDesignsJson = fs.existsSync(path.join(targetDir, 'designs.json'));
264
+
265
+ if (!hasHtml && !hasDesignsJson && entries.filter((e) => !e.startsWith('.')).length === 0) {
266
+ console.log(`[htmlboard] Directory is empty. Initializing starter artboards...`);
267
+ scaffoldProject(targetDir);
268
+ }
269
+
270
+ try {
271
+ const { url, rootDir } = await startServer({
272
+ dir: targetDir,
273
+ root: options.root ? path.resolve(options.root) : undefined,
274
+ port: options.port
275
+ });
276
+
277
+ console.log(`
278
+ ✦ \x1b[1m\x1b[36mHtmlBoard\x1b[0m \x1b[90mv${pkg.version}\x1b[0m
279
+ \x1b[90mInfinite Canvas & Design Explorer for HTML Artboards\x1b[0m
280
+
281
+ \x1b[32m➜\x1b[0m \x1b[1mLocal:\x1b[0m \x1b[36m${url}\x1b[0m
282
+ \x1b[32m➜\x1b[0m \x1b[1mTarget:\x1b[0m \x1b[90m${targetDir}\x1b[0m${rootDir !== targetDir ? `\n \x1b[32m➜\x1b[0m \x1b[1mRoot:\x1b[0m \x1b[90m${rootDir}\x1b[0m` : ''}
283
+ \x1b[32m➜\x1b[0m \x1b[1mLive:\x1b[0m \x1b[32mWatching files for hot live reload\x1b[0m
284
+
285
+ \x1b[90mPress \x1b[1mCtrl+C\x1b[0m\x1b[90m to stop.\x1b[0m
286
+ `);
287
+
288
+ if (options.open) {
289
+ openBrowser(url);
290
+ }
291
+ } catch (err) {
292
+ console.error(`[htmlboard] Error starting server:`, err.message);
293
+ process.exit(1);
294
+ }
295
+ }
296
+
297
+ main();
package/package.json CHANGED
@@ -1,6 +1,50 @@
1
1
  {
2
2
  "name": "htmlboard",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "Infinite canvas and design explorer for HTML artboards — designed for humans and LLMs",
5
+ "type": "module",
6
+ "bin": {
7
+ "htmlboard": "bin/htmlboard.js"
8
+ },
9
+ "main": "./src/index.js",
10
+ "files": [
11
+ "bin",
12
+ "src",
13
+ "skills",
14
+ "README.md",
15
+ "LICENSE"
16
+ ],
17
+ "scripts": {
18
+ "start": "node ./bin/htmlboard.js",
19
+ "dev": "node ./bin/htmlboard.js",
20
+ "test": "node --test"
21
+ },
22
+ "keywords": [
23
+ "canvas",
24
+ "design",
25
+ "artboard",
26
+ "html",
27
+ "ui",
28
+ "explorer",
29
+ "infinite-canvas",
30
+ "llm",
31
+ "prototyping",
32
+ "live-reload",
33
+ "agent-skills",
34
+ "claude-code",
35
+ "codex"
36
+ ],
37
+ "author": "Luiz Carlos (https://github.com/luizcarlos1405)",
38
+ "license": "MIT",
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "git+https://github.com/luizcarlos1405/htmlboard.git"
42
+ },
43
+ "homepage": "https://github.com/luizcarlos1405/htmlboard#readme",
44
+ "bugs": {
45
+ "url": "https://github.com/luizcarlos1405/htmlboard/issues"
46
+ },
47
+ "engines": {
48
+ "node": ">=18.0.0"
49
+ }
50
+ }