create-hozu 0.3.0 → 0.4.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/skill/reference.md +30 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-hozu",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "description": "Create a Hozu app, set up for Claude Code or for agents that read AGENTS.md",
5
5
  "keywords": [
6
6
  "hozu",
@@ -21,9 +21,30 @@ export const docs = route({ path: '/docs/:path+', params: z.object({ path: z.arr
21
21
  literal option values are all members, so one submit carries a title and a priority.
22
22
  - `ui.dom.valueAsNumber` (number | null), `ui.dom.checked`, `ui.dom.key`, and similar event fields.
23
23
  - Also: `ui.html(value)` (trusted HTML from query data only, HZ030), `ui.asset(new URL('./x.png', import.meta.url))`,
24
- `ui.window({ on })` / `ui.document({ on })` for global listeners, widgets (`ui.widget` / `ui.use`) for
24
+ `ui.window({ on })` / `ui.document({ on })` for global listeners, widgets (see Widgets) for browser APIs and
25
25
  third-party DOM libraries.
26
26
 
27
+ ## Widgets (browser APIs, DOM libraries)
28
+ There is no `widget` export: declare with `ui.widget`, place with `ui.use`, list the declaration in the feature's
29
+ `declarations`, and implement it in a client module.
30
+ ```ts
31
+ export const Copy = ui.widget({ tag: 'button', props: z.object({ text: z.string() }),
32
+ events: { copied: z.object({}) }, client: new URL('./copy.client.ts', import.meta.url), load: 'visible', wraps: true })
33
+ ui.use(Copy, { props: { text: block.code }, on: { copied: () => ui.send(Copied, {}) }, class: 'btn' }, ['Copy'])
34
+ ```
35
+ ```ts
36
+ // copy.client.ts: a type-only import of the declaration
37
+ import { implement } from '@hozu/core/widget'
38
+ import type { Copy } from './widgets.ts'
39
+ export default implement<typeof Copy>(({ el, props, emit, signal }) => {
40
+ el.addEventListener('click', () => navigator.clipboard.writeText(props.text).then(() => emit('copied', {})), { signal })
41
+ return { update(next) { props = next } }
42
+ })
43
+ ```
44
+ `load`: `'eager' | 'visible' | 'idle'`; `wraps: true` keeps the children as server HTML. Serve with
45
+ `widgets: await bundleWidgets(build)` from `@hozu/bundle` (and pass it to `exportStatic`); `hozu build` bundles
46
+ them itself (HZ029 for a client module that does not bundle).
47
+
27
48
  ## Forms without JavaScript
28
49
  A submit whose payload reads only `ui.dom.form('name')`, literals, context, params and search also works without JS
29
50
  (otherwise HZ036 warns). The server runs the same machine and mutation, then redirects (on `navigate`, or when the
@@ -112,8 +133,12 @@ There are no rewrites: one URL has one owner.
112
133
  dimensions). With `@hozu/image` installed, pass `images: await optimizeImages(build)` to `createServer` (and
113
134
  `hozu build` does it itself): raster assets get WebP `srcset` widths and `sizes`.
114
135
  - **Share images:** `head.render` → `image: ui.og({ title, subtitle })` renders a 1200×630 card; pass
115
- `og: ogImage` (from `@hozu/image`) to `createServer`.
136
+ `og: ogImage` (from `@hozu/image`) to `createServer`. On a static host, use a file instead:
137
+ `image: ui.asset(new URL('./share.png', import.meta.url))` (made absolute with `site.url`).
116
138
  - **Fonts:** a local `@font-face` gets a size-matched `"<Family> Fallback"` automatically.
139
+ - **Page transitions:** the stylesheet turns on cross-document view transitions, so links between pages cross-fade
140
+ instead of flashing (no JS). Turn them off with `@view-transition { navigation: none; }` in `app.css`; style them
141
+ with `::view-transition-*`.
117
142
 
118
143
  ## Preview (drafts)
119
144
  `createServer({ preview: { secret } })`; `GET /_hozu/preview?secret=…&path=/posts/a` turns preview on (a signed
@@ -136,6 +161,9 @@ Cloudflare Workers or Vercel the server is `createHandler({ build, manifest, res
136
161
  `@hozu/runtime-server` with `export default { fetch: handler.fetch }`, where
137
162
  `import * as render from './dist/server/render.js'` is the page code `hozu build` generates (edge runtimes cannot
138
163
  generate it at startup). Page cache and tag revalidation are per instance.
164
+ A fully static site (GitHub Pages, any file host): `exportStatic({ build, styles, resolvers, outDir })` from
165
+ `@hozu/adapter-static` writes every page without per-request data, plus the files they link to, and lists skipped
166
+ routes.
139
167
  ```ts
140
168
  import manifest from './dist/manifest.json' with { type: 'json' }
141
169
  import * as render from './dist/server/render.js'