Skip to main content

Docusaurus Build & CI/CD Optimization Plan

Created: 2026-03-22 Status: VERIFIED Approved: Yes Iterations: 0 Worktree: No Type: Feature

Summary

Goal: Optimize Docusaurus build/dev performance using experimental Rspack+SWC bundling, standardize on Yarn, add Cloudflare Pages deployment config, and create a GitHub Actions CI workflow for PR validation.

Architecture: Enable the full experimental_faster feature set in Docusaurus 3.9.2 (Rspack bundler, SWC transpilation/minification, Lightning CSS, persistent cache, SSG worker threads, MDX cross-compiler cache). Add Cloudflare Pages _headers for aggressive static asset caching. Create a GitHub Actions workflow for typecheck + build validation on PRs.

Tech Stack: Docusaurus 3.9.2, @docusaurus/faster, Rspack, SWC, Yarn 1.22.22, Cloudflare Pages, GitHub Actions

Scope

In Scope

  • Enable all experimental_faster flags in docusaurus.config.ts
  • Install @docusaurus/faster package
  • Remove stale package-lock.json (standardize on Yarn)
  • Add Cloudflare Pages _headers file for CDN caching
  • Add Cloudflare Pages _redirects file
  • Create GitHub Actions CI workflow (typecheck + build)
  • Add wrangler.toml for local Cloudflare Pages dev preview

Out of Scope

  • Image optimization/compression (separate concern, can be addressed later)
  • Mermaid lazy-loading or removal (functional change, not build optimization)
  • Blog author warning fix (content issue, not build perf)
  • Cloudflare Pages dashboard configuration (already set up)
  • Production deployment pipeline changes (already working)

Context for Implementer

Write for an implementer who has never seen the codebase.

  • Patterns to follow: docusaurus.config.ts:5-12 — the future block already has v4: true. The experimental_faster block goes alongside it inside future.
  • Conventions: TypeScript config files, Yarn for package management, static assets go in static/
  • Key files:
    • docusaurus.config.ts — main Docusaurus configuration (build, plugins, themes)
    • package.json — dependencies, scripts, packageManager field set to yarn@1.22.22
    • static/ — files copied as-is to build output (where _headers, _redirects go)
    • .gitignore — currently ignores /node_modules, /build, .docusaurus, .cache-loader
  • Gotchas:
    • Both yarn.lock and package-lock.json currently exist — only yarn.lock should remain
    • The future: { v4: true } shorthand enables v4 breaking changes but NOT experimental_faster — those are separate flags requiring the @docusaurus/faster package
    • The @docusaurus/theme-mermaid theme triggers a vscode-languageserver-types webpack warning — this is cosmetic and unrelated to our changes
    • Cloudflare Pages serves files from the build/ directory and reads _headers/_redirects from the build output root (which means they go in static/ pre-build)
    • Rspack persistent cache stores in ./node_modules/.cache — Cloudflare Pages CI caches node_modules between builds automatically
  • Domain context: This is a documentation site for Vidra (a Go video platform). Build speed matters for developer iteration and CI pipeline cost. The site is small (12 docs, 1 blog post) but the mermaid theme and webpack bundling make builds slower than necessary.

Assumptions

  • @docusaurus/faster is compatible with Docusaurus 3.9.2 — supported by [Docusaurus 3.6+ release notes, context7 docs] — Tasks 1, 2 depend on this
  • Cloudflare Pages CI may cache node_modules between builds (including node_modules/.cache where Rspack persistent cache lives) — unverified assumption, Cloudflare Pages cache behavior is environment-dependent. If cache doesn't persist, warm builds in CI will equal cold builds. Local dev still benefits regardless. — Task 2 depends on this for CI persistent cache benefit
  • The GitHub repo is hosted at github.com/yosefgamble/vidra-docs — supported by [docusaurus.config.ts:18] — Task 4 depends on this
  • Cloudflare Pages project is already connected to this GitHub repo for deployments — supported by [user confirmation: "already deployed"] — Task 3 depends on this

Risks and Mitigations

RiskLikelihoodImpactMitigation
experimental_faster Rspack bundler has edge cases with mermaid themeMediumBuild failsEach experimental_faster flag is independently toggleable — disable individual flags if one causes issues
Persistent cache corruption causes stale buildsLowWrong output servedyarn clear script already clears all caches; add cache-bust step to CI workflow
Removing package-lock.json causes CI confusionLowCI install failsVerify Cloudflare Pages CI is configured for Yarn, not npm

Goal Verification

Truths

  1. yarn build completes successfully with all experimental_faster flags enabled
  2. Cold build time is measurably faster than the 21s baseline
  3. Warm (cached) build time is significantly faster than cold build
  4. yarn typecheck passes
  5. GitHub Actions workflow file exists and is syntactically valid
  6. _headers file is present in build output with correct caching rules
  7. Only yarn.lock exists (no package-lock.json)

Artifacts

  1. docusaurus.config.ts — contains experimental_faster configuration block
  2. package.json — includes @docusaurus/faster dependency, no package-lock.json
  3. static/_headers — Cloudflare Pages caching and security headers
  4. static/_redirects — Cloudflare Pages redirect rules
  5. .github/workflows/ci.yml — GitHub Actions PR validation workflow
  6. wrangler.toml — Cloudflare Pages local dev configuration

Progress Tracking

  • Task 1: Clean up package manager and install @docusaurus/faster
  • Task 2: Enable experimental_faster in docusaurus.config.ts
  • Task 3: Add Cloudflare Pages configuration files
  • Task 4: Create GitHub Actions CI workflow

Total Tasks: 4 | Completed: 4 | Remaining: 0

Implementation Tasks

Task 1: Clean up package manager and install @docusaurus/faster

Objective: Remove the stale package-lock.json, ensure Yarn is the sole package manager, and install the @docusaurus/faster package required for build optimizations.

Dependencies: None

Files:

  • Delete: package-lock.json
  • Modify: package.json (new dependency: @docusaurus/faster)
  • Modify: .gitignore (add package-lock.json to prevent accidental recreation)

Key Decisions / Notes:

  • @docusaurus/faster is a peer package that provides SWC and Rspack integrations for Docusaurus 3.6+
  • The packageManager field in package.json already specifies yarn@1.22.22 — keep it
  • Run yarn add @docusaurus/faster to install and update yarn.lock
  • Add package-lock.json as a new line in .gitignore to prevent accidental recreation by npm

Definition of Done:

  • package-lock.json is deleted
  • package-lock.json is in .gitignore
  • @docusaurus/faster is in package.json dependencies
  • yarn install succeeds without errors
  • No dual lockfile situation

Verify:

  • ls package-lock.json should fail (file doesn't exist)
  • yarn install --frozen-lockfile should succeed
  • grep "docusaurus/faster" package.json should match

Task 2: Enable experimental_faster in docusaurus.config.ts

Objective: Configure all experimental_faster flags to replace webpack with Rspack and Babel with SWC, enabling dramatically faster builds.

Dependencies: Task 1 (needs @docusaurus/faster installed)

Files:

  • Modify: docusaurus.config.ts (add experimental_faster block inside future)

Key Decisions / Notes:

  • The existing future block at docusaurus.config.ts:10-12 currently has v4: true — this shorthand expands to individual v4 flags. We need to expand it to an object to add experimental_faster alongside.
  • All flags to enable: swcJsLoader, swcJsMinimizer, swcHtmlMinimizer, lightningCssMinimizer, rspackBundler, rspackPersistentCache, mdxCrossCompilerCache, ssgWorkerThreads
  • Pattern from context7 docs shows the exact structure

Definition of Done:

  • docusaurus.config.ts has all 8 experimental_faster flags set to true
  • yarn build completes successfully
  • Build output is functionally identical (same pages generated)
  • Cold build time measured and compared to 21s baseline
  • Mermaid diagram assets are present in build output (confirms theme compatibility with Rspack)

Verify:

  • yarn clear && time yarn build — should succeed and be faster than 21s
  • ls build/index.html build/docs/getting-started/overview/index.html — key pages exist
  • grep -rl 'mermaid' build/assets/js/ | head -3 — mermaid JS assets present in build

Task 3: Add Cloudflare Pages configuration files

Objective: Create _headers and _redirects files for Cloudflare Pages CDN optimization, plus a wrangler.toml for local dev preview.

Dependencies: None (can run in parallel with Task 2)

Files:

  • Create: static/_headers (Cloudflare Pages caching/security headers)
  • Create: static/_redirects (redirect rules)
  • Create: wrangler.toml (Cloudflare Pages local dev config)

Key Decisions / Notes:

  • _headers and _redirects go in static/ so Docusaurus copies them to build/ root where Cloudflare Pages reads them
  • Fingerprinted assets (/assets/*) get Cache-Control: public, max-age=31536000, immutable (1 year, safe because filenames contain content hashes)
  • Non-fingerprinted paths get shorter cache (max-age=3600) with revalidation
  • Security headers: X-Content-Type-Options: nosniff, X-Frame-Options: DENY, Referrer-Policy: strict-origin-when-cross-origin
  • wrangler.toml points pages_build_output_dir to ./build for wrangler pages dev local preview
  • Prevent *.pages.dev URLs from being indexed by search engines

Definition of Done:

  • static/_headers exists with fingerprinted asset caching and security headers
  • static/_redirects exists (even if minimal)
  • wrangler.toml exists with pages_build_output_dir = "./build"
  • After yarn build, _headers appears in build/ root

Verify:

  • yarn build && cat build/_headers — should show headers content
  • cat build/_redirects — should show redirect rules

Task 4: Create GitHub Actions CI workflow

Objective: Add a GitHub Actions workflow that runs typecheck and build validation on every PR, catching errors before Cloudflare Pages deploys.

Dependencies: Task 1 (needs clean Yarn setup), Task 2 (build should use new config)

Files:

  • Create: .github/workflows/ci.yml

Key Decisions / Notes:

  • Trigger on pull_request to main and push to main
  • Use actions/setup-node@v4 with cache: 'yarn' for dependency caching
  • Node 22 (matches project's engines.node >= 20 and current local version)
  • Steps: checkout → setup-node → yarn install --frozen-lockfileyarn typecheckyarn build
  • The build step validates that all links resolve (onBrokenLinks: 'throw')
  • Keep it simple — one job, sequential steps. Separate typecheck and build for clear failure messages.
  • Verify tsconfig.json has noEmit configured (via @docusaurus/tsconfig extends). If not, update the typecheck script to tsc --noEmit to prevent emitting compiled files in CI.

Definition of Done:

  • .github/workflows/ci.yml exists with correct syntax
  • Workflow triggers on PR to main and push to main
  • Workflow runs typecheck and build steps
  • Yarn dependency caching is configured
  • actionlint or manual YAML validation passes (if available)

Verify:

  • cat .github/workflows/ci.yml — valid YAML with expected structure
  • node -e "require('js-yaml').load(require('fs').readFileSync('.github/workflows/ci.yml'))" or manual review

Open Questions

None — all decisions resolved.

Deferred Ideas

  • Image optimization: Compress wizard PNGs (230-280KB each) to WebP or use docusaurus-plugin-ideal-image for responsive images
  • Mermaid lazy loading: The mermaid theme adds ~500KB to JS bundles; could explore code-splitting or conditional loading
  • Blog author cleanup: Fix the inline author warning in 2026-03-22-welcome.md by creating blog/authors.yml
  • Broken link monitoring: Add a scheduled CI job to check for broken external links