Mat Wiki Access Implementation

Decision

Build a read-only static HTML wiki viewer using Quartz v4, hosted on Cloudflare Pages, protected by Cloudflare Access email OTP. Total ongoing cost: $0/month. One-time build effort: 2–3 developer-days.

Status: Approved and building today (12 Apr 2026, Session 12). Full spec at _specs/WIKI-VIEWER-BUILD.md.

Two interfaces: (1) Static browsable site on Cloudflare Pages for reading/searching, (2) Claude queryability via Cowork + CLAUDE.md for Mat to ask questions in natural language.

Repo: Separate private repo (pride-wiki). Content synced from pride-turnaround/_wiki/ via script. Auto-deploys on push.

Context

Mat needs read-only access to the Pride wiki (currently 188 pages in Obsidian-compatible Markdown). Requirements established in Sessions 10–11:

  • [[wiki links]] must resolve correctly (including spaces in page names, subdirectory paths)
  • Non-technical CEO user — must be simple to navigate on desktop and iPhone
  • Auto-deploy on git push (no manual build steps after initial setup)
  • Free or near-free
  • Minimal ongoing maintenance
  • Read-only by architecture (no risk of accidental edits)

Six options were evaluated in Session 10. Shae selected Option 6: static HTML site as the approach. Three Perplexity Deep Research reports (Session 12) confirmed the specific tool choices.

LayerToolRationale
Static site generatorQuartz v4Only SSG with native [[wiki link]] support. Zero conversion layer. 15–30 min base setup.
SearchFlexSearch (built into Quartz)Sub-10ms results, Cmd+K modal, highlighted excerpts. No setup.
HostingCloudflare Pages (direct git integration)500 builds/month free, unlimited bandwidth, auto-deploy on push, free SSL.
Access controlCloudflare Access (email OTP)Free ≤50 users. Mat enters email → 6-digit PIN → session up to 1 month.
DomainTBD (Cloudflare custom domain or *.pages.dev subdomain)

Runner-Up (If Quartz Proves Problematic)

Starlight (Astro) + starlight-obsidian plugin + Pagefind + same Cloudflare hosting/access. Better long-term maintainability, better search (Pagefind > FlexSearch), build-time broken link detection. Trade-off: more initial setup (~2 hrs vs 30 min), wiki link support via third-party plugin (134 stars) rather than native.

Known Risks and Mitigations

RiskSeverityMitigation
Case-sensitive wiki links — Obsidian is case-insensitive, Quartz is not. Mismatched casing → silent 404.HighApply PR #2327 locally (one-line change: force lowercase slugs). Enforce consistent casing in vault.
No build-time broken link detection — dead [[links]] render as clickable 404s.MediumAdd linkchecker as CI step in Cloudflare Pages build pipeline.
Solo maintainer — Quartz maintained by one person (jackyzha0). Bus factor of 1.MediumMIT licence allows forking. Static HTML output works indefinitely even if development stops. Pin to v4 branch.
Graph view crashes on iOS Safari (global view).MediumDisable global graph view. Keep local graph (current page + connections) or disable entirely.
CEO can’t troubleshoot build errors.LowPre-configure CI/CD. Shae pushes wiki updates; Mat only reads.

CEO Customisation Plan

Quartz defaults to a “digital garden” aesthetic. Five changes transform it into a professional business tool:

  1. Remove digital garden signals: Disable graph view on homepage. Rename “Explorer” → “Contents”, “Backlinks” → “Related Pages”, “Tags” → “Topics”.
  2. Professional typography: Inter font family. Brand colour palette using Pride colours (primary dark 0C0A2F). 18–19px body text desktop, 16–17px mobile.
  3. Horizontal top nav: Replace sidebar Explorer with top navigation bar: Entities | Concepts | Sources | Analysis | Decisions | Search. Custom header component in quartz.layout.ts.
  4. Card-grid landing page: Custom content/index.md with 5 category cards (icon, plain-language description, page count) + search bar + single “recently updated” item.
  5. Category landing pages: Each folder gets an index.md optimised for its content volume — Concepts grouped by sub-domain, Sources as filterable list, Entities as alphabetical grid, Decisions and Analysis showing all items.

UX Architecture (from Research)

Four Navigation Layers

  • Layer 1 (global): Search bar/icon in header + breadcrumbs on every page.
  • Layer 2 (home): Search + 5 category cards + featured update.
  • Layer 3 (category): Per-category landing pages (Concepts needs sub-domain grouping for 102 pages).
  • Layer 4 (content page): Left sidebar scoped to current category, current page highlighted.

Mobile

  • Off-canvas left drawer (not bottom tab bar). 44×44pt touch targets. ≥16px search input font.
  • PWA with offline precaching (P2 priority — implement after core site works).

Page-Level Elements

PriorityElement
P0Breadcrumbs, responsive layout, readable typography
P1Sticky TOC, related pages footer, page type labels, last updated timestamp
P2PWA, reading time, Cmd+K shortcut, print stylesheet, dark mode
P3Local graph view, previous/next navigation

Implementation Spec (for Claude Code)

Phase 1: Base Site (Day 1)

  1. Fork Quartz → clone → npm inpx quartz create (empty Quartz)
  2. Copy pride-turnaround/_wiki/ content into content/ directory
  3. Create content/index.md files for each subdirectory (entities, concepts, sources, analysis, decisions) with title frontmatter
  4. Configure quartz.config.ts:
    • pageTitle: “Pride Intelligence Wiki”
    • enableSPA: true
    • enablePopovers: true
    • locale: “en-AU”
    • baseUrl: TBD
    • ignorePatterns: [“.obsidian”, “_templates”, “private”, “WIKI-SCHEMA.md”]
    • defaultDateType: “modified”
    • markdownLinkResolution: “shortest” (matches Obsidian default)
  5. Apply case-sensitivity fix: force lowercase slugs in quartz/util/path.ts (PR #2327 patch)
  6. Build and verify locally: npx quartz build --serve
  7. Fix any broken links or build errors
  8. Git add, commit, push

Phase 2: Customisation (Day 1–2)

  1. Typography and colours in quartz.config.ts:
    • Header + body font: Inter
    • Code font: JetBrains Mono
    • Light mode palette: professional blues, Pride brand accent (#0C0A2F)
    • Dark mode palette: off-black (#121212) backgrounds, off-white text
  2. Layout changes in quartz.layout.ts:
    • Remove Component.Graph() from layout
    • Add custom horizontal nav component (Entities | Concepts | Sources | Analysis | Decisions)
    • Rename component labels (Explorer → Contents, Backlinks → Related Pages)
  3. Landing page — custom content/index.md:
    • Site title + one-line description
    • Search bar (uses Quartz’s built-in search component)
    • 5 category cards with icons, descriptions, page counts
    • “Recently updated” section (last 3–5 updated pages)
  4. Category landing pages — each content/{category}/index.md:
    • Concepts: grouped by sub-domain (operations, strategy, finance, governance, marketing, technology)
    • Sources: chronological list with one-line descriptions
    • Entities: alphabetical grid
    • Decisions + Analysis: all items visible with summaries
  5. Mobile responsive check — verify off-canvas drawer, touch targets, font sizing
  6. Git add, commit, push

Phase 3: Deploy + Access Control (Day 2–3)

  1. Create Cloudflare account (or use existing)
  2. Connect GitHub repo to Cloudflare Pages:
    • Build command: git fetch --unshallow && npx quartz build
    • Output directory: public
    • Node version environment variable: 22
  3. Verify auto-deploy works on push
  4. Configure custom domain (if desired) or use *.pages.dev
  5. Set up Cloudflare Access:
    • In Cloudflare One dashboard → Access → Applications → Add application
    • Application domain: the Pages URL
    • Policy: Allow → Include → Email = Mat’s email address + Shae’s email
    • Identity provider: One-Time PIN
    • Session duration: 1 month
  6. Test: Mat receives OTP email, enters PIN, accesses site
  7. Git add, commit, push (any final config)

Phase 4: CI/CD Hardening (Day 3, if time)

  1. Add linkchecker post-build step to validate all internal links
  2. Add build-time frontmatter validation (warn on missing updated dates)
  3. Document the update workflow for Shae (edit wiki in Obsidian/Claude → push → auto-deploy)

Content Architecture Decision (Report 4 Scope)

Question: Should the wiki’s file structure (entities/concepts/sources/analysis/decisions) be reorganised into business-domain navigation (Finance, Operations, Strategy, Governance, Technology)?

Answer: No. Keep the current file structure. Build business-domain navigation into the Quartz category landing pages instead.

Rationale:

  • The current 5 categories are within the cognitive sweet spot (5–7 items per NNGroup research — see Perplexity Knowledge Base UX Research)
  • The real problem is the 102-page Concepts category. The fix is to group Concepts by sub-domain (Operations, Strategy, Finance, Governance, Marketing, Technology) on its landing page — not to move files
  • Restructuring files would risk breaking [[wiki links]] through ambiguity and case-sensitivity issues (the #1 failure mode per Perplexity SSG Stack Evaluation)
  • Quartz Explorer already supports custom sort/filter/map functions — navigation layer is independent of file location
  • This approach is already specified in Phase 2, Step 4 of the implementation spec above

Report 4 (Perplexity prompt) is therefore unnecessary — the existing three reports provide sufficient evidence to make this call.

Assumptions

  • The Pride wiki does not use Dataview queries (confirmed — no impact from Quartz’s lack of Dataview support)
  • The wiki does not use Obsidian Canvas files (confirmed — no impact)
  • Mat will only read, never edit the wiki (edits remain Shae’s responsibility via the source vault)
  • A *.pages.dev subdomain is acceptable if a custom domain isn’t immediately available

Confidence Level

High. Three independent research reports converge on the same recommendation. All features shipping today — no deferrals. Quartz is the only SSG that handles the wiki’s [[wiki link]] format natively. The Cloudflare stack is well-documented, free, and has no vendor lock-in for static content. The main uncertainty is the 2–3 day customisation effort — scope could expand if the horizontal nav component proves complex.