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.