openink 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/CHANGELOG.md +23 -0
- package/LICENSE +21 -0
- package/README.md +164 -0
- package/bin/openink.js +4 -0
- package/docs/ai-assistants.md +35 -0
- package/docs/architecture.md +50 -0
- package/docs/blocks.md +604 -0
- package/docs/extending.md +86 -0
- package/docs/getting-started.md +97 -0
- package/docs/spec.md +215 -0
- package/package.json +38 -0
- package/schema/spec.schema.json +2641 -0
- package/src/build.js +82 -0
- package/src/cli.js +133 -0
- package/src/dev.js +53 -0
- package/src/export.js +68 -0
- package/src/icons.js +47 -0
- package/src/index.js +14 -0
- package/src/render/blocks/actions.js +68 -0
- package/src/render/blocks/content.js +86 -0
- package/src/render/blocks/data.js +24 -0
- package/src/render/blocks/feedback.js +29 -0
- package/src/render/blocks/forms.js +86 -0
- package/src/render/blocks/index.js +42 -0
- package/src/render/blocks/layout.js +102 -0
- package/src/render/blocks/media.js +65 -0
- package/src/render/blocks/navigation.js +67 -0
- package/src/render/blocks/overlay.js +18 -0
- package/src/render/blocks/shared.js +20 -0
- package/src/render/blocks/text.js +49 -0
- package/src/render/context.js +63 -0
- package/src/render/page.js +76 -0
- package/src/runtime/chart.js +85 -0
- package/src/runtime/dom.js +21 -0
- package/src/runtime/i18n.js +24 -0
- package/src/runtime/icon.js +28 -0
- package/src/runtime/index.js +64 -0
- package/src/runtime/navigation.js +27 -0
- package/src/runtime/placeholder.js +88 -0
- package/src/spec/docs.js +65 -0
- package/src/spec/schema.js +110 -0
- package/src/spec/validate.js +219 -0
- package/src/styles/openink.css +250 -0
- package/src/styles/themes/blueprint.css +31 -0
- package/src/styles/themes/color.css +28 -0
- package/src/styles/themes/dark.css +31 -0
- package/src/styles/themes/pastel.css +26 -0
- package/src/themes.js +10 -0
- package/templates/starter/AGENTS.md +18 -0
- package/templates/starter/README.md +11 -0
- package/templates/starter/gitignore +3 -0
- package/templates/starter/spec.yaml +55 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes are documented here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project uses [Semantic Versioning](https://semver.org/).
|
|
4
|
+
|
|
5
|
+
## [Unreleased]
|
|
6
|
+
|
|
7
|
+
## [0.1.0]
|
|
8
|
+
|
|
9
|
+
First release.
|
|
10
|
+
|
|
11
|
+
- `openink` CLI: `init`, `build`, `dev` (live reload), `validate`, `pdf`, `png`, `blocks`; `--theme` to try a theme.
|
|
12
|
+
- YAML spec with 48 block types across layout, text, content, media, forms, actions, navigation, feedback, overlays and data.
|
|
13
|
+
- New blocks beyond the basics: `icon` (37 hand-drawn icons, also on buttons, nav and tab-bar items), `avatar`, `hero`, `stat`,
|
|
14
|
+
`rating`, `link`, `video`, `carousel`, `dropzone`, `chart` (line, area, bar, pie, donut), `search`, `alert`, `progress`,
|
|
15
|
+
`breadcrumb`, `pagination`, `steps`, `tabbar`, `accordion`, `device` (phone / tablet / browser frames), `modal`.
|
|
16
|
+
- Colour: themes (`sketch`, `color`, `pastel`, `blueprint`, `dark`), `colors:` token overrides, and `tone:` / `fill:` on any block or screen.
|
|
17
|
+
- Global `modals:` list, opened from any screen with `open:` and closed with `close:`, the X, Escape or a click outside.
|
|
18
|
+
- Hand-drawn look from wired-elements and RoughJS; image, map and generic placeholders.
|
|
19
|
+
- Optional multi-language prototypes (`languages:` + `{ en, de }` text values).
|
|
20
|
+
- Named header nav sets per screen, sticky-note annotations, custom theme CSS, assets folder, screen widths, YAML anchors via `x-*` keys.
|
|
21
|
+
- Spec validation with paths, "did you mean" hints and dead-link detection.
|
|
22
|
+
- JSON Schema (`openink/schema.json`) for editor autocomplete, generated from the block registry.
|
|
23
|
+
- PDF export (one screen per page) and per-screen PNG export.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Open Ink 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
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
<h1 align="center">
|
|
2
|
+
<picture>
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="assets/logo-white.svg">
|
|
4
|
+
<img src="assets/logo-black.svg" alt="Open Ink" width="340">
|
|
5
|
+
</picture>
|
|
6
|
+
</h1>
|
|
7
|
+
|
|
8
|
+
<p align="center"><strong>Describe screens in YAML. Get a clickable, hand-drawn wireframe prototype.</strong></p>
|
|
9
|
+
|
|
10
|
+
Static HTML you can host or open from disk, plus PDF and PNG export. Built on [wired-elements](https://github.com/rough-stuff/wired-elements) and [RoughJS](https://github.com/rough-stuff/rough), so it looks like a sketch and nobody mistakes it for the final design. Keep it plain pencil, or turn on colour for a whole project or just one part.
|
|
11
|
+
|
|
12
|
+
<p>
|
|
13
|
+
<img src="docs/img/photo-feed.png" width="32%" alt="Photo-sharing app: feed with stories, carousel and action icons" />
|
|
14
|
+
<img src="docs/img/photo-mobile.png" width="32%" alt="The same feed inside a phone frame with a tab bar" />
|
|
15
|
+
<img src="docs/img/saas-overview.png" width="32%" alt="SaaS dashboard in the colour theme with stats and charts" />
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
```yaml
|
|
19
|
+
name: Shop
|
|
20
|
+
theme: color # optional: sketch (default) | color | pastel | blueprint | dark
|
|
21
|
+
nav:
|
|
22
|
+
- { icon: home, label: Home, go: home }
|
|
23
|
+
screens:
|
|
24
|
+
- id: home
|
|
25
|
+
title: Home
|
|
26
|
+
blocks:
|
|
27
|
+
- { type: h1, text: Welcome }
|
|
28
|
+
- type: card
|
|
29
|
+
go: product # click → opens the product screen
|
|
30
|
+
children:
|
|
31
|
+
- { type: image, h: 120, label: Photo }
|
|
32
|
+
- { type: h3, text: Blue shirt }
|
|
33
|
+
- { type: rating, value: 4, text: (128 reviews) }
|
|
34
|
+
- id: product
|
|
35
|
+
title: Product
|
|
36
|
+
blocks:
|
|
37
|
+
- { type: button, label: Add to cart, icon: cart, primary: true, open: added }
|
|
38
|
+
modals:
|
|
39
|
+
- id: added
|
|
40
|
+
title: Added to cart
|
|
41
|
+
children:
|
|
42
|
+
- { type: button, label: Keep shopping, close: true, go: home }
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Why
|
|
46
|
+
|
|
47
|
+
- **Fast to write and change.** A screen is a dozen lines of YAML, not a page of HTML or an hour in a design tool.
|
|
48
|
+
- **Clickable.** Buttons, cards, table rows, tab bars and nav items link between screens; forms, tabs, accordions, modals, chips and toggles respond, so stakeholders can walk through a flow.
|
|
49
|
+
- **Looks like a sketch on purpose.** Feedback goes to structure and flow, not fonts and pixels.
|
|
50
|
+
- **Colour when you want it.** Themes for a whole project, `tone: pink` for one card, `fill: true` for a tinted panel.
|
|
51
|
+
- **Safe for AI to write.** Generate a spec with an assistant; `validate` catches typos, dead links and bad icon names with exact locations. See [docs/ai-assistants.md](docs/ai-assistants.md).
|
|
52
|
+
- **Easy to share.** One static folder, one PDF, or one PNG per screen. Multi-language prototypes are built in.
|
|
53
|
+
|
|
54
|
+
## Quick start
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
npx openink init my-wireframes
|
|
58
|
+
cd my-wireframes
|
|
59
|
+
npx openink dev # live preview at http://localhost:3000
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npx openink validate # check the spec
|
|
64
|
+
npx openink build # static site → dist/
|
|
65
|
+
npx openink pdf # dist/<name>.pdf, one screen per page
|
|
66
|
+
npx openink png # dist/png/<screen>.png
|
|
67
|
+
npx openink blocks # list every block and its props
|
|
68
|
+
npx openink dev --theme dark # try a colour theme without editing the spec
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Or install it once and drop the `npx`:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
npm install -g openink
|
|
75
|
+
openink dev
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Requires Node 20+. PDF and PNG export need Chrome, Chromium or Edge installed (set `CHROME_PATH` if it isn't found).
|
|
79
|
+
|
|
80
|
+
## What you can draw
|
|
81
|
+
|
|
82
|
+
48 blocks in 10 groups; see the [block reference](docs/blocks.md) and the [gallery example](examples/gallery), which shows every one.
|
|
83
|
+
|
|
84
|
+
| | |
|
|
85
|
+
|---|---|
|
|
86
|
+
| **Layout** | `stack` `row` `grid` `card` `accordion` `device` (phone / tablet / browser frame) `divider` `spacer` |
|
|
87
|
+
| **Text** | `h1` `h2` `h3` `text` `list` `note` `badge` |
|
|
88
|
+
| **Content** | `icon` (37 hand-drawn icons) `avatar` `hero` `stat` `rating` `link` |
|
|
89
|
+
| **Media** | `image` `map` `video` `carousel` `dropzone` `box` `chart` (line, area, bar, pie, donut) |
|
|
90
|
+
| **Forms** | `input` `search` `textarea` `select` `checkbox` `toggle` `radio` `slider` |
|
|
91
|
+
| **Actions** | `button` (with icon) `chips` `tabs` `nextbar` |
|
|
92
|
+
| **Navigation** | `breadcrumb` `pagination` `steps` `tabbar` |
|
|
93
|
+
| **Feedback** | `alert` `progress` |
|
|
94
|
+
| **Overlays** | `modal` (global, opened from any screen) |
|
|
95
|
+
| **Data** | `table` |
|
|
96
|
+
|
|
97
|
+
<p>
|
|
98
|
+
<img src="docs/img/gallery-media.png" width="49%" alt="Media blocks and hand-drawn charts" />
|
|
99
|
+
<img src="docs/img/gallery-colours.png" width="49%" alt="Nine tones on cards" />
|
|
100
|
+
</p>
|
|
101
|
+
|
|
102
|
+
## Colour
|
|
103
|
+
|
|
104
|
+
Plain pencil is the default. Colour is opt-in, at three levels:
|
|
105
|
+
|
|
106
|
+
| Level | How |
|
|
107
|
+
|---|---|
|
|
108
|
+
| Whole project | `theme: color \| pastel \| blueprint \| dark` and `colors: { accent: "#f97316" }` |
|
|
109
|
+
| One screen | `tone: blue` on the screen |
|
|
110
|
+
| One part | `tone: red` and `fill: true` on any block, e.g. only the "Delete" button, or a highlighted card |
|
|
111
|
+
|
|
112
|
+
<table>
|
|
113
|
+
<tr>
|
|
114
|
+
<td><img src="docs/img/theme-sketch.png" alt="sketch theme" /><br /><sub><code>sketch</code> (default)</sub></td>
|
|
115
|
+
<td><img src="docs/img/theme-color.png" alt="color theme" /><br /><sub><code>color</code></sub></td>
|
|
116
|
+
<td><img src="docs/img/theme-pastel.png" alt="pastel theme" /><br /><sub><code>pastel</code></sub></td>
|
|
117
|
+
</tr>
|
|
118
|
+
<tr>
|
|
119
|
+
<td><img src="docs/img/theme-blueprint.png" alt="blueprint theme" /><br /><sub><code>blueprint</code></sub></td>
|
|
120
|
+
<td><img src="docs/img/theme-dark.png" alt="dark theme" /><br /><sub><code>dark</code></sub></td>
|
|
121
|
+
<td></td>
|
|
122
|
+
</tr>
|
|
123
|
+
</table>
|
|
124
|
+
|
|
125
|
+
Details: [docs/spec.md#colour](docs/spec.md#colour).
|
|
126
|
+
|
|
127
|
+
## Examples
|
|
128
|
+
|
|
129
|
+
| Example | Shows |
|
|
130
|
+
|---|---|
|
|
131
|
+
| [`photo-sharing`](examples/photo-sharing) | 17 screens: feed, stories, reels, explore, messages, profile, a phone-frame mobile view, global modals, and colour on only a few parts |
|
|
132
|
+
| [`saas-admin`](examples/saas-admin) | The `color` theme: stat cards, area/bar/donut charts, tables, an invite modal |
|
|
133
|
+
| [`rental-portal`](examples/rental-portal) | Two languages and two header nav sets (public vs owner) |
|
|
134
|
+
| [`gallery`](examples/gallery) | Every block on one screen per family; try it with `--theme dark` |
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
npx openink dev examples/photo-sharing
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Documentation
|
|
141
|
+
|
|
142
|
+
- [Getting started](docs/getting-started.md)
|
|
143
|
+
- [Spec reference](docs/spec.md): screens, colour, modals, navigation, languages, icons
|
|
144
|
+
- [Block reference](docs/blocks.md)
|
|
145
|
+
- [Working with AI assistants](docs/ai-assistants.md)
|
|
146
|
+
- [Extending](docs/extending.md): add a block, change the look, use the API
|
|
147
|
+
- [Architecture](docs/architecture.md)
|
|
148
|
+
|
|
149
|
+
## Use it from code
|
|
150
|
+
|
|
151
|
+
```js
|
|
152
|
+
import { build, validate, exportFiles } from "openink";
|
|
153
|
+
|
|
154
|
+
await build({ dir: "./my-project", out: "dist", theme: "dark" });
|
|
155
|
+
await exportFiles({ dir: "./my-project", png: true });
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Contributing
|
|
159
|
+
|
|
160
|
+
Issues and pull requests are welcome; see [CONTRIBUTING.md](CONTRIBUTING.md). Adding a block is one object in `src/render/blocks/`.
|
|
161
|
+
|
|
162
|
+
## License
|
|
163
|
+
|
|
164
|
+
[MIT](LICENSE)
|
package/bin/openink.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Working with AI assistants
|
|
2
|
+
|
|
3
|
+
Open Ink is designed so that an assistant (Claude Code, Cursor, Copilot, ChatGPT…) can turn a description into a prototype **without writing HTML**:
|
|
4
|
+
|
|
5
|
+
> "Wireframe a marketplace for used bikes: search with filters, listing page with a contact form, seller dashboard."
|
|
6
|
+
|
|
7
|
+
The assistant writes `spec.yaml`, the tool checks it, and you get a consistent hand-drawn result. Because the spec is small and validated, it is cheap to iterate: "add a second tab to the listing page" is a five-line diff.
|
|
8
|
+
|
|
9
|
+
## How it works
|
|
10
|
+
|
|
11
|
+
`openink init` puts an `AGENTS.md` in your project. Most assistants read it automatically; it tells them to:
|
|
12
|
+
|
|
13
|
+
1. Run `npx openink blocks` to learn the available blocks.
|
|
14
|
+
2. Edit `spec.yaml` only.
|
|
15
|
+
3. Run `npx openink validate` and fix what it reports.
|
|
16
|
+
4. Run `npx openink png` and look at `dist/png/*.png` to check the layout.
|
|
17
|
+
|
|
18
|
+
If your assistant uses a different filename (`CLAUDE.md`, `.cursorrules`, …), copy or rename `AGENTS.md`.
|
|
19
|
+
|
|
20
|
+
## Why validation matters here
|
|
21
|
+
|
|
22
|
+
Assistants make small mistakes: a misspelt prop, a link to a screen they renamed, a translation missing in one language. `validate` reports each with its exact location in the spec and a "did you mean" hint, so the fix-and-retry loop is short and mechanical:
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
✗ 2 problems in the spec
|
|
26
|
+
error screens[1].blocks[3].type: Unknown block type "buton". Did you mean "button"?
|
|
27
|
+
error screens[0].blocks[0].go: Links to unknown screen "checkout". Did you mean "check-out"?
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Tips for good prompts
|
|
31
|
+
|
|
32
|
+
- Name the **users** and their **goals**, not the widgets: "a tenant who wants to find a flat in Zurich".
|
|
33
|
+
- Say which **states** matter (empty, error, paid, unpaid); each becomes a screen or a `note:`.
|
|
34
|
+
- Ask for `note:` on anything a sketch can't show ("results update live, there is no search button").
|
|
35
|
+
- Mention languages up front if you need them.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
```
|
|
4
|
+
spec.yaml ──► load + parse ──► validate ──► render ──► write dist/
|
|
5
|
+
(yaml) (spec/validate) (render/) │
|
|
6
|
+
├─ index.html (render/page.js)
|
|
7
|
+
├─ openink.js (runtime/ bundled by esbuild)
|
|
8
|
+
└─ openink.css (styles/)
|
|
9
|
+
|
|
10
|
+
dist/ ──► puppeteer-core + Chrome/Edge ──► PDF / PNG (export.js)
|
|
11
|
+
dist/ ──► http server + fs.watch + reload poller (dev.js)
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Design decisions
|
|
15
|
+
|
|
16
|
+
**Spec in, static files out.** The prototype is a single HTML page holding every screen; JavaScript only shows one at a time. That makes the output trivially hostable, printable and shareable by link (`#screen-id`), and it works from `file://`.
|
|
17
|
+
|
|
18
|
+
**One definition per block.** `src/render/blocks/` is the single source of truth. The validator, the JSON Schema, `docs/blocks.md` and `openink blocks` are all generated from it, and tests fail when the generated files are stale. Adding a block is one object.
|
|
19
|
+
|
|
20
|
+
**Validate everything, early.** Assistants and humans both make typos. The validator never throws; it returns `{ errors, warnings }` with a path into the spec and a suggestion, and `build` refuses to write output if there are errors.
|
|
21
|
+
|
|
22
|
+
**Bundled runtime.** wired-elements and RoughJS are bundled into `openink.js` at build time, so a prototype has no CDN dependency (except the Google Fonts stylesheet, which falls back to a system cursive font offline).
|
|
23
|
+
|
|
24
|
+
**No framework in the output.** The runtime is about a hundred lines of plain JavaScript plus the web components from wired-elements.
|
|
25
|
+
|
|
26
|
+
## Layout
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
bin/openink.js CLI entry
|
|
30
|
+
src/
|
|
31
|
+
cli.js argument parsing, commands, output formatting
|
|
32
|
+
build.js load spec → validate → write dist
|
|
33
|
+
dev.js dev server with live reload
|
|
34
|
+
export.js PDF / PNG via headless Chrome
|
|
35
|
+
index.js public API
|
|
36
|
+
spec/ validate.js, schema.js, docs.js
|
|
37
|
+
render/ context.js, page.js, blocks/*
|
|
38
|
+
runtime/ browser code (navigation, i18n, placeholder, redraw)
|
|
39
|
+
styles/ openink.css
|
|
40
|
+
templates/starter/ copied by `openink init`
|
|
41
|
+
examples/ example projects (also test fixtures and README screenshots)
|
|
42
|
+
test/ node:test suites
|
|
43
|
+
scripts/ generate.js (docs + schema), screenshots.js
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Known limitations
|
|
47
|
+
|
|
48
|
+
- wired-elements 3.0 is a release candidate and has not been updated for some time. Its dependency on `roughjs` is pinned to 4.3.1 for that reason (see CONTRIBUTING.md).
|
|
49
|
+
- Form controls are visual only; nothing is validated or submitted.
|
|
50
|
+
- One page per project: very large specs (hundreds of screens) load everything up front.
|