Skip to main content

Wiki Implementation Guide

Overview

This document describes the implementation of GitHub Issue #180: hosting the project documentation as a private, web-browsable wiki using Google Cloud Storage (GCS) and Docusaurus.

Architecture

Components

  1. Docusaurus Static Site Generator

    • Modern documentation framework
    • Automatic sidebar generation from folder structure
    • Local Search functionality (@easyops-cn/docusaurus-search-local)
    • Beautiful, responsive UI
  2. Firebase Hosting

    • Project: construction-code-expert-dev (Wiki Target)
    • Static website hosting
    • Firebase Authentication (Google Auth Integration)
    • Identity Aware Proxy / Allowlist logic handled by App
  3. Git Hooks

    • Post-commit hook triggers on docs changes
    • Automatically syncs docs to wiki directory

Data Flow

Developer edits docs/          git commit triggers post-commit hook
↓ ↓
docs/*.md rsync to wiki/docs/
↓ ↓
Commit Docusaurus build (generates search index)
↓ ↓
Post-commit hook wiki/dist/
↓ ↓
deploy-to-firebase-smart.sh firebase deploy
↓ ↓
wiki/docs/ Firebase Hosting (Target: wiki)

Web access via Firebase Auth

https://construction-code-expert-dev-wiki.web.app/

Implementation Files

Scripts

All scripts are located in cli/sdlc/wiki/:

  1. init-docusaurus.sh

    • One-time setup script
    • Creates Docusaurus project in wiki/ directory
  2. deploy-to-firebase-smart.sh

    • Smart Build: Checks timestamps to avoid rebuilding unchanged docs
    • Build: Runs npm run build (generates static HTML + Search Index)
    • Deploy: Deploys dist/ to Firebase Hosting target wiki
  3. sync-docs-to-wiki.sh

    • Syncs docs/ to wiki/docs/ using rsync
    • Handles MDX auto-escaping

Git Hook

.git/hooks/post-commit

  • Triggers after every commit
  • Detects changes in docs/ folder
  • Calls sync-docs-to-wiki.sh automatically
  • Provides user feedback

Configuration Files

  • .gitignore: Excludes wiki build artifacts and node_modules
  • wiki/docusaurus.config.ts: Main config, includes @easyops-cn/docusaurus-search-local plugin.
  • wiki/firebase.json: Hosting configuration (redirects, headers).
  • docs/wiki-implementation.md: This document

Setup Instructions

Prerequisites

# Ensure you have the required tools
node --version # Node.js 18+
npm --version # npm 9+
gcloud version # Google Cloud SDK

# Authenticate with GCP
gcloud auth application-default login
gcloud config set project construction-code-expert-dev

One-Time Setup

# 1. Initialize Docusaurus
./cli/sdlc/wiki/init-docusaurus.sh

# 2. Login to Firebase
firebase login

Daily Usage

# Edit documentation
vim docs/some-doc.md

# Commit changes (triggers automatic sync)
git add docs/
git commit -m "Update documentation"

# Deploy to GCS when ready
./cli/sdlc/wiki/deploy-to-gcs.sh

Deployment

# Smart deploy (builds only if needed)
./cli/sdlc/wiki/deploy-to-firebase-smart.sh

Access Control

The wiki is protected by Firebase Authentication on the main application domain. The Hosting rules require a valid session to access the content if integrated with the main app's routing, or via Cloud Run proxy depending on the specific setup.

Search Implementation

We use @easyops-cn/docusaurus-search-local for search functionality.

  • Type: Client-side (Offline) Search
  • Index: Built at compile time (search-index.json in dist/)
  • Privacy: 100% Private. The index never leaves the hosting environment and is protected by the same auth as the docs.

Configuration

Managed in wiki/docusaurus.config.ts:

themes: [
[
require.resolve("@easyops-cn/docusaurus-search-local"),
({
hashed: true,
language: ["en"],
docsRouteBasePath: "/",
indexBlog: false,
}),
],
]

Technical Details

GCS Configuration

The bucket is configured with:

  • Uniform bucket-level access: Enabled (required for IAM)
  • Main page: index.html
  • Error page: 404.html
  • CORS: Allows GET/HEAD from any origin
  • Cache-Control:
    • Static assets: 1 year
    • HTML files: 1 hour

Docusaurus Configuration

Key settings in wiki/docusaurus.config.ts:

  • Base URL: /construction-code-expert-dev-wiki/
  • URL: https://storage.googleapis.com
  • Docs route: Root path (/)
  • Blog: Disabled
  • Theme: Classic preset with Material design
  • Search: Built-in

Git Hook Behavior

The post-commit hook:

  1. Runs after every commit
  2. Checks git diff-tree for changed files
  3. If any file starts with docs/, triggers sync
  4. Does NOT automatically deploy to GCS (manual step)
  5. Provides informative console output

MDX Compatibility and Auto‑Escaping

Docusaurus v3 treats all .md files as MDX. Certain patterns that are harmless in plain Markdown can break MDX parsing or execute as JavaScript during static site generation. To keep source docs clean and avoid manual edits, the sync pipeline auto‑escapes MDX‑sensitive syntax.

What is MDX?

MDX is “Markdown + JSX.” It lets you embed React components and JavaScript expressions inside Markdown. Because MDX parses {}, <>, and other symbols as code, content like ${VAR} or <1s in plain Markdown can be misinterpreted at build time unless escaped or fenced. See the MDX docs for details: mdxjs.com.

What is JSX?

JSX is a JavaScript syntax extension used by React. It lets you write UI using HTML‑like tags that compile to React.createElement(...) calls. Example: <Button size="sm">Click</Button> is valid JSX. In MDX, JSX is allowed inline, so text that looks like a tag (for example <1s, <note>, or <foo>bar) may be parsed as JSX unless it’s escaped or fenced as code.

What does “fenced” mean?

Wrapped as code (inline backticks or triple‑backtick code blocks) so MDX doesn’t parse it as JSX/JS.

What can break MDX:

  • ${variable} outside code blocks (interpreted as JS interpolation)
  • <1s, <2s, >1s outside code blocks (interpreted as JSX)
  • JSON keys that MDX may misinterpret (e.g., keys with underscores) when content isn’t fenced

What the sync does automatically (cli/sdlc/wiki/escape-mdx-syntax.py):

  • Inside code fences:
    • Escapes ${ to \${} so template literals display literally
    • Escapes underscores in JSON keys: "project_id""project\_id"
  • Outside code fences:
    • Escapes ${ and additionally wraps any ${...} or \${...} in inline code to prevent MDX evaluation, e.g.
      • projects/${project_id}/projects/`$\{project_id\}`/
    • Neutralizes angle‑bracket comparisons before numbers: <1 `<`1 and >1 `>`1

How it runs:

  • The escaping script is invoked automatically by cli/sdlc/wiki/sync-docs-to-wiki.sh after rsync copies docs/ into wiki/docs/.
  • No changes are made to files under docs/; only the synced copies in wiki/docs/ are rewritten for MDX safety.

Validate locally:

# Re‑sync (applies auto‑escaping), then build
./cli/sdlc/wiki/sync-docs-to-wiki.sh
cd wiki && rm -rf .docusaurus dist && npm run build

# Spot‑check transformed lines (example paths)
sed -n '880,912p' wiki/docs/developer-playbooks/playbook.md

Tips when editing docs:

  • Prefer fenced code blocks for JSON and shell examples; MDX will leave fenced content alone (we still escape as defense‑in‑depth)
  • If you must use ${...} in narrative text, wrap it in inline code: `$\{name\}`
  • If comparisons like <1s appear in tables or prose, wrap the < or > in backticks: `<`1s / `>`1s

Advantages of This Approach

  1. Private by Default: IAM authentication, no public access
  2. Version Controlled: Docs are part of the repo
  3. No External Dependencies: Uses existing GCP infrastructure
  4. Cost Effective: GCS storage and bandwidth costs are minimal
  5. Automatic Sync: Git hooks keep wiki in sync with docs
  6. Beautiful UI: Docusaurus provides modern, searchable documentation
  7. No Additional Hosting: Uses GCP services already in use

Comparison with Alternatives

vs. GitHub Pages

  • ❌ GitHub Pages requires Enterprise for private access ($20+/user/month)
  • ✅ GCS uses existing GCP IAM, no additional cost

vs. Firebase Hosting

  • ❌ Firebase requires separate authentication setup
  • ✅ GCS uses existing GCP authentication

vs. Self-Hosted Server

  • ❌ Requires server maintenance, security updates
  • ✅ GCS is fully managed, highly available

Troubleshooting

Git Hook Not Running

# Make hook executable
chmod +x .git/hooks/post-commit

# Test manually
.git/hooks/post-commit

Permission Denied Errors

# Re-authenticate
gcloud auth application-default login
gcloud config set project construction-code-expert-dev

# Verify bucket permissions
gsutil iam get gs://construction-code-expert-dev-wiki

Build Errors

cd wiki
rm -rf node_modules package-lock.json .docusaurus
npm install
npm run build

Sync Issues

# Manual sync
./cli/sdlc/wiki/sync-docs-to-wiki.sh

# Check rsync output
rsync -av --delete --dry-run docs/ wiki/docs/

Maintenance

Updating Docusaurus

cd wiki
npm update
npm audit fix
git commit -am "Update Docusaurus dependencies"

Backup Strategy

The wiki content is backed up in multiple places:

  1. Source docs in git repository (primary source)
  2. GCS bucket (deployed version)
  3. Local wiki/docs directory (synced copy)

Monitoring

Monitor GCS bucket usage:

# Check bucket size
gsutil du -sh gs://construction-code-expert-dev-wiki

# Check access logs (if enabled)
gsutil ls gs://construction-code-expert-dev-wiki-logs/

Future Enhancements

Potential Improvements

  1. CI/CD Integration: GitHub Actions to auto-deploy on merge to main
  2. Custom Domain: Map to custom domain
  3. Analytics: Add Google Analytics
  4. Versioning: Add version selector
  5. Automated Testing: Add link checker

CI/CD Example (Future)

# .github/workflows/deploy-wiki.yml
name: Deploy Wiki
on:
push:
branches: [main]
paths: ['docs/**']
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: google-github-actions/setup-gcloud@v0
- run: ./cli/sdlc/wiki/sync-docs-to-wiki.sh --deploy

Support

For questions or issues:

  1. Check the QUICKSTART.md in the cli/sdlc/wiki/ directory
  2. Review the README.md in the cli/sdlc/wiki/ directory
  3. Check troubleshooting section above
  4. Open an issue on GitHub