Skip to content

Docs Hosting

The docs site should be hosted as a small static surface that stays separate from the Wavemap app/API deploy lane.

The first infrastructure and deploy slices are live. Hosting capacity exists, and the docs deploy workflow has published and smoked the first static artifact.

  • Public hostname: docs.wavemap.app.
  • Build artifact: apps/wavemap-docs/dist.
  • Runtime model: static files only.
  • App runtime dependencies: none.
  • Database dependencies: none.
  • Wake path dependencies: none.
  • Container host dependencies: none.

The docs site should be able to publish content updates without redeploying the frontend, backend, database, runtime host, or deployed-dev control plane.

The first reviewed generated topology figure for this lane is published as a curated docs asset. The paired Mermaid source is kept beside the rendered figure so the reviewed diagram remains inspectable without exposing private generated artifacts.

Topology diagram showing the docs public web surface depending on the static origin.

Documentation deployment topology generated from reviewed semantic topology data. Reviewed Mermaid source: fig-docs-site-documentation-deployment.mmd.

The first implementation uses Pulumi-managed AWS resources:

ConcernShape
Origin storagePrivate S3 bucket containing the built docs artifact.
CDNCloudFront distribution in front of the bucket.
Origin accessCloudFront origin access control, keeping the bucket private.
CertificateACM certificate for docs.wavemap.app, issued in us-east-1 for CloudFront.
DNSDelegated Route53 hosted zone for docs.wavemap.app, with A / AAAA aliases to CloudFront.
Error handlingStatic-site fallback behavior that preserves useful 404s from Starlight.

The docs hosting resources should be modeled as a separate deployable surface. They may live in the existing Pulumi project, but their purpose, outputs, and deploy permissions should remain distinct from app/API runtime deployment.

The root wavemap.app DNS provider delegates docs.wavemap.app to the Route53 hosted-zone nameservers created by Pulumi. Without that NS delegation, ACM DNS validation and public docs resolution cannot complete.

The first live apply had one external handoff:

  1. Pulumi creates the docs.wavemap.app hosted zone.
  2. The generated hosted-zone nameservers are added as NS records for docs.wavemap.app at the root DNS provider.
  3. ACM DNS validation can complete.
  4. CloudFront and the public docs alias records can finish provisioning.

If the apply is split, create the hosted zone first, delegate the NS records at the root provider, then apply the certificate, CloudFront distribution, and alias records.

Root DNS delegation remains a manual approval-gated action outside this repo.

Current delegated nameservers:

ns-1040.awsdns-02.org
ns-1878.awsdns-42.co.uk
ns-799.awsdns-35.net
ns-84.awsdns-10.com

The first docs-hosting preview planned 15 creates and 68 unchanged resources. No existing app/API runtime resources were planned for replacement or deletion.

The planned creates were limited to the docs site hosted zone, private S3 bucket, bucket controls, ACM certificate and validation, CloudFront distribution, origin access control, routing function, alias records, and bucket policy.

Pulumi update #14 on 2026-05-10 created the docs hosted zone, DNS validation, bucket controls, CloudFront distribution, bucket policy, and public alias records after an earlier apply attempt exposed a missing Route53 hosted-zone permission. The completed docs stack output is:

  • Public URL: https://docs.wavemap.app.
  • S3 bucket: wavemap-dev-docs-site-20260510155940197600000002.
  • CloudFront distribution: E3IU4R648DOIS5.
  • CloudFront domain: d2sy9ham1w9lwi.cloudfront.net.

The first artifact deploy has uploaded apps/wavemap-docs/dist, so docs.wavemap.app now serves the curated static docs site.

Pulumi update #15 on 2026-05-10 created the docs-specific GitHub OIDC role and policy for publishing that artifact. The GitHub dev environment now has DOCS_AWS_ROLE_TO_ASSUME set to the docs deploy role ARN.

First deploy proof: GitHub Actions run 25668228940 completed successfully on 2026-05-11T11:47:50Z against develop commit 540a176066e6ee6416e4359c6d97aca063af656d. It built the docs app, published the static artifact, and completed the read-only docs smoke check.

The repo-side docs deploy workflow is .github/workflows/deploy-docs.yml. It stays smaller than the deployed-dev app workflow:

For publish and smoke command contracts, wrapper paths, key flags, and default mutation posture, use the Deploy Docs and Smoke sections of the CLI command reference.

  1. Check out the selected ref.
  2. Install dependencies with the shared Node/pnpm setup.
  3. Assume the docs deploy role through GitHub OIDC.
  4. Read the current sanitized deployment contract from the private deployment contract store.
  5. Validate the docs target fields from that contract.
  6. Build with pnpm build:docs.
  7. Upload only apps/wavemap-docs/dist to the docs bucket.
  8. Delete removed files from the bucket during sync.
  9. Create a CloudFront invalidation when published files change.
  10. Smoke the public docs URL and a small set of critical static assets.

The workflow supports two trigger paths:

  • workflow_dispatch so a human can publish or republish docs on demand.
  • A path-filtered develop push trigger so relevant docs changes publish after merge.
  • No pull request preview deploys in the first hosting pass.

Path filters include the docs app, docs deploy scripts, docs workflow/action files, and workspace lockfiles. The apps/wavemap-docs/working-notes tree is excluded so scratch-pad changes do not publish by themselves.

The first live workflow proof is captured. Future workflow dispatches, permission changes, infrastructure changes, DNS changes, certificate changes, and OIDC trust changes remain approval-gated actions.

Docs deploy permissions use a docs-specific GitHub OIDC role instead of reusing the app/API deploy role. The workflow expects a GitHub dev environment secret named DOCS_AWS_ROLE_TO_ASSUME, plus environment variables for the deployment contract stack selector and private artifact bucket. Routine docs deploy does not require a Pulumi access token.

Current docs deploy environment values:

  • Secret: DOCS_AWS_ROLE_TO_ASSUME.
  • Variable: PULUMI_STACK, required value aws-dev.
  • Variable: DEPLOYMENT_CONTRACT_STORE_BUCKET, required value wavemap-dev-deployment-contracts-20260518124223904700000001.
  • Optional variable: DEPLOYMENT_CONTRACT_STORE_KEY_PREFIX, defaulting to deployment-contracts.

Current docs deploy access:

  • Role: wavemap-dev-github-docs-deploy-role.
  • Trust subject: repo:gabrielbourget/wavemap:environment:dev.
  • Policy: wavemap-dev-github-docs-deploy-policy.

The deploy role should be limited to:

  • Listing the docs bucket.
  • Putting and deleting objects under the docs bucket.
  • Creating CloudFront invalidations for the docs distribution.
  • Reading invalidation status only if the workflow waits for completion.
  • Reading the current deployment contract artifacts under the private deployment contract store prefix.

The deploy role should not be able to mutate app/API infrastructure, EC2 runtime state, database resources, SSM runtime parameters, media buckets, ECR repositories, deployment contract artifacts, Route53 records, or ACM certificates.

Pulumi infrastructure changes, DNS changes, certificate creation, OIDC trust changes, and first workflow deploy runs remain explicit approval-gated actions.

Use Cloud Automation Permission Review before broadening the docs deploy role, reusing another deploy role, or adding new docs publish actions.

Only curated site output should enter the public docs bucket.

  • Publish apps/wavemap-docs/dist.
  • Do not publish apps/wavemap-docs/working-notes.
  • Do not publish raw Pulumi exports, raw AWS inventory, workflow evidence, topology snapshots, or local operator notes.
  • Publish generated diagrams, summaries, or inventories only after they are reviewed and sanitized into curated docs content or static assets.

The Pagefind search index is acceptable because it is generated from curated docs content.

The first smoke check should prove that the static site is reachable and that generated assets load:

  • https://docs.wavemap.app/
  • https://docs.wavemap.app/developer/architecture/authentication-and-authorization/
  • The generated search/index assets used by Starlight.
  • At least one hashed static asset referenced by the HTML.

Smoke should be read-only. It should not call app/API runtime endpoints or wake deployed-dev infrastructure.

  • Pull request preview docs.
  • Versioned docs.
  • Docs release automation.
  • Analytics.
  • Access-controlled private docs.
  • Automated generated topology publishing.
  • Redirect compatibility for old local-only docs routes.