Alloy
A fast, extensible static site generator. Built in Go.
Why Alloy?
Static site generators tend to make you choose between speed and extensibility. Alloy doesn't. It compiles thousands of pages in seconds, uses Liquid templates for a familiar developer experience, and supports a flexible plugin system — embedded QuickJS for simplicity, compiled WASM for performance, and Node.js for full ecosystem access — without sacrificing build performance.
Features
- Fast builds — Go-powered concurrent pipeline targeting < 5s for 1,000 pages
- Liquid templates — Familiar syntax with Go
html/template as an alternative
- Data cascade — Global data, directory-level
_data.yaml, and front matter deep-merge predictably (front matter wins)
- Collections and taxonomies — Date-based section collections, cross-cutting taxonomy groups, auto-generated term pages
- Pagination — Paginated lists and virtual page generation from data
- Content lifecycle — Draft/future/expired content with sensible defaults
- Permalinks — Fast token replacement with Liquid fallback for complex patterns
- Multiple output formats — HTML, JSON, XML, or anything else from a single content file
- i18n — Opt-in multilingual support with per-language content trees and shared layouts
- Incremental rebuilds (dev mode) — Content-hash change detection in
alloy dev for fast rebuilds on file changes. alloy build always does a full clean rebuild for CI/CD reliability.
- Flexible plugin system — Built-in Go filters (ns), in-process JS/WASM plugins (us), Node subprocess plugins (ms)
- Plugin dependency tracking — Plugins declare file dependencies; dev server rebuilds only affected pages when those files change
- Dev server — File watching, WebSocket live reload, error reporting, concurrent process detection via lockfile
Installation
# Homebrew (macOS / Linux, recommended)
brew tap zeroedin/alloy-ssg
brew install alloy-ssg
# Go install (from source, requires Go 1.25+)
go install github.com/zeroedin/alloy@latest
Windows: use WSL and install via Homebrew inside your Linux environment, or download a prebuilt binary from the releases page. See Installation for all options, including building from source.
Quick Start
# Scaffold a new project
alloy init my-site && cd my-site
# Start the dev server
alloy dev
# Build for production
alloy build
Project Structure
my-site/
├── alloy.config.yaml # Site configuration (YAML, TOML, or JSON)
├── content/ # Content files (Markdown, HTML)
│ ├── index.md
│ └── blog/
│ ├── _data.yaml # Directory-level data (cascades down)
│ └── first-post.md
├── layouts/ # Liquid templates
│ ├── default.liquid
│ └── partials/
├── assets/ # Processed via plugin hooks
├── static/ # Copied as-is to output
├── data/ # Global data files (YAML, JSON, TOML, CSV)
└── plugins/ # JS, WASM, or Node plugins
See Project Structure for details.
Configuration
All site settings live in alloy.config.yaml (TOML and JSON also supported). Directory paths, build output, template engine, taxonomies, pagination, and passthrough mappings are all configurable. See Configuration for the full reference.
Content
Content files live in content/ with YAML, TOML, or JSON front matter. Template tags ({{ }} and {% %}) work directly in Markdown. See Content for details.
Templates
Alloy supports Liquid (default) and Go html/template as built-in engines. Both share the same layout lookup order, data context, and built-in filters. See Templates for details.
Data Cascade
Global data, directory data, and front matter deep-merge in a defined order (front matter wins). Plugin hooks can mutate page data at key points during the build. See Data Cascade for details.
Plugins
Three approaches, matched to what the plugin needs:
| Tier |
Runtime |
Latency |
Use case |
| 1 |
Go built-in |
~ns |
String, date, array, URL, math filters |
| 2 |
JS (QuickJS) or WASM via wazero |
~us |
Custom filters, shortcodes, data transforms |
| 3 |
Node subprocess |
~ms |
PostCSS, Sharp, Lit SSR, npm packages |
Drop a .js file in plugins/ and it runs on embedded QuickJS. Export runtime: "node" for Node. Drop a .wasm file for compiled plugins. No config needed. See Plugins for details.
Lifecycle Hooks
Plugins can hook into 14 lifecycle events covering config, content rendering, asset processing, and build completion. Hooks chain in alphabetical filename order. See Lifecycle Events for the full list and payloads.
CLI
alloy init Scaffold a new project
alloy build Full clean build to _site/
alloy dev Dev server with live reload (incremental rebuilds, drafts visible)
alloy serve Production server (same pipeline as build, served locally)
alloy version Print version
See CLI Reference for all flags and build modes.
Dependencies
| Package |
Purpose |
License |
| liquidgo |
Liquid template engine |
MIT |
| goldmark |
Markdown rendering |
MIT |
| cobra |
CLI framework |
Apache-2.0 |
| fsnotify |
File watching |
BSD-3 |
| wazero |
WASM runtime (plugins) |
Apache-2.0 |
| gorilla/websocket |
Live reload |
BSD-3 |
| sonic |
High-performance JSON |
Apache-2.0 |
| qjs |
QuickJS binding (Tier 2 JS plugins) |
MIT |
| toml |
TOML config/front matter parsing |
MIT |
| doublestar |
Glob pattern matching |
MIT |
| strftime |
Date formatting |
MIT |
| semver |
Version comparison (update checks) |
MIT |
| term |
Terminal detection |
BSD-3 |
Development
Prerequisites
- Go 1.25+ —
go version
- Node.js (optional) — only needed for Tier 3 plugins. Not required to build or test Alloy itself.
Build
# Clone and build
git clone https://github.com/zeroedin/alloy.git
cd alloy
go build -o alloy .
# Verify
./alloy version
Test
# Run all tests
go test ./...
# Run a specific package
go test ./internal/template/...
go test ./internal/pipeline/...
go test ./test/integration/...
# Verbose output
go test ./... -v
Tests use Ginkgo + Gomega. Tests are spec-derived and immutable — they define expected behavior. If a test fails, the implementation must change, not the test.
Project Layout
cmd/ CLI commands (init, build, dev, serve)
internal/
assets/ Asset processing hooks
cache/ Build cache for incremental rebuilds
cascade/ Data cascade (merge engine)
collection/ Collections and taxonomies
config/ Config loading (YAML, TOML, JSON)
content/ Content discovery, front matter, markdown
data/ Data file loading (YAML, JSON, TOML, CSV)
fetch/ External data source fetching (REST, GraphQL)
fileutil/ File utility helpers
i18n/ Multilingual support
jsonutil/ JSON utilities (sonic-backed)
ordered/ Ordered map for key-order preservation
output/ Output writing, sitemap, feeds
pagination/ Pagination and virtual pages
permalink/ URL generation
pipeline/ Build pipeline orchestration
plugin/ Plugin system (QuickJS, WASM, Node)
server/ Dev server, file watcher, WebSocket
ssr/ Web Component SSR (experimental)
static/ Static file and passthrough copy
template/ Liquid + Go template engines, filters
update/ Update notification (GitHub release checks)
validation/ Output path conflict detection
test/
fixtures/ Test site fixtures
integration/ Cross-package integration tests
plans/
PLAN.md Specification
IMPLEMENTATION.md Implementation guide
Architecture
The spec lives in plans/PLAN.md. The implementation guide is plans/IMPLEMENTATION.md. Both are the source of truth — tests encode the spec, implementation must conform to tests.
Workflow: Spec changes → tests → implementation. Tests are written first (red), implementation makes them green. Tests are never modified to pass.
License
MIT