gethtmlpress 0.0.0 → 0.2.0

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
@@ -1,3 +1,49 @@
1
- # gethtmlpress
1
+ # Htmlpress
2
2
 
3
- Placeholder. [htmlpress](https://htmlpress.dev) ships on npm from 0.1.0.
3
+ Htmlpress turns a folder of HTML pages into a site. Each page keeps its own markup, and
4
+ htmlpress adds one layout, one theme, a navigation and a live-reloading dev server. It is
5
+ made for coding agents: they write plain semantic HTML, and the result looks consistent
6
+ without a framework, a build config or Tailwind.
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ npm install --global gethtmlpress
12
+ # or run it without installing
13
+ npx gethtmlpress build docs
14
+ ```
15
+
16
+ The package carries a prebuilt binary for Linux, macOS and Windows (x64 and arm64)
17
+ through a platform-specific optional dependency; no Rust toolchain is needed.
18
+
19
+ ## Usage
20
+
21
+ ```bash
22
+ htmlpress build docs # render docs/ into docs/.htmlpress/build
23
+ htmlpress start docs # serve it on http://localhost:8000, rebuilding on save
24
+ htmlpress build docs --json # the result as JSON, for scripts and agents
25
+ htmlpress --llms # every command's input and output schema, for agents
26
+ ```
27
+
28
+ A page is any `.html` file in the folder: a full document or just a fragment. Its `<title>`
29
+ (else its first `<h1>`) names it in the navigation, `<meta name="order" content="1">` sorts it,
30
+ and `index.html` comes first. Every other file is copied as-is.
31
+
32
+ ```html
33
+ <title>Getting started</title>
34
+ <meta name="order" content="1" />
35
+
36
+ <h1>Getting started</h1>
37
+ <p>Plain HTML, styled by the built-in theme.</p>
38
+ <htmlpress-callout type="warning"
39
+ ><p>Light-DOM components cover what HTML lacks.</p></htmlpress-callout
40
+ >
41
+ ```
42
+
43
+ ## Documentation
44
+
45
+ Read the docs at [htmlpress.dev](https://htmlpress.dev), themselves built with htmlpress.
46
+
47
+ ## License
48
+
49
+ MIT.
@@ -0,0 +1,7 @@
1
+ /** Find the htmlpress binary: the env override first, else the matching platform package. */
2
+ export declare function resolveBinary(props: {
3
+ platform: string;
4
+ arch: string;
5
+ env: Record<string, string | undefined>;
6
+ resolvePackage: (specifier: string) => string;
7
+ }): string;
@@ -0,0 +1,22 @@
1
+ import { BINARY_ENV, PACKAGE_NAME, PLATFORMS } from "../../settings.js";
2
+ /** Find the htmlpress binary: the env override first, else the matching platform package. */
3
+ export function resolveBinary(props) {
4
+ const override = props.env[BINARY_ENV];
5
+ if (override)
6
+ return override;
7
+ const key = `${props.platform}-${props.arch}`;
8
+ const platform = PLATFORMS[key];
9
+ if (!platform) {
10
+ const supported = Object.keys(PLATFORMS).join(", ");
11
+ throw new Error(`${PACKAGE_NAME} has no binary for ${key}; supported: ${supported}. ` +
12
+ `Set ${BINARY_ENV} to a binary built with cargo to run it anyway.`);
13
+ }
14
+ try {
15
+ return props.resolvePackage(`${platform.packageName}/bin/${platform.binary}`);
16
+ }
17
+ catch {
18
+ throw new Error(`${platform.packageName} is not installed. Reinstall ${PACKAGE_NAME} without ` +
19
+ `--no-optional / --omit=optional so the binary for ${key} comes along.`);
20
+ }
21
+ }
22
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzb2x2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2FjdGlvbnMvYmluYXJ5L3Jlc29sdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFFLE1BQU0sbUJBQW1CLENBQUE7QUFFdkUsNkZBQTZGO0FBQzdGLE1BQU0sVUFBVSxhQUFhLENBQUMsS0FLN0I7SUFDQyxNQUFNLFFBQVEsR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFBO0lBQ3RDLElBQUksUUFBUTtRQUFFLE9BQU8sUUFBUSxDQUFBO0lBRTdCLE1BQU0sR0FBRyxHQUFHLEdBQUcsS0FBSyxDQUFDLFFBQVEsSUFBSSxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUE7SUFDN0MsTUFBTSxRQUFRLEdBQUcsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFBO0lBQy9CLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNkLE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQ25ELE1BQU0sSUFBSSxLQUFLLENBQ2IsR0FBRyxZQUFZLHNCQUFzQixHQUFHLGdCQUFnQixTQUFTLElBQUk7WUFDbkUsT0FBTyxVQUFVLGlEQUFpRCxDQUNyRSxDQUFBO0lBQ0gsQ0FBQztJQUNELElBQUksQ0FBQztRQUNILE9BQU8sS0FBSyxDQUFDLGNBQWMsQ0FBQyxHQUFHLFFBQVEsQ0FBQyxXQUFXLFFBQVEsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUE7SUFDL0UsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLE1BQU0sSUFBSSxLQUFLLENBQ2IsR0FBRyxRQUFRLENBQUMsV0FBVyxnQ0FBZ0MsWUFBWSxXQUFXO1lBQzVFLHFEQUFxRCxHQUFHLGVBQWUsQ0FDMUUsQ0FBQTtJQUNILENBQUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQklOQVJZX0VOViwgUEFDS0FHRV9OQU1FLCBQTEFURk9STVMgfSBmcm9tIFwiLi4vLi4vc2V0dGluZ3MudHNcIlxuXG4vKiogRmluZCB0aGUgaHRtbHByZXNzIGJpbmFyeTogdGhlIGVudiBvdmVycmlkZSBmaXJzdCwgZWxzZSB0aGUgbWF0Y2hpbmcgcGxhdGZvcm0gcGFja2FnZS4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlQmluYXJ5KHByb3BzOiB7XG4gIHBsYXRmb3JtOiBzdHJpbmdcbiAgYXJjaDogc3RyaW5nXG4gIGVudjogUmVjb3JkPHN0cmluZywgc3RyaW5nIHwgdW5kZWZpbmVkPlxuICByZXNvbHZlUGFja2FnZTogKHNwZWNpZmllcjogc3RyaW5nKSA9PiBzdHJpbmdcbn0pIHtcbiAgY29uc3Qgb3ZlcnJpZGUgPSBwcm9wcy5lbnZbQklOQVJZX0VOVl1cbiAgaWYgKG92ZXJyaWRlKSByZXR1cm4gb3ZlcnJpZGVcblxuICBjb25zdCBrZXkgPSBgJHtwcm9wcy5wbGF0Zm9ybX0tJHtwcm9wcy5hcmNofWBcbiAgY29uc3QgcGxhdGZvcm0gPSBQTEFURk9STVNba2V5XVxuICBpZiAoIXBsYXRmb3JtKSB7XG4gICAgY29uc3Qgc3VwcG9ydGVkID0gT2JqZWN0LmtleXMoUExBVEZPUk1TKS5qb2luKFwiLCBcIilcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgJHtQQUNLQUdFX05BTUV9IGhhcyBubyBiaW5hcnkgZm9yICR7a2V5fTsgc3VwcG9ydGVkOiAke3N1cHBvcnRlZH0uIGAgK1xuICAgICAgICBgU2V0ICR7QklOQVJZX0VOVn0gdG8gYSBiaW5hcnkgYnVpbHQgd2l0aCBjYXJnbyB0byBydW4gaXQgYW55d2F5LmAsXG4gICAgKVxuICB9XG4gIHRyeSB7XG4gICAgcmV0dXJuIHByb3BzLnJlc29sdmVQYWNrYWdlKGAke3BsYXRmb3JtLnBhY2thZ2VOYW1lfS9iaW4vJHtwbGF0Zm9ybS5iaW5hcnl9YClcbiAgfSBjYXRjaCB7XG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYCR7cGxhdGZvcm0ucGFja2FnZU5hbWV9IGlzIG5vdCBpbnN0YWxsZWQuIFJlaW5zdGFsbCAke1BBQ0tBR0VfTkFNRX0gd2l0aG91dCBgICtcbiAgICAgICAgYC0tbm8tb3B0aW9uYWwgLyAtLW9taXQ9b3B0aW9uYWwgc28gdGhlIGJpbmFyeSBmb3IgJHtrZXl9IGNvbWVzIGFsb25nLmAsXG4gICAgKVxuICB9XG59XG4iXX0=
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env node
2
+ import { spawnSync } from "node:child_process";
3
+ import { createRequire } from "node:module";
4
+ import { resolveBinary } from "../actions/binary/resolve.js";
5
+ const require = createRequire(import.meta.url);
6
+ let binary;
7
+ try {
8
+ binary = resolveBinary({
9
+ platform: process.platform,
10
+ arch: process.arch,
11
+ env: process.env,
12
+ resolvePackage: specifier => require.resolve(specifier),
13
+ });
14
+ }
15
+ catch (error) {
16
+ console.error(`error: ${error instanceof Error ? error.message : String(error)}`);
17
+ process.exit(1);
18
+ }
19
+ const result = spawnSync(binary, process.argv.slice(2), { stdio: "inherit" });
20
+ if (result.error) {
21
+ console.error(`error: cannot run ${binary}: ${result.error.message}`);
22
+ process.exit(1);
23
+ }
24
+ // Re-raise a signal so a parent sees the same death the binary had (Ctrl-C under start)
25
+ if (result.signal)
26
+ process.kill(process.pid, result.signal);
27
+ process.exit(result.status ?? 1);
28
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL2VudHJ5cG9pbnRzL21haW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUNBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQTtBQUM5QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sYUFBYSxDQUFBO0FBQzNDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQTtBQUU1RCxNQUFNLE9BQU8sR0FBRyxhQUFhLENBQUMsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUE7QUFFOUMsSUFBSSxNQUFjLENBQUE7QUFDbEIsSUFBSSxDQUFDO0lBQ0gsTUFBTSxHQUFHLGFBQWEsQ0FBQztRQUNyQixRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVE7UUFDMUIsSUFBSSxFQUFFLE9BQU8sQ0FBQyxJQUFJO1FBQ2xCLEdBQUcsRUFBRSxPQUFPLENBQUMsR0FBRztRQUNoQixjQUFjLEVBQUUsU0FBUyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQztLQUN4RCxDQUFDLENBQUE7QUFDSixDQUFDO0FBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztJQUNmLE9BQU8sQ0FBQyxLQUFLLENBQUMsVUFBVSxLQUFLLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFBO0lBQ2pGLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUE7QUFDakIsQ0FBQztBQUVELE1BQU0sTUFBTSxHQUFHLFNBQVMsQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLENBQUMsQ0FBQTtBQUM3RSxJQUFJLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUNqQixPQUFPLENBQUMsS0FBSyxDQUFDLHFCQUFxQixNQUFNLEtBQUssTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFBO0lBQ3JFLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUE7QUFDakIsQ0FBQztBQUNELHdGQUF3RjtBQUN4RixJQUFJLE1BQU0sQ0FBQyxNQUFNO0lBQUUsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQTtBQUMzRCxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUFDLENBQUEiLCJzb3VyY2VzQ29udGVudCI6WyIjIS91c3IvYmluL2VudiBub2RlXG5pbXBvcnQgeyBzcGF3blN5bmMgfSBmcm9tIFwibm9kZTpjaGlsZF9wcm9jZXNzXCJcbmltcG9ydCB7IGNyZWF0ZVJlcXVpcmUgfSBmcm9tIFwibm9kZTptb2R1bGVcIlxuaW1wb3J0IHsgcmVzb2x2ZUJpbmFyeSB9IGZyb20gXCIuLi9hY3Rpb25zL2JpbmFyeS9yZXNvbHZlLnRzXCJcblxuY29uc3QgcmVxdWlyZSA9IGNyZWF0ZVJlcXVpcmUoaW1wb3J0Lm1ldGEudXJsKVxuXG5sZXQgYmluYXJ5OiBzdHJpbmdcbnRyeSB7XG4gIGJpbmFyeSA9IHJlc29sdmVCaW5hcnkoe1xuICAgIHBsYXRmb3JtOiBwcm9jZXNzLnBsYXRmb3JtLFxuICAgIGFyY2g6IHByb2Nlc3MuYXJjaCxcbiAgICBlbnY6IHByb2Nlc3MuZW52LFxuICAgIHJlc29sdmVQYWNrYWdlOiBzcGVjaWZpZXIgPT4gcmVxdWlyZS5yZXNvbHZlKHNwZWNpZmllciksXG4gIH0pXG59IGNhdGNoIChlcnJvcikge1xuICBjb25zb2xlLmVycm9yKGBlcnJvcjogJHtlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IubWVzc2FnZSA6IFN0cmluZyhlcnJvcil9YClcbiAgcHJvY2Vzcy5leGl0KDEpXG59XG5cbmNvbnN0IHJlc3VsdCA9IHNwYXduU3luYyhiaW5hcnksIHByb2Nlc3MuYXJndi5zbGljZSgyKSwgeyBzdGRpbzogXCJpbmhlcml0XCIgfSlcbmlmIChyZXN1bHQuZXJyb3IpIHtcbiAgY29uc29sZS5lcnJvcihgZXJyb3I6IGNhbm5vdCBydW4gJHtiaW5hcnl9OiAke3Jlc3VsdC5lcnJvci5tZXNzYWdlfWApXG4gIHByb2Nlc3MuZXhpdCgxKVxufVxuLy8gUmUtcmFpc2UgYSBzaWduYWwgc28gYSBwYXJlbnQgc2VlcyB0aGUgc2FtZSBkZWF0aCB0aGUgYmluYXJ5IGhhZCAoQ3RybC1DIHVuZGVyIHN0YXJ0KVxuaWYgKHJlc3VsdC5zaWduYWwpIHByb2Nlc3Mua2lsbChwcm9jZXNzLnBpZCwgcmVzdWx0LnNpZ25hbClcbnByb2Nlc3MuZXhpdChyZXN1bHQuc3RhdHVzID8/IDEpXG4iXX0=
@@ -0,0 +1,14 @@
1
+ export interface Platform {
2
+ /** The npm package that carries this platform's binary. */
3
+ packageName: string;
4
+ /** The Rust target the binary is compiled for. */
5
+ target: string;
6
+ /** The binary's file name inside the package's `bin/`. */
7
+ binary: string;
8
+ }
9
+ /** The npm package users install; it pulls in the one platform package that matches. */
10
+ export declare const PACKAGE_NAME = "gethtmlpress";
11
+ /** An environment variable that points at a binary to run instead of the installed one. */
12
+ export declare const BINARY_ENV = "HTMLPRESS_BINARY";
13
+ /** Every published platform, keyed by `${process.platform}-${process.arch}`. */
14
+ export declare const PLATFORMS: Record<string, Platform>;
@@ -0,0 +1,18 @@
1
+ /** The npm package users install; it pulls in the one platform package that matches. */
2
+ export const PACKAGE_NAME = "gethtmlpress";
3
+ /** An environment variable that points at a binary to run instead of the installed one. */
4
+ export const BINARY_ENV = "HTMLPRESS_BINARY";
5
+ /** Every published platform, keyed by `${process.platform}-${process.arch}`. */
6
+ export const PLATFORMS = {
7
+ "linux-x64": createPlatform("linux-x64", "x86_64-unknown-linux-musl"),
8
+ "linux-arm64": createPlatform("linux-arm64", "aarch64-unknown-linux-musl"),
9
+ "darwin-x64": createPlatform("darwin-x64", "x86_64-apple-darwin"),
10
+ "darwin-arm64": createPlatform("darwin-arm64", "aarch64-apple-darwin"),
11
+ "win32-x64": createPlatform("win32-x64", "x86_64-pc-windows-msvc"),
12
+ "win32-arm64": createPlatform("win32-arm64", "aarch64-pc-windows-msvc"),
13
+ };
14
+ function createPlatform(key, target) {
15
+ const binary = key.startsWith("win32") ? "htmlpress.exe" : "htmlpress";
16
+ return { packageName: `@htmlpress/${key}`, target, binary };
17
+ }
18
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2V0dGluZ3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zZXR0aW5ncy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFTQSx3RkFBd0Y7QUFDeEYsTUFBTSxDQUFDLE1BQU0sWUFBWSxHQUFHLGNBQWMsQ0FBQTtBQUUxQywyRkFBMkY7QUFDM0YsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHLGtCQUFrQixDQUFBO0FBRTVDLGdGQUFnRjtBQUNoRixNQUFNLENBQUMsTUFBTSxTQUFTLEdBQTZCO0lBQ2pELFdBQVcsRUFBRSxjQUFjLENBQUMsV0FBVyxFQUFFLDJCQUEyQixDQUFDO0lBQ3JFLGFBQWEsRUFBRSxjQUFjLENBQUMsYUFBYSxFQUFFLDRCQUE0QixDQUFDO0lBQzFFLFlBQVksRUFBRSxjQUFjLENBQUMsWUFBWSxFQUFFLHFCQUFxQixDQUFDO0lBQ2pFLGNBQWMsRUFBRSxjQUFjLENBQUMsY0FBYyxFQUFFLHNCQUFzQixDQUFDO0lBQ3RFLFdBQVcsRUFBRSxjQUFjLENBQUMsV0FBVyxFQUFFLHdCQUF3QixDQUFDO0lBQ2xFLGFBQWEsRUFBRSxjQUFjLENBQUMsYUFBYSxFQUFFLHlCQUF5QixDQUFDO0NBQ3hFLENBQUE7QUFFRCxTQUFTLGNBQWMsQ0FBQyxHQUFXLEVBQUUsTUFBYztJQUNqRCxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQTtJQUN0RSxPQUFPLEVBQUUsV0FBVyxFQUFFLGNBQWMsR0FBRyxFQUFFLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxDQUFBO0FBQzdELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgaW50ZXJmYWNlIFBsYXRmb3JtIHtcbiAgLyoqIFRoZSBucG0gcGFja2FnZSB0aGF0IGNhcnJpZXMgdGhpcyBwbGF0Zm9ybSdzIGJpbmFyeS4gKi9cbiAgcGFja2FnZU5hbWU6IHN0cmluZ1xuICAvKiogVGhlIFJ1c3QgdGFyZ2V0IHRoZSBiaW5hcnkgaXMgY29tcGlsZWQgZm9yLiAqL1xuICB0YXJnZXQ6IHN0cmluZ1xuICAvKiogVGhlIGJpbmFyeSdzIGZpbGUgbmFtZSBpbnNpZGUgdGhlIHBhY2thZ2UncyBgYmluL2AuICovXG4gIGJpbmFyeTogc3RyaW5nXG59XG5cbi8qKiBUaGUgbnBtIHBhY2thZ2UgdXNlcnMgaW5zdGFsbDsgaXQgcHVsbHMgaW4gdGhlIG9uZSBwbGF0Zm9ybSBwYWNrYWdlIHRoYXQgbWF0Y2hlcy4gKi9cbmV4cG9ydCBjb25zdCBQQUNLQUdFX05BTUUgPSBcImdldGh0bWxwcmVzc1wiXG5cbi8qKiBBbiBlbnZpcm9ubWVudCB2YXJpYWJsZSB0aGF0IHBvaW50cyBhdCBhIGJpbmFyeSB0byBydW4gaW5zdGVhZCBvZiB0aGUgaW5zdGFsbGVkIG9uZS4gKi9cbmV4cG9ydCBjb25zdCBCSU5BUllfRU5WID0gXCJIVE1MUFJFU1NfQklOQVJZXCJcblxuLyoqIEV2ZXJ5IHB1Ymxpc2hlZCBwbGF0Zm9ybSwga2V5ZWQgYnkgYCR7cHJvY2Vzcy5wbGF0Zm9ybX0tJHtwcm9jZXNzLmFyY2h9YC4gKi9cbmV4cG9ydCBjb25zdCBQTEFURk9STVM6IFJlY29yZDxzdHJpbmcsIFBsYXRmb3JtPiA9IHtcbiAgXCJsaW51eC14NjRcIjogY3JlYXRlUGxhdGZvcm0oXCJsaW51eC14NjRcIiwgXCJ4ODZfNjQtdW5rbm93bi1saW51eC1tdXNsXCIpLFxuICBcImxpbnV4LWFybTY0XCI6IGNyZWF0ZVBsYXRmb3JtKFwibGludXgtYXJtNjRcIiwgXCJhYXJjaDY0LXVua25vd24tbGludXgtbXVzbFwiKSxcbiAgXCJkYXJ3aW4teDY0XCI6IGNyZWF0ZVBsYXRmb3JtKFwiZGFyd2luLXg2NFwiLCBcIng4Nl82NC1hcHBsZS1kYXJ3aW5cIiksXG4gIFwiZGFyd2luLWFybTY0XCI6IGNyZWF0ZVBsYXRmb3JtKFwiZGFyd2luLWFybTY0XCIsIFwiYWFyY2g2NC1hcHBsZS1kYXJ3aW5cIiksXG4gIFwid2luMzIteDY0XCI6IGNyZWF0ZVBsYXRmb3JtKFwid2luMzIteDY0XCIsIFwieDg2XzY0LXBjLXdpbmRvd3MtbXN2Y1wiKSxcbiAgXCJ3aW4zMi1hcm02NFwiOiBjcmVhdGVQbGF0Zm9ybShcIndpbjMyLWFybTY0XCIsIFwiYWFyY2g2NC1wYy13aW5kb3dzLW1zdmNcIiksXG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVBsYXRmb3JtKGtleTogc3RyaW5nLCB0YXJnZXQ6IHN0cmluZyk6IFBsYXRmb3JtIHtcbiAgY29uc3QgYmluYXJ5ID0ga2V5LnN0YXJ0c1dpdGgoXCJ3aW4zMlwiKSA/IFwiaHRtbHByZXNzLmV4ZVwiIDogXCJodG1scHJlc3NcIlxuICByZXR1cm4geyBwYWNrYWdlTmFtZTogYEBodG1scHJlc3MvJHtrZXl9YCwgdGFyZ2V0LCBiaW5hcnkgfVxufVxuIl19
package/package.json CHANGED
@@ -1,8 +1,40 @@
1
1
  {
2
2
  "name": "gethtmlpress",
3
- "version": "0.0.0",
4
- "description": "Placeholder; htmlpress ships from 0.1.0",
5
- "license": "MIT",
3
+ "version": "0.2.0",
4
+ "description": "Turn a folder of HTML pages into a site: one layout, one theme, live reload, made for agents",
5
+ "keywords": [
6
+ "agents",
7
+ "html",
8
+ "htmlpress",
9
+ "llm",
10
+ "static-site"
11
+ ],
6
12
  "homepage": "https://htmlpress.dev",
7
- "repository": { "type": "git", "url": "git+https://github.com/datisthq/htmlpress.git", "directory": "typescript" }
13
+ "license": "MIT",
14
+ "author": "Evgeny Karev",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/datisthq/htmlpress.git",
18
+ "directory": "typescript"
19
+ },
20
+ "bin": {
21
+ "htmlpress": "./build/entrypoints/main.js"
22
+ },
23
+ "files": [
24
+ "build",
25
+ "skills"
26
+ ],
27
+ "type": "module",
28
+ "sideEffects": false,
29
+ "engines": {
30
+ "node": ">=20"
31
+ },
32
+ "optionalDependencies": {
33
+ "@htmlpress/linux-x64": "0.2.0",
34
+ "@htmlpress/linux-arm64": "0.2.0",
35
+ "@htmlpress/darwin-x64": "0.2.0",
36
+ "@htmlpress/darwin-arm64": "0.2.0",
37
+ "@htmlpress/win32-x64": "0.2.0",
38
+ "@htmlpress/win32-arm64": "0.2.0"
39
+ }
8
40
  }
@@ -0,0 +1,157 @@
1
+ ---
2
+ name: htmlpress-authoring
3
+ description: Use when writing or editing pages in an htmlpress project — the page contract (title, order, head, metas), headings and the TOC, semantic HTML, the htmlpress-* components, code blocks, math, includes and checking the build.
4
+ ---
5
+
6
+ # Htmlpress Authoring
7
+
8
+ An htmlpress project is a folder of `.html` pages. Htmlpress wraps each in one layout with a
9
+ navigation and a theme, so a page carries content only: no `<nav>`, no site header, no styling.
10
+
11
+ ## When to use this skill
12
+
13
+ Invoke when the user asks to:
14
+
15
+ - Add, edit, move or reorder pages, or group them in the navigation.
16
+ - Use a callout, tabs, cards, steps or another component, or a code block, formula or diagram.
17
+ - Pull a shared partial or a source file into a page.
18
+
19
+ The config keys are in `htmlpress-configuration`; a different look in `htmlpress-customization`.
20
+
21
+ ## A page
22
+
23
+ ```html
24
+ <title>Getting started</title>
25
+ <meta name="description" content="Install and run it in a minute." />
26
+ <meta name="order" content="1" />
27
+
28
+ <h1>Getting started</h1>
29
+ <p>Plain semantic HTML.</p>
30
+ ```
31
+
32
+ - A full document (`<!doctype html>…<body>`) and a bare fragment are read the same way.
33
+ - `<title>` names the page in the navigation and the tab; without it the first `<h1>`, then the
34
+ file name. Give every page one `<title>` and one `<h1>`.
35
+ - `<meta name="order" content="N">` (an integer) sorts the navigation, lower first.
36
+ `index.html` always comes first; unordered pages follow by path, then negative orders
37
+ (`-1` pins a page last).
38
+ - Other `<head>` tags (`<link>`, `<style>`, `<script>`) are kept and added after the theme; a
39
+ fragment's are the ones before its first content, as a browser reads them.
40
+ - The navigation nests pages by folder at any depth (`guides/cli/…` inside `guides/…`), each
41
+ group named by its `index.html`, whose title links to it and whose `order` places the folder.
42
+ - Each page is served at its own folder URL: `guides/build.html` at `/guides/build/`,
43
+ `guides/index.html` at `/guides/`. Link to the page file (`guides/build.html`, relative or
44
+ root-relative) or to its URL: a link naming a page's file becomes its URL. Images and other
45
+ files are copied as-is; a relative `href`, `src`, `srcset` or `poster` resolves from the
46
+ source file, even when the page moves.
47
+ - A root `404.html` is the not-found page, kept out of the navigation; without one a built-in
48
+ is used.
49
+
50
+ ## Page metas
51
+
52
+ | Meta | Effect |
53
+ | -------------------------------------------- | ------------------------------------------------------------ |
54
+ | `description` | the page's summary for search, previews and `llms.txt` |
55
+ | `image` | its social preview image, relative to the file; needs `site` |
56
+ | `date` (`YYYY-MM-DD`), `author` (repeatable) | dates and signs it (a byline; none with `layout`) |
57
+ | `keywords` (`a, b`) | tags it (a blog post's tag pages) |
58
+ | `label` | a short name in the navigation |
59
+ | `icon` | a Lucide icon; top-level entries and folder index pages |
60
+ | `path` (`/start/`) | serves the page at another URL |
61
+ | `sidebar` (`false`) | built, not listed |
62
+ | `toc` (`false`) | no table of contents |
63
+ | `breadcrumbs` (`false` / `true`) | hides or shows the folder trail, over the config's |
64
+ | `layout` (`<name>`) | another layout, from `htmlpress-customization` |
65
+ | `language` (`<code>`) | marks the page a translation |
66
+ | `source-url`, `source-action` (`view`) | the page's source link |
67
+
68
+ A file that cannot carry metas, such as a `README.md`, gets them from `patches` in the config.
69
+
70
+ ## Translations
71
+
72
+ With `languages` in the config, a translation is `page.<code>.html` beside `page.html`, or a
73
+ file with `<meta name="language" content="<code>">`. It pairs with the original by URL below the
74
+ language prefix, so a renamed one needs the same `<meta name="path">`. Untranslated pages stay
75
+ listed in every language with a badge and link to the original. Without a translated home,
76
+ `/<code>/` redirects to the language's first page.
77
+
78
+ ## Headings
79
+
80
+ - `<h2>` to `<h4>` outside components make the page's table of contents; any `<h2>` to `<h6>`
81
+ without an `id` gets a slug of its text and an anchor link. Give a heading an `id` only when a link needs it fixed.
82
+ - A heading takes `data-toc="false"` (shown, not in the TOC) or `data-toc="only"` (in the TOC,
83
+ not shown); `<htmlpress-toc level="2">` (2–4, default 3) in a page renders its TOC inline.
84
+
85
+ ## Semantic HTML first
86
+
87
+ The theme styles the elements themselves: headings, `<p>`, lists, `<table>`, `<pre><code>`,
88
+ `<blockquote>`, `<details>`/`<summary>`, `<figure>`/`<figcaption>`, `<dl>`, `<kbd>`, `<hr>`.
89
+
90
+ - No inline `style`, no classes for looks, no utility CSS: every page should look like the same
91
+ site. A site-wide change is a token (`htmlpress-customization`).
92
+ - An image with `data-theme="light"` or `"dark"` shows in that theme only.
93
+ - `<abbr title>` and footnote references (`<sup><a href="#n1">` to an `<li id="n1">`) show a
94
+ hover hint; headings get a link on their own.
95
+ - Bare URLs and emails in prose become links and GitHub shortcodes (`:rocket:`) become emoji at
96
+ build time; text in links, code and `data-literal` elements stays as written.
97
+ - LaTeX: `$E = mc^2$` inline and `$$…$$` as a block (pandoc's rule keeps `$5 and $10` text; `\$`
98
+ is a dollar), or `<htmlpress-math display>…</htmlpress-math>`; rendered to MathML at build
99
+ time, and invalid LaTeX fails the build.
100
+ - `<htmlpress-include src="partial.html">` pastes in another file by path, relative to the page:
101
+ an `.html` body, rendered `.md`, or any other file as a titled code block that takes
102
+ `data-lines` and the other code block attributes. Exclude the partials folder in the config.
103
+
104
+ ## Code blocks
105
+
106
+ - Escape code inside `<pre><code>`: `&lt;` and `&amp;`. Name its language,
107
+ `<pre><code class="language-rust">`, to highlight it at build time; an inline
108
+ `<code class="language-js">` is highlighted too.
109
+ - `data-lines="2,4-5"` marks lines, `data-line-numbers` numbers them, `data-add`/`data-remove`
110
+ show a diff, `data-focus` dims the other lines, `data-error`/`data-warning` flag lines and
111
+ `data-words="a,b"` marks words.
112
+ - `<pre data-title="file.yaml">` adds a title bar with the language's logo;
113
+ `<pre data-collapse="10">` shows 10 lines with an Expand bar.
114
+ - `<pre><code class="language-ansi">` renders terminal color escapes (raw or `&#27;[31m`).
115
+ - Every block gets copy and wrap buttons. Tabs holding only code blocks join into one framed block.
116
+
117
+ ## Components
118
+
119
+ Only these; anything else is plain HTML. Put block content (`<p>`, `<h3>`, `<pre>`) inside a
120
+ component, not bare text.
121
+
122
+ | Element | Use |
123
+ | ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------- |
124
+ | `<htmlpress-callout type="…" label="…">` | a note; `type` is `info` (default), `note`, `tip`, `success`, `warning`, `danger` |
125
+ | `<htmlpress-grid cols="2">` + `<htmlpress-card>` | cards in columns (`cols` 2–4, else responsive); `<h3><a>` links a card |
126
+ | `<htmlpress-tabs sync="…">` + `<section title>` | tabs, one per `<section>`; tabs sharing `sync` switch together |
127
+ | `<htmlpress-steps>` + `<ol>` | numbered steps, one per `<li>`, each led by an `<h3>` |
128
+ | `<htmlpress-badge type="…">` | an inline label; `type` as a callout's, `neutral`, `outline`, `ghost` or `link` |
129
+ | `<htmlpress-file-tree>` + nested `<ul>` | a file tree; an `<li>` holding a `<ul>` is a folder |
130
+ | `<htmlpress-table>` + `<table>` | a table sorted by a click on a `<thead>` header |
131
+ | `<htmlpress-zoom>` + `<img>` | an image that opens full screen on click |
132
+ | `<htmlpress-icon name="…">` | an inline Lucide icon; names at htmlpress.dev/authoring/rich-elements/#icons |
133
+ | `<htmlpress-button type="…">` + `<a>` | a call-to-action link; `type` `secondary`/`outline`/`ghost`/`link`/`positive`/`warning`/`destructive`, `size` `sm`/`lg` |
134
+ | `<htmlpress-package-tabs>` + `<pre><code>` | one `npm`/`npx` command, built into npm, pnpm, yarn and bun tabs |
135
+ | `<htmlpress-terminal title="…">` + `<pre>` | terminal output: `<kbd>` command, `<samp>` output, `<ins>`/`<del>`/`<mark>` colours |
136
+ | `<htmlpress-youtube>` + `<a href>` | a YouTube video player for the linked video |
137
+ | `<htmlpress-soundcloud>` + `<a href>` | a SoundCloud player for the linked track |
138
+ | `<htmlpress-mermaid>` + `<pre>` | a Mermaid diagram from the source in `<pre>` (escape `<` and `&`) |
139
+
140
+ ## Verification
141
+
142
+ ```sh
143
+ htmlpress build <root> --json # {"output": "...", "pages": N, "files": N}; errors on stderr
144
+ htmlpress start <root> # http://localhost:8000 (or the next free port to 8009); --host for the network
145
+ htmlpress start <root> --json # {"url": "...", "network": []} on one line once serving
146
+ htmlpress --llms # every command's input and output schema
147
+ ```
148
+
149
+ After editing, run `build --json` and confirm `pages` counts every page and the exit code is 0.
150
+ For a visual check, run `start` and open the page; look at it narrow as well as wide. Never edit
151
+ `.htmlpress/build/`: every build replaces it.
152
+
153
+ ## References
154
+
155
+ - Pages: https://htmlpress.dev/authoring/
156
+ - Components: https://htmlpress.dev/authoring/rich-elements/
157
+ - Code blocks: https://htmlpress.dev/authoring/code-blocks/
@@ -0,0 +1,127 @@
1
+ ---
2
+ name: htmlpress-configuration
3
+ description: Use when editing htmlpress.yaml — site metadata, base, include/exclude globs, code themes, sections (blog, changelog, custom), links, languages, versions, patches, head tags, agent skills, content signals and the edit link.
4
+ ---
5
+
6
+ # Htmlpress Configuration
7
+
8
+ `htmlpress.yaml` at the project root is optional; its keys follow Livemark's config. An unknown
9
+ key is an error, so a typo fails the build instead of being ignored.
10
+
11
+ ## When to use this skill
12
+
13
+ Invoke when the user asks to:
14
+
15
+ - Set the site's title, description, logo, favicon, banner or URL.
16
+ - Choose which files become pages, or leave some out.
17
+ - Add a blog, a changelog or another section, or links in the header or sidebar.
18
+ - Publish the site in several languages, or keep docs for older versions.
19
+ - Give a file metas it cannot carry, or publish a Markdown file as a page.
20
+ - Add tags to every page's `<head>`, publish skills or set `robots.txt` signals.
21
+
22
+ ## The config shape
23
+
24
+ ```yaml
25
+ site: https://example.com
26
+ base: /
27
+ title: Acme
28
+ description: Acme's docs.
29
+ logo: /logo.svg
30
+ favicon: /favicon.svg
31
+ banner: <a href="/blog/">We shipped 2.0</a>
32
+ breadcrumbs: false
33
+ include: [docs/**/*.html]
34
+ exclude: [docs/includes/**]
35
+ codeThemeLight: catppuccin-latte
36
+ codeThemeDark: catppuccin-mocha
37
+ edit: https://github.com/acme/acme/edit/main/
38
+ links:
39
+ - { title: GitHub, url: https://github.com/acme/acme, position: header, icon: github }
40
+ sections:
41
+ - { title: Blog, prefix: /blog/, type: blog }
42
+ patches:
43
+ - { file: README.md, article: { title: Overview, order: 1 } }
44
+ skills: [.skills/*/SKILL.md]
45
+ contentSignals: { search: true, aiInput: true, aiTrain: false }
46
+ head:
47
+ meta: [{ name: theme-color, content: "#0b5" }]
48
+ ```
49
+
50
+ - `site` — the canonical origin; with it a build writes `sitemap.xml` and absolute feed URLs.
51
+ - `base` — a sub-path such as `/repo/`. Root-relative URLs get it as a prefix, so write them
52
+ without it.
53
+ - `title`, `description`, `logo`, `favicon` (URLs) and `banner` (HTML above the header).
54
+ - `breadcrumbs` — `false` hides the folder trail above every page; default `true`, and a
55
+ page's `<meta name="breadcrumbs">` overrides it.
56
+ - `include` — globs of the `.html` files that become pages, default `**/*.html`. Only files under
57
+ a glob's base, its folders before the first wildcard, are read, and they are served without it:
58
+ `docs/**/*.html` serves `docs/guide.html` at `/guide.html`. Other files there are copied as-is.
59
+ - `exclude` — globs left out of the build: partials for includes, drafts.
60
+ - `codeThemeLight`, `codeThemeDark` — the code block themes, by Shiki theme name.
61
+ - `edit` — a URL prefix for an "Edit on GitHub" link.
62
+
63
+ ## Sections
64
+
65
+ Each has a `title` and a `prefix`; optional `icon`, `position`, `siteTitle`, `siteLink` and
66
+ `siteDescription`. The sidebar and pager then show only the open section's pages.
67
+
68
+ - `type: article` (the default) — the pages under the prefix.
69
+ - `type: blog` — dated posts (`date`, `author`, `keywords` metas) with tag pages and RSS.
70
+ - `type: changelog` plus `source` — a page per version of a Markdown changelog, or per
71
+ release of a GitHub repository URL (`GITHUB_TOKEN` when set, cached in `.htmlpress/cache/`); `version: true`
72
+ shows the latest version beside the title.
73
+ - `type: custom` plus `url` — a link to anywhere.
74
+
75
+ ## Links
76
+
77
+ Each has `title`, `url` and `position: header | sidebar`; optional `icon` and `prefix`, which
78
+ shows the link only under one folder.
79
+
80
+ ## Languages
81
+
82
+ `languages` lists each `code` and `label`, optional `locale`, `dir` (`ltr` or `rtl`), `flag` and
83
+ `messages` replacing UI strings. The first is the default; the others are served under
84
+ `/<code>/`. With `languages`, `title`, `description`, `banner` and link and section titles also
85
+ take a map by language code (`title: { en: Docs, es: Documentos }`). Translated pages are in
86
+ `htmlpress-authoring`.
87
+
88
+ ## Versions
89
+
90
+ There is no dedicated option. For a few versions on one branch, put each older version's pages
91
+ in a folder with a section of its own (`title: v1`, `prefix: /v1/`, `siteTitle: Acme v1`);
92
+ search stays site-wide, so results mix versions. For majors on their own branches, deploy each
93
+ branch as its own site (`base`, a `banner` linking to the latest) and link them with a `custom`
94
+ section.
95
+
96
+ ## Patches
97
+
98
+ Each patch is a `file` and an `article` of metas (`title`, `label`, `description`, `icon`,
99
+ `order`, `path`, `sidebar`, `breadcrumbs`, `toc`, `image`, `author`, `date`, `tags`, `sourceUrl`,
100
+ `sourceAction`), set without touching the file; a patched `.md` file such as `README.md` is
101
+ published as a page. A patched path outside the project, through a symlink or into a dot-folder is refused.
102
+
103
+ ## Agents and head
104
+
105
+ - `skills` — globs of `SKILL.md` files to publish under `.well-known/agent-skills/`.
106
+ - `contentSignals` — `search`, `aiInput`, `aiTrain` for `robots.txt`.
107
+ - `head` — `meta`, `links`, `scripts`: lists of attribute maps added to every page; a script's
108
+ `children` is its source.
109
+
110
+ ## Rules of thumb
111
+
112
+ - Change one key at a time and rebuild: the error names the key.
113
+ - Keep the config for site-wide facts; a page's own facts are its metas (`htmlpress-authoring`).
114
+ - `htmlpress start` rebuilds on a config change; no restart needed.
115
+
116
+ ## Verification
117
+
118
+ Run `htmlpress build <root> --json`: exit code 0 and the expected `pages` count. An unknown or
119
+ misspelt key fails here with its name.
120
+
121
+ ## References
122
+
123
+ - Configuration: https://htmlpress.dev/customization/configuration-file/
124
+ - Sections: https://htmlpress.dev/customization/article-sections/
125
+ - Translations: https://htmlpress.dev/customization/translations/
126
+ - Versioning: https://htmlpress.dev/customization/versioning/
127
+ - Patches: https://htmlpress.dev/customization/article-patches/
@@ -0,0 +1,139 @@
1
+ ---
2
+ name: htmlpress-customization
3
+ description: Use when changing an htmlpress site's look or chrome — overriding --htmlpress-* tokens, escaping the layout, styles or a component into .htmlpress/ with `htmlpress escape`, adding layouts and project components.
4
+ ---
5
+
6
+ # Htmlpress Customization
7
+
8
+ Htmlpress ships a layout, a theme and a library of components, all compiled into the binary.
9
+ A file under `.htmlpress/` at a built-in's path replaces it; a new name adds one of your own.
10
+
11
+ ## When to use this skill
12
+
13
+ Invoke when the user asks to:
14
+
15
+ - Rebrand: colours, fonts, widths, radius.
16
+ - Change the header, sidebar, footer or another part of the chrome.
17
+ - Restyle a component, or add a block the built-in components do not have.
18
+ - Give some pages a different layout, such as a landing page without the sidebar
19
+ (`htmlpress-landing` covers what goes on one).
20
+
21
+ Do not escape for content: a page's own needs are semantic HTML and components
22
+ (`htmlpress-authoring`).
23
+
24
+ ## Tokens first
25
+
26
+ Most looks are a token. Override it in `.htmlpress/styles/tokens.css`, or in one page's own
27
+ `<style>` for that page only:
28
+
29
+ ```css
30
+ :root {
31
+ --htmlpress-accent: oklch(0.55 0.24 27);
32
+ }
33
+ ```
34
+
35
+ `--htmlpress-accent`, `-accent-text`, `-font`, `-mono`, `-bg`, `-surface`, `-text`, `-muted`,
36
+ `-prose`, `-prose-strong`, `-prose-marker`, `-border`, `-shadow`, `-radius`, `-width`,
37
+ `-nav-width`, `-banner`, `-banner-text`, `-highlight`, `-highlight-text` (search matches on
38
+ the page a result opened), and the
39
+ callout and badge tones `-info`, `-success`, `-warning`, `-danger`.
40
+
41
+ ## Escaping
42
+
43
+ ```sh
44
+ htmlpress escape # list every file, marking the escaped ones
45
+ htmlpress escape htmlpress-tabs # a component's .css and .js
46
+ htmlpress escape layout.html styles/tokens.css
47
+ htmlpress escape htmlpress-tabs -r docs # in another project folder
48
+ ```
49
+
50
+ `escape` copies a default to start from and never overwrites a file you already have. Deleting
51
+ an escape restores the default. An escaped copy keeps the code it was copied from, so after an
52
+ upgrade it misses the new defaults: escape only what you change.
53
+
54
+ | Path under `.htmlpress/` | Replaces |
55
+ | ------------------------------------------------ | ----------------------------------------------------------------- |
56
+ | `layout.html` | the page around the content |
57
+ | `layouts/<name>.html` | a layout of your own, picked by `<meta name="layout">` |
58
+ | `styles/tokens.css`, `layout.css`, `content.css` | the global theme: tokens, page globals, content elements |
59
+ | `favicon.svg` | the icon linked when the config sets neither `favicon` nor `logo` |
60
+ | `components/<name>/<name>.css`, `.js` | one component, `<htmlpress-<name>>` without its prefix |
61
+
62
+ ## Layouts
63
+
64
+ `layout.html` is plain HTML: htmlpress fills its `<head>` and replaces `<htmlpress-content>`,
65
+ `<htmlpress-brand>`, `<htmlpress-banner>`, `<htmlpress-nav>`, `<htmlpress-links>`,
66
+ `<htmlpress-breadcrumbs>`, `<htmlpress-toc>`, `<htmlpress-pager>`, `<htmlpress-edit>`,
67
+ `<htmlpress-toolbar>`, `<htmlpress-footer>`, `<htmlpress-language>` (the language picker) and
68
+ `<htmlpress-skip>` at build time, every string in the page's language. The interactive ones,
69
+ `<htmlpress-nav-toggle>`, `<htmlpress-search>`, `<htmlpress-theme-toggle>`, `<htmlpress-toc-bar>`
70
+ (the phone's contents bar), `<htmlpress-shortcuts>` (the keyboard shortcuts menu, listing every key and disabling the ones no
71
+ control on the page announces with `aria-keyshortcuts`) and `<htmlpress-back-to-top>`, run in the browser; the first three get their button at build time,
72
+ so the header is whole on its first frame. A head script sets `data-scripted` on `<html>`:
73
+ without it those buttons stay hidden, so style anything that needs scripts under
74
+ `:root[data-scripted]`. An element with nothing to show is removed. The theme toggle, the
75
+ language picker and the sidebar's section picker drop down from `56rem` up and, like the
76
+ contents bar, open an `<htmlpress-sheet>` on a phone: one bottom sheet the scripts append to
77
+ `<body>`, so escape `components/sheet/sheet.css` to restyle every sheet at once.
78
+
79
+ Pages crossfade only their content: `<htmlpress-header>` and `<htmlpress-sidebar>` carry the
80
+ view transition names `htmlpress-header` and `htmlpress-sidebar`, and a hovered link's page is
81
+ prerendered. An escape of either component's `.css` keeps its `view-transition-name`, or it
82
+ crossfades with the content.
83
+
84
+ The frame is elements too, never classes: `<htmlpress-shell>`, `-sidebar`, `-main`, `-header`,
85
+ `-page`, `-aside`, `-skip`, each a component whose `.css` can be escaped.
86
+
87
+ A page with `<meta name="layout" content="landing">` takes `layouts/landing.html` instead. It
88
+ starts bare: only the layout elements you put in it are drawn. A missing layout fails the build.
89
+
90
+ ## Project components
91
+
92
+ A folder under `components/` with a new name adds `<htmlpress-<name>>`, each file named like
93
+ the folder:
94
+
95
+ ```html
96
+ <!-- .htmlpress/components/credits/credits.html -->
97
+ <footer><p>Built by my team · 2026</p></footer>
98
+ ```
99
+
100
+ ```css
101
+ /* .htmlpress/components/credits/credits.css */
102
+ @scope (htmlpress-credits) {
103
+ :scope {
104
+ display: block;
105
+ }
106
+ p {
107
+ color: var(--htmlpress-muted);
108
+ }
109
+ }
110
+ ```
111
+
112
+ - The `.html` fills every such tag in the layouts and pages at build time; the tag stays, so its
113
+ `.css` scopes to it. A custom element is inline until its CSS says otherwise.
114
+ - Its `.css` and `.js` load only where the tag appears. A name is lowercase letters, digits and
115
+ hyphens.
116
+ - A layout or a component's `.html` may hold any built-in component, but not another project
117
+ component's tag: it is pasted in once, never rewritten again.
118
+ - The markup inside a layout element (`nav`, `toc`, `pager`, …) is built from the site; a
119
+ `components/brand/brand.html` replaces it with static HTML, and the built-in `.css` still
120
+ applies to the tag.
121
+
122
+ ## Rules of thumb
123
+
124
+ - A misspelt built-in name (`calout/`) adds a component rather than replacing one; a file
125
+ directly in `components/` fails the build. Check `htmlpress escape` marks the file escaped.
126
+ - To restyle a component from an outer one, beat its `:scope`: write `:scope htmlpress-header`,
127
+ not a bare `htmlpress-header`, which loses on specificity.
128
+ - Use tokens inside your CSS (`var(--htmlpress-muted)`) so dark mode keeps working.
129
+
130
+ ## Verification
131
+
132
+ Run `htmlpress build <root> --json` (exit code 0), then `htmlpress start <root>` and look at
133
+ the change in light and dark, wide and phone width. `start` picks up a new or deleted escape
134
+ at once.
135
+
136
+ ## References
137
+
138
+ - Overriding: https://htmlpress.dev/customization/overriding-escaping/
139
+ - Layouts: https://htmlpress.dev/customization/custom-routes/
@@ -0,0 +1,71 @@
1
+ ---
2
+ name: htmlpress-deployment
3
+ description: Use when publishing an htmlpress site — building into .htmlpress/build/, setting site and base, and wiring Cloudflare, GitHub Pages, Vercel, Netlify or any static host, by hand or from CI.
4
+ ---
5
+
6
+ # Htmlpress Deployment
7
+
8
+ `htmlpress build` writes a fully static site; every host that serves a directory of files can
9
+ serve it. There is no client-side routing, so no host needs an SPA fallback.
10
+
11
+ ## When to use this skill
12
+
13
+ Invoke when the user asks to:
14
+
15
+ - Publish the site, or set up a host or a CI deploy.
16
+ - Serve it under a sub-path such as a GitHub Pages project site.
17
+ - Fix a deploy that 404s, loses its styles or misses `sitemap.xml`.
18
+
19
+ ## The build
20
+
21
+ ```sh
22
+ htmlpress build # or `npx gethtmlpress build` in CI, without installing it
23
+ htmlpress preview # serves the production build locally, the way a host will
24
+ htmlpress clear # removes .htmlpress/build
25
+ ```
26
+
27
+ The output is `.htmlpress/build/`: an `index.html` per page in its own folder
28
+ (`guides/build.html` at `guides/build/index.html`), `404.html`,
29
+ `robots.txt`, `_headers`, a Markdown copy of each page and `llms.txt` for agents, the skills
30
+ under `.well-known/agent-skills/`, the theme under `_htmlpress/`, and every other project file.
31
+ With `site` set it adds `sitemap.xml`. Never edit the output: every build replaces it.
32
+
33
+ ## Config that affects deployment
34
+
35
+ - `site` — the final origin (`https://docs.example.com`): `sitemap.xml`, canonical URLs and
36
+ absolute social tags need it.
37
+ - `base` — only for a sub-path (`/my-docs/`). Write links without it; the build prefixes every
38
+ root-relative URL, and `start` and `preview` serve under it too. A custom domain needs no
39
+ `base`.
40
+
41
+ ## Hosts
42
+
43
+ | Host | Setup |
44
+ | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
45
+ | Cloudflare Workers | `wrangler.jsonc`: `assets.directory: ".htmlpress/build"`, `not_found_handling: "404-page"`; `npx wrangler deploy` |
46
+ | GitHub Pages | `site: https://<user>.github.io`, `base: /<repo>/`; `npx gh-pages -d .htmlpress/build --nojekyll --dotfiles`, or the Pages actions uploading `.htmlpress/build` |
47
+ | Vercel | `vercel.json`: `"framework": null`, `"buildCommand": "npx gethtmlpress build"`, `"outputDirectory": ".htmlpress/build"` |
48
+ | Netlify | `netlify.toml`: `[build] command = "npx gethtmlpress build"`, `publish = ".htmlpress/build"` |
49
+ | nginx | `try_files $uri $uri/ =404;` and `error_page 404 /404.html;` |
50
+ | Caddy | `file_server` plus `handle_errors { rewrite * /404.html; file_server }` |
51
+ | S3 + CloudFront | index `index.html`, error `404.html`, a 404 custom error response to `/404.html` |
52
+
53
+ ## Rules of thumb
54
+
55
+ - Point the host's not-found page at `404.html`, so unknown paths keep the site's layout.
56
+ - Keep `--nojekyll` and `--dotfiles` on a GitHub Pages branch deploy: Jekyll drops the
57
+ `_htmlpress/` theme, and without dot-files `.well-known/` is lost.
58
+ - Files under `_htmlpress/` keep their names between builds: cache them briefly or invalidate
59
+ them on each release.
60
+ - A project's dot-files are never copied: keep an `.htaccess` on the server.
61
+
62
+ ## Verification
63
+
64
+ Run `htmlpress build --json` and `htmlpress preview`, then after the deploy open the home page,
65
+ a nested page, an unknown path (the site's 404) and `/robots.txt`. Under a `base`, check that
66
+ styles load and links keep the prefix.
67
+
68
+ ## References
69
+
70
+ - Deployment: https://htmlpress.dev/deployment/
71
+ - Static hosting: https://htmlpress.dev/deployment/static-hosting/
@@ -0,0 +1,112 @@
1
+ ---
2
+ name: htmlpress-landing
3
+ description: Use when designing or rewriting an htmlpress project's landing page — a layout of its own, hero, sections, screenshots and calls to action as project components, taking htmlpress.dev's own landing as the reference.
4
+ ---
5
+
6
+ # Htmlpress Landing
7
+
8
+ Guidance for designing the page at `/` of an htmlpress project. The mechanics of a layout and a
9
+ project component are in `htmlpress-customization`; this skill is about what goes on the page.
10
+
11
+ ## When to use this skill
12
+
13
+ Invoke when the user asks to:
14
+
15
+ - Build a landing, home or marketing page for the site, or redesign the existing one.
16
+ - Add a hero, feature grid, screenshot carousel or call-to-action section.
17
+ - Make the landing look as polished as htmlpress.dev.
18
+
19
+ ## Start from the reference
20
+
21
+ htmlpress.dev's landing is itself an htmlpress page with its own layout and a set of project
22
+ components. Read it before writing anything, see it live, and borrow its structure:
23
+
24
+ - Live: https://htmlpress.dev/
25
+ - Page: https://github.com/datisthq/htmlpress/blob/main/rust/docs/index.html
26
+ - Layout and components: https://github.com/datisthq/htmlpress/tree/main/.htmlpress
27
+
28
+ None of it is in the packages, so fetch it from GitHub. Take the patterns, not the content:
29
+ rewrite every heading and line of copy for the project, and use the project's own screenshots
30
+ and links. Shipping htmlpress' copy, screenshots or Datist credit on someone else's site is a bug.
31
+
32
+ ## Skeleton
33
+
34
+ ```html
35
+ <!-- index.html -->
36
+ <title>Home</title>
37
+ <meta name="description" content="What the project does, in one line." />
38
+ <meta name="layout" content="landing" />
39
+ <meta name="sidebar" content="false" />
40
+
41
+ <htmlpress-landing-hero>…</htmlpress-landing-hero>
42
+ <htmlpress-landing-section>…</htmlpress-landing-section>
43
+ <htmlpress-landing-cta>…</htmlpress-landing-cta>
44
+ ```
45
+
46
+ ```html
47
+ <!-- .htmlpress/layouts/landing.html -->
48
+ <!doctype html>
49
+ <html lang="en">
50
+ <head></head>
51
+ <body>
52
+ <htmlpress-skip><a href="#content">Skip to content</a></htmlpress-skip>
53
+ <htmlpress-landing-page>
54
+ <htmlpress-banner></htmlpress-banner>
55
+ <htmlpress-header role="banner">
56
+ <htmlpress-brand></htmlpress-brand>
57
+ <htmlpress-links></htmlpress-links>
58
+ <htmlpress-search></htmlpress-search>
59
+ <htmlpress-theme-toggle></htmlpress-theme-toggle>
60
+ </htmlpress-header>
61
+ <main id="content"><htmlpress-content></htmlpress-content></main>
62
+ <htmlpress-landing-footer></htmlpress-landing-footer>
63
+ </htmlpress-landing-page>
64
+ <htmlpress-back-to-top></htmlpress-back-to-top>
65
+ </body>
66
+ </html>
67
+ ```
68
+
69
+ The reference runs hero → a differentiator ("Stays out of your way") → a feature grid → an
70
+ audience section (agents) → a final call to action → a credit footer. Pick the sections the
71
+ project has something real to say in; three strong ones beat seven thin ones.
72
+
73
+ ## Patterns from the reference
74
+
75
+ - **One component per block** — `landing-hero`, `-section`, `-features`, `-points`, `-cta`,
76
+ `-actions`, `-carousel`, `-window`, `-code`, `-backdrop`, `-footer`, `-page`, each a folder
77
+ under `.htmlpress/components/` with a `.css` scoped to its tag, and `.js` or `.html` only
78
+ where needed. The page holds semantic HTML inside them: `<section>`, `<header>`, `<hgroup>`,
79
+ `<h2>`, `<ul>` of `<li>` cards. No classes.
80
+ - **Section shell** — `<htmlpress-landing-section><section><header><h2>` plus a lede, then the
81
+ body; a two-column section pairs a point list with a visual (`landing-points` beside
82
+ `landing-window`).
83
+ - **Hero** — a short eyebrow `<p>` in an `<hgroup>` with the `<h1>`, a lede, then
84
+ `landing-actions` with two links: the docs first, the source second. A decorative
85
+ `landing-backdrop` takes `aria-hidden="true"`.
86
+ - **Show the product** — real screenshots, not stock art, each shipped light and dark as two
87
+ `<img>` toggled by the theme with an attribute the component's CSS reads; set `width` and
88
+ `height` so nothing shifts. `landing-carousel` turns `<section title>` slides into tabs.
89
+ - **Icons** — inline `<svg aria-hidden="true">` with `currentColor` strokes, so they follow the
90
+ theme.
91
+ - **Colour** — only `--htmlpress-*` tokens and `color-mix(in oklab, …)` of them, so the page
92
+ rebrands and goes dark with the rest of the site.
93
+
94
+ ## Rules of thumb
95
+
96
+ - Links are root-relative (`/introduction/`, or the file, `/introduction.html`); `base` is added
97
+ at build time.
98
+ - Keep the landing out of the sidebar (`sidebar` false) but give it a real `<title>` and
99
+ `description`: it is the site's social preview.
100
+ - Every component must read well with its JS off: the slides are already in the HTML.
101
+ - Check phone width first; a two-column section must fall back to one.
102
+
103
+ ## Verification
104
+
105
+ Run `htmlpress build <root> --json`, then `htmlpress start <root>` and look at `/` in light and
106
+ dark, wide and at phone width. Tab through it: the skip link, the actions and the carousel must
107
+ be reachable by keyboard.
108
+
109
+ ## References
110
+
111
+ - Layouts: https://htmlpress.dev/customization/custom-routes/
112
+ - Overriding: https://htmlpress.dev/customization/overriding-escaping/