create-foldkit-app 0.20.1 → 0.21.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.
package/README.md CHANGED
@@ -38,6 +38,7 @@ The CLI prompts you for a project name, starter example, and package manager. Pa
38
38
  | `generative-art` | Perlin-noise flow field with evolving particle trails, mouse vortex, and high-frequency Messages |
39
39
  | `auth` | Authentication with Submodels, OutMessage, and protected routes |
40
40
  | `shopping-cart` | Complex state management with nested Models and routing |
41
+ | `checkout-machine` | Experimental state machine checkout with guarded branches and edge Commands |
41
42
  | `pixel-art` | Pixel editor with undo/redo, UI components, and localStorage persistence |
42
43
  | `websocket-chat` | Managed resources with WebSocket integration |
43
44
  | `managed-resource-layer` | Layer-backed ManagedResource lifecycle with an Effect service |
package/dist/examples.js CHANGED
@@ -11,12 +11,14 @@ export const EXAMPLE_VALUES = [
11
11
  'api-cache',
12
12
  'charting',
13
13
  'routing',
14
+ 'route-transitions',
14
15
  'query-sync',
15
16
  'snake',
16
17
  'canvas-art',
17
18
  'generative-art',
18
19
  'auth',
19
20
  'shopping-cart',
21
+ 'checkout-machine',
20
22
  'pixel-art',
21
23
  'websocket-chat',
22
24
  'managed-resource-layer',
@@ -87,6 +89,11 @@ export const examples = [
87
89
  title: 'routing',
88
90
  description: 'URL routing with parser combinators and route parameters',
89
91
  },
92
+ {
93
+ value: 'route-transitions',
94
+ title: 'route-transitions',
95
+ description: 'Live transition log with entry, exit, and stayed navigation policies',
96
+ },
90
97
  {
91
98
  value: 'query-sync',
92
99
  title: 'query-sync',
@@ -117,6 +124,11 @@ export const examples = [
117
124
  title: 'shopping-cart',
118
125
  description: 'Complex state management with nested models and routing',
119
126
  },
127
+ {
128
+ value: 'checkout-machine',
129
+ title: 'checkout-machine',
130
+ description: 'Checkout workflow powered by the experimental state machine module with guarded branches and edge Commands',
131
+ },
120
132
  {
121
133
  value: 'pixel-art',
122
134
  title: 'pixel-art',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-foldkit-app",
3
- "version": "0.20.1",
3
+ "version": "0.21.1",
4
4
  "description": "Create Foldkit applications",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -12,15 +12,15 @@
12
12
  "templates"
13
13
  ],
14
14
  "dependencies": {
15
- "@effect/platform-node": "4.0.0-beta.88",
16
- "@effect/platform-node-shared": "4.0.0-beta.88",
15
+ "@effect/platform-node": "4.0.0-beta.97",
16
+ "@effect/platform-node-shared": "4.0.0-beta.97",
17
17
  "chalk": "^5.6.2",
18
- "effect": "4.0.0-beta.88",
18
+ "effect": "4.0.0-beta.97",
19
19
  "rimraf": "^6.1.3",
20
20
  "typescript": "^6.0.3"
21
21
  },
22
22
  "devDependencies": {
23
- "@effect/vitest": "4.0.0-beta.88",
23
+ "@effect/vitest": "4.0.0-beta.97",
24
24
  "@types/node": "^25.9.3",
25
25
  "vitest": "^4.1.9"
26
26
  },
@@ -1,12 +1,7 @@
1
1
  {
2
2
  "$schema": "./node_modules/oxlint/configuration_schema.json",
3
+ "extends": ["./node_modules/@foldkit/oxlint-plugin/recommended.json"],
3
4
  "plugins": ["typescript"],
4
- "jsPlugins": [
5
- {
6
- "name": "foldkit",
7
- "specifier": "@foldkit/oxlint-plugin"
8
- }
9
- ],
10
5
  "categories": {
11
6
  "correctness": "off"
12
7
  },
@@ -24,15 +19,7 @@
24
19
  "typescript/consistent-type-assertions": [
25
20
  "error",
26
21
  { "assertionStyle": "never" }
27
- ],
28
- "foldkit/no-noop-message": "error",
29
- "foldkit/got-submodel-message-name": "error",
30
- "foldkit/message-binding-matches-tag": "error",
31
- "foldkit/got-prefix-requires-submodel-payload": "error",
32
- "foldkit/no-empty-object-tagged-call": "error",
33
- "foldkit/prefer-callable-message-constructor": "error",
34
- "foldkit/command-binding-matches-name": "error",
35
- "foldkit/no-module-level-mutable-state": "error"
22
+ ]
36
23
  },
37
24
  "ignorePatterns": [
38
25
  "dist/",
@@ -54,7 +54,7 @@ Use `evo()` from `foldkit/struct` for immutable model updates. Never spread or `
54
54
 
55
55
  Bind the `html` factory inside each view function with `const h = html<Message>()` (never at module level), then reach for `h.div`, `h.OnClick`, etc. off the returned record. Use `empty` (not `null`) for conditional rendering, `M.value().pipe(M.tagsExhaustive({...}))` for discriminated unions, and `Array.match` for lists that may be empty.
56
56
 
57
- Use `keyed` wrappers whenever the view branches into structurally different layouts based on route or model state. Without keying, the virtual DOM tries to diff one layout into another, causing stale DOM and event handler mismatches.
57
+ Key every view branch based on route or model state, even when the branch root tags differ. Key inline branch roots directly (never a wrapper introduced only to carry a key); when the branches delegate to other view functions, key a single wrapper at the branch site with the discriminating key, for example `h.keyed('div')(model.route._tag, [], [routeContent])`. Without keying, the virtual DOM tries to diff one layout into another, causing stale DOM and event handler mismatches.
58
58
 
59
59
  ### Commands
60
60
 
@@ -66,7 +66,9 @@ For DOM operations (focus, scroll, modals, scroll lock), Foldkit ships a `Dom` m
66
66
 
67
67
  ### File Organization
68
68
 
69
- A Foldkit app lives in two files. `src/main.ts` holds the pure definitions (Model, Messages, init, update, view). `src/entry.ts` imports them and boots the runtime with `Runtime.makeApplication` and `Runtime.run`. `index.html` references `entry.ts`. The split keeps `main.ts` importable from tests without booting a runtime as a side effect. Never call `Runtime.run` from `main.ts`.
69
+ The invariant: keep the runtime boot separate from the pure definitions. `src/entry.ts` calls `Runtime.makeApplication` and `Runtime.run`, and `index.html` references it. The definitions (Model, Messages, init, update, view, Commands) never call `Runtime.run`, so they stay importable from tests without booting a runtime as a side effect. Never call `Runtime.run` from `main.ts`.
70
+
71
+ For a small app the definitions all fit in one `src/main.ts`. Split a unit into its own file when it has _both_ a distinct reason to change _and_ a name you'd give it unprompted: the pure domain core into `timer.ts` or `domain.ts`, the view into `view.ts` (or a `components/` directory), a Command's owned resource into its own module. Split on that revealed seam, not on line count alone. A file that has grown large is _evidence_ a seam has formed, so treat its size as a prompt to re-check for one. Two splits are forced: extract Messages to `message.ts` when Commands need the constructors (this breaks the cycle between `command.ts` and `main.ts`), and colocate Commands with the update that returns them. Exemplars: counter and stopwatch are a single `main.ts`; kanban splits `domain` / `command` / `message` / `model`; typing-game splits views by page.
70
72
 
71
73
  Use uppercase section headers (`// MODEL`, `// MESSAGE`, `// INIT`, `// UPDATE`, `// COMMAND`, `// VIEW`) for wayfinding.
72
74