Skip to content

Documentation Platform Architecture

How CampusCore's documentation is organized, who can see what, and how we publish it without duplicating content. This doc is itself an internal-tier page, authored under the model it describes.

The problem

Our docs serve different readers - clients onboarding, client IT, prospects later, and our own engineers - and the same fact often belongs to more than one of them. Organizing by audience (a client-facing/ folder, an internal/ folder) forces us to copy a fact to show it to a second audience, which drifts. Building every audience's content into one site and hiding the private parts risks leaking them.

Principles

The platform keeps three concerns independent:

  • Organize by topic. A page's folder reflects what it is about, never who may read it.
  • Gate by audience. Who may read a page is a tag on the page, not its location.
  • Share by include. A reusable detail is authored once and included wherever it is needed, never copied.

Decoupling these is what lets one source tree serve many audiences with no duplication and no leak risk.

Audiences

Two tiers for now, tiered so that broader access is a superset of narrower:

  • client - onboarded clients, via the existing Cloudflare Access email allowlist.
  • internal - CampusCore staff, via a Cloudflare Access policy scoped to our staff email domain.

internal sees everything; client sees only client pages. A third public tier (prospects, ungated) can be added later without reworking the model - it would simply be the broadest, most-restrictive-wins tier.

Source layout

One docs/ tree, organized by topic:

docs/
  onboarding/     # the deployment journey
  product/
    reference/    # technical reference
    how-to/       # task guides (deploy the IAM role, connect Drive, ...)
  architecture/   # system design (this folder)
  security/       # security posture and controls
  ops/            # internal runbooks (Sentry, Slack, pipeline, scraping)
  _shared/        # reusable snippets - never standalone pages

A topic folder holds pages for every audience; audience is metadata, not location.

Audience tagging

Every page declares its tier in front matter:

---
audience: client      # client | internal
---

Untagged pages default to internal - the model fails closed, so a page can never leak to clients by omission.

Builds

One MkDocs configuration produces both sites. A build hook (registered via hooks:) reads the target audience from an environment variable, inspects each page's audience front matter, and drops any page the target may not see. This means no parallel navs to keep in sync - the tag is the single control.

Build Target Includes Hosting
Client portal client client pages Cloudflare Pages, client email allowlist (existing)
Internal docs internal all pages Cloudflare Pages, staff email-domain Access policy

Internal content is physically absent from the client build, not merely hidden - the same safe posture as the original symlink allowlist, generalized.

Reuse without drift

  • Snippets. pymdownx.snippets pulls a shared file into a page: --8<-- "_shared/aws-resource-table.md". The AWS resource and cost table, the encryption-defaults block, and the deploy-role commands each live in one _shared/ file and are included into every page that needs them. Edit once, every view updates.
  • Overview vs procedure. Audience-specific overviews stay thin and link or include a single detailed procedure. An onboarding overview ("the deploy role") points at one product/how-to guide that holds the real console + CLI steps; the internal runbook references the same guide.

Rollout plan

Staged so the live client portal never regresses:

  1. Foundation. Enable pymdownx.snippets; add the audience front-matter convention and the filtering hook; tag existing pages (client-facing/* -> client, project/* + references/* -> internal). The client build output must match today's, page for page.
  2. Internal site. Add the internal build target, a CI job, and a staff-gated Cloudflare Pages project.
  3. Snippet refactor. Extract the already-duplicated facts (AWS resources/cost, encryption defaults, deploy-role commands) into _shared/ and include them.
  4. Topic reorg. Move files into the topic folders above; update links.
  5. New content. The deploy-role how-to guide first, then product reference and how-tos, then client-facing architecture and security pages assembled from _shared/ controls.