> For the complete documentation index, see [llms.txt](https://ai-os-and-trend-finder.gitbook.io/ai-os-and-trend-finder-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ai-os-and-trend-finder.gitbook.io/ai-os-and-trend-finder-docs/.spec_system/archive/sessions/phase31-session05-pages-build-and-deployment-scaffold/spec.md).

# Session Specification

**Session ID**: `phase31-session05-pages-build-and-deployment-scaffold` **Phase**: 31 - Cloudflare Pages Public Demo **Status**: Not Started **Created**: 2026-06-24

***

## 1. Session Overview

This session produces the reproducible static artifact boundary for the AI OS public demo. Sessions 01 through 04 made public-demo mode, committed fixtures, frozen app data, and route-level no-bridge behavior available; this session turns those pieces into a Cloudflare Pages-ready output under `demo-website/dist`.

The next concrete gap is deployment scaffolding rather than more route behavior. The current demo-pages Vite branch writes generated output to `demo-website/dist`, but the observed ignored output contains TanStack `client/` and `server/` trees and lacks a top-level `index.html`. Cloudflare Pages needs a static directory rooted at `demo-website/dist` with `index.html`, `_redirects`, `_headers`, and committed `/demo/*` assets available from the deploy root.

The implementation should keep the existing Cloudflare Worker build independent. The Pages path must not run the local-only snapshot exporter during Cloudflare builds, must not migrate root `wrangler.jsonc`, and must leave route-matrix smoke tests and privacy scans for Session 06.

***

## 2. Objectives

1. Add reproducible `demo:build:pages` and `demo:preview:pages` commands for the static public demo.
2. Assemble `demo-website/dist` as a Pages-rooted static directory with a top-level `index.html`.
3. Include `_redirects`, `_headers`, and committed `demo-website/public/demo/*` fixtures in final output.
4. Document Cloudflare Pages Git settings, direct upload behavior, and the separation from the Worker deployment path.

***

## 3. Prerequisites

### Required Sessions

* [x] `phase31-session01-demo-mode-foundation` - Provides public-demo mode, static TanStack output branch, and extension visibility behavior.
* [x] `phase31-session02-snapshot-exporter-and-fixtures` - Provides committed browser-safe fixtures under `demo-website/public/demo/*` and local-only `demo:snapshot`.
* [x] `phase31-session03-app-data-and-mutation-boundary` - Provides frozen app data loading and hosted mutation guards.
* [x] `phase31-session04-extensions-and-agent-routes` - Provides public-demo-safe agent, Knowledge Graph, Trend Finder, and AI Rogue route behavior.

### Required Tools Or Knowledge

* Bun 1.3.14.
* Vite 8 and TanStack Start demo-pages output shape.
* Wrangler 4.92.0 for `wrangler pages dev` and direct upload documentation.
* Cloudflare Pages static redirects and headers file conventions.

### Environment Requirements

* Repository root working directory.
* No Cloudflare Pages project name is required for build scaffold work.
* Direct upload can be documented with an operator-supplied `<pages-project-name>`.

***

## 4. Scope

### In Scope (MVP)

* AI OS operator can run `bun run demo:build:pages` - Build demo-pages mode and assemble `demo-website/dist` into a static Pages root.
* AI OS operator can run `bun run demo:preview:pages` - Build and serve the static output through Wrangler Pages dev, not Vite middleware.
* Cloudflare Pages can route client-side paths - Add `demo-website/public/_redirects` with the SPA fallback.
* Cloudflare Pages can apply conservative static-site headers - Add `demo-website/public/_headers` with security and cache headers.
* Public demo output contains committed fixtures - Copy `demo-website/public/demo/*` into final `demo-website/dist/demo/*`.
* Public demo docs explain deployment - Update `demo-website/README.md` with root directory, build command, output directory, branch, `BUN_VERSION=1.3.14`, direct upload command, and Worker separation.

### Out Of Scope (Deferred)

* Pages Functions or advanced `_worker.js` mode - Reason: Phase 31 v1 is static-only and `_redirects` or `_headers` behavior changes under Functions.
* Root `wrangler.jsonc` Pages migration - Reason: Existing Worker deployment remains the main app deployment contract.
* Full route matrix smoke tests and no `/__*` network assertions - Reason: Session 06 owns QA and privacy verification.
* Fixture and generated-output privacy scans - Reason: Session 06 owns scans against committed fixtures and `demo-website/dist`.
* Release polish, provenance UI, mobile review, and deployment docs under `docs/deployment.md` - Reason: Session 07 owns release polish after the build path is proven.
* Committing `demo-website/dist` - Reason: It is generated output and already ignored.

***

## 5. Technical Approach

### Architecture

Use the existing demo-pages Vite branch to produce the application bundle in `demo-website/dist`, then run a small deterministic assembly step that promotes the static client output to the Pages deploy root, removes server-only output from the static artifact, copies `demo-website/public/*` into the deploy root, and verifies the resulting file layout.

The assembly logic belongs in `scripts/lib/pages-demo-build.ts` with a thin CLI in `scripts/demo/assemble-pages-dist.ts`. Keeping filesystem behavior in a library makes it testable without running Vite. The package script can then compose Vite and the assembly CLI without changing the Worker build path:

```
VITE_AI_OS_PUBLIC_DEMO=1 VITE_CLAUDE_OS_ENABLED_EXTENSIONS=all vite build --mode demo-pages && bun run scripts/demo/assemble-pages-dist.ts
```

### Design Patterns

* Tested script library: Filesystem assembly behavior is covered by Vitest in `scripts/lib/__tests__/`.
* Generated output boundary: `demo-website/dist` remains ignored and reproducible from committed source plus fixtures.
* Static fixture boundary: Pages builds consume committed `demo-website/public/demo/*` and never run `demo:snapshot`.
* Worker/Pages separation: Root `wrangler.jsonc` and `worker:deploy` remain unchanged.

***

## 6. Deliverables

### Files To Create

| File                                             | Purpose                                                                  | Est. Lines |
| ------------------------------------------------ | ------------------------------------------------------------------------ | ---------- |
| `demo-website/public/_redirects`                 | Cloudflare Pages SPA fallback to `/index.html`.                          | \~1        |
| `demo-website/public/_headers`                   | Static-site security and cache headers for app assets and demo fixtures. | \~12       |
| `scripts/lib/pages-demo-build.ts`                | Testable assembly and verification helpers for `demo-website/dist`.      | \~180      |
| `scripts/demo/assemble-pages-dist.ts`            | Thin Bun CLI wrapper around the assembly helpers.                        | \~45       |
| `scripts/lib/__tests__/pages-demo-build.test.ts` | Unit coverage for Pages output assembly and failure paths.               | \~180      |

### Files To Modify

| File                     | Changes                                                                                                     | Est. Lines |
| ------------------------ | ----------------------------------------------------------------------------------------------------------- | ---------- |
| `package.json`           | Add `demo:build:pages` and `demo:preview:pages` scripts without changing Worker scripts.                    | \~4        |
| `demo-website/README.md` | Document Pages build, preview, Git settings, direct upload, static-only constraints, and Worker separation. | \~80       |

***

## 7. Success Criteria

### Functional Requirements

* [ ] `bun run demo:build:pages` creates `demo-website/dist/index.html`.
* [ ] `demo-website/dist` contains `_redirects`, `_headers`, and `demo/live-data.snapshot.json`.
* [ ] Final Pages output contains committed `demo-website/public/demo/graphs/*` and `demo-website/public/demo/snapshot-metadata.json`.
* [ ] Final Pages output does not require Vite middleware or root Worker deployment files.
* [ ] `bun run demo:preview:pages` serves `demo-website/dist` through Wrangler Pages dev.
* [ ] `demo-website/README.md` documents Git deployment settings and direct upload with an operator-supplied Pages project name.
* [ ] Root `wrangler.jsonc`, `worker:preview`, and `worker:deploy` remain independent of the Pages demo path.

### Testing Requirements

* [ ] Unit tests cover successful assembly, missing client index, missing routing/header files, fixture copy, and server output pruning.
* [ ] `bun run test -- scripts/lib/__tests__/pages-demo-build.test.ts` passes.
* [ ] `bun run typecheck:scripts` passes for new script code.
* [ ] Build and output-shape verification commands are run and recorded during implementation.

### Non-Functional Requirements

* [ ] Assembly is deterministic and idempotent across repeated local runs.
* [ ] Failed assembly reports explicit errors and does not silently ship a partial Pages artifact.
* [ ] Static headers stay conservative and analytics-free for v1.
* [ ] Pages docs use placeholders shorter than real key patterns and do not include secrets.

### Quality Gates

* [ ] All files ASCII-encoded.
* [ ] Unix LF line endings.
* [ ] Code follows project conventions.
* [ ] Primary user-facing surfaces contain product-facing copy only.

***

## 8. Implementation Notes

### Working Assumptions

* Build assembly is required: `vite.config.ts` already points demo-pages builds at `demo-website/dist`, and ignored generated output currently has `demo-website/dist/client/index.html` but no `demo-website/dist/index.html`. A post-build assembly step can make the output Pages-rooted without weakening the normal Worker build.
* The Pages build consumes committed fixtures only: `package.json` already has `demo:snapshot`, and Session 02 validation confirms `demo-website/public/demo/*` fixtures and metadata exist. Keeping `demo:snapshot` out of `demo:build:pages` preserves the local-only authoring boundary.

### Conflict Resolutions

* Session 05 folded source lists `demo:snapshot` among package scripts to add, but the current repo already added it in Session 02. Treat it as a completed prerequisite and plan only the new `demo:build:pages` and `demo:preview:pages` scripts.
* The Phase 31 current-state note says no `demo-website/` directory exists, but the current repo has `demo-website/README.md` and committed public demo fixtures from Session 02. Use the current repo state because completed sessions supersede the original audit snapshot.
* The stub proposes a direct Vite command for `demo:build:pages`, but the observed output is not yet a Pages-rooted static directory. Wrap Vite with a tested assembly CLI so the command satisfies the top-level `index.html`, `_redirects`, `_headers`, and `/demo/*` success criteria.

### Key Considerations

* Do not run `demo:snapshot` in the Pages build command.
* Do not add `pages_build_output_dir` to root `wrangler.jsonc`.
* Do not add CI guard work in this session.
* Do not scan or validate every route in this session; Session 06 owns the route matrix and privacy verification.

### Potential Challenges

* TanStack Start output shape may change: Keep assembly checks explicit and fail with actionable messages when expected directories are missing.
* Public files may be copied to the wrong root: Unit tests should assert exact `_headers`, `_redirects`, and `/demo/*` destinations.
* Wrangler Pages dev may be long-running: Implementation notes should record the command start behavior and any local external-configuration constraint without blocking the scaffold.

### Relevant Considerations

* \[P00] **Stack conventions**: Bun, Vite 8, TanStack Start, React 19, and Cloudflare constraints shape the scripts and docs.
* \[P02] **Extension payloads and labels stay bounded**: Final output must preserve explicit demo, fixture, fallback, degraded, blocked, and unavailable labels from committed fixtures.
* \[P21] **Claude OAuth material stays script-only**: Pages build and docs must not expose OAuth, token, account, or bearer material.
* \[P24] **Browser-safe export and triage boundaries**: Pages output copies only committed public fixtures, not raw generated private runtime data.
* \[P30] **Release gates stay bundled**: This session prepares build output, while Session 06 and Session 07 record scans, route coverage, and release gates together.

### Behavioral Quality Focus

Checklist active: Yes Top behavioral risks for this session:

* Filesystem assembly could leave a partial static artifact after failure.
* Package scripts could accidentally run local snapshot authoring in Cloudflare build environments.
* Output verification could pass despite missing routing, headers, or demo fixture files.

***

## 9. Testing Strategy

### Unit Tests

* Test `scripts/lib/pages-demo-build.ts` with temporary directories for successful client promotion, public file copy, server artifact pruning, and required-file validation.
* Test explicit failure messages for missing `client/index.html`, missing `_redirects`, missing `_headers`, and missing demo snapshot files.

### Integration Tests

* Run `bun run demo:build:pages` and inspect `demo-website/dist/index.html`, `demo-website/dist/_redirects`, `demo-website/dist/_headers`, and `demo-website/dist/demo/live-data.snapshot.json`.
* Run `bun run typecheck:scripts` to verify new script types.

### Runtime Verification

* Start `bun run demo:preview:pages` and confirm Wrangler serves the generated static directory without Vite middleware.
* Use file checks to confirm `demo-website/dist` remains generated output and root Worker deployment config remains unchanged.

### Edge Cases

* Re-running the build after an existing `demo-website/dist` exists.
* Missing or malformed static routing/header source files.
* Missing committed demo fixture files.
* Unexpected TanStack server output remaining in the static deploy root.

***

## 10. Dependencies

### Other Sessions

* Depends on: `phase31-session01-demo-mode-foundation`, `phase31-session02-snapshot-exporter-and-fixtures`, `phase31-session03-app-data-and-mutation-boundary`, `phase31-session04-extensions-and-agent-routes`
* Depended by: `phase31-session06-demo-qa-and-privacy-verification`, `phase31-session07-release-polish-and-documentation`

***

## Next Steps

Run the `implement` workflow step to begin 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://ai-os-and-trend-finder.gitbook.io/ai-os-and-trend-finder-docs/.spec_system/archive/sessions/phase31-session05-pages-build-and-deployment-scaffold/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.
