tileflow 0.1.0-alpha.18 → 0.1.0-alpha.19
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 +5 -29
- package/package.json +9 -10
- package/docs/agent-icon-composition.md +0 -68
- package/docs/build-artifacts.md +0 -40
- package/docs/cli-setup-and-defaults.md +0 -56
- package/docs/command-families.md +0 -36
- package/docs/coordinates.md +0 -68
- package/docs/deterministic-agent-diagnostics.md +0 -47
- package/docs/hosted-authentication-and-deploy.md +0 -237
- package/docs/inspect-vector-features.md +0 -19
- package/docs/local-visual-feedback.md +0 -268
- package/docs/map-authoring.md +0 -132
- package/docs/native-artifacts.md +0 -174
- package/docs/read-only-icon-comparison.md +0 -81
- package/docs/team-3d-models.md +0 -36
- package/docs/team-icon-sets.md +0 -130
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
# Hosted authentication and deploy
|
|
2
|
-
|
|
3
|
-
Start with the [tileflow guide](https://github.com/tileflow/tileflow-sdk/blob/main/packages/cli/README.md) for installation and a complete first example.
|
|
4
|
-
|
|
5
|
-
Hosted writes have two independent authorization paths:
|
|
6
|
-
|
|
7
|
-
- Personal developer session: run `npx tileflow login` once for a
|
|
8
|
-
Tileflow API origin. Login authenticates the account and selects no Map.
|
|
9
|
-
Map commands exchange it for a brief Map capability; tileset commands use a separate Team data
|
|
10
|
-
capability.
|
|
11
|
-
- CI key: create a dashboard `CI deploy` key, store it as
|
|
12
|
-
`TILEFLOW_API_KEY`, and let the repository workflow deploy without a local login. The server
|
|
13
|
-
binds that key to exactly one Map.
|
|
14
|
-
|
|
15
|
-
Hosted control-plane requests stay pinned to the configured HTTP(S) origin, apply a hard bounded
|
|
16
|
-
timeout, and stream at most 1 MiB of response data. CLI diagnostics never echo an untrusted remote
|
|
17
|
-
response body or bearer credential.
|
|
18
|
-
|
|
19
|
-
Inspect the account, then target the Map shown in the dashboard:
|
|
20
|
-
|
|
21
|
-
```sh
|
|
22
|
-
npx tileflow whoami --json
|
|
23
|
-
npx tileflow deploy --map-id map_AbCdEfGhIjKlMnOp
|
|
24
|
-
npx tileflow status --map-id map_AbCdEfGhIjKlMnOp
|
|
25
|
-
npx tileflow logout
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
Changing or resetting the hosted account password revokes saved personal CLI sessions. The next
|
|
29
|
-
account or hosted command stops with a clear message and asks you to run `tileflow login` again.
|
|
30
|
-
Project API and CI keys are independent project credentials and are not removed by a personal
|
|
31
|
-
password change.
|
|
32
|
-
|
|
33
|
-
## Create the Map from the terminal
|
|
34
|
-
|
|
35
|
-
After `tileflow login`, the CLI can create the Map itself; nothing has to be copied from the
|
|
36
|
-
dashboard. Run `deploy` without `--map-id`, or create the Map first with `maps create`:
|
|
37
|
-
|
|
38
|
-
```sh
|
|
39
|
-
npx tileflow login
|
|
40
|
-
npx tileflow deploy --origin https://www.example.com
|
|
41
|
-
npx tileflow maps create --any-website --json
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
The new Map belongs to a Team you administer. When you administer exactly one Team that can add a
|
|
45
|
-
Map, the CLI uses it; when several can, it asks, or takes `--team @team`; when none can, it stops
|
|
46
|
-
and says why (no administered Team, or every Team has reached its Map limit).
|
|
47
|
-
|
|
48
|
-
Browser access is always an explicit choice: `--origin` with an exact website origin such as
|
|
49
|
-
`https://www.example.com` (repeat it for up to 20 sites), or `--any-website`. Paths, wildcards and
|
|
50
|
-
bare host names are rejected. On a terminal the CLI asks; without one (for example when an agent
|
|
51
|
-
runs it), a missing choice stops before anything is created and names the flags. Browser access
|
|
52
|
-
is stored with the Map in Tileflow and can be changed in the dashboard; it is never written to the
|
|
53
|
-
repository.
|
|
54
|
-
|
|
55
|
-
`deploy` creates the Map only after the local config, assets and styles pass, then publishes to it
|
|
56
|
-
in the same run and prints `tileflow deploy --map-id <mapId>` for later deploys. If the manifest
|
|
57
|
-
already records a Map for that repository map, `deploy` stops and shows that command instead of
|
|
58
|
-
creating another Map. Each creation prints a setup key; rerunning an interrupted command with
|
|
59
|
-
`--setup-key <key>` returns the same Map instead of a second one.
|
|
60
|
-
|
|
61
|
-
Map creation uses only the personal session. With `TILEFLOW_API_KEY`, `--api-key`, `--with-native`,
|
|
62
|
-
or in CI, `deploy` requires `--map-id`.
|
|
63
|
-
|
|
64
|
-
## Deploy to an existing Map
|
|
65
|
-
|
|
66
|
-
A Map created in the dashboard, or by an earlier CLI run, is deployed with its exact Map ID. If the
|
|
67
|
-
config contains several maps, select the authored map explicitly:
|
|
68
|
-
|
|
69
|
-
```sh
|
|
70
|
-
npx tileflow deploy \
|
|
71
|
-
--map-id map_AbCdEfGhIjKlMnOp \
|
|
72
|
-
--map store-locator
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
The Map ID is a public destination, not a credential. A successful server-confirmed deploy keeps
|
|
76
|
-
unrelated manifest entries and records that Map's stable ID, hosted theme URLs, World `v1`
|
|
77
|
-
generation, and fixed session usage mode. Browser access remains server-owned and is never read
|
|
78
|
-
from or written to repository configuration. Do not add an API key or payment authority to a copied
|
|
79
|
-
prompt.
|
|
80
|
-
|
|
81
|
-
Team tileset commands exchange the same account session for a separate Team-scoped data capability;
|
|
82
|
-
it carries no Map authority. Inspect and preview remain account-free:
|
|
83
|
-
|
|
84
|
-
```sh
|
|
85
|
-
npx tileflow tileset inspect ./data/stores.pmtiles --json
|
|
86
|
-
npx tileflow tileset inspect ./data/stores.pmtiles \
|
|
87
|
-
--include-values category,status --json
|
|
88
|
-
npx tileflow tileset publish ./data/stores.pmtiles \
|
|
89
|
-
--id stores --team @acme --attribution 'Store data © Example' --json
|
|
90
|
-
npx tileflow tileset list --team @acme --json
|
|
91
|
-
npx tileflow tileset status stores --team @acme --json
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
Inspection schema 1 separates authoritative PMTiles/TileJSON declarations from bounded MVT
|
|
95
|
-
observations. Sampled fields report present/missing feature counts, observed distinct-value counts,
|
|
96
|
-
numeric min/max, and truncation. Raw primitive values remain absent unless `--include-values`
|
|
97
|
-
explicitly selects their comma-separated field names; the command emits at most 16 values per field,
|
|
98
|
-
32 selected fields, and 256 characters per string. `--no-sample` returns only authoritative metadata
|
|
99
|
-
and cannot be combined with value inspection. Directory traversal recomputes addressed-tile and
|
|
100
|
-
tile-entry counts; the header's tile-content count is reported only as a nullable declaration and is
|
|
101
|
-
not treated as authority.
|
|
102
|
-
|
|
103
|
-
`publish --id` names a Team-local logical resource; Tileflow owns its opaque delivery ID. The
|
|
104
|
-
command validates the archive locally before authentication, hashes it in fixed 16 MiB parts, then
|
|
105
|
-
uploads at most four parts concurrently without buffering the complete file. Interrupted sessions
|
|
106
|
-
remain resumable for 24 hours: rerunning the same command reconciles server receipts and transfers
|
|
107
|
-
only missing parts. Normal Queue initialization is polled for at most two minutes before the command
|
|
108
|
-
returns a resumable availability error. Retryable transfer failures receive fresh short-lived authorization; a changed
|
|
109
|
-
local file stops before completion. Free accepts versions through exactly 2,000,000,000 bytes and
|
|
110
|
-
Starter through exactly 4,000,000,000 bytes, subject to the Team's hosted-storage capacity.
|
|
111
|
-
|
|
112
|
-
Publication completes only after server-side integrity and PMTiles validation. A compatible new
|
|
113
|
-
version becomes current at the same stable TileJSON and tile URLs, so newly resolved browser
|
|
114
|
-
requests see it without creating a Map deployment. Purge requires `--confirm <exact-id>` and fails
|
|
115
|
-
with bounded dependency context while any retained Map deployment uses the resource. Automation may set a Team data
|
|
116
|
-
`TILEFLOW_API_KEY`; that key selects its Team, so commands omit `--team` and never load account
|
|
117
|
-
state.
|
|
118
|
-
|
|
119
|
-
`tileset publish --json` emits schema version 2 with the Team selector when known, logical and
|
|
120
|
-
opaque tileset identities, immutable version ID and number, exact byte count, content-hash
|
|
121
|
-
algorithm/hash, final state, and `changed` or `unchanged` publication result. It never emits the
|
|
122
|
-
local path, upload session, storage key, signed URL, ETag, credential, or retry details.
|
|
123
|
-
|
|
124
|
-
An explicit key or `TILEFLOW_API_KEY` never uses the saved account session. The deploy API rejects a
|
|
125
|
-
`--map-id` that does not match the key. Read-only hosted icon comparison validates the same binding
|
|
126
|
-
before loading its baseline.
|
|
127
|
-
|
|
128
|
-
A deploy-only key grants `styles:write` and `status:read`. Without additional permissions it cannot upload
|
|
129
|
-
datasets or render images. Give it an expiration, rotate the repository secret
|
|
130
|
-
before it expires, and avoid non-expiring CI keys.
|
|
131
|
-
|
|
132
|
-
Detected CI never falls back to the credential saved by `tileflow login`: if
|
|
133
|
-
`TILEFLOW_API_KEY` is absent, deploy stops before loading config or making a
|
|
134
|
-
request. Once captured, the key is hidden from `process.env` and `--api-key` is removed from the
|
|
135
|
-
temporary `process.argv` view before the CLI imports executable `tileflow.config.ts`; both process
|
|
136
|
-
surfaces are restored after the protected operation. Every config-aware command uses the same
|
|
137
|
-
scope, including validate, build, dev/watch, capture, visual, inspect, icon inspection, and deploy.
|
|
138
|
-
This is defense in depth, not a sandbox; deploy only reviewed repository code on a trusted runner,
|
|
139
|
-
and do not pass keys through the `--api-key` command line in CI.
|
|
140
|
-
|
|
141
|
-
The [deploy documentation](https://tileflow.dev/docs/deploy) contains copyable
|
|
142
|
-
GitHub Actions and GitLab CI workflows. Both use `npm ci`, the committed
|
|
143
|
-
lockfile, and the repository-local CLI. GitHub exposes the key only to its deploy
|
|
144
|
-
step. GitLab variables are job-scoped, so its example validates in a keyless job
|
|
145
|
-
and deploys in a protected `production` job; the locked install and runner are
|
|
146
|
-
part of that trusted job boundary. Both serialize publications and intentionally
|
|
147
|
-
omit path filters because `tileflow.config.ts` can import arbitrary repository
|
|
148
|
-
files.
|
|
149
|
-
|
|
150
|
-
The CLI records bounded private provenance for GitHub Actions, GitLab CI,
|
|
151
|
-
generic CI, and local runs. These provider fields are descriptive client
|
|
152
|
-
reports, not OIDC attestations. Provider values can be overridden with:
|
|
153
|
-
|
|
154
|
-
```txt
|
|
155
|
-
TILEFLOW_DEPLOY_REPOSITORY
|
|
156
|
-
TILEFLOW_DEPLOY_REVISION
|
|
157
|
-
TILEFLOW_DEPLOY_REF
|
|
158
|
-
TILEFLOW_DEPLOY_RUN_ID
|
|
159
|
-
TILEFLOW_DEPLOY_RUN_URL
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
Invalid explicit values fail before a network write. Provider metadata that is
|
|
163
|
-
missing, malformed, or too long is omitted. Secrets and the complete
|
|
164
|
-
environment are never logged.
|
|
165
|
-
|
|
166
|
-
A separate app-build step is absent from the minimal workflows. Self-hosted build and deploy emit the same
|
|
167
|
-
runtime manifest version 1 shape; Hosted fields are optional identity metadata on its map/theme
|
|
168
|
-
entries. Filesystem build writers refuse to replace a manifest carrying Hosted metadata by default,
|
|
169
|
-
and deploy refuses to replace a purely local manifest. Prefer `emitBuildArtifacts: false` or
|
|
170
|
-
separate output paths when the app deliberately packages a deploy manifest. The explicit
|
|
171
|
-
`overwriteHostedManifest: true` build option and
|
|
172
|
-
`tileflow deploy --overwrite-self-hosted-manifest` flag authorize that destination replacement. A
|
|
173
|
-
retry of the same compiled theme family reuses its deployment version and prints `Unchanged`;
|
|
174
|
-
changed cartography prints `Published` with a new version. Allowed websites is managed separately
|
|
175
|
-
in Tileflow and is never read from repository config. The
|
|
176
|
-
fingerprint binds resource references, not the changing bytes behind referenced
|
|
177
|
-
glyph or sprite URLs. Every theme of one logical map publishes atomically; separate maps can still
|
|
178
|
-
partially succeed when no remote batch release is used.
|
|
179
|
-
|
|
180
|
-
All config, theme-style, icon, and compatibility preflight happens before the first style write. After
|
|
181
|
-
that boundary the current Hosted API has no batch commit across repository-internal orchestration:
|
|
182
|
-
one singular config can publish before a later config fails. The orchestrator then leaves the
|
|
183
|
-
previous local manifest untouched, reports which publications succeeded, and tells the operator to
|
|
184
|
-
retry; idempotent publication converges on that retry. The local manifest
|
|
185
|
-
writer uses a durable same-directory temporary followed by direct rename and directory sync, so
|
|
186
|
-
readers see either the previous or next complete manifest. Multi-file artifact writers remain
|
|
187
|
-
rollback-capable sets. Neither mechanism is a remote transaction or can make several API writes
|
|
188
|
-
all-or-none.
|
|
189
|
-
|
|
190
|
-
Deploy treats the locally compiled MapLibre Style family as one logical-map artifact. The request
|
|
191
|
-
contains an exact `styles[theme]` collection, per-theme canonical SHA-256 identities in the build
|
|
192
|
-
manifest, only bounded hosting policy that does not belong in MapLibre itself, and the exact managed
|
|
193
|
-
icon-package identity when the family has one. Delivery
|
|
194
|
-
policy is not inherited with cartographic fields. Deploy does not serialize the module
|
|
195
|
-
configuration, send a public `tileset` selector, or ask the hosted API to compile the map again.
|
|
196
|
-
Hosted publication currently requires Tileflow World; `vectorTiles()` remains available for local
|
|
197
|
-
builds and previews but fails deploy before any remote write. The API binds recognized
|
|
198
|
-
Tileflow-owned world and terrain URLs to its generated map ID. A successful response must return
|
|
199
|
-
exactly the submitted theme names and a hosted Style URL for each. Deploy writes strict runtime
|
|
200
|
-
manifest version 1 with stable theme URLs, `colorScheme`, content revision, optional font faces and
|
|
201
|
-
style IDs, rather than duplicating dataset configuration. No older manifest is normalized.
|
|
202
|
-
|
|
203
|
-
For a map with `icons: ['./icons']`, hosted validation compiles the local SVG/PNG/JPEG/WebP files
|
|
204
|
-
without a key. Ordered directories apply left to right and later exact IDs replace earlier files.
|
|
205
|
-
Deploy uploads the four generated sprite files before its first style write and reuses
|
|
206
|
-
byte-identical packages by content hash. Source icons and absolute paths remain local; generated
|
|
207
|
-
atlas bytes and sorted icon names are public. Each hosted package is limited to 1,000 icons and 8 MiB
|
|
208
|
-
generated bytes as a processing envelope. Large artwork may reach the 2,048-pixel atlas bound before
|
|
209
|
-
the icon count. There is no package-count quota; physically retained
|
|
210
|
-
generated packages share the organization's 5/10-GB hosted-storage pool with retained PMTiles,
|
|
211
|
-
remain protected by deployment/library references, and otherwise enter the technical orphan grace
|
|
212
|
-
before deletion. Upload success must confirm the submitted `contentHash`, exact icon count, exact
|
|
213
|
-
generated byte total, one opaque `icp_<id>`, and the corresponding query-free
|
|
214
|
-
`/sprites/<id>/sprite` URL. The CLI rejects any missing or divergent field before using that URL.
|
|
215
|
-
|
|
216
|
-
Hosted deploy currently rejects local or package-owned web fonts before authentication or remote
|
|
217
|
-
writes. Use self-hosted delivery or an explicit public glyph provider. Enabling managed font bundles
|
|
218
|
-
requires a separately deployed ownership, quota, retention, and immutable-delivery contract.
|
|
219
|
-
|
|
220
|
-
A map's own 3D building models (the building models of its `models` directories) are its Team's
|
|
221
|
-
3D models, which `tileflow models publish` publishes by name. Deploy uploads no model files: it
|
|
222
|
-
compiles each placement's `url` as the placeholder `tileflow://team-models/<name>`, leaves the
|
|
223
|
-
building models out of the build's assets and model source identities, so the map's revision binds
|
|
224
|
-
their names and not their bytes, and sends `teamModelSources`, the SHA-256 and size of each glTF
|
|
225
|
-
binary a model was prepared from. Hosted replaces each placeholder with the model's address in the
|
|
226
|
-
map's Team, which follows the model's current version, and fails the deploy for a model the Team has
|
|
227
|
-
not published. The response's `teamModels` names each placed model's current version and whether it
|
|
228
|
-
was prepared from the same files (`match`, `differ` or `unknown`); the CLI warns on `differ`. A
|
|
229
|
-
deploy with `--with-native` rejects a map's own building models, because MapLibre Native draws no
|
|
230
|
-
models.
|
|
231
|
-
|
|
232
|
-
For every managed resource kind, `assetSetSha256` remains a separate per-map output identity. It
|
|
233
|
-
hashes each generated file's exact portable name, media type, byte count, and SHA-256 using Core's
|
|
234
|
-
asset-set v1 contract; it does not hash only the icon-package manifest. Hosted must
|
|
235
|
-
confirm the immutable resource bytes, reconstruct those same per-file identities (including the
|
|
236
|
-
`icons/<mapId>/` and `models/<mapId>/` prefixes), and reject the Style when the submitted
|
|
237
|
-
build-manifest hash diverges.
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
# Inspect vector features
|
|
2
|
-
|
|
3
|
-
Start with the [tileflow guide](https://github.com/tileflow/tileflow-sdk/blob/main/packages/cli/README.md) for installation and a complete first example.
|
|
4
|
-
|
|
5
|
-
See which bounded source features the exported map sees near a camera before tuning taxonomy,
|
|
6
|
-
density, or labels:
|
|
7
|
-
|
|
8
|
-
```sh
|
|
9
|
-
npx tileflow inspect features \
|
|
10
|
-
--center=-3.6927512,40.4086555 --zoom=16 \
|
|
11
|
-
--layers=poi --properties=name,category,type,icon,filter_rank,size_rank --json
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
The command supports HTTP(S) TileJSON/vector sources and returns only requested properties plus
|
|
15
|
-
geometry summaries in stable order. Viewport, tiles, bytes, scanned/returned features, names, and
|
|
16
|
-
timeouts are bounded. Safe provenance includes origins, a query-free TileJSON path, and configured
|
|
17
|
-
source revision or `null`; credentials, URL queries, hidden properties, response bodies, and
|
|
18
|
-
absolute paths are omitted. It is read-only apart from executable config's own possible side
|
|
19
|
-
effects and removes `TILEFLOW_API_KEY` before loading config.
|
|
@@ -1,268 +0,0 @@
|
|
|
1
|
-
# Local visual feedback
|
|
2
|
-
|
|
3
|
-
Start with the [tileflow guide](https://github.com/tileflow/tileflow-sdk/blob/main/packages/cli/README.md) for installation and a complete first example.
|
|
4
|
-
|
|
5
|
-
Explore with capture itself. The first run may install Playwright's exact pinned Chromium headless
|
|
6
|
-
shell into its versioned per-user cache:
|
|
7
|
-
|
|
8
|
-
```sh
|
|
9
|
-
npx tileflow capture \
|
|
10
|
-
--map madrid \
|
|
11
|
-
--theme dark \
|
|
12
|
-
--center=-3.69201,40.40871 \
|
|
13
|
-
--zoom=16.15 \
|
|
14
|
-
--width=1200 \
|
|
15
|
-
--height=1200 \
|
|
16
|
-
--json
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
The successful entry includes a normalized `definition` with its concrete `theme`, `camera`,
|
|
20
|
-
`viewport`, and default map `target`. Copy it under a chosen `scenes.<name>` key; the CLI never rewrites
|
|
21
|
-
executable TypeScript config. Then commit the bounded scene so agents and CI render the same map,
|
|
22
|
-
camera, and viewport:
|
|
23
|
-
|
|
24
|
-
```ts
|
|
25
|
-
import {defineMap} from '@tileflow/core';
|
|
26
|
-
import {streets} from '@tileflow/maps';
|
|
27
|
-
|
|
28
|
-
export default defineMap({
|
|
29
|
-
id: 'madrid',
|
|
30
|
-
name: 'Madrid',
|
|
31
|
-
version: 1,
|
|
32
|
-
extends: streets,
|
|
33
|
-
scenes: {
|
|
34
|
-
'madrid-desktop': {
|
|
35
|
-
theme: 'dark',
|
|
36
|
-
camera: {type: 'center', center: [-3.7038, 40.4168], zoom: 12},
|
|
37
|
-
viewport: {width: 1280, height: 800, dpr: 1},
|
|
38
|
-
},
|
|
39
|
-
'madrid-product': {
|
|
40
|
-
theme: 'dark',
|
|
41
|
-
camera: {type: 'center', center: [-3.7038, 40.4168], zoom: 12},
|
|
42
|
-
viewport: {width: 390, height: 844, dpr: 2},
|
|
43
|
-
target: {
|
|
44
|
-
kind: 'application',
|
|
45
|
-
path: '/maps/madrid',
|
|
46
|
-
captureId: 'product-map',
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
});
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
`scenes` is tooling metadata owned by this map. It is not inherited and does not enter the
|
|
54
|
-
cartographic compiler; tooling supplies the exported map ID when it normalizes a scene internally.
|
|
55
|
-
Every scene stores a concrete theme; omission and browser-only `system` are invalid.
|
|
56
|
-
|
|
57
|
-
### Live comparison in Inspector
|
|
58
|
-
|
|
59
|
-
Use the ordinary preview server with a right-hand selection to compare two maps or themes while
|
|
60
|
-
authoring:
|
|
61
|
-
|
|
62
|
-
```sh
|
|
63
|
-
# Two maps or themes from one config.
|
|
64
|
-
npx tileflow preview \
|
|
65
|
-
--map baedeker --theme light \
|
|
66
|
-
--against-map map-1777 --against-theme light
|
|
67
|
-
|
|
68
|
-
# Or compare against another config.
|
|
69
|
-
npx tileflow preview \
|
|
70
|
-
--config ./candidate.config.ts --map candidate \
|
|
71
|
-
--against-config ./reference.config.ts --against-map reference
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
Any `--against-*` option opens Inspector in comparison mode. Both previews remain same-origin and share
|
|
75
|
-
one synchronized camera. The toolbar switches between side-by-side, split, opacity overlay, and
|
|
76
|
-
blink modes; the selected mode, camera, split, opacity, and active interaction side survive in the
|
|
77
|
-
URL. Each config has its own watched, last-known-good session, so an invalid edit shows bounded
|
|
78
|
-
diagnostics without discarding the last valid map and recovers automatically after a fix.
|
|
79
|
-
|
|
80
|
-
Enable **Inspect** and click a rendered feature to see its bounded feature data, paint/layout values,
|
|
81
|
-
zoom-curve samples, and compiler contribution sidecar. The sprite gallery shows the compiled atlas,
|
|
82
|
-
not source directories. **Copy scene** produces a concrete-theme scene for the current camera and
|
|
83
|
-
viewport; **Copy command** produces the corresponding capture command. The inspector sidecar exists
|
|
84
|
-
only in memory in the local Inspector session and is not emitted by `tileflow build`.
|
|
85
|
-
|
|
86
|
-
### Reproducible two-style review
|
|
87
|
-
|
|
88
|
-
For shareable evidence with exact pixels, use headless capture instead of the live preview:
|
|
89
|
-
|
|
90
|
-
```sh
|
|
91
|
-
npx tileflow visual compare \
|
|
92
|
-
--config ./candidate.config.ts --map candidate --theme light \
|
|
93
|
-
--against-config ./reference.config.ts --against-map reference --against-theme light \
|
|
94
|
-
--center=-3.7038,40.4168 --zooms=12,14,16 \
|
|
95
|
-
--width=1200 --height=800 --dpr=1 --region=0,0,1200,760 \
|
|
96
|
-
--diff --open --json
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
`--against-config` is explicit and may name the same config. Both sides use one camera, viewport,
|
|
100
|
-
DPR, ordered zoom matrix, pinned browser session, and concrete theme. At most 16 zooms and 64 MiB
|
|
101
|
-
of aggregate embedded PNG data are accepted; an earlier preflight also caps the matrix at
|
|
102
|
-
67,108,864 aggregate physical pixels. The default transaction writes
|
|
103
|
-
`.tileflow/comparisons/compare.html`, a machine-readable sibling JSON document, and PNG/receipt-v4
|
|
104
|
-
pairs below `compare.assets`; `--diff` adds a highlighted diff when identities are comparable. The
|
|
105
|
-
HTML embeds every image, uses a restrictive CSP, performs no network request, and offers the same
|
|
106
|
-
side-by-side, wipe, overlay, and blink review modes.
|
|
107
|
-
|
|
108
|
-
`--region=x,y,width,height` selects one shared physical-pixel rectangle for compact appearance
|
|
109
|
-
profiles. Review JSON uses the explicit signed direction `rightMinusLeft`; the region does not crop
|
|
110
|
-
captures, changed-pixel metrics, or diffs.
|
|
111
|
-
|
|
112
|
-
Stdout and the sibling JSON use the same schema-version-1 `visual.compare` document: concrete
|
|
113
|
-
left/right selections, shared camera and viewport, zoom-sorted rows with Review v1 documents and
|
|
114
|
-
relative artifact paths, report/document paths, and sorted warnings. This document and the watch
|
|
115
|
-
NDJSON described below are versioned compatibility boundaries.
|
|
116
|
-
|
|
117
|
-
The asset directory also contains a bounded schema-version-1
|
|
118
|
-
`.tileflow-visual-compare.json` inventory. It assigns ownership only to the listed sibling assets
|
|
119
|
-
and records each exact SHA-256. A later successful transaction removes stale generated rows or
|
|
120
|
-
diffs only when that valid prior inventory names them, preserves unrelated files, and refuses a
|
|
121
|
-
managed asset that has been modified, replaced by a symlink/non-file, or grown beyond its bound.
|
|
122
|
-
`--force` does not weaken those ownership checks. The inventory is capped at 64 KiB and the complete
|
|
123
|
-
report, JSON, inventory, PNGs, receipts, stale cleanup, and optional diffs commit or roll back as one
|
|
124
|
-
file transaction.
|
|
125
|
-
|
|
126
|
-
Different pixels are ordinary review evidence and exit 0. A frame, dimension, runtime, or exact
|
|
127
|
-
data mismatch exits 1 and suppresses pixel metrics because the images are not comparable.
|
|
128
|
-
`--allow-data-mismatch` keeps a data-mismatch report inspectable with exit 0, but does not invent
|
|
129
|
-
pixel metrics. `--watch` observes both configs, cancels stale renders, preserves the last complete
|
|
130
|
-
report through invalid edits, and emits deterministic NDJSON with `--json`. An explicit report path
|
|
131
|
-
requires `--force` in watch mode; the managed default path is safely replaceable.
|
|
132
|
-
|
|
133
|
-
Watch events are `watching`, `building`, `invalid`, `recovered`, `generation-complete`, `failed`,
|
|
134
|
-
and `stopped`, with monotonic comparison generations and source-side generations where applicable.
|
|
135
|
-
Without `--allow-data-mismatch`, an incompatible generation emits `failed`, does not replace the
|
|
136
|
-
last complete report, and remains an unresolved failure; an allowed data mismatch emits
|
|
137
|
-
`generation-complete` but still has no pixel metrics. An orderly stop exits 0 only after at least
|
|
138
|
-
one complete generation and no unresolved invalid or failed state; otherwise it exits 1.
|
|
139
|
-
|
|
140
|
-
Render one checkpoint, or recapture after every edit:
|
|
141
|
-
|
|
142
|
-
```sh
|
|
143
|
-
npx tileflow capture madrid-desktop --json
|
|
144
|
-
npx tileflow capture --all --json
|
|
145
|
-
npx tileflow capture madrid-desktop --watch --json
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
Use the first command when you want a single image and the last command while refining a map. Watch
|
|
149
|
-
mode stays open, follows changes to the config, its local imports, and its effective icons and fonts,
|
|
150
|
-
and writes a new PNG after each valid edit. Keeping the browser ready makes repeated renders faster.
|
|
151
|
-
If an edit is invalid, the last good image remains in place and capture resumes automatically after
|
|
152
|
-
the fix. Stop watch mode with `Ctrl+C`. It accepts named committed scenes or `--all`, not exploratory
|
|
153
|
-
camera options.
|
|
154
|
-
|
|
155
|
-
Standalone scenes need no app server, account, API key, MCP service, system Chrome, or visible
|
|
156
|
-
window. The first command—or the first capture—may provision Playwright's pinned Chromium headless
|
|
157
|
-
shell in its versioned per-user cache. `--no-browser-install` makes a prepared/offline environment
|
|
158
|
-
strict. Tileflow never falls back to a system browser or packages the browser in npm.
|
|
159
|
-
|
|
160
|
-
For prepared or offline CI, install ahead of time with
|
|
161
|
-
`npx tileflow setup capture --json`. Use `setup capture --no-browser-install` or
|
|
162
|
-
`capture --no-browser-install` as an enforcement check that the exact shell is already cached.
|
|
163
|
-
|
|
164
|
-
For an application scene, its route and component props must render the committed camera. Tileflow
|
|
165
|
-
uses the camera in scene identity but does not mutate arbitrary application map state.
|
|
166
|
-
|
|
167
|
-
One-shot success JSON is one deterministic schema-version-1 document plus one newline. It contains
|
|
168
|
-
sorted scene/map/theme/target entries, relative output and receipt paths, image hash/dimensions/DPR,
|
|
169
|
-
renderer identity, remote-dependency state, and warnings; it contains no image bytes, credential,
|
|
170
|
-
origin, absolute path, user, or timestamp. Managed output is an atomic pair under
|
|
171
|
-
`.tileflow/captures/<scene>.png` and `<scene>.receipt.json`. `tileflow init` ignores managed captures
|
|
172
|
-
and `.tileflow/diffs` when creating a new `.gitignore`. Explicit output replacement requires
|
|
173
|
-
`--force`; symlinks and path escapes fail closed.
|
|
174
|
-
|
|
175
|
-
Each written receipt uses capture schema v4 and records the concrete theme. A Tileflow World
|
|
176
|
-
capture resolves its TileJSON once for
|
|
177
|
-
the whole capture session and records the exact `world-v1` release plus descriptor, archive, data
|
|
178
|
-
contract, and product-contract hashes. All selected scenes and retries therefore use one immutable
|
|
179
|
-
World release even if `current` moves while the command is running.
|
|
180
|
-
|
|
181
|
-
One-shot `--json` failures leave stdout empty and write exactly one deterministic failure document
|
|
182
|
-
to stderr with `code`, `phase`, bounded diagnostics, and optional origin-only resource metadata.
|
|
183
|
-
|
|
184
|
-
Watch JSON is NDJSON with monotonic `building`, `invalid`, `recovered`, `captured`, `failed`, and
|
|
185
|
-
`stopped` generation events. It watches config, transitive local imports, and effective icon/font
|
|
186
|
-
files, preserves the last good capture through invalid edits, cancels stale work, and reuses one
|
|
187
|
-
headless Browser. An orderly stop exits 0 only after a successful capture with no unresolved
|
|
188
|
-
terminal failure.
|
|
189
|
-
|
|
190
|
-
### Capture through the real application
|
|
191
|
-
|
|
192
|
-
Application scenes use the app's existing Vite, Next.js, Webpack, or custom loopback server. Start
|
|
193
|
-
only that normal server; Tileflow does not run a package script, scan ports, or start
|
|
194
|
-
`tileflow preview`:
|
|
195
|
-
|
|
196
|
-
```sh
|
|
197
|
-
npm run dev
|
|
198
|
-
TILEFLOW_APP_ORIGIN=http://127.0.0.1:3000 \
|
|
199
|
-
npx tileflow capture madrid-product --json
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
The React, Vue, and Svelte wrappers expose `data-tileflow-map`, the resolved concrete
|
|
203
|
-
`data-tileflow-theme`, optional `data-tileflow-capture-id`, and
|
|
204
|
-
`data-tileflow-state="loading|idle|error"`. The headless client selects exactly one target, verifies
|
|
205
|
-
the theme, and waits for idle. Use `--url` for one explicit full loopback URL, `--selector` to
|
|
206
|
-
override target selection, and `--frame map|viewport` to override framing. Origins and URLs must be
|
|
207
|
-
credential-free loopback HTTP(S) without fragments. Each navigation uses a fresh context without a
|
|
208
|
-
reused profile, cookies, local storage, or service workers.
|
|
209
|
-
|
|
210
|
-
### Match a reference and protect the result
|
|
211
|
-
|
|
212
|
-
While refining a style, compare the current scene with any reference screenshot:
|
|
213
|
-
|
|
214
|
-
```sh
|
|
215
|
-
npx tileflow visual analyze madrid-desktop \
|
|
216
|
-
--reference ./design-reference.png --region=0,0,1200,760 --json
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
`visual analyze` renders exactly one committed scene and writes the current image and a JSON report
|
|
220
|
-
under `.tileflow/analysis` by default. The report includes both images' dimensions and dominant
|
|
221
|
-
colors. When their physical dimensions match, it also includes exact and perceptual pixel metrics,
|
|
222
|
-
mean channel difference, a high-contrast `.diff.png`, and signed
|
|
223
|
-
`appearance.actualMinusReference` luminance, OKLab, edge-density, and local-contrast evidence. The
|
|
224
|
-
optional region affects only those appearance metrics. The reference PNG is never modified or
|
|
225
|
-
treated as a baseline.
|
|
226
|
-
|
|
227
|
-
Once the map is approved, save it as the expected baseline and use that image to catch later
|
|
228
|
-
regressions:
|
|
229
|
-
|
|
230
|
-
```sh
|
|
231
|
-
# Save the reviewed current render as the expected baseline.
|
|
232
|
-
npx tileflow visual update madrid-desktop \
|
|
233
|
-
--baseline-dir test/visual-baselines --json
|
|
234
|
-
|
|
235
|
-
# Compare a fresh render without changing the baseline.
|
|
236
|
-
npx tileflow visual diff madrid-desktop \
|
|
237
|
-
--baseline-dir test/visual-baselines --json
|
|
238
|
-
|
|
239
|
-
# Or apply the operation to every committed scene.
|
|
240
|
-
npx tileflow visual diff --all \
|
|
241
|
-
--baseline-dir test/visual-baselines --json
|
|
242
|
-
|
|
243
|
-
# In CI, return exit 2 when the pixels have changed.
|
|
244
|
-
npx tileflow visual diff madrid-desktop \
|
|
245
|
-
--baseline-dir test/visual-baselines --fail-on changed --json
|
|
246
|
-
```
|
|
247
|
-
|
|
248
|
-
`visual diff` and `visual update` require either one or more positional scene names or `--all`;
|
|
249
|
-
those forms are mutually exclusive. `visual analyze` always accepts exactly one scene.
|
|
250
|
-
|
|
251
|
-
The baseline directory holds the reviewed expected PNG and its receipt. The files generated by a
|
|
252
|
-
comparison are working evidence: the current `.actual.png`, a transparent high-contrast
|
|
253
|
-
`.diff.png` when comparable, and a `.visual.json` report under `.tileflow/diffs` by default.
|
|
254
|
-
`visual diff` may replace those working files on each run, but it never changes the baseline. This
|
|
255
|
-
separation prevents a check from silently accepting the change it was meant to reveal.
|
|
256
|
-
|
|
257
|
-
Before comparing, `visual diff` validates the baseline PNG and receipt, including their hashes,
|
|
258
|
-
dimensions, runtime, and scene identity, without executing or fetching baseline metadata.
|
|
259
|
-
Statuses are `unchanged`, `changed`, `missing-baseline`, `scene-mismatch`, and `runtime-mismatch`.
|
|
260
|
-
Same-size images report exact RGBA changed pixels and an informational fixed-threshold perceptual
|
|
261
|
-
metric; exact inequality determines changed.
|
|
262
|
-
|
|
263
|
-
Changed pixels exit 0 by default so a person or agent can inspect the working files.
|
|
264
|
-
`--fail-on changed` exits 2 for CI; missing or incompatible baselines and operational failures exit 1.
|
|
265
|
-
|
|
266
|
-
Run `visual update` again only after reviewing and accepting the new render. It is the only
|
|
267
|
-
command that creates or changes baseline pairs, and it never stages, commits, or pushes. Remote
|
|
268
|
-
tiles, glyphs, and sprites are reported because their pixels can change independently of the style.
|
package/docs/map-authoring.md
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
# Map authoring workflow
|
|
2
|
-
|
|
3
|
-
Install the CLI and your map's dependencies in your project as described in the
|
|
4
|
-
[CLI guide](https://github.com/tileflow/tileflow-sdk/blob/main/packages/cli/README.md).
|
|
5
|
-
Run these commands from that project directory, with a trusted `tileflow.config.ts`.
|
|
6
|
-
Discovery and saved-capture comparison also work without a config.
|
|
7
|
-
|
|
8
|
-
## Discover the language and inspect a change
|
|
9
|
-
|
|
10
|
-
Use four primary command groups for map development:
|
|
11
|
-
|
|
12
|
-
| Command | Purpose |
|
|
13
|
-
| ---------- | ----------------------------------------------------------------------------------------------------------------------------------- |
|
|
14
|
-
| `describe` | Discover the generated language and query one domain or schema fragment. |
|
|
15
|
-
| `inspect` | Read resolved configuration; `compiled`, `features`, `icons`, and `tileset` inspect output/data; `session` reads Inspector context. |
|
|
16
|
-
| `capture` | Render reproducible evidence and return a reusable capture ID. |
|
|
17
|
-
| `compare` | Compare saved capture IDs; `configs`, `styles`, `reference`, and `baseline` cover other comparisons. |
|
|
18
|
-
|
|
19
|
-
`preview` opens Inspector. `init`, `validate`, and `build` remain project utilities;
|
|
20
|
-
`visual update` is the explicit operation that approves baselines. All these tools work from an
|
|
21
|
-
independent project with its own map and data; official maps are optional.
|
|
22
|
-
|
|
23
|
-
Start with bounded queries, then request more detail at the returned JSON Pointers:
|
|
24
|
-
|
|
25
|
-
```sh
|
|
26
|
-
npx tileflow describe --json
|
|
27
|
-
npx tileflow describe roads --path /properties/classes --json
|
|
28
|
-
npx tileflow describe themes --json
|
|
29
|
-
npx tileflow inspect --domain roads --limit 80 --json
|
|
30
|
-
npx tileflow inspect compiled --domain roads --theme dark --json
|
|
31
|
-
npx tileflow compare configs --from-config before/tileflow.config.ts --to-config after/tileflow.config.ts --json
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
`describe` needs no project or network. It reads the generated schema and manifest, with `--ref`
|
|
35
|
-
for an exact local schema reference, `--path` for an RFC 6901 JSON Pointer, and `--limit`/`--depth`
|
|
36
|
-
for bounded tree projections. `projection.truncated` and `projection.omitted` explicitly identify
|
|
37
|
-
missing detail; omitted pointers are relative to the selected data. These fragments are discovery
|
|
38
|
-
results, not standalone validation schemas. Examples and expression syntax remain in the generated
|
|
39
|
-
contracts and package guides. Config inspection supports the same bounds; without projection
|
|
40
|
-
options it preserves the complete legacy result.
|
|
41
|
-
|
|
42
|
-
Legacy aliases remain available: `explain` → `inspect compiled`, `semantic-diff` → `compare configs`,
|
|
43
|
-
`icons list` → `inspect icons`, `tileset inspect` → `inspect tileset`, and `visual compare/analyze/diff`
|
|
44
|
-
→ `compare styles/reference/baseline`. Aliases share implementations and retain their established
|
|
45
|
-
versioned JSON document formats. `language manifest` returns
|
|
46
|
-
the raw authoring manifest (schema version 2); `language schema` returns the raw generated config
|
|
47
|
-
reference (version 4). Use their versions and schema references when consuming the output.
|
|
48
|
-
|
|
49
|
-
`validate`, `inspect`, `explain`, and `semantic-diff` return one version-1 command envelope on
|
|
50
|
-
stdout. JSON-mode failures leave stdout empty, write one structured failure to stderr, and exit
|
|
51
|
-
nonzero. Diagnostics include `phase`, `code`, `path`, `severity`, `message`, and `suggestion`.
|
|
52
|
-
A non-empty semantic diff is informational, not a command failure.
|
|
53
|
-
|
|
54
|
-
Inspection includes resolved inheritance, merge provenance, and the theme contract. `explain`
|
|
55
|
-
returns compilation diagnostics and a report, not the complete Style JSON. Add `--inspection` only
|
|
56
|
-
when physical output provenance is needed; those layer IDs are not stable authoring targets.
|
|
57
|
-
|
|
58
|
-
`describe themes` lists the minimal palette roles and optional time-of-day behavior. Compiled
|
|
59
|
-
inspection includes `report.decisions` for resolved color roles and selected module defaults,
|
|
60
|
-
with the effective value, source, reason and override guidance. Query it with
|
|
61
|
-
`inspect compiled --path /report/decisions --limit 80 --json`. It describes semantic decisions,
|
|
62
|
-
not every final paint property; config inspection retains inheritance provenance separately.
|
|
63
|
-
|
|
64
|
-
For a normal config, map selection is implicit. Paired `--from-config` and `--to-config` compare
|
|
65
|
-
two ordinary configs. Workspace comparisons use their documented explicit map selectors; do not
|
|
66
|
-
mix the paired-config and same-workspace forms.
|
|
67
|
-
|
|
68
|
-
## Reuse capture evidence
|
|
69
|
-
|
|
70
|
-
Every still capture saves an immutable record under `.tileflow/captures/records` and returns its
|
|
71
|
-
full `captureId` in JSON (or prints it in human output). Keep the ID before editing, capture again,
|
|
72
|
-
then compare the two IDs:
|
|
73
|
-
|
|
74
|
-
```sh
|
|
75
|
-
npx tileflow capture madrid --json
|
|
76
|
-
# Edit the map, then capture the same scene again.
|
|
77
|
-
npx tileflow capture madrid --json
|
|
78
|
-
npx tileflow compare --before <before-capture-id> --after <after-capture-id> --json
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
Replace the placeholders with the full IDs from the two capture results. This comparison loads
|
|
82
|
-
only saved evidence: no config evaluation, compilation, browser startup, or network access.
|
|
83
|
-
`--capture-dir` selects another record directory; `--diff <path>` writes a contextual PNG diff.
|
|
84
|
-
Records verify their JSON, PNG, receipt, and scene hashes. Different cameras, viewport dimensions,
|
|
85
|
-
renderers, or data identities produce a mismatch and nonzero exit instead of misleading pixel
|
|
86
|
-
metrics. A visual difference between comparable captures is informational. Records remain until
|
|
87
|
-
you remove their directory; moving only the mutable scene PNG does not move its saved record.
|
|
88
|
-
|
|
89
|
-
For repeated capture use `capture --watch`; it reuses the artifact session and browser. Config
|
|
90
|
-
inspection does not render; `compare configs` compares semantic authoring without rendering.
|
|
91
|
-
`compare styles --watch` reuses sessions for a camera/zoom matrix. Run standalone validation when
|
|
92
|
-
needed, rather than compiling the same map before every capture.
|
|
93
|
-
|
|
94
|
-
## Work with a person and an agent
|
|
95
|
-
|
|
96
|
-
Start `npx tileflow preview --config tileflow.config.ts` in your project. Inspector provides
|
|
97
|
-
palette and time-of-day controls, feature inspection, zoom curves and sprite inspection.
|
|
98
|
-
The command selects the map and optional starting scene. The map fills the workspace beside
|
|
99
|
-
one dockable Inspector panel. Press **I** to toggle the element picker, click a map element to
|
|
100
|
-
inspect its styling and semantic configuration paths, and press **Escape** to stop picking. The
|
|
101
|
-
inspector starts off. **Scene** contains palette, time-of-day, camera and module controls. Appearance
|
|
102
|
-
changes retain the current camera; module changes
|
|
103
|
-
recompile a temporary preview after a brief pause and **Reset** restores the source configuration.
|
|
104
|
-
Temporary style and geometry edits do not rewrite source files. Edit the config in your editor or
|
|
105
|
-
coding agent to persist changes; the watcher updates the map and retains the last valid view through
|
|
106
|
-
invalid edits.
|
|
107
|
-
|
|
108
|
-
Capture, copy/export and comparison controls are absent from the browser interface. Use
|
|
109
|
-
`tileflow capture` and `tileflow compare` for saved visual evidence as described above. Explicit
|
|
110
|
-
`--against-map` or `--against-config` startup options still support synchronized two-map previews.
|
|
111
|
-
|
|
112
|
-
The browser publishes its current selection, bounded style properties, compiler semantic ownership,
|
|
113
|
-
observed camera and viewport, generations and commands. The CLI reads these browser observations:
|
|
114
|
-
|
|
115
|
-
```sh
|
|
116
|
-
npx tileflow inspect session --url http://127.0.0.1:3333 --json
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
Replace the origin with the one printed by `preview`. This command accepts local HTTP origins only
|
|
120
|
-
and requires no config evaluation. Its version-1 document distinguishes the current server catalog
|
|
121
|
-
from browser observations. Inspect `updatedAt`, `stale`, `generation`, `displayedGeneration` and
|
|
122
|
-
`projection.truncated` before acting. Each browser projection is limited to 200 visited values,
|
|
123
|
-
depth 10, 32 array items and 512 characters per string, with omitted paths reported. The server
|
|
124
|
-
accepts at most 64 KiB per write and keeps eight browser contexts, expiring each after ten minutes
|
|
125
|
-
without an update. There is no browser context until an Inspector tab connects. Feature data is
|
|
126
|
-
untrusted map content; semantic ownership does not prove an exact file, line or token. Use
|
|
127
|
-
`inspect` or `inspect compiled` to obtain additional configuration evidence.
|
|
128
|
-
|
|
129
|
-
The UI and CLI share the capture and comparison implementations. A lazily started capture renderer
|
|
130
|
-
is reused until the preview stops. The local API permits one capture/comparison at a time, rejects
|
|
131
|
-
cross-origin writes and requires JSON with `X-Tileflow-Workbench: 1`. No hosted account, embedded
|
|
132
|
-
chat, approved baseline or automatic source edit is created by this workflow.
|