Styx
5 min read

Nix-based static site generator. Sites are defined entirely in Nix expressions; content is written in Markdown, AsciiDoc, or native Nix and rendered via customizable themes.

Key Features

• All templates, logic, and data use the same Nix expression language
• Efficient incremental builds via Nix's caching (only modified content is rebuilt)
• Minimal dependencies — only Nix required
• Type-checked configuration via NixOS module system
• Automatic SASS/SCSS compilation
• Embedded Nix expressions inside markup files ({{ expr }})
• Multipage / paginated content via mkSplit
• Taxonomy system (mkTaxonomyData / mkTaxonomyPages)
• Built-in link checker (styx linkcheck)

Limitations

• Markup conversion can be slow (mitigated by caching on rebuilds)
• Requires learning the Nix expression language

Installation

bash
# Temporary shell
nix shell github:styx-static/styx

Quick Start

bash
styx new site my-site
cd my-site
styx preview # serve at http://127.0.0.1:8080
styx doc # open full HTML documentation in browser

Preview a bundled theme without creating a site:

bash
styx preview-theme showcase

CLI Reference

Generic Flags

FlagDescription
--helpDisplay help
--versionDisplay version
--in DIRRun command in specified directory
--file FILEUse a custom file instead of site.nix
--draftsInclude draft content in build
--show-traceShow debug trace on failure
--arg NAME VALUEPass argument to main function
--argstr NAME VALUEPass string argument to main function
-I PATHAdd path to Nix expression search path

Commands

CommandDescription
styx new site NAMECreate a new site in current directory
styx new site NAME --in DIRCreate site in DIR/NAME
styx new theme NAME --in DIRCreate a new theme skeleton
styx buildBuild site to public/ directory
styx build --out DIRBuild to custom output directory
styx store-pathReturn the Nix store path of the built site
styx previewStart local server at 127.0.0.1:8080
styx preview --port 9090Start server on custom port
styx preview-theme NAMEPreview a bundled theme
styx liveAuto-rebuilding live preview (quit with q)
styx serveBuild and serve site on port 8080
styx serve --detachServe in background
styx linkcheckValidate all links in the built site
styx docOpen HTML documentation in browser
styx site-docGenerate and display site-specific docs
styx gen-dataGenerate sample data in ./data
styx theme-path NAMEPrint the store path of a bundled theme
styx deploy --init-gh-pagesInitialize gh-pages branch for GitHub Pages
styx deploy --gh-pagesBuild and deploy to GitHub Pages

Project Structure

A minimal site only needs site.nix. The styx new command scaffolds:

my-site/
├── conf.nix # site configuration
├── default.nix # allows building with plain `nix build`
├── site.nix # core site logic
├── data/ # content (Markdown, AsciiDoc, Nix files)
└── themes/ # custom/local themes

site.nix Structure

A site.nix is conventionally divided into sections:

nix
# 1. Init — load styx library
# 2. Themes — declare themes and load their assets/conf
# 3. Data — load content files with loadFile / loadDir
# 4. Pages — declare pages (path, template, layout)
# 5. Site — call mkSite with the pages list

Every page must declare three attributes:

AttributeDescription
pathOutput file path, must start with / (e.g. "/index.html")
templateFunction page -> page that processes the page data
layoutFunction page -> string that wraps the template output

Generation evaluates page.layout (page.template page) for each page.

Configuration (conf.nix)

Configuration is merged from three sources (highest priority last):

1. Theme's own conf.nix
2. Site root conf.nix
3. extraConf passed via CLI

conf.nix can be a plain attribute set or a function returning one (receives { lib }).

The only required field is siteUrl — must not end with /:

nix
{
siteUrl = "https://example.com";

theme.site.title = "My Site"; # override theme config
}

Content / Data

Loading Content

nix
data = {
posts = loadDir { dir = ./data/posts; }; # list of attr sets
about = loadFile { file = ./data/pages/about.md; };
};

loadFile / loadDir automatically:

• Parse YAML front matter (between --- delimiters)
• Extract introductions
• Evaluate embedded {{ nix }} expressions

Supported Formats

FormatUse caseProcessor
MarkdownSimple posts and pagesPandoc → content attr
AsciiDocComplex documents with rich formattingAsciidoctor
NixComplex data structures, parameterized dataNative

Drafts

Mark a file as a draft in front matter:

yaml
---
draft: true
---

Drafts are excluded unless --drafts flag is passed or renderDrafts = true in conf.

Taxonomies

nix
taxonomyData = mkTaxonomyData { data = posts; taxonomies = [ "tags" "author" ]; };
taxonomyPages = mkTaxonomyPages { data = taxonomyData; ... };

Page Types

TypeFunctionDescription
Simple—Single page with required attributes
Data-attached//Merge external data into a page
Split/PaginatedmkSplitDistribute a list across multiple pages with pagination metadata
MultipagesmkMultipagesHierarchical nested page sets
Page listmkPageListProduces list (no subpages) and pages (all) attributes
TaxonomymkTaxonomyPagesIndex + term pages from taxonomy data

Themes

Available Bundled Themes

ThemeDescription
agencyBusiness / corporate
generic-templatesFlexible reusable templates
ghostwriterContent-focused, readable
hydeSidebar layout
nixMinimalist
orbitModern / portfolio
showcasePortfolio / showcase

Using Themes in site.nix

nix
themes = [ pkgs.styx-themes.hyde ]; # official theme
# or
themes = [ ./themes/my-theme ]; # local theme

Items at the beginning of the list have lower priority; later entries override earlier ones — useful for layering a customization theme on top of a base theme.

Creating a Theme

bash
styx new theme my-theme --in ./themes

Scaffold:

my-theme/
├── conf.nix # typed or untyped configuration interface
├── meta.nix # metadata — must include `id` attribute
├── files/ # static assets copied to generated site
├── templates/ # template .nix files
└── lib.nix # (optional) custom functions

Theme config is merged into conf.theme and can be overridden from the site's conf.nix.

Deployment

GitHub Pages

bash
styx deploy --init-gh-pages # one-time: creates gh-pages branch
styx deploy --gh-pages # build + commit to gh-pages branch

Amazon S3

bash
aws s3 sync $(styx store-path) s3://<bucket-name>/