Documentation sites

Documentation sites

CardHorizon has two documentation sites. Both are built from one repository with docmd and hosted on Cloudflare Workers.

General docs Technical docs
URL https://docs.cardhorizon.com https://docstech.cardhorizon.com
Pages docs/ docs-tech/
Images assets/images/ docs-tech/assets/images/
docmd config docmd.config.json docmd.tech.config.json
Build output site/ site-tech/
Worker cardhorizon-docs cardhorizon-docs-tech
Wrangler config wrangler.jsonc wrangler.tech.jsonc
Access Cloudflare Access, wider group Cloudflare Access, technical team only

Why two separate builds

A docmd build puts the content of every page into shared files at the site root: the search index (_docmd-search/), llms.txt / llms-full.txt, the okf/ bundle, sitemap.xml and the sidebar on every page. If technical pages were part of the general build, anyone with access to the general docs could read them through search, even with the pages themselves blocked.

Two builds, two Workers and two hostnames keep the sites fully separate. Each has its own Cloudflare Access application.

Where to put images

docmd copies the top-level assets/ folder into both builds. Put images for technical pages in docs-tech/assets/, which only the technical build includes. Reference them as /assets/images/... as usual.

Commands

Command What it does
npm run dev General docs dev server with live reload at http://localhost:3000
npm run dev:tech Technical docs dev server with live reload at http://localhost:3001
npm run build Build both sites
npm run validate Check links on both sites
npm run preview / npm run preview:tech Serve the built site on the local Workers runtime
npm run deploy:docs / npm run deploy:tech Build and deploy one site
npm run deploy Build and deploy both sites

Hosting

Each Worker serves only static files; there is no Worker code. The settings in each Wrangler config:

  • assets.not_found_handling: "404-page": unknown URLs get the generated 404.html.
  • routes with custom_domain: true: Cloudflare creates the DNS record and certificate for the hostname.
  • workers_dev: false: no public *.workers.dev address that would bypass Cloudflare Access.