@owlmeans/create-app 0.1.18-rc.17 → 0.1.18-rc.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 CHANGED
@@ -65,8 +65,9 @@ is present even with `--no-install`.
65
65
  `--bare` keeps the three workspaces, the config/context/entrypoint wiring, the layout, the nav
66
66
  skeleton and one Home screen, and drops every piece of example code — the `SessionItem` types and
67
67
  schemas, the api's `app/session/**` handlers and its static resource, the About and Session screens.
68
- `sources/common/src/entrypoints.ts` exports an empty `sharedEntrypoints` that the api and the web
69
- already spread, so the first feature is one declaration plus a handler and a screen.
68
+ `sources/common/src/entrypoints.ts` exports an immutable `appEntrypoints` tree with an empty `api`
69
+ branch and the web routes. The API and web bind those branches locally, so the first feature adds a
70
+ declaration to the tree, then a handler and a screen binding.
70
71
 
71
72
  What bare removes and what it swaps in is declared in `template/_bare.json`, next to the
72
73
  `.bare.`-infixed variants it points at — not in the scaffolder's code.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owlmeans/create-app",
3
- "version": "0.1.18-rc.17",
3
+ "version": "0.1.18-rc.19",
4
4
  "license": "MIT",
5
5
  "description": "Scaffold a fullstack OwlMeans Common app — common + api + web workspaces, shadcn UI navigation/layout, no auth, and a session-scoped in-memory resource, or --bare for the demo-free shell. Also usable programmatically via scaffold(). Deploys agent skills via @owlmeans/agent-skills by default.",
6
6
  "type": "module",
@@ -30,7 +30,7 @@
30
30
  "template"
31
31
  ],
32
32
  "dependencies": {
33
- "@owlmeans/agent-skills": "^0.1.18-rc.14"
33
+ "@owlmeans/agent-skills": "^0.1.18-rc.15"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@owlmeans/dep-config": "workspace:*",
@@ -34,10 +34,10 @@ bun run dev
34
34
  1. **`sources/common/src/entrypoints.ts`** — declare the route as an OwlMeans *entrypoint* and
35
35
  give it an AJV filter. Both sides import this one declaration; neither re-declares the route.
36
36
  2. **`sources/api`** — register a resource in `src/context.ts` (widening `Context` in
37
- `src/types.ts`), then `elevate()` the entrypoint with a handler in `src/entrypoints.ts`.
37
+ `src/types.ts`), then `bind()` the entrypoint with a handler in `src/entrypoints.ts`.
38
38
  3. **`sources/web`** — add a screen under `src/screens`, hang it off a frontend route in
39
39
  `src/entrypoints.ts`, list it in `src/nav.ts`, and call the backend with
40
- `context.entrypoint(alias).call({ params, body })`.
40
+ `context.entrypoint(protocol).call({ params, body })`.
41
41
 
42
42
  See the [OwlMeans getting-started guide](https://github.com/owlmeans/common/blob/main/docs/getting-started.md)
43
43
  for a worked example of all three steps.
@@ -2,71 +2,8 @@
2
2
 
3
3
  __APP_DESCRIPTION__
4
4
 
5
- A minimal fullstack [OwlMeans Common](https://github.com/owlmeans/common) app, scaffolded with
6
- [`@owlmeans/create-app`](https://www.npmjs.com/package/@owlmeans/create-app).
5
+ An OwlMeans application has shared protocol declarations in `sources/common`, server bindings in
6
+ `sources/api`, and browser bindings/screens in `sources/web`. Contracts, request schemas, guards
7
+ and gates are declared once in common; runtime packages bind them without changing the declaration.
7
8
 
8
- No authentication; session data lives in an **in-memory static resource** on the backend.
9
-
10
- ## Workspaces
11
-
12
- ```
13
- sources/
14
- ├── common/ # shared entrypoints (routes), schemas and types — used by api AND web
15
- ├── api/ # @owlmeans/server-app backend; session items in @owlmeans/static-resource
16
- └── web/ # @owlmeans/web-panel + shadcn UI: navigation, layout and screens
17
- ```
18
-
19
- ## Develop
20
-
21
- ```sh
22
- bun install
23
- bun run dev
24
- ```
25
-
26
- - API: http://localhost:3000
27
- - Web: http://localhost:3001
28
-
29
- Open the **Session** page and add/remove items — they are stored per browser session
30
- (a `sid` kept in `localStorage`) in an in-memory resource on the API. Restarting the API
31
- clears them; opening a different browser/incognito window gets an isolated session.
32
-
33
- > **Note:** The API runs over plain HTTP in dev (`cfg.security = { unsecure: true }` in
34
- > `sources/common/src/config.ts`). If you edit `sources/common`, restart `bun run dev` to
35
- > rebuild it before the API and web pick up the changes.
36
-
37
- ## How it fits together
38
-
39
- 1. **`sources/common`** declares the API routes as OwlMeans *entrypoints* (`session.list`,
40
- `session.add`, `session.remove`) plus their AJV schemas and shared types.
41
- 2. **`sources/api`** registers a `@owlmeans/static-resource` in its context and `elevate()`s
42
- each entrypoint with a handler that does CRUD against it, keyed by the session id.
43
- 3. **`sources/web`** `elevate()`s the same entrypoints to screen components and calls them with
44
- `context.entrypoint(alias).call({ params, body })`.
45
-
46
- See [OwlMeans getting-started guide](https://github.com/owlmeans/common/blob/main/docs/getting-started.md)
47
- for a full walkthrough and the manual (non-scaffolded) version of this project.
48
-
49
- ## Agent guidance
50
-
51
- Always-on project context lives in `AGENTS.md`, which every agent reads; `CLAUDE.md` is a thin
52
- bridge that imports it. It carries the four mandatory sections a real OwlMeans monorepo uses —
53
- **Git Workflow**, **Reporting**, **Memory**, **Self-Education** — plus a project-purpose
54
- placeholder the agent fills in on its first session.
55
-
56
- Project memory is a single shared graph store at `.agents/memory/` (index `MEMORY.md`), used by
57
- every agent — never write memory anywhere else.
58
-
59
- Reusable guidance is one skill per topic at `.agents/skills/<name>/SKILL.md` — the
60
- [Agent Skills](https://agentskills.io) standard location, read natively by Copilot and Codex.
61
- Claude Code reads them through the generated per-skill symlinks under `.claude/skills/`, which
62
- `sh .agents/scripts/link-skills.sh` (re)creates; the committed `SessionStart` hook runs it each
63
- session. Never author a file under `.claude/skills/`.
64
-
65
- Files carrying an `AUTO-GENERATED` banner are managed by
66
- [`@owlmeans/agent-skills`](https://www.npmjs.com/package/@owlmeans/agent-skills) — don't hand-edit
67
- them; write your own guidance as separate, un-bannered files. Refresh after adding or upgrading
68
- `@owlmeans/*` packages:
69
-
70
- ```sh
71
- npx @owlmeans/agent-skills@^0.1.18-rc.12
72
- ```
9
+ Use `bun run build` from the project root to build every workspace.
@@ -1,152 +1,45 @@
1
1
  ---
2
2
  name: getting-started
3
- description: How to build a fullstack OwlMeans Common app from scratch — the common/api/web three-workspace pattern, context bootstrap on server and web, shared entrypoints + elevate(), and a session-scoped in-memory resource with @owlmeans/static-resource. Use when starting a new OwlMeans project, wiring web↔api, or asked how the pieces fit together.
4
- user-invocable: true
3
+ description: Start a protocol-first OwlMeans application with shared contracts, server entrypoints and browser entrypoints.
5
4
  metadata:
6
5
  scope: general
7
6
  ---
8
7
  <!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
9
8
 
10
- # Getting started with OwlMeans Common — fullstack app shape
9
+ # Protocol-first application shape
11
10
 
12
- A minimal OwlMeans app is a **bun-workspace monorepo with three packages**:
13
-
14
- ```
15
- sources/
16
- ├── common/ # shared entrypoints (routes), AJV schemas, types, config — the single source of truth
17
- │ # entrypoints.ts
18
- ├── api/ # @owlmeans/server-app backend; handlers attached to the shared entrypoints
19
- │ # context.ts, entrypoints.ts, app/<area>/*, index.ts
20
- └── web/ # @owlmeans/web-panel + shadcn UI; screens attached to the same entrypoints
21
- # context.ts, entrypoints.ts, nav.ts, layout/, screens/, render.tsx, index.tsx
22
- ```
23
-
24
- Three workspaces is the whole shape — a backend that needs its own long-running worker or a second
25
- API adds a workspace beside them and shares the same `common`.
26
-
27
- The full, runnable walkthrough (scaffolded **and** manual) lives in the
28
- [OwlMeans getting-started guide](https://github.com/owlmeans/common/blob/main/docs/getting-started.md).
29
- To generate this exact project, use [[scaffolding]] (`npm create @owlmeans/app`). This skill is the
30
- mental model.
31
-
32
- ## The core idea: one contract, two sides
33
-
34
- Declare each route once in `common` as an **entrypoint**, then `elevate()` it on each side:
35
-
36
- ```ts
37
- // common/entrypoints.ts — declaration + validation, no implementation
38
- export const sessionEntrypoints = [
39
- entrypoint(route(session.base, '/session')),
40
- entrypoint(route(session.list, '/:sid/items', { parent: session.base, method: RouteMethod.GET }),
41
- filter(params<SessionParams>(SessionParamsSchema))),
42
- entrypoint(route(session.add, '/:sid/items', { parent: session.base, method: RouteMethod.POST }),
43
- filter(params<SessionParams>(SessionParamsSchema, body<AddItemPayload>(AddItemSchema)))),
44
- ]
45
- ```
46
-
47
- ```ts
48
- // api/entrypoints.ts — attach handlers
49
- elevate(sessionEntrypoints, session.list, handlers.list)
50
- export const appEntrypoints = [...entrypoints, ...sessionEntrypoints] // `entrypoints` = framework defaults
51
- ```
52
-
53
- ```ts
54
- // web/entrypoints.ts — attach screen components, plus call-only elevation for backend routes
55
- const entrypoints = [...baseEntrypoints, ...sessionEntrypoints] // `baseEntrypoints` from web-panel
56
- elevate(entrypoints, session.list) // callable from the client
57
- entrypoints.push(entrypoint(route(web.session, '/session', frontend({ parent: BASE })), handler(SessionScreen)))
58
- export const appEntrypoints = entrypoints
59
- ```
60
-
61
- A route declaration is plain data: its `path` is the SEGMENT it contributes under its `parent`, and
62
- nothing ever rewrites it. `session.list` reads `/:sid/items` under `session.base`'s `/session`,
63
- under the api service's `base: 'api'` — so the address is `GET /api/session/:sid/items`, computed
64
- on demand by whoever asks. `elevate` is idempotent, so re-elevating an alias is allowed and guards
65
- given at elevation are added to the declared ones.
66
-
67
- Change a route or schema in `common` and both sides stay in sync. See [[entrypoint]], [[route]],
68
- [[server-app]], [[web-client]], [[web-panel]].
69
-
70
- ## Shared config (where services live)
71
-
72
- `common/config.ts` registers both services so the web knows where the API is. `base: 'api'`
73
- prefixes API routes with `/api`:
11
+ An OwlMeans application owns one shared protocol declaration and creates local entrypoints for each
12
+ runtime. The declaration is never modified by a server or browser.
74
13
 
75
14
  ```ts
76
- const cfg = service({ type: AppType.Frontend, service: APP_WEB, host: 'localhost', port: 3001 })
77
- service({ type: AppType.Backend, service: APP_API, host: 'localhost', port: 3000, base: 'api' }, cfg)
78
- cfg.debug = { all: true }
79
- cfg.alias = APP
80
- cfg.security = { unsecure: true } // local dev serves the API over plain HTTP
81
- export const commonConfig = cfg
15
+ // common/src/entrypoints.ts
16
+ export const sessionEntrypoints = {
17
+ list: protocol(
18
+ route(session.list, '/session', backend()),
19
+ contract.request({ query: typed<SessionQuery>(SessionQuerySchema) }, typed<Session[]>())
20
+ ),
21
+ }
82
22
  ```
83
23
 
84
- api: `config(APP_API, commonConfig)` (+ `cfg.port`). web: `config(APP_WEB, commonConfig)`. See [[config]].
85
-
86
- ## Backend bootstrap + in-memory data
87
-
88
24
  ```ts
89
- // api/context.ts
90
- const context = makeContext(cfg, true) // from @owlmeans/server-app
91
- appendStaticResource(context, SESSION_ITEMS) // @owlmeans/static-resource in-memory, no DB
25
+ // api/src/entrypoints.ts
26
+ const api = handlers<Context>()
27
+ export const appEntrypoints = [
28
+ ...frameworkEntrypoints,
29
+ bind(sessionEntrypoints.list, api.request(sessionEntrypoints.list, listSessions)),
30
+ ]
92
31
  ```
93
32
 
94
- Handlers use `handleRequest` / `handleBody` / `handleParams` (validated payload, then context, then
95
- req). Read/write `ctx.getStaticResource<T>(alias)` — the full resource contract
96
- (`get/load/list/count/create/update/save/delete/take/purge`), so the resource answers the whole
97
- question rather than the handler filtering afterwards:
98
-
99
33
  ```ts
100
- const { items } = await resource.list(
101
- { sessionId: params.sid },
102
- { sort: [{ field: 'createdAt', order: 'desc' }] }
103
- )
104
- ```
105
-
106
- `list` returns `{ items, total }`; the in-memory backends are unpaged unless a `size` is asked for.
107
- `main(context, appEntrypoints)` starts the server. See [[static-resource]], [[server-app]],
108
- [[resource]].
109
-
110
- Swap `@owlmeans/static-resource` for [[mongo-resource]] / [[redis-resource]] when you need
111
- persistence — the handler shape is identical.
112
-
113
- ## Web bootstrap (shadcn)
114
-
115
- `@owlmeans/web-panel`'s `PanelApp` is shadcn/Tailwind v4 (no MUI). The **app provides** the shadcn
116
- primitives at the `@` alias — `web-panel` references `@/lib/utils` and
117
- `@/components/ui/{alert,button,card,input,label,navigation-menu,progress}`; copy those into `src/`.
118
- Routing resolves itself from the active router plugin, so `PanelApp` takes no router prop —
119
- `render.tsx` is one line and `index.tsx` calls it:
120
-
121
- ```tsx
122
- // render.tsx — import { render as basicRender } from '@owlmeans/web-client'
123
- basicRender(<PanelApp context={context} />)
124
- ```
125
-
126
- `vite.config.ts` sets `@`→`src`, `@tailwindcss/vite`, and dedupes the owlmeans/react singletons.
127
- `index.css` is `@import "tailwindcss";` + a shadcn `@theme` token block (replaces `@owlmeans/owl-theme`).
128
- A parent `BASE` route renders the layout via `handler(MainLayout)`; `HOME` is its default child, declared `frontend({ default: true, parent: BASE })`.
129
- `index.tsx` calls `context.registerEntrypoints(appEntrypoints)` and `context.serviceRoute(...)` for
130
- each service, then renders.
131
-
132
- Screens address the backend through three explicit verbs on the entrypoint:
34
+ // web/src/entrypoints.ts
35
+ export const appEntrypoints = [
36
+ ...frameworkEntrypoints,
37
+ ...bindAll(sessionEntrypoints),
38
+ ]
133
39
 
134
- ```tsx
135
- const items = await ctx.entrypoint<ClientEntrypoint<Item[]>>(session.list).call({ params: { sid } })
136
- const { value, outcome } = await ctx.entrypoint<ClientEntrypoint<Item>>(session.add).invoke({ body })
137
- const href = await ctx.entrypoint<ClientEntrypoint<string>>(web.about).url()
40
+ const sessions = await context.entrypoint(sessionEntrypoints.list).call({ query: { sid } })
138
41
  ```
139
42
 
140
- `call` resolves to the VALUE and throws the reply's error; `invoke` gives `{ value, outcome }` when
141
- the outcome decides what happens next; `url` gives the address (`{ absolute: true }` forces a fully
142
- qualified one). A screen entrypoint answers `url()` and refuses `call()` — a screen is navigated to.
143
- See [[web-panel]], [[web-client]], [[shadcn-web]], [[client-entrypoint]].
144
-
145
- The screen keeps nothing in component state: `makeContext` registers a `@owlmeans/state` resource,
146
- the fetch writes what came back into it with `store.replace(items)`, and `useStoreList` renders the
147
- live subscription. See [[state]].
148
-
149
- ## Authentication
150
-
151
- This shape is intentionally **auth-free**. To add it: `@owlmeans/server-auth` + `@owlmeans/client-auth`
152
- and `guard(...)` on entrypoints. See [[auth-protocol]], [[server-auth]], [[client-auth]].
43
+ Use `schema<T>(...)` or `typed<T>(...)` at the contract boundary. Bind all route parents with their
44
+ children. Keep organization entity values on the wire as `entitySlug`; database relations use
45
+ `entityId` only.
@@ -57,7 +57,7 @@ other `@owlmeans/*` packages:
57
57
 
58
58
  ```json
59
59
  "dependencies": {
60
- "@owlmeans/queue": "^0.1.18-rc.11"
60
+ "@owlmeans/queue": "^0.1.18-rc.12"
61
61
  }
62
62
  ```
63
63
 
@@ -11,8 +11,8 @@
11
11
  "typecheck": "tsc -b"
12
12
  },
13
13
  "dependencies": {
14
- "@owlmeans/server-app": "^0.1.18-rc.19",
15
- "@owlmeans/static-resource": "^0.1.18-rc.10",
14
+ "@owlmeans/server-app": "^0.1.18-rc.21",
15
+ "@owlmeans/static-resource": "^0.1.18-rc.12",
16
16
  "__APP_SLUG__-common": "workspace:^"
17
17
  },
18
18
  "devDependencies": {
@@ -1,5 +1,4 @@
1
- import { elevate, entrypoints } from '@owlmeans/server-app'
2
- import { sharedEntrypoints } from '__APP_SLUG__-common'
1
+ import { entrypoints } from '@owlmeans/server-app'
3
2
 
4
- // Handlers bind to a protocol; a bare shell starts without any implementations.
5
- export const appEntrypoints = [...entrypoints, ...elevate(sharedEntrypoints, [])]
3
+ // The bare shell has no API declarations yet. Bind new protocols here as they are added.
4
+ export const appEntrypoints = [...entrypoints]
@@ -1,8 +1,13 @@
1
- import { elevate, entrypoints } from '@owlmeans/server-app'
2
- import { sessionEntrypoints } from '__APP_SLUG__-common'
1
+ import { entrypoints } from '@owlmeans/server-app'
2
+ import { bind } from '@owlmeans/server-entrypoint'
3
+ import { appEntrypoints as protocols } from '__APP_SLUG__-common'
3
4
  import * as handlers from './app/session/index.js'
4
5
 
5
- // Each handler is already bound to its protocol; elevation materializes the local server entries.
6
- const sessionModules = elevate(sessionEntrypoints, [handlers.list, handlers.add, handlers.remove])
7
-
8
- export const appEntrypoints = [...entrypoints, ...sessionModules]
6
+ /** Local server bindings for the shared session protocol tree. */
7
+ export const appEntrypoints = [
8
+ ...entrypoints,
9
+ bind(protocols.api.session.base),
10
+ bind(protocols.api.session.list, handlers.list),
11
+ bind(protocols.api.session.add, handlers.add),
12
+ bind(protocols.api.session.remove, handlers.remove),
13
+ ]
@@ -19,11 +19,11 @@
19
19
  "typecheck": "tsc -b"
20
20
  },
21
21
  "dependencies": {
22
- "@owlmeans/config": "^0.1.18-rc.13",
23
- "@owlmeans/entrypoint": "^0.1.18-rc.12",
24
- "@owlmeans/error": "^0.1.18-rc.9",
25
- "@owlmeans/resource": "^0.1.18-rc.10",
26
- "@owlmeans/route": "^0.1.18-rc.10",
22
+ "@owlmeans/config": "^0.1.18-rc.15",
23
+ "@owlmeans/entrypoint": "^0.1.18-rc.14",
24
+ "@owlmeans/error": "^0.1.18-rc.11",
25
+ "@owlmeans/resource": "^0.1.18-rc.12",
26
+ "@owlmeans/route": "^0.1.18-rc.12",
27
27
  "ajv": "^8.17.1"
28
28
  },
29
29
  "devDependencies": {
@@ -1,8 +1,14 @@
1
- import type { EntrypointProtocol } from '@owlmeans/entrypoint'
1
+ import { openProtocol } from '@owlmeans/entrypoint'
2
+ import { BASE, HOME } from '@owlmeans/context'
3
+ import { frontend, route } from '@owlmeans/route'
2
4
 
3
- /**
4
- * The entrypoint declarations both sides share: the api elevates them with handlers, the web
5
- * elevates them with screens or just calls them. Routes resolve under the api service `base`
6
- * (`/api`), so an `entrypoint(route(alias, '/items', ...))` added here answers on `/api/items`.
7
- */
8
- export const sharedEntrypoints: EntrypointProtocol[] = []
5
+ const webBase = openProtocol(route(BASE, '/', frontend()))
6
+
7
+ /** The shared immutable protocol tree. Add API declarations below `api` as the shell grows. */
8
+ export const appEntrypoints = {
9
+ api: {},
10
+ web: {
11
+ base: webBase,
12
+ home: openProtocol(route(HOME, '/', frontend({ default: true, parent: webBase }))),
13
+ },
14
+ }
@@ -1,4 +1,4 @@
1
- import { contract, openProtocol, protocol, protocols, typed } from '@owlmeans/entrypoint'
1
+ import { contract, openProtocol, protocol, typed } from '@owlmeans/entrypoint'
2
2
  import { route, RouteMethod, frontend } from '@owlmeans/route'
3
3
  import { AddItemSchema, ItemParamsSchema, SessionParamsSchema } from './schemas.js'
4
4
  import type { SessionItem } from './types.js'
@@ -22,8 +22,8 @@ const sessionBase = protocol(route(aliases.session.base, '/session'), contract()
22
22
  const webBase = openProtocol(route(aliases.web.base, '/', frontend()))
23
23
 
24
24
  /**
25
- * Shared entrypoint declarations. The api elevates these with handlers; the web
26
- * elevates them with screen components and calls them. Routes resolve under the
25
+ * Shared entrypoint declarations. The api materializes these with handlers; the web
26
+ * materializes them with screen components and calls them. Routes resolve under the
27
27
  * api service `base` (`/api`), so e.g. `session.list` → `GET /api/session/:sid/items`.
28
28
  */
29
29
  export const session = {
@@ -53,4 +53,8 @@ export const web = {
53
53
  about: openProtocol(route(aliases.web.about, '/about', frontend({ parent: webBase }))),
54
54
  }
55
55
 
56
- export const sessionEntrypoints = protocols(session)
56
+ /** The shared immutable protocol tree. Runtime packages bind their own local handlers and screens. */
57
+ export const appEntrypoints = {
58
+ api: { session },
59
+ web,
60
+ }
@@ -11,16 +11,16 @@
11
11
  "preview": "vite preview"
12
12
  },
13
13
  "dependencies": {
14
- "@owlmeans/client": "^0.1.18-rc.17",
15
- "@owlmeans/client-config": "^0.1.18-rc.13",
16
- "@owlmeans/client-context": "^0.1.18-rc.14",
17
- "@owlmeans/client-entrypoint": "^0.1.18-rc.14",
18
- "@owlmeans/client-i18n": "^0.1.18-rc.16",
19
- "@owlmeans/entrypoint": "^0.1.18-rc.12",
20
- "@owlmeans/route": "^0.1.18-rc.10",
21
- "@owlmeans/state": "^0.1.18-rc.11",
22
- "@owlmeans/web-client": "^0.1.18-rc.25",
23
- "@owlmeans/web-panel": "^0.1.18-rc.33",
14
+ "@owlmeans/client": "^0.1.18-rc.19",
15
+ "@owlmeans/client-config": "^0.1.18-rc.15",
16
+ "@owlmeans/client-context": "^0.1.18-rc.16",
17
+ "@owlmeans/client-entrypoint": "^0.1.18-rc.16",
18
+ "@owlmeans/client-i18n": "^0.1.18-rc.18",
19
+ "@owlmeans/entrypoint": "^0.1.18-rc.14",
20
+ "@owlmeans/route": "^0.1.18-rc.12",
21
+ "@owlmeans/state": "^0.1.18-rc.13",
22
+ "@owlmeans/web-client": "^0.1.18-rc.27",
23
+ "@owlmeans/web-panel": "^0.1.18-rc.35",
24
24
  "@radix-ui/react-label": "^2.1.0",
25
25
  "@radix-ui/react-navigation-menu": "^1.2.14",
26
26
  "@radix-ui/react-progress": "^1.1.0",
@@ -1,13 +1,13 @@
1
- import { BASE, bind, entrypoint, entrypoints as baseEntrypoints, frontend, handler, HOME, route } from '@owlmeans/web-panel'
2
- import { sharedEntrypoints } from '__APP_SLUG__-common'
1
+ import { bindAll, bindScreen, entrypoints as baseEntrypoints, handler } from '@owlmeans/web-panel'
2
+ import { appEntrypoints as protocols } from '__APP_SLUG__-common'
3
3
  import { MainLayout } from './layout/main.js'
4
4
  import { HomeScreen } from './screens/home.js'
5
5
 
6
- // Backend protocol declarations are materialized locally so each can be called from the browser.
7
- const entrypoints = [...baseEntrypoints, ...sharedEntrypoints.map(protocol => bind(protocol))]
8
-
9
- // Frontend layout + screens. BASE renders the shared layout; HOME is its default child.
10
- entrypoints.push(entrypoint(route(BASE, '/', frontend()), handler(MainLayout)))
11
- entrypoints.push(entrypoint(route(HOME, '/', frontend({ default: true, parent: BASE })), handler(HomeScreen)))
12
-
13
- export const appEntrypoints = entrypoints
6
+ /** Local browser bindings for shared API and screen protocols. */
7
+ export const appEntrypoints = [
8
+ ...baseEntrypoints,
9
+ ...bindAll(protocols.api),
10
+ // BASE renders the shared layout; HOME is its default child.
11
+ bindScreen(protocols.web.base, handler(MainLayout)),
12
+ bindScreen(protocols.web.home, handler(HomeScreen)),
13
+ ]
@@ -1,16 +1,16 @@
1
1
  import { bindAll, bindScreen, entrypoints as baseEntrypoints, handler } from '@owlmeans/web-panel'
2
- import { session, web } from '__APP_SLUG__-common'
2
+ import { appEntrypoints as protocols } from '__APP_SLUG__-common'
3
3
  import { MainLayout } from './layout/main.js'
4
4
  import { AboutScreen } from './screens/about.js'
5
5
  import { HomeScreen } from './screens/home.js'
6
6
  import { SessionScreen } from './screens/session.js'
7
7
 
8
- const entrypoints = [...baseEntrypoints, ...bindAll(session)]
9
-
10
- // Frontend protocol declarations bind to renderers in the web project.
11
- entrypoints.push(bindScreen(web.base, handler(MainLayout)))
12
- entrypoints.push(bindScreen(web.home, handler(HomeScreen)))
13
- entrypoints.push(bindScreen(web.session, handler(SessionScreen)))
14
- entrypoints.push(bindScreen(web.about, handler(AboutScreen)))
15
-
16
- export const appEntrypoints = entrypoints
8
+ /** Local browser bindings for shared API and screen protocols. */
9
+ export const appEntrypoints = [
10
+ ...baseEntrypoints,
11
+ ...bindAll(protocols.api),
12
+ bindScreen(protocols.web.base, handler(MainLayout)),
13
+ bindScreen(protocols.web.home, handler(HomeScreen)),
14
+ bindScreen(protocols.web.session, handler(SessionScreen)),
15
+ bindScreen(protocols.web.about, handler(AboutScreen)),
16
+ ]
@@ -5,7 +5,7 @@
5
5
  * scan by default — so the classes that exist ONLY inside @owlmeans/web-panel components
6
6
  * (the navigation shell, the footer) would never reach the stylesheet. This line adds them.
7
7
  */
8
- @source "../../../node_modules/@owlmeans/web-panel/build";
8
+ @source "../../../node_modules/@owlmeans/web-panel/src";
9
9
 
10
10
  /*
11
11
  * shadcn / Tailwind v4 design tokens (new-york, neutral). The app owns these — they