@sempods/apps 0.7.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +200 -0
  2. package/README.md +6 -3
  3. package/bin/sempods-apps.mjs +1 -0
  4. package/instructions/app-workflow.md +322 -111
  5. package/instructions/publish.md +13 -7
  6. package/instructions/setup.md +38 -23
  7. package/instructions/visual-check.md +43 -0
  8. package/package.json +3 -3
  9. package/scripts/build-site.mjs +15 -3
  10. package/scripts/check.mjs +3 -1
  11. package/scripts/icon.mjs +47 -0
  12. package/scripts/lib/apps.mjs +56 -2
  13. package/scripts/lib/generate.mjs +55 -14
  14. package/scripts/lib/icon.mjs +192 -0
  15. package/scripts/lib/overview.mjs +5 -3
  16. package/scripts/lib/page.mjs +137 -0
  17. package/scripts/lib/themes.mjs +58 -0
  18. package/scripts/migrate.mjs +44 -14
  19. package/scripts/new-app.mjs +43 -10
  20. package/scripts/sdk-update.mjs +16 -1
  21. package/shared/files/{f2fb601d5ebc4ca72274ac9d3fcf7b7a96e27958bb92cd065a9165b501ee94d7 → 44c114d4d2c8b172f4757100f79e8a1a00d30c96ba2ad8f75c3373e52f6b849f} +2 -2
  22. package/shared/files/{31ede0d1a035d8531100ebfd751510c772ab0871309a0b9752a77fb96187eb53 → 843c078e84912158607ebb8ce0042589d676a742bcd3cf8b6c474d62ff3a6845} +3 -2
  23. package/shared/files/{1c29eed0a0297c742ca5814de9081ff8efce3b2da5d9e1bdf90a403873da4aa9 → e1c798ec8536cf8cff6c19caf622fa9076ae210b0d1733a6e82ea2c1f4104c43} +17 -2
  24. package/shared/snapshot.json +4 -4
  25. package/skeleton/app/NOTES.md +20 -2
  26. package/skeleton/app/index.html +7 -3
  27. package/skeleton/app/package.json +6 -6
  28. package/skeleton/app/src/App.tsx +53 -21
  29. package/skeleton/app/src/NewVersionNotice.tsx +6 -11
  30. package/skeleton/app/src/examples/ListScreen.tsx +176 -0
  31. package/skeleton/app/src/index.css +86 -13
  32. package/skeleton/app/src/main.tsx +3 -0
  33. package/skeleton/app/src/pwa.ts +1 -1
  34. package/skeleton/app/src/routes.test.ts +19 -0
  35. package/skeleton/app/src/routes.ts +139 -0
  36. package/skeleton/app/src/texts.test.ts +28 -0
  37. package/skeleton/app/src/texts.ts +35 -0
  38. package/skeleton/app/src/themes/calm.css +11 -0
  39. package/skeleton/app/src/themes/fresh.css +11 -0
  40. package/skeleton/app/src/themes/playful.css +11 -0
  41. package/skeleton/app/src/themes/warm.css +11 -0
  42. package/skeleton/app/src/ui/Composer.tsx +18 -0
  43. package/skeleton/app/src/ui/ContextSwitch.tsx +94 -0
  44. package/skeleton/app/src/ui/Dialog.tsx +120 -0
  45. package/skeleton/app/src/ui/Menu.tsx +118 -0
  46. package/skeleton/app/src/ui/Tabs.tsx +39 -0
  47. package/skeleton/app/src/ui/dismiss.ts +30 -0
  48. package/skeleton/app/src/ui/icons.tsx +53 -0
  49. package/skeleton/app/src/ui/ui.css +249 -0
  50. package/skeleton/app/vite.config.ts +4 -4
  51. package/skills/update/SKILL.md +4 -2
  52. package/skeleton/app/public/favicon.svg +0 -1
  53. package/skeleton/app/public/icon-192.png +0 -0
  54. package/skeleton/app/public/icon-512.png +0 -0
  55. package/skeleton/app/src/start.test.ts +0 -15
  56. package/skeleton/app/src/start.ts +0 -9
package/CHANGELOG.md CHANGED
@@ -4,6 +4,206 @@ 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.8.0
8
+
9
+ ### Changes
10
+
11
+ SDK:
12
+
13
+ - New repositories use SDK 0.6.0 (`@sempods/app-sdk` and
14
+ `@sempods/client-sdk`), and `@sempods/apps` supports `^0.6.0`. The 0.6.0
15
+ release notes and migration guide name what changes for apps: among others,
16
+ `AppShell` and `ConnectionControls` are gone, row commands move to
17
+ `mutate.for(item)`, SDK texts follow the browser language, lists keep their
18
+ rows while reloading, a cancelled re-authorization keeps the session, and
19
+ the leave confirmation shows above app dialogs.
20
+ - After an SDK update, `sdk-update` and the app workflow point to the
21
+ installed release notes and migration guide
22
+ (`node_modules/@sempods/app-sdk/docs/releases/<version>.md`, `migration.md`)
23
+ instead of GitHub, and the workflow skips a section on adopting the release
24
+ in the apps template.
25
+
26
+ Look:
27
+
28
+ - Four themes in the skeleton's `src/themes/`: calm (the default, graphite on
29
+ white), fresh (teal), warm (terracotta on cream) and playful (violet). Each
30
+ sets the six `--sempods-*` colour tokens in light and dark mode with at
31
+ least 4.5:1 contrast, which a test checks; the SDK components read the same
32
+ tokens, so a theme restyles the whole app. Fonts and corner radii stay the
33
+ SDK's. An app imports one theme in `src/main.tsx`; `new-app --theme <name>`
34
+ chooses it.
35
+ - The skeleton's `src/index.css` styles only the app's own markup and leaves
36
+ SDK components (`[data-sempods-ui]`) alone, so `AppAccess` keeps its
37
+ layout. App buttons read as text in the accent colour with a calm hover, a
38
+ visible focus and 44px touch targets. Inputs have 44px targets; checkboxes
39
+ and radios are a compact 24px box whose wrapping `<label>` is the 44px
40
+ target, as in the SDK. Lists lose the browser's indentation and bullets.
41
+ - The page's `theme-color` follows light and dark mode, and the generated web
42
+ app manifest uses a white background and theme colour instead of green.
43
+ - `new-app` draws the app icon as a monogram, the title's first letter on a
44
+ rounded square in the theme's accent, instead of a plain green square:
45
+ `public/favicon.svg` (in the theme's dark accent in dark mode) and the
46
+ manifest icons `icon-192.png` and `icon-512.png`, all from the same strokes.
47
+ A title that does not start with a letter A–Z, accents aside, gets the plain
48
+ square. `pnpm run icon <id>` (new) draws it again after a rename or a theme
49
+ change.
50
+ - The skeleton's header shows the app's icon and name, room for the app's
51
+ icon actions and a menu (⋮) whose "Pods & sharing" opens `AppAccess`
52
+ management as its dialog (`onClose`), with signing out inside. It replaces
53
+ the "Data access" button. `AppAccess` shows the icon and the app's
54
+ description on the sign-in screen, `<AccessNotice only="write" />` beside it
55
+ says when a context is shared read-only, and the viewport adds
56
+ `viewport-fit=cover` and `interactive-widget=resizes-content`.
57
+ - The skeleton has a small UI kit in `src/ui/`, styled by `ui.css` on the
58
+ `--sempods-*` tokens: `Menu` (a button with a list of actions or choices;
59
+ Escape, a press outside and the arrow keys), `ContextSwitch` (the everyday
60
+ switch between the contexts shared with the app over the SDK's
61
+ `useContexts`, in place of the header's `<h1>`), `Tabs` (views as links with
62
+ their routes), `Composer` (an input bar fixed at the bottom, above the home
63
+ indicator and, where browsers support it, the on-screen keyboard), `Dialog`
64
+ (modal, a bottom sheet on phones, for example around a `ResourceEditor`)
65
+ and line icons.
66
+ - The skeleton ships `src/examples/ListScreen.tsx`, not mounted: the SDK's
67
+ quickstart screen built with the kit (loading and failed reads, an empty
68
+ state, rows with a labelled checkbox, the item's `ResourceEditor` in a
69
+ `Dialog`, `RemoveButton`, open outcomes and a `Composer`, which a list the
70
+ person can only read does not show). It compiles with every app, so it
71
+ stays valid against the SDK.
72
+
73
+ Content and configuration:
74
+
75
+ - Apps are international by default. `language` in `apps.json` accepts
76
+ `"auto"`, and `new-app` uses it unless `--language de` or `en` fixes one
77
+ language. The skeleton resolves the UI language and locale from the browser
78
+ with the SDK's `resolveLocale` (German or English, otherwise English, with
79
+ the browser's region for formats), passes both to `SempodsProvider` and
80
+ sets `<html lang>`. For `"auto"` the generated configuration keeps
81
+ `app.language` as `"auto"`, the manifest has no `lang` and the overview
82
+ announces no language for the app.
83
+ - The skeleton keeps the app's own texts in `src/texts.ts`, one typed
84
+ catalogue per language, read with the SDK's `useMessages(texts)` and tested
85
+ in `src/texts.test.ts`; `src/start.ts` and its test are gone.
86
+ - The app title has one source, `apps.json`. The generated
87
+ `vite.sempods.generated.ts` exports the Vite plugin `pageTitle`, which adds
88
+ the title to the head of the served and built page; the skeleton's
89
+ `vite.config.ts` uses it and its `index.html` has no `<title>` of its own.
90
+ `check` reports a page with its own title and a `vite.config.ts` without
91
+ the plugin.
92
+ - `apps.json` accepts an optional `description` (one short sentence), set by
93
+ `new-app --description`. It becomes the generated `app.description`, which
94
+ the skeleton passes to `AppAccess`, the manifest's `description` and the
95
+ overview card's line.
96
+ - Apps can give their views addresses: `routes` in an app's `apps.json` entry
97
+ lists lowercase English segments, for example `"routes": ["bought"]` for
98
+ `/<id>/bought`. The generated `app.routes` lists them, and `build-site`
99
+ writes `<id>/<route>.html`, so the published site answers each route
100
+ without a rewrite and unknown paths still show the not-found page. The
101
+ service worker serves the cached app for the start page and every route,
102
+ and the generated `returnTo` is a function the runtime calls when each
103
+ sign-in starts, so sign-in returns to the route the person is on.
104
+ - The skeleton's `src/routes.ts` provides `useRoute()`: the current route,
105
+ `link(route)` for an `<a>` to it and `go(route)`, which switches views under
106
+ the SDK's leave policy (`useApp().navigate`); back and forward are guarded
107
+ the same way, and staying keeps the view and its address. It shows unknown
108
+ paths as the start page and drops a trailing slash. The runtime's
109
+ `replaceUrl` goes through it, so the return after a sign-in shows the right
110
+ view.
111
+ - `migrate` moves existing apps where that is unambiguous: a `vite.config.ts`
112
+ unchanged from the skeleton gets the `pageTitle` plugin, and a page whose
113
+ only title is the app's title from `apps.json` loses it. It does so, and
114
+ regenerates the apps, also for a release whose starter is unchanged. A page
115
+ or `vite.config.ts` that is a symbolic link stops `update` and `migrate`
116
+ before they change anything.
117
+
118
+ Instructions:
119
+
120
+ - App planning settles purpose, personal versus shared data and context
121
+ access limits before generation, with at most three short questions at a
122
+ time. The assistant proposes layout, theme, name and icon; a vague request
123
+ need not wait for visual choices. Decisions go into the app's `NOTES.md`.
124
+ - The workflow chooses reusable data mappings from existing data and
125
+ established vocabularies, preserving identities and fields other apps use.
126
+ If the owner wants, optional read-only inspection through a connected MCP
127
+ Pod informs this choice within an agreed scope. Setup and the user guide
128
+ explain that MCP is optional and separate from signing in to the app;
129
+ app trials still use synthetic data in dedicated test contexts.
130
+ - Before generation, the workflow settles what the app reads, where new
131
+ records go and where existing records are edited: one context, several one
132
+ at a time, read all and write in one, edit overview rows in their source
133
+ contexts, or write into several. It starts from the installed SDK's path
134
+ for that shape. The skeleton's notes record Data and Vocabulary decisions,
135
+ including observed mappings and assumptions still to verify. Setup asks
136
+ for one test context per context the shape uses.
137
+ - The app workflow starts a list from the list example, takes only behaviour
138
+ from the SDK's examples, deletes rows with `RemoveButton`, relies on the
139
+ SDK's list refresh when the page becomes visible again, adds kit parts only
140
+ when the app needs them, and describes routes, renaming and themes. It is
141
+ reordered: planning, optional data inspection, context shape, vocabulary,
142
+ `new-app`, screen, views, configuration.
143
+ - A visual check before handover (`instructions/visual-check.md`): the
144
+ assistant takes screenshots at 375px and desktop width, light and dark, with
145
+ real states (empty, a few items, an open item, a notice), checks them
146
+ against a short checklist, fixes what fails and shows the owner the 375px
147
+ screenshot for a verdict. The app workflow and setup require it; visual
148
+ checks are their own kind of evidence in `NOTES.md`. The docs no longer say
149
+ the screen can be tried without a Pod: only the sign-in screen can.
150
+ - The setup record of new repositories names "Test Pod and contexts" and the
151
+ owner's language for the app texts.
152
+
153
+ ### Upgrade notes
154
+
155
+ 1. The migration does by itself: it adds the root script `icon`, regenerates
156
+ every app (`app.routes`, `app.description` as `null` until set, the
157
+ manifest colours, the `pageTitle` plugin, the service worker's allowlist
158
+ for routes), moves apps to the generated page title where that is
159
+ unambiguous and replaces the viewport and green `theme-color` lines an
160
+ app's `index.html` kept from the 0.7 skeleton, listed under "Updated". For
161
+ any other app, `check` names what is left: add `pageTitle` from
162
+ `./vite.sempods.generated.ts` to the plugins in its `vite.config.ts`, as
163
+ the skeleton does, and remove the `<title>` from its `index.html`. A page title other than the one in `apps.json` was
164
+ chosen by hand: ask the owner whether it should be the app's title, put it
165
+ into `apps.json` and run `pnpm run regenerate`. Settle these cases before
166
+ the SDK move: `sdk-update` ends with `check` and stops on them.
167
+ 2. Then move the repository to SDK 0.6.0, on its own branch:
168
+ `pnpm run sdk-update 0.6.0`. Until then `check` reports the SDK as outside
169
+ the supported range, and apps created by `new-app` would use the old SDK
170
+ with a skeleton written for 0.6.0. Then follow the SDK's migration
171
+ checklist (`node_modules/@sempods/app-sdk/docs/migration.md`, "From 0.5.0
172
+ to 0.6.0") for each app: replace `AppShell`/`ConnectionControls` with the
173
+ skeleton's layout, move row commands to `mutate.for(item)`, handle
174
+ `not-sent` results, and check texts and dialogs that tests match. Run
175
+ `pnpm run check --standalone all` and list for the owner what to try on the
176
+ Pod: sign-in, reload, editing, guarded navigation and recovery.
177
+ 3. Existing apps keep their code, look and notes. When working on an app next,
178
+ offer what the owner wants of the new skeleton, from
179
+ `node_modules/@sempods/apps/skeleton/app/`, once the repository is on SDK
180
+ 0.6.0:
181
+ - a theme: copy `src/themes/`, import the chosen one in `src/main.tsx`
182
+ before `index.css`, remove the token block from `index.css`, and run
183
+ `pnpm run icon <id>` for a monogram in its accent;
184
+ - the scoped CSS rules of `src/index.css`, where the app still has global
185
+ `header`, `button`, `input` or `select` rules: they stop shifting the
186
+ sign-in form and placing the `AppAccess` icon beside its title;
187
+ - the header with icon, name and menu, `src/ui/` and `AppAccess` with
188
+ `icon`, `description` and `onClose`, with their texts in `src/texts.ts`;
189
+ - routes, for an app that switches views by itself: copy `src/routes.ts`
190
+ and `src/routes.test.ts`, pass `replaceUrl` to `createBrowserRuntime` as
191
+ `src/App.tsx` does, list the routes in `apps.json` and run
192
+ `pnpm run regenerate`; an app that rewrote its address after a sign-in
193
+ can drop that code;
194
+ - the browser's language: set `language` to `"auto"` in `apps.json`, run
195
+ `pnpm run regenerate` and adopt `uiLocale` from `src/texts.ts` in
196
+ `src/App.tsx` (passed as `language` and `locale`, and
197
+ `document.documentElement.lang`), because `app.language` is then
198
+ `"auto"`; read the app's texts from a catalogue with both languages
199
+ through `useMessages`;
200
+ - Design, Data and Vocabulary sections in `NOTES.md`, following the app
201
+ workflow. Check personal/shared access assumptions, reuse of existing
202
+ data and the separate destinations of new records and edits. Offer MCP
203
+ inspection only when existing data is relevant and the owner wants it;
204
+ record unverified assumptions when it is skipped. These instructions
205
+ do not migrate existing Pod data.
206
+
7
207
  ## 0.7.1
8
208
 
9
209
  ### Changes
package/README.md CHANGED
@@ -12,6 +12,8 @@ Create a repository with `pnpm create @sempods/apps <directory>`
12
12
  `package.json` runs the other commands through `sempods-apps <command>`:
13
13
 
14
14
  - `pnpm run new-app <id>` creates `apps/<id>` with the root's SDK version.
15
+ - `pnpm run icon <id>` draws an app's monogram icon again in its theme's
16
+ accent.
15
17
  - `pnpm run dev <id>` starts that app.
16
18
  - `pnpm run regenerate` rewrites every app's generated configuration from
17
19
  `apps.json`, for example after a tooling update.
@@ -32,9 +34,10 @@ Create a repository with `pnpm create @sempods/apps <directory>`
32
34
 
33
35
  Contents:
34
36
 
35
- - `instructions/`: the setup procedure, the app workflow and the publish
36
- guide; `skills/` holds the skill entries that route to them.
37
- - `skeleton/app/`: what a new app starts from. Files named `*.generated.ts` in
37
+ - `instructions/`: the setup procedure, the app workflow, the visual check and
38
+ 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
38
41
  an app are written from `apps.json`; do not edit them. `check` reports any
39
42
  difference, and `regenerate` rewrites them.
40
43
  - `shared/`: the starter of this release, its files stored by content hash in
@@ -7,6 +7,7 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
7
7
  const COMMANDS = {
8
8
  create: 'create a new apps repository from the starter',
9
9
  'new-app': 'create apps/<id> and add it to apps.json',
10
+ icon: "draw an app's monogram icon again in its theme's accent",
10
11
  dev: 'start the development server of one app',
11
12
  regenerate: "rewrite every app's generated configuration from apps.json",
12
13
  'configure-site': 'record where the apps are published',