Skip to content

Commit e20864f

Browse files
committed
docs(create-objectstack): say what the wired starter ships, and walk a chain that composes
The starter's tree, config and agent guide, the package README, the Your First Project page and the CLI page described an objects-only starter. They now name the seven wired barrels, `exportsOf` and the `triggers` requirement. The CLI page's first-app walkthrough generated an action bound to an object nobody declared; on the wired starter that is refused, so the walkthrough now binds the flow and the action to the object it creates. Claude-Session: https://claude.ai/code/session_01UYBdGBzWSrAMzpW8ah3GbP Co-authored-by: Claude <noreply@anthropic.com>
1 parent 40309ff commit e20864f

7 files changed

Lines changed: 90 additions & 23 deletions

File tree

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
'create-objectstack': patch
3+
---
4+
5+
fix(create-objectstack): the blank starter wires every directory `os generate` writes into
6+
7+
`npm create objectstack` scaffolded an `objectstack.config.ts` that imported `./src/objects` alone. `os g view`, `action`, `flow`, `dashboard`, `app` and `skill` each wrote a file and a barrel `index.ts` that nothing imported, and `os validate` then exited 0 printing `Logic: 0 Flows`: the generated metadata was never loaded.
8+
9+
**What a new blank project now ships** is the wiring `os init` writes:
10+
11+
- `objectstack.config.ts` imports every directory `os generate` writes into (`src/objects`, `src/views`, `src/actions`, `src/flows`, `src/dashboards`, `src/apps`, `src/skills`) and hands each barrel's exports to `defineStack` under its key (`objects`, `views`, …). A file `os g` writes there is part of the stack with no edit to the config. The keys read the barrels through a small `exportsOf` helper declared in the config, because `Object.values` on an empty barrel does not type-check against `defineStack`'s collection types.
12+
- An `index.ts` containing only `export {};` in each of those directories except `src/objects`, which keeps the sample object.
13+
- `requires: ['automation', 'triggers']`. `automation` was already there for the three connector plugins. `triggers` fires a flow that starts on a record change, the kind `os g flow` writes, and without it the config stops loading as soon as it holds one. A project with no flow boots as before.
14+
15+
**Projects scaffolded by an earlier release** keep their config. `os g` says when a file it wrote is not wired, and prints the lines to add.

‎content/docs/deployment/cli.mdx‎

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,15 @@ This scaffolds a working project with `objectstack.config.ts`, a sample object,
3333

3434
```bash
3535
os generate object customer # Add a Customer object
36-
os generate action approve # Add an action
37-
os generate flow onboarding # Add an automation flow
36+
os generate flow customer # Add an automation flow on it
37+
os generate action customer # Add an action on it that runs the flow
3838
```
3939

40+
Each command writes a file and its export line, and the starter's config already
41+
wires every directory they write into, so all three are part of the stack. The
42+
flow and the action bind to the object named like them, which is why the object
43+
comes first: an action bound to an object the stack does not declare is refused.
44+
4045
### Launch the dev server
4146

4247
```bash
@@ -739,8 +744,8 @@ the view and the action listed under
739744
renamed out of that page's `support_desk_` namespace into `my_app_`. That page's `support`
740745
app is **not** added, and a zero count is never printed, which is why the `UI:` row reads
741746
`1 Views 1 Actions` with no `Apps`. The walkthrough's `os generate` commands are **not**
742-
part of the fixture — run those as well and the summary gains `my_app_customer` and a
743-
`Logic:` row. Timings are machine identity, and the rule count and artifact size track the
747+
part of the fixture — run those as well and the summary gains `my_app_customer`, a second
748+
action and a `Logic:` row. Timings are machine identity, and the rule count and artifact size track the
744749
CLI version; everything else is fixture identity and reproduces.
745750
</Callout>
746751
@@ -1410,7 +1415,8 @@ else a scaffold names (an action's, flow's or app's own `name`) is prefixed.
14101415
14111416
**Every scaffold reaches the stack, or the command says it does not.** The
14121417
`objectstack.config.ts` that `os init` writes for the `app` and `plugin`
1413-
templates wires every directory in the table below: it imports each
1418+
templates, and the one the `npm create objectstack` starter ships, wires every
1419+
directory in the table below: it imports each
14141420
`src/<dir>/index.ts` barrel and hands its exports to `defineStack` under the key
14151421
in the **Collected as** column, so a file `os g` writes there is part of the
14161422
stack with no edit to the config. It also declares
@@ -1421,8 +1427,8 @@ After writing, `os g` loads the config again and says which of these holds:
14211427
checks it.
14221428
- **Not wired**: the config loads and its stack does not carry the item, or
14231429
there is no config. This is what happens with a config that imports
1424-
`./src/objects` alone, as `os init` projects from earlier releases and the
1425-
`npm create objectstack` starter do. The file is written, the config is left
1430+
`./src/objects` alone, as projects that `os init` and `npm create objectstack`
1431+
scaffolded in earlier releases do. The file is written, the config is left
14261432
as it was, and the command prints the import and the `defineStack` key that
14271433
wire the directory.
14281434
- **Cannot run**: the stack carries a flow, and its `requires` lacks

‎content/docs/getting-started/your-first-project.mdx‎

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -91,22 +91,41 @@ my-app/
9191
├── tsconfig.json
9292
├── AGENTS.md # conventions for coding agents
9393
└── src/
94-
└── objects/
95-
├── index.ts # barrel — re-exports every object
96-
└── note.object.ts # a sample object
94+
├── objects/
95+
│ ├── index.ts # barrel — re-exports every object
96+
│ └── note.object.ts # a sample object
97+
├── views/index.ts # an empty barrel for each directory
98+
├── actions/index.ts # `os generate` writes into, already
99+
├── flows/index.ts # wired into objectstack.config.ts
100+
├── dashboards/index.ts
101+
├── apps/index.ts
102+
└── skills/index.ts
97103
```
98104

99105
Two files matter most:
100106

101107
**`objectstack.config.ts`** wires everything together. There is no
102-
filename-suffix magic — metadata exists in the app only if it is imported here:
108+
filename-suffix magic — metadata exists in the app only if it is imported here.
109+
Every directory `os generate` writes into is already imported, so a generated
110+
view, action or flow adds a file and one export line to its directory's
111+
`index.ts` and is part of the stack with no edit to this file:
103112

104113
```typescript title="objectstack.config.ts"
105114
import { defineStack } from '@objectstack/spec';
106115
import { ConnectorRestPlugin } from '@objectstack/connector-rest';
107116
import { ConnectorOpenApiPlugin } from '@objectstack/connector-openapi';
108117
import { ConnectorMcpPlugin } from '@objectstack/connector-mcp';
109-
import * as objects from './src/objects/index.js';
118+
import * as objects from './src/objects';
119+
import * as views from './src/views';
120+
import * as actions from './src/actions';
121+
import * as flows from './src/flows';
122+
import * as dashboards from './src/dashboards';
123+
import * as apps from './src/apps';
124+
import * as skills from './src/skills';
125+
126+
// Object.values, typed by what the barrel exports, so an empty barrel still
127+
// type-checks.
128+
const exportsOf = <M extends object>(barrel: M): M[keyof M][] => Object.values(barrel);
110129

111130
export default defineStack({
112131
manifest: {
@@ -120,14 +139,22 @@ export default defineStack({
120139
},
121140
// `automation` runs flows and, per ADR-0097, materializes declarative
122141
// `connectors:` entries at boot. The three generic executors below register
123-
// their `rest` / `openapi` / `mcp` provider factories with it.
124-
requires: ['automation'],
142+
// their `rest` / `openapi` / `mcp` provider factories with it. `triggers`
143+
// fires a flow that starts on a record change, the kind `os generate flow`
144+
// writes.
145+
requires: ['automation', 'triggers'],
125146
plugins: [
126147
new ConnectorRestPlugin(),
127148
new ConnectorOpenApiPlugin(),
128149
new ConnectorMcpPlugin(),
129150
],
130-
objects: Object.values(objects),
151+
objects: exportsOf(objects),
152+
views: exportsOf(views),
153+
actions: exportsOf(actions),
154+
flows: exportsOf(flows),
155+
dashboards: exportsOf(dashboards),
156+
apps: exportsOf(apps),
157+
skills: exportsOf(skills),
131158
});
132159
```
133160

‎packages/create-objectstack/README.md‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,15 @@ my-app/
7777
├── README.md
7878
├── AGENTS.md # conventions for coding agents
7979
└── src/
80-
└── objects/
81-
├── index.ts
82-
└── note.object.ts
80+
├── objects/
81+
│ ├── index.ts
82+
│ └── note.object.ts
83+
├── views/index.ts # an empty barrel for each directory
84+
├── actions/index.ts # `objectstack generate` writes into,
85+
├── flows/index.ts # already wired into objectstack.config.ts
86+
├── dashboards/index.ts
87+
├── apps/index.ts
88+
└── skills/index.ts
8389
```
8490

8591
Next steps inside the project:

‎packages/create-objectstack/src/starter-comments-self-contained.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ const MONOREPO_ONLY = [
142142
// "the shallowest point a path reaches"). In THIS population the two give
143143
// the same answer, for a measured reason: every relative reference the
144144
// shipped tree carries is `./`-anchored and points DOWNWARD from the file
145-
// that writes it (`./note.object.js`, `./src/objects/index.js`), so the
145+
// that writes it (`./note.object.js`, `./src/objects`), so the
146146
// count of `../` here — escaping or merely climbing — is zero. The bare
147147
// anchor therefore has no correct text to redden. The leading lookbehind is
148148
// what keeps it that way: it refuses a `..` that is itself part of a longer

‎packages/create-objectstack/src/templates/AGENTS.md‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,11 @@ Run `npm run build` when you need the compiled `dist/objectstack.json` artifact.
4646

4747
1. **Zod First** — All schema definitions start with Zod. Types are derived via `z.infer<>`.
4848
2. `defineStack()` is the single configuration entry point in `objectstack.config.ts`.
49-
3. Use `Object.values()` barrel pattern for metadata arrays.
49+
3. Metadata reaches the stack through barrels: each `src/*/index.ts` exports what its
50+
directory holds, and `objectstack.config.ts` already hands every barrel to
51+
`defineStack()` through `exportsOf()` — a typed `Object.values()` that still
52+
type-checks while a barrel is empty, so keep it. Export a new file from its barrel
53+
rather than adding a key for it.
5054
4. Import from `@objectstack/spec` — never use relative paths into the spec package.
5155
5. **Predicates are CEL** — `visible`, `disabled`, `requiredWhen`, validation rules,
5256
flow conditions and sharing rules reference record fields as `record.<field>`,

‎packages/create-objectstack/src/templates/blank/README.md‎

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,10 @@ the whole time — the `curl` above returns it, and an MCP client can read and
3838
write it. What it has no route into is the Console's navigation.
3939

4040
**An object appears in Console navigation only when an app lists it.** Add an
41-
`*.app.ts` under `src/apps/` (plus the views it points at), and the Console
42-
renders it after the next `pnpm dev` rebuild. The `objectstack-ui` skill covers
41+
`*.app.ts` under `src/apps/` (plus the views it points at), export each one from
42+
its directory's `index.ts`, and the Console renders it after the next `pnpm dev`
43+
rebuild. `objectstack generate app NAME` and `objectstack generate view NAME`
44+
write the file and its export line together. The `objectstack-ui` skill covers
4345
the shape; describing the app you want to your coding agent is the intended
4446
path.
4547

@@ -63,8 +65,15 @@ for OAuth, API keys, and which objects/actions become tools.
6365

6466
## Layout
6567

66-
- `objectstack.config.ts` — environment manifest (objects, API, plugins)
68+
- `objectstack.config.ts` — environment manifest (objects, API, plugins), and
69+
the wiring for every directory below
6770
- `src/objects/` — object definitions (one file per object)
71+
- `src/views/`, `src/actions/`, `src/flows/`, `src/dashboards/`, `src/apps/`,
72+
`src/skills/` — empty to start. Each directory's `index.ts` exports what it
73+
holds and `objectstack.config.ts` hands those exports to the stack, so
74+
`objectstack generate flow NAME` (or `view`, `action`, …) adds a file and one
75+
export line, and the item is loaded, and counted by `pnpm validate`, with no
76+
edit to the config
6877

6978
## Connectors (default providers)
7079

0 commit comments

Comments
 (0)