Skip to content

Publishing a Knowledge Base

Every FreeDocStore knowledge base follows the same lifecycle: plan → repo → build → deploy → register.

Lifecycle

  1. Plan. Turn a topic into a concrete plan: KB id (slug), repo name, Cloudflare Pages project, production URL, first pages. The MCP publish_plan tool generates this plan without creating anything.
  2. Publish. The console calls the API worker's POST /api/publish, a single server-side operation that creates the public repo (as the signed-in user), commits all source files in one commit, and registers the KB in site/registry.json — idempotently, with per-step results.
  3. Build. GitHub Actions installs Zensical and runs python -m zensical build --strict, producing static HTML in site/ (never committed).
  4. Deploy. The workflow ensures the Cloudflare Pages project exists, then deploys site/ to it, using the FreeDocStore org-level Actions secrets.
  5. Discover. The registry entry makes the KB visible to the product site, the console library, and MCP agents.

The deploy workflow

Each KB repo carries .github/workflows/deploy.yml, triggered on push to main (and manual dispatch):

  1. Checkout, set up Python 3.12.
  2. python -m pip install zensical
  3. python -m zensical build --strict — strict mode fails the build on broken links or config errors.
  4. Source metadata injection — a Node script stamps every generated HTML page with:

    <meta name="source-repo" content="FreeDocStore/<kb-id>">
    <meta name="source-path" content="docs/<page>.md">
    

    This maps each published page back to its Markdown source, which is what makes published pages agent-readable and editable from the Chrome extension.

  5. wrangler pages deploy site --project-name=<kb-id> via cloudflare/wrangler-action.

The Cloudflare step is conditional on CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID being available. These are org-level Actions secrets on the FreeDocStore GitHub org, visible to public repositories — a new public KB repo inherits them with no per-repo setup. If they are missing, the workflow prints a notice and skips deployment instead of failing.

Publishing checklist

  • Repo created under FreeDocStore/<kb-id>, public
  • zensical.toml at root with site_url set to the production URL
  • docs/index.md plus topic pages, listed in nav
  • .github/workflows/deploy.yml copied from an existing KB with --project-name=<kb-id>
  • .gitignore excludes site/, .cache/, __pycache__/
  • Actions run is green (the workflow creates the Pages project on first run) and the site answers at https://<kb-id>.freedocstore.online/
  • Registry entry exists in site/registry.json (automatic via /api/publish; manual only for hand-scaffolded repos)

Updating a published KB

Push to main — or merge a proposal PR — and the same workflow rebuilds and redeploys. There is no separate publish step. Agents can propose updates through the MCP update_files tool, which opens a reviewable PR by default.

Domains

Every KB gets a platform subdomain by default: https://<kb-id>.freedocstore.online/. The deploy workflow's "Attach custom domain" step registers the domain on the Pages project and ensures the CNAME record via the Cloudflare API, using the org-level Actions secrets — no manual Cloudflare steps. The underlying <kb-id>.pages.dev URL keeps working.

Bring-your-own domains use the same workflow step with a different DOMAIN value; the registry records all attached domains in cloudflare.custom_domains.