How-to guides
Most of the site is how-tos, and they share one rule: a guide ends with a number. Configuration alone is cheap to publish and easy to get subtly wrong, so every how-to here shows the setup it was measured on, what changed, and by how much — a versioned Docusaurus build that went from 1 min 50 s to 58 s, a mobile LCP that moved from 2.9 to 1.7 seconds after a migration, a Hugo cold build cut from 131 to 34 seconds.
They are grouped below by topic, in the same order as the sections of the site, so tasks that belong together sit together: caching the build, then deploying only what changed, then rolling back when it goes wrong. Each entry carries its one-line summary so you can tell two similar-looking guides apart before you open either.
Accessibility for Static Sites
- Accessible Code Blocks in Documentation SitesMake highlighted code blocks keyboard-scrollable, readable at AA contrast in both themes and labelled for screen readers, using Shiki, Prism or Hugo Chroma.
- Accessible Dark Mode Toggles for Static SitesBuild a theme toggle for a static site that follows the OS setting, has a real name and state, avoids a flash of the wrong theme and keeps AA contrast in both.
- Accessible SVG Diagrams on Static SitesGive inline SVG diagrams a name, a useful description and a text alternative, keep labels readable in both themes, and check all of it at build time.
- Enforcing Alt Text for Markdown Images at Build TimeFail a static site build when Markdown images have missing, placeholder or file-name alt text, with remark and markdown-it plugins and a sensible escape hatch.
- Keyboard Navigation and Focus Order on Static SitesMake every link, menu and widget on a static site reachable by keyboard, with a visible focus ring and a tab order that follows the page.
- Skip Links and Landmarks in SSG LayoutsAdd a working skip link and a complete set of landmark regions to Astro, Eleventy, Hugo and Jekyll layouts, then test them with axe and a screen reader.
Astro vs Eleventy for Documentation Sites
- Loading Remote Content With Astro Content Layer LoadersPull content from an API or CMS into Astro collections with a custom content layer loader, cache it between builds with digests, and validate it with a schema.
- Sidebar Navigation in Astro and EleventyBuild a docs sidebar from content in Astro and Eleventy: ordering, nesting, active state, collapsed sections, page weight, and keeping incremental builds fast.
- Syntax Highlighting with Shiki in Astro and EleventyHighlight code at build time with Shiki in Astro and Eleventy: dual light and dark themes, line annotations, build-time cost and zero runtime JavaScript.
- Upgrading Eleventy 2 to 3 With ESM ConfigurationUpgrade an Eleventy 2 site to Eleventy 3, convert config and data files to ESM, fix plugin and filter breakage, and diff the output against the old build.
Docs Frameworks: Docusaurus, Starlight and VitePress
- Adding Local Search to a VitePress SiteTurn on VitePress's built-in local search, tune what it indexes and how it ranks, keep the index small on large docs, and measure its cost to the page.
- Customizing Starlight Without Forking the ThemeBrand a Starlight docs site with CSS custom properties, component overrides and plugins so every upgrade stays a one-line version bump instead of a merge.
- Generating API Reference Pages in Starlight From OpenAPIBuild REST API reference pages in Starlight from an OpenAPI spec at build time, link them with the guides, validate the spec in CI and keep pages fast.
- Internationalizing Starlight DocsAdd languages to a Starlight documentation site: locales config, translated UI strings, sidebar labels, fallback notices, per-locale search and build cost.
- Migrating MkDocs Documentation to VitePressMove an MkDocs Material site to VitePress: convert admonitions, tabs and nav, keep every URL working, and compare build time and page weight after.
- Migrating from MkDocs to StarlightMove a Material for MkDocs site to Starlight: convert admonitions and tabs, rebuild navigation from mkdocs.yml, keep every URL and cut build time by two thirds.
- Speeding Up Docusaurus Builds With RspackEnable Docusaurus Faster (Rspack, SWC and Lightning CSS) on a large docs site, fix the plugins that break, and measure build time and memory before and after.
- Versioned Documentation with DocusaurusCut a Docusaurus docs version, keep builds fast as versions pile up, archive old versions to static snapshots and route readers to the right one.
- Versioning VitePress Documentation Without a PluginPublish several versions of VitePress docs side by side using git branches, a version switcher and one deploy, with canonicals pointing at the latest.
Hugo Build Times for Large Repositories
- How to Benchmark Hugo vs Astro Build SpeedsBuild a reproducible Hugo-vs-Astro benchmark with hyperfine — identical corpus, pinned containers, production builds only — so numbers reflect the generators, not your laptop.
- Hugo Image Processing Cache in CIPersist Hugo’s resources cache between CI runs so image resizing and format conversion only run for new images, and keep the cache from growing forever.
- Hugo Modules and Dependency CachingUse Hugo Modules for themes and shared content, vendor or cache them in CI, pin versions with go.sum, and cut module download time from Hugo builds.
- Hugo partialCached for Faster BuildsFind the partials that dominate a Hugo build with template metrics, cache them with partialCached and the right variant keys, and avoid stale output.
- Parallel Hugo Builds Across CI JobsSplit a very large Hugo site into segments built in parallel CI jobs, merge the output safely, and measure when parallel builds beat a single larger runner.
- Profiling Hugo Templates With Template MetricsUse hugo --templateMetrics to find which partial is eating your build: read cumulative duration, spot cache misses, and cut a 41 s build to 6 s on 4,000 pages.
- Sharing a Theme Across Hugo Sites With ModulesMove a theme copied into several Hugo sites into one versioned Hugo Module, let sites override safely, roll out updates with Renovate and keep CI fast.
- Speeding Up Hugo Builds with Render Hooks & CachingCut Hugo build time with render hooks, partialCached, a persistent --cacheDir, and the image resource cache — with measured before/after seconds from hyperfine.
- Splitting Large Hugo Sites with SegmentsUse Hugo segments to render only part of a very large site, build sections in parallel CI jobs, and merge the output without breaking links or sitemaps.
Internationalization for Static Sites
- Language Detection and Redirects at the EdgeRedirect first-time visitors to their language with a Cloudflare Worker on the root URL only, honour a saved choice and keep crawlers and shared links intact.
- Multilingual Eleventy Sites With the i18n PluginBuild a multilingual Eleventy site with the official i18n plugin: per-language folders, locale-aware links and dates, translated strings and a switcher.
- Multilingual Sites with HugoBuild a multilingual Hugo site: per-language content directories, translated menus and string tables, translationKey linking and build-time checks per locale.
- Right-to-Left Layouts on Static SitesAdd Arabic or Hebrew to a static site: dir and lang per locale, logical CSS properties, mirrored icons, LTR code blocks and fonts that keep LCP in budget.
- Translation Workflows with Git and CrowdinConnect a static site repository to Crowdin so source changes flow to translators, translations return as pull requests and stale pages are flagged in CI.
- hreflang and Language Alternates on Static SitesGenerate reciprocal hreflang alternates from a translation key at build time in Hugo, Astro or Eleventy, and validate every language group in CI.
- i18n Routing in AstroConfigure Astro i18n routing: locales, an unprefixed default language, fallbacks, locale-aware links and content collections organised per language.
Jekyll Plugin Ecosystem
- Custom Domains and HTTPS for Jekyll on GitHub PagesPoint a custom domain at a Jekyll site on GitHub Pages, get HTTPS enforced, fix certificate and DNS errors, and keep url and baseurl correct in _config.yml.
- Deploying Jekyll with GitHub ActionsReplace the classic GitHub Pages Jekyll builder with a GitHub Actions workflow: any plugin, any Jekyll version, caching, previews and Pages deployment.
- Replacing Jekyll Plugins When Migrating to EleventyMap common Jekyll plugins — jekyll-seo-tag, jekyll-feed, jekyll-paginate, jekyll-picture-tag — to their Eleventy equivalents, with config and measured build impact.
- Running Jekyll in Docker for Reproducible BuildsBuild a Jekyll site in a pinned Docker image so writers, CI and production use the same Ruby, gems and native extensions, with fast cached rebuilds.
- Running Jekyll on GitHub Pages Without PluginsThe allowlist blocks most gems. Replace plugin behaviour with Liquid, data files and a build step — or take the Actions route and keep the plugins you actually need.
- Upgrading Jekyll and Ruby Versions SafelyMove an old Jekyll 3 site to Jekyll 4 and a supported Ruby without breaking pages: pin versions, upgrade in steps, diff the built output and fix what changes.
Migrating Between Static Site Generators
- Auditing Content Parity After a MigrationProve an SSG migration lost nothing: crawl old and new builds, compare URLs, titles, headings, links, images and metadata page by page, and triage the diffs.
- Converting Front Matter at Scale During MigrationScript front matter conversion across thousands of Markdown files between generators: field maps, type fixes, validation against a schema, and reviewable diffs.
- Keeping Redirects Working After an SSG MigrationBuild a redirect map from production data, emit it in your host’s format, chain nothing, and gate it in CI — so no inbound link breaks when the generator changes.
- Migrating From Hugo to Astro Without Breaking URLsMove a Hugo site to Astro content collections while reproducing every permalink: slug mapping, a typed schema, shortcodes as MDX components, and a URL parity gate in CI.
- Migrating WordPress to a Static Site GeneratorMove a WordPress blog to a static generator: export posts to Markdown, localise media, keep every URL, replace comments and forms, and measure the gain.
- Migrating a Docs Site From Jekyll to HugoConvert Jekyll collections, Liquid includes and permalinks to Hugo sections, partials and URL config — with a build that drops from 96 s to 3.4 s on 1,200 pages.
- Migrating a WordPress Export to EleventyConvert a WordPress XML export into Eleventy Markdown with front matter, images, categories and comments, keep every URL with redirects and verify parity.
- Migrating from Docusaurus to StarlightMove a Docusaurus documentation site to Starlight: content and admonition conversion, sidebars, MDX components, versioning decisions, redirects and results.
- Migrating from Gatsby to AstroMove a Gatsby content site to Astro: replace GraphQL queries with content collections, port React components as islands, and keep image quality and URLs.
- Migrating from Next.js Pages Router to AstroMove a content-heavy Next.js Pages Router site with getStaticProps to Astro: routes, data fetching, MDX, React islands, images, redirects and the measured result.
- Porting Shortcodes and Includes Between GeneratorsMap Jekyll includes, Hugo shortcodes, Eleventy shortcodes and MDX components onto each other — with a census-first strategy, stub-then-port order, and a rendering test per component.
- Replacing Gatsby GraphQL Queries During a MigrationInventory every Gatsby GraphQL query, map each to plain data functions or content collections, and migrate page by page with output checks.
Next.js Static Export for Content Sites
- Generating Sitemaps and RSS in Next.js Static ExportProduce sitemap.xml, robots.txt and an RSS feed from a Next.js App Router site with output export, using metadata routes and static route handlers.
- Handling Dynamic Routes in Next.js Static ExportgenerateStaticParams, catch-all segments, trailing slashes and the 404 problem: how to make dynamic routes work under output export without a server.
- Migrating from Gatsby to Next.js Static ExportA concrete recipe for moving a Gatsby content site to a Next.js static export — GraphQL data layer to file reads, plugins to libraries, with measured build and bundle deltas.
- Optimizing Images in Next.js Static Exportnext/image cannot optimise at request time in a static export. Three ways to get responsive, modern-format images back — build-time, loader and CDN — measured.
- Trailing Slash and basePath in Next.js Static ExportConfigure trailingSlash, basePath and assetPrefix in a Next.js static export so links, assets, canonicals and host URL handling agree on every static host.
- Using MDX in Next.js Static ExportRender MDX content in a Next.js App Router static export: @next/mdx vs next-mdx-remote, frontmatter, remark and rehype plugins, components and build cost.
Search for Static Sites
- Accessible Search UI for Static SitesBuild a static site search dialog that works with keyboards and screen readers: dialog semantics, result lists, live result counts and focus handling.
- Adding Pagefind to an Astro SiteAdd Pagefind search to a plain Astro site: post-build indexing, content boundaries, heading weights, a lazy-loaded UI and a CI relevance check.
- Building a Lunr Index at Build Time in EleventyGenerate a prebuilt Lunr search index from Eleventy collections, keep it small with field boosts and stop words, and load it only when readers search.
- Customizing the Pagefind UIMake Pagefind's search UI match your design system: theme variables, filters, result metadata, a modal trigger, or a custom UI on the JavaScript API.
- Indexing Hugo Sites with PagefindAdd fast, serverless search to a Hugo site with Pagefind: template attributes, taxonomy filters, multilingual output, CI integration and measured build cost.
- Multilingual Search on Static SitesBuild per-language search for a static site: language detection, stemming, compound words, CJK segmentation and keeping each locale's index small.
- Search Index Size Budgets for Large DocsSet a byte budget for static search on large documentation sites, measure first-query cost on real phones, and trim indexes that have quietly grown too big.
- Self-Hosting Typesense for a Static SiteRun Typesense as search for a large static site: index from the build, scoped search keys, typo tolerance, facets, cost and when Pagefind is enough.
- Tracking Zero-Result SearchesLog searches that return nothing on a static site with Pagefind or a search server, respect privacy, and turn the weekly report into synonyms and new content.
Technical SEO for Static Sites
- Adding JSON-LD Structured Data at Build TimeEmit valid JSON-LD from frontmatter in Astro, Eleventy and Hugo: build objects not strings, pick the right schema.org types, and validate every page in CI.
- Canonical URLs and Duplicate Content on Static SitesStop static sites serving one page at many URLs: pick a trailing-slash policy, redirect variants at the host and emit self-referencing canonicals from config.
- Generating Breadcrumb Structured Data in AstroGenerate visible breadcrumbs and matching BreadcrumbList JSON-LD in Astro from the URL or content collections, with readable names, and test both in CI.
- Generating Sitemaps for Large Static SitesGenerate sitemap indexes for static sites with thousands of pages: split by section, real lastmod from Git, only indexable URLs, and a CI check against the build.
- RSS and Atom Feeds for Static BlogsPublish valid RSS and Atom feeds from Eleventy, Astro or Hugo with full content, absolute URLs, stable IDs and correct headers, then check them in CI.
- SEO-Safe Pagination and Tag PagesGenerate crawlable pagination and useful tag archives in Eleventy and Hugo: plain links, self canonicals, a minimum tag size and no thin date archives.
- robots.txt and noindex for Preview and StagingKeep preview, staging and platform-host copies of a static site out of search results with X-Robots-Tag headers on Netlify, Vercel and Cloudflare.
CDN Caching Rules for SSGs
- Cache Busting with Content-Hashed FilenamesFingerprint every static asset so it can be cached for a year yet update instantly on deploy: bundler hashing, images, fonts and the HTML pointing to them.
- Cache Keys and Query Strings on CDNsStop tracking parameters from fragmenting a static site’s CDN cache: normalize query strings in the cache key on Cloudflare and CloudFront, and measure hit ratio.
- Cache-Control Headers for Static Sites in NginxSet Cache-Control in Nginx for a static site: immutable hashed assets, revalidated HTML, short-lived 404s and the add_header inheritance trap.
- Cache-Control Headers on Cloudflare PagesSet Cache-Control on Cloudflare Pages with a _headers file and Cache Rules — year-long immutable assets, revalidated HTML, and CF-Cache-Status HIT verified with curl.
- Cache-Control Headers on S3 and CloudFrontSet Cache-Control for a static site on S3 behind CloudFront: object metadata on upload, cache policies, response headers policies and invalidation, measured.
- Cache-Control Headers on Vercel for Static SitesHow Vercel caches static output by default, when to override it in vercel.json, and how CDN-Cache-Control and immutable assets change repeat-visit performance.
- Caching 404s and Redirects at the EdgeCache 404 pages and redirects on a static site’s CDN so bots, broken links and migration redirects stop hitting the origin, without making fixes slow to appear.
- Proper Cache Headers on Netlify for SSGsConfigure Cache-Control headers in Netlify _headers files — fingerprinted assets cached for a year, HTML revalidated every request, with exact Netlify syntax and curl verification.
- Purging the CDN Cache After a Static DeployPurge by path or tag instead of everything: why a full purge is an origin stampede, which files actually need invalidating, and how to wire a surgical purge into CI.
- Stale-While-Revalidate for Static HTMLCache static HTML at the edge with stale-while-revalidate: faster TTFB and repeat views, bounded staleness after deploys, and when to purge instead.
- Tiered Caching and Origin ShieldUse Cloudflare Tiered Cache or CloudFront Origin Shield so edge misses on a static site are served from a regional tier instead of the origin, with measured results.
CSS and JavaScript Asset Optimization
- Code Splitting and Module Preload in Vite-Based SSGsFind JavaScript that loads on every page of an Astro or VitePress site, split it with dynamic imports and manualChunks, and keep modulepreload hints honest.
- Inlining Critical CSS on Static SitesRemove the render-blocking stylesheet on static sites: inline small CSS whole, or extract critical rules per page with Beasties, and measure the trade-off.
- Keeping Tailwind CSS Output Small on Static SitesMeasure what makes Tailwind CSS grow on a static site, from broad sources and safelists to arbitrary values and theme bloat, and keep it under a budget.
- Minifying HTML, CSS and JS in EleventyMinify Eleventy output safely with html-minifier-terser, Lightning CSS and esbuild, keep code blocks intact, and measure what minification saves after brotli.
- Precompressing Assets with Brotli and ZstdPrecompress static site output at build time with brotli 11 and zstd 19, serve the variants from Caddy, nginx or Cloudflare, and measure the transfer saving.
- Purging Unused CSS with Tailwind and Lightning CSSCut unused CSS on static sites: tighten Tailwind content sources, purge legacy stylesheets against built HTML, safelist runtime classes and verify with Coverage.
- Tailwind v4 in Astro Without PostCSS PluginsMove an Astro site from Tailwind 3 with the PostCSS integration to Tailwind 4 on its Vite plugin: CSS-first config, sources, dark mode and build time, measured.
Cumulative Layout Shift Fixes for Static Sites
- Measuring CLS in the Field With web-vitals.jsCollect real-user CLS from a static site with the web-vitals attribution build, send it to an edge endpoint, and turn a 75th-percentile score into a named element to fix.
- Reserving Space for Ad and Promo SlotsStop ad units, sponsor blocks and promo banners from shifting a static site: size slots per breakpoint, handle empty fills, and render promos at build time.
- Reserving Space for Images and EmbedsStamp intrinsic dimensions on every image, wrap iframes in an aspect-ratio box, and handle art-directed sources — the build-time recipe that takes body-image CLS from 0.31 to 0.01.
Font Loading Strategies for Static Sites
- Auditing Font Payload per PageMeasure which fonts, weights and subsets each template of a static site really downloads, find unused faces and fallbacks, and set a font budget in CI.
- Metric-Matched Fallback Fonts with size-adjustUse size-adjust, ascent-override and descent-override to make a local fallback font take the same space as your web font, so the swap causes no layout shift.
- Preloading Fonts Without Double DownloadsA font preload that misses crossorigin, or points at a different URL than the @font-face rule, downloads the font twice. Here is how to preload fonts correctly.
- Self-Host Google Fonts to Eliminate Layout ShiftSelf-host Google Fonts to kill CLS and a third-party connection: download, subset, preload, font-display swap, and a size-adjust fallback with measured before/after CLS.
- Subsetting Variable Fonts for Faster First RenderCut a 128 KB variable font to 31 KB with glyph subsetting and axis pinning, generate the subset in the build, and keep punctuation and code glyphs from disappearing.
- Using System Font Stacks to Skip Web FontsReplace web fonts with modern system font stacks on a static site: which stacks to use, monospace and CJK choices, brand trade-offs and measured LCP and CLS.
Image Optimization Pipelines in Astro
- Art Direction with the Picture ElementServe different crops of a hero image to mobile and desktop with picture and media queries in Astro, Eleventy and Hugo, without hurting LCP or causing layout shift.
- Blur-Up Placeholders with LQIPGenerate tiny blurred placeholders for images at build time in Astro or Eleventy, inline them without slowing LCP, and decide when a solid colour is better.
- Building an Image CDN Pipeline for Static SitesWhen to offload image transforms to an image CDN versus build time: URL-based transforms, edge caching, and cost, compared across Cloudflare Images, imgix, and Netlify.
- Caching Processed Images Between BuildsPersist Astro and Eleventy image caches between CI builds so AVIF and WebP variants are generated once, with correct cache keys, pruning and measured build times.
- Generating Open Graph Images at Build TimeRender a unique social preview image for every page at build time with Satori and resvg, cache the output, and wire og:image tags into Astro, Hugo or Eleventy.
- Lazy-Loading Images Without Hurting LCPloading="lazy" saves bytes below the fold but delays the LCP image when applied to it. How to decide per image, per template, in Astro, Hugo and Eleventy.
- Optimizing WebP Images in Hugo Without PluginsGenerate WebP at build time using only Hugo's built-in image processing — no Node, no plugins, no system libraries. Requires the hugo-extended edition for WebP.
- Responsive Images with srcset in EleventyGenerate AVIF, WebP and JPEG widths with @11ty/eleventy-img, emit srcset and sizes that match your layout, and cache the output so builds stay fast.
- Serving AVIF With Fallbacks on Static SitesEmit AVIF, WebP and a legacy fallback from one build step, order picture sources correctly, keep Vary headers honest, and measure the real byte and LCP savings.
- Serving Astro Images Through Cloudflare Image ResizingMove Astro image processing from build time to Cloudflare Images transformations with a custom image service, cutting build time while keeping srcset and AVIF.
JavaScript Hydration & Partial Rendering
- Breaking Up Long Tasks on Static SitesFind long tasks that hurt INP on a static site, split them with scheduler.yield and idle callbacks, move work off the main thread, and measure the field result.
- Deferring Hydration with client:visible in AstroUse client:visible, client:idle and client:media to delay Astro island hydration until it is needed, cut startup JavaScript and protect INP on content pages.
- How to Reduce Bundle Size in Eleventy BuildsCut JavaScript in Eleventy builds — scope scripts per route, tree-shake and bundle with esbuild, and defer third-party code. Concrete before/after KB numbers.
- Measuring INP on Static Sites with RUMMeasure Interaction to Next Paint in the field with the web-vitals library and a RUM beacon, attribute INP to specific interactions, and reconcile lab versus field data.
- Replacing React Islands with Web ComponentsSmall interactive widgets rarely need React. Rewriting islands as custom elements removes the framework runtime, cuts JavaScript and improves INP.
- Server Islands in AstroUse Astro server islands to add small per-request parts to a static page, such as stock or account state, with fallbacks, caching headers and measured costs.
Largest Contentful Paint Optimization for Static Sites
- Improving TTFB for Static HTMLCut time to first byte for a static site’s HTML: edge caching of HTML, redirect hops, TLS and protocol settings, origin placement and 103 Early Hints, measured in the field.
- Measuring LCP Subparts with DevToolsSplit Largest Contentful Paint into TTFB, load delay, load duration and render delay in DevTools and field data, so you fix the part that is actually slow.
- Optimizing LCP on Astro with Priority HintsUse fetchpriority="high", rel=preload, and Astro Image priority to load the hero first and cut LCP — with measured before/after numbers from Lighthouse and WebPageTest.
Performance Budgets and Lighthouse CI
- Measuring Web Vitals in Playwright TestsMeasure LCP, CLS and interaction latency inside existing Playwright tests on a static site, with throttling, stable thresholds and per-PR results.
- Per-Template Performance BudgetsSet a performance budget for each page template of a static site, pick representative URLs automatically, and enforce them with Lighthouse CI and size checks.
- Performance Testing on Throttled Mobile ProfilesChoose throttling that matches your real readers, calibrate Lighthouse and WebPageTest against field data, and test static sites on real mid-range phones.
- Running WebPageTest Scripts Against Preview DeploysScript multi-step WebPageTest journeys — search, navigation, repeat views — against every preview deploy, from locations Lighthouse cannot emulate.
- Setting Up Lighthouse CI for a Static SiteWire Lighthouse CI into GitHub Actions against every preview deploy: URL selection, assertions, a required status check and stored reports, in about an hour.
- Tracking Bundle Size per Pull RequestCompare every build's JavaScript, CSS and font output against the base branch, post the diff on the pull request and fail on budget breaches in seconds.
- Tracking Page Weight Over TimeRecord page weight per template on every deploy of a static site, chart the trend, attribute each jump to a commit, and catch slow growth that budgets miss.
- Writing a Performance Budget That Fails BuildsDerive byte, request and timing limits from your own site, encode them per template in budget.json and CI, and ratchet them down without constant false alarms.
Resource Hints and Navigation Speed
- Auditing Unused PreloadsFind preloads that waste bandwidth or compete with the LCP resource across a whole static site, remove them safely, and stop new ones creeping back in.
- Early Hints (103) on CloudflareSend 103 Early Hints from Cloudflare for a static site so browsers start fetching CSS, fonts and the LCP image before the HTML arrives, and measure when it helps.
- Fetchpriority Beyond the Hero ImageUse fetchpriority beyond the LCP image: demote carousels and decorative images, raise critical fetches, and measure the effect on LCP and INP.
- Instant Navigation with Speculation RulesPrerender likely next pages on a static site with the Speculation Rules API: eagerness levels, exclusions, prerender-aware analytics and field results.
- Prefetching Links in AstroConfigure Astro's built-in prefetch — strategies, defaults, per-link overrides and speculation rules — and measure what it does to navigation speed.
- View Transitions in Astro Without Hurting VitalsAdd view transitions to an Astro site with the ClientRouter or native cross-document transitions, then keep LCP, INP and CLS intact with measured settings.
- View Transitions on Multi-Page Static SitesAdd cross-document view transitions to a static site with CSS alone: opt-in rules, named elements, reduced motion, avoiding layout shift, and the measured cost.
Third-Party Script Performance on Static Sites
- Auditing Third-Party Scripts With LighthouseUse the third-party summary, the treemap and a long-task trace to attribute every kilobyte and millisecond to a vendor — then gate the total in CI so it cannot creep back.
- Facades for Chat Widgets and MapsReplace chat widgets, maps and other heavy embeds on a static site with lightweight facades that load the real thing on interaction, with measured savings.
- Lazy-Loading YouTube Embeds on Static SitesReplace the iframe player with a build-time poster facade: 780 KB and 310 ms of blocking time removed from every page load, with keyboard and screen-reader support intact.
- Loading Google Tag Manager Without Hurting INPGoogle Tag Manager and the tags it injects run long tasks that delay clicks. Load it later, trim triggers, and yield in click handlers to keep INP healthy.
- Measuring Third-Party Cost with Request BlockingQuantify what each third-party script costs a static site by blocking it in Lighthouse and WebPageTest, then compare LCP, TBT and bytes with and without it.
- Running Third-Party Scripts in a Web Worker with PartytownPartytown moves analytics and tag scripts into a web worker so they stop blocking the main thread. How to set it up on a static site and which scripts break.
- Self-Hosting Analytics to Cut Third-Party RequestsReplace a vendor analytics connection with a first-party script and an edge endpoint: no extra DNS or TLS, no consent-blocking dependency, and 6 KB instead of 96 KB.
Cloudflare Pages Edge Caching Setup
- Automating Eleventy Deployments on Cloudflare PagesDeploy Eleventy from Git on Cloudflare Pages: connect the repo, set the build command and _site output, pin Node, wire env vars, and ship cache headers — with build times.
- Branch Deploy Controls on Cloudflare PagesControl which branches build and deploy on Cloudflare Pages, name preview aliases, skip builds for docs-only changes and keep preview traffic private and cheap.
- Cloudflare Pages Functions MiddlewareUse _middleware.js in Cloudflare Pages Functions to add headers, auth, redirects and A/B routing to a static site, scoped by path and measured for latency and cost.
- Configuring Redirects on Cloudflare PagesWrite a _redirects file for Cloudflare Pages, know its limits, and move large or dynamic rule sets to Bulk Redirects or a Worker without slowing requests.
- Custom Domains and TLS on Cloudflare PagesAttach apex and www domains to Cloudflare Pages, understand how certificates are issued, choose the right SSL mode, and fix the common validation failures.
- Deploying Astro to Cloudflare Workers Static AssetsDeploy a static Astro site to Cloudflare Workers with static assets: wrangler config, trailing slashes, 404 handling, headers, previews and optional server routes.
- Deploying Hugo to Cloudflare Pages and WorkersDeploy a Hugo site to Cloudflare Pages — pin HUGO_VERSION, set the build command and public output dir — and learn when Workers and Wrangler earn their place.
- Deploying to Cloudflare From GitHub Actions With WranglerDeploy a static site to Cloudflare Workers Static Assets or Pages from GitHub Actions with Wrangler: scoped tokens, PR previews, caching and rollback.
- Migrating from Cloudflare Pages to Workers Static AssetsMove a static site from Cloudflare Pages to Workers static assets: wrangler config, _headers and _redirects, previews and a zero-downtime domain cutover.
Content Workflows for Documentation Teams
- Checking Links in Pull RequestsCatch broken internal links and anchors before merge by checking the built site in CI with lychee, and handle external links without flaky failures.
- Content Linting with markdownlintLint Markdown in a docs repository with markdownlint-cli2: tune rules, add custom rules for site conventions, autofix on commit and annotate pull requests.
- Editorial Checks with Vale in CIRun Vale on every pull request to enforce your style guide, terminology and readability in Markdown docs, with inline review comments and a gradual rollout.
- Managing Images in Docs-as-Code ReposKeep screenshots and diagrams in a docs repository without bloating Git: size limits, Git LFS, co-location, alt text checks and automated screenshots.
- Release Notes and Changelogs from GitGenerate a changelog section for a static docs site from Git and conventional commits or changesets, with per-release pages, feeds and writer-edited release notes.
- Scheduled Content Publishing With GitHub ActionsPublish reviewed pull requests at a set time with GitHub Actions, for embargoed launches and releases, with time zones, approvals and failed-build guards.
- Scheduling Content Publication With Cron-Triggered BuildsPublish future-dated pages on a static site with no runtime: filter at build time, rebuild on a cron, skip no-op deploys, and keep embargoed content out of the artifact.
- Wiring a Headless CMS to a Static BuildConnect a Git-backed or API-backed CMS to a static generator: content model, auth, webhook rebuilds, media handling, and keeping the repository the source of truth.
GitHub Actions for Automated SSG Builds
- Building Astro Sites with GitHub ActionsA production GitHub Actions workflow for Astro: pinned Node, dependency and image caches, astro check, build artifacts and a deploy job that only runs on main.
- Caching node_modules in GitHub ActionsCut SSG CI time by caching npm in GitHub Actions — actions/setup-node built-in cache vs actions/cache, lockfile-hash keys, and the install minutes you actually save.
- Concurrency Groups to Cancel Stale BuildsUse GitHub Actions concurrency groups to cancel superseded static site builds on pull requests, serialize production deploys, and cut wasted CI minutes.
- Deploying to GitHub Pages with ActionsDeploy any static site generator to GitHub Pages with the official Actions workflow: artifacts, base paths, custom domains and what Pages cannot do.
- Deploying to Multiple Environments From One WorkflowBuild the artifact once and promote it to preview, staging and production with environment-scoped secrets, approvals and per-environment config injected at deploy time.
- GitHub Actions for Hugo DeploymentsDeploy Hugo with GitHub Actions using the extended edition for SCSS and WebP — a two-job build-and-publish pipeline, resource caching, and the Hugo-specific gotchas.
- Matrix Builds for Multi-Site MonoreposBuild and deploy only the sites a change affects in a monorepo, using a dynamic GitHub Actions matrix generated from changed paths, with per-site caches.
- Pinning Actions by Commit SHAPin third-party GitHub Actions in static site workflows to full commit SHAs, keep them updated with Renovate or Dependabot, and restrict which actions may run.
- Publishing Any Generator to GitHub Pages With ActionsOne reusable GitHub Actions workflow that publishes Hugo, Astro, Eleventy, Jekyll or VitePress sites to GitHub Pages, with base paths, caching and a 404 page.
- Reusable Workflows for SSG BuildsShare one build, test and deploy pipeline across many static sites with GitHub Actions reusable workflows and composite actions, versioned and called by tag.
Incremental Builds and Build Caching for SSGs
- Build Caching on Netlify and VercelMake Netlify and Vercel reuse dependency, framework and image caches between static site builds, verify cache hits in logs, and measure the savings.
- Caching Hugo Builds in GitHub ActionsCache Hugo resources/_gen and the module cache in GitHub Actions with content-hashed keys. Includes the workflow, cache key design, and measured CI minutes saved.
- Deploying Only Changed FilesUpload only the files that changed in a static site deploy using content hashes, rsync or S3 sync with checksums, while keeping the deploy atomic and purges scoped.
- Enabling Incremental Builds in EleventyUse Eleventy --incremental and --ignore-initial to rebuild only changed templates. Covers the programmatic API, what gets rebuilt, and measured rebuild times.
- Incremental Builds in Astro with the Content LayerHow the Astro content layer caches entries between builds, how to write loaders with digests, and how to persist the data store in CI so builds stay fast.
- Measuring Build-Time Regressions in CITrack build duration per commit, separate cache misses from real slowdowns, and set a budget that fails a pull request before a 4-second build becomes a 4-minute one.
- Remote Caching with Turborepo for SSG MonoreposUse Turborepo task hashing and a remote cache to skip rebuilding unchanged sites and packages in a static site monorepo, locally and in CI.
- Sharing Build Cache Across CI RunnersShare a build cache across parallel CI runners with Turborepo remote cache, an S3-backed store, or scoped actions/cache. Architecture, signing, and measured savings.
Monitoring Static Sites in Production
- Alerting on Cache Hit Ratio DropsMeasure CDN cache hit ratio for a static site by path prefix, alert on sharp drops against last week, and trace the usual causes: Vary, cookies, query strings.
- Building a Core Web Vitals Dashboard from RUM DataCollect LCP, INP and CLS from real readers with web-vitals, store them cheaply at the edge, and chart p75 by template, device and deploy with attribution.
- Crawling for Broken Links on a ScheduleRun a weekly crawl of a live static site with lychee, separate internal from external breakage, track link rot as issues, and keep false positives low.
- Logging 404s at the EdgeCollect every 404 a static site serves at the CDN edge, rank paths by reader impact, separate bots from people, and turn the top of the list into redirects.
- Monitoring TLS Certificate ExpiryCatch expiring or misconfigured TLS certificates on static site domains before readers do: inventory hostnames, check expiry and chains, and alert on renewal failures.
- Real-User Error Tracking on Static SitesCapture JavaScript errors, failed resources and CSP violations from real readers of a static site with a tiny collector, filter noise from extensions, and alert on new errors.
- Synthetic Monitoring With Scheduled Playwright ChecksRun Playwright checks against a live static site on a schedule: search, forms and navigation, with screenshots on failure, alert routing and run costs.
- Tracking Deploy Markers in AnalyticsRecord every static site deploy as a marker in RUM, analytics and error dashboards, tag data with the build version, and link metric changes to commits.
- Uptime and Synthetic Checks for Static SitesContent-aware synthetic checks for a static site: one URL per template, markers not just status codes, TLS expiry, two regions, and paging only on real outages.
Netlify vs Vercel Deployment Strategies
- Configuring Redirects on Vercel for Static SitesConfigure redirects for a static site on Vercel in vercel.json: patterns, status codes, trailing slashes, host redirects and limits, tested in CI.
- Configuring Vercel for Hugo and EleventyDeploy Hugo and Eleventy sites on Vercel with pinned versions, the right output directory, clean URLs, trailing slashes, headers and redirects in vercel.json.
- Deploying Astro to Vercel as a Fully Static SiteDeploy an Astro site to Vercel as pure static output with no functions: skipping the adapter, headers and redirects in vercel.json, and images.
- Netlify Build Hooks for Content UpdatesTrigger Netlify rebuilds from a headless CMS without a Git push. Create, secure, time, and debug Netlify build hooks for automated static site content updates.
- Netlify Deploy Previews for Every Pull RequestTurn on Netlify Deploy Previews so every PR gets its own built URL — config, the unique deploy-preview link, scoped env vars, and the automatic PR comment.
- Netlify Edge Functions for Static SitesAdd small pieces of request-time logic to a static site on Netlify with Edge Functions: geolocation, rewrites, header changes and HTML transforms, scoped and cached.
- Netlify Redirects and Rewrites for Static SitesWrite Netlify redirects and rewrites in _redirects or netlify.toml: status codes, splats, placeholders, shadowing, proxying and country or language rules.
- Vercel Build Output API for Custom SSGsDeploy any static site generator to Vercel with the Build Output API: static files, headers, redirects, cache rules and an optional edge function.
Preview Environments for Pull Requests
- Automating Preview Deploy Pipelines with GitHub ActionsBuild an ephemeral per-PR preview pipeline in GitHub Actions — build the SSG, deploy to a unique URL, comment the link, and tear it down when the PR closes.
- Cleaning Up Stale Preview DeploymentsPreview deploys accumulate: indexed by search engines, holding old secrets, and costing storage. Tear them down on merge, sweep the stragglers, and keep them out of the index.
- Commenting on Preview DeploysPost one self-updating pull request comment per preview with the URL, changed pages, checks and screenshots, and collect reviewer feedback on the preview.
- Password-Protecting Preview DeploymentsKeep pull request previews private with platform protection, Cloudflare Access or a small edge function, and keep them out of search indexes with noindex.
- Preview Deploys for MonoreposBuild and preview only the static sites a pull request affects in a monorepo, with per-site preview URLs, shared package awareness and one combined comment.
- Previewing Headless CMS DraftsShow editors unpublished headless CMS content on a static site: a draft build, on-demand preview routes, or a small preview server, and how to secure each.
- Pull Request Previews for GitHub Pages SitesGive a GitHub Pages site a preview per pull request: deploy builds to a preview host or a subfolder, comment the URL, handle base paths and clean up on close.
- Visual Regression Testing on Preview DeploysScreenshot key templates on every preview deploy with Playwright, compare them with main, and review diffs in the pull request without drowning in noise.
Rollbacks and Deploy Safety for Static Sites
- Blue-Green Deploys for Static SitesRun blue-green deploys for a self-hosted static site: two complete environments, verification before switching, an instant switch at the CDN and one-step rollback.
- Canary Releases for Static SitesSend a small share of traffic to a new static build before everyone gets it, using Worker gradual deployments or an edge split, and watch errors and vitals.
- Feature Flags on Static SitesShip code dark and turn features on without a rebuild: build-time flags, edge-evaluated flags and client flags on static sites, and how to avoid flicker.
- Post-Deploy Verification ChecklistsTurn a static site post-deploy checklist into an automated suite: version, key pages, redirects, headers, assets, search and forms, with rollback on failure.
- Rolling Back Netlify Deploys From the CLI and APIRoll back a Netlify site to an earlier deploy from the API, the CLI or a GitHub Actions button, lock auto-publishing during incidents, and verify the restore.
- Rolling Back S3 and CloudFront Deploys With Versioned PrefixesMake S3 and CloudFront deploys atomic by uploading each build to its own prefix and switching CloudFront's origin path, so a rollback takes one config change.
- Rolling Back a Bad Static Deploy in Under a MinuteA per-host runbook for reverting a broken static deploy: find the last good deployment ID, promote it, verify, and communicate — with no rebuild in the critical path.
- Running Smoke Tests Against a Preview URLTen seconds of checks against the deployed preview — status codes, template markers, referenced assets, sitemap and redirects — that catch the deploys a build gate cannot.
Security Headers and Hardening for Static Sites
- Auditing npm Dependencies in SSG PipelinesReduce supply-chain risk in a static site build: lockfiles, npm ci, install-script controls, audit gates, provenance checks and a review step for new packages.
- Enabling HSTS and Preload SafelyRoll out Strict-Transport-Security in stages, audit every subdomain before includeSubDomains, and decide whether the HSTS preload list is worth its permanence.
- Hash-Based CSP for Inline Scripts in AstroCompute SHA-256 hashes for every inline script in an Astro build, write them into the CSP header automatically, and keep unsafe-inline out of the policy.
- Permissions-Policy and Cross-Origin HeadersSet Permissions-Policy, COOP, CORP and COEP on a static site: disable unused browser features, isolate the browsing context, and avoid breaking embeds and CDNs.
- Securing Deploy Credentials with GitHub OIDCReplace long-lived deploy tokens with short-lived OIDC credentials in GitHub Actions for AWS, Cloudflare and Netlify, scoped to one branch and one deploy job.
- Security Headers for Static Sites Served by CaddyConfigure HSTS, CSP, framing, referrer and permissions headers in a Caddyfile for a static site, with per-path rules, a snippet and header tests.
- Security Headers on Vercel for Static SitesAdd HSTS, CSP, framing, referrer and permissions headers to a static site on Vercel with vercel.json, relax them only on previews, and test each deploy.
- Subresource Integrity for Third-Party AssetsProtect a static site from tampered CDN scripts with Subresource Integrity: when it applies, generating hashes at build time, and when self-hosting is better.
- Writing a Content Security Policy for a Static SiteBuild a Content-Security-Policy for a static site from an inventory of its sources, roll it out in report-only mode, and switch to enforcing without breakage.
- security.txt and Disclosure for Static SitesPublish a valid security.txt from a static site build, set up a disclosure policy and intake that works, keep the file from expiring, and handle incoming reports.
Self-Hosting Static Sites on S3, Nginx and Caddy
- Brotli and Gzip Precompression Served by NginxServe build-time Brotli and gzip files from Nginx with brotli_static and gzip_static, verify negotiation and Vary headers, and measure bytes and CPU saved.
- Clean URLs and Trailing Slashes on S3Make directory-style URLs work on S3 behind CloudFront: a viewer-request function for index files, one canonical trailing-slash form, and tests that prove it.
- CloudFront Functions for RedirectsServe hundreds of redirects for a static site on S3 from a CloudFront Function and KeyValueStore, generated from the build and tested on every deploy.
- Deploying a Static Site to S3 and CloudFrontDeploy a static site to a private S3 bucket behind CloudFront with Origin Access Control, split cache headers, ordered uploads and a targeted invalidation.
- Hosting on Azure Static Web AppsDeploy a static site to Azure Static Web Apps: routes and headers in one config file, preview environments, custom domains, sign-in and measured speed.
- Serving a Static Site From a Docker Container With NginxPackage a static site in a small Nginx container: multi-stage build, non-root user, read-only filesystem, health checks and running behind a proxy.
- Serving a Static Site With Caddy and Automatic HTTPSRun several static sites on one Caddy server with automatic certificates: DNS and ports, staging CA tests, rate limits, storage and wildcards.
- Serving a Static Site with CaddyHost a static site on Caddy with automatic HTTPS, clean URLs, precompressed files, cache tiers, security headers and per-pull-request preview subdomains.
- Serving a Static Site with NginxA production nginx config for a static site: clean URLs, two cache tiers, brotli, security headers that survive nested blocks, redirects, TLS and the 404 page.
- Static Hosting on Google Cloud StorageHost a static site on Google Cloud Storage behind a load balancer and Cloud CDN: bucket setup, clean URLs, 404s, cache headers, HTTPS and keyless deploys.
- Zero-Downtime Deploys with Symlink SwapsDeploy a static site to a VM atomically: one directory per release, an atomic symlink swap, one-second rollback, retention and a GitHub Actions workflow.
Serverless Functions for Static Sites
- Adding a Contact Form with Cloudflare WorkersBuild a contact form for a static site on Cloudflare: a Pages Function that validates, checks Turnstile, rate-limits, stores in D1 and emails the team.
- Handling Form Submissions on a Static SiteFour ways to accept form submissions on a static site — host forms, form services, your own function, mailto — compared on spam, privacy, cost and page weight.
- Newsletter Signup with an Edge FunctionReplace a newsletter embed on a static site with a native form and a small edge function: double opt-in, spam protection, consent records and results.
- Protecting a Static Site Behind AuthenticationGate a static site or one section of it behind single sign-on with Cloudflare Access or an edge JWT check, without leaking pages through caches or search.
- Proxying Third-Party APIs from an Edge FunctionServe live third-party data on a static site through an edge proxy: hidden API keys, strict allow-lists, response shaping, caching and graceful fallback.
- Rate Limiting Edge FunctionsProtect the dynamic endpoints of a static site, such as forms and APIs, with edge rate limits: platform rules, Workers bindings, keys and measured effect.
Testing Static Sites in CI
- Accessibility Testing with axe and pa11y in CIRun axe-core through Playwright and pa11y-ci on sampled pages of a static site in both themes, fail pull requests on new violations and track the rest.
- End-to-End Tests for Static Sites with PlaywrightProtect the few interactive flows on a static site with Playwright: search, theme toggle, mobile menu, copy buttons and forms, run against every preview deploy.
- Snapshot Testing Build OutputSnapshot a static site’s built HTML in CI: normalize volatile parts, summarize every page, diff key pages fully and review changes in the pull request.
- Testing Redirects and Headers Before DeployTable-driven tests for redirects, cache and security headers on a static site, generated from the redirect map and run against every preview before production.
- Testing Search and Navigation Flows With PlaywrightTest the interactive parts of a static docs site with Playwright: search results and keyboard use, mobile menus, sidebar state, versions and 404s.
- Testing Structured Data and Meta TagsCheck titles, descriptions, canonicals, Open Graph tags and JSON-LD on every built page in CI, including cross-page duplicates and FAQ text that must match.
- Validating HTML Output in CIValidate every built page of a static site with html-validate in CI: choose rules, ignore third-party markup, baseline existing errors and fail on new ones.
Other kinds of guide
- FixesStarts from a symptom and ends at the cause and the fix.
- ComparisonsWeighs two or more options against measured criteria.
- ConceptsExplains how something works and when it matters.