Best Static Site Generator Stack for a 178-Page Obsidian Wiki

Executive Summary

For converting a 178-page Obsidian-style Markdown wiki with [[wiki links]], YAML frontmatter, and subdirectory organisation into a read-only HTML knowledge base for a single non-technical user, the recommended stack is:

Quartz v4 (SSG) + FlexSearch (built-in search) + Cloudflare Pages (hosting) + Cloudflare Access with email OTP (access control)

This combination provides the lowest setup effort, zero ongoing maintenance cost, native Obsidian compatibility without plugins, and auto-deploy on git push — all on free tiers. Quartz is the only SSG evaluated that handles [[wiki links]] out of the box with zero configuration, which eliminates the single largest source of integration risk.

A strong runner-up stack — Starlight (Astro docs theme) + Pagefind (search) + Cloudflare Pages + Cloudflare Access — offers better long-term maintainability and search quality, but requires the starlight-obsidian plugin and more initial configuration.


Static Site Generator Comparison

Summary Matrix

CriterionQuartz v4MkDocs MaterialDocusaurusAstro (bare)Starlight (Astro)EleventyHugoVitePress
Wiki links nativeYesNo (plugin)No (plugin)No (plugin)No (plugin)No (plugin)No (custom Go)No (plugin)
Frontmatter parsingYesYesYes (MDX)YesYes + schemaYesYesYes
Build ~200 pages~5–15s~3s~15–30s~5–15s~5–12s~0.5s~0.1–0.3s~3–5s
Theme quality (wiki)BestExcellentGoodDIYExcellentDIYTheme-dependentGood
Plugin ecosystem27 built-inLarge (Python)Large (React)Large (remark)42 focused100+ npm189 themesModerate
Maintenance riskSingle maintainerMaintenance modeMeta-backedVenture-backedAstro orgSingle maintainerVery activeVue.js org
Setup for this use case~15–30 min~45–60 min~2–4 hrs~2–3 hrs~1–2 hrs~2–3 hrs~3–4 hrs~1–2 hrs
GitHub stars11.8K26.5K64.5K58.4K8.3K19.5K87.5K17.5K
Latest releasev5.0.0 tag (active dev on v4 branch, Mar 2026)9.7.6 (Mar 2026)ActiveActive (daily)0.38.3 (Apr 2026)3.1.5 (Mar 2026)0.160.1 (Apr 2026)2.0.0-alpha.17

Detailed Evaluations

Quartz v4

Quartz is the only SSG purpose-built for Obsidian vaults (Quartz documentation). Wiki link resolution is handled natively by the CrawlLinks plugin with zero configuration. It supports all three Obsidian link resolution modes — shortest path, relative, and absolute — controlled via markdownLinkResolution in quartz.config.ts (Quartz wikilinks docs). Heading anchors ([[Page#section|Section]]), block references ([[Page#^block-id|^block-id]]), aliases ([[Page|Display Text]]), and transclusion embeds (![[Page]]) all work natively.

The default theme ships a graph view, backlinks panel, popover previews, table of contents, explorer sidebar, and full-text search — all the elements expected in a knowledge base, with no additional configuration (Quartz configuration docs). Search is powered by FlexSearch, which returns results in under 10ms for sites up to half a million words and includes a Cmd+K / Ctrl+K modal with highlighted excerpts (Quartz search docs).

The main risks are maintainability and edge case handling. Quartz is maintained by a single developer (jackyzha0) with 11.8K GitHub stars — a bus factor of 1. There is a known case-sensitivity bug where [[Note Two]] vs [[Note two]] silently produces a 404. Broken wiki links generate no build-time warning — they silently become dead links in the output. Performance can degrade on default settings due to the graph view component inflating JavaScript bundle size from 60KB to 618KB; disabling the graph view and Mermaid restores mobile PageSpeed from 34 to 91.

MkDocs Material

MkDocs Material has the most polished documentation theme of any SSG (26.5K stars), with excellent search, dark mode, versioning, and navigation. Build time for 200 pages is roughly 3 seconds — among the fastest. However, wiki link support requires the third-party mkdocs-obsidian-links (ezlinks) plugin, which adds warn_ambiguities: true for disambiguation and a CSS class for broken links.

The critical concern is ecosystem health. MkDocs Material entered maintenance mode in November 2025, with the maintainer building a successor product (Zensical). MkDocs core has had no meaningful development in 18+ months. Starting a new project on a platform in maintenance mode introduces risk that bugs and compatibility issues will go unresolved. The Python ecosystem requirement (pip, virtualenv) adds friction compared to Node.js-based alternatives.

Docusaurus v3

Maintained by Meta with 64.5K GitHub stars, Docusaurus has the strongest organisational backing of any option. It ships the best built-in broken link checker (configurable to halt builds on broken links). However, it is the worst fit for Obsidian content: there is no mature wiki link plugin (the best available, docusaurus-plugin-obsidian-vault, has 1 star and 2 commits). MDX strictness means many Obsidian Markdown patterns require manual fixing. Build times of 15–30 seconds reflect the React/MDX overhead. Setup time is estimated at 2–4 hours, making it the most labour-intensive option for this use case.

Starlight (Astro Docs Theme)

Starlight is an Astro-native docs framework with 8.3K stars and backing from the Astro organisation (used by Cloudflare, Google, and Microsoft for their docs). It ships Pagefind as its default search engine with zero configuration, provides sidebar navigation, dark mode, and mobile responsiveness out of the box.

The starlight-obsidian plugin (134 stars, last release March 2026) handles wiki link resolution, heading anchors, and embeds. Additional community plugins include starlight-links-validator for build-time broken link detection and starlight-site-graph for an Obsidian-style node graph. TypeScript frontmatter schema validation means invalid frontmatter produces clear build errors rather than silent failures.

The trade-off is that the Obsidian plugin is a single-person project (134 stars vs Quartz’s native support), and setup requires ~1–2 hours versus Quartz’s 15–30 minutes. Build time for 200 pages is 5–12 seconds.

Eleventy (11ty)

Eleventy offers the best broken link handling of any SSG via @photogabble/eleventy-plugin-interlinker, which provides console warnings, JSON reports for CI, and configurable severity. It enforces alias uniqueness (build halts on duplicate aliases). Build time is fast (~0.5 seconds for 200 pages).

The major drawback is that Eleventy ships no default theme — building a knowledge base layout from scratch or adapting a starter template is a multi-hour effort. The project is maintained by a single developer (Zach Leatherman, 19.5K stars), creating the same bus-factor risk as Quartz. Wiki link support is good but not as complete as Quartz’s native Obsidian compatibility (no block references, no transclusion).

Hugo

Hugo is the fastest SSG by a wide margin — 200 pages build in 0.1–0.3 seconds thanks to its Go-based compiler (Hugo GitHub, 87.5K stars). It has the most active maintenance cadence with monthly releases. However, its lead maintainer explicitly closed the native wiki link feature request in May 2023, stating [[...]] syntax makes Markdown “unportable.” Wiki link support requires ~100 lines of custom Go template code that you write and maintain yourself. Hugo’s urlize function aggressively strips special characters (&, ?, !) from URL slugs, which can cause silent URL collisions between pages with similar names. Not recommended for this use case unless Hugo is already in use for other reasons.

VitePress

VitePress (17.5K stars) provides an excellent docs theme with Vue.js integration. Wiki links are handled via the @portaljs/remark-wiki-link package, which supports heading anchors and display text. MiniSearch is the built-in search engine with true Levenshtein fuzzy matching.

The concern is maturity: VitePress is still in v2.0.0-alpha, with potential breaking changes ahead. Its wiki link resolution relies on a permalinks array that must be regenerated when content changes — case-sensitive exact string matching with no built-in ambiguity detection.


Client-Side Search Comparison

Summary Matrix

CriterionPagefindLunr.jsFlexSearchMiniSearchFuse.jsStorkAlgolia DocSearch
Index size (200 pages)~100–150 KB chunked~500 KB–1 MB~300–600 KB~300–500 KB~200–500 KBVaries (.st binary)Hosted
On-demand loadingChunked (partial)Full loadFull loadFull loadFull loadWASM + partialAPI calls
RankingBM25-inspired, tunableBM25FContextual (custom)BM25+IDF-weighted BitapCustomProprietary
Typo tolerancePrefix/stemming onlyManual ~1 syntaxPhonetic/tokenizerLevenshtein (configurable)Bitap (≤32 chars)Prefix onlyFull automatic
Ships a UIFull modal + excerptsAPI onlyAPI onlyAPI onlyAPI onlyInput + overlayFull ⌘K modal
Stars / Last release5.1K / Apr 20269.2K / 201913.7K / May 20255.9K / 202520.1K / Apr 20262.8K / Jan 2023SaaS

Analysis

Pagefind is the strongest overall choice for static knowledge bases (pagefind.app). Its chunked index loading means the browser only downloads the slice relevant to each query — roughly 100–150 KB total for a 200-page site, with only a fraction loaded per search. It ships a complete drop-in UI with excerpts, sub-results by heading, and highlighting. It works with any SSG as a post-build step and is Starlight’s built-in default. Its main weakness is the absence of true Levenshtein fuzzy matching — it relies on stemming and prefix matching, so a search for “astor” will not find “astro.”

MiniSearch offers the best typo tolerance of the client-side options, with configurable Levenshtein distance matching (fuzzy: 0.2) and BM25+ ranking (MiniSearch GitHub). It ships no UI components, but VitePress bundles it with a polished modal interface. The full index for 200 pages loads in one shot (~300–500 KB raw, ~60–100 KB gzipped) — acceptable at this scale.

FlexSearch is what Quartz uses natively. It is extremely fast (sub-10ms for half a million words) and supports CJK tokenisation, but does not implement true Levenshtein fuzzy matching despite marketing claims — its “fuzzy” is tokenizer/phonetic-based (Quartz search docs).

Lunr.js is unmaintained (last release 2019) and should be avoided for new projects. It remains MkDocs Material’s default, but the Material maintainer has acknowledged its BM25 implementation is poorly suited to typeahead search.

Fuse.js (20.1K stars) excels at fuzzy matching short strings (titles, names) but performs a linear scan per query — unsuitable for full-text paragraph search across 200 pages.

Stork is abandoned (developer wound down the project; last release January 2023). Do not use for new work.

Algolia DocSearch is best-in-class on every dimension (typo tolerance, ranking, UI, ⌘K modal) but the free tier requires the site to be publicly accessible open-source documentation. A private business knowledge base does not qualify.

SSG-Search Integration Map

SSGBuilt-in SearchIntegration Effort
QuartzFlexSearch (built-in, zero config)None
StarlightPagefind (built-in, zero config)None
VitePressMiniSearch (built-in, zero config)None
MkDocs MaterialLunr.js (built-in, legacy)None (but Lunr is unmaintained)
HugoNonePost-build Pagefind step
EleventyNonePost-build Pagefind step
DocusaurusAlgolia (requires qualification)Medium

Most Dangerous Failure Modes

The most insidious wiki link issues are those that fail silently — no build error, no warning, just a broken link in production. Three patterns recur across SSGs:

Case sensitivity mismatch. Quartz resolves [[Note Two]] and [[Note two]] to different URLs. If the file is Note two.md, the capitalised variant produces a silent 404. Obsidian is case-insensitive; Quartz and most remark-based resolvers are not. This is an open bug in Quartz with no fix.

Ambiguous page names across subdirectories. When entities/Report.md and analysis/Report.md both exist, [[Report]] resolves non-deterministically (build-order dependent) in Quartz’s shortest mode, MkDocs roamlinks, Hugo, and Astro’s remark-wiki-link. Only MkDocs ezlinks with warn_ambiguities: true emits a warning.

Heading anchor divergence. The heading ## Conclusion & Future Work generates #conclusion--future-work (double hyphen) in remark-based parsers (Quartz, Astro) but #conclusion-future-work (single hyphen) in MkDocs and Hugo’s Goldmark. Wiki links with heading anchors copied between systems silently break.

Robustness Ranking

SSGWiki Link RobustnessBroken Link DetectionKey Risk
Quartz7/10 — best Obsidian compatibilityNone (silent 404s)Case sensitivity bug
Eleventy + interlinker8/10 — best broken link detectionConsole/JSON warningsNo block refs or transclusion
MkDocs + ezlinks7/10 — ambiguity warningsCSS class onlyMaintenance mode ecosystem
VitePress + remark-wiki-link6/10 — full feature setCSS class onlyCase-sensitive permalink matching
Starlight + starlight-obsidian6/10 — good plugin coverageValidator plugin availableSmall plugin (134 stars)
Hugo (custom)5/10 — maximum effortCustom template possibleURL slug character stripping

Mitigation Strategies

Regardless of SSG choice, three practices prevent the majority of wiki link failures:

  1. Use explicit subdirectory paths: [[entities/Page Name]] instead of [[Page Name]]. Eliminates ambiguity entirely.
  2. Enforce consistent casing: Run a linting script pre-build to catch case mismatches between link text and filenames.
  3. Add a CI broken link checker: None of the SSGs provide reliable comprehensive detection. Add linkchecker or a custom script as a CI step.

Auto-Deployment Pipelines

Summary Matrix

OptionFree Build LimitDeploy SpeedBandwidthSetup TimeRecommended
Cloudflare Pages (direct git)500 builds/mo30s–2 minUnlimited~5 minYes
Netlify (direct git)300 min/mo1–3 min100 GB/mo~5 minViable
Vercel (direct git)6,000 min/mo30s–2 min100 GB/mo~5 minToS concern
GH Actions → Cloudflare Pages2,000 GHA min + 500 builds1–3 minUnlimited~20 minIf build step complex
GH Actions → Netlify2,000 GHA min + 300 Netlify min1–3 min100 GB/mo~20 minUnnecessary overhead
GH Actions → Railway2,000 GHA min + $5/mo1–3 minUsage-based~30 minNot recommended

Recommendation: Cloudflare Pages Direct Git Integration

Cloudflare Pages is the clear winner for this use case (pages.cloudflare.com):

  • 500 builds/month on the free tier — each push counts as one build regardless of duration. Pushing once daily uses 30 of 500.
  • Unlimited bandwidth and static requests — no surprise suspensions, no metering (Cloudflare Pages pricing).
  • ~30 second to 2 minute deploy time across 300+ global edge locations.
  • Free SSL and custom domain support (up to 100 custom domains per project) (Cloudflare Pages limits).
  • 5-minute setup: Connect GitHub repo → select branch → set build command → deploy. No YAML configuration required.
  • 20,000 file limit on the free plan — a 200-page site is well within bounds.

Netlify is a strong second choice with an equally simple setup, but its free plan suspends the site for the rest of the month if limits are exceeded, and bandwidth is capped at 100 GB.

Vercel offers the most generous build minutes (6,000/month) but its Hobby plan is ToS-restricted to personal/non-commercial use, which matters for a business knowledge base.

Railway is not recommended — it has no permanent free tier ($5/month minimum after trial) and is designed for app backends, not static hosting (Railway pricing docs).

GitHub Actions pipelines (options 1–3) add setup overhead without meaningful benefit when the hosting provider’s built-in git integration handles the same workflow in fewer steps.


Access Control

Summary Matrix

OptionCostSetup ComplexitySession PersistenceSecurity LevelRecommended
Cloudflare Access (email OTP)Free (up to 50 users)Medium (~15 min)Cookie, configurable up to 1 monthStrong (identity-verified)Yes
Netlify password protection$19/mo (Pro plan)Low (~2 min)Browser sessionModerate (shared secret)Only if already on Pro
HTTP basic auth (any host)FreeLow (~5 min)Browser session (native dialog)LowNot for non-technical users
Vercel password protection$150/mo add-onLowSession-basedModerateCost prohibitive
Private URL (no auth)FreeNoneN/ANoneNot for business content

Recommendation: Cloudflare Access with Email OTP

Cloudflare Access is the only option that combines strong security, good user experience, and zero cost for this use case (Cloudflare Access docs):

  • Free for up to 50 authenticated users on Cloudflare’s Zero Trust free plan (Cloudflare Zero Trust pricing).
  • User experience: Mat visits the site → enters their email → receives a 6-digit PIN → enters PIN → gets access. The session cookie can be configured to last up to 1 month, so they won’t need to re-authenticate on every visit (Cloudflare One-Time PIN docs).
  • Setup: In Cloudflare One dashboard, add an Access application for the Pages domain → create a policy allowing Mat’s email address → enable One-Time PIN as an identity provider. Takes ~15 minutes.
  • Security: Identity-verified (email ownership confirmed via OTP), not a shared secret that could be forwarded or guessed. Appropriate for business-sensitive but not regulated content.
  • Native integration: Works seamlessly with Cloudflare Pages since both are in the Cloudflare ecosystem — no proxy configuration or DNS changes needed.

Netlify’s site-wide password protection is simpler (shared password, no email step) but requires the $19/month Pro plan — it is not available on the free tier. The free tier only offers HTTP basic auth via _headers files, which presents an ugly native browser dialog.

Vercel’s password protection costs $150/month for production URLs, which is not viable for a single-user knowledge base.

A private URL (security through obscurity) is not a real access control mechanism and should not be used for business-sensitive content.


Primary Recommendation: Quartz + Cloudflare Pages + Cloudflare Access

LayerChoiceRationale
SSGQuartz v4Only SSG with native [[wiki link]] support matching all three Obsidian resolution modes. Zero-config graph view, backlinks, search, popover previews. 15–30 minute setup.
SearchFlexSearch (built into Quartz)Sub-10ms results for sites up to 500K words. Cmd+K modal with highlighted excerpts. No setup required.
HostingCloudflare Pages (direct git)500 builds/month, unlimited bandwidth, free SSL, custom domains. 5-minute setup. Auto-deploy on push.
Access controlCloudflare Access (email OTP)Free for up to 50 users. Mat authenticates with their email once per configurable session period (up to 1 month). Native Cloudflare integration.
Total cost$0/monthAll components on free tiers.

Setup workflow:

  1. Fork Quartz → clone → copy Obsidian vault content into content/ directory
  2. Set markdownLinkResolution in quartz.config.ts to match your Obsidian “New link format” setting
  3. Disable graph view and Mermaid if page speed matters (Plugin.ObsidianFlavoredMarkdown({ mermaid: false }) + comment out Component.Graph())
  4. Push to GitHub → connect repo to Cloudflare Pages → site deploys
  5. In Cloudflare One dashboard, create an Access application → add Mat’s email to an Allow policy → enable One-Time PIN

Known trade-offs to accept:

  • Single-maintainer project (bus factor 1) — mitigated by the site being static HTML that continues working even if Quartz development stops
  • Case-sensitive link resolution — mitigate by enforcing consistent casing in the vault
  • No build-time broken link detection — add a CI step with linkchecker if this matters
  • FlexSearch lacks true Levenshtein fuzzy matching — stemming and prefix matching are adequate for a knowledge base where the user knows the domain vocabulary

Runner-Up: Starlight + Pagefind + Cloudflare Pages + Cloudflare Access

LayerChoiceRationale
SSGStarlight (Astro) + starlight-obsidian pluginVenture-backed Astro org, TypeScript frontmatter validation, starlight-links-validator for broken link detection. Slightly more future-proof than Quartz.
SearchPagefind (built into Starlight)Chunked loading (~100 KB), better ranking than FlexSearch, full drop-in UI. Zero config in Starlight.
HostingCloudflare PagesSame as above.
Access controlCloudflare AccessSame as above.
Total cost$0/month

Choose this stack if long-term maintainability and broken link detection outweigh the faster initial setup of Quartz. The starlight-obsidian plugin is a smaller project (134 stars) than Quartz itself, but Starlight’s ecosystem (used by Cloudflare, Google, Microsoft) provides stronger institutional backing.

What to Avoid

  • MkDocs Material: Maintenance mode since November 2025. Do not start new projects on a platform with an uncertain future.
  • Docusaurus: No viable wiki link plugin. Requires the most effort to adapt Obsidian content.
  • Hugo for this use case: Wiki link support requires writing and maintaining ~100 lines of custom Go templates. The maintainer has explicitly rejected native wiki link support.
  • Railway for hosting: Costs $5/month for what Cloudflare Pages does for free.
  • Vercel for hosting: ToS restricts Hobby tier to non-commercial use.
  • Stork for search: Abandoned project.
  • Lunr.js for search: Unmaintained since 2019.