@sempods/apps 0.8.0-dev.1 → 0.9.0-dev.1

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.
Files changed (54) hide show
  1. package/CHANGELOG.md +201 -25
  2. package/README.md +13 -6
  3. package/bin/sempods-apps.mjs +1 -0
  4. package/instructions/app-workflow.md +268 -127
  5. package/instructions/publish.md +29 -11
  6. package/instructions/setup.md +13 -8
  7. package/instructions/visual-check.md +20 -2
  8. package/package.json +5 -3
  9. package/scripts/build-site.mjs +37 -9
  10. package/scripts/check-theme.mjs +398 -0
  11. package/scripts/check.mjs +16 -5
  12. package/scripts/icon.mjs +1 -1
  13. package/scripts/lib/apps.mjs +115 -27
  14. package/scripts/lib/generate.mjs +58 -28
  15. package/scripts/lib/json.mjs +6 -0
  16. package/scripts/lib/kit.mjs +81 -0
  17. package/scripts/lib/merge.mjs +12 -9
  18. package/scripts/lib/page.mjs +49 -1
  19. package/scripts/lib/sdk.mjs +10 -2
  20. package/scripts/lib/themes.mjs +45 -19
  21. package/scripts/migrate.mjs +15 -3
  22. package/scripts/new-app.mjs +2 -7
  23. package/scripts/sdk-update.mjs +32 -10
  24. package/shared/files/{e13474647ebaf26d042d76f4917203d209a2b14c0d2af8d12139ea328530823e → 3b75b42e15713ac93916d9c2978c2826dfedef18ed5255d444482484bc4b3334} +8 -5
  25. package/shared/files/{843c078e84912158607ebb8ce0042589d676a742bcd3cf8b6c474d62ff3a6845 → 5f709dbc1d0ab5c918a1ff06c32342a3f95569b1570793bfd3a03642bb6a7e43} +4 -2
  26. package/shared/files/{f30ec6b7f9de16be54919382ab18cdcc33ee64938f7b907d855bcf6740e4c102 → e1c798ec8536cf8cff6c19caf622fa9076ae210b0d1733a6e82ea2c1f4104c43} +11 -2
  27. package/shared/snapshot.json +4 -4
  28. package/skeleton/app/NOTES.md +11 -3
  29. package/skeleton/app/package.json +3 -0
  30. package/skeleton/app/src/App.tsx +53 -21
  31. package/skeleton/app/src/examples/ContextSwitch.tsx +131 -0
  32. package/skeleton/app/src/examples/ListScreen.tsx +176 -69
  33. package/skeleton/app/src/index.css +10 -110
  34. package/skeleton/app/src/main.tsx +1 -3
  35. package/skeleton/app/src/places.test.ts +128 -0
  36. package/skeleton/app/src/places.ts +146 -0
  37. package/skeleton/app/src/texts.ts +8 -0
  38. package/skeleton/app/src/themes/calm.css +22 -8
  39. package/skeleton/app/src/themes/fresh.css +22 -8
  40. package/skeleton/app/src/themes/playful.css +22 -8
  41. package/skeleton/app/src/themes/warm.css +22 -8
  42. package/skeleton/app/vite.config.ts +12 -2
  43. package/skills/update/SKILL.md +6 -1
  44. package/update-policy.json +1 -1
  45. package/skeleton/app/src/routes.test.ts +0 -19
  46. package/skeleton/app/src/routes.ts +0 -139
  47. package/skeleton/app/src/ui/Composer.tsx +0 -18
  48. package/skeleton/app/src/ui/ContextSwitch.tsx +0 -85
  49. package/skeleton/app/src/ui/Dialog.tsx +0 -103
  50. package/skeleton/app/src/ui/Menu.tsx +0 -118
  51. package/skeleton/app/src/ui/Tabs.tsx +0 -39
  52. package/skeleton/app/src/ui/dismiss.ts +0 -30
  53. package/skeleton/app/src/ui/icons.tsx +0 -53
  54. package/skeleton/app/src/ui/ui.css +0 -240
package/CHANGELOG.md CHANGED
@@ -4,6 +4,172 @@ Each release lists what changed and **upgrade notes** for the assistant that
4
4
  applies it. The notes cover what an update cannot decide alone: owner files,
5
5
  configuration choices and the SDK migration.
6
6
 
7
+ ## 0.9.0
8
+
9
+ Prerelease `0.9.0-dev.1` for acceptance testing against SDK `0.7.0-dev.2`.
10
+
11
+ ### Changes
12
+
13
+ SDK and UI kit:
14
+
15
+ - New repositories use SDK 0.7.0-dev.2 (`@sempods/app-sdk`,
16
+ `@sempods/client-sdk`) and the UI kit `@sempods/app-ui` of the same
17
+ version, which is released with the SDK. `@sempods/apps` supports
18
+ `^0.7.0-dev.2` of all three. The UI kit is shadcn/ui (style aria-nova) on
19
+ React Aria for Tailwind CSS 4, with sempods adapters (`ScreenDialog`,
20
+ `HeaderMenu`, `DateChooser`, `ActionButton`/`ActionLink`/`ActionGroup`,
21
+ `ChipGroup`/`Chip`), the router `useNav` and a theme token contract with a
22
+ bridge to the SDK's tokens. Kit fixes reach apps through its version.
23
+ - The UI kit joins the SDK in `update-policy.json` (`sdk`): the root declares
24
+ it, an app declares it when it uses it, and `check` requires one version
25
+ for all of them. `sdk-update` moves it with the SDK packages, adds it to a
26
+ root that lacks it, checks that the release supports the SDK and moves it
27
+ in an app only where the app declares it. `new-app` gives a new app the
28
+ root's version. The Dependabot SDK groups include it. `build-site`
29
+ publishes its licence notices with the apps that use it.
30
+ - The migration never adds the UI kit to a root at an SDK version that has
31
+ none (before 0.7.0); its report says that `sdk-update` adds it.
32
+
33
+ Skeleton:
34
+
35
+ - Tailwind CSS 4 (`tailwindcss`, `@tailwindcss/vite`) and `@sempods/app-ui`.
36
+ `src/index.css` declares the layer order
37
+ `@layer theme, base, sempods, components, utilities;`, then imports
38
+ Tailwind, the UI kit's styles and the app's theme; `main.tsx` imports only
39
+ `index.css`. `vite.config.ts` adds the Tailwind plugin and raises Vite's
40
+ chunk warning to 1000 kB: React, the SDK and the UI kit come to about
41
+ 570 kB minified (180 kB gzip) in one chunk.
42
+ - The four themes in `src/themes/` set the palette roles of the theme
43
+ contract (`--background`, `--foreground`, `--card`, `--popover`,
44
+ `--primary`, `--secondary`, `--muted`, `--accent`, `--destructive`,
45
+ `--border`, `--input`, `--ring` with their foregrounds) in light and dark
46
+ mode, instead of the `--sempods-*` tokens, which the kit's bridge now sets.
47
+ Each passes `check:theme` in every action variant. Action variants switch
48
+ with `data-actions` and `data-secondary` on `<html>`. The icon takes the
49
+ theme's primary colour.
50
+ - The copied kit in `src/ui/` and the router in `src/routes.ts` are gone.
51
+ `src/places.ts` is the app's address model (start page, a view per route,
52
+ an item per resource address with its source Context, the callback and an
53
+ explicit not-found place), and `App.tsx` routes with `useNav(places)`,
54
+ passes the kit's `replaceUrl` to the runtime through `inApp`, uses
55
+ `HeaderMenu` for the menu and shows a not-found page once the person is
56
+ connected. `inApp` keeps the return of a callback without a matching
57
+ sign-in, for example an expired one, in the app: the SDK returns such a
58
+ callback to `/`, the site's overview, when `returnTo` is a function.
59
+ - `src/examples/ListScreen.tsx` is rebuilt on the kit: each item has its own
60
+ address and opens in a `ScreenDialog` with the SDK's editor for the Context
61
+ the address names; closing returns to the opener and reloads the list
62
+ without waiting for it. The input of the bar at the bottom keeps its focus
63
+ while it adds several items: read-only while a creation is pending and
64
+ focused from the submit handler, also after a press on Add
65
+ (sempods/sempods-apps-template#113).
66
+ - `src/examples/ContextSwitch.tsx` replaces `ui/ContextSwitch.tsx`, built on
67
+ the kit's menu parts.
68
+
69
+ Addresses:
70
+
71
+ - `routes` in `apps.json` takes literal addresses of up to four segments
72
+ (`tasks/add`); `build-site` writes their copies in subfolders.
73
+ - `resources` (new) declares patterns with placeholders for one segment each
74
+ (`tasks/:id`, `tasks/:id/postpone`). The first segment is a word, so a
75
+ pattern never catches the callback or the app's files; patterns that name
76
+ the same addresses are refused. `build-site` writes `site-dist/_redirects`
77
+ with one rewrite per pattern to the app's page, for hosts that read it
78
+ (Netlify, Cloudflare Pages).
79
+ - The PWA navigation allowlist covers the start page, every route and every
80
+ resource pattern, each with an optional query: Workbox matches path and
81
+ query, so the start page with a query and every resource address now open
82
+ offline.
83
+ - Sign-in returns to the address it started from with its query when the app
84
+ declares it (start page, route or resource), otherwise to the start page,
85
+ also in an app without routes. It drops the callback's parameters (`code`,
86
+ `state`, `error`, `iss`, `response`), which the SDK refuses in a return
87
+ address, and keeps the rest of the query. The generated `returnTo` is now a
88
+ function for every app.
89
+
90
+ Tooling:
91
+
92
+ - `pnpm run check:theme [<id>]` (new; `sempods-apps check-theme`) builds each
93
+ app that uses the UI kit, loads its stylesheet with the attributes of its
94
+ `<html>` in Chromium and runs the kit's role check under a light and a dark
95
+ preference, for every action variant. It prints one line per failing pair
96
+ with the variants, colours, ratio and roles to adjust, reports a scheme the
97
+ theme excludes as not sampled, prints the reports with `--json` and fails on
98
+ any contrast failure or checker error. Playwright is a dependency of
99
+ `@sempods/apps`; `--install-browser` installs its Chromium once.
100
+ - `migrate` names every app that still has the kit copied in 0.8.0, with the
101
+ files that are as shipped and those the owner changed. It changes none of
102
+ them.
103
+
104
+ Instructions:
105
+
106
+ - The app workflow, the skill's visual check and the publish guide name the
107
+ kit's components and adapters, the theme contract and `check:theme`, the
108
+ address model with `routes` and `resources`, the source Context in resource
109
+ addresses and the rewrite requirement for resource patterns. A component
110
+ the kit lacks comes from `shadcn add` and is the app's own; copying a kit
111
+ component to change it is a recorded decision.
112
+
113
+ ### Upgrade notes
114
+
115
+ 1. After `migrate`, `check` reports the SDK as outside the supported range
116
+ and, at the root, the missing `@sempods/app-ui`. Run
117
+ `pnpm run sdk-update <version>` with the SDK release this tooling names
118
+ (now `0.7.0-dev.2`); it adds the UI kit to the root. Then follow the SDK's
119
+ `migration.md`, "From 0.6.0 to 0.7.0": its styles now sit in the cascade
120
+ layer `sempods`, so check the sign-in screen, the Pods & sharing dialog, an
121
+ editor and a confirmation with each app's real stylesheet.
122
+ 2. `pnpm run regenerate` (the migration runs it) widens the offline
123
+ allowlist to addresses with a query and keeps the query on sign-in, also
124
+ in an app without routes. Its `returnTo` is then a function, so a
125
+ callback without a matching sign-in returns to `/`, the site's overview.
126
+ Keep it in the app where `App.tsx` creates the runtime:
127
+ `replaceUrl: (url) => replaceUrl(url.startsWith(app.basePath) ? url : app.basePath)`,
128
+ or `inApp` from the skeleton's `src/places.ts` once the app has it.
129
+ 3. An app with the copied kit keeps working; `check` does not require the UI
130
+ kit. Move it to the package only when the owner agrees, as its own pull
131
+ request, with the migration report's note for that app at hand:
132
+ 1. `pnpm add --dir apps/<id> @sempods/app-ui@<the SDK version>
133
+ lucide-react@1.65.0` and
134
+ `pnpm add --dir apps/<id> -D tailwindcss@4.3.3 @tailwindcss/vite@4.3.3`.
135
+ 2. Add `tailwindcss()` from `@tailwindcss/vite` to the plugins in
136
+ `vite.config.ts`, as the skeleton does
137
+ (`node_modules/@sempods/apps/skeleton/app/vite.config.ts`).
138
+ 3. Take the skeleton's `src/index.css`, with the app's theme name in its
139
+ import line, and import only it in `src/main.tsx`. Move the app's own
140
+ global rules into `@layer base` or into Tailwind classes; an unlayered
141
+ element rule overrides every SDK rule.
142
+ 4. A theme the app kept as shipped: copy the skeleton's theme of the same
143
+ name. A changed theme: carry its colours over to the palette roles
144
+ (`--sempods-bg` → `--background`, `--sempods-text` → `--foreground`,
145
+ `--sempods-muted` → `--muted-foreground`, `--sempods-line` →
146
+ `--border`, `--sempods-accent` → `--primary` and `--ring`,
147
+ `--sempods-on-accent` → `--primary-foreground`), add the other roles
148
+ from the skeleton's theme, give `--input` 3:1 against the surfaces, and
149
+ run `pnpm run check:theme <id>` until it passes.
150
+ 5. Replace `src/routes.ts` with the skeleton's `src/places.ts` and
151
+ `places.test.ts`: a route `r` becomes `{ kind: 'view', route: r }`, the
152
+ start page `{ kind: 'start' }`; `useRoute()` becomes `useNav(places)`
153
+ once in the frame, `go(r)` `nav.go(place)`, `link(r)`
154
+ `nav.link(place)`, and `replaceUrl` comes from `@sempods/app-ui`,
155
+ passed to the runtime through `inApp` as the skeleton's `App.tsx` does.
156
+ Declare an item screen's address under `resources` and open it with
157
+ `ScreenDialog`, as the list example does.
158
+ 6. Replace each kit part: `Menu` with `HeaderMenu`, `Dialog` with
159
+ `ScreenDialog`, `Composer` with the bar of the list example, `Tabs` with
160
+ links (`nav.link`) or a View submenu of `HeaderMenu`, `ContextSwitch`
161
+ with the skeleton's `src/examples/ContextSwitch.tsx`, the icons with
162
+ `lucide-react`. Delete the files the note lists as shipped once nothing
163
+ imports them. A file the note lists as changed holds the owner's own
164
+ work: carry that change over into the new composition, or keep the file
165
+ as the app's own and record that under Decisions in `NOTES.md`; ask the
166
+ owner which.
167
+ 7. Run `pnpm run check`, `pnpm run check:theme <id>` and the visual check,
168
+ including Back, Escape and Close with an unsaved edit, and record them
169
+ in the app's `NOTES.md`.
170
+ 4. Apps with resource patterns need a host that reads `_redirects`; check
171
+ each resource address as the publish guide's deployment check describes.
172
+
7
173
  ## 0.8.0
8
174
 
9
175
  ### Changes
@@ -58,7 +224,7 @@ Look:
58
224
  `--sempods-*` tokens: `Menu` (a button with a list of actions or choices;
59
225
  Escape, a press outside and the arrow keys), `ContextSwitch` (the everyday
60
226
  switch between the contexts shared with the app over the SDK's
61
- `useContexts`, in place of the app's name), `Tabs` (views as links with
227
+ `useContexts`, in place of the header's `<h1>`), `Tabs` (views as links with
62
228
  their routes), `Composer` (an input bar fixed at the bottom, above the home
63
229
  indicator and, where browsers support it, the on-screen keyboard), `Dialog`
64
230
  (modal, a bottom sheet on phones, for example around a `ResourceEditor`)
@@ -66,8 +232,9 @@ Look:
66
232
  - The skeleton ships `src/examples/ListScreen.tsx`, not mounted: the SDK's
67
233
  quickstart screen built with the kit (loading and failed reads, an empty
68
234
  state, rows with a labelled checkbox, the item's `ResourceEditor` in a
69
- `Dialog`, `RemoveButton`, open outcomes and a `Composer`). It compiles with
70
- every app, so it stays valid against the SDK.
235
+ `Dialog`, `RemoveButton`, open outcomes and a `Composer`, which a list the
236
+ person can only read does not show). It compiles with every app, so it
237
+ stays valid against the SDK.
71
238
 
72
239
  Content and configuration:
73
240
 
@@ -116,25 +283,29 @@ Content and configuration:
116
283
 
117
284
  Instructions:
118
285
 
119
- - The app workflow starts a new app with a short design conversation
120
- (purpose, mood as a theme, name and icon), asked as choices with "choose for
121
- me", and records it under Design in the app's `NOTES.md`; later wishes
122
- change the recorded choice instead of adding one-off styles. It says which
123
- parts of the look are shared (layout, kit) and which are chosen per app
124
- (theme, name, icon).
125
- - The app workflow settles how an app uses contexts before its first screen:
126
- one context, several one at a time, read all and write in one, or write
127
- into several. It infers the shape or asks once in everyday words and starts
128
- from the SDK's path for it (`AppAccess` or a preset, `useContexts` with
129
- `ContextSwitch`, the Pod overview with `useCreation`, one `useCreation` per
130
- context). The skeleton's `NOTES.md` has Design and Data sections, and setup
131
- asks for one test context per context the shape uses.
286
+ - App planning settles purpose, personal versus shared data and context
287
+ access limits before generation, with at most three short questions at a
288
+ time. The assistant proposes layout, theme, name and icon; a vague request
289
+ need not wait for visual choices. Decisions go into the app's `NOTES.md`.
290
+ - The workflow chooses reusable data mappings from existing data and
291
+ established vocabularies, preserving identities and fields other apps use.
292
+ If the owner wants, optional read-only inspection through a connected MCP
293
+ Pod informs this choice within an agreed scope. Setup and the user guide
294
+ explain that MCP is optional and separate from signing in to the app;
295
+ app trials still use synthetic data in dedicated test contexts.
296
+ - Before generation, the workflow settles what the app reads, where new
297
+ records go and where existing records are edited: one context, several one
298
+ at a time, read all and write in one, edit overview rows in their source
299
+ contexts, or write into several. It starts from the installed SDK's path
300
+ for that shape. The skeleton's notes record Data and Vocabulary decisions,
301
+ including observed mappings and assumptions still to verify. Setup asks
302
+ for one test context per context the shape uses.
132
303
  - The app workflow starts a list from the list example, takes only behaviour
133
304
  from the SDK's examples, deletes rows with `RemoveButton`, relies on the
134
305
  SDK's list refresh when the page becomes visible again, adds kit parts only
135
306
  when the app needs them, and describes routes, renaming and themes. It is
136
- reordered: design conversation and `new-app`, context shape, vocabulary,
137
- screen, views, configuration.
307
+ reordered: planning, optional data inspection, context shape, vocabulary,
308
+ `new-app`, screen, views, configuration.
138
309
  - A visual check before handover (`instructions/visual-check.md`): the
139
310
  assistant takes screenshots at 375px and desktop width, light and dark, with
140
311
  real states (empty, a few items, an open item, a notice), checks them
@@ -150,11 +321,12 @@ Instructions:
150
321
  1. The migration does by itself: it adds the root script `icon`, regenerates
151
322
  every app (`app.routes`, `app.description` as `null` until set, the
152
323
  manifest colours, the `pageTitle` plugin, the service worker's allowlist
153
- for routes) and moves apps to the generated page title where that is
154
- unambiguous, listed under "Updated". For any other app, `check` names what
155
- is left: add `pageTitle` from `./vite.sempods.generated.ts` to the plugins
156
- in its `vite.config.ts`, as the skeleton does, and remove the `<title>`
157
- from its `index.html`. A page title other than the one in `apps.json` was
324
+ for routes), moves apps to the generated page title where that is
325
+ unambiguous and replaces the viewport and green `theme-color` lines an
326
+ app's `index.html` kept from the 0.7 skeleton, listed under "Updated". For
327
+ any other app, `check` names what is left: add `pageTitle` from
328
+ `./vite.sempods.generated.ts` to the plugins in its `vite.config.ts`, as
329
+ the skeleton does, and remove the `<title>` from its `index.html`. A page title other than the one in `apps.json` was
158
330
  chosen by hand: ask the owner whether it should be the app's title, put it
159
331
  into `apps.json` and run `pnpm run regenerate`. Settle these cases before
160
332
  the SDK move: `sdk-update` ends with `check` and stops on them.
@@ -191,8 +363,12 @@ Instructions:
191
363
  `document.documentElement.lang`), because `app.language` is then
192
364
  `"auto"`; read the app's texts from a catalogue with both languages
193
365
  through `useMessages`;
194
- - Design and Data sections in `NOTES.md`, settling the context shape as the
195
- app workflow describes.
366
+ - Design, Data and Vocabulary sections in `NOTES.md`, following the app
367
+ workflow. Check personal/shared access assumptions, reuse of existing
368
+ data and the separate destinations of new records and edits. Offer MCP
369
+ inspection only when existing data is relevant and the owner wants it;
370
+ record unverified assumptions when it is skipped. These instructions
371
+ do not migrate existing Pod data.
196
372
 
197
373
  ## 0.7.1
198
374
 
package/README.md CHANGED
@@ -11,17 +11,19 @@ Create a repository with `pnpm create @sempods/apps <directory>`
11
11
  `sempods-apps create <directory>` of the same version. The repository's root
12
12
  `package.json` runs the other commands through `sempods-apps <command>`:
13
13
 
14
- - `pnpm run new-app <id>` creates `apps/<id>` with the root's SDK version.
14
+ - `pnpm run new-app <id>` creates `apps/<id>` with the root's SDK version,
15
+ built with the UI kit `@sempods/app-ui`.
15
16
  - `pnpm run icon <id>` draws an app's monogram icon again in its theme's
16
- accent.
17
+ primary colour.
17
18
  - `pnpm run dev <id>` starts that app.
18
19
  - `pnpm run regenerate` rewrites every app's generated configuration from
19
20
  `apps.json`, for example after a tooling update.
20
21
  - `pnpm run configure-site --production <origin>` records where the apps are
21
22
  published and regenerates their configuration.
22
23
  - `pnpm run build-site` builds all apps and the overview into one static site,
23
- `site-dist/`.
24
- - `pnpm run sdk-update <version>` moves all apps to one SDK release.
24
+ `site-dist/`, with `_redirects` rewrites for the apps' resource addresses.
25
+ - `pnpm run sdk-update <version>` moves all apps to one SDK release: the SDK
26
+ packages and the UI kit.
25
27
  - `pnpm run update [<version>]` checks that Node and pnpm suit the target
26
28
  version, installs it and runs its `migrate`. `pnpm run migrate` applies the
27
29
  installed version's starter to the repository from `.sempods-baseline.json`.
@@ -31,13 +33,18 @@ Create a repository with `pnpm create @sempods/apps <directory>`
31
33
  - `pnpm run check` checks all apps; `--standalone all` also installs, lints,
32
34
  builds and tests each app on its own. It reports an SDK version outside the
33
35
  range this package supports (its `peerDependencies`).
36
+ - `pnpm run check:theme [<id>]` checks the contrast of each app's theme in
37
+ light and dark mode and every action variant, in Chromium through
38
+ Playwright; `--json` prints the reports, and `--install-browser` installs
39
+ the browser once.
34
40
 
35
41
  Contents:
36
42
 
37
43
  - `instructions/`: the setup procedure, the app workflow, the visual check and
38
44
  the publish guide; `skills/` holds the skill entries that route to them.
39
- - `skeleton/app/`: what a new app starts from, with its themes, UI kit and
40
- list example. Files named `*.generated.ts` in
45
+ - `skeleton/app/`: what a new app starts from: Tailwind CSS 4 and
46
+ `@sempods/app-ui`, its themes, its address model and the list and context
47
+ switch examples. Files named `*.generated.ts` in
41
48
  an app are written from `apps.json`; do not edit them. `check` reports any
42
49
  difference, and `regenerate` rewrites them.
43
50
  - `shared/`: the starter of this release, its files stored by content hash in
@@ -13,6 +13,7 @@ const COMMANDS = {
13
13
  'configure-site': 'record where the apps are published',
14
14
  'build-site': 'build all apps and the overview into site-dist/',
15
15
  check: "check the repository's apps",
16
+ 'check-theme': "check the contrast of an app's theme in a browser",
16
17
  'sdk-update': 'move all apps to one SDK release',
17
18
  update: 'install a newer @sempods/apps and migrate to its starter',
18
19
  migrate: "apply the installed @sempods/apps' starter to this repository",