From e35a133c9190d50d6055165eda848c80f22b644f Mon Sep 17 00:00:00 2001 From: SarthakWade Date: Thu, 27 Aug 2026 22:45:34 +0530 Subject: [PATCH 1/6] ci(web): codify Vercel deployment --- AGENTS.md | 12 +++- apps/web/package.json | 2 +- .../scripts/validate-deployment-config.mjs | 48 ++++++++++++++ docs/DEPLOYMENT.md | 63 +++++++++++++++++++ docs/ROADMAP.md | 5 +- docs/roadmap/improvements-backlog.md | 14 ++--- vercel.json | 8 +++ 7 files changed, 140 insertions(+), 12 deletions(-) create mode 100644 apps/web/scripts/validate-deployment-config.mjs create mode 100644 docs/DEPLOYMENT.md create mode 100644 vercel.json diff --git a/AGENTS.md b/AGENTS.md index e2e28a0..8923fd0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,7 +23,7 @@ Read before making non-trivial changes: check items off when you fix them and add the named test. - `CONTRIBUTING.md` — the same rules for humans, plus setup detail. - `SECURITY.md` — the boundaries a bug report is measured against. -- To *use* Headless as a browser tool (rather than develop it), follow the +- To _use_ Headless as a browser tool (rather than develop it), follow the skill: `.agents/skills/headless-computer-use/SKILL.md`. ## Layout @@ -130,3 +130,13 @@ Tags `v*` trigger `.github/workflows/release.yml` (macOS zip + Linux tarballs). `HEADLESS_VERSION` flows from the tag; protocol version (`"0.5"` in `Protocol.swift`) is independent — bump it only for wire-visible changes, with a decision entry. + +## Website deployment + +Vercel deploys `apps/web` from the repository root using +[`vercel.json`](vercel.json). The production branch is `main`, and the +canonical production URL is . Keep the +Vercel for GitHub integration enabled for pull-request previews and preview-URL +comments. Do not add a second deployment workflow that can race the integration. +Hosting setup, verification, rollback, and the custom-domain decision are in +[`docs/DEPLOYMENT.md`](docs/DEPLOYMENT.md). diff --git a/apps/web/package.json b/apps/web/package.json index 2b30b09..17df122 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -6,7 +6,7 @@ "dev": "next dev", "build": "next build", "start": "next start", - "lint": "node scripts/validate-harness-onboarding.mjs && node scripts/validate-content-provenance.mjs && eslint .", + "lint": "node scripts/validate-harness-onboarding.mjs && node scripts/validate-content-provenance.mjs && node scripts/validate-deployment-config.mjs && eslint .", "brand": "node scripts/render-brand.mjs" }, "dependencies": { diff --git a/apps/web/scripts/validate-deployment-config.mjs b/apps/web/scripts/validate-deployment-config.mjs new file mode 100644 index 0000000..82d4ae2 --- /dev/null +++ b/apps/web/scripts/validate-deployment-config.mjs @@ -0,0 +1,48 @@ +import assert from "node:assert/strict"; +import { readFile } from "node:fs/promises"; +import { resolve } from "node:path"; + +const root = resolve(import.meta.dirname, "../../.."); +const read = (path) => readFile(resolve(root, path), "utf8"); +const config = JSON.parse(await read("vercel.json")); + +assert.deepEqual(config, { + $schema: "https://openapi.vercel.sh/vercel.json", + framework: "nextjs", + installCommand: "pnpm install --frozen-lockfile --filter @headless/web", + buildCommand: "pnpm --filter @headless/web build", + devCommand: "pnpm --filter @headless/web dev", + outputDirectory: "apps/web/.next", +}); + +const productionUrl = "https://headless-web-pi.vercel.app"; +const [metadata, deploymentDocs, agentRules, nextConfig] = await Promise.all([ + read("apps/web/lib/site-metadata.ts"), + read("docs/DEPLOYMENT.md"), + read("AGENTS.md"), + read("apps/web/next.config.ts"), +]); + +for (const source of [metadata, deploymentDocs, agentRules]) { + assert.match(source, new RegExp(productionUrl.replaceAll(".", "\\."))); +} + +assert.doesNotMatch(JSON.stringify(config), /headers|contentSecurityPolicy/i); +for (const header of [ + "Content-Security-Policy", + "Permissions-Policy", + "Referrer-Policy", + "X-Content-Type-Options", + "X-Frame-Options", +]) { + assert.match(nextConfig, new RegExp(`key: "${header}"`)); +} +for (const directive of [ + "base-uri 'none'", + "frame-ancestors 'none'", + "object-src 'none'", +]) { + assert.match(nextConfig, new RegExp(directive.replaceAll("'", "\\'"))); +} + +console.log("Vercel deployment configuration is consistent"); diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md new file mode 100644 index 0000000..5f9af99 --- /dev/null +++ b/docs/DEPLOYMENT.md @@ -0,0 +1,63 @@ +# Website deployment + +The marketing and documentation site is deployed to Vercel from this monorepo. +The repository configuration in [`vercel.json`](../vercel.json) is the source +of truth for framework detection, dependency installation, build command, local +development command, and output location. + +## Production contract + +- **Production branch:** `main`. +- **Production URL:** . +- **Project root:** the repository root, not `apps/web`. +- **Application:** `apps/web` (`@headless/web`). +- **Security headers:** `apps/web/next.config.ts`. Do not duplicate them in + `vercel.json`, where they could drift from local and CI builds. + +The Vercel project alias is the canonical domain for now. The LockInTime +organization does not publish a verifiable custom domain in repository or +organization metadata, so this project must not claim one. A custom domain can +replace the alias only after a maintainer confirms control of its DNS. That +change must update `apps/web/lib/site-metadata.ts`, the GitHub repository +homepage, this document, and the Vercel production-domain assignment together. + +## GitHub integration + +Connect the `LockInTime/headless` repository through Vercel for GitHub with +these project settings: + +1. Leave Root Directory empty so Vercel reads the root `vercel.json` and the + workspace lockfile. +2. Set the production branch to `main`. +3. Keep preview deployments enabled for pull requests and branch pushes. +4. Keep pull-request comments enabled so each PR receives its immutable preview + URL. Keep deployment status events enabled so the URL also appears in the + GitHub deployment timeline. +5. Do not add a second token-driven GitHub Actions deployment. Two independent + deployers can race production aliases and make rollback history ambiguous. + +The integration is an account-level control and cannot be stored in git. If a +PR has no Vercel deployment or preview link, treat that as a disconnected or +disabled integration. A Vercel project maintainer must reconnect the repository +under Project Settings, Git before the PR is considered deployment-verified. + +## Verification + +Run the same web gates locally before pushing: + +```sh +pnpm install --frozen-lockfile --filter @headless/web +pnpm --filter @headless/web lint +pnpm --filter @headless/web build +``` + +For a pull request, open the Vercel preview from the PR deployment entry and +check the homepage, one docs route, `robots.txt`, and `sitemap.xml`. Confirm the +response still carries the CSP, `X-Content-Type-Options`, `X-Frame-Options`, +`Referrer-Policy`, and `Permissions-Policy` headers declared in +`apps/web/next.config.ts`. + +After merging, verify that the production deployment points at the merge commit +and that serves it. Vercel keeps prior +production deployments available for rollback. Roll back in Vercel, then +revert the faulty commit in git so repository history and production converge. diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 2dc8f6a..2f25ceb 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -103,7 +103,7 @@ summary|outline|text|actions|full`, `--task`, `--within @rN`, `--budget`) notarization/stapling, a checksum-pinned Homebrew cask, the verified Linux bootstrap, release checksums, and a multi-platform GHCR image. These paths become user-visible with the next tag. -- A Next.js marketing/docs site (`apps/web`) — built, not deployed. +- A Next.js marketing/docs site (`apps/web`) deployed to Vercel from `main`. - An agent skill (`.agents/skills/headless-computer-use/`) with safety rules, command reference, and a Docker sandbox wrapper. @@ -265,7 +265,8 @@ and drive Headless with zero manual prompting beyond repo checkout. ### Phase 5 — Website and docs as a product surface -- Deploy `apps/web` (Vercel or static export + CDN) with CI. +- Keep the Vercel deployment of `apps/web` reproducible, previewable, and + verified alongside CI. - Kill the three-copy content drift: docs prose and benchmark numbers come from single sources (benchmark emits JSON; site imports it; command tables generated from the CLI) (backlog §F). diff --git a/docs/roadmap/improvements-backlog.md b/docs/roadmap/improvements-backlog.md index 568afa4..d08b4f5 100644 --- a/docs/roadmap/improvements-backlog.md +++ b/docs/roadmap/improvements-backlog.md @@ -408,14 +408,12 @@ Owner-decided scope: package managers, no hosted service. ## §F — Website & docs (Phase 5) -- **F1. Deploy pipeline is invisible to the repo** ([#47](https://github.com/LockInTime/headless/issues/47)) — the site _is_ live at - `https://headless-web-pi.vercel.app` (set as the repo homepage) via Vercel's - GitHub integration, but nothing in the tree records that: no `vercel.json`, - no deploy docs, no preview-URL comment on PRs, and the temporary - `*-pi.vercel.app` hostname suggests no custom domain. Make the deployment - reproducible and reviewable — check in the project config, document the - hosting in `AGENTS.md`, and decide on a domain. Keep the existing headers/CSP - in `next.config.ts`; consider a nonce so `unsafe-inline` can be dropped. +- **F1. Deploy pipeline is invisible to the repo:** [x] ([#47](https://github.com/LockInTime/headless/issues/47)) ~~The live Vercel project had no checked-in build config, hosting + runbook, preview contract, or explicit domain decision.~~ **Done:** root + deployment settings are versioned and linted, the GitHub preview and rollback + contract is documented, security headers remain in Next.js, and the proven + Vercel project alias is canonical until the organization publishes a + controlled custom domain. - **F2. Content provenance** ([#48](https://github.com/LockInTime/headless/issues/48)) — ~~benchmark numbers hand-copied in `app/page.tsx:26-38`, `components/efficiency-chart.tsx:26-31`, `components/benchmark-chart.tsx:21-26` (+ date in two places); docs prose diff --git a/vercel.json b/vercel.json new file mode 100644 index 0000000..d9d7338 --- /dev/null +++ b/vercel.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://openapi.vercel.sh/vercel.json", + "framework": "nextjs", + "installCommand": "pnpm install --frozen-lockfile --filter @headless/web", + "buildCommand": "pnpm --filter @headless/web build", + "devCommand": "pnpm --filter @headless/web dev", + "outputDirectory": "apps/web/.next" +} From 45a275ed45123d89585a86d2a7a563fed38b9394 Mon Sep 17 00:00:00 2001 From: SarthakWade Date: Thu, 27 Aug 2026 22:46:13 +0530 Subject: [PATCH 2/6] docs: keep deployment verification pending --- docs/roadmap/improvements-backlog.md | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/docs/roadmap/improvements-backlog.md b/docs/roadmap/improvements-backlog.md index d08b4f5..33afb03 100644 --- a/docs/roadmap/improvements-backlog.md +++ b/docs/roadmap/improvements-backlog.md @@ -408,12 +408,7 @@ Owner-decided scope: package managers, no hosted service. ## §F — Website & docs (Phase 5) -- **F1. Deploy pipeline is invisible to the repo:** [x] ([#47](https://github.com/LockInTime/headless/issues/47)) ~~The live Vercel project had no checked-in build config, hosting - runbook, preview contract, or explicit domain decision.~~ **Done:** root - deployment settings are versioned and linted, the GitHub preview and rollback - contract is documented, security headers remain in Next.js, and the proven - Vercel project alias is canonical until the organization publishes a - controlled custom domain. +- **F1. Deploy pipeline is invisible to the repo** ([#47](https://github.com/LockInTime/headless/issues/47)) — **Repository side ready:** root deployment settings are versioned and linted, the GitHub preview and rollback contract is documented, security headers remain in Next.js, and the proven Vercel project alias is canonical until the organization publishes a controlled custom domain. **Pending account verification:** reconnect the Vercel for GitHub integration and confirm a PR preview plus a `main` production deployment before checking this item off. - **F2. Content provenance** ([#48](https://github.com/LockInTime/headless/issues/48)) — ~~benchmark numbers hand-copied in `app/page.tsx:26-38`, `components/efficiency-chart.tsx:26-31`, `components/benchmark-chart.tsx:21-26` (+ date in two places); docs prose From 7c9dc0e304213a5536a19d634ae48117328936a9 Mon Sep 17 00:00:00 2001 From: Aditya Garud <153842990+yashranaway@users.noreply.github.com> Date: Thu, 27 Aug 2026 18:48:56 +0000 Subject: [PATCH 3/6] fix(web): correct Vercel package and port handling --- AGENTS.md | 2 +- .../scripts/validate-deployment-config.mjs | 24 ++++++++++++------- docs/DEPLOYMENT.md | 6 +++-- docs/ROADMAP.md | 5 ++-- vercel.json | 3 +-- 5 files changed, 24 insertions(+), 16 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 8923fd0..05020f7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,7 +23,7 @@ Read before making non-trivial changes: check items off when you fix them and add the named test. - `CONTRIBUTING.md` — the same rules for humans, plus setup detail. - `SECURITY.md` — the boundaries a bug report is measured against. -- To _use_ Headless as a browser tool (rather than develop it), follow the +- To *use* Headless as a browser tool (rather than develop it), follow the skill: `.agents/skills/headless-computer-use/SKILL.md`. ## Layout diff --git a/apps/web/scripts/validate-deployment-config.mjs b/apps/web/scripts/validate-deployment-config.mjs index 82d4ae2..0a80bad 100644 --- a/apps/web/scripts/validate-deployment-config.mjs +++ b/apps/web/scripts/validate-deployment-config.mjs @@ -9,19 +9,27 @@ const config = JSON.parse(await read("vercel.json")); assert.deepEqual(config, { $schema: "https://openapi.vercel.sh/vercel.json", framework: "nextjs", - installCommand: "pnpm install --frozen-lockfile --filter @headless/web", buildCommand: "pnpm --filter @headless/web build", - devCommand: "pnpm --filter @headless/web dev", + devCommand: "pnpm --filter @headless/web exec next dev --port $PORT", outputDirectory: "apps/web/.next", }); const productionUrl = "https://headless-web-pi.vercel.app"; -const [metadata, deploymentDocs, agentRules, nextConfig] = await Promise.all([ - read("apps/web/lib/site-metadata.ts"), - read("docs/DEPLOYMENT.md"), - read("AGENTS.md"), - read("apps/web/next.config.ts"), -]); +const [metadata, deploymentDocs, agentRules, nextConfig, rootPackage, lockfile] = + await Promise.all([ + read("apps/web/lib/site-metadata.ts"), + read("docs/DEPLOYMENT.md"), + read("AGENTS.md"), + read("apps/web/next.config.ts"), + read("package.json"), + read("pnpm-lock.yaml"), + ]); + +const packageJson = JSON.parse(rootPackage); +assert.match(packageJson.packageManager ?? "", /^pnpm@9\./); +assert.match(packageJson.engines?.pnpm ?? "", />=9/); +assert.match(lockfile, /^lockfileVersion: ['"]?9\.0['"]?$/m); +assert.equal(config.installCommand, undefined); for (const source of [metadata, deploymentDocs, agentRules]) { assert.match(source, new RegExp(productionUrl.replaceAll(".", "\\."))); diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md index 5f9af99..df216fb 100644 --- a/docs/DEPLOYMENT.md +++ b/docs/DEPLOYMENT.md @@ -2,8 +2,10 @@ The marketing and documentation site is deployed to Vercel from this monorepo. The repository configuration in [`vercel.json`](../vercel.json) is the source -of truth for framework detection, dependency installation, build command, local -development command, and output location. +of truth for framework detection, build and development commands, and output +location. Vercel derives pnpm from the root lockfile. Do not add an install +override with plain `pnpm install`: Vercel uses its oldest available pnpm +runtime for that override, while this repository requires pnpm 9 or newer. ## Production contract diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index 2f25ceb..a50a16e 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -118,9 +118,8 @@ summary|outline|text|actions|full`, `--task`, `--within @rN`, `--budget`) unimplemented. - The latest features (capture formats, context pruning) are **unreleased** — no tag since v1.0.2 (2026-07-19). -- No `CLAUDE.md`/`AGENTS.md`; the skill is not auto-discovered by Claude Code. -- The website's benchmark numbers, docs prose, and commands are hand-copied in - three places each and will drift; the site has no deploy pipeline. +- The website deployment configuration is versioned, but GitHub-to-Vercel + preview and production deployments remain unverified. - Windows is not supported. - A list of real code defects (thread-safety on shutdown, oversized `qa report` responses, `@eN` ref invalidation surprises, host code duplication) diff --git a/vercel.json b/vercel.json index d9d7338..923de4b 100644 --- a/vercel.json +++ b/vercel.json @@ -1,8 +1,7 @@ { "$schema": "https://openapi.vercel.sh/vercel.json", "framework": "nextjs", - "installCommand": "pnpm install --frozen-lockfile --filter @headless/web", "buildCommand": "pnpm --filter @headless/web build", - "devCommand": "pnpm --filter @headless/web dev", + "devCommand": "pnpm --filter @headless/web exec next dev --port $PORT", "outputDirectory": "apps/web/.next" } From e7df8c8736df3473e272d0536f7b48793c844f28 Mon Sep 17 00:00:00 2001 From: SarthakWade Date: Thu, 10 Sep 2026 22:18:37 +0530 Subject: [PATCH 4/6] style(web): format deployment validation files --- AGENTS.md | 2 +- .../scripts/validate-deployment-config.mjs | 24 ++++++++++++------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 4a1174c..a1112ee 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,7 +23,7 @@ Read before making non-trivial changes: check items off when you fix them and add the named test. - `CONTRIBUTING.md` — the same rules for humans, plus setup detail. - `SECURITY.md` — the boundaries a bug report is measured against. -- To *use* Headless as a browser tool (rather than develop it), follow the +- To _use_ Headless as a browser tool (rather than develop it), follow the skill: `.agents/skills/headless-computer-use/SKILL.md`. ## Layout diff --git a/apps/web/scripts/validate-deployment-config.mjs b/apps/web/scripts/validate-deployment-config.mjs index 0a80bad..71cf417 100644 --- a/apps/web/scripts/validate-deployment-config.mjs +++ b/apps/web/scripts/validate-deployment-config.mjs @@ -15,15 +15,21 @@ assert.deepEqual(config, { }); const productionUrl = "https://headless-web-pi.vercel.app"; -const [metadata, deploymentDocs, agentRules, nextConfig, rootPackage, lockfile] = - await Promise.all([ - read("apps/web/lib/site-metadata.ts"), - read("docs/DEPLOYMENT.md"), - read("AGENTS.md"), - read("apps/web/next.config.ts"), - read("package.json"), - read("pnpm-lock.yaml"), - ]); +const [ + metadata, + deploymentDocs, + agentRules, + nextConfig, + rootPackage, + lockfile, +] = await Promise.all([ + read("apps/web/lib/site-metadata.ts"), + read("docs/DEPLOYMENT.md"), + read("AGENTS.md"), + read("apps/web/next.config.ts"), + read("package.json"), + read("pnpm-lock.yaml"), +]); const packageJson = JSON.parse(rootPackage); assert.match(packageJson.packageManager ?? "", /^pnpm@9\./); From dc4a03316ef4ba923d81959e55da4784f7199492 Mon Sep 17 00:00:00 2001 From: SarthakWade Date: Thu, 10 Sep 2026 23:37:28 +0530 Subject: [PATCH 5/6] fix(web): align Vercel config with app root --- .gitignore | 5 ++++ AGENTS.md | 11 +++---- .../scripts/validate-deployment-config.mjs | 27 +++++++++-------- apps/web/vercel.json | 7 +++++ docs/DEPLOYMENT.md | 30 +++++++++++-------- vercel.json | 7 ----- 6 files changed, 50 insertions(+), 37 deletions(-) create mode 100644 apps/web/vercel.json delete mode 100644 vercel.json diff --git a/.gitignore b/.gitignore index c51ee79..47112b4 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,8 @@ build/qa-evidence/ # Rust build artifacts apps/headless-rs/target/ + +# Local Vercel state and environment secrets +.vercel/ +.env.local +.env.*.local diff --git a/AGENTS.md b/AGENTS.md index a1112ee..49a70ee 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -132,10 +132,11 @@ with a decision entry. ## Website deployment -Vercel deploys `apps/web` from the repository root using -[`vercel.json`](vercel.json). The production branch is `main`, and the -canonical production URL is . Keep the -Vercel for GitHub integration enabled for pull-request previews and preview-URL -comments. Do not add a second deployment workflow that can race the integration. +Vercel deploys `apps/web` with that directory configured as the project root, +using [`apps/web/vercel.json`](apps/web/vercel.json). The production branch is +`main`, and the canonical production URL is +. Keep the Vercel for GitHub integration +enabled for pull-request previews and preview-URL comments. Do not add a second +deployment workflow that can race the integration. Hosting setup, verification, rollback, and the custom-domain decision are in [`docs/DEPLOYMENT.md`](docs/DEPLOYMENT.md). diff --git a/apps/web/scripts/validate-deployment-config.mjs b/apps/web/scripts/validate-deployment-config.mjs index 71cf417..9d1d676 100644 --- a/apps/web/scripts/validate-deployment-config.mjs +++ b/apps/web/scripts/validate-deployment-config.mjs @@ -2,16 +2,19 @@ import assert from "node:assert/strict"; import { readFile } from "node:fs/promises"; import { resolve } from "node:path"; -const root = resolve(import.meta.dirname, "../../.."); -const read = (path) => readFile(resolve(root, path), "utf8"); -const config = JSON.parse(await read("vercel.json")); +const repositoryRoot = resolve(import.meta.dirname, "../../.."); +const webRoot = resolve(repositoryRoot, "apps/web"); +const readRepositoryFile = (path) => + readFile(resolve(repositoryRoot, path), "utf8"); +const readWebFile = (path) => readFile(resolve(webRoot, path), "utf8"); +const config = JSON.parse(await readWebFile("vercel.json")); assert.deepEqual(config, { $schema: "https://openapi.vercel.sh/vercel.json", framework: "nextjs", - buildCommand: "pnpm --filter @headless/web build", - devCommand: "pnpm --filter @headless/web exec next dev --port $PORT", - outputDirectory: "apps/web/.next", + buildCommand: "pnpm build", + devCommand: "pnpm exec next dev --port $PORT", + outputDirectory: ".next", }); const productionUrl = "https://headless-web-pi.vercel.app"; @@ -23,12 +26,12 @@ const [ rootPackage, lockfile, ] = await Promise.all([ - read("apps/web/lib/site-metadata.ts"), - read("docs/DEPLOYMENT.md"), - read("AGENTS.md"), - read("apps/web/next.config.ts"), - read("package.json"), - read("pnpm-lock.yaml"), + readWebFile("lib/site-metadata.ts"), + readRepositoryFile("docs/DEPLOYMENT.md"), + readRepositoryFile("AGENTS.md"), + readWebFile("next.config.ts"), + readRepositoryFile("package.json"), + readRepositoryFile("pnpm-lock.yaml"), ]); const packageJson = JSON.parse(rootPackage); diff --git a/apps/web/vercel.json b/apps/web/vercel.json new file mode 100644 index 0000000..8e852cc --- /dev/null +++ b/apps/web/vercel.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://openapi.vercel.sh/vercel.json", + "framework": "nextjs", + "buildCommand": "pnpm build", + "devCommand": "pnpm exec next dev --port $PORT", + "outputDirectory": ".next" +} diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md index df216fb..442e41e 100644 --- a/docs/DEPLOYMENT.md +++ b/docs/DEPLOYMENT.md @@ -1,18 +1,19 @@ # Website deployment The marketing and documentation site is deployed to Vercel from this monorepo. -The repository configuration in [`vercel.json`](../vercel.json) is the source -of truth for framework detection, build and development commands, and output -location. Vercel derives pnpm from the root lockfile. Do not add an install -override with plain `pnpm install`: Vercel uses its oldest available pnpm -runtime for that override, while this repository requires pnpm 9 or newer. +The application configuration in +[`apps/web/vercel.json`](../apps/web/vercel.json) is the source of truth for +framework detection, build and development commands, and output location. +Vercel derives pnpm from the repository lockfile. Do not add an install override +with plain `pnpm install`: Vercel uses its oldest available pnpm runtime for that +override, while this repository requires pnpm 9 or newer. ## Production contract - **Production branch:** `main`. - **Production URL:** . -- **Project root:** the repository root, not `apps/web`. -- **Application:** `apps/web` (`@headless/web`). +- **Project root:** `apps/web`. +- **Application:** `@headless/web`. - **Security headers:** `apps/web/next.config.ts`. Do not duplicate them in `vercel.json`, where they could drift from local and CI builds. @@ -28,14 +29,17 @@ homepage, this document, and the Vercel production-domain assignment together. Connect the `LockInTime/headless` repository through Vercel for GitHub with these project settings: -1. Leave Root Directory empty so Vercel reads the root `vercel.json` and the - workspace lockfile. -2. Set the production branch to `main`. -3. Keep preview deployments enabled for pull requests and branch pushes. -4. Keep pull-request comments enabled so each PR receives its immutable preview +1. Set Root Directory to `apps/web` so Vercel reads the application-local + `vercel.json` and detects Next.js from the application package. +2. Enable "Include source files outside of the Root Directory in the Build + Step". The site imports checked-in documentation and package metadata from + the repository root, `apps/headless`, and `packages` during its build. +3. Set the production branch to `main`. +4. Keep preview deployments enabled for pull requests and branch pushes. +5. Keep pull-request comments enabled so each PR receives its immutable preview URL. Keep deployment status events enabled so the URL also appears in the GitHub deployment timeline. -5. Do not add a second token-driven GitHub Actions deployment. Two independent +6. Do not add a second token-driven GitHub Actions deployment. Two independent deployers can race production aliases and make rollback history ambiguous. The integration is an account-level control and cannot be stored in git. If a diff --git a/vercel.json b/vercel.json deleted file mode 100644 index 923de4b..0000000 --- a/vercel.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "$schema": "https://openapi.vercel.sh/vercel.json", - "framework": "nextjs", - "buildCommand": "pnpm --filter @headless/web build", - "devCommand": "pnpm --filter @headless/web exec next dev --port $PORT", - "outputDirectory": "apps/web/.next" -} From 0eb2093f4199ad21d68a8f0b9f9fcbd04e00ae0c Mon Sep 17 00:00:00 2001 From: SarthakWade Date: Thu, 10 Sep 2026 23:44:47 +0530 Subject: [PATCH 6/6] docs: record verified Vercel deployment --- docs/ROADMAP.md | 2 -- docs/roadmap/improvements-backlog.md | 7 ++++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md index a50a16e..fe76ffb 100644 --- a/docs/ROADMAP.md +++ b/docs/ROADMAP.md @@ -118,8 +118,6 @@ summary|outline|text|actions|full`, `--task`, `--within @rN`, `--budget`) unimplemented. - The latest features (capture formats, context pruning) are **unreleased** — no tag since v1.0.2 (2026-07-19). -- The website deployment configuration is versioned, but GitHub-to-Vercel - preview and production deployments remain unverified. - Windows is not supported. - A list of real code defects (thread-safety on shutdown, oversized `qa report` responses, `@eN` ref invalidation surprises, host code duplication) diff --git a/docs/roadmap/improvements-backlog.md b/docs/roadmap/improvements-backlog.md index cc7f536..fa9aceb 100644 --- a/docs/roadmap/improvements-backlog.md +++ b/docs/roadmap/improvements-backlog.md @@ -408,7 +408,12 @@ Owner-decided scope: package managers, no hosted service. ## §F — Website & docs (Phase 5) -- **F1. Deploy pipeline is invisible to the repo** ([#47](https://github.com/LockInTime/headless/issues/47)) — **Repository side ready:** root deployment settings are versioned and linted, the GitHub preview and rollback contract is documented, security headers remain in Next.js, and the proven Vercel project alias is canonical until the organization publishes a controlled custom domain. **Pending account verification:** reconnect the Vercel for GitHub integration and confirm a PR preview plus a `main` production deployment before checking this item off. +- **F1.** [x] ([#47](https://github.com/LockInTime/headless/issues/47)) + The Vercel deployment is repo-visible and verified. Application-local + settings are versioned and linted, the preview and rollback contract is + documented, security headers remain in Next.js, and a Git-backed pull-request + preview was verified before merge. The proven Vercel project alias remains + canonical until the organization publishes a controlled custom domain. - **F2. Content provenance** ([#48](https://github.com/LockInTime/headless/issues/48)) — ~~benchmark numbers hand-copied in `app/page.tsx:26-38`, `components/efficiency-chart.tsx:26-31`, `components/benchmark-chart.tsx:21-26` (+ date in two places); docs prose