@nextwebwg/htmlkit 1.0.0-alpha.35 → 1.0.0-alpha.36

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/README.md +4 -257
  2. package/package.json +2 -2
package/README.md CHANGED
@@ -5,7 +5,7 @@ layouts, server loaders, browser delivery, and development tools. The first prod
5
5
  generates static pages; [the server-rendering design](./docs/server-rendering.md) preserves a path
6
6
  to request-time rendering.
7
7
 
8
- Use Node 22.13+ or Node 24 and Corepack pnpm. Install `@nextwebwg/htmlkit`, then run:
8
+ Use Node `>=22.22.2 <23 || >=24.15 <25` and Corepack pnpm. Install `@nextwebwg/htmlkit`, then run:
9
9
 
10
10
  ```sh
11
11
  corepack pnpm exec htmlkit dev
@@ -13,262 +13,9 @@ corepack pnpm exec htmlkit build
13
13
  corepack pnpm exec htmlkit preview
14
14
  ```
15
15
 
16
- Commands accept an optional application root and `--base /docs/`, `--origin https://example.com`,
17
- `--out-dir dist`, `--port 3000`, and `--host 127.0.0.1`. Development and preview default to loopback.
18
- Preview serves the built files without running loaders. Deploy `dist` to a static host at the chosen
19
- base path; configure its missing-page response to use `404.html`.
20
-
21
- ## Routes and layouts
22
-
23
- File routes follow familiar Nuxt directory and parameter names:
24
-
25
- ```text
26
- app/
27
- components/ reusable HTML Next components
28
- layouts/
29
- default.html automatic shared shell
30
- default.server.ts optional shell loader
31
- admin.html named alternative shell
32
- pages/
33
- index.html /
34
- index.server.ts optional home loader
35
- about.html /about/
36
- items/
37
- [slug].html /items/[slug]/
38
- [slug].server.ts loader and static entries
39
- public/ files copied to the deployment root
40
- htmlkit.config.ts optional configuration
41
- ```
42
-
43
- A page resource selects one entry component. A single definition is inferred; a file with helper
44
- components must select its page using `<meta name="htmlkit:page" content="page-products">`.
45
- Selection never depends on declaration order. The file-level selector is separate from component-owned
46
- metadata: each page or layout declares its own title, description, links, and layout choice as direct
47
- children of its `<template component>`. Helpers use ordinary HTML Next component semantics; their
48
- metadata never contributes to the page head, even when the page renders them.
49
- Layouts each declare one root component and project the page through `<slot name="page"></slot>`.
50
- Component links and controllers use existing HTML Next syntax and resolution rules. Keep non-page
51
- resources outside `app/pages`; filenames beginning with `_` or `.` are ignored by file routing.
52
-
53
- Page component names must be unique across the application, including both file and registered
54
- routes. Discovery reports both conflicting files and route patterns before executing any loaders
55
- or controllers. Use `page-` by convention, for example `page-home`, `page-products`, and
56
- `page-product-detail`; the prefix is recommended rather than required. One page definition may
57
- serve several registered route aliases or many parameter values without needing another name.
58
- Renaming a page requires route rediscovery; the development server does this on file changes.
59
-
60
- Route URLs, component names, and bundle locations are separate identities. For example,
61
- `app/pages/shop.html` may declare `component="page-products"`; its URL is `/shop/`, and its generated
62
- browser module has an independent build-assigned location. `ApplicationRoute.pageName` exposes the
63
- component name separately from `pattern` and the `component` source path. The deployment manifest's
64
- `pages` records likewise separate `pathname`, `pageName`, and `browserModule`, so bundle grouping
65
- does not define application routes or authored component names.
66
-
67
- Each filename contributes a URL segment; `index.html` names its directory's URL. Whole segments
68
- such as `[slug]` become parameters. Literal segments take priority over parameters. Routes have
69
- trailing slashes; preview redirects directory URLs that omit them. Equivalent patterns and output
70
- collisions are errors. Optional parameters, mixed parameter segments, groups, catch-all routes,
71
- and client routing are outside this first delivery.
72
-
73
- The default layout is `app/layouts/default.html` when present. Page metadata chooses a named
74
- layout or disables it with `content="none"`. Layout selection is independent of the route URL;
75
- choosing `admin` replaces the default shell. Nested shells can compose ordinary HTML Next
76
- components explicitly. Adding a parent page never wraps descendant routes.
77
-
78
- ```html
79
- <template component="page-products">
80
- <meta name="htmlkit:layout" content="admin">
81
- <meta name="description" content="Manage your products.">
82
- <meta property="og:title" content="Product administration">
83
- <title>Products · Admin</title>
84
-
85
- <article><h1>Products</h1></article>
86
- </template>
87
- ```
88
-
89
- A layout uses normal component syntax:
90
-
91
- ```html
92
- <template component="admin-shell">
93
- <title>Administration</title>
94
- <meta name="description" content="Administration tools.">
95
- <main><header>Administration</header><slot name="page"></slot></main>
96
- </template>
97
- ```
98
-
99
- `htmlkit:*` metadata configures the build and is removed from the generated document. Ordinary
100
- `title`, `meta`, and metadata `link` elements directly inside a selected carrier contribute to the
101
- document head. They are siblings of `<defs>`, the rendered root, and `<style>`; no `<head>` wrapper
102
- is needed. Keep only `htmlkit:page` and component dependency links at file scope. HTMLKit diagnoses
103
- file-level head metadata instead of silently assigning it to a component. The regular HTML Next
104
- resource loader accepts and ignores resource-level and direct carrier metadata;
105
- it does not select layouts, update a host document, or evaluate their bindings. Resource-level
106
- `style`, `script`, `base`, policy `meta` (`http-equiv`), and arbitrary body nodes are rejected.
107
- Component styles inside a carrier and controller references retain their normal behavior.
108
-
109
- Head values may bind to the selected component's declared props, populated by its loader, using
110
- the existing HTML Next binding syntax:
111
-
112
- ```html
113
- <template component="page-item">
114
- <title $value="$label"></title>
115
- <meta name="description" from:content="$description">
116
- <link rel="canonical" from:href="$canonicalURL">
117
- <defs>
118
- <prop name="label" type="string" required>Item label</prop>
119
- <prop name="description" type="string" required>Description</prop>
120
- <prop name="canonicalURL" type="string" required>Canonical URL</prop>
121
- </defs>
122
- <article><h1 $value="$label"></h1></article>
123
- </template>
124
- ```
125
-
126
- Head bindings use the same parser, prop contracts, serialization, and renderer as body bindings.
127
- They run during rendering against props; they do not start browser controllers, reads, or reactive
128
- subscriptions. Layout metadata supplies defaults. A page replaces matching title, description,
129
- meta name/property, canonical link, or alternate language/type/media defaults. The last singleton
130
- in a layer wins. Stylesheets and alternate languages remain repeatable; social image arrays stay
131
- ordered, and a page's image group replaces the layout's image group. A loader's `head` fields take
132
- precedence over that layer's declarative title/description. Values are escaped when assembled.
133
- Use public URLs (including `base` where needed) for head links; these links do not enter Vite's
134
- component stylesheet pipeline.
135
-
136
- Its `[slug].server.ts` can export:
137
-
138
- ```ts
139
- import type { LoadContext, LoaderResult } from '@nextwebwg/htmlkit';
140
-
141
- export const entries = () => [{ slug: 'one' }, { slug: 'two' }];
142
- export function load({ params }: LoadContext): LoaderResult {
143
- return {
144
- props: {
145
- label: `Item ${params.slug}`, description: `Details for ${params.slug}`,
146
- canonicalURL: `https://example.com/items/${params.slug}/`,
147
- },
148
- head: { title: `Item ${params.slug}` },
149
- };
150
- }
151
- ```
152
-
153
- Development can render any matching parameter value. Static production requires `entries()` to
154
- list every intended parameterized page, including parameters from ancestor directories. It must
155
- return a nonempty array with exactly the declared parameter keys. Values must be single URL
156
- segments. Discovery and enumeration produce a complete build manifest; no link crawler decides
157
- which pages exist.
158
-
159
- ## Loaders and browser behavior
160
-
161
- `.server.ts` and `.server.js` modules run only in Node. Layout loaders run outermost first, then the
162
- page loader. Each receives `phase: 'prerender'`, `url`, `params`, `base`, `parent`, `fetch`, and
163
- `signal`. `parent` merges the preceding loaders' `data` objects; later keys take precedence.
164
- Use `base` when constructing application links or public asset URLs. `url` uses the configured
165
- canonical origin, not a preview reader's request. Query parameters and request data are unavailable
166
- in this static adapter; accessing `context.request` throws a source diagnostic.
167
-
168
- Each loader returns `props`, `state`, `data`, and/or `head` (`title`, `description`, `lang`). Props
169
- and state belong to that loader's page or layout, are checked by HTML Next, and become **public
170
- HTML**, including structured values. `data` stays in the loader chain unless a descendant puts it
171
- into a public prop or state. Never place secrets in props or state. Inner head fields override outer
172
- ones. Each render runs loaders again; application module globals are not isolated between renders.
173
-
174
- Node uses HTML Next's renderer for the baseline. It executes neither browser controllers nor
175
- declared browser reads. Per-page browser modules register parsed definitions and let HTML Next
176
- adopt existing DOM, resume reads, and connect controllers. The platform adds no parser, scheduler,
177
- hydration record, or lifecycle registry. Document navigation uses native links. The browser emits
178
- `htmlkit:ready` on `document` after initial observation is installed.
179
-
180
- Relative declared read sources are bundled as assets beside the browser delivery. Root-relative
181
- read URLs are prefixed with the application base; absolute HTTP(S) sources retain their origin.
182
- Reads remain pending in Node and start through HTML Next on browser connection.
183
-
184
- Component CSS is emitted as an external stylesheet. Vite handles controller imports, their CSS
185
- imports, and imported assets. Files under `public` retain their names; `_htmlkit` and `404.html`
186
- are reserved. Public assets may not be symlinks. Builds stage output beside the deployment
187
- directory and replace it after successful rendering and bundling. An existing nonempty output
188
- directory must contain an HTMLKit manifest before HTMLKit will replace it.
189
-
190
- Development uses the same renderer and loaders, with Vite serving browser modules. Changes trigger
191
- a full document reload, including loader dependencies, component HTML, and added/removed routes.
192
- Errors appear with source information in the preview response. Native form behavior and controller
193
- cleanup remain HTML Next's responsibility.
194
-
195
- ## Explicit routes and library API
196
-
197
- Use `htmlkit.config.ts` (or `.js`) for configuration. Explicit routes supplement file routes, or
198
- set `fileRoutes: false` for a fully registered route table:
199
-
200
- ```ts
201
- import { defineConfig } from '@nextwebwg/htmlkit';
202
-
203
- export default defineConfig({
204
- base: '/docs/',
205
- layoutDefaults: { '/admin/': 'admin', '/account/': 'account' },
206
- routes: [{
207
- pattern: '/catalog/[id]/',
208
- component: 'app/catalog/item.html',
209
- server: 'app/catalog/item.server.ts',
210
- layouts: [{ component: 'app/catalog/shell.html' }],
211
- }],
212
- });
213
- ```
214
-
215
- Page layout metadata wins over the most specific `layoutDefaults` directory prefix, then the
216
- application `layout` option (a name or `false`), then the automatic default layout. Registered
217
- `layouts` can supply an explicit outer-to-inner chain when no named/default override is chosen.
218
-
219
- Paths are relative to the application root. Explicit routes use the same parameter, loader,
220
- composition, collision, and entry rules as file routes; they do not create another renderer.
221
- No config file is read implicitly by the library API: pass options directly to `createApplication`,
222
- `buildApplication`, `devApplication`, or `previewApplication`. Close returned applications and
223
- servers when finished. `Application.render(pathname, signal?)` returns a baseline document, body,
224
- styles, metadata, and the parsed component graph; browser delivery is added by dev/build.
225
-
226
- ## Ordered file routes and navigation
227
-
228
- Enable `routeOrdering: true` to use numeric filename and directory prefixes. For example,
229
- `app/pages/01-guide/02-install.html` becomes `/guide/install/`, and `01-index.html` becomes
230
- its directory's landing page. Prefixes sort numerically (1, 2, 10); unprefixed siblings follow
231
- prefixed siblings. Directory landing pages precede their descendants. Numeric ties use the URL
232
- as a deterministic tie-breaker. Empty stripped segments and URL collisions are errors naming
233
- the physical sources. Registered route patterns keep their authored URLs. The default is false.
234
-
235
- Navigation contains only concrete routes, including aliases and enumerated dynamic entries.
236
- Unenumerated dynamic patterns are omitted; static builds still require their `entries()`.
237
- A loader can query a subtree using an application-relative prefix; hrefs include the deployment base:
238
-
239
- ```ts
240
- import type { LoadContext } from '@nextwebwg/htmlkit';
241
-
242
- export async function load({ navigation }: LoadContext) {
243
- return { props: { navigation: await navigation({ from: '/guide/' }) } };
244
- }
245
- ```
246
-
247
- ```html
248
- <link rel="component" href="@nextwebwg/htmlkit/components/navigation.html">
249
- <template component="site-shell">
250
- <defs>
251
- <prop name="navigation" type="list(object({ href: string, label: string, current: string, depth: number, pageName: string }))" required>Links</prop>
252
- </defs>
253
- <main>
254
- <htmlkit-navigation from:items="$navigation" label="Guide"></htmlkit-navigation>
255
- <slot name="page"></slot>
256
- </main>
257
- </template>
258
- ```
259
-
260
- Each item has `href`, a default `label` from the final URL segment (Home at the root),
261
- `current` (`page` or `false` for `aria-current`), `depth` relative to the selected subtree,
262
- and `pageName`. Project labels and visibility policy can be applied in the loader. The component
263
- renders native anchors in a flat list with `data-depth` on each item; it adds no controller or theme.
264
-
265
- `application.navigation({ from, current })` is also available outside loaders. `from` defaults
266
- to `/`; `current` is a deployment pathname and defaults to the current page inside a loader.
267
- Static entries are materialized once per application so rendering and navigation use the same catalog.
268
-
269
- Controllers can be authored as `counter.ts` and referenced from HTML as `controller="./counter.js"`.
270
- Vite resolves and transpiles the source for development and production. Run TypeScript separately
271
- for type checking; browser URLs refer to JavaScript bundles.
16
+ **Guide:** [nextwebwg.org/htmlkit](https://nextwebwg.org/htmlkit/) covers routes and layouts,
17
+ loaders and browser delivery, ordered routes and navigation, and configuration. Its source is
18
+ [`docs/guide`](./docs/guide/) in this package.
272
19
 
273
20
  ## Proof applications
274
21
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextwebwg/htmlkit",
3
- "version": "1.0.0-alpha.35",
3
+ "version": "1.0.0-alpha.36",
4
4
  "description": "HTML Next application platform: file-based routes, layouts, loaders, and static deployment.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -20,7 +20,7 @@
20
20
  "node": ">=22.22.2 <23 || >=24.15 <25"
21
21
  },
22
22
  "dependencies": {
23
- "@nextwebwg/html-next": "1.0.0-alpha.35",
23
+ "@nextwebwg/html-next": "1.0.0-alpha.36",
24
24
  "vite": "8.3.2",
25
25
  "parse5": "8.0.1"
26
26
  },