DOMStack builds static websites and multi-page apps from HTML, Markdown, CSS, and JavaScript. No special syntax to learn. No editor plugins to install. No complex configuration files to learn. Just create pages in a directory, and DOMStack builds your site. It's built around Node.js and esbuild, with a bunch of features that are there when you need them and stay out of the way when you don't.
Documentation · Examples · v12 migration guide · Discord
domstack supports:
- A natural filesystem-based router
- Reusable and composable layouts with fully customizable templating systems
- Markdown pages with frontmatter
- HTML pages (with template support)
- TS/JS pages (pages generated with anything you want)
- A comprehensive variable cascade system (global, layout, and page variables)
- Static asset management
- A live-reloading development server (with cross-device sync and debugging tools)
- Fast builds
- Faster incremental rebuilds
- esbuild-based page, layout, and global client bundling (TSX/JSX supported)
- esbuild-based page, layout, and global CSS bundling
- A global data introspection and collection pipeline
- Expressive (optional) TypeScript support
- A comprehensive build manifest (for offline MPA support)
- Service worker support
- Web worker support
- Page generators (generate pages from other pages)
- Template generators (generate anything from pages)
- Test helpers
- A default layout and stylesheet if none are provided
- Extensive examples, docs, and a cookbook
domstack builds pages from a src directory into a destination directory (usually public).
Page URLs follow the source directory structure, creating a filesystem router without separate routing configuration.
Given this source:
src/
├── page.md # The home page
├── style.css # Styles scoped to the home page
├── client.ts # Browser code loaded by the home page
├── layouts/
│ ├── root.layout.ts # The default layout for every page
│ └── blog.layout.ts # An optional layout selected by page variables
├── globals/
│ ├── global.css # Styles loaded by every page
│ ├── global.client.ts # Browser code loaded by every page
│ └── global.vars.ts # Variables available to every page and layout
├── about/
│ └── page.md # The /about/ page
├── interactive/
│ ├── page.html # The /interactive/ page
│ └── client.tsx # Page-scoped browser UI written with JSX
└── blog/
├── page.ts # The /blog/ page
└── first-post/
├── README.md # The /blog/first-post/ page
└── diagram.svg # A static asset colocated with the post
domstack produces output resembling the following (generated bundle hashes will vary):
public/
├── index.html # Home content rendered through root.layout.ts
├── style-ABC123.css # Bundle built from the home page's style.css
├── client-ABC123.js # Bundle built from the home page's client.ts
├── globals/
│ ├── global-ABC123.css # Site-wide bundle built from global.css
│ └── global.client-ABC123.js # Site-wide bundle built from global.client.ts
├── about/
│ └── index.html # About content rendered through root.layout.ts
├── interactive/
│ ├── index.html # Loads the bundle built from client.tsx
│ └── client-ABC123.js # Approximate output name for the TSX bundle
└── blog/
├── index.html # Blog content rendered through the selected layout
└── first-post/
├── index.html # Post content rendered through the selected layout
└── diagram.svg # Copied alongside the page that uses it
A page directory contains a page.md, page.html, or page.ts file.
README.md may be used instead of page.md, making the source tree browsable on GitHub.
Pages can also have colocated assets:
style.cssfor page-specific stylesclient.tsorclient.tsxfor page-specific browser codepage.vars.tsfor page variables*.worker.tsfor web workers
Note
Wherever you see .ts being used, you can also use .js.
Type checking is supported in both file types.
See Supported file types for all available extensions.
Layouts wrap page content in complete HTML documents.
The root layout is the default, while pages can select another layout through the layout variable.
Global styles, browser code, and variables apply across the site regardless of where their files live in src.
Templates and other advanced features can generate additional output as needed. The documentation covers each convention in detail.
domstack ships with sane defaults, so you can point it at a standard Markdown-documented repository and build a website with near-zero preparation.
Use Node.js 22.18+ within the 22.x release line, or Node.js 24 or newer.
The v12 prerelease is published under the beta npm tag.
In a new project directory:
npm init -y
npm install --save-dev @domstack/static@beta
mkdir srcCreate src/page.md:
# Hello, web
This page is built with DOMStack.Build the site:
npx domstackThe generated page is public/index.html, rendered with the bundled default layout and stylesheet.
Run npx domstack --watch to rebuild on changes, then open the local development server's URL.
Use npx domstack --serve to preview a production build.