Skip to main content

Hosting the handbook

This handbook (the Docusaurus site you are reading) is hosted on Cloudflare Pages, locked down with Cloudflare Access so only @adjustsquare.com accounts can read it, and auto-deployed from Bitbucket on every change. This page explains how it all fits together and how to set it up once.

PieceChoice
HostCloudflare Pages (project contentsvision-docs)
URLhttps://contentsvision-docs.pages.dev (custom domain optional later)
AccessCloudflare Access, One-time PIN email login, restricted to @adjustsquare.com
CI/CDBitbucket Pipelines, deploying with Wrangler
Production branchstage (merges to stage publish the live site)
Previewsevery PR that touches docs/** gets its own preview URL
Why Wrangler and not Pages Git integration

Cloudflare Pages' built-in Git integration supports GitHub and GitLab, not Bitbucket. So we deploy from Bitbucket Pipelines using Wrangler (wrangler pages deploy), which is the supported path for Bitbucket and also gives us per-PR preview deploys.

How auto-deploy works

The pipeline lives in bitbucket-pipelines.yml at the repo root. It only runs when docs/** changes, so backend and frontend commits never rebuild the docs.

Each step: npm ci, npm run build (Docusaurus emits docs/build), then wrangler pages deploy. Wrangler reads the project name and output dir from docs/wrangler.jsonc. A deploy whose --branch equals the project's production branch (stage) is a production deploy; anything else is a preview.

One-time setup

You only do this once. It needs a Cloudflare account on the adjustsquare.dev (or any) zone and admin on the Bitbucket repo.

1. Create the Pages project

With Wrangler authenticated to the account (wrangler login, or CLOUDFLARE_API_TOKEN set):

cd docs
npx wrangler@4 pages project create contentsvision-docs --production-branch=stage

Or in the dashboard: Workers & Pages -> Create -> Pages -> Direct Upload, name it contentsvision-docs, and set the production branch to stage in the project settings.

2. Create a deploy API token

In the Cloudflare dashboard: My Profile -> API Tokens -> Create Token, using the "Edit Cloudflare Workers" template, or a custom token with:

  • Permissions: Account -> Cloudflare Pages -> Edit
  • Account resources: your account

Copy the token. Also note your Account ID (Workers & Pages overview, right sidebar).

3. Add the Bitbucket repository variables

Repository settings -> Pipelines -> Repository variables, both marked Secured:

VariableValue
CLOUDFLARE_API_TOKENthe token from step 2
CLOUDFLARE_ACCOUNT_IDyour account id

Enable Pipelines if it is not already on (Repository settings -> Pipelines -> Settings).

4. Lock it to @adjustsquare.com with Cloudflare Access

This is the "native Cloudflare auth" email login. It covers the production URL and every preview deployment.

  1. In the dashboard, open the contentsvision-docs Pages project -> Settings -> Access policy and click Enable Access policy (this creates a self-hosted Access application for *.contentsvision-docs.pages.dev).
  2. In Zero Trust -> Access -> Applications, open the application and add a policy:
    • Action: Allow
    • Include: Emails ending in -> @adjustsquare.com
  3. Make sure the One-time PIN login method is enabled (Zero Trust -> Settings -> Authentication -> Login methods). It is on by default and needs no identity provider: users enter their email and receive a code.
  4. Optional: set the session duration (for example 24 hours) so people are not re-prompted constantly.

The result: visiting the docs shows Cloudflare's email screen. A reader enters their address, and only @adjustsquare.com addresses receive a code and get in. Everyone else is blocked.

5. First deploy

Merge a docs/** change to stage (for example, merge the handbook PR). The pipeline builds and publishes to contentsvision-docs.pages.dev. From then on it is automatic.

To attach a custom domain later (for example docs.adjustsquare.dev): Pages project -> Custom domains -> Set up a domain, then update url in docs/docusaurus.config.ts. The Access policy follows the project, so the custom domain is protected too.

Automating the Access setup (optional)

The dashboard steps above can be scripted against the Cloudflare API for repeatable, reviewable setup. A reference helper lives at infra/cloudflare/setup-access.sh; it creates the Pages project and the Access application + @adjustsquare.com policy from CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID. See infra/cloudflare/README.md.

Operational notes

  • Previews are protected too. Because Access is enabled on the Pages project, preview URLs (<hash>.contentsvision-docs.pages.dev) require the same @adjustsquare.com login. No preview is ever public.
  • Search is offline and self-contained. npm run build bundles a local search index into docs/build (via @easyops-cn/docusaurus-search-local), so the navbar search needs no Algolia account or external crawler. That is the right fit here: a hosted crawler could not reach the site behind Cloudflare Access anyway. The index refreshes on every build, so search reflects whatever was last deployed.
  • Rollbacks are instant from Pages project -> Deployments (promote any previous deployment).
  • Build logs for a failed deploy are in the Bitbucket pipeline run, and in Pages -> Deployments for the upload step.
  • The pipeline fails until steps 1-3 are done (no project or token). That is expected during setup; it goes green once the project exists and the variables are set.