---
title: Operational Runbook & Hosting Recipes
description: Production hosting procedures, edge routing recipes, health verification, and incident triage for VertiWiki.
tags: [vertiwiki, operations, runbook, hosting, cloudflare, vercel, nginx]
---

# Operational Runbook & Hosting Recipes

> For the complete documentation index and agent navigation, see [llms.txt](/llms.txt).

VertiWiki is a 100% static, zero-backend single-page application. Operating it in production involves configuring static web servers, edge CDNs, and content negotiation rules.

---

## ☁️ Multi-Cloud Deployment Recipes

### 1. Vercel (`vercel.json`)
To deploy to Vercel with automatic AI content negotiation (`Accept: text/markdown`) and trailing slash preservation:

```json
{
  "trailingSlash": true,
  "cleanUrls": false,
  "rewrites": [
    {
      "source": "/docs/:path*/",
      "has": [{ "type": "header", "key": "Accept", "value": ".*text/markdown.*" }],
      "destination": "/docs/:path*/index.md"
    },
    {
      "source": "/docs",
      "destination": "/docs/index.html"
    }
  ]
}
```

### 2. Cloudflare Pages & Workers
Use Cloudflare Pages for ultra-fast global distribution. For edge content negotiation:

```javascript
export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    const accept = request.headers.get("Accept") || "";

    // If AI agent requests raw Markdown
    if (accept.includes("text/markdown") && !url.pathname.endsWith(".md")) {
      const targetMd = url.pathname.endsWith("/") ? `${url.pathname}index.md` : `${url.pathname}/index.md`;
      return env.ASSETS.fetch(new Request(new URL(targetMd, url.origin)));
    }

    return env.ASSETS.fetch(request);
  }
};
```

### 3. Nginx (`vertiwiki.conf`)
```nginx
server {
    listen 80;
    server_name docs.example.com;
    root /var/www/vertiwiki;
    index index.html;

    # Gzip compression for single-file bundle and markdown
    gzip on;
    gzip_types text/plain text/css text/markdown application/javascript application/json image/svg+xml;

    # Serve static assets and raw markdown directly
    location / {
        try_files $uri $uri/ /index.html;
    }

    # Cache static engine bundle aggressively
    location = /index.html {
        add_header Cache-Control "no-cache, must-revalidate";
    }

    location ~* \.(?:svg|png|jpg|woff2|json)$ {
        expires 30d;
        add_header Cache-Control "public, no-transform";
    }
}
```

---

## 🩺 Health Checks & Verification

Perform the following health checks after any deployment:

| Check | Target | Expected Result | Action if Degraded |
| :--- | :--- | :--- | :--- |
| **Engine Bundle** | `GET /index.html` | HTTP 200, Content-Type: `text/html` | Verify asset deployment and file permissions. |
| **Configuration** | `GET /config.json` | HTTP 200, Valid JSON | Check JSON syntax using `jq . config.json`. |
| **Navigation** | `GET /navigation.md` | HTTP 200, Valid Markdown | Ensure navigation file exists at specified path. |
| **Home Page** | `GET /index.md` | HTTP 200, Valid Markdown | Verify `homePage` setting in `config.json`. |
| **AI Agent Directives** | `GET /llms.txt` | HTTP 200, Plain text index | Check `llmsTxtUrl` setting and robots.txt. |

---

## 🚨 Incident Triage & Emergency Playbook

### Scenario A: Browser Shows Blank White Screen
1. Open Developer Tools (<kbd>F12</kbd>) and check the Console tab.
2. If `SyntaxError: Unexpected token in JSON at position ...`:
   - `config.json` has a trailing comma or syntax error. Run `npx jsonlint config.json` or `jq . config.json`.
3. If `NetworkError: Failed to fetch config.json`:
   - Verify that your web server is running and accessible over HTTP.
   - Confirm you are not opening via `file:///` protocol (which blocks CORS requests in Chromium/Safari).

### Scenario B: Clicking Navigation Links Shows 404
1. Inspect the URL hash route (e.g. `#/guides/authoring.md`).
2. Verify that the physical file exists on the server at that exact path.
3. Check case sensitivity: Linux file servers enforce strict case matching (`guide.md` vs `Guide.md`).

---

## 🔄 Disaster Recovery & Backups

Because VertiWiki has no database:
1. **Source of Truth**: The Git repository containing your `.md` files and `config.json` is your primary source of truth.
2. **Instant Restore**: In the event of a server failure, re-clone the Git repository to any static file host or S3 bucket. Recovery Time Objective (RTO) is `< 60 seconds`.
