@penpair/web 0.1.1 → 0.1.3

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/README.md CHANGED
@@ -19,10 +19,10 @@
19
19
  </p>
20
20
 
21
21
  <p align="center">
22
+ <a href="#start-here-the-setup-guide"><strong>Start here</strong></a> ·
22
23
  <a href="#why-penpair">Why</a> ·
23
24
  <a href="#quick-start">Quick start</a> ·
24
25
  <a href="#web-or-docker">Web or Docker</a> ·
25
- <a href="#add-penpair-to-your-repo">Add to your repo</a> ·
26
26
  <a href="#packages">Packages</a> ·
27
27
  <a href="#use-it-with-marwes">Marwes</a> ·
28
28
  <a href="#check-each-page-with-reflection">Reflection</a> ·
@@ -40,6 +40,36 @@ penpair makes a Penpot design file the **source of truth** for your project's UI
40
40
  | **Know it** | The rules and the quirks of the tool ship with the code as skills your agent follows. |
41
41
  | **Extend it** | Plug in your component library, your checks and your own snippets. The core stays neutral. |
42
42
 
43
+ ## Start here: the setup guide
44
+
45
+ The easiest way in is to let your AI assistant walk you through it. **[penpair-setup-guide](https://github.com/niklas-westman/penpair/blob/main/skills/penpair-setup-guide/SKILL.md)** is a skill for Claude Code, Codex and GitHub Copilot that guides you from nothing to a first design, one step at a time:
46
+
47
+ 1. checks Node and your project,
48
+ 2. asks whether Penpot runs **on the web** (recommended) or **in Docker** on your computer,
49
+ 3. helps you get a Penpot account and a design file,
50
+ 4. installs penpair and connects the Penpot plugin,
51
+ 5. shows you **where your MCP link goes**, without the key ever passing through the chat, and verifies it all with `doctor`,
52
+ 6. asks whether you want **Marwes UI** tokens in Penpot,
53
+ 7. installs the rules your assistant follows,
54
+ 8. and ends with a **test POC** on its own page, so you see what it can do.
55
+
56
+ **No install needed:** in your project's folder, tell your assistant:
57
+
58
+ > Read https://raw.githubusercontent.com/niklas-westman/penpair/main/skills/penpair-setup-guide/SKILL.md and follow it to set up penpair in this project.
59
+
60
+ **Or install it as a skill** in your project, so it is there next time (also the way to go if your assistant cannot open web pages):
61
+
62
+ ```bash
63
+ # Claude Code
64
+ mkdir -p .claude/skills/penpair-setup-guide && curl -fsSL https://raw.githubusercontent.com/niklas-westman/penpair/main/skills/penpair-setup-guide/SKILL.md -o .claude/skills/penpair-setup-guide/SKILL.md
65
+ # Codex
66
+ mkdir -p .agents/skills/penpair-setup-guide && curl -fsSL https://raw.githubusercontent.com/niklas-westman/penpair/main/skills/penpair-setup-guide/SKILL.md -o .agents/skills/penpair-setup-guide/SKILL.md
67
+ # GitHub Copilot
68
+ mkdir -p .github/skills/penpair-setup-guide && curl -fsSL https://raw.githubusercontent.com/niklas-westman/penpair/main/skills/penpair-setup-guide/SKILL.md -o .github/skills/penpair-setup-guide/SKILL.md
69
+ ```
70
+
71
+ Then ask: *"set up penpair"*. Prefer to do it yourself? Read on: [Quick start](#quick-start).
72
+
43
73
  ## Why penpair
44
74
 
45
75
  An AI assistant can already reach Penpot through its MCP server: it gets one tool that runs code inside your open file. That is power without hands-on knowledge, and designing a whole page that way fails in small, expensive ways. penpair is what makes it dependable, so you can prompt for a page and get a page.
@@ -70,7 +100,7 @@ penpair does not design for you, and it has no "make me a page" button. It makes
70
100
 
71
101
  ## Quick start
72
102
 
73
- > **New here, or not a terminal person?** Follow the step-by-step guide with the browser steps: **[Getting started →](https://github.com/niklas-westman/penpair/blob/main/docs/getting-started.md)**
103
+ > **New here, or not a terminal person?** Let your assistant guide you with the [setup guide](#start-here-the-setup-guide), or follow the step-by-step guide with the browser steps: **[Getting started →](https://github.com/niklas-westman/penpair/blob/main/docs/getting-started.md)**
74
104
 
75
105
  You need [Node.js](https://nodejs.org) 22 or later and a terminal. In your project's folder:
76
106
 
@@ -90,6 +120,15 @@ It asks where your Penpot is and does the rest, saying in plain words what it is
90
120
 
91
121
  Run it again any time; it continues where it stopped. `npx @penpair/web doctor` tells you what works, what does not and what to do about it.
92
122
 
123
+ Then commit what it made (never `.env.local`; it is already git-ignored):
124
+
125
+ ```bash
126
+ git add penpair.config.json .gitignore .skills .agents .claude
127
+ git commit -m "Add penpair"
128
+ ```
129
+
130
+ Each teammate runs their own `npx @penpair/web connect`: the key belongs to a person, not to the repo. To pin penpair for the team, add it as a dev dependency (`npm i -D @penpair/web`, or `@penpair/docker`; one of the two, not both); the command is then `npx penpair …`. To write your own Penpot operations, use the library from the same package: `import { defineSnippet } from "@penpair/web"`.
131
+
93
132
  ## Web or Docker
94
133
 
95
134
  Two ways to run Penpot, one way to connect. Pick one; you can switch later.
@@ -104,38 +143,30 @@ Two ways to run Penpot, one way to connect. Pick one; you can switch later.
104
143
 
105
144
  The full comparison, what is checked and how to switch: **[Web or Docker →](https://github.com/niklas-westman/penpair/blob/main/packages/core/skills/penpair-setup/references/web-or-docker.md)**
106
145
 
107
- ## Add penpair to your repo
108
-
109
- ```bash
110
- cd your-project
111
- npx @penpair/web setup # asks: web or this computer
112
- ```
113
-
114
- Then commit what it made (not `.env.local`; it is already in `.gitignore`):
115
-
116
- ```bash
117
- git add penpair.config.json .gitignore .skills .agents .claude
118
- git commit -m "Add penpair"
119
- ```
120
-
121
- Everyone who works with the assistant does their own `npx @penpair/web connect`: the key belongs to a person, not to the repo. To pin penpair for the team, add it as a dev dependency: `npm i -D @penpair/web` (or `@penpair/docker` for Penpot in Docker; install one of the two, not both). The command is then `npx penpair …`. To write your own Penpot operations, use the library from the same package: `import { defineSnippet } from "@penpair/web"` (the library alone is `@penpair/core`).
122
-
123
146
  ## Packages
124
147
 
125
148
  | Package | What it is | Status |
126
149
  | --- | --- | --- |
127
- | [`@penpair/web`](https://www.npmjs.com/package/@penpair/web) | The `penpair` command for Penpot on the web. Includes everything in the core | 0.1.1 |
128
- | [`@penpair/docker`](https://www.npmjs.com/package/@penpair/docker) | The same command, plus Penpot in Docker on your computer: `up`, `down`, `backup`, `restore`. Includes everything in the core | 0.1.1 |
129
- | [`@penpair/core`](https://www.npmjs.com/package/@penpair/core) | The library and engine, with the skills. No command of its own; the two above are built on it | 0.1.1 |
150
+ | [`@penpair/web`](https://www.npmjs.com/package/@penpair/web) | The `penpair` command for Penpot on the web. Includes everything in the core | Published |
151
+ | [`@penpair/docker`](https://www.npmjs.com/package/@penpair/docker) | The same command, plus Penpot in Docker on your computer: `up`, `down`, `backup`, `restore`. Includes everything in the core | Published |
152
+ | [`@penpair/core`](https://www.npmjs.com/package/@penpair/core) | The library and engine, with the skills. No command of its own; the two above are built on it | Published |
130
153
  | `penpair` | The short name for `@penpair/web`, so that `npx penpair setup` works | Waiting for npm to allow the name (it is blocked as too close to an unrelated package). Until then use `npx @penpair/web`. |
131
- | `@penpair/marwes-ui` | The adapter for the Marwes UI component library | Planned, see below |
154
+ | [`@penpair/marwes-ui`](https://www.npmjs.com/package/@penpair/marwes-ui) | The adapter for the Marwes UI component library: Marwes tokens (and your theme) in Penpot, with drift checks | Published: tokens now, components planned. See below |
132
155
  | `@penpair/reflection-check` | The link to Reflection's `reflection-check`, as its own package (today `penpair baselines` does it) | Planned |
133
156
 
134
157
  You install **one** command package, `@penpair/web` or `@penpair/docker`; the core comes with it.
135
158
 
136
159
  ## Use it with Marwes
137
160
 
138
- Using [Marwes UI](https://marwes.io), the themeable component library for React, Vue and Svelte? Connecting Marwes is the recommended setup: your Penpot file then speaks the same tokens and components as your code, so what is designed is what gets built. The adapter, `@penpair/marwes-ui`, is the next package on the plan: it will import the Marwes tokens into your Penpot file and check that frames use them. Until it ships, set up penpair as above and name Marwes as your library in the project facts the setup skill asks you to fill in; the assistant then works against Marwes's tokens and components.
161
+ Using [Marwes UI](https://marwes.io), the themeable component library for React, Vue and Svelte? Connecting Marwes is the recommended setup: your Penpot file then speaks the same tokens as your code, so what is designed is what gets built.
162
+
163
+ ```bash
164
+ npm i -D @penpair/marwes-ui
165
+ npx penpair marwes tokens snapshot --write # the expected tokens, from the installed Marwes and your own theme
166
+ npx penpair marwes tokens push --apply # Penpot gets them: Marwes sets, plus a small overlay of what your theme changes
167
+ ```
168
+
169
+ The part that keeps it solid is drift: a Marwes upgrade, a theme edit or a hand edit in Penpot is found, not discovered later. `penpair marwes tokens check` runs offline in CI and fails when the committed snapshot no longer matches the installed Marwes; `diff` shows what Penpot lacks and how many shapes each changed token reaches. How it works and how to put it in CI: [Marwes tokens in Penpot, and keeping them true](https://github.com/niklas-westman/penpair/blob/main/docs/marwes-tokens.md). Marwes components in Penpot are not covered yet; they are built as your pages need them.
139
170
 
140
171
  ## Check each page with Reflection
141
172
 
@@ -179,12 +210,12 @@ One thing to know before you rely on it: the percentage is not a verdict. A corr
179
210
 
180
211
  ## For an AI agent
181
212
 
182
- If you were told to set penpair up, read [the setup skill](https://github.com/niklas-westman/penpair/blob/main/packages/core/skills/penpair-setup/SKILL.md) first and follow it. In short:
213
+ Guiding a person through a first setup? Follow [penpair-setup-guide](https://github.com/niklas-westman/penpair/blob/main/skills/penpair-setup-guide/SKILL.md). Repairing a project that is already set up? Follow [penpair-setup](https://github.com/niklas-westman/penpair/blob/main/packages/core/skills/penpair-setup/SKILL.md). Either way:
183
214
 
184
- - Run `npx @penpair/web doctor --json` to see where things stand; every failing check carries a `remedy`.
185
- - Web is the default; use Docker only when the person asks for offline or local data.
186
- - **The personal MCP key never goes through you.** The person pastes it themselves into `npx @penpair/web connect` (a hidden prompt), or pipes it from their clipboard.
187
- - Done means `doctor` reports `ok: true` and "editor and plugin" connected. Then `npx @penpair/web skills install` gives you the rules for working in Penpot (`penpot-design`) and for judging a screen (`design-judgment`).
215
+ - `npx @penpair/web doctor --json` says where things stand; every failing check carries a `remedy`.
216
+ - Web is the default; Docker only when the person asks for offline work or local data.
217
+ - **The personal MCP key never goes through you.** The person pastes it into `npx @penpair/web connect` (a hidden prompt), or pipes it from their clipboard.
218
+ - Done means `doctor` reports `ok: true` and "editor and plugin" connected. Then `skills install` gives you the rules for working in Penpot (`penpair-design`) and for judging a screen (`design-judgment`).
188
219
 
189
220
  ## Commands
190
221
 
@@ -205,12 +236,14 @@ If you were told to set penpair up, read [the setup skill](https://github.com/ni
205
236
 
206
237
  - Penpot's plugin needs the **editor tab open and visible** while the assistant works, so penpair cannot run unattended overnight. It acts on one Penpot at a time, on the page you have open.
207
238
  - Checked against Penpot 2.18.3 (Docker) and the hosted Penpot 2.18.4: the same tools and limits, and a full deep check on both ([compatibility](https://github.com/niklas-westman/penpair/blob/main/docs/compatibility.md)). Not proven yet: a large file with a shared library on the hosted service, paid plans, two editors in one file, and a full `.penpot` export and import round trip.
208
- - penpair is early (0.1.0). Expect rough edges and quick fixes. The plan and the open questions are in [PLAN.md](https://github.com/niklas-westman/penpair/blob/main/PLAN.md).
239
+ - penpair is early (0.1.x). Expect rough edges and quick fixes. The plan and the open questions are in [PLAN.md](https://github.com/niklas-westman/penpair/blob/main/PLAN.md).
209
240
 
210
241
  ## Documentation
211
242
 
212
- - [Getting started](https://github.com/niklas-westman/penpair/blob/main/docs/getting-started.md): step by step, for designers and for whoever sets it up
243
+ - [Setup guide skill](https://github.com/niklas-westman/penpair/blob/main/skills/penpair-setup-guide/SKILL.md): your assistant walks you through the whole setup
244
+ - [Getting started](https://github.com/niklas-westman/penpair/blob/main/docs/getting-started.md): step by step by hand, for designers and for whoever sets it up
213
245
  - [Guide](https://github.com/niklas-westman/penpair/blob/main/docs/guide.md): extension points, instances, commands
246
+ - [Marwes tokens](https://github.com/niklas-westman/penpair/blob/main/docs/marwes-tokens.md): Marwes tokens in Penpot and drift checks
214
247
  - [Compatibility](https://github.com/niklas-westman/penpair/blob/main/docs/compatibility.md): what was checked on which Penpot
215
248
  - [Releasing](https://github.com/niklas-westman/penpair/blob/main/docs/releasing.md), [Changelog](https://github.com/niklas-westman/penpair/blob/main/CHANGELOG.md)
216
249
 
@@ -2,6 +2,8 @@
2
2
 
3
3
  Draft. Written for someone who has not used a terminal much. The steps marked **(not tried yet)** come from Penpot's help pages, not from a run; the first person to follow this guide on a clean machine should mark what differs.
4
4
 
5
+ **Easiest:** let your AI assistant (Claude Code, Codex or GitHub Copilot) walk you through it with the [setup guide skill](https://github.com/niklas-westman/penpair/blob/main/skills/penpair-setup-guide/SKILL.md). This page is the same path by hand.
6
+
5
7
  The normal way is to use Penpot on the web (or your team's own Penpot) and connect the AI assistant to it. Nothing runs on your computer except penpair. If you want your own copy of Penpot on your computer instead, see "Alternative: run Penpot on your own computer" at the end.
6
8
 
7
9
  There are two roles. You may be both.
@@ -62,7 +64,7 @@ If you want to know what your Penpot offers before you start, `npx @penpair/web
62
64
  ```
63
65
  npx @penpair/web skills install
64
66
  ```
65
- This copies the rules the assistant follows (how to work safely in Penpot, and how to judge a screen) into `.skills/` and makes them visible to Codex and Claude Code. It prints a line for each to add to your `AGENTS.md`. Then fill in `.skills/penpot-design/references/project-facts.md` (your file, never replaced): the Penpot file, the token sets, the names you use, who approves.
67
+ This copies the rules the assistant follows (how to work safely in Penpot, and how to judge a screen) into `.skills/` and makes them visible to Codex and Claude Code. It prints a line for each to add to your `AGENTS.md`. Then fill in `.skills/penpair-design/references/project-facts.md` (your file, never replaced): the Penpot file, the token sets, the names you use, who approves.
66
68
 
67
69
  ### Every day
68
70
  Open the file in Penpot, choose **File, MCP Server, Connect**, keep the tab visible, and start working with the assistant.
package/docs/guide.md CHANGED
@@ -6,7 +6,7 @@ The contract an adopting project works through. It grows with the code; each sec
6
6
  | Point | A project supplies | First implementations |
7
7
  | --- | --- | --- |
8
8
  | Connection profile | endpoint, Penpot version, where the token comes from | local Docker, shared self-hosted, hosted |
9
- | Library adapter | where tokens and components come from | Marwes |
9
+ | Library adapter | where tokens and components come from; commands the adapter adds, listed under `adapters` in `penpair.config.json` (`defineAdapter` in `@penpair/core`) | `@penpair/marwes-ui` (tokens) |
10
10
  | Snippet registry | named plugin snippets with inputs and a size check | tree, audit, tokens, archive |
11
11
  | Verification provider | what "matches the design" means | `penpair baselines` (images and Reflection cases, below), a page-verify gate |
12
12
  | Skill pack | rules the agent follows | the Penpot skill, design judgment |
@@ -0,0 +1,119 @@
1
+ # Marwes tokens in Penpot, and keeping them true
2
+
3
+ `@penpair/marwes-ui` puts the design tokens of [Marwes UI](https://marwes.io) (and your own theme on top of them) into your Penpot file, and keeps them from drifting away from the Marwes your app actually uses. The idea in one line: **the installed Marwes and your theme file are the truth; Penpot is made to match, and anything that stops matching is found.**
4
+
5
+ ## How it fits together
6
+
7
+ ```
8
+ installed Marwes ─┐
9
+ (@marwes-ui/core) ├──▶ expected tokens ──▶ committed snapshot ──▶ Penpot file
10
+ your theme file ─┘ (generated) design/…snapshot.json (sets and themes)
11
+ (acmeLight …) reviewed in git
12
+ ```
13
+
14
+ - **Nothing is typed in twice.** The tokens are generated from the Marwes the app resolves and from the theme file the app imports (the same file and export), so what you design with is what the app renders.
15
+ - **Your choices stay visible.** Marwes's own values go in `Marwes · Core` and `Marwes · Dark`. What your theme changes goes in a small overlay set on top (`Acme · Light`, `Acme · Dark`), holding only the differences. A Marwes update moves the Marwes sets and never silently loses your choices, and the colours Marwes derives from yours (hover, pressed, disabled) follow automatically.
16
+ - **The snapshot is the record.** `design/marwes-tokens.snapshot.json` is generated, committed and reviewed like code. A Marwes bump shows up as a readable git diff of exactly which tokens changed.
17
+
18
+ ## Setup
19
+
20
+ ```bash
21
+ npm i -D @penpair/marwes-ui # next to @penpair/web (or @penpair/docker)
22
+ ```
23
+
24
+ In `penpair.config.json`:
25
+
26
+ ```json
27
+ {
28
+ "adapters": ["@penpair/marwes-ui"],
29
+ "marwes": {
30
+ "name": "Acme",
31
+ "project": "packages/app",
32
+ "themes": {
33
+ "light": { "module": "packages/app/src/theme.ts", "export": "acmeLight" },
34
+ "dark": { "module": "packages/app/src/theme.ts", "export": "acmeDark" }
35
+ },
36
+ "snapshot": "design/marwes-tokens.snapshot.json"
37
+ }
38
+ }
39
+ ```
40
+
41
+ | Setting | Meaning |
42
+ | --- | --- |
43
+ | `name` | Prefix for your overlay sets. Defaults to the instance name, capitalised. |
44
+ | `project` | The folder of the package that depends on Marwes (a workspace package in a monorepo). Default: the project root. |
45
+ | `themes` | Your own light and dark themes: a file and the name of its export (a Marwes `ThemeInput`; TypeScript is fine). Leave them out and only the Marwes sets are made. |
46
+ | `snapshot` | Where the committed snapshot lives. Default: `design/marwes-tokens.snapshot.json`. |
47
+
48
+ Then:
49
+
50
+ ```bash
51
+ penpair marwes tokens snapshot --write # generate the expectation and save it; commit the file
52
+ penpair marwes tokens push --apply # make Penpot match (look first without --apply)
53
+ ```
54
+
55
+ ## The commands
56
+
57
+ | Command | Needs Penpot | What it does |
58
+ | --- | --- | --- |
59
+ | `penpair marwes tokens snapshot [--write]` | no | Builds the expected tokens from the installed Marwes and your theme, and shows how they differ from the committed snapshot. `--write` saves it. |
60
+ | `penpair marwes tokens check [--json]` | no | Is the committed snapshot current? Exit 0 yes, 2 stale or missing, 1 broken (for example a half-finished Marwes upgrade). Made for CI. |
61
+ | `penpair marwes tokens diff [--json]` | yes | Penpot against the snapshot: what is missing, what differs, what was added by hand, and **how many shapes use each changed token**. |
62
+ | `penpair marwes tokens push [--apply] [--prune]` | yes | Brings Penpot to the snapshot. Looks first and prints the plan; `--apply` writes. |
63
+ | `penpair marwes tokens status` | optional | One screen: the installed Marwes packages, the snapshot, and Penpot. |
64
+
65
+ ## What can drift, and what catches it
66
+
67
+ | What drifted | Caught by | Resolved by |
68
+ | --- | --- | --- |
69
+ | Marwes was upgraded (any token changed, added or removed) | `check` (offline, in CI): the snapshot is stale | `snapshot --write`, review the git diff, commit, then `push --apply` |
70
+ | Your theme file changed | `check`: the snapshot is stale | the same |
71
+ | Marwes packages are at different versions (a half-finished upgrade) | `check` fails with exit 1 | finish the upgrade; Marwes releases its packages together |
72
+ | **Marwes grew a kind of variable the adapter does not turn into a token** | `check`: the snapshot lists every variable it does not cover, so a new one changes it | review it, then extend the adapter or accept it by writing the snapshot |
73
+ | Someone edited a token in Penpot by hand | `diff`: shown as a difference, with what it reaches | `push --apply` puts it back (Marwes is authoritative) |
74
+ | Someone added a token to a Marwes set by hand | `diff`: "not in the expectation" | kept unless you push with `--prune` |
75
+ | A set was deleted or a theme changed in Penpot | `diff` | `push --apply` |
76
+ | The recorded Marwes version (in every token's description) is old | `diff` | `push --apply` updates it, so the file says which Marwes it came from |
77
+
78
+ ## After a Marwes bump
79
+
80
+ ```bash
81
+ pnpm up @marwes-ui/react # the app moves to the new Marwes
82
+ penpair marwes tokens check # fails: the snapshot is stale, and says what changed
83
+ penpair marwes tokens snapshot --write # regenerate; review `git diff design/` (the tokens that moved)
84
+ penpair marwes tokens diff # what Penpot lacks, and how many shapes each change reaches
85
+ penpair marwes tokens push --apply # bring Penpot along; it reads everything back to verify
86
+ ```
87
+
88
+ `push` refuses to run while the snapshot is stale: the repository's record must lead, so a token never reaches Penpot that has not been through a commit. After the push, export your pages and let [Reflection](https://github.com/niklas-westman/reflection) show you what the new tokens changed visually.
89
+
90
+ ## Keeping it from drifting in the first place
91
+
92
+ - **CI.** Add the check to the same pipeline that runs your tests: `penpair marwes tokens check`. It needs no Penpot and no key, so it runs anywhere. A pull request that bumps Marwes (by hand or by a dependency bot) or edits the theme without a new snapshot cannot merge.
93
+ - **A test, if you prefer.** The adapter exports the same check for your test runner:
94
+
95
+ ```ts
96
+ import { checkTokenSnapshot } from "@penpair/marwes-ui";
97
+
98
+ it("the Penpot token snapshot is current", async () => {
99
+ const check = await checkTokenSnapshot(process.cwd());
100
+ expect(check.problems).toEqual([]);
101
+ expect(check.current).toBe(true);
102
+ });
103
+ ```
104
+
105
+ - **Before designing.** `penpair marwes tokens status` takes a second and says whether the design file is on the Marwes the app uses.
106
+
107
+ ## What `push` does and does not touch
108
+
109
+ - It manages only the sets the snapshot names (`Marwes · …` and your `Acme · Light/Dark`). Any other set in the file is yours and is never touched.
110
+ - It creates new sets inactive and builds the Light and Dark themes. If the file has **no active theme**, it activates Light so the tokens take part; a file that already has an active theme keeps its choice.
111
+ - Plain values are updated in place. Typography tokens are removed and added again, because Penpot stores a typography value assigned in place un-normalised.
112
+ - Tokens go in batches that stay under Penpot's request limit, and it stops at the first token Penpot rejects and says which.
113
+ - Afterwards it reads everything back: the file must match the snapshot, and **no shape may have moved or been rebound** (a fingerprint of every page's structure is compared before and after). Otherwise it says so and exits 1.
114
+
115
+ ## What is covered, and what is not
116
+
117
+ Everything Marwes resolves for a theme becomes a token: colours, density sizes, the two radii, the three font families and the typography styles, plus the spacing scale. A variable that is not (today: `--mw-density-spacing-multiplier`, a multiplier) is listed in the snapshot's `unmapped` field and in `snapshot` output, so the gap is visible and a change to it is noticed.
118
+
119
+ Not covered yet: Marwes **components** in Penpot. Tokens come first; components are built as pages need them.
package/docs/releasing.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Releasing
2
2
 
3
- All packages in this repository are released **together, at one version, even a package that did not change**: `@penpair/core`, `@penpair/web`, `@penpair/docker`, `penpair`, and anything added under `packages/` later. The root of the repository is a private workspace and is never published. The rule is enforced, not remembered:
3
+ All packages in this repository are released **together, at one version, even a package that did not change**: `@penpair/core`, `@penpair/web`, `@penpair/docker`, `@penpair/marwes-ui`, `penpair`, and anything added under `packages/` later. The root of the repository is a private workspace and is never published. The rule is enforced, not remembered:
4
4
 
5
5
  | Guard | What it stops |
6
6
  | --- | --- |
@@ -22,7 +22,7 @@ Publishing cannot be undone: a version, once published, cannot be replaced. Chec
22
22
  pnpm bump patch # or minor, major, or an exact x.y.z: every package and version.ts move together
23
23
  # add a section to CHANGELOG.md
24
24
  pnpm check # typecheck, tests, build and the version check
25
- git commit -am "Release 0.1.2" && git push
25
+ git commit -am "Release 0.1.3" && git push
26
26
 
27
27
  pnpm release # dry run: checks everything, prints the plan, publishes nothing
28
28
  pnpm release --publish # the real thing; npm asks for your one-time code (or add --otp <code>)
@@ -63,13 +63,14 @@ The release is then reported as `INCOMPLETE` (exit code 3) on purpose, and `pnpm
63
63
  npm view @penpair/core version
64
64
  npm view @penpair/web version
65
65
  npm view @penpair/docker version
66
+ npm view @penpair/marwes-ui version
66
67
  ```
67
68
 
68
69
  Then, in an empty folder, run `npx @penpair/web --version`, `npx @penpair/web setup --help` and `npx @penpair/docker --version` (and, once the short name is published, the same with `npx penpair`). Tag the release if you want one: `git tag v<version> && git push origin v<version>`.
69
70
 
70
71
  ## What each package ships
71
72
 
72
- The core ships `dist`, `skills`, `LICENSE` and a short `README.md`. The web package ships `dist`, `docs`, `LICENSE` and the repository's `README.md` (copied in by `prepack`, git-ignored there). The Docker package ships `dist`, `LICENSE` and `README.md`. The short name ships `bin`, `LICENSE` and `README.md`. Check with `npm pack --dry-run --ignore-scripts` in a package.
73
+ The core ships `dist`, `skills`, `LICENSE` and a short `README.md`. The web package ships `dist`, `docs`, `LICENSE` and the repository's `README.md` (copied in by `prepack`, git-ignored there). The Docker package and the Marwes adapter ship `dist`, `LICENSE` and `README.md`. The short name ships `bin`, `LICENSE` and `README.md`. Check with `npm pack --dry-run --ignore-scripts` in a package.
73
74
 
74
75
  ## After publishing
75
76
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@penpair/web",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "The penpair command for Penpot on the web (design.penpot.app or your team's own): guided setup, a safe write protocol, skills for AI agents. Includes everything in @penpair/core.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -20,8 +20,8 @@
20
20
  "types": "./dist/index.d.ts",
21
21
  "exports": {
22
22
  ".": {
23
- "import": "./dist/index.js",
24
- "types": "./dist/index.d.ts"
23
+ "types": "./dist/index.d.ts",
24
+ "import": "./dist/index.js"
25
25
  },
26
26
  "./cli": "./dist/cli.js",
27
27
  "./package.json": "./package.json"
@@ -47,7 +47,7 @@
47
47
  "access": "public"
48
48
  },
49
49
  "dependencies": {
50
- "@penpair/core": "0.1.1"
50
+ "@penpair/core": "0.1.3"
51
51
  },
52
52
  "scripts": {
53
53
  "build": "tsc -p tsconfig.json",