> For the complete documentation index, see [llms.txt](https://faction-os.gitbook.io/faction-os-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://faction-os.gitbook.io/faction-os-docs/.spec_system/archive/sessions/phase16-session04-cloudflare-pages-deployment-path/spec.md).

# Session Specification

**Session ID**: `phase16-session04-cloudflare-pages-deployment-path` **Phase**: 16 - Quality, Deployment, And Launch Handoff **Status**: Complete **Created**: 2026-06-02 **Package**: public-website **Package Stack**: Astro/TypeScript

***

## 1. Session Overview

This session continues Phase 16 by turning the static public website build into a clear Cloudflare Pages deployment path for `https://faction-os.com/`. Sessions 01 through 03 have already hardened responsive behavior, accessibility, performance, images, fonts, and automated static build gates. The remaining gap before launch handoff is deployment readiness for the main website, not another product page or runtime feature.

The repository already has working deployment patterns for the War Room Worker and the synthetic public demo, but `docs/deployment.md` still records the main `public-website` surface as having no production host configured. This session should add a dedicated website deployment path when the repo pattern supports it, document the Cloudflare Pages dashboard settings, preserve a manual Wrangler fallback, and keep credential handling explicit without writing secrets into tracked files.

The website must remain a fully static Astro output deployed from `public-website/dist`. This session must not add `@astrojs/cloudflare`, server rendering, hosted forms, runtime analytics, CMS behavior, auth, or coupling to the `public-demo` artifact. It should make the main website deployable while preserving the public demo URL and external GitBook docs URL as independent destinations.

***

## 2. Objectives

1. Define and document the Cloudflare Pages deployment path for the static `public-website/dist` output.
2. Add a dedicated website deploy workflow if the existing GitHub Actions pattern supports it, with package-scoped gates and credential-safe skipping.
3. Record manual deploy commands, dashboard settings, credential prerequisites, and domain expectations without tracked secrets.
4. Validate the deployment path against static-site boundaries: no adapter, no demo coupling, no analytics, no hosted forms, and no overclaimed production-hosted evidence.

***

## 3. Prerequisites

### Required Sessions

* [x] `phase16-session03-automated-checks-and-build-gates` - provides the website typecheck, build, and deterministic static output gate that this deployment path must run before upload.
* [x] `phase16-session02-performance-and-image-optimization` - confirms the website static output, media, fonts, and no-telemetry posture are launch hardened enough for deployment planning.
* [x] `phase16-session01-responsive-and-accessibility-hardening` - confirms the website has responsive, keyboard, focus, reduced-motion, and semantic hardening for the launch candidate.

### Required Tools/Knowledge

* npm workspaces from the repository root.
* GitHub Actions workflow structure used by `.github/workflows/public-demo-deploy.yml` and `.github/workflows/warroom-deploy.yml`.
* Cloudflare Pages static deploy behavior through Wrangler.
* Existing package scripts in `public-website/package.json`.
* Existing static site checker at `scripts/check-public-website-links.mjs`.
* Static website privacy and no-claim boundaries from `CONSIDERATIONS.md`, `SECURITY-COMPLIANCE.md`, and stable deployment docs.

### Environment Requirements

* Node.js 26.2.0 or newer.
* npm 11.16.0 or compatible workspace support.
* Cloudflare credentials only for live deploys: `CLOUDFLARE_ACCOUNT_ID` and `CLOUDFLARE_API_TOKEN`.
* Optional website-specific repository variables: `CLOUDFLARE_PUBLIC_WEBSITE_PAGES_PROJECT_NAME` and `FACTIONOS_PUBLIC_WEBSITE_URL`.
* No Cloudflare credentials required for local development, local builds, static checks, or credential-skipped CI runs.

***

## 4. Scope

### In Scope (MVP)

* Release operators can find Cloudflare Pages settings for the main website: root directory `public-website`, build command `npm run build`, output directory `dist`, and production domain `https://faction-os.com/`.
* Maintainers can run a package-scoped static gate before deploy: `npm --workspace @factionos/public-website run typecheck`, `npm --workspace @factionos/public-website run build`, and `npm --workspace @factionos/public-website run check:links`.
* GitHub Actions can deploy the main website from `public-website/dist` when Cloudflare credentials are available, with duplicate-run cancellation and a clear skip notice when credentials are absent.
* The deploy path uses a website-specific Pages project default of `factionos-public-website` and does not reuse the public demo Pages project variable by accident.
* Manual deployment instructions include the recommended `wrangler pages deploy` command with commit metadata and no secret values.
* Deployment docs preserve the independent public demo URL `https://demo.faction-os.com/` and public docs URL `https://faction-os.gitbook.io/faction-os-docs`.
* Docs explain that Cloudflare credentials are deploy-only and must not become browser config, local development requirements, or product runtime claims.
* Implementation evidence records whether live deploy and hosted smoke were run, skipped, blocked, or unavailable.

### Out of Scope (Deferred)

* Adding `@astrojs/cloudflare` - *Reason: the first website launch remains a static Astro build with no server adapter.*
* Server actions, sessions, dynamic personalization, form handling, Cloudflare bindings, Workers routes, or runtime APIs - *Reason: this session only ships a static Pages path.*
* Deploying, modifying, or validating the synthetic public demo artifact - *Reason: `public-demo` has its own deployment workflow and URL.*
* Production-hosted validation claims for the app shell, War Room Worker, hosted identity, hosted storage, analytics, public replay, or trusted erasure - *Reason: those are separate claim boundaries.*
* Formal legal, WCAG, security, or privacy certification - *Reason: launch handoff can record review status, but this session does not perform formal certification.*

***

## 5. Technical Approach

### Architecture

Use a dedicated GitHub Actions workflow for the main website rather than extending the public demo workflow. The new workflow should follow the existing repo pattern: checkout, setup Node from `.nvmrc`, `npm ci --no-audit --no-fund`, package-scoped website gates, credential availability check, conditional Wrangler deploy, and a bounded post-deploy smoke only when deployment ran.

The workflow should deploy `public-website/dist` with:

```bash
npx wrangler pages deploy public-website/dist \
  --project-name="${CLOUDFLARE_PUBLIC_WEBSITE_PAGES_PROJECT_NAME}" \
  --branch="${GITHUB_REF_NAME}" \
  --commit-hash="${GITHUB_SHA}" \
  --commit-message="$(git log -1 --pretty=%s)"
```

Use `factionos-public-website` as the default Pages project name and `https://faction-os.com/` as the default smoke URL. Keep project name and smoke URL in website-specific variables so public demo deploy settings cannot drift into the main website path. Credential checks must log only availability and skip reasons, never raw secret values.

Update docs in the same pass so the workflow, manual fallback, dashboard settings, production status, and release gates all describe the same deploy path. The docs should explicitly state that local development, local build checks, and first-release website behavior do not require Cloudflare credentials, analytics, hosted forms, server rendering, auth, or a CMS.

### Design Patterns

* Dedicated deploy surface: Keep the main website deploy workflow independent from the public demo and War Room workflows.
* Credential-safe skip: Treat missing Cloudflare secrets as a skipped deploy, not as a local development failure.
* Static gate before upload: Always run website typecheck, build, and static checker before Wrangler upload.
* Bounded external call: Use timeouts and limited retries for post-deploy homepage checks, with sanitized output only.
* Claim-scoped evidence: Record local static validation separately from live production-hosted validation.

### Technology Stack

* Node.js 26.2.0 or newer.
* npm 11.16.0 workspaces.
* Astro 6.4.2 static output.
* TypeScript 5.9.3.
* Wrangler 4.95.0 from the root dev dependency set.
* GitHub Actions with Cloudflare Pages credentials stored as repository or environment secrets.

***

## 6. Deliverables

### Files to Create

| File                                                                                            | Purpose                                                                             | Est. Lines |
| ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- | ---------- |
| `.github/workflows/public-website-deploy.yml`                                                   | Dedicated Cloudflare Pages deploy workflow for the static main website              | \~100      |
| `.spec_system/specs/phase16-session04-cloudflare-pages-deployment-path/implementation-notes.md` | Command evidence, credential status, docs changes, deploy status, and handoff notes | \~160      |

### Files to Modify

| File                                      | Changes                                                                                                                | Est. Lines |
| ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ---------- |
| `public-website/README_public-website.md` | Sync deployment recommendation, workflow path, manual deploy command, Pages settings, and no-adapter boundary          | \~70       |
| `docs/deployment.md`                      | Update production status, workflow table, credentials, manual fallback, smoke expectations, and demo/docs independence | \~100      |
| `docs/release.md`                         | Add public website deploy gate and claim-scoped launch evidence guidance                                               | \~45       |
| `.github/workflows/README_workflows.md`   | Document the dedicated public website deploy workflow and no-secret rule                                               | \~20       |
| `.spec_system/CONVENTIONS.md`             | Update operations/deploy convention tables for the public website Pages workflow                                       | \~20       |

***

## 7. Success Criteria

### Functional Requirements

* [ ] Cloudflare Pages settings for `faction-os.com` are documented with root directory, build command, output directory, and production domain.
* [ ] A dedicated main website deploy workflow exists or a documented reason explains why a workflow was not added.
* [ ] The workflow runs website typecheck, build, and static checker before any deploy attempt.
* [ ] The workflow deploys `public-website/dist` to the website Pages project when Cloudflare credentials are configured.
* [ ] The workflow skips cleanly with a clear notice when required credentials or project name values are unavailable.
* [ ] The manual `wrangler pages deploy public-website/dist` command is recorded with branch, commit hash, and commit message metadata.
* [ ] Public demo deployment remains independent at `https://demo.faction-os.com/`.
* [ ] Public docs remain an external GitBook destination at `https://faction-os.gitbook.io/faction-os-docs`.
* [ ] No `@astrojs/cloudflare` adapter, server rendering, hosted forms, analytics, auth, CMS, or runtime personalization is added.
* [ ] No tracked file contains Cloudflare account ids, tokens, secret values, dashboard dumps, or credential-bearing URLs.

### Testing Requirements

* [ ] `npm --workspace @factionos/public-website run typecheck` passes.
* [ ] `npm --workspace @factionos/public-website run build` passes.
* [ ] `npm --workspace @factionos/public-website run check:links` passes against the fresh build output.
* [ ] `npm run format:check` passes for workflow and docs changes.
* [ ] `npm run lint` passes for workflow and docs changes.
* [ ] `npm run security:secrets` passes after adding workflow and docs files.
* [ ] Live deploy and post-deploy smoke are either passed or recorded as skipped, blocked, or unavailable without overclaiming production validation.

### Non-Functional Requirements

* [ ] The website stays a fully static Astro Pages deployment.
* [ ] Deployment steps use timeouts, retry bounds, and duplicate-run prevention where external systems are called.
* [ ] Workflow logs and docs use sanitized project labels, hostnames, and status values only.
* [ ] Local development and local validation remain credential-free.
* [ ] Release docs distinguish local static build evidence from live production hosted evidence.

### Quality Gates

* [ ] All files ASCII-encoded.
* [ ] Unix LF line endings.
* [ ] Code follows project conventions.
* [ ] No secrets are written to tracked files.

***

## 8. Implementation Notes

### Key Considerations

* Use website-specific variable names for the Pages project and production URL so the public demo deploy configuration cannot be reused accidentally.
* The deploy workflow can share Cloudflare credentials with other Cloudflare workflows, but those secrets must remain deploy-only and never enter browser config or docs as raw values.
* Keep the old repo-wide `deploy.yml` placeholder wording accurate. It can say dedicated workflows own War Room, public demo, and public website deployment while the app shell still has no production target.
* If Cloudflare credentials are unavailable in the implementation environment, record that as a deploy blocker or skipped live validation, not as a static build failure.

### Potential Challenges

* Credential ambiguity: Use explicit website variable names and defaults, then record owner-required setup without raw values.
* Overclaiming hosted evidence: Separate local static checks from any live `faction-os.com` smoke result in implementation notes and release docs.
* Workflow drift: Update workflow docs and conventions alongside the workflow so operations tables remain current.
* External deploy flakiness: Use a bounded settle/retry window for post-deploy homepage checks and avoid infinite polling.

### Relevant Considerations

* \[P16-public-website] **Launch hardening is still ahead**: This session closes the deployment path while leaving launch evidence and final handoff to Session 05.
* \[P13-public-website] **Static Astro boundary is intentional**: The website stays separate from `apps/web`, `public-demo`, and GitBook docs, with no server adapter, CMS, auth, hosted forms, or analytics by default.
* \[P13-public-website] **Public website external links are explicit**: Demo and docs links remain approved external destinations; runtime third-party services need a separate privacy and security review.
* \[P15-public-website] **Route contract drift is a launch risk**: The static checker must remain part of the deploy gate so route, CTA, metadata, and guarded copy drift is caught before upload.
* \[P08] **Release evidence is claim-scoped**: Local build and deploy workflow readiness must not become production-hosted validation for unrelated surfaces.

### Behavioral Quality Focus

Checklist active: Yes

Top behavioral risks for this session:

* Missing credentials should skip deploy with a clear notice, not fail local validation or leak secret names beyond safe labels.
* Wrangler upload and post-deploy checks call external systems, so they need duplicate-run cancellation, bounded retries, timeouts, and sanitized failure output.
* The workflow must deploy only `public-website/dist`, never `public-demo/` or app-shell artifacts.
* Docs must avoid claiming production validation unless the live deploy and hosted smoke actually run and pass.

***

## 9. Testing Strategy

### Unit Tests

* No new unit tests are expected unless implementation adds a helper script.

### Integration Tests

* Run `npm --workspace @factionos/public-website run typecheck`.
* Run `npm --workspace @factionos/public-website run build`.
* Run `npm --workspace @factionos/public-website run check:links`.
* Run `npm run security:secrets` after workflow and docs changes.

### Manual Testing

* Inspect `.github/workflows/public-website-deploy.yml` for expected triggers, path filters, concurrency, credential checks, package gates, deploy path, and sanitized smoke output.
* Confirm `docs/deployment.md`, `docs/release.md`, `public-website/README_public-website.md`, and workflow docs agree on the same project name, domain, commands, and no-secret posture.
* If credentials are available, run the workflow or manual deploy from an authorized environment and record the result.

### Edge Cases

* Credentials absent in CI should produce a skipped deploy notice after static gates pass.
* Project name variable absent should default to `factionos-public-website`.
* Smoke URL absent should default to `https://faction-os.com/`.
* Smoke URL with query strings, fragments, credentials, non-HTTPS protocol, or localhost should be rejected or documented as invalid before fetch.
* Cloudflare custom domain propagation delay should be handled by bounded retries, not an unbounded wait.

***

## 10. Dependencies

### External Libraries

* Wrangler: root dev dependency, used through `npx wrangler pages deploy`.
* GitHub Actions `actions/checkout@v4`.
* GitHub Actions `actions/setup-node@v4`.

### Other Sessions

* **Depends on**: `phase16-session03-automated-checks-and-build-gates`, `phase16-session02-performance-and-image-optimization`, `phase16-session01-responsive-and-accessibility-hardening`.
* **Depended by**: `phase16-session05-launch-review-and-documentation-handoff`.

***

## Next Steps

Run the implement workflow step to begin AI-led implementation.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://faction-os.gitbook.io/faction-os-docs/.spec_system/archive/sessions/phase16-session04-cloudflare-pages-deployment-path/spec.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
