Skip to content

Replace Next.js build with a custom Rust SSG#2320

Open
hockeybuggy wants to merge 2 commits intomainfrom
site-rewrite
Open

Replace Next.js build with a custom Rust SSG#2320
hockeybuggy wants to merge 2 commits intomainfrom
site-rewrite

Conversation

@hockeybuggy
Copy link
Copy Markdown
Owner

The site was built on Next.js 15 (Pages Router) with React 19. Even though every page used getStaticProps/getStaticPaths with fallback: false — making the output functionally static — the build still required Node, a React runtime, the Next.js Netlify adapter, and a substantial JS dependency tree. The only real client-side behaviour was the nav menu toggle.

This commit introduces a Rust static site generator in ssg/ that reads content/ + styles/ + templates and writes a flat directory tree to dist/. The package.json build/start/dev scripts now invoke cargo rather than next. The Netlify publish target is updated from .next to dist and the lambda functions config is dropped.

The Rust SSG uses pulldown-cmark for Markdown, minijinja for Jinja2-style templates, serde_yaml for YAML frontmatter, chrono for date parsing/formatting, and grass for compiling the existing SCSS unchanged. An Atom feed (public/blog/index.xml) and sitemap (public/sitemap.xml) are generated as part of the same cargo run. Client-side JS is reduced to a single 41-line nav.js that handles the hamburger menu toggle; the Plausible snippet stays as inline script in base.html.

A custom Node static server (serve_static.js) replaces next start. It serves dist/ on port 4000 and resolves directory URLs to index.html in-place without trailing-slash redirects, which is required because the Puppeteer e2e tests assert page.url() === the original URL.

All 87 e2e tests and 5 prebuild tests pass against the new output.

The site was built on Next.js 15 (Pages Router) with React 19. Even
though every page used getStaticProps/getStaticPaths with fallback:
false — making the output functionally static — the build still
required Node, a React runtime, the Next.js Netlify adapter, and a
substantial JS dependency tree. The only real client-side behaviour
was the nav menu toggle.

This commit introduces a Rust static site generator in ssg/ that
reads content/ + styles/ + templates and writes a flat directory
tree to dist/. The package.json build/start/dev scripts now invoke
cargo rather than next. The Netlify publish target is updated from
.next to dist and the lambda functions config is dropped.

The Rust SSG uses pulldown-cmark for Markdown, minijinja for
Jinja2-style templates, serde_yaml for YAML frontmatter, chrono for
date parsing/formatting, and grass for compiling the existing SCSS
unchanged. An Atom feed (public/blog/index.xml) and sitemap
(public/sitemap.xml) are generated as part of the same cargo run.
Client-side JS is reduced to a single 41-line nav.js that handles
the hamburger menu toggle; the Plausible snippet stays as inline
script in base.html.

A custom Node static server (serve_static.js) replaces `next start`.
It serves dist/ on port 4000 and resolves directory URLs to
index.html in-place without trailing-slash redirects, which is
required because the Puppeteer e2e tests assert page.url() === the
original URL.

All 87 e2e tests and 5 prebuild tests pass against the new output.
The build-site action was written for Next.js and had two problems
after the switch to a Rust SSG:

1. No Rust toolchain was installed, so `cargo run` would fail
   immediately on every CI run.

2. The cache paths referenced `.next/` and `public/`, which are no
   longer the build outputs. The built site now lives in `dist/`.

This commit installs the stable Rust toolchain via
dtolnay/rust-toolchain@stable, adds a Cargo registry/target cache
keyed on Cargo.lock (so dependency rebuilds are skipped when deps
haven't changed), and updates the output cache to point at `dist/`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant