From 4bb1e9471825311c31df516e87f33876697fc016 Mon Sep 17 00:00:00 2001 From: Javid Date: Thu, 6 Aug 2026 11:51:34 +0200 Subject: [PATCH 1/8] Use canonical production build script --- .github/workflows/deploy-pages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-pages.yml b/.github/workflows/deploy-pages.yml index 2a90aa2..784af9a 100644 --- a/.github/workflows/deploy-pages.yml +++ b/.github/workflows/deploy-pages.yml @@ -31,7 +31,7 @@ jobs: restore-keys: | ${{ runner.os }}-next-${{ hashFiles('package-lock.json') }}- - run: npm ci - - run: npm run build:github + - run: npm run build env: NEXT_TELEMETRY_DISABLED: 1 - uses: actions/upload-pages-artifact@v3 From 3ebd2ce1f51e97e397d3b98856632429efae405c Mon Sep 17 00:00:00 2001 From: Javid Date: Thu, 6 Aug 2026 11:51:35 +0200 Subject: [PATCH 2/8] Make GitHub Pages build the supported default --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index e298118..20852df 100644 --- a/package.json +++ b/package.json @@ -6,14 +6,14 @@ "node": ">=22.13.0" }, "scripts": { - "install:ci": "bash scripts/install-ci.sh", "dev": "next dev", - "build": "bash scripts/build-verified.sh", - "build:github": "next build", - "start": "WRANGLER_LOG_PATH=.wrangler/wrangler.log vinext start", + "build": "next build", "test": "npm run build && node --test tests/rendered-html.test.mjs", "validate:artifact": "bash scripts/validate-artifact.sh", "lint": "bash scripts/sites-env.sh -- eslint . --ignore-pattern dist --ignore-pattern .next", + "build:sites": "bash scripts/build-verified.sh", + "start:sites": "WRANGLER_LOG_PATH=.wrangler/wrangler.log vinext start", + "install:sites": "bash scripts/install-ci.sh", "db:generate": "bash scripts/sites-env.sh -- drizzle-kit generate" }, "dependencies": { From 127e0f023a596e824f773d69551b57e5b83d3eca Mon Sep 17 00:00:00 2001 From: Javid Date: Thu, 6 Aug 2026 11:51:37 +0200 Subject: [PATCH 3/8] Document supported website deployment path --- README.md | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 53184c7..8ad7acd 100644 --- a/README.md +++ b/README.md @@ -1,43 +1,38 @@ # CoreLink Platform Website -Official website for [CoreLink Platform](https://corelinkplatform.ir): connected-product infrastructure for devices, applications, and digital services. +Official website for [CoreLink Platform](https://corelinkplatform.ir). -## Stack +## Supported production path -- Next.js 16 / React 19 / TypeScript -- Static export (`output: "export"`) -- GitHub Actions deployment to GitHub Pages -- No runtime server or database dependency +**GitHub Pages is the only supported production deployment path.** + +- Runtime: static export from Next.js 16 / React 19 / TypeScript. +- Build: `npm ci && npm run build`. +- Artifact: `out/`. +- Deployment: `.github/workflows/deploy-pages.yml` on `main`. +- Production has no application server or database dependency. + +See [DEPLOYMENT.md](DEPLOYMENT.md) for release evidence and rollback. ## Local development ```bash npm ci npm run dev +npm run build ``` -## Verify the GitHub Pages build - -```bash -npm run build:github -``` - -The deployable static site is generated in `out/`. - -## GitHub Pages deployment - -The workflow at `.github/workflows/deploy-pages.yml` builds and deploys every push to `main`. - -In the GitHub repository settings: +## Internal preview tooling -1. Open **Settings → Pages**. -2. Set **Source** to **GitHub Actions**. -3. Ensure the custom domain is `corelinkplatform.ir`. -4. Point the domain DNS records to GitHub Pages, then enable **Enforce HTTPS** after verification. +The `*:sites` scripts and their Vinext/Wrangler/Vite/Cloudflare dependencies are +retained only for internal preview/tooling experiments. They are **not** a +supported CoreLink production deployment path and must not be used as release +evidence for this website. ## Public developer resources - [API Contracts](https://github.com/CoreLinkPlatform/api-contracts) +- [TypeScript SDK](https://github.com/CoreLinkPlatform/sdk-typescript) - [Python SDK](https://github.com/CoreLinkPlatform/sdk-python) - [Java SDK](https://github.com/CoreLinkPlatform/sdk-java) - [CLI](https://github.com/CoreLinkPlatform/cli) From 7f75f9165e9ac268e8709fcb490c3887970afc75 Mon Sep 17 00:00:00 2001 From: Javid Date: Thu, 6 Aug 2026 11:51:39 +0200 Subject: [PATCH 4/8] Document website deployment and rollback --- DEPLOYMENT.md | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 DEPLOYMENT.md diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md new file mode 100644 index 0000000..bdce216 --- /dev/null +++ b/DEPLOYMENT.md @@ -0,0 +1,46 @@ +# Website deployment + +## Decision + +The supported production target for `corelinkplatform.ir` is **GitHub Pages**. +The site is a static Next.js export. No Cloudflare/Vinext/Wrangler runtime is +part of the production contract. + +## Reproducible build + +From a clean checkout with Node 22.13 or newer: + +```bash +npm ci +npm run build +test -d out +``` + +The GitHub Actions workflow performs the same build and uploads `out/`. A +release is evidenced by the successful `Deploy to GitHub Pages` run for the +exact `main` commit. + +## Ownership and release checks + +Web Experience owns site content/build correctness. SRE and Release owns the +production deployment/rollback procedure. + +Before accepting a website release: + +1. build the exact commit with `npm ci && npm run build`; +2. run repository checks; +3. review public maturity/device/SDK claims against repository/runtime evidence; +4. merge through review; +5. retain the successful GitHub Pages run URL and deployed commit. + +## Rollback + +Revert the offending `main` change through Git, then let the same GitHub Pages +workflow deploy the reverted commit. Record the bad release commit and the +successful rollback deployment run. Do not manually edit the Pages artifact. + +## Internal tooling boundary + +`npm run build:sites`, `npm run start:sites`, and `npm run install:sites` +are internal preview experiments. They are unsupported production alternatives +and their success does not satisfy WEB-01 deployment acceptance. From 1c0a43de60d0ba02089e65b38d21e266650fe217 Mon Sep 17 00:00:00 2001 From: Javid Date: Thu, 6 Aug 2026 11:56:01 +0200 Subject: [PATCH 5/8] Validate supported website build --- .github/workflows/ci.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..2528810 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,24 @@ +name: Website CI + +on: + pull_request: + push: + branches: [main] + +permissions: + contents: read + +jobs: + build-and-test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + - run: npm ci + - run: npm run lint + - run: npm test + env: + NEXT_TELEMETRY_DISABLED: 1 From 242cee83cd7470fad34ffb84d28070711714f019 Mon Sep 17 00:00:00 2001 From: Javid Date: Thu, 6 Aug 2026 14:52:24 +0200 Subject: [PATCH 6/8] Test canonical static production artifact --- tests/rendered-html.test.mjs | 31 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/tests/rendered-html.test.mjs b/tests/rendered-html.test.mjs index 5392f9f..9010442 100644 --- a/tests/rendered-html.test.mjs +++ b/tests/rendered-html.test.mjs @@ -1,33 +1,14 @@ import assert from "node:assert/strict"; +import { readFile } from "node:fs/promises"; import test from "node:test"; const developmentPreviewMeta = /]*\bname=["']codex-preview["'])(?=[^>]*\bcontent=["']development["'])[^>]*>/i; -test("renders development preview metadata", async () => { - const workerUrl = new URL("../dist/server/index.js", import.meta.url); - workerUrl.searchParams.set("test", `${process.pid}-${Date.now()}`); - const { default: worker } = await import(workerUrl.href); +test("renders production static HTML metadata", async () => { + const html = await readFile(new URL("../out/index.html", import.meta.url), "utf8"); - const response = await worker.fetch( - new Request("http://localhost/", { - headers: { accept: "text/html" }, - }), - { - ASSETS: { - fetch: async () => new Response("Not found", { status: 404 }), - }, - }, - { - waitUntil() {}, - passThroughOnException() {}, - }, - ); - - assert.equal(response.status, 200); - assert.match( - response.headers.get("content-type") ?? "", - /^text\/html\b/i, - ); - assert.match(await response.text(), developmentPreviewMeta); + assert.match(html, /]*\blang=["']fa["'])(?=[^>]*\bdir=["']rtl["'])[^>]*>/i); + assert.match(html, /CoreLink Platform \| زیرساخت محصولات متصل<\/title>/i); + assert.match(html, developmentPreviewMeta); }); From 10707f5a9e722982cf775689692680a3fb2e16de Mon Sep 17 00:00:00 2001 From: Javid <javid.momeni@gmail.com> Date: Thu, 6 Aug 2026 14:52:25 +0200 Subject: [PATCH 7/8] Preserve internal Sites worker validation --- tests/sites-worker.test.mjs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 tests/sites-worker.test.mjs diff --git a/tests/sites-worker.test.mjs b/tests/sites-worker.test.mjs new file mode 100644 index 0000000..8526bcc --- /dev/null +++ b/tests/sites-worker.test.mjs @@ -0,0 +1,33 @@ +import assert from "node:assert/strict"; +import test from "node:test"; + +const developmentPreviewMeta = + /<meta(?=[^>]*\bname=["']codex-preview["'])(?=[^>]*\bcontent=["']development["'])[^>]*>/i; + +test("renders development preview metadata through Sites worker", async () => { + const workerUrl = new URL("../dist/server/index.js", import.meta.url); + workerUrl.searchParams.set("test", `${process.pid}-${Date.now()}`); + const { default: worker } = await import(workerUrl.href); + + const response = await worker.fetch( + new Request("http://localhost/", { + headers: { accept: "text/html" }, + }), + { + ASSETS: { + fetch: async () => new Response("Not found", { status: 404 }), + }, + }, + { + waitUntil() {}, + passThroughOnException() {}, + }, + ); + + assert.equal(response.status, 200); + assert.match( + response.headers.get("content-type") ?? "", + /^text\/html\b/i, + ); + assert.match(await response.text(), developmentPreviewMeta); +}); From e7ca896ff338c0dda8eec162c46148d0e2dcc8b9 Mon Sep 17 00:00:00 2001 From: Javid <javid.momeni@gmail.com> Date: Thu, 6 Aug 2026 14:52:28 +0200 Subject: [PATCH 8/8] Separate production and internal Sites tests --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 20852df..0c5c99b 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "dev": "next dev", "build": "next build", "test": "npm run build && node --test tests/rendered-html.test.mjs", + "test:sites": "npm run build:sites && node --test tests/sites-worker.test.mjs", "validate:artifact": "bash scripts/validate-artifact.sh", "lint": "bash scripts/sites-env.sh -- eslint . --ignore-pattern dist --ignore-pattern .next", "build:sites": "bash scripts/build-verified.sh",