Skip to content

Configuration

.staticbolt.ts

The config is a TypeScript file at the project root that exports a list of plugins. Everything the build does is a plugin, and the order they are listed in is the order they run.

import { defineConfig } from "@staticbolt/core";
import * as plugins from "@staticbolt/core/plugins";
import postcssPresetEnv from "postcss-preset-env";
export default defineConfig({
plugins: [
plugins.loadSourcesPlugin({ include: ["./pages/**/*.{html,md}"] }),
plugins.transformJsPlugin(),
plugins.transformCssPlugin({ plugins: [postcssPresetEnv()] }),
plugins.bundlePackagesPlugin(),
plugins.htmlLayoutPlugin(),
plugins.htmlPagesPlugin(),
plugins.htmlInsertPlugin(),
plugins.htmlInlineScriptPlugin(),
plugins.htmlInlineStylePlugin(),
plugins.htmlBundleScriptPlugin(),
plugins.htmlMarkdownPlugin(),
plugins.htmlPreloadPlugin(),
plugins.writeFilesPlugin({ clean: true, minify: { enabled: true } }),
plugins.convertImagePlugin(),
plugins.copyAssetsPlugin(),
plugins.analyzeOutputPlugin({ skipUnusedFiles: true }),
plugins.developmentServerPlugin(),
plugins.coreMarkdownPlugin(),
plugins.coreHtmlPlugin(),
plugins.coreScriptPlugin(),
plugins.coreStylePlugin(),
plugins.buildCliPlugin(),
plugins.serveCliPlugin(),
],
});

Use --config <path> to point at a different file, and --cwd <directory> to run against a different project. Both work with every command.

Plugin order

The stages run top to bottom, and each one only sees what the ones above it produced:

Stage What runs there
Sources loadSourcesPlugin picks the entry points. The transform plugins compile JS and CSS.
HTML Layouts, parts, inlining, bundling, markdown: everything that rewrites a document.
Output writeFilesPlugin, image conversion, asset copying, then analyzeOutputPlugin sweeps up.
Post-build Sitemap, service worker, search indexes: anything that reads the finished output.
Core The parsers that each file type goes to. They sit last so plugins above can claim work first.
CLI The commands the staticbolt binary exposes.

Moving a plugin above or below another changes what it sees, which is the point: a plugin that should claim a <script> before the core HTML plugin does simply sits earlier in the list.

A plugin can also set enforce. "pre" runs each of its hooks before every hook without an enforce, "post" after them. The config order still holds inside each group, and the core base plugin stays last either way.

One hook can set its own enforce instead, without moving the rest of the plugin:

{
name: "my-plugin",
write: { enforce: "pre", handler() { /* runs before every plain write hook */ } },
postBuild() { /* stays where the plugin is listed */ },
}

Aliases

Aliases come from tsconfig.json, so the build and the editor resolve paths the same way:

{
"compilerOptions": {
"paths": {
"~/*": ["./pages/*"],
"@/*": ["./sources/*"],
"@assets/*": ["./sources/assets/*"],
"@scripts/*": ["./sources/scripts/*"],
"@styles/*": ["./sources/styles/*"],
"@layouts/*": ["./sources/layouts/*"],
"@parts/*": ["./sources/parts/*"]
}
}
}

Adding a directory means adding its alias here, and nothing else has to change. ~/about/ in an href resolves to the built page, relative to whatever file the link ends up in, so the same markup works at the site root and under a sub-path.

Environment

production-only and development-only attributes drop an element from the build it does not belong in:

<link href="@styles/docs.css" production-only rel="prefetch" />

Per-plugin reference

Every plugin has its own page under docs/plugins, grouped by what it works on.