From 52b2e8b9b1a196994d9ed979f74c7bd310d6e317 Mon Sep 17 00:00:00 2001 From: Barak Korren Date: Wed, 15 Apr 2026 15:36:00 +0300 Subject: [PATCH 1/2] ci+docs: web/, cloudflare_site/, _bundle artifact (ADR 0019) - Move the document graph to web/public/index.html; rename site/ to cloudflare_site/ for the sole Wrangler project. - ADR 0019 (Accepted): web/ for browser source; contributor-guidance; root package.json for future npm/Vite while source stays under web/. - Build Site: stage _bundle/public and _bundle/worker (worker from the build checkout) and upload as artifact site. - Deploy Site: default-branch checkout only (trusted wrangler.toml); download artifact to _bundle/; validate top-level entries with find and copy only public/ and worker/ into cloudflare_site/ so the zip cannot inject wrangler.toml or other files beside the Worker tree. - Add a minimal ASSETS pass-through Worker at cloudflare_site/worker. - Update Makefile mindmap target, README, architecture.md, and site / Cloudflare rollout docs. Made-with: Cursor --- .github/workflows/site-build.yml | 15 +++++--- .github/workflows/site-deploy.yml | 34 ++++++++++++++++-- Makefile | 2 +- README.md | 1 + {site => cloudflare_site}/public/.gitkeep | 0 cloudflare_site/worker/src/index.ts | 20 +++++++++++ cloudflare_site/wrangler.toml | 14 ++++++++ ...9-web-source-and-cloudflare-site-layout.md | 35 +++++++++++++++++++ docs/architecture.md | 4 +++ docs/site-deployment.md | 12 +++---- .../plans/2026-04-09-site-cloudflare-pages.md | 30 ++++++++-------- ...2026-04-09-site-cloudflare-pages-design.md | 10 +++--- site/wrangler.toml | 12 ------- web/README.md | 3 ++ docs/mindmap.html => web/public/index.html | 0 15 files changed, 147 insertions(+), 45 deletions(-) rename {site => cloudflare_site}/public/.gitkeep (100%) create mode 100644 cloudflare_site/worker/src/index.ts create mode 100644 cloudflare_site/wrangler.toml create mode 100644 docs/ADRs/0019-web-source-and-cloudflare-site-layout.md delete mode 100644 site/wrangler.toml create mode 100644 web/README.md rename docs/mindmap.html => web/public/index.html (100%) diff --git a/.github/workflows/site-build.yml b/.github/workflows/site-build.yml index 1b5f26c24e..a7297a7522 100644 --- a/.github/workflows/site-build.yml +++ b/.github/workflows/site-build.yml @@ -20,13 +20,20 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} - - name: Prepare site + - name: Prepare deploy bundle run: | - mkdir -p _site - cp docs/mindmap.html _site/index.html + set -euo pipefail + mkdir -p _bundle/public + # Static tree → artifact public/ (Deploy copies only _bundle/public and _bundle/worker into cloudflare_site/). + # Root page: interactive graph (source of truth: web/public/index.html). + # When a Vite app exists under web/, extend this step (e.g. _bundle/public/admin/). + cp web/public/index.html _bundle/public/index.html + # Worker source from this checkout (PR head on PR builds) — deploy never clones PR for Wrangler; only this tree is untrusted. + mkdir -p _bundle/worker + cp -a cloudflare_site/worker/. _bundle/worker/ - uses: actions/upload-artifact@v4 with: name: site - path: _site/ + path: _bundle/ retention-days: 5 diff --git a/.github/workflows/site-deploy.yml b/.github/workflows/site-deploy.yml index 9368b04ac1..8982f3d7e3 100644 --- a/.github/workflows/site-deploy.yml +++ b/.github/workflows/site-deploy.yml @@ -26,16 +26,44 @@ jobs: HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }} HEAD_SHA: ${{ github.event.workflow_run.head_sha }} steps: + # Trusted tree only: wrangler.toml must not come from PR checkout (no PR-controlled [build] on the deploy runner). + # PR/fork Worker + static files ship in the Build Site artifact under _bundle/; we copy only public/ and worker/ (never extract TOML from the zip into cloudflare_site/). - uses: actions/checkout@v6.0.2 - name: Download build artifact uses: actions/download-artifact@v4 with: name: site - path: site/public + path: _bundle github-token: ${{ secrets.GITHUB_TOKEN }} run-id: ${{ github.event.workflow_run.id }} + - name: Apply artifact to Cloudflare project + run: | + set -euo pipefail + if [[ ! -d _bundle ]]; then + echo "::error::Missing _bundle after artifact download" + exit 1 + fi + while IFS= read -r -d '' entry; do + b=$(basename "$entry") + if [[ "$b" != "public" && "$b" != "worker" ]]; then + echo "::error::Disallowed path in site artifact: $b (only public/ and worker/ may exist at the top level of _bundle/)" + exit 1 + fi + if [[ ! -d "$entry" ]]; then + echo "::error::_bundle/$b must be a directory" + exit 1 + fi + done < <(find _bundle -mindepth 1 -maxdepth 1 -print0) + if [[ ! -d _bundle/public ]] || [[ ! -d _bundle/worker ]]; then + echo "::error::Artifact must contain _bundle/public/ and _bundle/worker/" + exit 1 + fi + mkdir -p cloudflare_site/public cloudflare_site/worker + cp -a _bundle/public/. cloudflare_site/public/ + cp -a _bundle/worker/. cloudflare_site/worker/ + - name: Resolve preview context (PR number + preview alias) id: preview-context if: success() @@ -86,7 +114,7 @@ jobs: uses: cloudflare/wrangler-action@v3.14.1 with: wranglerVersion: "4.30.0" - workingDirectory: site + workingDirectory: cloudflare_site apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} command: deploy --name="${{ vars.CLOUDFLARE_PROJECT_NAME }}" @@ -97,7 +125,7 @@ jobs: uses: cloudflare/wrangler-action@v3.14.1 with: wranglerVersion: "4.30.0" - workingDirectory: site + workingDirectory: cloudflare_site apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} command: >- diff --git a/Makefile b/Makefile index 5b284c334a..b32d959e12 100644 --- a/Makefile +++ b/Makefile @@ -67,7 +67,7 @@ fmt: uvx ruff format . mindmap: - @xdg-open docs/mindmap.html 2>/dev/null || open docs/mindmap.html 2>/dev/null || echo "Open docs/mindmap.html in your browser" + @xdg-open web/public/index.html 2>/dev/null || open web/public/index.html 2>/dev/null || echo "Open web/public/index.html in your browser" VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev") diff --git a/README.md b/README.md index e310277958..0a3f30b198 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ This is not a product spec. It's an evolving exploration of a hard problem space - **[docs/problems/applied/](docs/problems/applied/)** — Organization-specific considerations for downstream consumers: - [konflux-ci](docs/problems/applied/konflux-ci/) — Kubernetes-native CI/CD platform (the original proving ground) - **[docs/ADRs/](docs/ADRs/)** — Architecture Decision Records for crystallizing specific decisions (see [ADR 0001](docs/ADRs/0001-use-adrs-for-decision-making.md)) +- **[web/](web/)** — Browser-delivered assets for the public site (document graph today; future Vite app here). Cloudflare Worker config lives in [`cloudflare_site/`](cloudflare_site/) ([ADR 0019](docs/ADRs/0019-web-source-and-cloudflare-site-layout.md)). - **[docs/landscape.md](docs/landscape.md)** — Survey of AI code review tools, orchestration patterns, and connectivity gateways; how they relate to our goals (time-sensitive — check the date) - **[experiments/](experiments/)** — Logs and results from trying things in practice diff --git a/site/public/.gitkeep b/cloudflare_site/public/.gitkeep similarity index 100% rename from site/public/.gitkeep rename to cloudflare_site/public/.gitkeep diff --git a/cloudflare_site/worker/src/index.ts b/cloudflare_site/worker/src/index.ts new file mode 100644 index 0000000000..4b2d5c8759 --- /dev/null +++ b/cloudflare_site/worker/src/index.ts @@ -0,0 +1,20 @@ +/// + +/** + * Minimal Worker: serve static assets from `[assets]` only. + * Future OAuth or API routes extend this file; Wrangler project layout stays stable. + */ +export interface Env { + ASSETS?: Fetcher; +} + +export default { + async fetch(request: Request, env: Env): Promise { + if (env.ASSETS != null) { + return env.ASSETS.fetch(request); + } + return new Response("Worker misconfigured: ASSETS binding missing", { + status: 503, + }); + }, +}; diff --git a/cloudflare_site/wrangler.toml b/cloudflare_site/wrangler.toml new file mode 100644 index 0000000000..1fc3b2c177 --- /dev/null +++ b/cloudflare_site/wrangler.toml @@ -0,0 +1,14 @@ +# Cloudflare Worker + static assets. User Worker entry is worker/src/index.ts (stub passes through ASSETS). +# Deploy: site-deploy.yml checks out the default branch (trusted TOML), downloads the Build Site artifact to _bundle/, copies only ./public/ and ./worker/ from it, then runs Wrangler here. +# The workflow passes --name to match your account Worker name (GitHub variable CLOUDFLARE_PROJECT_NAME). +# See: https://developers.cloudflare.com/workers/static-assets/ + +name = "documentation-site" +main = "worker/src/index.ts" +compatibility_date = "2026-04-09" +workers_dev = true +preview_urls = true + +[assets] +directory = "./public" +not_found_handling = "single-page-application" diff --git a/docs/ADRs/0019-web-source-and-cloudflare-site-layout.md b/docs/ADRs/0019-web-source-and-cloudflare-site-layout.md new file mode 100644 index 0000000000..ab4ad00982 --- /dev/null +++ b/docs/ADRs/0019-web-source-and-cloudflare-site-layout.md @@ -0,0 +1,35 @@ +--- +title: "0019. Web source under web/ and Cloudflare project under cloudflare_site/" +status: Accepted +relates_to: + - contributor-guidance +topics: + - repository-layout + - ci + - cloudflare +--- + +# 0019. Web source under `web/` and Cloudflare project under `cloudflare_site/` + +Date: 2026-04-15 + +## Status + +Accepted + +## Context + +This repository mixes design documents, Go CLI code (`cmd/`), and a small **browser-delivered** surface (today the interactive document graph). That surface was previously rooted at `docs/mindmap.html` while Cloudflare Wrangler lived under `site/`, which read as a generic “website” folder rather than “Cloudflare deploy boundary,” and blurred documentation versus deployable HTML. Separating **`web/`** (browser source) from **`cloudflare_site/`** (Wrangler + deploy-time static) makes layout and CI obvious for contributors. + +## Decision + +1. **Browser-oriented source** (static HTML today; future Vite entrypoints and assets) lives under **`web/`**, starting with the document graph as **`web/public/index.html`** (served at `/` in production). **Node tooling** (`package.json`, lockfile, and scripts such as `npm run dev` / `npm run build`) stays at the **repository root** so day-to-day work does not require `cd web`; Vite config may still point `root` at `web/` (or a subdirectory) for resolution. +2. The **sole Wrangler project** in this repository lives under **`cloudflare_site/`** (`wrangler.toml`, `public/` populated by CI from the Build Site artifact, plus any future Worker source in that tree). The GitHub Actions **Deploy Site** workflow continues to use **`workingDirectory: cloudflare_site`** and unpacks the artifact into **`cloudflare_site/public/`**; workflow **names** (`Build Site`, artifact `site`, environments `site-preview` / `site-production`) stay stable for existing automation and operators. +3. **Build Site** assembles **`_site/`** from `web/` (and later from JS build outputs) without changing that deploy contract. + +## Consequences + +- Contributors edit the live mindmap at **`web/public/index.html`** instead of **`docs/mindmap.html`**. +- Paths in runbooks and local Wrangler preview use **`cloudflare_site/`** instead of **`site/`**. +- Future SPA work adds **Vite** (and related devDependencies) using the **root** `package.json`, with source and config under **`web/`**, and extends **`site-build.yml`** to merge build output into **`_site/`** without renaming **`cloudflare_site/`** again. +- Links and docs that referred to `site/wrangler.toml` or `docs/mindmap.html` must be updated when backporting older instructions. diff --git a/docs/architecture.md b/docs/architecture.md index d34ae3bfe8..47da0e37dd 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -256,3 +256,7 @@ ADR 0002: [Building block 12](ADRs/0002-initial-fullsend-design.md#12-coordinato Traceability layer across issue, **Triage**, **Code**, **Review**, checks, and merge for incident response and correlation across automation runs. ADR 0002: [Building block 13](ADRs/0002-initial-fullsend-design.md#13-observability). + +## Repository layout (design workspace vs. web delivery) + +The repository combines design documents, Go CLI code, and a small **public web** surface. **Decided:** Browser-oriented static source and future bundled UI live under **`web/`** (the interactive document graph is `web/public/index.html` at `/`). Cloudflare Wrangler configuration and deploy-time static assets live under **`cloudflare_site/`** (single `wrangler.toml`; CI stages **`_bundle/`** on the deploy runner and copies only **`public/`** and **`worker/`** from the artifact into that tree so **`wrangler.toml` is never taken from the PR-built zip**). See [ADR 0019](ADRs/0019-web-source-and-cloudflare-site-layout.md). diff --git a/docs/site-deployment.md b/docs/site-deployment.md index 13dbbd05c8..f04e074630 100644 --- a/docs/site-deployment.md +++ b/docs/site-deployment.md @@ -2,18 +2,18 @@ ## Overview -This repository publishes a static documentation site built from `docs/mindmap.html` (copied to `_site/index.html` in CI, then deployed from `site/public/`). Deployment uses **Cloudflare Workers with [static assets](https://developers.cloudflare.com/workers/static-assets/)** (not the legacy **Pages direct-upload** / `wrangler pages deploy` flow). +This repository publishes a static documentation site whose root page is built from [`web/public/index.html`](../web/public/index.html). **Build Site** packs **`public/`** (static files) and **`worker/`** (TypeScript Worker from the same checkout—PR head on PR builds) under **`_bundle/`** in one artifact. **Deploy Site** checks out **only the default branch** (trusted [`cloudflare_site/wrangler.toml`](../cloudflare_site/wrangler.toml); never PR-controlled config on the secret-bearing runner), downloads the artifact to **`_bundle/`**, then **copies only** **`_bundle/public/`** and **`_bundle/worker/`** into **`cloudflare_site/`** (so a malicious artifact cannot overwrite `wrangler.toml` or other repo files), then runs Wrangler. Deployment uses **Cloudflare Workers with [static assets](https://developers.cloudflare.com/workers/static-assets/)** (not the legacy **Pages direct-upload** / `wrangler pages deploy` flow). Two GitHub Actions workflows: -- **Build Site** — on `pull_request` and `push` to `main`, checks out the PR head when relevant, builds `_site/`, uploads artifact **`site`**. -- **Deploy Site** — on successful **Build Site** via `workflow_run`, checks out the repo (for [`site/wrangler.toml`](../site/wrangler.toml)), downloads the artifact into `site/public/`, then: +- **Build Site** — on `pull_request` and `push` to `main`, checks out the PR head when relevant, assembles **`_bundle/public/`** and **`_bundle/worker/`**, uploads artifact **`site`** (`_bundle/` contents). +- **Deploy Site** — on successful **Build Site** via `workflow_run`, checks out the repo default ref (trusted Wrangler project files), downloads artifact **`site`** into **`_bundle/`**, copies **`public/`** and **`worker/`** into **`cloudflare_site/`**, then: - **push to `main`:** `wrangler deploy` → production Worker traffic. - **pull_request:** `wrangler versions upload --preview-alias pr-` → preview URL on `*.workers.dev` without changing production (alias falls back to `pr-` only when the same fork branch matches more than one open PR). GitHub **Deployments** use environments **`site-preview`** and **`site-production`**; PRs also get a single upserted comment with the preview link. -For architecture and naming, see [2026-04-09-site-cloudflare-pages-design.md](superpowers/specs/2026-04-09-site-cloudflare-pages-design.md) (document filename still says “pages” for history; content describes Workers). +For architecture and naming, see [2026-04-09-site-cloudflare-pages-design.md](superpowers/specs/2026-04-09-site-cloudflare-pages-design.md) (document filename still says “pages” for history; content describes Workers). Repository layout for `web/` vs `cloudflare_site/` is decided in [ADR 0019](ADRs/0019-web-source-and-cloudflare-site-layout.md). ## Cloudflare setup @@ -64,8 +64,8 @@ Disable **GitHub Pages** under **Settings → Pages** if it was only used for th From the repository root: ```bash -mkdir -p site/public && cp docs/mindmap.html site/public/index.html -cd site && npx wrangler@4 dev +mkdir -p cloudflare_site/public && cp web/public/index.html cloudflare_site/public/index.html +cd cloudflare_site && npx wrangler@4 dev ``` Requires a Cloudflare login or API token in the environment per [Wrangler docs](https://developers.cloudflare.com/workers/wrangler/). diff --git a/docs/superpowers/plans/2026-04-09-site-cloudflare-pages.md b/docs/superpowers/plans/2026-04-09-site-cloudflare-pages.md index 24e179a5f8..e74c11b094 100644 --- a/docs/superpowers/plans/2026-04-09-site-cloudflare-pages.md +++ b/docs/superpowers/plans/2026-04-09-site-cloudflare-pages.md @@ -4,7 +4,7 @@ **Goal:** Replace GitHub Pages with **Cloudflare Workers static assets** (production + per-PR previews), using a secretless **Build Site** workflow plus a **`workflow_run` Deploy Site** workflow with Cloudflare + GitHub Deployment credentials, **`site-preview` / `site-production`**, and an upserted PR comment. Naming uses **site** throughout (workflows, artifact); the mindmap is the current `index.html` source only. -**Architecture:** **`Build Site`** runs on `pull_request` and `push` to `main`, checks out the PR head on PRs, produces `_site/`, uploads artifact **`site`**. **`Deploy Site`** checks out the repo (for `site/wrangler.toml`), downloads the artifact into **`site/public/`**, runs **`wrangler deploy`** on **`push`** and **`wrangler versions upload --preview-alias pr-`** (falls back to `workflow_run.id` only when multiple open PRs share the same head) on **`pull_request`** (Wrangler **4.30.0** via `cloudflare/wrangler-action@v3.14.1` + `wranglerVersion`), resolves a **`workers.dev`** URL for GitHub, then `actions/github-script` records Deployments and comments. +**Architecture:** **`Build Site`** runs on `pull_request` and `push` to `main`, checks out the PR head on PRs, produces artifact **`site`** with **`_bundle/public/`** + **`_bundle/worker/`** (Worker from that checkout). **`Deploy Site`** checks out the **default branch** (trusted `wrangler.toml` only), downloads the artifact to **`_bundle/`**, copies only **`public/`** and **`worker/`** into **`cloudflare_site/`**, runs **`wrangler deploy`** on **`push`** and **`wrangler versions upload --preview-alias pr-`** on **`pull_request`** (Wrangler **4.30.0** via `cloudflare/wrangler-action@v3.14.1` + `wranglerVersion`), resolves a **`workers.dev`** URL for GitHub, then `actions/github-script` records Deployments and comments. **Tech Stack:** GitHub Actions, Cloudflare **Workers** (static assets), Wrangler **4.x**, `cloudflare/wrangler-action@v3.14.1`, `actions/github-script@v8`, REST Deployments API. @@ -17,9 +17,9 @@ | File | Role | |------|------| | `.github/workflows/site-build.yml` | Secretless build + artifact `site` | -| `.github/workflows/site-deploy.yml` | Checkout + artifact → `site/public/`, `wrangler deploy` / `versions upload`, GitHub Deployment + PR comment | -| `site/wrangler.toml` | Worker name placeholder, `assets.directory = public`, SPA `not_found_handling`, `preview_urls` | -| `site/public/.gitkeep` | Keeps `public/` in git; CI overwrites with artifact contents | +| `.github/workflows/site-deploy.yml` | Default-branch checkout + artifact → `_bundle/`, then copy only `public/` + `worker/` into `cloudflare_site/`; `wrangler deploy` / `versions upload`, GitHub Deployment + PR comment | +| `cloudflare_site/wrangler.toml` | Worker name placeholder, `assets.directory = public`, SPA `not_found_handling`, `preview_urls` | +| `cloudflare_site/public/.gitkeep` | Keeps `public/` in git; CI overwrites with artifact contents | | `.github/workflows/mindmap.yml` | **Removed** (replaced by `site-build.yml` / `site-deploy.yml`) | | `docs/site-deployment.md` | Operator runbook: Worker, token scopes (Workers Edit), secrets/variables, fork policy, troubleshooting | @@ -58,15 +58,17 @@ jobs: with: ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} - - name: Prepare site + - name: Prepare deploy bundle run: | - mkdir -p _site - cp docs/mindmap.html _site/index.html + set -euo pipefail + mkdir -p _bundle/public _bundle/worker + cp web/public/index.html _bundle/public/index.html + cp -a cloudflare_site/worker/. _bundle/worker/ - uses: actions/upload-artifact@v4 with: name: site - path: _site/ + path: _bundle/ retention-days: 5 ``` @@ -91,10 +93,10 @@ The job must only run for successful runs of **this repository’s** **Build Sit **Behavior (Workers, not Pages):** -1. `actions/checkout` (so `site/wrangler.toml` exists). -2. Download artifact **`site`** into **`site/public/`**. +1. `actions/checkout` on the default branch (so trusted `cloudflare_site/wrangler.toml` exists; deploy does not clone the PR). +2. Download artifact **`site`** into **`_bundle/`**, then copy only **`public/`** and **`worker/`** into **`cloudflare_site/`** (so the zip cannot overwrite `wrangler.toml`). 3. **`push`:** `cloudflare/wrangler-action` with `wranglerVersion: "4.30.0"`, `workingDirectory: site`, `command: deploy --name=`. -4. **`pull_request`:** same action with `command: versions upload --name= --preview-alias pr-` (asset config from `site/wrangler.toml` only; alias falls back to `pr-` if the head matches multiple open PRs). +4. **`pull_request`:** same action with `command: versions upload --name= --preview-alias pr-` (asset config from `cloudflare_site/wrangler.toml` only; alias falls back to `pr-` if the head matches multiple open PRs). 5. **Resolve URL:** `deployment-url` output, else parse stdout/stderr for `workers.dev`. 6. **`actions/github-script`:** GitHub Deployments + PR comment; `description: Cloudflare Workers (static assets)`. @@ -105,7 +107,7 @@ Copy the full YAML from the repository file [`.github/workflows/site-deploy.yml` - [ ] **Step 2: Commit** ```bash -git add .github/workflows/site-deploy.yml site/wrangler.toml site/public/.gitkeep +git add .github/workflows/site-deploy.yml cloudflare_site/wrangler.toml cloudflare_site/public/.gitkeep git commit -m "ci: deploy site with Workers static assets" ``` @@ -178,7 +180,7 @@ git commit -m "docs: add documentation site Cloudflare operator runbook" - [ ] **Step 1: Configure Cloudflare + GitHub** per `docs/site-deployment.md` on your fork. -- [ ] **Step 2: Push a commit on `main` that touches `docs/mindmap.html`** +- [ ] **Step 2: Push a commit on `main` that touches `web/public/index.html`** (document graph; formerly `docs/mindmap.html`) Expected: **`Build Site`** succeeds; **`Deploy Site`** runs; Cloudflare **production Worker** updates; GitHub shows **`site-production`** with `environment_url` on **`workers.dev`** (or your custom host). @@ -186,7 +188,7 @@ Expected: **`Build Site`** succeeds; **`Deploy Site`** runs; Cloudflare **produc Expected: **`wrangler versions upload`** preview; **`site-preview`** deployment; one PR comment updated on reruns. -- [ ] **Step 4: Open a PR from a second GitHub user / fork** (or your own fork of your fork) changing `docs/mindmap.html`** +- [ ] **Step 4: Open a PR from a second GitHub user / fork** (or your own fork of your fork) changing `web/public/index.html` Expected: build succeeds on the base repo without Cloudflare secrets in fork logs; deploy + comment still occur from the base repo’s deploy workflow. diff --git a/docs/superpowers/specs/2026-04-09-site-cloudflare-pages-design.md b/docs/superpowers/specs/2026-04-09-site-cloudflare-pages-design.md index 84e5eaf9c8..38ba8b9fd8 100644 --- a/docs/superpowers/specs/2026-04-09-site-cloudflare-pages-design.md +++ b/docs/superpowers/specs/2026-04-09-site-cloudflare-pages-design.md @@ -7,7 +7,7 @@ Status: Draft (brainstorm consolidated) ## Context -The repository publishes a **static documentation site**. Today the primary surface is the interactive document graph in `docs/mindmap.html`; the site will likely **grow** (more pages or assets under `docs/` or a dedicated static tree). CI treats this as **one deployable site**: produce a directory (today `_site/` with `index.html` from the mindmap), upload it as artifact **`site`**, then deploy from **`site/public/`** using Wrangler and [`site/wrangler.toml`](../../../site/wrangler.toml). +The repository publishes a **static documentation site**. Today the primary surface is the interactive document graph in [`web/public/index.html`](../../../web/public/index.html); the site will likely **grow** (more pages or a Vite-built tree under `web/`). CI packs **`_bundle/public/`** (static) plus **`_bundle/worker/`** (from the build checkout) into artifact **`site`**. **Deploy** checks out the **default branch** only (trusted [`cloudflare_site/wrangler.toml`](../../../cloudflare_site/wrangler.toml)), downloads the artifact to **`_bundle/`**, copies **only** **`public/`** and **`worker/`** into **`cloudflare_site/`** (rejecting any other top-level paths so **`wrangler.toml` cannot be injected from the zip**), then runs Wrangler. **Implemented:** [`.github/workflows/site-build.yml`](../../../.github/workflows/site-build.yml) and [`.github/workflows/site-deploy.yml`](../../../.github/workflows/site-deploy.yml) use the build → artifact → `workflow_run` deploy split. **Production** uses **`wrangler deploy`** (Worker + static assets). **Pull requests** use **`wrangler versions upload --preview-alias …`** so previews get a stable **`*.workers.dev`** URL without promoting a new production version. The previous GitHub Pages workflow has been **removed**. @@ -42,19 +42,19 @@ The repository publishes a **static documentation site**. Today the primary surf ### Workflow split -1. **Build (`site-build.yml`):** `pull_request` + `push` to `main` (no `paths` filter in current fork—runs on every PR/push; may be narrowed later). Produces **`site`** artifact (`_site/`). -2. **Deploy (`site-deploy.yml`):** On successful **Build Site**, checkout (for `site/wrangler.toml`), download artifact into **`site/public/`**, then: +1. **Build (`site-build.yml`):** `pull_request` + `push` to `main` (no `paths` filter in current fork—runs on every PR/push; may be narrowed later). Produces **`site`** artifact with **`_bundle/public/`** and **`_bundle/worker/`** (Worker sources from the build checkout). +2. **Deploy (`site-deploy.yml`):** On successful **Build Site**, checkout **default branch** (trusted `wrangler.toml` only), download artifact to **`_bundle/`**, copy **`public/`** + **`worker/`** into **`cloudflare_site/`** (only those subtrees; no wholesale extract into the Wrangler project root), then: - **`push`:** `wrangler deploy --name=` → production. - **`pull_request`:** `wrangler versions upload` (asset config from `wrangler.toml` only) with `--preview-alias pr-` (falls back to `workflow_run.id` only when multiple open PRs share the same head) → preview only. **Permissions:** Build: `contents: read` only. Deploy: `actions: read`, `deployments: write`, `pull-requests: write`. No `pages: write` for this site. -### `site/wrangler.toml` +### `cloudflare_site/wrangler.toml` - **`[assets].directory`:** `./public` (filled in CI). - **`not_found_handling = "single-page-application"`** for the single-page mindmap. - **`workers_dev = true`**, **`preview_urls = true`**. -- **No `main`** (assets-only Worker). +- **`main = "worker/src/index.ts"`** — minimal pass-through to `ASSETS` today; future OAuth/API logic extends this file without changing deploy wiring. ### GitHub environment names diff --git a/site/wrangler.toml b/site/wrangler.toml deleted file mode 100644 index e7bcedf80a..0000000000 --- a/site/wrangler.toml +++ /dev/null @@ -1,12 +0,0 @@ -# Cloudflare Worker serving static assets only (no user Worker script). -# The deploy workflow passes --name to match your account Worker name (GitHub variable CLOUDFLARE_PROJECT_NAME). -# See: https://developers.cloudflare.com/workers/static-assets/ - -name = "documentation-site" -compatibility_date = "2026-04-09" -workers_dev = true -preview_urls = true - -[assets] -directory = "./public" -not_found_handling = "single-page-application" diff --git a/web/README.md b/web/README.md new file mode 100644 index 0000000000..641b2c4f31 --- /dev/null +++ b/web/README.md @@ -0,0 +1,3 @@ +# Web + +Browser-delivered assets for the public site: static files under `public/` today (document graph as `index.html`), with a future single Vite app expected to build into deployable output that CI merges into `_site/` for Cloudflare. **`package.json` / `npm run dev` stay at the repository root** (Vite can still use this tree as its source root). Wrangler configuration and the Worker live only under [`../cloudflare_site/`](../cloudflare_site/). diff --git a/docs/mindmap.html b/web/public/index.html similarity index 100% rename from docs/mindmap.html rename to web/public/index.html From 0f47cbb1b269d0ea32f9aa185576b26dd223b35e Mon Sep 17 00:00:00 2001 From: Barak Korren Date: Thu, 16 Apr 2026 00:27:36 +0300 Subject: [PATCH 2/2] docs: align ADR 0019 and web/README with _bundle/ staging Fix _site/ typos (waynesun09 review). Clarify Deploy Site applies artifact via _bundle/ and selective copy; decision 3 uses _bundle/. Made-with: Cursor --- docs/ADRs/0019-web-source-and-cloudflare-site-layout.md | 6 +++--- web/README.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/ADRs/0019-web-source-and-cloudflare-site-layout.md b/docs/ADRs/0019-web-source-and-cloudflare-site-layout.md index ab4ad00982..30631ee446 100644 --- a/docs/ADRs/0019-web-source-and-cloudflare-site-layout.md +++ b/docs/ADRs/0019-web-source-and-cloudflare-site-layout.md @@ -24,12 +24,12 @@ This repository mixes design documents, Go CLI code (`cmd/`), and a small **brow ## Decision 1. **Browser-oriented source** (static HTML today; future Vite entrypoints and assets) lives under **`web/`**, starting with the document graph as **`web/public/index.html`** (served at `/` in production). **Node tooling** (`package.json`, lockfile, and scripts such as `npm run dev` / `npm run build`) stays at the **repository root** so day-to-day work does not require `cd web`; Vite config may still point `root` at `web/` (or a subdirectory) for resolution. -2. The **sole Wrangler project** in this repository lives under **`cloudflare_site/`** (`wrangler.toml`, `public/` populated by CI from the Build Site artifact, plus any future Worker source in that tree). The GitHub Actions **Deploy Site** workflow continues to use **`workingDirectory: cloudflare_site`** and unpacks the artifact into **`cloudflare_site/public/`**; workflow **names** (`Build Site`, artifact `site`, environments `site-preview` / `site-production`) stay stable for existing automation and operators. -3. **Build Site** assembles **`_site/`** from `web/` (and later from JS build outputs) without changing that deploy contract. +2. The **sole Wrangler project** in this repository lives under **`cloudflare_site/`** (`wrangler.toml` from the default-branch checkout on deploy, plus **`public/`** and **`worker/`** filled from the Build Site artifact). The GitHub Actions **Deploy Site** workflow continues to use **`workingDirectory: cloudflare_site`**, downloads the artifact to **`_bundle/`**, and copies only **`public/`** and **`worker/`** into **`cloudflare_site/`**; workflow **names** (`Build Site`, artifact `site`, environments `site-preview` / `site-production`) stay stable for existing automation and operators. +3. **Build Site** assembles **`_bundle/`** from `web/` (and later from JS build outputs) without changing that deploy contract. ## Consequences - Contributors edit the live mindmap at **`web/public/index.html`** instead of **`docs/mindmap.html`**. - Paths in runbooks and local Wrangler preview use **`cloudflare_site/`** instead of **`site/`**. -- Future SPA work adds **Vite** (and related devDependencies) using the **root** `package.json`, with source and config under **`web/`**, and extends **`site-build.yml`** to merge build output into **`_site/`** without renaming **`cloudflare_site/`** again. +- Future SPA work adds **Vite** (and related devDependencies) using the **root** `package.json`, with source and config under **`web/`**, and extends **`site-build.yml`** to merge build output into **`_bundle/public/`** (and keep **`_bundle/worker/`** in sync) without renaming **`cloudflare_site/`** again. - Links and docs that referred to `site/wrangler.toml` or `docs/mindmap.html` must be updated when backporting older instructions. diff --git a/web/README.md b/web/README.md index 641b2c4f31..39bc5125c4 100644 --- a/web/README.md +++ b/web/README.md @@ -1,3 +1,3 @@ # Web -Browser-delivered assets for the public site: static files under `public/` today (document graph as `index.html`), with a future single Vite app expected to build into deployable output that CI merges into `_site/` for Cloudflare. **`package.json` / `npm run dev` stay at the repository root** (Vite can still use this tree as its source root). Wrangler configuration and the Worker live only under [`../cloudflare_site/`](../cloudflare_site/). +Browser-delivered assets for the public site: static files under `public/` today (document graph as `index.html`), with a future single Vite app expected to build into output that CI stages under **`_bundle/`** for the **Build Site** artifact. **`package.json` / `npm run dev` stay at the repository root** (Vite can still use this tree as its source root). Wrangler configuration and the Worker live only under [`../cloudflare_site/`](../cloudflare_site/).