@webjsdev/cli 0.10.40 → 0.10.41

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 (69) hide show
  1. package/bin/webjs.js +4 -46
  2. package/lib/create.js +282 -479
  3. package/lib/doctor.js +1 -38
  4. package/package.json +5 -1
  5. package/templates/.agents/rules/workflow.md +61 -271
  6. package/templates/.agents/skills/webjs/SKILL.md +226 -0
  7. package/templates/.agents/skills/webjs/references/auth-and-sessions.md +220 -0
  8. package/templates/.agents/skills/webjs/references/built-ins.md +200 -0
  9. package/templates/.agents/skills/webjs/references/client-router-and-streaming.md +204 -0
  10. package/templates/.agents/skills/webjs/references/components.md +167 -0
  11. package/templates/.agents/skills/webjs/references/data-and-actions.md +187 -0
  12. package/templates/.agents/skills/webjs/references/muscle-memory-gotchas.md +170 -0
  13. package/templates/.agents/skills/webjs/references/optimistic-ui.md +128 -0
  14. package/templates/.agents/skills/webjs/references/routing-and-pages.md +158 -0
  15. package/templates/.agents/skills/webjs/references/runtime.md +80 -0
  16. package/templates/.agents/skills/webjs/references/service-worker.md +78 -0
  17. package/templates/.agents/skills/webjs/references/styling.md +123 -0
  18. package/templates/.agents/skills/webjs/references/testing.md +125 -0
  19. package/templates/.agents/skills/webjs/references/typescript.md +148 -0
  20. package/templates/.claude/hooks/check-server-imports.mjs +1 -1
  21. package/templates/.claude/hooks/require-tests-with-src.sh +1 -1
  22. package/templates/.claude/settings.json +0 -14
  23. package/templates/.cursorrules +21 -189
  24. package/templates/.github/copilot-instructions.md +7 -185
  25. package/templates/.github/pull_request_template.md +1 -1
  26. package/templates/AGENTS.md +59 -1494
  27. package/templates/CLAUDE.md +0 -1
  28. package/templates/CONVENTIONS.md +32 -1383
  29. package/templates/GEMINI.md +11 -0
  30. package/templates/gallery/app/apple-icon.ts +0 -1
  31. package/templates/gallery/app/examples/todo/page.ts +0 -1
  32. package/templates/gallery/app/features/async-render/page.ts +0 -1
  33. package/templates/gallery/app/features/boundaries/page.ts +0 -1
  34. package/templates/gallery/app/features/broadcast/page.ts +0 -1
  35. package/templates/gallery/app/features/caching/page.ts +0 -1
  36. package/templates/gallery/app/features/client-router/page.ts +0 -1
  37. package/templates/gallery/app/features/client-router/second/page.ts +0 -1
  38. package/templates/gallery/app/features/components/page.ts +0 -1
  39. package/templates/gallery/app/features/directives/page.ts +0 -1
  40. package/templates/gallery/app/features/env/page.ts +0 -1
  41. package/templates/gallery/app/features/file-storage/page.ts +0 -1
  42. package/templates/gallery/app/features/forms/page.ts +0 -1
  43. package/templates/gallery/app/features/metadata/page.ts +0 -1
  44. package/templates/gallery/app/features/optimistic-ui/page.ts +0 -1
  45. package/templates/gallery/app/features/rate-limit/page.ts +0 -1
  46. package/templates/gallery/app/features/route-handler/page.ts +0 -1
  47. package/templates/gallery/app/features/routing/page.ts +0 -1
  48. package/templates/gallery/app/features/server-actions/page.ts +0 -1
  49. package/templates/gallery/app/features/service-worker/page.ts +0 -1
  50. package/templates/gallery/app/features/sessions/page.ts +0 -1
  51. package/templates/gallery/app/features/websockets/page.ts +0 -1
  52. package/templates/gallery/app/global-error.ts +0 -1
  53. package/templates/gallery/app/global-not-found.ts +0 -1
  54. package/templates/gallery/app/icon.ts +0 -1
  55. package/templates/gallery/app/manifest.ts +0 -1
  56. package/templates/gallery/app/opengraph-image.ts +0 -1
  57. package/templates/gallery/app/robots.ts +0 -1
  58. package/templates/gallery/app/sitemap.ts +0 -1
  59. package/templates/gallery/app/twitter-image.ts +0 -1
  60. package/templates/public/favicon.svg +5 -0
  61. package/templates/public/sw.js +1 -1
  62. package/templates/scripts/clear-gallery.mjs +95 -0
  63. package/lib/clear-placeholders.js +0 -98
  64. package/lib/design-bar.js +0 -67
  65. package/templates/.claude/hooks/design-review-before-stop.sh +0 -36
  66. package/templates/.claude/hooks/route-skills.sh +0 -35
  67. package/templates/.claude/skills/webjs-design-review/SKILL.md +0 -84
  68. package/templates/LAYOUT-REFERENCE.md +0 -96
  69. package/templates/lib/utils/ui.ts +0 -83
@@ -1,84 +0,0 @@
1
- ---
2
- name: webjs-design-review
3
- description: >-
4
- Render-and-look review for ANY UI work in a WebJs app. Invoke after building
5
- or changing a page, layout, or component, and before you report the work done.
6
- Triggers: "build", "create", "add a page", "component", "layout", "style",
7
- "design", "UI", "screen", "board", "form", "dashboard", "make it look".
8
- ---
9
-
10
- # Render the app and LOOK before you call UI work done
11
-
12
- You write CSS blind. You never see the pixels, so a whole class of defects ships
13
- silently: `webjs check` passes, `webjs typecheck` passes, the server boots, and
14
- the app still looks broken. A collapsed component, cells of unequal size, a
15
- layout that resizes as it fills with content, text that overflows its box, an
16
- app that just kept the scaffold's colors and chrome, none of these fail a test.
17
- The only thing that catches them is rendering the app and looking at it.
18
-
19
- So for ANY work that touches a page, layout, or component, this is the loop:
20
-
21
- ## 1. Run the app and open what you changed
22
-
23
- ```sh
24
- webjs dev # or: webjs start, for the production render
25
- ```
26
-
27
- Open every route you touched in a real browser. Use the browser MCP
28
- (`mcp__playwright__*` or `mcp__chrome-devtools__*`) if available so you can drive
29
- and screenshot it; otherwise open it yourself and take screenshots.
30
-
31
- ## 2. Drive EVERY state, not just the first paint
32
-
33
- The first paint is the easy case. Bugs hide in the states you reach by
34
- interacting. Play the app the way a user will:
35
-
36
- - A game board: play a full game. Fill it. Win. Draw. Reset. Watch whether the
37
- board or its cells change size as marks appear (they must NOT).
38
- - A list: empty, one item, many items, an item long enough to wrap.
39
- - A form: empty, invalid, submitted, error returned, success.
40
- - Anything async: loading, loaded, error, refetch.
41
-
42
- Reload each state. Resize the window narrow (mobile) and wide.
43
-
44
- ## 3. Confirm the things a test can't
45
-
46
- Look at each state and confirm, with your eyes:
47
-
48
- 1. **Nothing collapses, overflows, or resizes.** A container is the size it
49
- should be (not 0-height, not collapsed to its content when it should fill).
50
- Grid/flex children that should be equal ARE equal, and STAY equal as content
51
- changes. Text stays inside its box.
52
- 2. **The design is this app's OWN.** Not the scaffold shell, not its default
53
- color tokens. The palette (real `oklch`/hex values, not just shadcn token
54
- NAMES), the typography, the layout, and the chrome are chosen for THIS app.
55
- "It still looks like the starter" is a defect to fix, not ship.
56
- 3. **Light AND dark both look right.** Toggle the theme. Check contrast, that
57
- nothing disappears against its background, that borders and shadows read.
58
- 4. **It still renders with JavaScript OFF.** WebJs is SSR + progressive
59
- enhancement, so the page must read and look right with no JS (disable it in
60
- devtools, or load in a JS-off context). Content shows, `<a>` navigates,
61
- forms submit, and CRUCIALLY the CSS is fully applied (the app links a static
62
- compiled `public/tailwind.css`, so utilities resolve with no JS). An app that
63
- goes unstyled or blank with JS off is a broken first paint, not a design to
64
- ship.
65
-
66
- ## 4. Iterate until it holds, then say what you saw
67
-
68
- If any of the above is wrong, fix it and re-render. Do not stop on the first
69
- render. When it holds, state in your final message WHAT you rendered and WHAT
70
- you confirmed (which states, light + dark), so the review is on the record.
71
-
72
- ---
73
-
74
- **Why this is a skill and not just a test:** a real-browser test
75
- (`webjs test --browser`) catches the mechanical failures (collapse, uneven
76
- cells, reflow) and you SHOULD ship one. There is no framework helper for this; a
77
- layout-stability check is a few lines you write against your own component (in a
78
- `*/test/**/browser/*.test.js`): measure `getBoundingClientRect()` on the grid
79
- children and assert they stay equal-sized before AND after a move, so a collapse
80
- or reflow FAILS the test. But "looks like the scaffold", "the
81
- palette is bland", "the spacing is off", "it's ugly in dark mode" are judgment
82
- calls no assertion makes for you. That is what this human-in-the-loop look is
83
- for. Do both: the test for the mechanical floor, the look for everything above
84
- it. See CONVENTIONS item 6 and `agent-docs/styling.md`.
@@ -1,96 +0,0 @@
1
- # Layout reference
2
-
3
- `app/layout.ts` ships as a **minimal shell**: it wires the theme, design tokens,
4
- and the linked static Tailwind stylesheet, then renders `${children}` in a bare full-height
5
- container with no chrome. That is on purpose. A delivered app should design its
6
- own layout from what the app IS, not inherit a generic header and footer.
7
-
8
- This file is the **reference** for how to build a real layout: read it to learn
9
- the patterns (a fixed header, a brand mark, a nav, a theme toggle, a reading
10
- column, a footer), then write the layout your app actually needs in
11
- `app/layout.ts`. Decide from scratch: does a tic-tac-toe game want a header at
12
- all? Does a dashboard want a sidebar instead? Does a landing page want a
13
- full-bleed hero? Keep only what fits.
14
-
15
- > **This is ONE example, not a template to reproduce.** Reproducing this exact
16
- > header (a slim bar with a mark on the left and a theme toggle on the right)
17
- > just recreates the old scaffold look under a new name. It is here to show the
18
- > mechanics (how a header, nav, theme toggle, or footer are wired), not the
19
- > design. Design a layout that fits what THIS app is: a game might be a
20
- > full-bleed centered stage with no header; a tool might have a compact command
21
- > bar; a reader might have a wide sidebar. Take the mechanics, invent the form.
22
-
23
- You do not import from this file. Copy the mechanics you want into
24
- `app/layout.ts`'s returned template, inside the `<main>` (or replacing it), and
25
- restyle them into your own design.
26
-
27
- ## A complete worked layout
28
-
29
- This is the chrome the scaffold used to ship inline. It goes in the body of
30
- `RootLayout`, after the `<script>`/`<style>` infrastructure blocks. `navLink` is a
31
- small SSR helper you would declare above `RootLayout`.
32
-
33
- ```ts
34
- // Declare above RootLayout: a nav-link helper (SSR-time, no client runtime).
35
- const navLink = (href: string, label: string) => html`
36
- <a href=${href} class="text-muted-foreground no-underline font-medium text-[13px] leading-none tracking-[0.005em] transition-colors duration-fast hover:text-foreground">${label}</a>
37
- `;
38
-
39
- // Inside RootLayout's returned html``, in place of the minimal <main>:
40
-
41
- // A fixed header (NOT sticky: a sticky header flickers on iOS WebKit during a
42
- // client-router nav). --header-h reserves its height for the content below; the
43
- // header-measure script already in app/layout.ts sets --header-h to the real
44
- // height the moment a <header> exists.
45
- <header class="fixed inset-x-0 top-0 z-20 flex items-center gap-6 px-4 sm:px-6 py-3 border-b border-border bg-[color-mix(in_oklch,var(--background)_75%,transparent)] backdrop-blur-[18px]">
46
- <a href="/" class="mr-auto inline-flex items-center gap-2 no-underline text-foreground font-semibold text-[15px] leading-none tracking-tight">
47
- <!-- Your brand or logo mark goes here. A glyph, a wordmark, the real product name. -->
48
- <span>{{APP_NAME}}</span>
49
- </a>
50
- <nav class="flex gap-4 items-center">
51
- <!-- Your app's real navigation (or drop the nav entirely for a single-page app). -->
52
- ${navLink('/', 'Home')}
53
- <theme-toggle></theme-toggle>
54
- </nav>
55
- </header>
56
-
57
- // A content shell. The max-w-[760px] cap is a comfortable READING width, right
58
- // for prose, forms, and marketing. For a full-bleed app, dashboard, or board,
59
- // widen the cap (for example max-w-[1400px]) or drop the cap and mx-auto for an
60
- // edge-to-edge layout. A wide layout left in the 760px column overflows into a
61
- // horizontal scrollbar.
62
- <div class="flex flex-col min-h-[calc(100dvh-var(--header-h))]">
63
- <main class="flex-1 w-full max-w-[760px] mx-auto px-4 sm:px-6 pt-[72px] pb-12">
64
- ${children}
65
- </main>
66
- <!-- Your footer. Do NOT ship a "Built with webjs" footer: write your app's own. -->
67
- <footer class="border-t border-border">
68
- <div class="max-w-[760px] mx-auto px-4 sm:px-6 py-6 flex items-center justify-center">
69
- <span class="text-sm text-muted-foreground">Your footer</span>
70
- </div>
71
- </footer>
72
- </div>
73
- ```
74
-
75
- ## The `theme-toggle` element
76
-
77
- The scaffold ships `components/theme-toggle.ts` (already imported by
78
- `app/layout.ts` as a side effect, so the element is registered). Place
79
- `<theme-toggle></theme-toggle>` wherever you want the light/dark switch, or delete
80
- the import and the theme apparatus in `app/layout.ts` for a single-theme app.
81
-
82
- ## What stays in `app/layout.ts` no matter what
83
-
84
- The infrastructure above the `<main>` is not chrome and should stay:
85
-
86
- - the theme-detection `<script>` (light/dark apparatus) and the header-measure
87
- script,
88
- - the `<link rel="stylesheet" href="/public/tailwind.css">` (the STATIC stylesheet
89
- compiled from `public/input.css` by `css:build`, so the app is styled with JS
90
- off),
91
- - the `<style>` block of design-token VALUES (`:root` / dark / light), which
92
- carries its own `webjs-scaffold-placeholder` marker, so own the colors. The
93
- Tailwind `@theme` maps that turn those tokens into utilities live in
94
- `public/input.css`.
95
-
96
- Design the chrome; keep the plumbing.
@@ -1,83 +0,0 @@
1
- /**
2
- * Shared UI helpers for pages, layouts, and components.
3
- *
4
- * When the same bundle of Tailwind classes repeats in 2+ places, extract
5
- * it here. The helper runs at SSR time inside `html\`\``, so the browser
6
- * receives fully materialised HTML: no client-side runtime, identical
7
- * output to writing the classes inline.
8
- *
9
- * When to extract:
10
- * • Classes repeat 2+ times identically → extract.
11
- * • Varies by 1–2 props → extract with a small parameter.
12
- * • Radically different per call site → keep inline.
13
- *
14
- * This file lives under `_utils/`: any folder whose name starts with `_`
15
- * is ignored by the router, so it can never accidentally become a route.
16
- */
17
- import { html } from '@webjsdev/core';
18
-
19
- /** `● label` kicker: small caps, brand colour, above headings. */
20
- export function rubric(label: string, mb: 'sm' | 'md' = 'md') {
21
- const mbCls = mb === 'sm' ? 'mb-3' : 'mb-4';
22
- return html`
23
- <span class="block font-mono text-[11px] leading-none font-semibold tracking-[0.2em] uppercase text-primary ${mbCls}">● ${label}</span>
24
- `;
25
- }
26
-
27
- /** Monospaced small-caps label: for stats, counts, bylines. */
28
- export function stat(content: unknown, extraCls = '') {
29
- return html`
30
- <span class="font-mono text-[11px] leading-none font-medium tracking-[0.15em] uppercase text-fg-subtle ${extraCls}">${content}</span>
31
- `;
32
- }
33
-
34
- /** "← label" back link. */
35
- export function backLink(href: string, label: string, mb: 'sm' | 'md' = 'md') {
36
- const mbCls = mb === 'sm' ? 'mb-6' : 'mb-12';
37
- return html`
38
- <a href=${href} class="inline-block ${mbCls} text-fg-subtle no-underline font-mono text-[11px] leading-none font-medium tracking-[0.15em] uppercase transition-colors duration-fast hover:text-fg">← ${label}</a>
39
- `;
40
- }
41
-
42
- /** Large display heading: home / detail hero. */
43
- export function displayH1(content: unknown) {
44
- return html`
45
- <h1 class="font-serif text-display leading-[1.02] tracking-[-0.035em] font-bold m-0 mb-6 text-balance">${content}</h1>
46
- `;
47
- }
48
-
49
- /** Clamp-scale H1: login, compose, etc. */
50
- export function clampH1(content: unknown) {
51
- return html`
52
- <h1 class="font-serif text-[clamp(2rem,1.5rem+1.6vw,2.8rem)] leading-[1.08] tracking-[-0.03em] font-bold m-0 mb-6">${content}</h1>
53
- `;
54
- }
55
-
56
- /** Section H2: serif subheading. */
57
- export function sectionH2(content: unknown, mb: 'sm' | 'md' = 'sm') {
58
- const mbCls = mb === 'sm' ? 'mb-2' : 'mb-4';
59
- return html`
60
- <h2 class="font-serif text-[1.6rem] tracking-[-0.02em] font-bold m-0 ${mbCls}">${content}</h2>
61
- `;
62
- }
63
-
64
- /** Notice / banner paragraph: soft card above primary content. */
65
- export function banner(content: unknown) {
66
- return html`
67
- <p class="p-6 bg-[color-mix(in_oklch,var(--bg-elev)_50%,transparent)] border border-border rounded-[10px] text-sm my-6 mb-12 text-fg-muted">${content}</p>
68
- `;
69
- }
70
-
71
- /** Inline brand link: used inside body copy and banners. */
72
- export function accentLink(href: string, label: unknown) {
73
- return html`
74
- <a href=${href} class="text-primary font-semibold no-underline hover:underline hover:underline-offset-[3px]">${label}</a>
75
- `;
76
- }
77
-
78
- /** Small code chip: inline monospaced token with a tinted surface. */
79
- export function codeChip(text: string) {
80
- return html`
81
- <code class="font-mono text-[0.88em] px-1.5 py-0.5 rounded-md bg-bg-subtle border border-border break-words [overflow-wrap:anywhere]">${text}</code>
82
- `;
83
- }