@plitzi/cli 0.38.7 → 0.38.9
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 +251 -0
- package/README.md +191 -78
- package/dist/index.js +11019 -8597
- package/package.json +3 -3
- package/skills/plitzi-cli/SKILL.md +43 -198
- package/skills/plitzi-cli/reference/from-space.md +5 -5
- package/skills/plitzi-cli/reference/functions.md +4 -5
- package/skills/plitzi-cli/reference/plugins.md +75 -0
- package/skills/plitzi-cli/reference/projects.md +42 -0
- package/skills/plitzi-cli/reference/troubleshooting.md +12 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plitzi/cli",
|
|
3
|
-
"version": "0.38.
|
|
3
|
+
"version": "0.38.9",
|
|
4
4
|
"license": "AGPL-3.0",
|
|
5
5
|
"description": "Command line for Plitzi: scaffold a project that renders a space, a plugin package, or an element of your own.",
|
|
6
6
|
"files": [
|
|
@@ -21,14 +21,14 @@
|
|
|
21
21
|
},
|
|
22
22
|
"sideEffects": false,
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@plitzi/sdk-authoring": "0.38.
|
|
24
|
+
"@plitzi/sdk-authoring": "0.38.9",
|
|
25
25
|
"chalk": "^6.0.1",
|
|
26
26
|
"commander": "^15.0.0",
|
|
27
27
|
"esbuild": "^0.28.2",
|
|
28
28
|
"fflate": "^0.8.3"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@plitzi/sdk-shared": "0.38.
|
|
31
|
+
"@plitzi/sdk-shared": "0.38.9",
|
|
32
32
|
"@types/node": "^26.6.4",
|
|
33
33
|
"eslint": "^9.39.5",
|
|
34
34
|
"eslint-plugin-import": "^2.32.0",
|
|
@@ -4,211 +4,56 @@ description: >-
|
|
|
4
4
|
Use the Plitzi command line (@plitzi/cli, `plitzi …` or `npx @plitzi/cli …`) instead of hand-writing what it
|
|
5
5
|
generates: scaffold a project that renders a space, add plugins to it or build a plugin package, pack, upload and
|
|
6
6
|
install one, edit a space's functions, take a space on Plitzi out as a self-hosted project and back (`create --from`,
|
|
7
|
-
`pull`, `push`),
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
`space pull`, `space push`), check a project (`doctor`) or how its space's source is written (`space lint`), and
|
|
8
|
+
write a report to Plitzi of what broke, misled or cost time (`feedback`). Use whenever the task is to start a Plitzi
|
|
9
|
+
project, create or change a plugin, pack, upload or install one, pull/push/try a space's functions, move a space to a
|
|
10
|
+
server of its own and back, work out which space the CLI is connected to — or when the person asks for a report,
|
|
11
|
+
feedback or a list of what went wrong with Plitzi.
|
|
10
12
|
---
|
|
11
13
|
|
|
12
14
|
# The Plitzi CLI
|
|
13
15
|
|
|
14
|
-
The CLI writes what an agent would otherwise get subtly wrong by hand: a project's server, bundler, lint and visual
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
The CLI writes what an agent would otherwise get subtly wrong by hand: a project's server, bundler, lint and visual test
|
|
17
|
+
wired together; a plugin's files in the shape Plitzi's own elements use; a signed-in upload. **Reach for it before
|
|
18
|
+
writing any of those yourself.** `plitzi <command> --help` lists every flag.
|
|
17
19
|
|
|
18
20
|
```bash
|
|
19
|
-
npx
|
|
20
|
-
npx
|
|
21
|
-
npx
|
|
22
|
-
npx
|
|
23
|
-
npx
|
|
24
|
-
npx
|
|
25
|
-
npx
|
|
26
|
-
npx
|
|
27
|
-
npx
|
|
28
|
-
npx
|
|
29
|
-
npx @plitzi/cli upgrade # the project up to this CLI: files, package.json, skills, renames (--write)
|
|
30
|
-
npx @plitzi/cli explain navigate # what a name means: element, step, trigger, code, helper (bindTemplate, motion)
|
|
31
|
-
npx @plitzi/cli functions pull # the space's functions (its own server code) into src/functions/
|
|
32
|
-
npx @plitzi/cli functions push # src/functions/ back as the space's draft, built and checked
|
|
33
|
-
npx @plitzi/cli functions try feed.read --params '{"limit":3}' # one task of the saved draft, in the sandbox
|
|
34
|
-
npx @plitzi/cli functions dev feed.read --watch # the same, from src/functions/, on this machine
|
|
21
|
+
npx plitzi element where hero-cta # where the code writes an element: file:line and the call
|
|
22
|
+
npx plitzi element edit hero-cta --set content="Hi" # an attribute written there, checked
|
|
23
|
+
npx plitzi element remove ent-trust # an element taken out, with what only it used
|
|
24
|
+
npx plitzi element move ent-faq --before ent-pricing # an element put elsewhere among its siblings
|
|
25
|
+
npx plitzi verify # left passing? author, lints, types, format, pages
|
|
26
|
+
npx plitzi page check -- /about --width 1440,390 # whether a page is whole, in text
|
|
27
|
+
npx plitzi explain navigate # what a name means: element, step, code, any export
|
|
28
|
+
npx plitzi doctor # whether the project is whole; --fix the simple parts
|
|
29
|
+
npx plitzi upgrade # the project up to this CLI (--write)
|
|
30
|
+
npx plitzi feedback # a report to Plitzi, for the person to send as a link
|
|
35
31
|
```
|
|
36
32
|
|
|
37
|
-
`plitzi <command> --help` lists every flag; what follows is what the help does not say.
|
|
38
|
-
|
|
39
33
|
## Running it as an agent
|
|
40
34
|
|
|
41
|
-
- **Which check.**
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
- **
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
Where the space lives decides which one an agent uses — the two never take turns on one space.
|
|
68
|
-
|
|
69
|
-
| The space | Use |
|
|
70
|
-
| --- | --- |
|
|
71
|
-
| In a project, written in code (`src/space/`, `--source local`) | this CLI and `@plitzi/sdk-authoring`. No account and no MCP |
|
|
72
|
-
| On Plitzi — edited in the builder, with collaborators, published from there | the Plitzi MCP server: it reads and edits the live space, previews a page and checks every edit with the same linter |
|
|
73
|
-
| On Plitzi, and wanted in code from now on | `create --from <space>`, then `pull` and `push` keep both in step |
|
|
74
|
-
|
|
75
|
-
The MCP needs a signed-in account; when nobody can give one, do not wait on it: a `--source local` project needs
|
|
76
|
-
neither.
|
|
77
|
-
|
|
78
|
-
## Projects (`create`)
|
|
79
|
-
|
|
80
|
-
| | `--source local` | `--source cloud` |
|
|
81
|
-
| --- | --- | --- |
|
|
82
|
-
| `--mode server` | A page server of your own, rendering the space in `src/space/`. No account | Your page server, rendering the live space from Plitzi (secret self-hosting key in `.env`) |
|
|
83
|
-
| `--mode client` | Vite + the SDK in the browser, no server, no account | The SDK fetches the space with the public render key |
|
|
84
|
-
|
|
85
|
-
What a project gives you, so you use it rather than rebuild it:
|
|
86
|
-
|
|
87
|
-
| Script | What it is for |
|
|
88
|
-
| --- | --- |
|
|
89
|
-
| `start` | serve it — in client mode Vite, which hot-replaces on save. The server prints only what goes wrong; `-- --verbose` adds every request |
|
|
90
|
-
| `start:dev` | server mode: restarted on a save to its code; a plugin is swapped in the open page. Options in `src/config/serverOptions.ts`, actions in `src/actions/`; `plitzi/` is the CLI's, never edit it |
|
|
91
|
-
| `author` | author `src/space/`: every problem at once (file:line, what to change), then the suggestions (`[suggest]`: a shorter way to the same page, the most elements saved first); `-- --json` for a tool |
|
|
92
|
-
| `lint:space` | how `src/space/` is written, at file:line, and authoring's suggestions; `-- --max-warnings 0`. On purpose: `// plitzi-lint-disable-next-line <code> -- why` (a suggestion: `quiet` on its element) |
|
|
93
|
-
| `npx plitzi fix` | what `author` reports that has one fix, as a diff of your source; `--write` writes it, formatted, and keeps it only if the space then authors with it gone and nothing new |
|
|
94
|
-
| `check -- /path --width 1440,390` | whether a page is whole, in text: elements on screen, overflow, console, refused requests, failed flows, a binding its data lacks; `--state`, `--element <id>`: what it holds; `--ssr`: SSR misses; `--as <user>`; `--json` |
|
|
95
|
-
| `npx plitzi import <url>` | a page the user owns, as a start: `tokens.ts`, `outline.ts` (blocks and layout per breakpoint), lists as `data/*.json`, screenshots, `IMPORT.md`. Never the words. **Only when the user asks.** A site not on this machine needs `--account` (their Plitzi account, its domain verified on a space): ask first |
|
|
96
|
-
| `shot -- /path --width 390 --scheme dark` | a picture of one page — `--clip <element>` one element, `--scroll-to <element>` / `--viewport` the screen there, `--frames 4` what moves, `--compare <url>` what differs from another site, by section and by text |
|
|
97
|
-
| `visual` | a browser asserts every element the space names is visible |
|
|
98
|
-
| `typecheck`, `lint`, `format` | before calling a change done |
|
|
99
|
-
|
|
100
|
-
**Which port.** `start` takes 8080, or the next free one — printed, and written to `tmp/dev-server.json` for `check`,
|
|
101
|
-
`shot` and `visual`. `PORT` chooses one (a taken one is then an error). `/health` answers with the space's name.
|
|
102
|
-
|
|
103
|
-
Data with no backend, server mode: `src/data/*.json`, never served — a provider with `runtime: 'server'` and `query:
|
|
104
|
-
'/data/x.json'` reads it on the server. Client mode: `public/data/`, fetched — public. Learn a file's fields with
|
|
105
|
-
`data describe`, never by reading it.
|
|
106
|
-
|
|
107
|
-
**`public/` is on the internet**: never a secret there. `tmp/`, `state/` (its `kv`) ignored; `.plitzi/` committed.
|
|
108
|
-
`--dry-run` on a command that writes or sends says what it would do, and does none of it.
|
|
109
|
-
|
|
110
|
-
A local space starts as a tour of the platform with a plugin of the project's own; **`--template blank`** as tokens, a
|
|
111
|
-
layout and one empty page — for a project about to be a specific site; **`--template catalog`** as a small shop
|
|
112
|
-
(layout, card component, data in `src/data`, a filtered list, a page per product), a file per part — the one to read
|
|
113
|
-
when unsure how a whole site is put together.
|
|
114
|
-
|
|
115
|
-
The space itself is written with `@plitzi/sdk-authoring` — see the `plitzi-authoring` skill, which `create` copies into
|
|
116
|
-
`.claude/skills/` beside this one.
|
|
117
|
-
|
|
118
|
-
## A space on Plitzi, as a project (`create --from`, `pull`)
|
|
119
|
-
|
|
120
|
-
Taking a space out of Plitzi as a server project of its own, and keeping it in step: read
|
|
121
|
-
[reference/from-space.md](reference/from-space.md) when the task names `--from` or `pull`.
|
|
122
|
-
|
|
123
|
-
## Elements of your own (`add plugin`)
|
|
124
|
-
|
|
125
|
-
A plugin is a React component the space renders — a map, a chart, a seat picker: whatever is not text in a box. **Never
|
|
126
|
-
start one from a blank file**: `add plugin <name>` writes it in the shape the platform, the builder and the linter all
|
|
127
|
-
read.
|
|
128
|
-
|
|
129
|
-
```bash
|
|
130
|
-
plitzi add plugin seat-picker # one; asks what the builder calls it and what it is for
|
|
131
|
-
plitzi add plugin seat-picker legend # several at once
|
|
132
|
-
plitzi add plugin ticker --prop interval:number=5000 --prop paused:boolean --trigger onTick:count --callback reset --headless
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
**Say its shape and it is written in it**: `--prop name:type=default` (string, number, boolean; `list`/`json` for data
|
|
136
|
-
a binding fills) per attribute — typed, bindable, with a control in its panel; `--trigger onTick:count` per event and
|
|
137
|
-
what a flow reads, fired with its `use<Name>Events()` hook; `--callback reset` per action a flow calls; `--headless`
|
|
138
|
-
for one with nothing to see. Without them it writes a counter showing the three ways an element talks to a space.
|
|
139
|
-
|
|
140
|
-
Each is a folder (`src/plugins/SeatPicker/` in a project `create` wrote):
|
|
141
|
-
|
|
142
|
-
| File | What it holds |
|
|
143
|
-
| --- | --- |
|
|
144
|
-
| `SeatPicker.tsx` | the component. Its props ARE the element's attributes; render through `RootElement` |
|
|
145
|
-
| `declaration.ts` | its `type`, the `triggers` (events) it fires, the `callbacks` (actions) it answers, its default attributes — data only |
|
|
146
|
-
| `Settings.tsx` | its panel in the builder |
|
|
147
|
-
| `index.ts` | the three put together |
|
|
148
|
-
|
|
149
|
-
- **Registered by itself**: every folder of `src/plugins` is, under its name in camelCase (`SeatPicker` → `seatPicker`).
|
|
150
|
-
Elsewhere the command prints the line that registers it (for `render()`, `<PlitziSdk>` or a page server).
|
|
151
|
-
- **Host it** with `custom({ renderType: 'seatPicker', … })` in `src/space/` — or a Custom element in the builder.
|
|
152
|
-
- **Checked like a built-in element**: its folder's `declaration.ts` is found by itself and handed to
|
|
153
|
-
`authorSpace(space, { plugins })`: flows on its events, steps to its actions and its attributes are
|
|
154
|
-
refused when wrong; `declaredTrigger(declaration, 'onPick')` and `declaredCallback(declaration, 'reset', { on: 'seats' })`
|
|
155
|
-
build them typed. A plugin written by hand is added to that list.
|
|
156
|
-
- **A new event or action** is declared in `declaration.ts` and registered by the component FROM there — never only
|
|
157
|
-
in the component, or neither the builder nor the linter knows it exists.
|
|
158
|
-
- A name that is a built-in type (`button`, `form`) is refused: a space could not tell the two apart.
|
|
159
|
-
- **A server half** (`--server`): `functions/index.ts` in its folder — routes under `/fn/plugins/<type>/`
|
|
160
|
-
(`usePluginRoute`), steps `<type>.<action>`, its own `kv`, none of the space's credentials.
|
|
161
|
-
|
|
162
|
-
## Plugin packages (`create --plugin`)
|
|
163
|
-
|
|
164
|
-
Elements any space can load, published on their own, with a Vite preview to write them in:
|
|
165
|
-
|
|
166
|
-
```bash
|
|
167
|
-
plitzi create seat-picker --plugin
|
|
168
|
-
plitzi create packages/seat-picker --plugin --name @acme/plitzi-plugin-seat-picker --elements legend,price-tag
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
Its scripts: `start` (the elements inside a space, hot-replaced), `visual`, `typecheck`, `lint`. Add more elements with
|
|
172
|
-
`add plugin` from inside it — they are listed in `src/elements.ts` and `src/declarations.ts`, which the package
|
|
173
|
-
publishes from. A package's element is authored as a TYPE of its own: `defineElement<SeatPickerAttributes>(declaration)`.
|
|
174
|
-
|
|
175
|
-
## Building and shipping (`pack plugin`, `upload plugin`)
|
|
176
|
-
|
|
177
|
-
```bash
|
|
178
|
-
plitzi pack plugin # in a plugin package: every element
|
|
179
|
-
plitzi pack plugin src/plugins/SeatPicker # an element of a project; several folders → one plugin, the first its main
|
|
180
|
-
plitzi upload plugin # the zip pack left, onto the space whoami names, installed there
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
`pack` writes one ES module (React and the SDK kept out — the page provides them), `plugin-manifest.json` from the
|
|
184
|
-
declarations with integrity hashes, and the zip the builder takes under Resources. `upload` checks the manifest,
|
|
185
|
-
sends the zip to one of the space's CDNs (`--cdn`) and installs it — a plugin already there moves to the new version with
|
|
186
|
-
its settings kept. `--plugin-version` sets the version the manifest carries. The plugin's source — every file it
|
|
187
|
-
imports, followed from its entry — is kept beside it on the space (`runtime push` does the same for a runtime), which
|
|
188
|
-
is what `create --from` brings back; `plitzi pack source` writes what would be kept to a file, to look at.
|
|
189
|
-
|
|
190
|
-
A self-hosted page server does not need `pack`: it compiles a plugin from its source (`action: 'compile'`).
|
|
191
|
-
|
|
192
|
-
The same server decides its own say over the space's **feature flags**: `createServer({ flags: { newCheckout: true } })`
|
|
193
|
-
(or a function of `{ spaceId, environment }` when it serves several). It overrides what the space declares — only for
|
|
194
|
-
flags the space declares — and is overridden by the SDK's `flags` prop and a tester's dev tools. Declaring the flags
|
|
195
|
-
themselves is the space's (`flags` in the spec; see the authoring skill's feature flags).
|
|
196
|
-
|
|
197
|
-
## Server code (`functions`, `runtime`)
|
|
198
|
-
|
|
199
|
-
A space's own server code, edited in `src/functions/` (`pull`, `push`, `try`, `dev`) or run as its runtime
|
|
200
|
-
(`src/runtime/`, `add runtime`, `runtime push`): read [reference/functions.md](reference/functions.md) for either.
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
## When something does not work
|
|
204
|
-
|
|
205
|
-
| What you see | What it is |
|
|
206
|
-
| --- | --- |
|
|
207
|
-
| `create` printed questions and wrote nothing | nobody answered the three choices — ask the user, pass them as flags |
|
|
208
|
-
| `start` says the port is in use | `PORT` is set to a taken port — unset it to take the next free one, or choose another |
|
|
209
|
-
| A page that is not this project's, or `shot` refuses the port | another server answers there — `curl 127.0.0.1:<port>/health` names it; `tmp/dev-server.json` has this project's port |
|
|
210
|
-
| "Custom Component … Not Found", or a flow on a plugin's event never runs | `doctor` names the folder whose type or declaration is off |
|
|
211
|
-
| "not laid out as Plitzi reads it" | each misplaced part, with its fix; `doctor --fix` |
|
|
212
|
-
| `upload` opens a browser | there is no session, or no space chosen — the person completes it there |
|
|
213
|
-
| The upload went to the wrong space | `plitzi space` chooses another; check `whoami` first |
|
|
214
|
-
| `pull` wrote nothing and named files | they changed here and on the space — set your changes aside and pull again, or `--force` |
|
|
35
|
+
- **Which check.** All of it before you finish: `verify` — only what fails is printed. The space alone: `npm run
|
|
36
|
+
author`; a page: `page check`. The project around them: `doctor`, before `space push`. Pages for signed-in visitors
|
|
37
|
+
are checked as the account `.env` names (`PLITZI_CHECK_USER`, `PLITZI_CHECK_PASSWORD`); `verify` says when none is.
|
|
38
|
+
- **`create` never decides for the person.** With nobody at the terminal it writes nothing and prints each choice as a
|
|
39
|
+
question: ask the user, then run again with their answers as flags. Never guess them.
|
|
40
|
+
- **Signing in happens in the browser** (`login`, `space use`, a first `plugin upload`): tell the person a tab is waiting.
|
|
41
|
+
- **One space at a time** — the one `whoami --json` names; `plitzi space use` switches it.
|
|
42
|
+
- **A report to Plitzi** — the person asks for a report, feedback, the bugs found or what cost time: `npx plitzi
|
|
43
|
+
feedback` (`--previous <link>` continues an earlier one). It reads the versions and `doctor` itself and writes the
|
|
44
|
+
page; fill it and publish it as its brief says, rather than a report of your own making.
|
|
45
|
+
- **Read stdout, exit code and stderr apart.** The answer is on stdout (`--json`: one line); exit 1 means it did not do
|
|
46
|
+
what was asked. A refusal says what to change: change it — the same refusal twice says to stop and ask.
|
|
47
|
+
|
|
48
|
+
**The MCP or this CLI.** A space written in code (`src/space/`) is this CLI's, with no account. One kept on Plitzi —
|
|
49
|
+
edited in the builder — is the Plitzi MCP's. Never both on one space.
|
|
50
|
+
|
|
51
|
+
## What to read
|
|
52
|
+
|
|
53
|
+
| The task | Read |
|
|
54
|
+
| -------------------------------------------------------------------------- | ----------------------------------------------- |
|
|
55
|
+
| Start a project, its modes, scripts and port | [projects](reference/projects.md) |
|
|
56
|
+
| An element of your own, a plugin package, packing and uploading one | [plugins](reference/plugins.md) |
|
|
57
|
+
| A space on Plitzi as a project, and back (`create --from`, `space pull`, `space push`) | [from-space](reference/from-space.md) |
|
|
58
|
+
| The space's own server code (`functions`, `runtime`) | [functions](reference/functions.md) |
|
|
59
|
+
| Something does not work | [troubleshooting](reference/troubleshooting.md) |
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# A space on Plitzi, as a project (`create --from`, `pull`, `push`)
|
|
1
|
+
# A space on Plitzi, as a project (`create --from`, `space pull`, `space push`)
|
|
2
2
|
|
|
3
3
|
`create --from <space>` (its permanent URL or id) writes a server project holding everything the space is made of, and
|
|
4
4
|
serving it with nothing of Plitzi's — neither its servers nor its CDN:
|
|
@@ -17,19 +17,19 @@ pinned) says otherwise. Read the report it prints: a
|
|
|
17
17
|
plugin or runtime uploaded before Plitzi kept sources comes across built only (`vendor/`), and a space with visitor
|
|
18
18
|
roles needs sign-in of its own (the report says how).
|
|
19
19
|
|
|
20
|
-
`pull` brings the project up to date: what changed on the space alone is written, what changed here alone is kept,
|
|
20
|
+
`space pull` brings the project up to date: what changed on the space alone is written, what changed here alone is kept,
|
|
21
21
|
and when one file changed on both it writes **nothing** and names them — keep your changes aside and pull again, or
|
|
22
22
|
`--force` to take the space's copy. It never touches `.env`, and only adds to `package.json`. What the project was given
|
|
23
23
|
is recorded in `.plitzi/space.json`: commit it. It follows the version the project was made from; `pull --environment
|
|
24
24
|
… --revision …` moves it to another, `--revision latest` lets go of a pin.
|
|
25
25
|
|
|
26
|
-
`push` is the way back: what changed in the project, as the space's **draft** — publishing stays the builder's. At a
|
|
26
|
+
`space push` is the way back: what changed in the project, as the space's **draft** — publishing stays the builder's. At a
|
|
27
27
|
terminal it lists the parts with what changed ticked; otherwise it sends what changed, or the parts named:
|
|
28
|
-
`push space functions` (`space`, `functions`, `data`, `runtime`, `plugins`, `files`). Plugins and the files of
|
|
28
|
+
`space push space functions` (`space`, `functions`, `data`, `runtime`, `plugins`, `files`). Plugins and the files of
|
|
29
29
|
`public/assets/` go up first (each file at the same path under the space's `assets/`), then the functions, the data, the
|
|
30
30
|
runtime, and the pages, actions and connectors last. Only `public/assets/` reaches the space's CDN: put a file the space
|
|
31
31
|
names there, never elsewhere in `public/`. It is refused when the draft was edited in the builder since the
|
|
32
32
|
project last had it — pull first, or `--force` to replace it — and a project that never had the space may only take a
|
|
33
33
|
space nobody has worked on without `--force`. It pushes to the space the CLI is connected to, which must be the one
|
|
34
|
-
the project came from, and records what it sent in `.plitzi/space.json`, so `pull` works afterwards — on a project that
|
|
34
|
+
the project came from, and records what it sent in `.plitzi/space.json`, so `space pull` works afterwards — on a project that
|
|
35
35
|
started on its own too.
|
|
@@ -4,9 +4,9 @@ A space's own server code — TypeScript tasks its actions run as steps, and rou
|
|
|
4
4
|
`src/functions/` in a project is a **working copy** of it. The contract (`defineFunctions`, `ctx`) is typed in
|
|
5
5
|
`@plitzi/sdk-server/functions`, whose `.d.ts` documents every field; what matters for the CLI:
|
|
6
6
|
|
|
7
|
-
- **Pull before you edit, push when done.** `pull` refuses to overwrite what is not pushed (`--force` throws it
|
|
8
|
-
away); `push` refuses when the space changed since the pull — someone saved in the builder. Then: keep your
|
|
9
|
-
aside, `pull`, apply them again, `push`. Never `--force` over somebody else's work to get past it.
|
|
7
|
+
- **Pull before you edit, push when done.** `functions pull` refuses to overwrite what is not pushed (`--force` throws it
|
|
8
|
+
away); `functions push` refuses when the space changed since the pull — someone saved in the builder. Then: keep your
|
|
9
|
+
changes aside, `functions pull`, apply them again, `functions push`. Never `--force` over somebody else's work to get past it.
|
|
10
10
|
- **A push is checked, not just stored.** A problem comes back as `src/functions/<file>:<line> <message>` and nothing is
|
|
11
11
|
saved — fix it and push again. `index.ts` must default-export `defineFunctions({ … })`; files import each other by
|
|
12
12
|
relative path and `@plitzi/sdk-server/functions`, nothing else. `src/data/` is read with `ctx.data('x.json')`, never
|
|
@@ -21,7 +21,7 @@ A space's own server code — TypeScript tasks its actions run as steps, and rou
|
|
|
21
21
|
## A space's runtime (`runtime`)
|
|
22
22
|
|
|
23
23
|
What a function cannot be — Node packages, a connection held open, state across requests — is the space's **runtime**:
|
|
24
|
-
`src/runtime/index.ts` (`plitzi add
|
|
24
|
+
`src/runtime/index.ts` (`plitzi runtime add`), default-exporting `defineRuntime` from `@plitzi/sdk-server/runtime` (its
|
|
25
25
|
`.d.ts` documents it). The project's server runs it as Plitzi does, so try it with `npm start` before pushing.
|
|
26
26
|
|
|
27
27
|
- `runtime push` packs it (`--entry` for another file) as the draft's runtime; publishing deploys it. Its source goes
|
|
@@ -30,4 +30,3 @@ What a function cannot be — Node packages, a connection held open, state acros
|
|
|
30
30
|
reads the value from stdin (`printf %s "$V" | …`), never echo it in a command line; `vars unset NAME` removes one.
|
|
31
31
|
- `runtime size small|medium|large`, `stop`, `start` — the draft's unless `--environment` names a published one.
|
|
32
32
|
- It needs a plan that includes runtimes and a private bucket on the space's CDN; a refusal says which is missing.
|
|
33
|
-
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Elements of your own, and plugin packages
|
|
2
|
+
|
|
3
|
+
## Elements of your own (`plugin add`)
|
|
4
|
+
|
|
5
|
+
A plugin is a React component the space renders — a map, a chart, a seat picker: whatever is not text in a box. **Never
|
|
6
|
+
start one from a blank file**: `add plugin <name>` writes it in the shape the platform, the builder and the linter all
|
|
7
|
+
read.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
plitzi plugin add seat-picker # one; asks what the builder calls it and what it is for
|
|
11
|
+
plitzi plugin add seat-picker legend # several at once
|
|
12
|
+
plitzi plugin add ticker --prop interval:number=5000 --prop paused:boolean --trigger onTick:count --callback reset --headless
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
**Say its shape and it is written in it**: `--prop name:type=default` (string, number, boolean; `list`/`json` for data
|
|
16
|
+
a binding fills) per attribute — typed, bindable, with a control in its panel; `--trigger onTick:count` per event and
|
|
17
|
+
what a flow reads, fired with its `use<Name>Events()` hook; `--callback reset` per action a flow calls; `--headless`
|
|
18
|
+
for one with nothing to see. Without them it writes a counter showing the three ways an element talks to a space.
|
|
19
|
+
|
|
20
|
+
Each is a folder (`src/plugins/SeatPicker/` in a project `create` wrote):
|
|
21
|
+
|
|
22
|
+
| File | What it holds |
|
|
23
|
+
| --- | --- |
|
|
24
|
+
| `SeatPicker.tsx` | the component. Its props ARE the element's attributes; render through `RootElement` |
|
|
25
|
+
| `declaration.ts` | its `type`, the `triggers` (events) it fires, the `callbacks` (actions) it answers, its default attributes — data only |
|
|
26
|
+
| `Settings.tsx` | its panel in the builder |
|
|
27
|
+
| `index.ts` | the three put together |
|
|
28
|
+
|
|
29
|
+
- **Registered by itself**: every folder of `src/plugins` is, under its name in camelCase (`SeatPicker` → `seatPicker`).
|
|
30
|
+
Elsewhere the command prints the line that registers it (for `render()`, `<PlitziSdk>` or a page server).
|
|
31
|
+
- **Host it** with `custom({ renderType: 'seatPicker', … })` in `src/space/` — or a Custom element in the builder.
|
|
32
|
+
- **Checked like a built-in element**: its folder's `declaration.ts` is found by itself and handed to
|
|
33
|
+
`authorSpace(space, { plugins })`: flows on its events, steps to its actions and its attributes are
|
|
34
|
+
refused when wrong; `declaredTrigger(declaration, 'onPick')` and `declaredCallback(declaration, 'reset', { on: 'seats' })`
|
|
35
|
+
build them typed. A plugin written by hand is added to that list.
|
|
36
|
+
- **A new event or action** is declared in `declaration.ts` and registered by the component FROM there — never only
|
|
37
|
+
in the component, or neither the builder nor the linter knows it exists.
|
|
38
|
+
- A name that is a built-in type (`button`, `form`) is refused: a space could not tell the two apart.
|
|
39
|
+
- **A server half** (`--server`): `functions/index.ts` in its folder — routes under `/fn/plugins/<type>/`
|
|
40
|
+
(`usePluginRoute`), steps `<type>.<action>`, its own `kv`, none of the space's credentials.
|
|
41
|
+
|
|
42
|
+
## Plugin packages (`create --plugin`)
|
|
43
|
+
|
|
44
|
+
Elements any space can load, published on their own, with a Vite preview to write them in:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
plitzi create seat-picker --plugin
|
|
48
|
+
plitzi create packages/seat-picker --plugin --name @acme/plitzi-plugin-seat-picker --elements legend,price-tag
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Its scripts: `start` (the elements inside a space, hot-replaced), `visual`, `typecheck`, `lint`. Add more elements with
|
|
52
|
+
`plugin add` from inside it — they are listed in `src/elements.ts` and `src/declarations.ts`, which the package
|
|
53
|
+
publishes from. A package's element is authored as a TYPE of its own: `defineElement<SeatPickerAttributes>(declaration)`.
|
|
54
|
+
|
|
55
|
+
## Building and shipping (`plugin pack`, `plugin upload`)
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
plitzi plugin pack # in a plugin package: every element
|
|
59
|
+
plitzi plugin pack src/plugins/SeatPicker # an element of a project; several folders → one plugin, the first its main
|
|
60
|
+
plitzi plugin upload # the zip pack left, onto the space whoami names, installed there
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`pack` writes one ES module (React and the SDK kept out — the page provides them), `plugin-manifest.json` from the
|
|
64
|
+
declarations with integrity hashes, and the zip the builder takes under Resources. `upload` checks the manifest,
|
|
65
|
+
sends the zip to one of the space's CDNs (`--cdn`) and installs it — a plugin already there moves to the new version with
|
|
66
|
+
its settings kept. `--plugin-version` sets the version the manifest carries. The plugin's source — every file it
|
|
67
|
+
imports, followed from its entry — is kept beside it on the space (`runtime push` does the same for a runtime), which
|
|
68
|
+
is what `create --from` brings back; `plitzi source pack` writes what would be kept to a file, to look at.
|
|
69
|
+
|
|
70
|
+
A self-hosted page server does not need `pack`: it compiles a plugin from its source (`action: 'compile'`).
|
|
71
|
+
|
|
72
|
+
The same server decides its own say over the space's **feature flags**: `createServer({ flags: { newCheckout: true } })`
|
|
73
|
+
(or a function of `{ spaceId, environment }` when it serves several). It overrides what the space declares — only for
|
|
74
|
+
flags the space declares — and is overridden by the SDK's `flags` prop and a tester's dev tools. Declaring the flags
|
|
75
|
+
themselves is the space's (`flags` in the spec; see the authoring skill's feature flags).
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Projects
|
|
2
|
+
|
|
3
|
+
## `create`
|
|
4
|
+
|
|
5
|
+
| | `--source local` | `--source cloud` |
|
|
6
|
+
| --- | --- | --- |
|
|
7
|
+
| `--mode server` | A page server of your own, rendering the space in `src/space/`. No account | Your page server, rendering the live space from Plitzi (secret self-hosting key in `.env`) |
|
|
8
|
+
| `--mode client` | Vite + the SDK in the browser, no server, no account | The SDK fetches the space with the public render key |
|
|
9
|
+
|
|
10
|
+
What a project gives you, so you use it rather than rebuild it:
|
|
11
|
+
|
|
12
|
+
| Script | What it is for |
|
|
13
|
+
| --- | --- |
|
|
14
|
+
| `start` | serve it — in client mode Vite, which hot-replaces on save. The server prints only what goes wrong; `-- --verbose` adds every request |
|
|
15
|
+
| `start:dev` | server mode: restarted on a save to its code; a plugin is swapped in the open page. Options in `src/config/serverOptions.ts`, actions in `src/actions/`; `plitzi/` is the CLI's, never edit it |
|
|
16
|
+
| `author` | author `src/space/`: every problem at once (file:line, what to change), then the suggestions (`[suggest]`: a shorter way to the same page, the most elements saved first); `-- --json` for a tool |
|
|
17
|
+
| `lint:space` | how `src/space/` is written, at file:line, and authoring's suggestions; `-- --max-warnings 0`. On purpose: `// plitzi-lint-disable-next-line <code> -- why` (a suggestion: `quiet` on its element) |
|
|
18
|
+
| `npx plitzi space fix` | what `author` reports that has one fix, as a diff of your source; `--write` writes it, formatted, and keeps it only if the space then authors with it gone and nothing new |
|
|
19
|
+
| `npx plitzi element where <id\|class\|words>` | where the code writes an element: file:line and the call — edit it there, not the files around it. `npx plitzi element edit <id> --set content="…"` writes an attribute in it, `remove <id>` takes it out, `move <id> --before <id>` reorders it — each checked |
|
|
20
|
+
| `check -- /path --width 1440,390` | whether a page is whole, in text: elements on screen, overflow, console, refused requests, failed flows, a binding its data lacks; `--state`, `--element <id>`: what it holds; `--ssr`: SSR misses; `--as <user>`; `--json` |
|
|
21
|
+
| `npx plitzi page import <url>` | a page the user owns, as a start: tokens, its blocks' layout, lists as `data/*.json` — never the words. **Only when the user asks**; a site not on this machine needs `--account`: ask first |
|
|
22
|
+
| `shot -- /path --width 390 --scheme dark` | a picture of one page — `--clip <element>` one element, `--frames 4` what moves, `--compare <url>` what differs from another site |
|
|
23
|
+
| `visual` | a browser asserts every element the space names is visible |
|
|
24
|
+
| `typecheck`, `lint`, `format` | before calling a change done |
|
|
25
|
+
|
|
26
|
+
**Which port.** `start` takes 8080, or the next free one — printed, and written to `tmp/dev-server.json` for `check`,
|
|
27
|
+
`shot` and `visual`. `PORT` chooses one (a taken one is then an error). `/health` answers with the space's name.
|
|
28
|
+
|
|
29
|
+
Data with no backend, server mode: `src/data/*.json`, never served — a provider with `runtime: 'server'` and `query:
|
|
30
|
+
'/data/x.json'` reads it on the server. Client mode: `public/data/`, fetched — public. Learn a file's fields with
|
|
31
|
+
`data describe`, never by reading it.
|
|
32
|
+
|
|
33
|
+
**`public/` is on the internet**: never a secret there. `tmp/`, `state/` (its `kv`) ignored; `.plitzi/` committed.
|
|
34
|
+
`--dry-run` on a command that writes or sends says what it would do, and does none of it.
|
|
35
|
+
|
|
36
|
+
A local space starts as a tour of the platform with a plugin of the project's own; **`--template blank`** as tokens, a
|
|
37
|
+
layout and one empty page — for a project about to be a specific site; **`--template catalog`** as a small shop
|
|
38
|
+
(layout, card component, data in `src/data`, a filtered list, a page per product), a file per part — the one to read
|
|
39
|
+
when unsure how a whole site is put together.
|
|
40
|
+
|
|
41
|
+
The space itself is written with `@plitzi/sdk-authoring` — see the `plitzi-authoring` skill, which `create` copies into
|
|
42
|
+
`.claude/skills/` beside this one.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# When something does not work
|
|
2
|
+
|
|
3
|
+
| What you see | What it is |
|
|
4
|
+
| --- | --- |
|
|
5
|
+
| `create` printed questions and wrote nothing | nobody answered the three choices — ask the user, pass them as flags |
|
|
6
|
+
| `start` says the port is in use | `PORT` is set to a taken port — unset it to take the next free one, or choose another |
|
|
7
|
+
| A page that is not this project's, or `page shot` refuses the port | another server answers there — `curl 127.0.0.1:<port>/health` names it; `tmp/dev-server.json` has this project's port |
|
|
8
|
+
| "Custom Component … Not Found", or a flow on a plugin's event never runs | `doctor` names the folder whose type or declaration is off |
|
|
9
|
+
| "not laid out as Plitzi reads it" | each misplaced part, with its fix; `doctor --fix` |
|
|
10
|
+
| `upload` opens a browser | there is no session, or no space chosen — the person completes it there |
|
|
11
|
+
| The upload went to the wrong space | `plitzi space use` chooses another; check `whoami` first |
|
|
12
|
+
| `space pull` wrote nothing and named files | they changed here and on the space — set your changes aside and pull again, or `--force` |
|