From c6b37ba1536de6d2bb4cecb96afe1299d21741f8 Mon Sep 17 00:00:00 2001 From: Rocky shi Date: Sat, 10 Oct 2026 01:23:18 +0000 Subject: [PATCH 1/3] docs: publish the documentation site to vextjs.github.io --- .github/workflows/docs.yml | 156 +++++++++++++----- README.md | 28 ++-- package.json | 2 +- .../verify-documentation-contract.mjs | 34 ++-- src/cli/create.ts | 2 +- test/unit/cli/create.test.ts | 6 +- website/docs/en/guide/deployment.md | 12 +- .../en/resources/documentation-data-and-ai.md | 26 +-- website/docs/public/docs-events.schema.json | 2 +- website/docs/public/robots.txt | 2 +- website/docs/zh/guide/deployment.md | 12 +- .../zh/resources/documentation-data-and-ai.md | 26 +-- website/rspress.config.ts | 4 +- .../scripts/generate-machine-artifacts.mjs | 2 +- 14 files changed, 204 insertions(+), 110 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 6c9d7be5..2e489e58 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -3,11 +3,15 @@ # # 触发条件: # - main 的 push-triggered CI 成功后,部署该次 CI 的精确 SHA -# - 手动触发(workflow_dispatch) +# - 在 main 手动触发(workflow_dispatch) # # 流水线结构: # 1. build — 在 website/ 目录安装依赖并执行 rspress build -# 2. deploy — 部署到当前仓库 GitHub Pages: /vextjs/ +# 2. deploy — 推送静态产物到 vextjs/vextjs.github.io 的 main +# 由目标仓库的 branch-source Pages 发布到 https://vextjs.github.io/ +# +# 首次配置:目标仓库初始化 main,Pages 选择 main / (root), +# 添加可写 Deploy Key,并在源码仓库保存 VEXT_DOCS_DEPLOY_KEY。 # # @see website/package.json §scripts # @see https://rspress.dev/guide/start/deploy @@ -23,16 +27,14 @@ on: - main workflow_dispatch: -# 同一分支同时只允许一个部署运行,新运行会取消旧运行 -concurrency: - group: pages-${{ github.event.workflow_run.head_branch || github.ref_name || github.run_id }} - cancel-in-progress: true - -# GitHub Pages 部署所需权限 +# 源码与产物读取使用 GITHUB_TOKEN;目标仓库写入使用专用 SSH Deploy Key。 permissions: contents: read - pages: write - id-token: write + +env: + VEXT_DOCS_BASE: / + VEXT_DOCS_SITE_URL: https://vextjs.github.io + DOCS_PUBLISH_REPOSITORY: vextjs/vextjs.github.io # ── Jobs ───────────────────────────────────────────────────── @@ -45,24 +47,29 @@ jobs: runs-on: ubuntu-latest if: >- ${{ - github.event_name == 'workflow_dispatch' || + (github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') || ( github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'push' && - github.event.workflow_run.head_branch == 'main' + github.event.workflow_run.head_branch == 'main' && + github.event.workflow_run.head_repository.full_name == github.repository ) }} env: DEPLOY_SHA: ${{ github.event.workflow_run.head_sha || github.sha }} + outputs: + deploy_sha: ${{ steps.commit.outputs.sha }} + current: ${{ steps.current.outputs.publish }} steps: - name: Checkout uses: actions/checkout@v7 with: fetch-depth: 0 # 获取完整提交历史,rspress lastUpdated 功能需要 ref: ${{ env.DEPLOY_SHA }} + persist-credentials: false - name: Verify deployment commit - if: github.event_name == 'workflow_run' + id: commit shell: bash run: | ACTUAL_SHA=$(git rev-parse HEAD) @@ -71,14 +78,8 @@ jobs: echo "Checked out SHA: $ACTUAL_SHA" exit 1 fi - echo "Deploying successful CI SHA: $ACTUAL_SHA" - - - name: Resolve deployment target - id: target - shell: bash - run: | - echo "docs_base=/vextjs/" >> "$GITHUB_OUTPUT" - echo "site_url=https://devcodex-labs.github.io/vextjs" >> "$GITHUB_OUTPUT" + echo "sha=$ACTUAL_SHA" >> "$GITHUB_OUTPUT" + echo "Building deployment SHA: $ACTUAL_SHA" - name: Setup Node.js uses: actions/setup-node@v7 @@ -87,9 +88,6 @@ jobs: cache: "npm" cache-dependency-path: website/package-lock.json - - name: Setup GitHub Pages - uses: actions/configure-pages@v6 - - name: Install dependencies working-directory: website run: npm ci @@ -106,47 +104,123 @@ jobs: run: npm run build:publish -- --rollout=final env: NODE_ENV: production - VEXT_DOCS_BASE: ${{ steps.target.outputs.docs_base }} - VEXT_DOCS_SITE_URL: ${{ steps.target.outputs.site_url }} - - name: Rewrite robots sitemap URL + - name: Prepare Pages files shell: bash run: | cat > website/dist/robots.txt <> "$GITHUB_OUTPUT" + else + echo "Skipping superseded build: $DEPLOY_SHA (main is $CURRENT_SHA)" + echo "publish=false" >> "$GITHUB_OUTPUT" + fi - name: Upload docs artifact + if: steps.current.outputs.publish == 'true' uses: actions/upload-artifact@v7 with: name: docs-dist path: website/dist - - - name: Upload artifact - uses: actions/upload-pages-artifact@v5 - with: - path: website/dist + if-no-files-found: error + include-hidden-files: true # ──────────────────────────────────────────────────────────── - # 2a. 部署到当前仓库 GitHub Pages + # 2. 向独立站点仓库推送;目标仓库保留普通提交历史,不强制推送 # ──────────────────────────────────────────────────────────── deploy-pages: - name: Deploy to GitHub Pages + name: Publish to vextjs.github.io runs-on: ubuntu-latest needs: build + if: needs.build.outputs.current == 'true' + + # 只串行化已通过构建且仍对应 main 的发布,不中断正在进行的 Git 推送。 + concurrency: + group: vextjs-docs-production + cancel-in-progress: false environment: name: github-pages - url: ${{ steps.deployment.outputs.page_url }} + url: https://vextjs.github.io/ + + env: + DEPLOY_SHA: ${{ needs.build.outputs.deploy_sha }} steps: - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v5 + - name: Check current main commit + id: current + env: + GH_TOKEN: ${{ github.token }} + shell: bash + run: | + CURRENT_SHA=$(gh api "repos/${GITHUB_REPOSITORY}/git/ref/heads/main" --jq '.object.sha') + if [[ "$CURRENT_SHA" != "$DEPLOY_SHA" ]]; then + echo "Skipping superseded build: $DEPLOY_SHA (main is $CURRENT_SHA)" + echo "publish=false" >> "$GITHUB_OUTPUT" + else + echo "publish=true" >> "$GITHUB_OUTPUT" + fi - - name: Print deployment URL + - name: Verify deployment key + if: steps.current.outputs.publish == 'true' + env: + DOCS_DEPLOY_KEY: ${{ secrets.VEXT_DOCS_DEPLOY_KEY }} + shell: bash run: | - echo "✅ 文档站已部署至: ${{ steps.deployment.outputs.page_url }}" + if [[ -z "$DOCS_DEPLOY_KEY" ]]; then + echo "::error::Set VEXT_DOCS_DEPLOY_KEY to the writable Deploy Key for ${DOCS_PUBLISH_REPOSITORY}." + exit 1 + fi + + - name: Checkout Pages repository + if: steps.current.outputs.publish == 'true' + uses: actions/checkout@v7 + with: + repository: ${{ env.DOCS_PUBLISH_REPOSITORY }} + ref: main + path: site + ssh-key: ${{ secrets.VEXT_DOCS_DEPLOY_KEY }} + + - name: Download verified docs + if: steps.current.outputs.publish == 'true' + uses: actions/download-artifact@v8 + with: + name: docs-dist + path: docs-dist + + - name: Publish verified docs + if: steps.current.outputs.publish == 'true' + shell: bash + run: | + test -f docs-dist/index.html + test -f docs-dist/zh/index.html + test -f docs-dist/docs-manifest.json + test -f docs-dist/sitemap.xml + git -C site rm -r --ignore-unmatch -- . + cp -a docs-dist/. site/ + touch site/.nojekyll + cd site + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git add --all + if git diff --cached --quiet; then + echo "Documentation is already current." + else + git commit -m "docs: publish ${DEPLOY_SHA}" + git push origin HEAD:main + fi + echo "Published to ${DOCS_PUBLISH_REPOSITORY}; Pages will update ${VEXT_DOCS_SITE_URL}/" diff --git a/README.md b/README.md index 98fdfa63..2919b071 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![License: Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![Node.js](https://img.shields.io/badge/Node.js-%5E20.19.0%20%7C%7C%20%3E%3D22.12.0-green.svg)](https://nodejs.org/) [![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue.svg)](https://www.typescriptlang.org/) -[![Docs](https://img.shields.io/badge/docs-devcodex--labs.github.io-informational)](https://devcodex-labs.github.io/vextjs/) +[![Docs](https://img.shields.io/badge/docs-vextjs.github.io-informational)](https://vextjs.github.io/) > **Build AI-assisted APIs and server-rendered React pages in one Node.js application.** @@ -14,7 +14,7 @@ AI-first describes the engineering surface: conventions, scaffolding, typed cont The npm package name is `vextjs`; the CLI binary is `vext`. Requires Node.js **`^20.19.0 || >=22.12.0`**. Cold-start from the registry with **`npx vextjs …`**. After install, use project scripts or local `npx vext`. -**Docs:** https://devcodex-labs.github.io/vextjs/ · **Migration:** [MIGRATION.md](./MIGRATION.md) · **Changelog:** [CHANGELOG.md](./CHANGELOG.md) +**Docs:** https://vextjs.github.io/ · **Migration:** [MIGRATION.md](./MIGRATION.md) · **Changelog:** [CHANGELOG.md](./CHANGELOG.md) --- @@ -174,7 +174,7 @@ VextJS is a strong fit when: VextJS uses **route-native SSR**: `src/routes/**` + `res.render()` provide SSR, normal hydration or pure-HTML `hydration: "none"`, Suspense, opt-in Streaming SSR, same-route navigation, static/revalidate freshness, and local media. It does not currently implement selective/partial hydration, an Islands component model, React Server Components, Server Functions or Actions, partial prerendering (PPR), or third-party bundler plugin ecosystems. Those models require additional execution and asset boundaries; Vext does not claim them until those contracts exist. -Read the exact lifecycle, trade-offs, and exclusions in [Frontend boundaries and roadmap](https://devcodex-labs.github.io/vextjs/frontend/boundaries-and-roadmap). Implementation guides cover [rendering modes](https://devcodex-labs.github.io/vextjs/frontend/rendering-modes), [data flow](https://devcodex-labs.github.io/vextjs/frontend/data-flow), [assets and media](https://devcodex-labs.github.io/vextjs/frontend/static-assets-and-cdn), and the [typed API client](https://devcodex-labs.github.io/vextjs/frontend/api-client-and-contracts). +Read the exact lifecycle, trade-offs, and exclusions in [Frontend boundaries and roadmap](https://vextjs.github.io/frontend/boundaries-and-roadmap). Implementation guides cover [rendering modes](https://vextjs.github.io/frontend/rendering-modes), [data flow](https://vextjs.github.io/frontend/data-flow), [assets and media](https://vextjs.github.io/frontend/static-assets-and-cdn), and the [typed API client](https://vextjs.github.io/frontend/api-client-and-contracts). --- @@ -197,7 +197,7 @@ export default { }; ``` -Benchmark methodology: [Adapter Matrix](https://devcodex-labs.github.io/vextjs/benchmark). It keeps one Vext application fixed and compares the supported adapters; reproduce it with `npm run test:bench` in this repo. +Benchmark methodology: [Adapter Matrix](https://vextjs.github.io/benchmark). It keeps one Vext application fixed and compares the supported adapters; reproduce it with `npm run test:bench` in this repo. --- @@ -235,7 +235,7 @@ built-in defaults → default → {profile} → local (development/test only) Select profile with `vext start --config ` or `VEXT_CONFIG=` (do not rely on baked `process.env.NODE_ENV` after `vext build` for profile selection). -Common fields: `port`, `host`, `adapter`, `logger`, `cors`, `bodyParser`, `rateLimit`, `openapi`, `frontend`, `cache`, `session`, `shutdown`. See the [configuration guide](https://devcodex-labs.github.io/vextjs/guide/configuration) and [configuration reference](https://devcodex-labs.github.io/vextjs/api/config) before changing production behavior. +Common fields: `port`, `host`, `adapter`, `logger`, `cors`, `bodyParser`, `rateLimit`, `openapi`, `frontend`, `cache`, `session`, `shutdown`. See the [configuration guide](https://vextjs.github.io/guide/configuration) and [configuration reference](https://vextjs.github.io/api/config) before changing production behavior. `rateLimit` is disabled by default and installs middleware only when `rateLimit.enabled === true`. Framework SEO is configured under @@ -263,15 +263,15 @@ describe("API", () => { ## Documentation for people and AI assistants -| Resource | URL | -| ------------------------------- | ---------------------------------------------------------------------- | -| Human docs (EN/ZH) | https://devcodex-labs.github.io/vextjs/ | -| Quick start | https://devcodex-labs.github.io/vextjs/guide/quick-start | -| Frontend guide and typed client | https://devcodex-labs.github.io/vextjs/frontend/getting-started | -| Runtime boundaries | https://devcodex-labs.github.io/vextjs/frontend/boundaries-and-roadmap | -| `llms.txt` | https://devcodex-labs.github.io/vextjs/llms.txt | -| `capabilities.json` | https://devcodex-labs.github.io/vextjs/capabilities.json | -| `docs-manifest.json` | https://devcodex-labs.github.io/vextjs/docs-manifest.json | +| Resource | URL | +| ------------------------------- | -------------------------------------------------------- | +| Human docs (EN/ZH) | https://vextjs.github.io/ | +| Quick start | https://vextjs.github.io/guide/quick-start | +| Frontend guide and typed client | https://vextjs.github.io/frontend/getting-started | +| Runtime boundaries | https://vextjs.github.io/frontend/boundaries-and-roadmap | +| `llms.txt` | https://vextjs.github.io/llms.txt | +| `capabilities.json` | https://vextjs.github.io/capabilities.json | +| `docs-manifest.json` | https://vextjs.github.io/docs-manifest.json | **For AI assistants:** prefer citing `docs-manifest.json` canonical URLs; check `capabilities.json` and the boundaries page before describing frontend capabilities. Do not invent features from React version, SSR, or Suspense alone. diff --git a/package.json b/package.json index e0461098..fd269ca4 100644 --- a/package.json +++ b/package.json @@ -145,7 +145,7 @@ "bugs": { "url": "https://github.com/devcodex-labs/vextjs/issues" }, - "homepage": "https://devcodex-labs.github.io/vextjs/", + "homepage": "https://vextjs.github.io/", "engines": { "node": "^20.19.0 || >=22.12.0" }, diff --git a/scripts/validation/verify-documentation-contract.mjs b/scripts/validation/verify-documentation-contract.mjs index 6f146ac1..067601a6 100644 --- a/scripts/validation/verify-documentation-contract.mjs +++ b/scripts/validation/verify-documentation-contract.mjs @@ -442,10 +442,10 @@ function verifyDocumentationGrowthContract() { "docs-manifest.json", "capabilities.json", "ai-gold-questions.json", - "https://devcodex-labs.github.io/vextjs/llms.txt", - "https://devcodex-labs.github.io/vextjs/llms-full.txt", - "https://devcodex-labs.github.io/vextjs/zh/llms.txt", - "https://devcodex-labs.github.io/vextjs/zh/llms-full.txt", + "https://vextjs.github.io/llms.txt", + "https://vextjs.github.io/llms-full.txt", + "https://vextjs.github.io/zh/llms.txt", + "https://vextjs.github.io/zh/llms-full.txt", "Language and completeness contract", "docs-events.schema.json", "docs-dashboard-definition.json", @@ -456,10 +456,10 @@ function verifyDocumentationGrowthContract() { "docs-manifest.json", "capabilities.json", "ai-gold-questions.json", - "https://devcodex-labs.github.io/vextjs/llms.txt", - "https://devcodex-labs.github.io/vextjs/llms-full.txt", - "https://devcodex-labs.github.io/vextjs/zh/llms.txt", - "https://devcodex-labs.github.io/vextjs/zh/llms-full.txt", + "https://vextjs.github.io/llms.txt", + "https://vextjs.github.io/llms-full.txt", + "https://vextjs.github.io/zh/llms.txt", + "https://vextjs.github.io/zh/llms-full.txt", "语言与完整性合同", "docs-events.schema.json", "docs-dashboard-definition.json", @@ -1907,10 +1907,10 @@ function verifyReadmePublicEntryContract() { "npx vextjs create", "res.render", "Apache-2.0", - "https://devcodex-labs.github.io/vextjs/", + "https://vextjs.github.io/", "https://github.com/devcodex-labs/vextjs", - "https://devcodex-labs.github.io/vextjs/llms.txt", - "https://devcodex-labs.github.io/vextjs/capabilities.json", + "https://vextjs.github.io/llms.txt", + "https://vextjs.github.io/capabilities.json", "For AI assistants", "Build AI-assisted APIs and server-rendered React pages", "AI-first full-stack Node.js application framework", @@ -1932,7 +1932,7 @@ function verifyReadmePublicEntryContract() { "rateLimit.enabled: true", ]); forbidTokens("README.md", [ - "vextjs.github.io", + "devcodex-labs.github.io/vextjs", "github.com/vextjs/vext", "License: MIT", "Node.js-%3E%3D18.0.0", @@ -2303,7 +2303,7 @@ function verifyRenderedMachineArtifacts() { ); } const siteUrl = ( - process.env.VEXT_DOCS_SITE_URL || "https://devcodex-labs.github.io/vextjs" + process.env.VEXT_DOCS_SITE_URL || "https://vextjs.github.io" ).replace(/\/+$/, ""); const relationSources = sourceEntries.map((entry) => { const source = read(entry.sourcePath); @@ -2616,8 +2616,8 @@ function verifyRenderedMachineArtifacts() { locale: "en", indexName: "llms.txt", fullName: "llms-full.txt", - fullUrl: "https://devcodex-labs.github.io/vextjs/llms-full.txt", - alternateUrl: "https://devcodex-labs.github.io/vextjs/zh/llms.txt", + fullUrl: "https://vextjs.github.io/llms-full.txt", + alternateUrl: "https://vextjs.github.io/zh/llms.txt", optionalHeading: "## Other language", forbiddenOptionalHeading: "## Optional", }, @@ -2625,8 +2625,8 @@ function verifyRenderedMachineArtifacts() { locale: "zh", indexName: "zh/llms.txt", fullName: "zh/llms-full.txt", - fullUrl: "https://devcodex-labs.github.io/vextjs/zh/llms-full.txt", - alternateUrl: "https://devcodex-labs.github.io/vextjs/llms.txt", + fullUrl: "https://vextjs.github.io/zh/llms-full.txt", + alternateUrl: "https://vextjs.github.io/llms.txt", optionalHeading: "## 可选语言", forbiddenOptionalHeading: "## Optional", }, diff --git a/src/cli/create.ts b/src/cli/create.ts index c07bc0fa..d9af467a 100644 --- a/src/cli/create.ts +++ b/src/cli/create.ts @@ -65,7 +65,7 @@ interface CreateOptions { const VALID_ADAPTERS = ["hono", "fastify", "express", "koa", "native"]; const VALID_TEMPLATES = ["api", "fullstack-react"]; const VALID_FRONTENDS = ["react", "none"]; -const VEXT_DOCUMENTATION_URL = "https://devcodex-labs.github.io/vextjs/"; +const VEXT_DOCUMENTATION_URL = "https://vextjs.github.io/"; /** * adapter 对应的 peer dependency 映射 diff --git a/test/unit/cli/create.test.ts b/test/unit/cli/create.test.ts index b3da221f..3608d68e 100644 --- a/test/unit/cli/create.test.ts +++ b/test/unit/cli/create.test.ts @@ -1078,7 +1078,7 @@ describe("vext create", () => { "getting-started", ); expect(files["src/frontend/pages/index.tsx"]).toContain( - 'href="https://devcodex-labs.github.io/vextjs/"', + 'href="https://vextjs.github.io/"', ); expect(files["src/frontend/components/AppShell.tsx"]).toContain( "useVextI18n", @@ -1093,7 +1093,7 @@ describe("vext create", () => { 'href="/docs"', ); expect(files["src/frontend/components/AppShell.tsx"]).toContain( - 'href="https://devcodex-labs.github.io/vextjs/"', + 'href="https://vextjs.github.io/"', ); expect(files["src/frontend/components/AppShell.tsx"]).toContain( 'className="nav-docs"', @@ -1186,7 +1186,7 @@ describe("vext create", () => { /openapi:\s*\{\s*enabled: true,/, ); expect(files["src/frontend/pages/index.jsx"]).toContain( - 'href="https://devcodex-labs.github.io/vextjs/"', + 'href="https://vextjs.github.io/"', ); expect(files["src/frontend/pages/index.jsx"]).toContain( "runtime-trace", diff --git a/website/docs/en/guide/deployment.md b/website/docs/en/guide/deployment.md index 58bfdea7..48ff055d 100644 --- a/website/docs/en/guide/deployment.md +++ b/website/docs/en/guide/deployment.md @@ -887,7 +887,17 @@ Run Job schedulers and workers as processes separate from HTTP. `npx vextjs job ## Publish the documentation site -When maintaining this VextJS repository, `.github/workflows/docs.yml` publishes the documentation to [GitHub Pages](https://devcodex-labs.github.io/vextjs/) with base path `/vextjs/`. Automatic publishing follows a successful main push CI and checks out that exact SHA. This is separate from application deployment above. The DevCodex Labs organization homepage is maintained in a separate repository. +When maintaining this VextJS repository, documentation sources remain in `devcodex-labs/vextjs`. The built static site lives in the separate public repository `vextjs/vextjs.github.io` and is served at [https://vextjs.github.io/](https://vextjs.github.io/) with base path `/`. This is separate from application deployment above. + +Complete this setup once; subsequent builds publish automatically: + +1. Create the public repository `vextjs.github.io` in the `vextjs` organization and initialize its `main` branch. This repository is reserved for build output: publishing replaces the site files at its root, removes stale output, and preserves Git commit history. +2. Create a dedicated SSH Deploy Key for that repository. Add the public key in the site repository's `Settings → Deploy keys` with **Allow write access** enabled. Save the private key as `VEXT_DOCS_DEPLOY_KEY` in the source repository's `Settings → Secrets and variables → Actions`. Never put the private key in source code, documentation, or chat messages. +3. In the site repository's `Settings → Pages`, select **Deploy from a branch**, branch **main**, and folder **/(root)**. The repository name determines the organization root URL; no CNAME is needed. + +`.github/workflows/docs.yml` builds with Node.js 22, `VEXT_DOCS_BASE=/`, and `VEXT_DOCS_SITE_URL=https://vextjs.github.io`. Automatic publishing follows a successful source-repository `main` push CI and checks out that exact SHA. After the complete documentation publishing checks pass, the workflow pushes the output to the site repository using its dedicated Deploy Key. Before pushing, it checks the current source `main` commit and skips builds superseded by a later commit. The target repository's Pages job then publishes the new content. + +To republish, select `main` in the source repository's `Actions → Deploy Docs → Run workflow`. This manual entry also runs the complete documentation checks; other branches cannot publish to the production site through it. Failed builds do not push site files. After the workflow pushes successfully, wait for the target repository's Pages publishing job to finish before checking the updated site. ## Next step diff --git a/website/docs/en/resources/documentation-data-and-ai.md b/website/docs/en/resources/documentation-data-and-ai.md index 47bf1198..2040a328 100644 --- a/website/docs/en/resources/documentation-data-and-ai.md +++ b/website/docs/en/resources/documentation-data-and-ai.md @@ -13,19 +13,19 @@ This page is for developers of search, AI answers, and a future knowledge graph. These links point to the formal site. For a local preview of the Chinese stage, read the corresponding files from that local build; do not assume the current changes have been deployed. Inspect the actual `schemaVersion`, `rollout`, and `verification` before integration. -| Asset | Purpose | -| --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | -| [`docs-manifest.json`](https://devcodex-labs.github.io/vextjs/docs-manifest.json) | `vext.docs-manifest/v2`: document identity, role, locale, URL, source hash, and relationship index. | -| [`capabilities.json`](https://devcodex-labs.github.io/vextjs/capabilities.json) | Existing v1 capability summary and non-goals, not complete capability definitions or a graph; read details and limitations. | -| [`ai-gold-questions.json`](https://devcodex-labs.github.io/vextjs/ai-gold-questions.json) | Questions, required documents/routes, and forbidden claims for answer regression. Structural checks do not prove semantics. | -| [`llms.txt`](https://devcodex-labs.github.io/vextjs/llms.txt) | Concise English entry points for language models and documentation tools. It is an index, not a crawler-control file. | -| [`llms-full.txt`](https://devcodex-labs.github.io/vextjs/llms-full.txt) | Complete English URL-and-summary index: every public English documentation page appears exactly once. | -| [`zh/llms.txt`](https://devcodex-labs.github.io/vextjs/zh/llms.txt) | Concise Simplified Chinese entry points, isolated from the default English index. | -| [`zh/llms-full.txt`](https://devcodex-labs.github.io/vextjs/zh/llms-full.txt) | Complete Simplified Chinese URL-and-summary index: every public Chinese documentation page appears exactly once. | -| [`docs-events.schema.json`](https://devcodex-labs.github.io/vextjs/docs-events.schema.json) | Optional privacy-preserving event contract. No collector is enabled by VextJS. | -| [`docs-dashboard-definition.json`](https://devcodex-labs.github.io/vextjs/docs-dashboard-definition.json) | Metric definitions and collection boundary for a site owner who later chooses a compliant collector. | - -The build also generates [`spec-rules.json`](https://devcodex-labs.github.io/vextjs/spec-rules.json), with `schemaVersion: vext.spec-rules/v1`, projecting rule identities, levels, and links from Specification pages. +| Asset | Purpose | +| ------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| [`docs-manifest.json`](https://vextjs.github.io/docs-manifest.json) | `vext.docs-manifest/v2`: document identity, role, locale, URL, source hash, and relationship index. | +| [`capabilities.json`](https://vextjs.github.io/capabilities.json) | Existing v1 capability summary and non-goals, not complete capability definitions or a graph; read details and limitations. | +| [`ai-gold-questions.json`](https://vextjs.github.io/ai-gold-questions.json) | Questions, required documents/routes, and forbidden claims for answer regression. Structural checks do not prove semantics. | +| [`llms.txt`](https://vextjs.github.io/llms.txt) | Concise English entry points for language models and documentation tools. It is an index, not a crawler-control file. | +| [`llms-full.txt`](https://vextjs.github.io/llms-full.txt) | Complete English URL-and-summary index: every public English documentation page appears exactly once. | +| [`zh/llms.txt`](https://vextjs.github.io/zh/llms.txt) | Concise Simplified Chinese entry points, isolated from the default English index. | +| [`zh/llms-full.txt`](https://vextjs.github.io/zh/llms-full.txt) | Complete Simplified Chinese URL-and-summary index: every public Chinese documentation page appears exactly once. | +| [`docs-events.schema.json`](https://vextjs.github.io/docs-events.schema.json) | Optional privacy-preserving event contract. No collector is enabled by VextJS. | +| [`docs-dashboard-definition.json`](https://vextjs.github.io/docs-dashboard-definition.json) | Metric definitions and collection boundary for a site owner who later chooses a compliant collector. | + +The build also generates [`spec-rules.json`](https://vextjs.github.io/spec-rules.json), with `schemaVersion: vext.spec-rules/v1`, projecting rule identities, levels, and links from Specification pages. The manifest, rules, and llms indexes are generated after the site build without build timestamps. Their output is repeatable when document sources, build contracts, navigation, question set, lockfile, and site configuration are fixed. Capabilities, questions, and metrics contracts are public source assets; do not mistake them for data wholly extracted from page prose. diff --git a/website/docs/public/docs-events.schema.json b/website/docs/public/docs-events.schema.json index 7dc6b03f..fc5ed6ba 100644 --- a/website/docs/public/docs-events.schema.json +++ b/website/docs/public/docs-events.schema.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://devcodex-labs.github.io/vextjs/docs-events.schema.json", + "$id": "https://vextjs.github.io/docs-events.schema.json", "title": "VextJS documentation event", "description": "Optional, privacy-preserving event contract for a documentation analytics collector. VextJS does not enable or bundle a collector by default.", "type": "object", diff --git a/website/docs/public/robots.txt b/website/docs/public/robots.txt index bd3d0f68..e1dfb58e 100644 --- a/website/docs/public/robots.txt +++ b/website/docs/public/robots.txt @@ -1,4 +1,4 @@ User-agent: * Allow: / -Sitemap: https://devcodex-labs.github.io/vextjs/sitemap.xml +Sitemap: https://vextjs.github.io/sitemap.xml diff --git a/website/docs/zh/guide/deployment.md b/website/docs/zh/guide/deployment.md index 5af5e942..d8429b30 100644 --- a/website/docs/zh/guide/deployment.md +++ b/website/docs/zh/guide/deployment.md @@ -890,7 +890,17 @@ Job scheduler 和 worker 使用独立于 HTTP 的进程。用 `npx vextjs job sc ## 文档站发布 -维护 VextJS 仓库本身时,文档站由 `.github/workflows/docs.yml` 发布到 [GitHub Pages](https://devcodex-labs.github.io/vextjs/),base path 为 `/vextjs/`。自动发布跟随 main 的成功 push CI,检出对应精确 SHA;它与上文业务应用部署是两套流程。DevCodex Labs 组织主页由独立仓库维护。 +维护 VextJS 仓库本身时,文档源保存在 `devcodex-labs/vextjs`,构建后的静态站点保存在独立公开仓库 `vextjs/vextjs.github.io`,访问地址为 [https://vextjs.github.io/](https://vextjs.github.io/),base path 为 `/`。它与上文业务应用部署是两套流程。 + +首次发布需要以下配置,之后不需要手动复制构建结果: + +1. 在 `vextjs` 组织创建公开仓库 `vextjs.github.io`,初始化 `main` 分支。该仓库专门保存构建结果;发布时会替换根目录中的站点文件,删除旧产物并保留 Git 提交历史。 +2. 为该仓库创建专用 SSH Deploy Key。公钥放入站点仓库的 `Settings → Deploy keys`,勾选 **Allow write access**;私钥通过源码仓库的 `Settings → Secrets and variables → Actions` 保存为 `VEXT_DOCS_DEPLOY_KEY`。不要把私钥放进源码、文档或聊天消息。 +3. 在站点仓库的 `Settings → Pages` 选择 **Deploy from a branch**,分支选择 **main**、目录选择 **/(root)**。该组织根地址由仓库名称决定,无需配置 CNAME。 + +`.github/workflows/docs.yml` 使用 Node.js 22,以 `VEXT_DOCS_BASE=/`、`VEXT_DOCS_SITE_URL=https://vextjs.github.io` 构建。自动发布跟随源码仓库 `main` 的成功 push CI,检出该次 CI 的精确 SHA,执行完整文档发布校验后,将产物通过专用 Deploy Key 推送到站点仓库。推送前检查源码 `main` 的当前提交;已被后续提交替代的构建会跳过发布。站点仓库的 Pages 随后发布新内容。 + +需要重新发布时,在源码仓库的 `Actions → Deploy Docs → Run workflow` 选择 `main`。手动入口同样执行完整文档校验;其他分支不能通过该入口发布到生产站点。构建失败不会推送站点文件;工作流完成推送后,仍需等待目标仓库的 Pages 发布任务完成才能看到更新。 ## 下一步 diff --git a/website/docs/zh/resources/documentation-data-and-ai.md b/website/docs/zh/resources/documentation-data-and-ai.md index b4fae826..8cf116fc 100644 --- a/website/docs/zh/resources/documentation-data-and-ai.md +++ b/website/docs/zh/resources/documentation-data-and-ai.md @@ -14,19 +14,19 @@ VextJS 同时提供面向读者的文档页面和确定性的构建产物。这 以下链接为正式站点地址。中文预览阶段应读取对应本地构建中的文件,不假定线上已部署当前改造;接入时先检查实际 schemaVersion、rollout 与 verification。 -| 资产 | 用途 | -| --------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | -| [`docs-manifest.json`](https://devcodex-labs.github.io/vextjs/docs-manifest.json) | vext.docs-manifest/v2;文档身份、角色、语言、URL、源文件 hash 与关系索引。 | -| [`capabilities.json`](https://devcodex-labs.github.io/vextjs/capabilities.json) | 既有 v1 能力摘要与 non-goal;非完整能力定义或图谱,需再读对应细节和运行限制。 | -| [`ai-gold-questions.json`](https://devcodex-labs.github.io/vextjs/ai-gold-questions.json) | 问题及所需文档/路由、禁止声称的边界;用于回答回归,结构校验不等于语义正确。 | -| [`zh/llms.txt`](https://devcodex-labs.github.io/vextjs/zh/llms.txt) | 面向语言模型和文档工具的简体中文精选入口;它是索引,不是 crawler 控制文件。 | -| [`zh/llms-full.txt`](https://devcodex-labs.github.io/vextjs/zh/llms-full.txt) | 完整简体中文 URL 与摘要索引:每个公开中文文档页只出现一次。 | -| [`llms.txt`](https://devcodex-labs.github.io/vextjs/llms.txt) | 默认英文精选入口,与简体中文内容隔离。 | -| [`llms-full.txt`](https://devcodex-labs.github.io/vextjs/llms-full.txt) | 完整英文 URL 与摘要索引:每个公开英文文档页只出现一次。 | -| [`docs-events.schema.json`](https://devcodex-labs.github.io/vextjs/docs-events.schema.json) | 可选的隐私保护事件合同;VextJS 没有启用 collector。 | -| [`docs-dashboard-definition.json`](https://devcodex-labs.github.io/vextjs/docs-dashboard-definition.json) | 供未来自行选择合规 collector 的站点所有者使用的指标定义和采集边界。 | - -另外,构建生成 [`spec-rules.json`](https://devcodex-labs.github.io/vextjs/spec-rules.json),schemaVersion 为 vext.spec-rules/v1,由 Specification 正文投影规则身份、等级和链接。 +| 资产 | 用途 | +| ------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | +| [`docs-manifest.json`](https://vextjs.github.io/docs-manifest.json) | vext.docs-manifest/v2;文档身份、角色、语言、URL、源文件 hash 与关系索引。 | +| [`capabilities.json`](https://vextjs.github.io/capabilities.json) | 既有 v1 能力摘要与 non-goal;非完整能力定义或图谱,需再读对应细节和运行限制。 | +| [`ai-gold-questions.json`](https://vextjs.github.io/ai-gold-questions.json) | 问题及所需文档/路由、禁止声称的边界;用于回答回归,结构校验不等于语义正确。 | +| [`zh/llms.txt`](https://vextjs.github.io/zh/llms.txt) | 面向语言模型和文档工具的简体中文精选入口;它是索引,不是 crawler 控制文件。 | +| [`zh/llms-full.txt`](https://vextjs.github.io/zh/llms-full.txt) | 完整简体中文 URL 与摘要索引:每个公开中文文档页只出现一次。 | +| [`llms.txt`](https://vextjs.github.io/llms.txt) | 默认英文精选入口,与简体中文内容隔离。 | +| [`llms-full.txt`](https://vextjs.github.io/llms-full.txt) | 完整英文 URL 与摘要索引:每个公开英文文档页只出现一次。 | +| [`docs-events.schema.json`](https://vextjs.github.io/docs-events.schema.json) | 可选的隐私保护事件合同;VextJS 没有启用 collector。 | +| [`docs-dashboard-definition.json`](https://vextjs.github.io/docs-dashboard-definition.json) | 供未来自行选择合规 collector 的站点所有者使用的指标定义和采集边界。 | + +另外,构建生成 [`spec-rules.json`](https://vextjs.github.io/spec-rules.json),schemaVersion 为 vext.spec-rules/v1,由 Specification 正文投影规则身份、等级和链接。 manifest、rules 与 llms 索引在站点构建后生成,不含构建时间戳;固定文档源、构建合同、导航、问题集、依赖锁及站点配置时输出可重复。capabilities、问题集与度量合同是公开源资产,不应将它们误认为全部从正文自动提取。 diff --git a/website/rspress.config.ts b/website/rspress.config.ts index 1db4948f..bc7c92a2 100644 --- a/website/rspress.config.ts +++ b/website/rspress.config.ts @@ -7,8 +7,8 @@ import { resolveDocsVerification, } from "./scripts/docs-rollout.mjs"; -const DEFAULT_DOCS_BASE = "/vextjs/"; -const DEFAULT_DOCS_SITE_URL = "https://devcodex-labs.github.io/vextjs"; +const DEFAULT_DOCS_BASE = "/"; +const DEFAULT_DOCS_SITE_URL = "https://vextjs.github.io"; function normalizeDocsBase(value?: string) { const raw = value?.trim() || DEFAULT_DOCS_BASE; diff --git a/website/scripts/generate-machine-artifacts.mjs b/website/scripts/generate-machine-artifacts.mjs index c6c1f226..922b3331 100644 --- a/website/scripts/generate-machine-artifacts.mjs +++ b/website/scripts/generate-machine-artifacts.mjs @@ -33,7 +33,7 @@ const docsRoot = path.join(websiteRoot, "docs"); const distRoot = path.join(websiteRoot, "dist"); const rollout = resolveDocsRollout(); const verification = resolveDocsVerification(); -const DEFAULT_DOCS_SITE_URL = "https://devcodex-labs.github.io/vextjs"; +const DEFAULT_DOCS_SITE_URL = "https://vextjs.github.io"; const docsSiteUrl = ( process.env.VEXT_DOCS_SITE_URL || DEFAULT_DOCS_SITE_URL ).replace(/\/+$/, ""); From 67fcd49f097de4d6def9e30b99936e649d054e8a Mon Sep 17 00:00:00 2001 From: Rocky shi Date: Sat, 10 Oct 2026 01:49:18 +0000 Subject: [PATCH 2/3] docs: retain repository Pages alongside organization site --- .github/workflows/docs.yml | 119 +++++++++++++----- README.md | 28 ++--- package.json | 2 +- .../verify-documentation-contract.mjs | 32 ++--- src/cli/create.ts | 2 +- test/unit/cli/create.test.ts | 6 +- website/docs/en/guide/deployment.md | 15 ++- .../en/resources/documentation-data-and-ai.md | 26 ++-- website/docs/public/docs-events.schema.json | 2 +- website/docs/public/robots.txt | 2 +- website/docs/zh/guide/deployment.md | 15 ++- .../zh/resources/documentation-data-and-ai.md | 26 ++-- website/rspress.config.ts | 4 +- .../scripts/generate-machine-artifacts.mjs | 2 +- 14 files changed, 178 insertions(+), 103 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 2e489e58..15b23bdd 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -1,5 +1,5 @@ # ───────────────────────────────────────────────────────────── -# VextJS 文档站 — GitHub Pages 自动部署 +# VextJS 文档站 — 保留源码仓库 Pages,并新增组织根站点 # # 触发条件: # - main 的 push-triggered CI 成功后,部署该次 CI 的精确 SHA @@ -7,8 +7,8 @@ # # 流水线结构: # 1. build — 在 website/ 目录安装依赖并执行 rspress build -# 2. deploy — 推送静态产物到 vextjs/vextjs.github.io 的 main -# 由目标仓库的 branch-source Pages 发布到 https://vextjs.github.io/ +# 2. deploy-pages — 保留源码仓库的 /vextjs/ Pages 发布 +# 3. deploy-organization — 新增独立组织根站点 https://vextjs.github.io/ # # 首次配置:目标仓库初始化 main,Pages 选择 main / (root), # 添加可写 Deploy Key,并在源码仓库保存 VEXT_DOCS_DEPLOY_KEY。 @@ -32,9 +32,7 @@ permissions: contents: read env: - VEXT_DOCS_BASE: / - VEXT_DOCS_SITE_URL: https://vextjs.github.io - DOCS_PUBLISH_REPOSITORY: vextjs/vextjs.github.io + DEPLOY_SHA: ${{ github.event.workflow_run.head_sha || github.sha }} # ── Jobs ───────────────────────────────────────────────────── @@ -43,7 +41,7 @@ jobs: # 1. 构建文档站 # ──────────────────────────────────────────────────────────── build: - name: Build Docs + name: Build Docs (${{ matrix.site }}) runs-on: ubuntu-latest if: >- ${{ @@ -55,11 +53,22 @@ jobs: github.event.workflow_run.head_repository.full_name == github.repository ) }} + permissions: + contents: read + pages: write + strategy: + fail-fast: false + matrix: + include: + - site: project + base: /vextjs/ + url: https://devcodex-labs.github.io/vextjs + - site: organization + base: / + url: https://vextjs.github.io env: - DEPLOY_SHA: ${{ github.event.workflow_run.head_sha || github.sha }} - outputs: - deploy_sha: ${{ steps.commit.outputs.sha }} - current: ${{ steps.current.outputs.publish }} + VEXT_DOCS_BASE: ${{ matrix.base }} + VEXT_DOCS_SITE_URL: ${{ matrix.url }} steps: - name: Checkout uses: actions/checkout@v7 @@ -69,7 +78,6 @@ jobs: persist-credentials: false - name: Verify deployment commit - id: commit shell: bash run: | ACTUAL_SHA=$(git rev-parse HEAD) @@ -78,7 +86,6 @@ jobs: echo "Checked out SHA: $ACTUAL_SHA" exit 1 fi - echo "sha=$ACTUAL_SHA" >> "$GITHUB_OUTPUT" echo "Building deployment SHA: $ACTUAL_SHA" - name: Setup Node.js @@ -88,6 +95,10 @@ jobs: cache: "npm" cache-dependency-path: website/package-lock.json + - name: Setup source repository Pages + if: matrix.site == 'project' + uses: actions/configure-pages@v6 + - name: Install dependencies working-directory: website run: npm ci @@ -116,7 +127,29 @@ jobs: EOF touch website/dist/.nojekyll - - name: Check built commit is still current + - name: Upload docs artifact + uses: actions/upload-artifact@v7 + with: + name: docs-dist-${{ matrix.site }} + path: website/dist + if-no-files-found: error + include-hidden-files: true + + - name: Upload source repository Pages artifact + if: matrix.site == 'project' + uses: actions/upload-pages-artifact@v5 + with: + path: website/dist + + # 在进入发布并发组前跳过旧 CI 的迟到构建。 + prepare-deployment: + name: Check deployment commit + runs-on: ubuntu-latest + needs: build + outputs: + current: ${{ steps.current.outputs.publish }} + steps: + - name: Check current main commit id: current env: GH_TOKEN: ${{ github.token }} @@ -130,35 +163,63 @@ jobs: echo "publish=false" >> "$GITHUB_OUTPUT" fi - - name: Upload docs artifact + # 原源码仓库 Pages 保留官方 Actions 发布流程,与组织站点并行。 + deploy-pages: + name: Publish source repository Pages + runs-on: ubuntu-latest + needs: prepare-deployment + if: needs.prepare-deployment.outputs.current == 'true' + permissions: + contents: read + pages: write + id-token: write + concurrency: + group: vextjs-docs-project + cancel-in-progress: false + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Check current main commit + id: current + env: + GH_TOKEN: ${{ github.token }} + shell: bash + run: | + CURRENT_SHA=$(gh api "repos/${GITHUB_REPOSITORY}/git/ref/heads/main" --jq '.object.sha') + if [[ "$CURRENT_SHA" == "$DEPLOY_SHA" ]]; then + echo "publish=true" >> "$GITHUB_OUTPUT" + else + echo "Skipping superseded build: $DEPLOY_SHA (main is $CURRENT_SHA)" + echo "publish=false" >> "$GITHUB_OUTPUT" + fi + + - name: Deploy source repository Pages if: steps.current.outputs.publish == 'true' - uses: actions/upload-artifact@v7 - with: - name: docs-dist - path: website/dist - if-no-files-found: error - include-hidden-files: true + id: deployment + uses: actions/deploy-pages@v5 # ──────────────────────────────────────────────────────────── - # 2. 向独立站点仓库推送;目标仓库保留普通提交历史,不强制推送 + # 新增组织根站点;其密钥或推送失败不阻止原站点的独立发布任务。 # ──────────────────────────────────────────────────────────── - deploy-pages: + deploy-organization: name: Publish to vextjs.github.io runs-on: ubuntu-latest - needs: build - if: needs.build.outputs.current == 'true' + needs: prepare-deployment + if: needs.prepare-deployment.outputs.current == 'true' # 只串行化已通过构建且仍对应 main 的发布,不中断正在进行的 Git 推送。 concurrency: - group: vextjs-docs-production + group: vextjs-docs-organization cancel-in-progress: false environment: - name: github-pages + name: organization-docs url: https://vextjs.github.io/ env: - DEPLOY_SHA: ${{ needs.build.outputs.deploy_sha }} + DOCS_PUBLISH_REPOSITORY: vextjs/vextjs.github.io + VEXT_DOCS_SITE_URL: https://vextjs.github.io steps: - name: Check current main commit @@ -199,7 +260,7 @@ jobs: if: steps.current.outputs.publish == 'true' uses: actions/download-artifact@v8 with: - name: docs-dist + name: docs-dist-organization path: docs-dist - name: Publish verified docs diff --git a/README.md b/README.md index 2919b071..a7350090 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![License: Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![Node.js](https://img.shields.io/badge/Node.js-%5E20.19.0%20%7C%7C%20%3E%3D22.12.0-green.svg)](https://nodejs.org/) [![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue.svg)](https://www.typescriptlang.org/) -[![Docs](https://img.shields.io/badge/docs-vextjs.github.io-informational)](https://vextjs.github.io/) +[![Docs](https://img.shields.io/badge/docs-devcodex--labs.github.io-informational)](https://devcodex-labs.github.io/vextjs/) > **Build AI-assisted APIs and server-rendered React pages in one Node.js application.** @@ -14,7 +14,7 @@ AI-first describes the engineering surface: conventions, scaffolding, typed cont The npm package name is `vextjs`; the CLI binary is `vext`. Requires Node.js **`^20.19.0 || >=22.12.0`**. Cold-start from the registry with **`npx vextjs …`**. After install, use project scripts or local `npx vext`. -**Docs:** https://vextjs.github.io/ · **Migration:** [MIGRATION.md](./MIGRATION.md) · **Changelog:** [CHANGELOG.md](./CHANGELOG.md) +**Docs:** https://devcodex-labs.github.io/vextjs/ · **Organization docs:** https://vextjs.github.io/ · **Migration:** [MIGRATION.md](./MIGRATION.md) · **Changelog:** [CHANGELOG.md](./CHANGELOG.md) --- @@ -174,7 +174,7 @@ VextJS is a strong fit when: VextJS uses **route-native SSR**: `src/routes/**` + `res.render()` provide SSR, normal hydration or pure-HTML `hydration: "none"`, Suspense, opt-in Streaming SSR, same-route navigation, static/revalidate freshness, and local media. It does not currently implement selective/partial hydration, an Islands component model, React Server Components, Server Functions or Actions, partial prerendering (PPR), or third-party bundler plugin ecosystems. Those models require additional execution and asset boundaries; Vext does not claim them until those contracts exist. -Read the exact lifecycle, trade-offs, and exclusions in [Frontend boundaries and roadmap](https://vextjs.github.io/frontend/boundaries-and-roadmap). Implementation guides cover [rendering modes](https://vextjs.github.io/frontend/rendering-modes), [data flow](https://vextjs.github.io/frontend/data-flow), [assets and media](https://vextjs.github.io/frontend/static-assets-and-cdn), and the [typed API client](https://vextjs.github.io/frontend/api-client-and-contracts). +Read the exact lifecycle, trade-offs, and exclusions in [Frontend boundaries and roadmap](https://devcodex-labs.github.io/vextjs/frontend/boundaries-and-roadmap). Implementation guides cover [rendering modes](https://devcodex-labs.github.io/vextjs/frontend/rendering-modes), [data flow](https://devcodex-labs.github.io/vextjs/frontend/data-flow), [assets and media](https://devcodex-labs.github.io/vextjs/frontend/static-assets-and-cdn), and the [typed API client](https://devcodex-labs.github.io/vextjs/frontend/api-client-and-contracts). --- @@ -197,7 +197,7 @@ export default { }; ``` -Benchmark methodology: [Adapter Matrix](https://vextjs.github.io/benchmark). It keeps one Vext application fixed and compares the supported adapters; reproduce it with `npm run test:bench` in this repo. +Benchmark methodology: [Adapter Matrix](https://devcodex-labs.github.io/vextjs/benchmark). It keeps one Vext application fixed and compares the supported adapters; reproduce it with `npm run test:bench` in this repo. --- @@ -235,7 +235,7 @@ built-in defaults → default → {profile} → local (development/test only) Select profile with `vext start --config ` or `VEXT_CONFIG=` (do not rely on baked `process.env.NODE_ENV` after `vext build` for profile selection). -Common fields: `port`, `host`, `adapter`, `logger`, `cors`, `bodyParser`, `rateLimit`, `openapi`, `frontend`, `cache`, `session`, `shutdown`. See the [configuration guide](https://vextjs.github.io/guide/configuration) and [configuration reference](https://vextjs.github.io/api/config) before changing production behavior. +Common fields: `port`, `host`, `adapter`, `logger`, `cors`, `bodyParser`, `rateLimit`, `openapi`, `frontend`, `cache`, `session`, `shutdown`. See the [configuration guide](https://devcodex-labs.github.io/vextjs/guide/configuration) and [configuration reference](https://devcodex-labs.github.io/vextjs/api/config) before changing production behavior. `rateLimit` is disabled by default and installs middleware only when `rateLimit.enabled === true`. Framework SEO is configured under @@ -263,15 +263,15 @@ describe("API", () => { ## Documentation for people and AI assistants -| Resource | URL | -| ------------------------------- | -------------------------------------------------------- | -| Human docs (EN/ZH) | https://vextjs.github.io/ | -| Quick start | https://vextjs.github.io/guide/quick-start | -| Frontend guide and typed client | https://vextjs.github.io/frontend/getting-started | -| Runtime boundaries | https://vextjs.github.io/frontend/boundaries-and-roadmap | -| `llms.txt` | https://vextjs.github.io/llms.txt | -| `capabilities.json` | https://vextjs.github.io/capabilities.json | -| `docs-manifest.json` | https://vextjs.github.io/docs-manifest.json | +| Resource | URL | +| ------------------------------- | ---------------------------------------------------------------------- | +| Human docs (EN/ZH) | https://devcodex-labs.github.io/vextjs/ | +| Quick start | https://devcodex-labs.github.io/vextjs/guide/quick-start | +| Frontend guide and typed client | https://devcodex-labs.github.io/vextjs/frontend/getting-started | +| Runtime boundaries | https://devcodex-labs.github.io/vextjs/frontend/boundaries-and-roadmap | +| `llms.txt` | https://devcodex-labs.github.io/vextjs/llms.txt | +| `capabilities.json` | https://devcodex-labs.github.io/vextjs/capabilities.json | +| `docs-manifest.json` | https://devcodex-labs.github.io/vextjs/docs-manifest.json | **For AI assistants:** prefer citing `docs-manifest.json` canonical URLs; check `capabilities.json` and the boundaries page before describing frontend capabilities. Do not invent features from React version, SSR, or Suspense alone. diff --git a/package.json b/package.json index fd269ca4..e0461098 100644 --- a/package.json +++ b/package.json @@ -145,7 +145,7 @@ "bugs": { "url": "https://github.com/devcodex-labs/vextjs/issues" }, - "homepage": "https://vextjs.github.io/", + "homepage": "https://devcodex-labs.github.io/vextjs/", "engines": { "node": "^20.19.0 || >=22.12.0" }, diff --git a/scripts/validation/verify-documentation-contract.mjs b/scripts/validation/verify-documentation-contract.mjs index 067601a6..1ea4007c 100644 --- a/scripts/validation/verify-documentation-contract.mjs +++ b/scripts/validation/verify-documentation-contract.mjs @@ -442,10 +442,10 @@ function verifyDocumentationGrowthContract() { "docs-manifest.json", "capabilities.json", "ai-gold-questions.json", - "https://vextjs.github.io/llms.txt", - "https://vextjs.github.io/llms-full.txt", - "https://vextjs.github.io/zh/llms.txt", - "https://vextjs.github.io/zh/llms-full.txt", + "https://devcodex-labs.github.io/vextjs/llms.txt", + "https://devcodex-labs.github.io/vextjs/llms-full.txt", + "https://devcodex-labs.github.io/vextjs/zh/llms.txt", + "https://devcodex-labs.github.io/vextjs/zh/llms-full.txt", "Language and completeness contract", "docs-events.schema.json", "docs-dashboard-definition.json", @@ -456,10 +456,10 @@ function verifyDocumentationGrowthContract() { "docs-manifest.json", "capabilities.json", "ai-gold-questions.json", - "https://vextjs.github.io/llms.txt", - "https://vextjs.github.io/llms-full.txt", - "https://vextjs.github.io/zh/llms.txt", - "https://vextjs.github.io/zh/llms-full.txt", + "https://devcodex-labs.github.io/vextjs/llms.txt", + "https://devcodex-labs.github.io/vextjs/llms-full.txt", + "https://devcodex-labs.github.io/vextjs/zh/llms.txt", + "https://devcodex-labs.github.io/vextjs/zh/llms-full.txt", "语言与完整性合同", "docs-events.schema.json", "docs-dashboard-definition.json", @@ -1907,10 +1907,11 @@ function verifyReadmePublicEntryContract() { "npx vextjs create", "res.render", "Apache-2.0", + "https://devcodex-labs.github.io/vextjs/", "https://vextjs.github.io/", "https://github.com/devcodex-labs/vextjs", - "https://vextjs.github.io/llms.txt", - "https://vextjs.github.io/capabilities.json", + "https://devcodex-labs.github.io/vextjs/llms.txt", + "https://devcodex-labs.github.io/vextjs/capabilities.json", "For AI assistants", "Build AI-assisted APIs and server-rendered React pages", "AI-first full-stack Node.js application framework", @@ -1932,7 +1933,6 @@ function verifyReadmePublicEntryContract() { "rateLimit.enabled: true", ]); forbidTokens("README.md", [ - "devcodex-labs.github.io/vextjs", "github.com/vextjs/vext", "License: MIT", "Node.js-%3E%3D18.0.0", @@ -2303,7 +2303,7 @@ function verifyRenderedMachineArtifacts() { ); } const siteUrl = ( - process.env.VEXT_DOCS_SITE_URL || "https://vextjs.github.io" + process.env.VEXT_DOCS_SITE_URL || "https://devcodex-labs.github.io/vextjs" ).replace(/\/+$/, ""); const relationSources = sourceEntries.map((entry) => { const source = read(entry.sourcePath); @@ -2616,8 +2616,8 @@ function verifyRenderedMachineArtifacts() { locale: "en", indexName: "llms.txt", fullName: "llms-full.txt", - fullUrl: "https://vextjs.github.io/llms-full.txt", - alternateUrl: "https://vextjs.github.io/zh/llms.txt", + fullUrl: `${siteUrl}/llms-full.txt`, + alternateUrl: `${siteUrl}/zh/llms.txt`, optionalHeading: "## Other language", forbiddenOptionalHeading: "## Optional", }, @@ -2625,8 +2625,8 @@ function verifyRenderedMachineArtifacts() { locale: "zh", indexName: "zh/llms.txt", fullName: "zh/llms-full.txt", - fullUrl: "https://vextjs.github.io/zh/llms-full.txt", - alternateUrl: "https://vextjs.github.io/llms.txt", + fullUrl: `${siteUrl}/zh/llms-full.txt`, + alternateUrl: `${siteUrl}/llms.txt`, optionalHeading: "## 可选语言", forbiddenOptionalHeading: "## Optional", }, diff --git a/src/cli/create.ts b/src/cli/create.ts index d9af467a..c07bc0fa 100644 --- a/src/cli/create.ts +++ b/src/cli/create.ts @@ -65,7 +65,7 @@ interface CreateOptions { const VALID_ADAPTERS = ["hono", "fastify", "express", "koa", "native"]; const VALID_TEMPLATES = ["api", "fullstack-react"]; const VALID_FRONTENDS = ["react", "none"]; -const VEXT_DOCUMENTATION_URL = "https://vextjs.github.io/"; +const VEXT_DOCUMENTATION_URL = "https://devcodex-labs.github.io/vextjs/"; /** * adapter 对应的 peer dependency 映射 diff --git a/test/unit/cli/create.test.ts b/test/unit/cli/create.test.ts index 3608d68e..b3da221f 100644 --- a/test/unit/cli/create.test.ts +++ b/test/unit/cli/create.test.ts @@ -1078,7 +1078,7 @@ describe("vext create", () => { "getting-started", ); expect(files["src/frontend/pages/index.tsx"]).toContain( - 'href="https://vextjs.github.io/"', + 'href="https://devcodex-labs.github.io/vextjs/"', ); expect(files["src/frontend/components/AppShell.tsx"]).toContain( "useVextI18n", @@ -1093,7 +1093,7 @@ describe("vext create", () => { 'href="/docs"', ); expect(files["src/frontend/components/AppShell.tsx"]).toContain( - 'href="https://vextjs.github.io/"', + 'href="https://devcodex-labs.github.io/vextjs/"', ); expect(files["src/frontend/components/AppShell.tsx"]).toContain( 'className="nav-docs"', @@ -1186,7 +1186,7 @@ describe("vext create", () => { /openapi:\s*\{\s*enabled: true,/, ); expect(files["src/frontend/pages/index.jsx"]).toContain( - 'href="https://vextjs.github.io/"', + 'href="https://devcodex-labs.github.io/vextjs/"', ); expect(files["src/frontend/pages/index.jsx"]).toContain( "runtime-trace", diff --git a/website/docs/en/guide/deployment.md b/website/docs/en/guide/deployment.md index 48ff055d..25be7c99 100644 --- a/website/docs/en/guide/deployment.md +++ b/website/docs/en/guide/deployment.md @@ -887,17 +887,24 @@ Run Job schedulers and workers as processes separate from HTTP. `npx vextjs job ## Publish the documentation site -When maintaining this VextJS repository, documentation sources remain in `devcodex-labs/vextjs`. The built static site lives in the separate public repository `vextjs/vextjs.github.io` and is served at [https://vextjs.github.io/](https://vextjs.github.io/) with base path `/`. This is separate from application deployment above. +When maintaining this VextJS repository, documentation sources remain in `devcodex-labs/vextjs`. The same commit is published to two documentation sites. These are separate from application deployment above. -Complete this setup once; subsequent builds publish automatically: +| Site | URL | Base path | Publishing method | +| ------------------------------- | ---------------------------------------------------------------------------------- | ---------- | -------------------------------------------------------------------------------------------------------------- | +| Source repository documentation | [https://devcodex-labs.github.io/vextjs/](https://devcodex-labs.github.io/vextjs/) | `/vextjs/` | GitHub Actions Pages deployment in the source repository | +| Organization documentation | [https://vextjs.github.io/](https://vextjs.github.io/) | `/` | Push to the separate public repository `vextjs/vextjs.github.io`, then publish through that repository's Pages | + +Keep **GitHub Actions** selected in the source repository's `Settings → Pages → Source`. Complete this setup once for the additional organization site; subsequent builds publish automatically: 1. Create the public repository `vextjs.github.io` in the `vextjs` organization and initialize its `main` branch. This repository is reserved for build output: publishing replaces the site files at its root, removes stale output, and preserves Git commit history. 2. Create a dedicated SSH Deploy Key for that repository. Add the public key in the site repository's `Settings → Deploy keys` with **Allow write access** enabled. Save the private key as `VEXT_DOCS_DEPLOY_KEY` in the source repository's `Settings → Secrets and variables → Actions`. Never put the private key in source code, documentation, or chat messages. 3. In the site repository's `Settings → Pages`, select **Deploy from a branch**, branch **main**, and folder **/(root)**. The repository name determines the organization root URL; no CNAME is needed. -`.github/workflows/docs.yml` builds with Node.js 22, `VEXT_DOCS_BASE=/`, and `VEXT_DOCS_SITE_URL=https://vextjs.github.io`. Automatic publishing follows a successful source-repository `main` push CI and checks out that exact SHA. After the complete documentation publishing checks pass, the workflow pushes the output to the site repository using its dedicated Deploy Key. Before pushing, it checks the current source `main` commit and skips builds superseded by a later commit. The target repository's Pages job then publishes the new content. +`.github/workflows/docs.yml` builds with Node.js 22 and sets `VEXT_DOCS_BASE` and `VEXT_DOCS_SITE_URL` separately for the paths and URLs in the table. Both artifacts are validated and uploaded separately to keep root-path assets distinct from `/vextjs/` assets. Automatic publishing follows a successful source-repository `main` push CI and checks out that exact SHA. + +After both builds and their complete documentation publishing checks pass, two independent publishing jobs start: the source repository uses a Pages artifact and the built-in `GITHUB_TOKEN`; the organization site uses `VEXT_DOCS_DEPLOY_KEY` to push its output. A missing organization key or a failed organization push does not block the source repository's publishing job. Either build failing prevents both sites from publishing in that run. Before publishing, each job checks the current source `main` commit and skips builds superseded by a later commit. -To republish, select `main` in the source repository's `Actions → Deploy Docs → Run workflow`. This manual entry also runs the complete documentation checks; other branches cannot publish to the production site through it. Failed builds do not push site files. After the workflow pushes successfully, wait for the target repository's Pages publishing job to finish before checking the updated site. +To rebuild and republish both sites, select `main` in the source repository's `Actions → Deploy Docs → Run workflow`. This manual entry also runs the complete documentation checks; other branches cannot publish to the production site through it. After the organization site's push succeeds, wait for the target repository's Pages publishing job to finish before checking the updated site. ## Next step diff --git a/website/docs/en/resources/documentation-data-and-ai.md b/website/docs/en/resources/documentation-data-and-ai.md index 2040a328..47bf1198 100644 --- a/website/docs/en/resources/documentation-data-and-ai.md +++ b/website/docs/en/resources/documentation-data-and-ai.md @@ -13,19 +13,19 @@ This page is for developers of search, AI answers, and a future knowledge graph. These links point to the formal site. For a local preview of the Chinese stage, read the corresponding files from that local build; do not assume the current changes have been deployed. Inspect the actual `schemaVersion`, `rollout`, and `verification` before integration. -| Asset | Purpose | -| ------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | -| [`docs-manifest.json`](https://vextjs.github.io/docs-manifest.json) | `vext.docs-manifest/v2`: document identity, role, locale, URL, source hash, and relationship index. | -| [`capabilities.json`](https://vextjs.github.io/capabilities.json) | Existing v1 capability summary and non-goals, not complete capability definitions or a graph; read details and limitations. | -| [`ai-gold-questions.json`](https://vextjs.github.io/ai-gold-questions.json) | Questions, required documents/routes, and forbidden claims for answer regression. Structural checks do not prove semantics. | -| [`llms.txt`](https://vextjs.github.io/llms.txt) | Concise English entry points for language models and documentation tools. It is an index, not a crawler-control file. | -| [`llms-full.txt`](https://vextjs.github.io/llms-full.txt) | Complete English URL-and-summary index: every public English documentation page appears exactly once. | -| [`zh/llms.txt`](https://vextjs.github.io/zh/llms.txt) | Concise Simplified Chinese entry points, isolated from the default English index. | -| [`zh/llms-full.txt`](https://vextjs.github.io/zh/llms-full.txt) | Complete Simplified Chinese URL-and-summary index: every public Chinese documentation page appears exactly once. | -| [`docs-events.schema.json`](https://vextjs.github.io/docs-events.schema.json) | Optional privacy-preserving event contract. No collector is enabled by VextJS. | -| [`docs-dashboard-definition.json`](https://vextjs.github.io/docs-dashboard-definition.json) | Metric definitions and collection boundary for a site owner who later chooses a compliant collector. | - -The build also generates [`spec-rules.json`](https://vextjs.github.io/spec-rules.json), with `schemaVersion: vext.spec-rules/v1`, projecting rule identities, levels, and links from Specification pages. +| Asset | Purpose | +| --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| [`docs-manifest.json`](https://devcodex-labs.github.io/vextjs/docs-manifest.json) | `vext.docs-manifest/v2`: document identity, role, locale, URL, source hash, and relationship index. | +| [`capabilities.json`](https://devcodex-labs.github.io/vextjs/capabilities.json) | Existing v1 capability summary and non-goals, not complete capability definitions or a graph; read details and limitations. | +| [`ai-gold-questions.json`](https://devcodex-labs.github.io/vextjs/ai-gold-questions.json) | Questions, required documents/routes, and forbidden claims for answer regression. Structural checks do not prove semantics. | +| [`llms.txt`](https://devcodex-labs.github.io/vextjs/llms.txt) | Concise English entry points for language models and documentation tools. It is an index, not a crawler-control file. | +| [`llms-full.txt`](https://devcodex-labs.github.io/vextjs/llms-full.txt) | Complete English URL-and-summary index: every public English documentation page appears exactly once. | +| [`zh/llms.txt`](https://devcodex-labs.github.io/vextjs/zh/llms.txt) | Concise Simplified Chinese entry points, isolated from the default English index. | +| [`zh/llms-full.txt`](https://devcodex-labs.github.io/vextjs/zh/llms-full.txt) | Complete Simplified Chinese URL-and-summary index: every public Chinese documentation page appears exactly once. | +| [`docs-events.schema.json`](https://devcodex-labs.github.io/vextjs/docs-events.schema.json) | Optional privacy-preserving event contract. No collector is enabled by VextJS. | +| [`docs-dashboard-definition.json`](https://devcodex-labs.github.io/vextjs/docs-dashboard-definition.json) | Metric definitions and collection boundary for a site owner who later chooses a compliant collector. | + +The build also generates [`spec-rules.json`](https://devcodex-labs.github.io/vextjs/spec-rules.json), with `schemaVersion: vext.spec-rules/v1`, projecting rule identities, levels, and links from Specification pages. The manifest, rules, and llms indexes are generated after the site build without build timestamps. Their output is repeatable when document sources, build contracts, navigation, question set, lockfile, and site configuration are fixed. Capabilities, questions, and metrics contracts are public source assets; do not mistake them for data wholly extracted from page prose. diff --git a/website/docs/public/docs-events.schema.json b/website/docs/public/docs-events.schema.json index fc5ed6ba..7dc6b03f 100644 --- a/website/docs/public/docs-events.schema.json +++ b/website/docs/public/docs-events.schema.json @@ -1,6 +1,6 @@ { "$schema": "https://json-schema.org/draft/2020-12/schema", - "$id": "https://vextjs.github.io/docs-events.schema.json", + "$id": "https://devcodex-labs.github.io/vextjs/docs-events.schema.json", "title": "VextJS documentation event", "description": "Optional, privacy-preserving event contract for a documentation analytics collector. VextJS does not enable or bundle a collector by default.", "type": "object", diff --git a/website/docs/public/robots.txt b/website/docs/public/robots.txt index e1dfb58e..bd3d0f68 100644 --- a/website/docs/public/robots.txt +++ b/website/docs/public/robots.txt @@ -1,4 +1,4 @@ User-agent: * Allow: / -Sitemap: https://vextjs.github.io/sitemap.xml +Sitemap: https://devcodex-labs.github.io/vextjs/sitemap.xml diff --git a/website/docs/zh/guide/deployment.md b/website/docs/zh/guide/deployment.md index d8429b30..b65fe436 100644 --- a/website/docs/zh/guide/deployment.md +++ b/website/docs/zh/guide/deployment.md @@ -890,17 +890,24 @@ Job scheduler 和 worker 使用独立于 HTTP 的进程。用 `npx vextjs job sc ## 文档站发布 -维护 VextJS 仓库本身时,文档源保存在 `devcodex-labs/vextjs`,构建后的静态站点保存在独立公开仓库 `vextjs/vextjs.github.io`,访问地址为 [https://vextjs.github.io/](https://vextjs.github.io/),base path 为 `/`。它与上文业务应用部署是两套流程。 +维护 VextJS 仓库本身时,文档源保存在 `devcodex-labs/vextjs`,同一提交发布到两个文档站。它们与上文业务应用部署是两套流程。 -首次发布需要以下配置,之后不需要手动复制构建结果: +| 站点 | 访问地址 | base path | 发布方式 | +| -------------- | ---------------------------------------------------------------------------------- | ---------- | ---------------------------------------------------------------------- | +| 源码仓库文档站 | [https://devcodex-labs.github.io/vextjs/](https://devcodex-labs.github.io/vextjs/) | `/vextjs/` | 源码仓库的 GitHub Actions Pages 部署 | +| 组织文档站 | [https://vextjs.github.io/](https://vextjs.github.io/) | `/` | 推送到独立公开仓库 `vextjs/vextjs.github.io` 后,由该仓库的 Pages 发布 | + +源码仓库的 `Settings → Pages → Source` 保持 **GitHub Actions**。新增组织站需要以下首次配置,之后不需要手动复制构建结果: 1. 在 `vextjs` 组织创建公开仓库 `vextjs.github.io`,初始化 `main` 分支。该仓库专门保存构建结果;发布时会替换根目录中的站点文件,删除旧产物并保留 Git 提交历史。 2. 为该仓库创建专用 SSH Deploy Key。公钥放入站点仓库的 `Settings → Deploy keys`,勾选 **Allow write access**;私钥通过源码仓库的 `Settings → Secrets and variables → Actions` 保存为 `VEXT_DOCS_DEPLOY_KEY`。不要把私钥放进源码、文档或聊天消息。 3. 在站点仓库的 `Settings → Pages` 选择 **Deploy from a branch**,分支选择 **main**、目录选择 **/(root)**。该组织根地址由仓库名称决定,无需配置 CNAME。 -`.github/workflows/docs.yml` 使用 Node.js 22,以 `VEXT_DOCS_BASE=/`、`VEXT_DOCS_SITE_URL=https://vextjs.github.io` 构建。自动发布跟随源码仓库 `main` 的成功 push CI,检出该次 CI 的精确 SHA,执行完整文档发布校验后,将产物通过专用 Deploy Key 推送到站点仓库。推送前检查源码 `main` 的当前提交;已被后续提交替代的构建会跳过发布。站点仓库的 Pages 随后发布新内容。 +`.github/workflows/docs.yml` 使用 Node.js 22,分别设置 `VEXT_DOCS_BASE` 与 `VEXT_DOCS_SITE_URL`,按表中的路径和地址构建两个站点。两份产物分别上传和校验,避免根路径与 `/vextjs/` 的资源链接混用。自动发布跟随源码仓库 `main` 的成功 push CI,检出该次 CI 的精确 SHA。 + +两份构建及完整文档发布校验均通过后,工作流启动两个独立发布任务:源码仓库使用 Pages artifact 与内置 `GITHUB_TOKEN`;组织站使用 `VEXT_DOCS_DEPLOY_KEY` 推送产物。组织站缺少密钥或推送失败,不会阻止源码仓库的发布任务;任一构建失败会阻止本次两个站点的发布。发布前再次检查源码 `main` 的当前提交;已被后续提交替代的构建会跳过发布。 -需要重新发布时,在源码仓库的 `Actions → Deploy Docs → Run workflow` 选择 `main`。手动入口同样执行完整文档校验;其他分支不能通过该入口发布到生产站点。构建失败不会推送站点文件;工作流完成推送后,仍需等待目标仓库的 Pages 发布任务完成才能看到更新。 +需要重新发布时,在源码仓库的 `Actions → Deploy Docs → Run workflow` 选择 `main`,同时重建和发布两个站点。手动入口同样执行完整文档校验;其他分支不能通过该入口发布到生产站点。组织站的推送任务成功后,仍需等待目标仓库的 Pages 发布任务完成才能看到更新。 ## 下一步 diff --git a/website/docs/zh/resources/documentation-data-and-ai.md b/website/docs/zh/resources/documentation-data-and-ai.md index 8cf116fc..b4fae826 100644 --- a/website/docs/zh/resources/documentation-data-and-ai.md +++ b/website/docs/zh/resources/documentation-data-and-ai.md @@ -14,19 +14,19 @@ VextJS 同时提供面向读者的文档页面和确定性的构建产物。这 以下链接为正式站点地址。中文预览阶段应读取对应本地构建中的文件,不假定线上已部署当前改造;接入时先检查实际 schemaVersion、rollout 与 verification。 -| 资产 | 用途 | -| ------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | -| [`docs-manifest.json`](https://vextjs.github.io/docs-manifest.json) | vext.docs-manifest/v2;文档身份、角色、语言、URL、源文件 hash 与关系索引。 | -| [`capabilities.json`](https://vextjs.github.io/capabilities.json) | 既有 v1 能力摘要与 non-goal;非完整能力定义或图谱,需再读对应细节和运行限制。 | -| [`ai-gold-questions.json`](https://vextjs.github.io/ai-gold-questions.json) | 问题及所需文档/路由、禁止声称的边界;用于回答回归,结构校验不等于语义正确。 | -| [`zh/llms.txt`](https://vextjs.github.io/zh/llms.txt) | 面向语言模型和文档工具的简体中文精选入口;它是索引,不是 crawler 控制文件。 | -| [`zh/llms-full.txt`](https://vextjs.github.io/zh/llms-full.txt) | 完整简体中文 URL 与摘要索引:每个公开中文文档页只出现一次。 | -| [`llms.txt`](https://vextjs.github.io/llms.txt) | 默认英文精选入口,与简体中文内容隔离。 | -| [`llms-full.txt`](https://vextjs.github.io/llms-full.txt) | 完整英文 URL 与摘要索引:每个公开英文文档页只出现一次。 | -| [`docs-events.schema.json`](https://vextjs.github.io/docs-events.schema.json) | 可选的隐私保护事件合同;VextJS 没有启用 collector。 | -| [`docs-dashboard-definition.json`](https://vextjs.github.io/docs-dashboard-definition.json) | 供未来自行选择合规 collector 的站点所有者使用的指标定义和采集边界。 | - -另外,构建生成 [`spec-rules.json`](https://vextjs.github.io/spec-rules.json),schemaVersion 为 vext.spec-rules/v1,由 Specification 正文投影规则身份、等级和链接。 +| 资产 | 用途 | +| --------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | +| [`docs-manifest.json`](https://devcodex-labs.github.io/vextjs/docs-manifest.json) | vext.docs-manifest/v2;文档身份、角色、语言、URL、源文件 hash 与关系索引。 | +| [`capabilities.json`](https://devcodex-labs.github.io/vextjs/capabilities.json) | 既有 v1 能力摘要与 non-goal;非完整能力定义或图谱,需再读对应细节和运行限制。 | +| [`ai-gold-questions.json`](https://devcodex-labs.github.io/vextjs/ai-gold-questions.json) | 问题及所需文档/路由、禁止声称的边界;用于回答回归,结构校验不等于语义正确。 | +| [`zh/llms.txt`](https://devcodex-labs.github.io/vextjs/zh/llms.txt) | 面向语言模型和文档工具的简体中文精选入口;它是索引,不是 crawler 控制文件。 | +| [`zh/llms-full.txt`](https://devcodex-labs.github.io/vextjs/zh/llms-full.txt) | 完整简体中文 URL 与摘要索引:每个公开中文文档页只出现一次。 | +| [`llms.txt`](https://devcodex-labs.github.io/vextjs/llms.txt) | 默认英文精选入口,与简体中文内容隔离。 | +| [`llms-full.txt`](https://devcodex-labs.github.io/vextjs/llms-full.txt) | 完整英文 URL 与摘要索引:每个公开英文文档页只出现一次。 | +| [`docs-events.schema.json`](https://devcodex-labs.github.io/vextjs/docs-events.schema.json) | 可选的隐私保护事件合同;VextJS 没有启用 collector。 | +| [`docs-dashboard-definition.json`](https://devcodex-labs.github.io/vextjs/docs-dashboard-definition.json) | 供未来自行选择合规 collector 的站点所有者使用的指标定义和采集边界。 | + +另外,构建生成 [`spec-rules.json`](https://devcodex-labs.github.io/vextjs/spec-rules.json),schemaVersion 为 vext.spec-rules/v1,由 Specification 正文投影规则身份、等级和链接。 manifest、rules 与 llms 索引在站点构建后生成,不含构建时间戳;固定文档源、构建合同、导航、问题集、依赖锁及站点配置时输出可重复。capabilities、问题集与度量合同是公开源资产,不应将它们误认为全部从正文自动提取。 diff --git a/website/rspress.config.ts b/website/rspress.config.ts index bc7c92a2..1db4948f 100644 --- a/website/rspress.config.ts +++ b/website/rspress.config.ts @@ -7,8 +7,8 @@ import { resolveDocsVerification, } from "./scripts/docs-rollout.mjs"; -const DEFAULT_DOCS_BASE = "/"; -const DEFAULT_DOCS_SITE_URL = "https://vextjs.github.io"; +const DEFAULT_DOCS_BASE = "/vextjs/"; +const DEFAULT_DOCS_SITE_URL = "https://devcodex-labs.github.io/vextjs"; function normalizeDocsBase(value?: string) { const raw = value?.trim() || DEFAULT_DOCS_BASE; diff --git a/website/scripts/generate-machine-artifacts.mjs b/website/scripts/generate-machine-artifacts.mjs index 922b3331..c6c1f226 100644 --- a/website/scripts/generate-machine-artifacts.mjs +++ b/website/scripts/generate-machine-artifacts.mjs @@ -33,7 +33,7 @@ const docsRoot = path.join(websiteRoot, "docs"); const distRoot = path.join(websiteRoot, "dist"); const rollout = resolveDocsRollout(); const verification = resolveDocsVerification(); -const DEFAULT_DOCS_SITE_URL = "https://vextjs.github.io"; +const DEFAULT_DOCS_SITE_URL = "https://devcodex-labs.github.io/vextjs"; const docsSiteUrl = ( process.env.VEXT_DOCS_SITE_URL || DEFAULT_DOCS_SITE_URL ).replace(/\/+$/, ""); From 3b852bccdcce122bdc7d0e0a44eec347ad79ac4f Mon Sep 17 00:00:00 2001 From: Rocky shi Date: Sat, 10 Oct 2026 02:38:54 +0000 Subject: [PATCH 3/3] ci: skip organization docs publishing until deployment key is configured --- .github/workflows/docs.yml | 21 +++++++++++++++++++-- website/docs/en/guide/deployment.md | 2 +- website/docs/zh/guide/deployment.md | 2 +- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 15b23bdd..131f4a87 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -143,11 +143,12 @@ jobs: # 在进入发布并发组前跳过旧 CI 的迟到构建。 prepare-deployment: - name: Check deployment commit + name: Check deployment prerequisites runs-on: ubuntu-latest needs: build outputs: current: ${{ steps.current.outputs.publish }} + organization_ready: ${{ steps.organization.outputs.ready }} steps: - name: Check current main commit id: current @@ -163,6 +164,20 @@ jobs: echo "publish=false" >> "$GITHUB_OUTPUT" fi + - name: Check organization deployment setup + id: organization + if: steps.current.outputs.publish == 'true' + env: + DOCS_DEPLOY_KEY: ${{ secrets.VEXT_DOCS_DEPLOY_KEY }} + shell: bash + run: | + if [[ -n "$DOCS_DEPLOY_KEY" ]]; then + echo "ready=true" >> "$GITHUB_OUTPUT" + else + echo "ready=false" >> "$GITHUB_OUTPUT" + echo "::notice::Skipping organization Pages publication until VEXT_DOCS_DEPLOY_KEY is configured." + fi + # 原源码仓库 Pages 保留官方 Actions 发布流程,与组织站点并行。 deploy-pages: name: Publish source repository Pages @@ -206,7 +221,9 @@ jobs: name: Publish to vextjs.github.io runs-on: ubuntu-latest needs: prepare-deployment - if: needs.prepare-deployment.outputs.current == 'true' + if: >- + needs.prepare-deployment.outputs.current == 'true' && + needs.prepare-deployment.outputs.organization_ready == 'true' # 只串行化已通过构建且仍对应 main 的发布,不中断正在进行的 Git 推送。 concurrency: diff --git a/website/docs/en/guide/deployment.md b/website/docs/en/guide/deployment.md index bd49c063..2df38d1f 100644 --- a/website/docs/en/guide/deployment.md +++ b/website/docs/en/guide/deployment.md @@ -902,7 +902,7 @@ Keep **GitHub Actions** selected in the source repository's `Settings → Pages `.github/workflows/docs.yml` builds with Node.js 22 and sets `VEXT_DOCS_BASE` and `VEXT_DOCS_SITE_URL` separately for the paths and URLs in the table. Both artifacts are validated and uploaded separately to keep root-path assets distinct from `/vextjs/` assets. Automatic publishing follows a successful source-repository `main` push CI and checks out that exact SHA. -After both builds and their complete documentation publishing checks pass, two independent publishing jobs start: the source repository uses a Pages artifact and the built-in `GITHUB_TOKEN`; the organization site uses `VEXT_DOCS_DEPLOY_KEY` to push its output. A missing organization key or a failed organization push does not block the source repository's publishing job. Either build failing prevents both sites from publishing in that run. Before publishing, each job checks the current source `main` commit and skips builds superseded by a later commit. +After both builds and their complete documentation publishing checks pass, independent publishing jobs start: the source repository uses a Pages artifact and the built-in `GITHUB_TOKEN`; the organization site uses `VEXT_DOCS_DEPLOY_KEY` to push its output. Until that key is configured, the workflow skips organization publication with a notice and continues publishing the source site. After setup, a failed organization push also does not block the source repository's publishing job. Either build failing prevents both sites from publishing in that run. Before publishing, each job checks the current source `main` commit and skips builds superseded by a later commit. To rebuild and republish both sites, select `main` in the source repository's `Actions → Deploy Docs → Run workflow`. This manual entry also runs the complete documentation checks; other branches cannot publish to the production site through it. After the organization site's push succeeds, wait for the target repository's Pages publishing job to finish before checking the updated site. diff --git a/website/docs/zh/guide/deployment.md b/website/docs/zh/guide/deployment.md index 8841ab30..81aa4163 100644 --- a/website/docs/zh/guide/deployment.md +++ b/website/docs/zh/guide/deployment.md @@ -905,7 +905,7 @@ Job scheduler 和 worker 使用独立于 HTTP 的进程。用 `npx vextjs job sc `.github/workflows/docs.yml` 使用 Node.js 22,分别设置 `VEXT_DOCS_BASE` 与 `VEXT_DOCS_SITE_URL`,按表中的路径和地址构建两个站点。两份产物分别上传和校验,避免根路径与 `/vextjs/` 的资源链接混用。自动发布跟随源码仓库 `main` 的成功 push CI,检出该次 CI 的精确 SHA。 -两份构建及完整文档发布校验均通过后,工作流启动两个独立发布任务:源码仓库使用 Pages artifact 与内置 `GITHUB_TOKEN`;组织站使用 `VEXT_DOCS_DEPLOY_KEY` 推送产物。组织站缺少密钥或推送失败,不会阻止源码仓库的发布任务;任一构建失败会阻止本次两个站点的发布。发布前再次检查源码 `main` 的当前提交;已被后续提交替代的构建会跳过发布。 +两份构建及完整文档发布校验均通过后,工作流启动独立发布任务:源码仓库使用 Pages artifact 与内置 `GITHUB_TOKEN`;组织站使用 `VEXT_DOCS_DEPLOY_KEY` 推送产物。尚未配置该密钥时,工作流跳过组织站发布并记录提示,源码仓库仍照常发布。配置完成后的组织站推送失败,也不会阻止源码仓库的发布任务;任一构建失败会阻止本次两个站点的发布。发布前再次检查源码 `main` 的当前提交;已被后续提交替代的构建会跳过发布。 需要重新发布时,在源码仓库的 `Actions → Deploy Docs → Run workflow` 选择 `main`,同时重建和发布两个站点。手动入口同样执行完整文档校验;其他分支不能通过该入口发布到生产站点。组织站的推送任务成功后,仍需等待目标仓库的 Pages 发布任务完成才能看到更新。