@webjsdev/cli 0.10.67 → 0.10.69

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.
@@ -1,82 +1,52 @@
1
1
  # AGENTS.md for {{APP_NAME}}
2
2
 
3
- This is a WebJs app: AI-first, web-components-first, buildless, and
4
- progressively enhanced. Read this whole file before you edit anything, then
5
- follow it. The steps here are required, not optional.
6
-
7
- ## Gather context BEFORE you build (required)
8
-
9
- WebJs is its own framework. It is not React, Next, or Lit, so writing code from
10
- that muscle memory produces broken WebJs code. Before you write or change
11
- anything, gather context from these sources. Do not skip a step to save time.
12
- This is what separates a working app from a broken one.
13
-
14
- 1. **Read the skill.** Start with `.agents/skills/webjs/SKILL.md`, then load the
15
- `references/*.md` files it routes to for the surface you are touching. The
16
- skill is the guide to building a WebJs app: it helps you choose the right
17
- layer, reach for the right export, and avoid the mistakes Next.js or Lit
18
- habits cause. Reading it is never wasted work: it survives the
19
- gallery-clearing step in the playbook below.
20
- 2. **Study the shipped examples, then build on a clean slate.** The template
21
- playbook below says what ships and the exact order to follow. The workflow
22
- rules (git, tests, review) are in `.agents/rules/workflow.md`; follow them
23
- too.
24
- 3. **Read the framework source for exact contracts.** WebJs is 100% buildless
25
- native ES modules, so the source you run IS the source you read. When you
26
- need a precise API signature or behavior, open the package source under
27
- `node_modules/@webjsdev/*` directly (each package ships its own `AGENTS.md`).
28
- The full hosted docs are at https://webjs.dev/docs.
3
+ This is a WebJs app: server-rendered pages, web components for interactivity,
4
+ server actions, Drizzle, and no build step. WebJs is its own framework, not
5
+ React, Next.js or Lit, so write it from the patterns in this file rather than
6
+ from that memory. Read this whole file before you edit anything.
29
7
 
30
8
  {{PLAYBOOK}}
31
9
 
32
- ## Type everything (all templates)
33
-
34
- Full-stack type safety is what the `.server.ts` boundary buys you: a client
35
- component importing a server action resolves to that action's real signature at
36
- type-check time, with no build step and no code generation in between. So
37
- DERIVE the type at every boundary instead of widening it:
38
-
39
- - A database row: `export type Todo = typeof todos.$inferSelect` in
40
- `db/schema.server.ts` (`$inferInsert` for a write), carried into a
41
- browser-shipped component with `import type` (erased before it reaches the
42
- browser, so it does not trip the server-import boundary).
43
- - An action's input: a named `interface`. Its result: `ActionResult<T>`.
44
- Narrow with `if (result.success && result.data)`.
45
- - Routing files: `PageProps<'/blog/[slug]'>`, `LayoutProps`,
46
- `RouteHandlerContext`, all from `@webjsdev/core`. Run `npx webjsdev types`
47
- for the typed `Route` union and per-route `params`.
48
- - A reactive property: `prop<Student>(Object)`, `prop<Tag[]>(Array)`.
49
-
50
- Never reach for `any` or a loose `as any` cast, and do not reach for `unknown`
51
- either just because it looks safer. `unknown` is right for a payload nothing
52
- has vouched for yet, narrowed on the very next line (a `route.ts` `await
53
- req.json()`, an action's `export const validate` or a validator it delegates
54
- to, a `catch` binding), and for a parameter of YOUR OWN helper that forwards
55
- into an `html` template hole (a hole renders a string, a number, a
56
- `TemplateResult`, or an array of those, so `TemplateResult` alone is too
57
- narrow). That second case is about a value you accept, never one the framework
58
- already types. Everywhere else it is a missing type, not a safe one: `unknown`
59
- that survives into a return type, a component prop, a layout's `children`, or
60
- an action signature is the shape to fix.
61
- Nothing enforces this (both are valid TypeScript, so `webjs check` and `tsc`
62
- pass either way), which is exactly why it is written down. The full ladder,
63
- with an end-to-end example, is in
64
- `.agents/skills/webjs/references/typescript.md`.
65
-
66
- Keep server-only code (database drivers, secrets, `node:*` builtins) in
67
- `.server.ts` modules. There are exactly two kinds:
68
-
69
- - A `.server.ts` file WITH `'use server';` as its first line is a server
70
- action: WebJs exposes its exported async functions to browser code as RPC
71
- calls, so browser modules may import it directly.
72
- - A `.server.ts` file WITHOUT `'use server'` is a server-only utility:
73
- importing it from a page, layout, or component CRASHES in the browser at
74
- module load. Reach it only from `'use server'` actions, `route.ts` handlers,
75
- or middleware. Never add `'use server'` to a file only other server code
76
- imports (the DB connection, the schema).
77
-
78
- ## Data (all templates)
79
-
80
- Use the wired-up database (Drizzle) for every piece of data the app stores;
81
- the playbook above has the modeling step. Never store app data in a JSON file,
82
- an in-memory array, or localStorage.
10
+ ## Rules that hold everywhere
11
+
12
+ - **Type every boundary from its source.** A row is
13
+ `typeof posts.$inferSelect` (exported from `db/schema.server.ts`, carried
14
+ into browser code with `import type`), an action's input is a named
15
+ `interface`, a routing file uses `PageProps<'/posts/[id]'>` / `LayoutProps` /
16
+ `RouteHandlerContext` from `@webjsdev/core`, and a component prop that holds
17
+ an object is `prop<Post>(Object)`. Never reach for `any` or `as any`, and
18
+ keep `unknown` for an untrusted payload you narrow on the next line.
19
+ - **Server-only code stays behind `.server.ts`.** A file WITH `'use server'`
20
+ exposes its exported async functions as actions; a file WITHOUT it is a
21
+ server-only utility that only other server code may import. Never add
22
+ `'use server'` to a file only server code imports (the DB connection, the
23
+ schema).
24
+ - **Store data with Drizzle** in the wired-up database (`db/`), never in a
25
+ JSON file, an in-memory array or Map, or localStorage. Every schema change is
26
+ `npm run db:generate` then `npm run db:migrate`, and the generated
27
+ migrations are committed.
28
+ - **TypeScript is erasable:** no `enum`, no `namespace`, no constructor
29
+ parameter properties, no decorators. Never put a backtick inside an
30
+ `html` template body, even in a comment.
31
+ - **Errors tell you the fix.** `npm run check` and `npm run typecheck` name
32
+ the file, the rule and the fix; do what they say rather than searching.
33
+
34
+ ## Git
35
+
36
+ Commit per logical unit (CLAUDE.md has the rule). When you build a whole app
37
+ from a spec in one session, the build is one unit: work on a feature branch
38
+ (commits to `main` are refused), and commit once at the end after the checks
39
+ pass (`git add -A && git commit -m "<imperative subject>"`). Team workflow
40
+ (pull requests, CI, worktrees) is in `.agents/rules/workflow.md`.
41
+
42
+ ## When you need more
43
+
44
+ The reference set is `.agents/skills/webjs/` (`SKILL.md` routes to
45
+ `references/*.md`). Open one only for a surface this file does not show:
46
+ streaming and Suspense (`client-router-and-streaming.md`), optimistic UI
47
+ (`optimistic-ui.md`), caching, rate limits, file uploads, env vars
48
+ (`built-ins.md`), OAuth providers and sessions (`auth-and-sessions.md`),
49
+ browser and e2e tests (`testing.md`), deeper component topics such as slots,
50
+ shadow DOM, context and directives (`components.md`). The exact framework
51
+ source is under `node_modules/@webjsdev/*`, and the hosted docs are at
52
+ https://webjs.dev/docs.
@@ -3,21 +3,19 @@
3
3
  # Committing per logical unit (this OVERRIDES Claude Code's default)
4
4
 
5
5
  Claude Code's built-in default is to NEVER commit unless the user explicitly
6
- asks. **For this project that default does NOT apply.** Commit and push per
7
- logical unit (one feature, one fix, one rename, one doc rewrite) as soon as it
8
- is complete, WITHOUT being asked. Do not save all the work for one commit at the
9
- end. A finished implementation with zero commits is a mistake here, because git
10
- history is the user's revert and cherry-pick safety net.
6
+ asks. **For this project that default does NOT apply.** Commit per logical
7
+ unit (one feature, one fix, one rename, one doc rewrite) as soon as it is
8
+ complete and its checks pass, WITHOUT being asked, then push when there is a
9
+ remote. Git history is the user's revert and cherry-pick safety net.
11
10
 
12
- - After each completed unit whose tests pass, `git add` the related files and
13
- `git commit` with an imperative subject under 72 chars, then push. If 5+ files
14
- span more than one concern, you already waited too long.
15
- - Never commit to `main`. Work on a feature branch (the
16
- `.claude/hooks/guard-branch-context.sh` hook enforces this).
17
- - No AI-attribution trailers (`Co-Authored-By`, `Generated by`).
11
+ - Building a whole app from a spec in one session is ONE unit: build it,
12
+ verify it, then commit once. Later changes are one commit each.
13
+ - Never commit to `main`. Work on a feature branch (the pre-commit hook
14
+ refuses `main`).
15
+ - Imperative subject under 72 characters. No AI-attribution trailers
16
+ (`Co-Authored-By`, `Generated by`).
18
17
 
19
- See AGENTS.md "Git workflow" for the full contract. Two hooks back this up: the
20
- `.claude/hooks/nudge-uncommitted.sh` PostToolUse hook reminds you while
21
- uncommitted changes pile up during work, and the
22
- `.claude/hooks/commit-before-stop.sh` Stop hook stops you from ending a turn
23
- with a pile of uncommitted work still on a feature branch.
18
+ Two hooks back this up: `.claude/hooks/nudge-uncommitted.sh` reminds you while
19
+ uncommitted changes pile up on a branch that already has commits, and
20
+ `.claude/hooks/commit-before-stop.sh` stops you from ending a turn with
21
+ uncommitted work on a feature branch.
@@ -1,9 +1,9 @@
1
1
  # Conventions for {{APP_NAME}}
2
2
 
3
- The conventions for building a WebJs app live in the agent skill. **Read
4
- `AGENTS.md` first, then `.agents/skills/webjs/SKILL.md`** (it routes to focused
5
- references under `.agents/skills/webjs/references/`, loaded on demand). This file
6
- is the short version.
3
+ The conventions for building a WebJs app live in **`AGENTS.md`**, which shows
4
+ every common pattern as a worked example. The deeper reference set is
5
+ `.agents/skills/webjs/` (`SKILL.md` routes to `references/*.md`), for the rarer
6
+ surfaces. This file is the short version.
7
7
 
8
8
  ## The essentials
9
9
 
@@ -17,13 +17,12 @@ is the short version.
17
17
  - **Use the wired-up database (Drizzle).** Define real models in
18
18
  `db/schema.server.ts`, then `npm run db:generate` and `npm run db:migrate`.
19
19
  Never persist to a JSON file, an in-memory array or Map, or localStorage.
20
- - **The scaffold ships a showcase to learn from.** A full-stack app ships a UI
21
- feature gallery (`app/features/`, `app/examples/todo`); the api template ships
22
- a backend-features showcase (`app/api/features/`), with logic in `modules/`.
23
- When you build a real app, study the parts that match your task (the skill
24
- teaches the same and survives the clear), run `npm run gallery:clear` to shed
25
- the showcase, then grow the app in place. `AGENTS.md` has the full
26
- template-specific playbook.
20
+ - **The scaffold ships a demo showcase.** A full-stack app ships a UI feature
21
+ gallery (`app/features/`, `app/examples/todo`); the api template ships a
22
+ backend-features showcase (`app/api/features/`), with logic in `modules/`.
23
+ When you build a real app, run `npm run gallery:clear` first to shed the
24
+ showcase, then grow the app in place. `AGENTS.md` has the template-specific
25
+ build steps.
27
26
  - **Derive types at every boundary.** Rows from `$inferSelect`, action inputs
28
27
  from an `interface`, routing files from `PageProps` / `LayoutProps`. Never
29
28
  `any`, and never `unknown` where a real type exists.
@@ -3,12 +3,14 @@
3
3
  // content type, so an inline SVG needs no asset file. Generate it dynamically
4
4
  // (per-theme, per-tenant) when the mark must be computed at request time.
5
5
  //
6
- // This is the DEMO of that surface, not the gallery's own favicon. A metadata
7
- // route is not auto-linked: the framework emits `<link rel="icon">` only from
8
- // metadata.icons, so the gallery declares the static WebJs brand mark from
9
- // public/ there (see app/layout.ts) and this route stays browsable at /icon.
10
- // For a favicon that never changes, that static path is the one to copy; drop
11
- // this route when your app has no request-time mark to compute.
6
+ // This is the DEMO of that surface, not the gallery's own favicon. With no
7
+ // metadata.icons declared, the framework auto-links an app-root icon: a STATIC
8
+ // file (app/icon.svg, app/icon.png) wins that link over this route, and a
9
+ // declared metadata.icons wins over both. The gallery declares its WebJs brand
10
+ // mark in app/layout.ts, so this route stays browsable at /icon without being
11
+ // the tab icon. For an icon that never changes, write app/icon.svg instead
12
+ // (what `webjs create` ships); keep a route like this only when the mark must
13
+ // be computed at request time (per theme, per tenant).
12
14
  export default function Icon() {
13
15
  const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
14
16
  <rect width="32" height="32" rx="7" fill="#1e2226"/>
@@ -3,6 +3,9 @@
3
3
  // icons to your app; pair it with the opt-in service worker for an installable
4
4
  // PWA. See agent-docs/service-worker.md. (Gallery files are copied verbatim, so
5
5
  // set the real app name here by hand rather than expecting substitution.)
6
+ // The framework links an app-root manifest into <head> by itself. A static
7
+ // app/manifest.webmanifest (what `webjs create` ships) wins that link over this
8
+ // route; write a route like this only when a value must be computed.
6
9
  export default function Manifest() {
7
10
  return {
8
11
  name: 'webjs app',
@@ -12,7 +15,7 @@ export default function Manifest() {
12
15
  background_color: '#ffffff',
13
16
  theme_color: '#1e2226',
14
17
  icons: [
15
- { src: '/favicon.svg', sizes: 'any', type: 'image/svg+xml' },
18
+ { src: '/icon', sizes: 'any', type: 'image/svg+xml' },
16
19
  ],
17
20
  };
18
21
  }