Add Eleventy SSG: pre-render partials, minify HTML/CSS/JS#33
Open
noahbaculi wants to merge 2 commits intostagingfrom
Open
Add Eleventy SSG: pre-render partials, minify HTML/CSS/JS#33noahbaculi wants to merge 2 commits intostagingfrom
noahbaculi wants to merge 2 commits intostagingfrom
Conversation
Eliminates 4-6 runtime fetch() calls per page that caused layout shift on
slower connections. Shared partials (header, nav, footer) are now inlined
at build time via Eleventy + Nunjucks templates.
Build pipeline:
- eleventy.config.js: processes all .html pages through Nunjucks, copies
static assets, minifies HTML output (collapseWhitespace, minifyCSS, minifyJS)
via html-minifier-terser transform
- scripts/minify-assets.js: post-build CSS minification (clean-css) and JS
minification (terser) on _site/assets/
Layout system:
- _includes/layouts/base.njk: all pages — inlines header, navbar, conditional
subnavbar (section: professional|hobbies), side_menu, footer, main.js
- _includes/layouts/home.njk: homepage only — inline animated SVG tagline,
top_professional and top_projects snippets; no subnavbar needed
- _includes/head.njk: shared <head> accepting title, description, noindex,
extraCss[], preJs[], extraJs[] front matter variables
Pages:
- Each .html file now has YAML front matter (layout, title, description,
section) and contains only its unique body content
- professional/index.html and projects/index.html use {% include %} to inline
top_professional.njk / top_projects.njk rather than fetch()-filling divs
- Standalone pages (baculicall.html, projects/guitar-tab-generator.html)
left unchanged — no layout needed
- familytree.html and 404.html use extraCss/extraJs front matter for their
additional stylesheet and script dependencies
main.js:
- Removed: loadSection(), replaceWithSection(), initNavbars(),
loadHomepageSections() and their top-level invocations
- Kept: highlightCurrentPages() (active nav link), initMenu() (mobile drawer)
- Both called directly on script load (no async dependency on fetch)
Routing:
- _data/eleventyComputed.js overrides Eleventy's default clean-URL output
(foo/index.html) to preserve .html extensions (foo.html), keeping all
existing internal links and Netlify redirects valid
- Output directory: _site/ (added to .gitignore)
- Netlify build: command = "bun run build", publish = "_site"
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove _data/eleventyComputed.js which forced .html output paths. Eleventy's default clean URL output (contact/ instead of contact.html) is correct since Netlify has Pretty URLs enabled. Strip .html extensions from all internal absolute links across _includes and page files. Fix /xxx/index links to /xxx/. Add permalink: /404.html to 404.html so Netlify serves it as the custom 404 page. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Every page load triggered 4–6 sequential
fetch()calls to inject the header, navbar, subnavbar, side menu, and footer fromassets/html/*.htmlfragments. This caused:Solution
Introduce Eleventy as a build step that pre-renders all shared partials into each HTML page at build time, and adds CSS/JS minification as a post-build step.
Design decisions
Why Eleventy over Hugo:
Hugo's implicit page-kind lookup (list/single/home) doesn't map cleanly to this site's flat structure. Eleventy's explicit
layout: base.njkfront matter declaration is more readable and the learning curve is lower for a small static site.Why clean URLs (no
.htmlextensions):Eleventy's default output is clean URLs (
contact.html→_site/contact/index.html, served at/contact/). Since Netlify has "Pretty URLs" enabled and all existing_redirectsalready target paths without.html, there's no reason to override this. The only exception is404.html, which keeps an explicitpermalink: /404.htmlso Netlify recognizes it as the custom 404 page. Internal links across all_includes/and page files have been updated to use clean URL paths.Why
html-minifier-terseras a transform rather than a plugin:The originally planned
@11ty/eleventy-plugin-html-minifier-terserpackage does not exist on npm.html-minifier-terseris already installed as an Eleventy transitive dependency, so a one-lineraddTransformineleventy.config.jsachieves the same result with zero extra dependencies.Two layouts instead of one:
base.njkhandles all pages identically.home.njkexists only because the homepage has a unique animated SVG tagline header and directly embeds thetop_professional/top_projectssnapshot sections — content that lives in the layout rather than the page body so it doesn't clutterindex.html.Standalone pages left untouched:
baculicall.html(no nav) andprojects/guitar-tab-generator.html(Twind CSS, fully custom structure) don't use the standard layout. Eleventy processes them as pass-through Nunjucks templates and outputs them unchanged.What changed
assets/html/*.htmlfetched at runtime_includes/*.njkinlined at buildmain.jsloadSection(),replaceWithSection(),initNavbars(),loadHomepageSections()highlightCurrentPages()+initMenu()called directly<!doctype>wrappers, placeholder divsclean-css+terser).htmlextensions/contact/,/professional/aldras/)bun run build→_site/Verification checklist
bun run buildcompletes with no errors,_site/populated/professional/aldras/) — header, subnavbar, footer inlined, no fetch calls in DevTools Network/hobbies/music/) — hobbies subnavbar present/) — animated SVG tagline, experience + projects snapshots visible without layout shift_site/assets/css/main.cssis minified (single line, no comments)_site/assets/js/main.jsis minified_site/404.htmlexists at root (not_site/404/index.html)🤖 Generated with Claude Code