@fwdslsh/unify

中文文档
0.12.0发布于 2026/11/10MPL-2.0ES Module构建来源已验证近 30 天下载 2527

A static site generator for HTML-native composition: includes, layouts, and slots in plain HTML — no expression language, no client runtime

原始使用文档
文档目录11 节
  1. Install
  2. Quick start
  3. How it works
  4. Commands
  5. Examples
  6. Documentation
  7. For Agents
  8. Guarantees
  9. Auditing
  10. Contributing
  11. License

unify

HTML-native composition — no expression language, no client runtime.

unify is a static site generator for people fluent in HTML and CSS who want nothing to do with JavaScript frameworks, templating languages, or build tooling. Write a header, nav, footer, or page layout once, in plain HTML, and unify renders it into every page. The output is exactly the HTML and CSS you wrote — unify adds no JavaScript of its own. It replaces copy-paste chrome and Apache SSI; it does not compete with Hugo, Eleventy, or Astro.

The entire authoring surface is five things, learnable in five minutes:

You want to…You write…
Reuse a fragment (nav, footer, badge)<include src="/_includes/nav.html"></include>
Wrap pages in a layoutnothing — the nearest _layout.html applies; data-layout="/path.html" picks one, "none" opts out
Mark where page content lands, or let pages replace a named region<main> for the default; <slot name="footer"> in the layout, slot="footer" on a page element
Keep a file or folder out of the built sitea leading underscore: _draft.html, _includes/
Ship a bare snippet exactly as written (for <include>, embeds, fetch)name it *.fragment.html

If it cannot be expressed with these five, it does not belong in unify.

The specification set in docs/ is authoritative, and every normative rule in it is covered by a test that runs against the real CLI.

Install

Standalone binary (Linux and macOS, x86_64 and arm64 — nothing else to install):

curl -fsSL https://raw.githubusercontent.com/fwdslsh/unify/main/install.sh | bash

Installs to ~/.local/bin; the script accepts --global, --dir PATH, --version vX.Y.Z, --force, and --dry-run. Binaries are attached to GitHub releases. No Windows binary yet — use the install below.

Node or Bun:

npx @fwdslsh/unify build     # no install at all
npm install -g @fwdslsh/unify
bun add -g @fwdslsh/unify

Node >= 22.12.0 or Bun >= 1.2.0. The same unify runs on both and produces byte-identical output; the installed script picks Node by default, and bun add -g runs it under Bun. Deno is not supported. Never heard of either? Use the binary above.

Quick start

unify init      # scaffold a starter site into site/
unify dev       # build, watch, serve, reload — http://localhost:3000
unify build     # write the final site to dist/ — upload it anywhere

unify init scaffolds a complete site into site/ — a layout, a nav include, a home page, CSS with a theme file of custom properties you edit, a robots.txt, and ready-to-copy example pages under site/_examples/ that never publish — plus three files at the project root, outside site/ so they can never publish: README.md, guidance for whoever (or whatever) edits the site next, DEPLOY.md, the deployment recipe, and a unify.yaml listing every build flag, described and commented out, so you uncomment only what differs from the default — with template: live — the template this site came from, which unify update fetches again to copy its changed files over the site after showing you the list and asking, and under it keep:, the files an update never overwrites: the theme and unify.yaml itself. Five templates: default, basic, blog, docs, portfolio. Every scaffold passes unify build --dry-run --strict and unify audit --strict out of the box.

New here? The tutorial is Getting Started.

How it works

A layout is a complete HTML page — open it in a browser and its slot fallbacks are its own preview:

<!-- site/_layout.html -->
<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <title>— My Site</title>
    <link rel="stylesheet" href="/assets/style.css">
  </head>
  <body>
    <include src="/_includes/nav.html"></include>
    <main><slot></slot></main>
    <footer><slot name="footer"><p>© My Site</p></slot></footer>
  </body>
</html>

A page is also a complete, ordinary HTML document. It never mentions the layout — the nearest _layout.html applies automatically:

<!-- site/index.html -->
<!doctype html>
<html>
  <head><title>Home</title></head>
  <body>
    <main>
      <h1>Home</h1>
      <p>This lands in the layout's &lt;main&gt;.</p>
    </main>
  </body>
</html>

The built page is the layout with its <main> filled by the page's content, and the page's title joined in front of the layout's: <title>Home — My Site</title>. To replace a named region, a page puts one standard attribute on an ordinary element — <p slot="footer">© My Site — <a href="mailto:[email protected]">email us</a></p> — and that element replaces the layout's <slot name="footer">, tag and all. The precedence rule in one sentence: named fills go to named slots, everything else to the bare slot, else into <main>.

Markdown pages compose identically, with frontmatter supplying the head. title, layout, class, lang, dir, and schema are the frontmatter keys with behavior; every other key becomes a <meta> tag, and draft, permalink, and slug are errors that name what unify does instead. Built pages contain no <slot> elements, no data-layout attributes, and no injected script — the one unify token that can survive into output is <meta name="schema">, on a page that asked for a generated JSON-LD block.

The full model is specified in the Product Specification; the exact algorithms — slots, head merge, root attributes, URL rewriting — are in the Conformance Specification.

Commands

unify [build]            build the site (default command)
unify audit              evaluate the site the build would publish — writes nothing
unify dev                build, watch, serve, and reload — the inner loop
unify watch              build + rebuild on change, no server
unify init [template]    scaffold a starter site — a built-in name, a directory, a git repository (URL/<subdirectory>#ref), or any npm package
unify update [template]  fetch the template again and copy its changed files over the site: the files it would overwrite are listed and confirmed first (--yes answers, --dry-run previews); keep: under template: in unify.yaml names the files it never overwrites

unify --help lists every option — among them --pretty-urls, --base-url (which also generates sitemap.xml, and feed.xml once a page declares schema: Article/BlogPosting), --canonical none (completion is on once --base-url is set), --catalog, --search-corpus, --dry-run, and --strict. The CLI Reference documents every command, option, and exit code — there are no others. An optional unify.yaml at the project root holds saved flags and nothing more — only what differs from the defaults; unify init writes one with every option described and commented out, and unify build --save-config fills it from the flags you pass.

Examples

examples/ holds eight complete sites, each building clean under unify build --dry-run --strict. Four were authored by agents given nothing but the sixty-line authoring rules and a client brief, and kept because they passed review — so they show what the rules actually lead someone to build; the other four are hand-maintained, including unify's own documentation site built by unify, another generator (Eleventy) adopted as source through --generate, and a blog whose browse, filter, and search UI is data-driven from --catalog/--search-corpus. Between them: pages generated from a data file, client-side filtering, a section with its own chrome, a page with no chrome for embedding, deploying under a subdirectory, htmx swapping .fragment.html panels, a Svelte component compiled to an ordinary asset, and client-side search over generated JSON. examples/README.md names the pattern in each.

Documentation

Everything below is published at unify.fwdslsh.dev, built from docs/ by unify itself.

Using unify

  • Getting Started — the tutorial.
  • Authoring Rules — the complete authoring surface, in under sixty lines.
  • CLI Reference — every command, option, and exit code.
  • JavaScript API — experimental, may be removed before v1. run(options): the build as a function, returning the status, the diagnostics, the built files and the audit report as data.
  • Templates — scaffold from a built-in, a directory, a git repository or an npm package; keep the site current with unify update, which lists what it would overwrite and asks; publish a template of your own.
  • Integrations — the compile-to-asset pattern: Svelte, TypeScript, or anything with a compiler, without adopting a framework.
  • Eleventy + htmx — the advanced stack: another generator produces data-driven pages, unify composes them, htmx enhances them. Optional layers, and when not to reach for them.
  • Catalog and Search — a blog list, facets, and a search box built client-side from the two files --catalog/--search-corpus write.
  • Generator Recipes — a content hash in an asset's URL, and an RSS feed with day-only dates handled your way, each in a screenful of --generate.
  • Porting an Existing Site — keep every live URL: which source path answers to each address, with and without --pretty-urls, and a ten-line check of the whole list against a build.
  • Template Versions — pin a template to a version, move the pin with unify update, pin what extends: builds on, and try a template or unify before it ships.
  • Docker Usage — running the CLI in a container.
  • Examples — eight complete sites and the patterns they demonstrate.

How unify is defined

How the documentation was validated

For Agents

Authoring or editing a site built with unify? Review docs/authoring-rules.md — the complete authoring surface in under sixty lines — before writing anything, and do not substitute conventions from other generators: unify has no props, no expressions, no draft:/permalink:/slug: keys, and layouts do not chain.

  • unify init drops an README.md at the project root (outside site/, so it cannot publish) restating the most commonly guessed-wrong rules. If the project has one, read it — it restates the rules linked above, never a variant of them.
  • Finish by checking: unify build --dry-run --strict, then unify audit --strict. Exit 0 from unify build means dist/ is the complete site; non-zero means nothing was published and the previous output is untouched — never report success on a non-zero exit.
  • unify --help lists the complete CLI. There are no other commands or flags; the authoring rules live in docs/authoring-rules.md and the scaffolded README.md, not in a CLI command.

Contributing to unify itself? Start with CLAUDE.md and CONTRIBUTING.md; the Conformance Specification is normative.

Guarantees

  • Content you wrote is never silently dropped. Anything that would lose authored content is a problem, and problems block publishing. The milder severity, advisory, never blocks (under --strict it counts). Diagnostics are plain language, located, and name a fix — no rule codes.
  • Publishing is transactional. Composition and every check — including a reference check of every internal URL — run into a temporary tree, and dist/ is replaced only on zero problems. Exit 0 means dist/ is the complete site; 1 means problems were found and the previous output is byte-for-byte untouched; 2 means invalid usage.
  • unify build --dry-run --strict runs the whole build and every check while writing nothing — the one-line CI lint.

And the guarantees that run the other way — what unify will never do:

  • Ship JavaScript. Your scripts pass through untouched; unify injects none of its own (dev's live reload never reaches dist/).
  • Grow a templating language. No variables, loops, conditionals, or props. Derived pages come from a script you own, run before the build — a feed is the one exception (schema: plus --base-url).
  • Become a component framework. Slots fill layouts; <include> splices a file verbatim, or fills a fragment's slots with markup you wrote — never props or values.
  • Need configuration. Conventions, not config files.
  • Scope your CSS, or be a real web server. @scope/@layer and a real server already answer those.

The full list, with the reasoning and the accepted costs, is Product Specification §5.

Auditing

unify audit answers a different question — not is this build sound? but is this site complete? It runs the same pipeline, publishes nothing, and reports findings: a page with no description, two pages sharing a title, a #fragment link that names nothing, duplicate ids, a page nothing links to, structured data that contradicts its page. No score, no grade, no character counts — and build never runs any of it, so no finding can hold up a release. unify audit exits 1 on a broken finding (output that contradicts itself — wrong whatever you meant), unify audit --strict also fails on incomplete ones (what you may have chosen) and is the strict CI gate, while unify build --audit publishes only if the same audit would pass. --format json|sarif is the machine-readable mirror, and --external checks off-origin links — the one flag in the product that touches the network. While unify dev is running, the same findings are a live page at http://localhost:3000/_unify/, grouped by page with each page's record beside them.

Contributing

See CONTRIBUTING.md. Development setup:

git clone https://github.com/fwdslsh/unify
cd unify
bun install
bun test

License

Mozilla Public License 2.0. See LICENSE.

版本与发布记录

@fwdslsh/unify 共发布 56 个版本,首次发布于 2025/08/01;过去 12 个月发布了 45 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.12.0latest2026/11/105 天前
0.11.192026/11/105 天前
0.11.182026/11/106 天前
0.11.172026/10/2917 天前
0.11.162026/10/131 个月前
0.11.16-alpha.1next2026/10/131 个月前

关于 @fwdslsh/unify 的常见问题

@fwdslsh/unify 是什么?

A static site generator for HTML-native composition: includes, layouts, and slots in plain HTML — no expression language, no client runtime

如何安装 @fwdslsh/unify?

在项目目录运行 npm install @fwdslsh/unify,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 unify,可以用 npx unify 直接运行。

@fwdslsh/unify 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/fwdslsh__unify 是否存在。

@fwdslsh/unify 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@fwdslsh/unify 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22.12.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@fwdslsh/unify 可以商用吗?

@fwdslsh/unify 使用 MPL-2.0 许可。弱 Copyleft:可以商用,也可以和闭源代码一起使用;但如果分发时修改了 MPL 授权的文件,这些文件的修改需以 MPL 开源。以上为概括,不构成法律意见,请以许可原文为准。

@fwdslsh/unify 的下载量有多少?

根据 npm 官方下载统计,@fwdslsh/unify 在 2026/10/16 – 2026/11/14 这 30 天内被下载 2,527 次,日均约 84 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@fwdslsh/unify 还在维护吗?

最新版本 0.12.0 发布于 2026/11/10(5 天前);至今共发布 56 个版本,其中过去 12 个月发布了 45 个;首次发布于 2025/08/01。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。