diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4a7450b5..2d619ed7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,4 +23,4 @@ permissions: jobs: check: name: CI - uses: kirchDev/workflows/.github/workflows/_ci-check.yml@7fd4eaf529500fcd07c527ae70c839ab9ac7d76f # v0.7.0 + uses: kirchDev/workflows/.github/workflows/_ci-check.yml@94cbcbd676b989ac6c6327055a240132f5cd76a5 # v0.8.0 diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 9d363d7b..6022683f 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -28,4 +28,4 @@ jobs: packages: read actions: read contents: read - uses: kirchDev/workflows/.github/workflows/_codeql.yml@7fd4eaf529500fcd07c527ae70c839ab9ac7d76f # v0.7.0 + uses: kirchDev/workflows/.github/workflows/_codeql.yml@94cbcbd676b989ac6c6327055a240132f5cd76a5 # v0.8.0 diff --git a/.github/workflows/fast-forward-queue.yml b/.github/workflows/fast-forward-queue.yml index c84db007..8467a90a 100644 --- a/.github/workflows/fast-forward-queue.yml +++ b/.github/workflows/fast-forward-queue.yml @@ -34,7 +34,7 @@ jobs: pull-requests: read checks: read statuses: read - uses: kirchDev/workflows/.github/workflows/_fast-forward-queue.yml@7fd4eaf529500fcd07c527ae70c839ab9ac7d76f # v0.7.0 + uses: kirchDev/workflows/.github/workflows/_fast-forward-queue.yml@94cbcbd676b989ac6c6327055a240132f5cd76a5 # v0.8.0 with: pr: ${{ inputs.pr }} secrets: diff --git a/.github/workflows/promotion-pr.yml b/.github/workflows/promotion-pr.yml index a7bc9f7c..ee23edba 100644 --- a/.github/workflows/promotion-pr.yml +++ b/.github/workflows/promotion-pr.yml @@ -18,4 +18,4 @@ permissions: jobs: promotion-pr: name: Promotion PR - uses: kirchDev/workflows/.github/workflows/_promotion-pr.yml@7fd4eaf529500fcd07c527ae70c839ab9ac7d76f # v0.7.0 + uses: kirchDev/workflows/.github/workflows/_promotion-pr.yml@94cbcbd676b989ac6c6327055a240132f5cd76a5 # v0.8.0 diff --git a/.github/workflows/queue-branch.yml b/.github/workflows/queue-branch.yml index aedbf6a2..17a67919 100644 --- a/.github/workflows/queue-branch.yml +++ b/.github/workflows/queue-branch.yml @@ -20,6 +20,6 @@ jobs: permissions: contents: read pull-requests: write - uses: kirchDev/workflows/.github/workflows/_queue-branch.yml@7fd4eaf529500fcd07c527ae70c839ab9ac7d76f # v0.7.0 + uses: kirchDev/workflows/.github/workflows/_queue-branch.yml@94cbcbd676b989ac6c6327055a240132f5cd76a5 # v0.8.0 secrets: BWS_ACCESS_TOKEN: ${{ secrets.BWS_ACCESS_TOKEN }} diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml index 5fb6dae4..0ba2f4b7 100644 --- a/.github/workflows/release-please.yml +++ b/.github/workflows/release-please.yml @@ -15,6 +15,6 @@ jobs: permissions: contents: write pull-requests: write - uses: kirchDev/workflows/.github/workflows/_release-please.yml@7fd4eaf529500fcd07c527ae70c839ab9ac7d76f # v0.7.0 + uses: kirchDev/workflows/.github/workflows/_release-please.yml@94cbcbd676b989ac6c6327055a240132f5cd76a5 # v0.8.0 secrets: BWS_ACCESS_TOKEN: ${{ secrets.BWS_ACCESS_TOKEN }} diff --git a/package.json b/package.json index 18a81450..479237ab 100644 --- a/package.json +++ b/package.json @@ -58,5 +58,5 @@ "engines": { "node": ">=24" }, - "packageManager": "pnpm@12.2.1" + "packageManager": "pnpm@12.3.4" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4ff01dff..4b479c1c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,96 +7,96 @@ importers: configDependencies: {} packageManagerDependencies: pnpm: - specifier: 12.2.1 - version: 12.2.1 + specifier: 12.3.4 + version: 12.3.4 packages: - '@pnpm/exe.darwin-arm64@12.2.1': - resolution: {integrity: sha512-efC1yfz2xbyHiMLrQAYtnoo5XP20LeAiYYcyL1962qQagZrMXIB0BoQYeZoPTLggLh0Q4MD7jpZUInU5fWxCgQ==} + '@pnpm/exe.darwin-arm64@12.3.4': + resolution: {integrity: sha512-PAyUol8T1+/+ViOiXAt51ECA+QnfXCqz6foL4bW+LsoX0NcVd5XVEM2mRQu+LV4oc7uRz9zf9U0P+XFfuQeDAw==} cpu: [arm64] os: [darwin] - '@pnpm/exe.darwin-x64@12.2.1': - resolution: {integrity: sha512-0bloFmxrvYY5LYex5V6SZySwg+egBk0pOW+YUeOm9fiG2U1wv+qRVLBOUvIzLAeJE7vBlAzxUwXkQAYtr12n+Q==} + '@pnpm/exe.darwin-x64@12.3.4': + resolution: {integrity: sha512-fxP9JCk0Cdye+ePuj+GJJLMUMTqHGWRdb1dtv4How876uQ2ehxvenpgiYAir/ceO9PsYUZkFTtyZdx+rRu5QOA==} cpu: [x64] os: [darwin] - '@pnpm/exe.linux-arm64-musl@12.2.1': - resolution: {integrity: sha512-AZl7apVZC4TV1/vTp/bS16XUsHeqx9AHsU4V55joiGR+iR6vl+WF0WlGvGCTjqjICS4q/kThpgNrtG8aqQ9seQ==} + '@pnpm/exe.linux-arm64-musl@12.3.4': + resolution: {integrity: sha512-FBOt0/7ye6O6q4AllVV5QMviB6qE6fqkeczV/+MDWQsmo+QJrlfsh6X7CpH/tClVpBZEyIbjpUoT8bNhCYBxEg==} cpu: [arm64] os: [linux] libc: [musl] - '@pnpm/exe.linux-arm64@12.2.1': - resolution: {integrity: sha512-S36+tMEGrPz3nwtfFU9kYxbHoi8sV7WJfMO9njEL4jRaShTNaLRERMAqyI2DUCiA5QCr6/a50lt4+pKCV2mCvw==} + '@pnpm/exe.linux-arm64@12.3.4': + resolution: {integrity: sha512-t71AVA7LRqiKTyZ5xMYaZc2n5DfdpMbfokZuiIOXHBOM03ECnF0t4iYwaBDqJgVjlKYUOwaF/bRQajGNA4cJ4w==} cpu: [arm64] os: [linux] libc: [glibc] - '@pnpm/exe.linux-x64-musl@12.2.1': - resolution: {integrity: sha512-4MQClkAk1em55LFZJpeIqb7j+gEqCgX8yC42j9DFWL42q1uMX1e1tvTy2Dtd4NoWQqgdkLxOStZ+D9CYC+28ow==} + '@pnpm/exe.linux-x64-musl@12.3.4': + resolution: {integrity: sha512-RPmk7Jb/aYaFvL2iyDN/AtMY+hUEsue732WmXpcuQ9tBpMnGyA5py7Z3+e+qmQaJ0zY/4ni9jJiyPBQHujmv6w==} cpu: [x64] os: [linux] libc: [musl] - '@pnpm/exe.linux-x64@12.2.1': - resolution: {integrity: sha512-A/AlR71Leph7qgB3ThSU9yU/vLfre4HmP6nbt3/qt51fzAjQ0xuq7j+cw0f1yDskzOsGzmo5uD6ruefCwLK5uQ==} + '@pnpm/exe.linux-x64@12.3.4': + resolution: {integrity: sha512-2ZqOlSPkfwX1h5cR+FPiWf8+F+2hZT/3TvhUK5sigHqwaQCIiq8R7CGxhndKs63JtcLi2a1Qpo+wX/EoyfjyJQ==} cpu: [x64] os: [linux] libc: [glibc] - '@pnpm/exe.win32-arm64@12.2.1': - resolution: {integrity: sha512-TEGUmroT6NGfo2O2+tHK9Zr1lhP1zLzpwx+QAQV19l8V4ljUoMfz8Os5V9zzNCtIpzyKcK7SuG7fkVbxFgRMzg==} + '@pnpm/exe.win32-arm64@12.3.4': + resolution: {integrity: sha512-ANyrHqyqco6SXBysUTRF74itDyyraea7IbFsKFdNXTjcFnfycTDx37EwuhdpPYFNSIh2JhUG4fByclsRfiHX7w==} cpu: [arm64] os: [win32] - '@pnpm/exe.win32-x64@12.2.1': - resolution: {integrity: sha512-V2Q+AF8fCsw8/CC3bWF8kopOmH0aAjgk9m7H7uAQNulOYIJs9YJBiAlgByswmt+igV9axc4dBI//ZlK2NKpDcw==} + '@pnpm/exe.win32-x64@12.3.4': + resolution: {integrity: sha512-WH/KqBPY/hq2Tb7SgQltEZytimcjgKRaCRL/aM9CI0c67iKc5TVmHUhIiL3Ux9FB4bWn36i6XewUcScQI+zG8w==} cpu: [x64] os: [win32] - pnpm@12.2.1: - resolution: {integrity: sha512-9Vymiqy561q2nGb4KKmK+JoyKGcDrvH42hMcp+q01nfzS/qF4YZGepGcB5nfi29KokD33CkZszsycxkBBBYmFg==} + pnpm@12.3.4: + resolution: {integrity: sha512-lhqkH7B32joEpEHZ+OFevAyW2o73ELLrZ7+e58sGEOq9SPH9hfUc/+c4RnhfoPh8VqOocqHYk/hEZ0G1zORUVw==} engines: {node: '>=18.*'} hasBin: true snapshots: - '@pnpm/exe.darwin-arm64@12.2.1': + '@pnpm/exe.darwin-arm64@12.3.4': optional: true - '@pnpm/exe.darwin-x64@12.2.1': + '@pnpm/exe.darwin-x64@12.3.4': optional: true - '@pnpm/exe.linux-arm64-musl@12.2.1': + '@pnpm/exe.linux-arm64-musl@12.3.4': optional: true - '@pnpm/exe.linux-arm64@12.2.1': + '@pnpm/exe.linux-arm64@12.3.4': optional: true - '@pnpm/exe.linux-x64-musl@12.2.1': + '@pnpm/exe.linux-x64-musl@12.3.4': optional: true - '@pnpm/exe.linux-x64@12.2.1': + '@pnpm/exe.linux-x64@12.3.4': optional: true - '@pnpm/exe.win32-arm64@12.2.1': + '@pnpm/exe.win32-arm64@12.3.4': optional: true - '@pnpm/exe.win32-x64@12.2.1': + '@pnpm/exe.win32-x64@12.3.4': optional: true - pnpm@12.2.1: + pnpm@12.3.4: optionalDependencies: - '@pnpm/exe.darwin-arm64': 12.2.1 - '@pnpm/exe.darwin-x64': 12.2.1 - '@pnpm/exe.linux-arm64': 12.2.1 - '@pnpm/exe.linux-arm64-musl': 12.2.1 - '@pnpm/exe.linux-x64': 12.2.1 - '@pnpm/exe.linux-x64-musl': 12.2.1 - '@pnpm/exe.win32-arm64': 12.2.1 - '@pnpm/exe.win32-x64': 12.2.1 + '@pnpm/exe.darwin-arm64': 12.3.4 + '@pnpm/exe.darwin-x64': 12.3.4 + '@pnpm/exe.linux-arm64': 12.3.4 + '@pnpm/exe.linux-arm64-musl': 12.3.4 + '@pnpm/exe.linux-x64': 12.3.4 + '@pnpm/exe.linux-x64-musl': 12.3.4 + '@pnpm/exe.win32-arm64': 12.3.4 + '@pnpm/exe.win32-x64': 12.3.4 --- lockfileVersion: '9.0' diff --git a/www/.data/content/contents.sqlite b/www/.data/content/contents.sqlite new file mode 100644 index 00000000..48981fb9 Binary files /dev/null and b/www/.data/content/contents.sqlite differ diff --git a/www/.data/content/github.com-kirchDev-workflows-main b/www/.data/content/github.com-kirchDev-workflows-main new file mode 160000 index 00000000..7ad702c2 --- /dev/null +++ b/www/.data/content/github.com-kirchDev-workflows-main @@ -0,0 +1 @@ +Subproject commit 7ad702c291ecc86de464a64374763dd79b0635be diff --git a/www/.data/content/github.com-kirchDev-workflows-tag-v0.7.0 b/www/.data/content/github.com-kirchDev-workflows-tag-v0.7.0 new file mode 160000 index 00000000..7fd4eaf5 --- /dev/null +++ b/www/.data/content/github.com-kirchDev-workflows-tag-v0.7.0 @@ -0,0 +1 @@ +Subproject commit 7fd4eaf529500fcd07c527ae70c839ab9ac7d76f diff --git a/www/.nuxt/app.config.mjs b/www/.nuxt/app.config.mjs new file mode 100644 index 00000000..0b712c13 --- /dev/null +++ b/www/.nuxt/app.config.mjs @@ -0,0 +1,21 @@ + +import { defuFn } from 'defu' + +const inlineConfig = { + "nuxt": {} +} + +/** client **/ +import { _replaceAppConfig } from '#app/config' + +// Vite - webpack is handled directly in #app/config +if (import.meta.dev && !import.meta.nitro && import.meta.hot) { + import.meta.hot.accept((newModule) => { + _replaceAppConfig(newModule.default) + }) +} +/** client-end **/ + + + +export default /*@__PURE__*/ defuFn(inlineConfig) diff --git a/www/.nuxt/cache/nuxt/icon/lucide_bot_5_gA74R7dhvv2zR_CefjvFBqmJmVETaodqkqNEg2wms_M.json b/www/.nuxt/cache/nuxt/icon/lucide_bot_5_gA74R7dhvv2zR_CefjvFBqmJmVETaodqkqNEg2wms_M.json new file mode 100644 index 00000000..165411ff --- /dev/null +++ b/www/.nuxt/cache/nuxt/icon/lucide_bot_5_gA74R7dhvv2zR_CefjvFBqmJmVETaodqkqNEg2wms_M.json @@ -0,0 +1 @@ +{"expires":1789149585134,"value":{"code":200,"headers":{"etag":"W/\"xXXQ7Xpigm\"","last-modified":"Fri, 04 Sep 2026 17:59:45 GMT","cache-control":"s-maxage=604800, stale-while-revalidate"},"body":{"prefix":"lucide","icons":{"bot":{"body":""},"code":{"body":""},"git-merge":{"body":""},"package":{"body":""},"palette":{"body":""}},"lastModified":1787982846,"width":24,"height":24}},"mtime":1788544785140,"integrity":"EhcnHHMtfv"} \ No newline at end of file diff --git a/www/.nuxt/cache/nuxt/icon/lucide_bot_6_uiybHHAmFQcgSVvHl0QymhHErHErbeZbuQYUrxSk7I.json b/www/.nuxt/cache/nuxt/icon/lucide_bot_6_uiybHHAmFQcgSVvHl0QymhHErHErbeZbuQYUrxSk7I.json new file mode 100644 index 00000000..d7346dff --- /dev/null +++ b/www/.nuxt/cache/nuxt/icon/lucide_bot_6_uiybHHAmFQcgSVvHl0QymhHErHErbeZbuQYUrxSk7I.json @@ -0,0 +1 @@ +{"expires":1789224632040,"value":{"code":200,"headers":{"etag":"W/\"xeq0ixRQpS\"","last-modified":"Sat, 05 Sep 2026 14:50:32 GMT","cache-control":"s-maxage=604800, stale-while-revalidate"},"body":{"prefix":"lucide","icons":{"bot":{"body":""},"code":{"body":""},"git-merge":{"body":""},"github":{"body":"","hidden":true},"package":{"body":""},"palette":{"body":""}},"lastModified":1787982846,"width":24,"height":24}},"mtime":1788619832045,"integrity":"EhcnHHMtfv"} \ No newline at end of file diff --git a/www/.nuxt/cache/nuxt/icon/lucide_box_4_X0LKERbmQxXNhkRKcEcE9TWTL07PjMVSqlT0wRt1M0E.json b/www/.nuxt/cache/nuxt/icon/lucide_box_4_X0LKERbmQxXNhkRKcEcE9TWTL07PjMVSqlT0wRt1M0E.json new file mode 100644 index 00000000..f07633ec --- /dev/null +++ b/www/.nuxt/cache/nuxt/icon/lucide_box_4_X0LKERbmQxXNhkRKcEcE9TWTL07PjMVSqlT0wRt1M0E.json @@ -0,0 +1 @@ +{"expires":1789146173613,"value":{"code":200,"headers":{"etag":"W/\"YOTUnQbP8d\"","last-modified":"Fri, 04 Sep 2026 17:02:53 GMT","cache-control":"s-maxage=604800, stale-while-revalidate"},"body":{"prefix":"lucide","icons":{"box":{"body":""},"code":{"body":""},"paintbrush":{"body":""},"palette":{"body":""}},"lastModified":1787982846,"width":24,"height":24}},"mtime":1788541373614,"integrity":"EhcnHHMtfv"} \ No newline at end of file diff --git a/www/.nuxt/cache/nuxt/icon/lucide_circlealert_3_klaqnu5JSkG1HW0hbeketi1pRJnwkyf0U7nFwEqHU8.json b/www/.nuxt/cache/nuxt/icon/lucide_circlealert_3_klaqnu5JSkG1HW0hbeketi1pRJnwkyf0U7nFwEqHU8.json new file mode 100644 index 00000000..fb679b83 --- /dev/null +++ b/www/.nuxt/cache/nuxt/icon/lucide_circlealert_3_klaqnu5JSkG1HW0hbeketi1pRJnwkyf0U7nFwEqHU8.json @@ -0,0 +1 @@ +{"expires":1789146149854,"value":{"code":200,"headers":{"etag":"W/\"pftWn0HJFg\"","last-modified":"Fri, 04 Sep 2026 17:02:29 GMT","cache-control":"s-maxage=604800, stale-while-revalidate"},"body":{"prefix":"lucide","icons":{"circle-alert":{"body":""},"message-circle":{"body":""},"star":{"body":""}},"lastModified":1787982846,"width":24,"height":24}},"mtime":1788541349854,"integrity":"EhcnHHMtfv"} \ No newline at end of file diff --git a/www/.nuxt/cache/nuxt/icon/lucide_github_2_zxJW8meyYMFUjoQZJE6P3yawFXG_HN7SH3KwyQv6Fz8.json b/www/.nuxt/cache/nuxt/icon/lucide_github_2_zxJW8meyYMFUjoQZJE6P3yawFXG_HN7SH3KwyQv6Fz8.json new file mode 100644 index 00000000..f54b4ee1 --- /dev/null +++ b/www/.nuxt/cache/nuxt/icon/lucide_github_2_zxJW8meyYMFUjoQZJE6P3yawFXG_HN7SH3KwyQv6Fz8.json @@ -0,0 +1 @@ +{"expires":1789146149796,"value":{"code":200,"headers":{"etag":"W/\"w1gTDDr4lh\"","last-modified":"Fri, 04 Sep 2026 17:02:29 GMT","cache-control":"s-maxage=604800, stale-while-revalidate"},"body":{"prefix":"lucide","icons":{"github":{"body":"","hidden":true},"workflow":{"body":""}},"lastModified":1787982846,"width":24,"height":24}},"mtime":1788541349806,"integrity":"EhcnHHMtfv"} \ No newline at end of file diff --git a/www/.nuxt/cache/nuxt/icon/vscodeicons_filetypemarkdown_2_Xa8f3SQrBSymNSEigs5hFnHB1oHyQtakLRn3H2HerVY.json b/www/.nuxt/cache/nuxt/icon/vscodeicons_filetypemarkdown_2_Xa8f3SQrBSymNSEigs5hFnHB1oHyQtakLRn3H2HerVY.json new file mode 100644 index 00000000..d905ee12 --- /dev/null +++ b/www/.nuxt/cache/nuxt/icon/vscodeicons_filetypemarkdown_2_Xa8f3SQrBSymNSEigs5hFnHB1oHyQtakLRn3H2HerVY.json @@ -0,0 +1 @@ +{"expires":1789151488775,"value":{"code":200,"headers":{"etag":"W/\"IaA51VcfCG\"","last-modified":"Fri, 04 Sep 2026 18:31:28 GMT","cache-control":"s-maxage=604800, stale-while-revalidate"},"body":{"prefix":"vscode-icons","icons":{"file-type-markdown":{"body":""},"file-type-npm":{"body":""}},"lastModified":1787983126,"width":32,"height":32}},"mtime":1788546688792,"integrity":"EhcnHHMtfv"} \ No newline at end of file diff --git a/www/.nuxt/cache/nuxt/icon/vscodeicons_filetypemarkdown_3_i2_YtZEqyhkorpwd3Yca9NIVi6skvpfJHCce69OQqRk.json b/www/.nuxt/cache/nuxt/icon/vscodeicons_filetypemarkdown_3_i2_YtZEqyhkorpwd3Yca9NIVi6skvpfJHCce69OQqRk.json new file mode 100644 index 00000000..3c07f98e --- /dev/null +++ b/www/.nuxt/cache/nuxt/icon/vscodeicons_filetypemarkdown_3_i2_YtZEqyhkorpwd3Yca9NIVi6skvpfJHCce69OQqRk.json @@ -0,0 +1 @@ +{"expires":1789146599647,"value":{"code":200,"headers":{"etag":"W/\"DR6zzQI9sG\"","last-modified":"Fri, 04 Sep 2026 17:09:59 GMT","cache-control":"s-maxage=604800, stale-while-revalidate"},"body":{"prefix":"vscode-icons","icons":{"file-type-markdown":{"body":""},"file-type-npm":{"body":""},"file-type-nuxt":{"body":""}},"lastModified":1787983126,"width":32,"height":32}},"mtime":1788541799648,"integrity":"EhcnHHMtfv"} \ No newline at end of file diff --git a/www/.nuxt/cache/nuxt/icon/vscodeicons_filetypeyaml_1_4JvddjiFLmGl3G7wmwdWhy96S1gfz9gJV2rRXKAKEJo.json b/www/.nuxt/cache/nuxt/icon/vscodeicons_filetypeyaml_1_4JvddjiFLmGl3G7wmwdWhy96S1gfz9gJV2rRXKAKEJo.json new file mode 100644 index 00000000..6731ee33 --- /dev/null +++ b/www/.nuxt/cache/nuxt/icon/vscodeicons_filetypeyaml_1_4JvddjiFLmGl3G7wmwdWhy96S1gfz9gJV2rRXKAKEJo.json @@ -0,0 +1 @@ +{"expires":1789146165179,"value":{"code":200,"headers":{"etag":"W/\"CIwv5rfR4n\"","last-modified":"Fri, 04 Sep 2026 17:02:45 GMT","cache-control":"s-maxage=604800, stale-while-revalidate"},"body":{"prefix":"vscode-icons","icons":{"file-type-yaml":{"body":""}},"lastModified":1787983126,"width":32,"height":32}},"mtime":1788541365214,"integrity":"EhcnHHMtfv"} \ No newline at end of file diff --git a/www/.nuxt/components.d.ts b/www/.nuxt/components.d.ts new file mode 100644 index 00000000..2bf84e76 --- /dev/null +++ b/www/.nuxt/components.d.ts @@ -0,0 +1,66 @@ + +import type { DefineComponent, SlotsType } from 'vue' +type IslandComponent = DefineComponent<{}, {refresh: () => Promise}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, SlotsType<{ fallback: { error: unknown } }>> & T + +type HydrationStrategies = { + hydrateOnVisible?: IntersectionObserverInit | true + hydrateOnIdle?: number | true + hydrateOnInteraction?: keyof HTMLElementEventMap | Array | true + hydrateOnMediaQuery?: string + hydrateAfter?: number + hydrateWhen?: boolean + hydrateNever?: true +} +type LazyComponent = DefineComponent void }> & T + + +export const NuxtWelcome: typeof import("../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/welcome.vue")['default'] +export const NuxtLayout: typeof import("../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-layout")['default'] +export const NuxtErrorBoundary: typeof import("../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-error-boundary.vue")['default'] +export const ClientOnly: typeof import("../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/client-only")['default'] +export const DevOnly: typeof import("../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/dev-only")['default'] +export const ServerPlaceholder: typeof import("../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/server-placeholder")['default'] +export const NuxtLink: typeof import("../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-link")['default'] +export const NuxtLoadingIndicator: typeof import("../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-loading-indicator")['default'] +export const NuxtTime: typeof import("../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-time.vue")['default'] +export const NuxtRouteAnnouncer: typeof import("../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-route-announcer")['default'] +export const NuxtAnnouncer: typeof import("../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-announcer")['default'] +export const NuxtImg: typeof import("../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-stubs")['NuxtImg'] +export const NuxtPicture: typeof import("../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-stubs")['NuxtPicture'] +export const NuxtPage: typeof import("../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/pages/runtime/page-placeholder")['default'] +export const NoScript: typeof import("../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/head/runtime/components")['NoScript'] +export const Link: typeof import("../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/head/runtime/components")['Link'] +export const Base: typeof import("../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/head/runtime/components")['Base'] +export const Title: typeof import("../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/head/runtime/components")['Title'] +export const Meta: typeof import("../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/head/runtime/components")['Meta'] +export const Style: typeof import("../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/head/runtime/components")['Style'] +export const Head: typeof import("../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/head/runtime/components")['Head'] +export const Html: typeof import("../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/head/runtime/components")['Html'] +export const Body: typeof import("../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/head/runtime/components")['Body'] +export const NuxtIsland: typeof import("../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-island")['default'] +export const LazyNuxtWelcome: LazyComponent +export const LazyNuxtLayout: LazyComponent +export const LazyNuxtErrorBoundary: LazyComponent +export const LazyClientOnly: LazyComponent +export const LazyDevOnly: LazyComponent +export const LazyServerPlaceholder: LazyComponent +export const LazyNuxtLink: LazyComponent +export const LazyNuxtLoadingIndicator: LazyComponent +export const LazyNuxtTime: LazyComponent +export const LazyNuxtRouteAnnouncer: LazyComponent +export const LazyNuxtAnnouncer: LazyComponent +export const LazyNuxtImg: LazyComponent +export const LazyNuxtPicture: LazyComponent +export const LazyNuxtPage: LazyComponent +export const LazyNoScript: LazyComponent +export const LazyLink: LazyComponent +export const LazyBase: LazyComponent +export const LazyTitle: LazyComponent +export const LazyMeta: LazyComponent +export const LazyStyle: LazyComponent +export const LazyHead: LazyComponent +export const LazyHtml: LazyComponent +export const LazyBody: LazyComponent +export const LazyNuxtIsland: LazyComponent + +export const componentNames: string[] diff --git a/www/.nuxt/content/components.ts b/www/.nuxt/content/components.ts new file mode 100644 index 00000000..e9becbcc --- /dev/null +++ b/www/.nuxt/content/components.ts @@ -0,0 +1,175 @@ +const pickExport = (mod, exportName, componentName, path) => { + const resolved = exportName === 'default' ? mod?.default : mod?.[exportName] + if (!resolved) { + throw new Error(`[nuxt-content] Missing export "${exportName}" for component "${componentName}" in "${path}".`) + } + return resolved +} +export const localComponentLoaders = { + Callout: () => import("./../../../app/components/content/Callout.vue").then(m => pickExport(m, "default", "Callout", "./../../../app/components/content/Callout.vue")), + FileTree: () => import("./../../../app/components/content/FileTree.vue").then(m => pickExport(m, "default", "FileTree", "./../../../app/components/content/FileTree.vue")), + PackageManagers: () => import("./../../../app/components/content/PackageManagers.vue").then(m => pickExport(m, "default", "PackageManagers", "./../../../app/components/content/PackageManagers.vue")), + PageCards: () => import("./../../../app/components/content/PageCards.vue").then(m => pickExport(m, "default", "PageCards", "./../../../app/components/content/PageCards.vue")), + ProseH2: () => import("./../../../app/components/content/ProseH2.vue").then(m => pickExport(m, "default", "ProseH2", "./../../../app/components/content/ProseH2.vue")), + ProseH3: () => import("./../../../app/components/content/ProseH3.vue").then(m => pickExport(m, "default", "ProseH3", "./../../../app/components/content/ProseH3.vue")), + ProseH4: () => import("./../../../app/components/content/ProseH4.vue").then(m => pickExport(m, "default", "ProseH4", "./../../../app/components/content/ProseH4.vue")), + ProsePre: () => import("./../../../app/components/content/ProsePre.vue").then(m => pickExport(m, "default", "ProsePre", "./../../../app/components/content/ProsePre.vue")), + ProseTable: () => import("./../../../app/components/content/ProseTable.vue").then(m => pickExport(m, "default", "ProseTable", "./../../../app/components/content/ProseTable.vue")), + Steps: () => import("./../../../app/components/content/Steps.vue").then(m => pickExport(m, "default", "Steps", "./../../../app/components/content/Steps.vue")), + DuxtBreadcrumb: () => import("./../../../app/components/DuxtBreadcrumb.vue").then(m => pickExport(m, "default", "DuxtBreadcrumb", "./../../../app/components/DuxtBreadcrumb.vue")), + DuxtCodeBlock: () => import("./../../../app/components/DuxtCodeBlock.vue").then(m => pickExport(m, "default", "DuxtCodeBlock", "./../../../app/components/DuxtCodeBlock.vue")), + DuxtFooter: () => import("./../../../app/components/DuxtFooter.vue").then(m => pickExport(m, "default", "DuxtFooter", "./../../../app/components/DuxtFooter.vue")), + DuxtHeader: () => import("./../../../app/components/DuxtHeader.vue").then(m => pickExport(m, "default", "DuxtHeader", "./../../../app/components/DuxtHeader.vue")), + DuxtLocale: () => import("./../../../app/components/DuxtLocale.vue").then(m => pickExport(m, "default", "DuxtLocale", "./../../../app/components/DuxtLocale.vue")), + DuxtNavigation: () => import("./../../../app/components/DuxtNavigation.vue").then(m => pickExport(m, "default", "DuxtNavigation", "./../../../app/components/DuxtNavigation.vue")), + DuxtNavigationLink: () => import("./../../../app/components/DuxtNavigationLink.vue").then(m => pickExport(m, "default", "DuxtNavigationLink", "./../../../app/components/DuxtNavigationLink.vue")), + DuxtPageNav: () => import("./../../../app/components/DuxtPageNav.vue").then(m => pickExport(m, "default", "DuxtPageNav", "./../../../app/components/DuxtPageNav.vue")), + DuxtSearch: () => import("./../../../app/components/DuxtSearch.vue").then(m => pickExport(m, "default", "DuxtSearch", "./../../../app/components/DuxtSearch.vue")), + DuxtSections: () => import("./../../../app/components/DuxtSections.vue").then(m => pickExport(m, "default", "DuxtSections", "./../../../app/components/DuxtSections.vue")), + DuxtToc: () => import("./../../../app/components/DuxtToc.vue").then(m => pickExport(m, "default", "DuxtToc", "./../../../app/components/DuxtToc.vue")), + DuxtVersion: () => import("./../../../app/components/DuxtVersion.vue").then(m => pickExport(m, "default", "DuxtVersion", "./../../../app/components/DuxtVersion.vue")), + NuxtWelcome: () => import("./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/welcome.vue").then(m => pickExport(m, "default", "NuxtWelcome", "./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/welcome.vue")), + NuxtLayout: () => import("./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-layout").then(m => pickExport(m, "default", "NuxtLayout", "./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-layout")), + NuxtErrorBoundary: () => import("./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-error-boundary.vue").then(m => pickExport(m, "default", "NuxtErrorBoundary", "./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-error-boundary.vue")), + ClientOnly: () => import("./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/client-only").then(m => pickExport(m, "default", "ClientOnly", "./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/client-only")), + DevOnly: () => import("./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/dev-only").then(m => pickExport(m, "default", "DevOnly", "./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/dev-only")), + ServerPlaceholder: () => import("./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/server-placeholder").then(m => pickExport(m, "default", "ServerPlaceholder", "./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/server-placeholder")), + NuxtLink: () => import("./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-link").then(m => pickExport(m, "default", "NuxtLink", "./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-link")), + NuxtLoadingIndicator: () => import("./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-loading-indicator").then(m => pickExport(m, "default", "NuxtLoadingIndicator", "./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-loading-indicator")), + NuxtTime: () => import("./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-time.vue").then(m => pickExport(m, "default", "NuxtTime", "./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-time.vue")), + NuxtRouteAnnouncer: () => import("./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-route-announcer").then(m => pickExport(m, "default", "NuxtRouteAnnouncer", "./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-route-announcer")), + NuxtAnnouncer: () => import("./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-announcer").then(m => pickExport(m, "default", "NuxtAnnouncer", "./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-announcer")), + NuxtImg: () => import("./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-stubs").then(m => pickExport(m, "NuxtImg", "NuxtImg", "./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-stubs")), + NuxtPicture: () => import("./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-stubs").then(m => pickExport(m, "NuxtPicture", "NuxtPicture", "./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-stubs")), + ContentRenderer: () => import("./../../../node_modules/.pnpm/@nuxt+content@3.16.0_@oxc-project+types@0.147.0_esbuild@0.28.2_magic-string@0.30.21_mag_a1b8fcebb62d81318b5eaba6a646e180/node_modules/@nuxt/content/dist/runtime/components/ContentRenderer.vue").then(m => pickExport(m, "default", "ContentRenderer", "./../../../node_modules/.pnpm/@nuxt+content@3.16.0_@oxc-project+types@0.147.0_esbuild@0.28.2_magic-string@0.30.21_mag_a1b8fcebb62d81318b5eaba6a646e180/node_modules/@nuxt/content/dist/runtime/components/ContentRenderer.vue")), + ColorScheme: () => import("./../../../node_modules/.pnpm/@nuxtjs+color-mode@4.0.1_magic-string@0.30.21_magicast@0.5.4_oxc-parser@0.141.0_rolldow_3bc1c2a09afa5e491ed4c9ef841d05a3/node_modules/@nuxtjs/color-mode/dist/runtime/component.vue").then(m => pickExport(m, "default", "ColorScheme", "./../../../node_modules/.pnpm/@nuxtjs+color-mode@4.0.1_magic-string@0.30.21_magicast@0.5.4_oxc-parser@0.141.0_rolldow_3bc1c2a09afa5e491ed4c9ef841d05a3/node_modules/@nuxtjs/color-mode/dist/runtime/component.vue")), + Alert: () => import("./../../../app/components/ui/alert/index").then(m => pickExport(m, "Alert", "Alert", "./../../../app/components/ui/alert/index")), + AlertDescription: () => import("./../../../app/components/ui/alert/index").then(m => pickExport(m, "AlertDescription", "AlertDescription", "./../../../app/components/ui/alert/index")), + AlertTitle: () => import("./../../../app/components/ui/alert/index").then(m => pickExport(m, "AlertTitle", "AlertTitle", "./../../../app/components/ui/alert/index")), + Badge: () => import("./../../../app/components/ui/badge/index").then(m => pickExport(m, "Badge", "Badge", "./../../../app/components/ui/badge/index")), + Breadcrumb: () => import("./../../../app/components/ui/breadcrumb/index").then(m => pickExport(m, "Breadcrumb", "Breadcrumb", "./../../../app/components/ui/breadcrumb/index")), + BreadcrumbEllipsis: () => import("./../../../app/components/ui/breadcrumb/index").then(m => pickExport(m, "BreadcrumbEllipsis", "BreadcrumbEllipsis", "./../../../app/components/ui/breadcrumb/index")), + BreadcrumbItem: () => import("./../../../app/components/ui/breadcrumb/index").then(m => pickExport(m, "BreadcrumbItem", "BreadcrumbItem", "./../../../app/components/ui/breadcrumb/index")), + BreadcrumbLink: () => import("./../../../app/components/ui/breadcrumb/index").then(m => pickExport(m, "BreadcrumbLink", "BreadcrumbLink", "./../../../app/components/ui/breadcrumb/index")), + BreadcrumbList: () => import("./../../../app/components/ui/breadcrumb/index").then(m => pickExport(m, "BreadcrumbList", "BreadcrumbList", "./../../../app/components/ui/breadcrumb/index")), + BreadcrumbPage: () => import("./../../../app/components/ui/breadcrumb/index").then(m => pickExport(m, "BreadcrumbPage", "BreadcrumbPage", "./../../../app/components/ui/breadcrumb/index")), + BreadcrumbSeparator: () => import("./../../../app/components/ui/breadcrumb/index").then(m => pickExport(m, "BreadcrumbSeparator", "BreadcrumbSeparator", "./../../../app/components/ui/breadcrumb/index")), + Button: () => import("./../../../app/components/ui/button/index").then(m => pickExport(m, "Button", "Button", "./../../../app/components/ui/button/index")), + Card: () => import("./../../../app/components/ui/card/index").then(m => pickExport(m, "Card", "Card", "./../../../app/components/ui/card/index")), + CardAction: () => import("./../../../app/components/ui/card/index").then(m => pickExport(m, "CardAction", "CardAction", "./../../../app/components/ui/card/index")), + CardContent: () => import("./../../../app/components/ui/card/index").then(m => pickExport(m, "CardContent", "CardContent", "./../../../app/components/ui/card/index")), + CardDescription: () => import("./../../../app/components/ui/card/index").then(m => pickExport(m, "CardDescription", "CardDescription", "./../../../app/components/ui/card/index")), + CardFooter: () => import("./../../../app/components/ui/card/index").then(m => pickExport(m, "CardFooter", "CardFooter", "./../../../app/components/ui/card/index")), + CardHeader: () => import("./../../../app/components/ui/card/index").then(m => pickExport(m, "CardHeader", "CardHeader", "./../../../app/components/ui/card/index")), + CardTitle: () => import("./../../../app/components/ui/card/index").then(m => pickExport(m, "CardTitle", "CardTitle", "./../../../app/components/ui/card/index")), + Collapsible: () => import("./../../../app/components/ui/collapsible/index").then(m => pickExport(m, "Collapsible", "Collapsible", "./../../../app/components/ui/collapsible/index")), + CollapsibleContent: () => import("./../../../app/components/ui/collapsible/index").then(m => pickExport(m, "CollapsibleContent", "CollapsibleContent", "./../../../app/components/ui/collapsible/index")), + CollapsibleTrigger: () => import("./../../../app/components/ui/collapsible/index").then(m => pickExport(m, "CollapsibleTrigger", "CollapsibleTrigger", "./../../../app/components/ui/collapsible/index")), + Command: () => import("./../../../app/components/ui/command/index").then(m => pickExport(m, "Command", "Command", "./../../../app/components/ui/command/index")), + CommandDialog: () => import("./../../../app/components/ui/command/index").then(m => pickExport(m, "CommandDialog", "CommandDialog", "./../../../app/components/ui/command/index")), + CommandEmpty: () => import("./../../../app/components/ui/command/index").then(m => pickExport(m, "CommandEmpty", "CommandEmpty", "./../../../app/components/ui/command/index")), + CommandGroup: () => import("./../../../app/components/ui/command/index").then(m => pickExport(m, "CommandGroup", "CommandGroup", "./../../../app/components/ui/command/index")), + CommandInput: () => import("./../../../app/components/ui/command/index").then(m => pickExport(m, "CommandInput", "CommandInput", "./../../../app/components/ui/command/index")), + CommandItem: () => import("./../../../app/components/ui/command/index").then(m => pickExport(m, "CommandItem", "CommandItem", "./../../../app/components/ui/command/index")), + CommandList: () => import("./../../../app/components/ui/command/index").then(m => pickExport(m, "CommandList", "CommandList", "./../../../app/components/ui/command/index")), + CommandSeparator: () => import("./../../../app/components/ui/command/index").then(m => pickExport(m, "CommandSeparator", "CommandSeparator", "./../../../app/components/ui/command/index")), + CommandShortcut: () => import("./../../../app/components/ui/command/index").then(m => pickExport(m, "CommandShortcut", "CommandShortcut", "./../../../app/components/ui/command/index")), + Dialog: () => import("./../../../app/components/ui/dialog/index").then(m => pickExport(m, "Dialog", "Dialog", "./../../../app/components/ui/dialog/index")), + DialogClose: () => import("./../../../app/components/ui/dialog/index").then(m => pickExport(m, "DialogClose", "DialogClose", "./../../../app/components/ui/dialog/index")), + DialogContent: () => import("./../../../app/components/ui/dialog/index").then(m => pickExport(m, "DialogContent", "DialogContent", "./../../../app/components/ui/dialog/index")), + DialogDescription: () => import("./../../../app/components/ui/dialog/index").then(m => pickExport(m, "DialogDescription", "DialogDescription", "./../../../app/components/ui/dialog/index")), + DialogFooter: () => import("./../../../app/components/ui/dialog/index").then(m => pickExport(m, "DialogFooter", "DialogFooter", "./../../../app/components/ui/dialog/index")), + DialogHeader: () => import("./../../../app/components/ui/dialog/index").then(m => pickExport(m, "DialogHeader", "DialogHeader", "./../../../app/components/ui/dialog/index")), + DialogOverlay: () => import("./../../../app/components/ui/dialog/index").then(m => pickExport(m, "DialogOverlay", "DialogOverlay", "./../../../app/components/ui/dialog/index")), + DialogScrollContent: () => import("./../../../app/components/ui/dialog/index").then(m => pickExport(m, "DialogScrollContent", "DialogScrollContent", "./../../../app/components/ui/dialog/index")), + DialogTitle: () => import("./../../../app/components/ui/dialog/index").then(m => pickExport(m, "DialogTitle", "DialogTitle", "./../../../app/components/ui/dialog/index")), + DialogTrigger: () => import("./../../../app/components/ui/dialog/index").then(m => pickExport(m, "DialogTrigger", "DialogTrigger", "./../../../app/components/ui/dialog/index")), + DropdownMenu: () => import("./../../../app/components/ui/dropdown-menu/index").then(m => pickExport(m, "DropdownMenu", "DropdownMenu", "./../../../app/components/ui/dropdown-menu/index")), + DropdownMenuCheckboxItem: () => import("./../../../app/components/ui/dropdown-menu/index").then(m => pickExport(m, "DropdownMenuCheckboxItem", "DropdownMenuCheckboxItem", "./../../../app/components/ui/dropdown-menu/index")), + DropdownMenuContent: () => import("./../../../app/components/ui/dropdown-menu/index").then(m => pickExport(m, "DropdownMenuContent", "DropdownMenuContent", "./../../../app/components/ui/dropdown-menu/index")), + DropdownMenuGroup: () => import("./../../../app/components/ui/dropdown-menu/index").then(m => pickExport(m, "DropdownMenuGroup", "DropdownMenuGroup", "./../../../app/components/ui/dropdown-menu/index")), + DropdownMenuItem: () => import("./../../../app/components/ui/dropdown-menu/index").then(m => pickExport(m, "DropdownMenuItem", "DropdownMenuItem", "./../../../app/components/ui/dropdown-menu/index")), + DropdownMenuLabel: () => import("./../../../app/components/ui/dropdown-menu/index").then(m => pickExport(m, "DropdownMenuLabel", "DropdownMenuLabel", "./../../../app/components/ui/dropdown-menu/index")), + DropdownMenuRadioGroup: () => import("./../../../app/components/ui/dropdown-menu/index").then(m => pickExport(m, "DropdownMenuRadioGroup", "DropdownMenuRadioGroup", "./../../../app/components/ui/dropdown-menu/index")), + DropdownMenuRadioItem: () => import("./../../../app/components/ui/dropdown-menu/index").then(m => pickExport(m, "DropdownMenuRadioItem", "DropdownMenuRadioItem", "./../../../app/components/ui/dropdown-menu/index")), + DropdownMenuSeparator: () => import("./../../../app/components/ui/dropdown-menu/index").then(m => pickExport(m, "DropdownMenuSeparator", "DropdownMenuSeparator", "./../../../app/components/ui/dropdown-menu/index")), + DropdownMenuShortcut: () => import("./../../../app/components/ui/dropdown-menu/index").then(m => pickExport(m, "DropdownMenuShortcut", "DropdownMenuShortcut", "./../../../app/components/ui/dropdown-menu/index")), + DropdownMenuSub: () => import("./../../../app/components/ui/dropdown-menu/index").then(m => pickExport(m, "DropdownMenuSub", "DropdownMenuSub", "./../../../app/components/ui/dropdown-menu/index")), + DropdownMenuSubContent: () => import("./../../../app/components/ui/dropdown-menu/index").then(m => pickExport(m, "DropdownMenuSubContent", "DropdownMenuSubContent", "./../../../app/components/ui/dropdown-menu/index")), + DropdownMenuSubTrigger: () => import("./../../../app/components/ui/dropdown-menu/index").then(m => pickExport(m, "DropdownMenuSubTrigger", "DropdownMenuSubTrigger", "./../../../app/components/ui/dropdown-menu/index")), + DropdownMenuTrigger: () => import("./../../../app/components/ui/dropdown-menu/index").then(m => pickExport(m, "DropdownMenuTrigger", "DropdownMenuTrigger", "./../../../app/components/ui/dropdown-menu/index")), + DropdownMenuPortal: () => import("./../../../app/components/ui/dropdown-menu/index").then(m => pickExport(m, "DropdownMenuPortal", "DropdownMenuPortal", "./../../../app/components/ui/dropdown-menu/index")), + Input: () => import("./../../../app/components/ui/input/index").then(m => pickExport(m, "Input", "Input", "./../../../app/components/ui/input/index")), + NavigationMenu: () => import("./../../../app/components/ui/navigation-menu/index").then(m => pickExport(m, "NavigationMenu", "NavigationMenu", "./../../../app/components/ui/navigation-menu/index")), + NavigationMenuContent: () => import("./../../../app/components/ui/navigation-menu/index").then(m => pickExport(m, "NavigationMenuContent", "NavigationMenuContent", "./../../../app/components/ui/navigation-menu/index")), + NavigationMenuIndicator: () => import("./../../../app/components/ui/navigation-menu/index").then(m => pickExport(m, "NavigationMenuIndicator", "NavigationMenuIndicator", "./../../../app/components/ui/navigation-menu/index")), + NavigationMenuItem: () => import("./../../../app/components/ui/navigation-menu/index").then(m => pickExport(m, "NavigationMenuItem", "NavigationMenuItem", "./../../../app/components/ui/navigation-menu/index")), + NavigationMenuLink: () => import("./../../../app/components/ui/navigation-menu/index").then(m => pickExport(m, "NavigationMenuLink", "NavigationMenuLink", "./../../../app/components/ui/navigation-menu/index")), + NavigationMenuList: () => import("./../../../app/components/ui/navigation-menu/index").then(m => pickExport(m, "NavigationMenuList", "NavigationMenuList", "./../../../app/components/ui/navigation-menu/index")), + NavigationMenuTrigger: () => import("./../../../app/components/ui/navigation-menu/index").then(m => pickExport(m, "NavigationMenuTrigger", "NavigationMenuTrigger", "./../../../app/components/ui/navigation-menu/index")), + NavigationMenuViewport: () => import("./../../../app/components/ui/navigation-menu/index").then(m => pickExport(m, "NavigationMenuViewport", "NavigationMenuViewport", "./../../../app/components/ui/navigation-menu/index")), + ScrollArea: () => import("./../../../app/components/ui/scroll-area/index").then(m => pickExport(m, "ScrollArea", "ScrollArea", "./../../../app/components/ui/scroll-area/index")), + ScrollBar: () => import("./../../../app/components/ui/scroll-area/index").then(m => pickExport(m, "ScrollBar", "ScrollBar", "./../../../app/components/ui/scroll-area/index")), + Separator: () => import("./../../../app/components/ui/separator/index").then(m => pickExport(m, "Separator", "Separator", "./../../../app/components/ui/separator/index")), + Sheet: () => import("./../../../app/components/ui/sheet/index").then(m => pickExport(m, "Sheet", "Sheet", "./../../../app/components/ui/sheet/index")), + SheetClose: () => import("./../../../app/components/ui/sheet/index").then(m => pickExport(m, "SheetClose", "SheetClose", "./../../../app/components/ui/sheet/index")), + SheetContent: () => import("./../../../app/components/ui/sheet/index").then(m => pickExport(m, "SheetContent", "SheetContent", "./../../../app/components/ui/sheet/index")), + SheetDescription: () => import("./../../../app/components/ui/sheet/index").then(m => pickExport(m, "SheetDescription", "SheetDescription", "./../../../app/components/ui/sheet/index")), + SheetFooter: () => import("./../../../app/components/ui/sheet/index").then(m => pickExport(m, "SheetFooter", "SheetFooter", "./../../../app/components/ui/sheet/index")), + SheetHeader: () => import("./../../../app/components/ui/sheet/index").then(m => pickExport(m, "SheetHeader", "SheetHeader", "./../../../app/components/ui/sheet/index")), + SheetTitle: () => import("./../../../app/components/ui/sheet/index").then(m => pickExport(m, "SheetTitle", "SheetTitle", "./../../../app/components/ui/sheet/index")), + SheetTrigger: () => import("./../../../app/components/ui/sheet/index").then(m => pickExport(m, "SheetTrigger", "SheetTrigger", "./../../../app/components/ui/sheet/index")), + Sidebar: () => import("./../../../app/components/ui/sidebar/index").then(m => pickExport(m, "Sidebar", "Sidebar", "./../../../app/components/ui/sidebar/index")), + SidebarContent: () => import("./../../../app/components/ui/sidebar/index").then(m => pickExport(m, "SidebarContent", "SidebarContent", "./../../../app/components/ui/sidebar/index")), + SidebarFooter: () => import("./../../../app/components/ui/sidebar/index").then(m => pickExport(m, "SidebarFooter", "SidebarFooter", "./../../../app/components/ui/sidebar/index")), + SidebarGroup: () => import("./../../../app/components/ui/sidebar/index").then(m => pickExport(m, "SidebarGroup", "SidebarGroup", "./../../../app/components/ui/sidebar/index")), + SidebarGroupAction: () => import("./../../../app/components/ui/sidebar/index").then(m => pickExport(m, "SidebarGroupAction", "SidebarGroupAction", "./../../../app/components/ui/sidebar/index")), + SidebarGroupContent: () => import("./../../../app/components/ui/sidebar/index").then(m => pickExport(m, "SidebarGroupContent", "SidebarGroupContent", "./../../../app/components/ui/sidebar/index")), + SidebarGroupLabel: () => import("./../../../app/components/ui/sidebar/index").then(m => pickExport(m, "SidebarGroupLabel", "SidebarGroupLabel", "./../../../app/components/ui/sidebar/index")), + SidebarHeader: () => import("./../../../app/components/ui/sidebar/index").then(m => pickExport(m, "SidebarHeader", "SidebarHeader", "./../../../app/components/ui/sidebar/index")), + SidebarInput: () => import("./../../../app/components/ui/sidebar/index").then(m => pickExport(m, "SidebarInput", "SidebarInput", "./../../../app/components/ui/sidebar/index")), + SidebarInset: () => import("./../../../app/components/ui/sidebar/index").then(m => pickExport(m, "SidebarInset", "SidebarInset", "./../../../app/components/ui/sidebar/index")), + SidebarMenu: () => import("./../../../app/components/ui/sidebar/index").then(m => pickExport(m, "SidebarMenu", "SidebarMenu", "./../../../app/components/ui/sidebar/index")), + SidebarMenuAction: () => import("./../../../app/components/ui/sidebar/index").then(m => pickExport(m, "SidebarMenuAction", "SidebarMenuAction", "./../../../app/components/ui/sidebar/index")), + SidebarMenuBadge: () => import("./../../../app/components/ui/sidebar/index").then(m => pickExport(m, "SidebarMenuBadge", "SidebarMenuBadge", "./../../../app/components/ui/sidebar/index")), + SidebarMenuButton: () => import("./../../../app/components/ui/sidebar/index").then(m => pickExport(m, "SidebarMenuButton", "SidebarMenuButton", "./../../../app/components/ui/sidebar/index")), + SidebarMenuItem: () => import("./../../../app/components/ui/sidebar/index").then(m => pickExport(m, "SidebarMenuItem", "SidebarMenuItem", "./../../../app/components/ui/sidebar/index")), + SidebarMenuSkeleton: () => import("./../../../app/components/ui/sidebar/index").then(m => pickExport(m, "SidebarMenuSkeleton", "SidebarMenuSkeleton", "./../../../app/components/ui/sidebar/index")), + SidebarMenuSub: () => import("./../../../app/components/ui/sidebar/index").then(m => pickExport(m, "SidebarMenuSub", "SidebarMenuSub", "./../../../app/components/ui/sidebar/index")), + SidebarMenuSubButton: () => import("./../../../app/components/ui/sidebar/index").then(m => pickExport(m, "SidebarMenuSubButton", "SidebarMenuSubButton", "./../../../app/components/ui/sidebar/index")), + SidebarMenuSubItem: () => import("./../../../app/components/ui/sidebar/index").then(m => pickExport(m, "SidebarMenuSubItem", "SidebarMenuSubItem", "./../../../app/components/ui/sidebar/index")), + SidebarProvider: () => import("./../../../app/components/ui/sidebar/index").then(m => pickExport(m, "SidebarProvider", "SidebarProvider", "./../../../app/components/ui/sidebar/index")), + SidebarRail: () => import("./../../../app/components/ui/sidebar/index").then(m => pickExport(m, "SidebarRail", "SidebarRail", "./../../../app/components/ui/sidebar/index")), + SidebarSeparator: () => import("./../../../app/components/ui/sidebar/index").then(m => pickExport(m, "SidebarSeparator", "SidebarSeparator", "./../../../app/components/ui/sidebar/index")), + SidebarTrigger: () => import("./../../../app/components/ui/sidebar/index").then(m => pickExport(m, "SidebarTrigger", "SidebarTrigger", "./../../../app/components/ui/sidebar/index")), + Skeleton: () => import("./../../../app/components/ui/skeleton/index").then(m => pickExport(m, "Skeleton", "Skeleton", "./../../../app/components/ui/skeleton/index")), + Toaster: () => import("./../../../app/components/ui/sonner/index").then(m => pickExport(m, "Toaster", "Toaster", "./../../../app/components/ui/sonner/index")), + Tabs: () => import("./../../../app/components/ui/tabs/index").then(m => pickExport(m, "Tabs", "Tabs", "./../../../app/components/ui/tabs/index")), + TabsContent: () => import("./../../../app/components/ui/tabs/index").then(m => pickExport(m, "TabsContent", "TabsContent", "./../../../app/components/ui/tabs/index")), + TabsList: () => import("./../../../app/components/ui/tabs/index").then(m => pickExport(m, "TabsList", "TabsList", "./../../../app/components/ui/tabs/index")), + TabsTrigger: () => import("./../../../app/components/ui/tabs/index").then(m => pickExport(m, "TabsTrigger", "TabsTrigger", "./../../../app/components/ui/tabs/index")), + Tooltip: () => import("./../../../app/components/ui/tooltip/index").then(m => pickExport(m, "Tooltip", "Tooltip", "./../../../app/components/ui/tooltip/index")), + TooltipContent: () => import("./../../../app/components/ui/tooltip/index").then(m => pickExport(m, "TooltipContent", "TooltipContent", "./../../../app/components/ui/tooltip/index")), + TooltipProvider: () => import("./../../../app/components/ui/tooltip/index").then(m => pickExport(m, "TooltipProvider", "TooltipProvider", "./../../../app/components/ui/tooltip/index")), + TooltipTrigger: () => import("./../../../app/components/ui/tooltip/index").then(m => pickExport(m, "TooltipTrigger", "TooltipTrigger", "./../../../app/components/ui/tooltip/index")), + InstallButton: () => import("./../../../node_modules/.pnpm/@nuxtjs+mcp-toolkit@0.19.0_@vue+compiler-sfc@3.5.42_h3@1.15.11_magic-string@0.30.21_mag_467f1d813e724e89e024de7c60e319b0/node_modules/@nuxtjs/mcp-toolkit/dist/runtime/components/InstallButton.vue").then(m => pickExport(m, "default", "InstallButton", "./../../../node_modules/.pnpm/@nuxtjs+mcp-toolkit@0.19.0_@vue+compiler-sfc@3.5.42_h3@1.15.11_magic-string@0.30.21_mag_467f1d813e724e89e024de7c60e319b0/node_modules/@nuxtjs/mcp-toolkit/dist/runtime/components/InstallButton.vue")), + NuxtLinkLocale: () => import("./../../../node_modules/.pnpm/@nuxtjs+i18n@10.6.0_@vue+compiler-dom@3.5.42_db0@0.3.4_esbuild@0.28.2_eslint@10.9.1_jit_882b05db15702ae219b02326b98e2631/node_modules/@nuxtjs/i18n/dist/runtime/components/NuxtLinkLocale").then(m => pickExport(m, "default", "NuxtLinkLocale", "./../../../node_modules/.pnpm/@nuxtjs+i18n@10.6.0_@vue+compiler-dom@3.5.42_db0@0.3.4_esbuild@0.28.2_eslint@10.9.1_jit_882b05db15702ae219b02326b98e2631/node_modules/@nuxtjs/i18n/dist/runtime/components/NuxtLinkLocale")), + SwitchLocalePathLink: () => import("./../../../node_modules/.pnpm/@nuxtjs+i18n@10.6.0_@vue+compiler-dom@3.5.42_db0@0.3.4_esbuild@0.28.2_eslint@10.9.1_jit_882b05db15702ae219b02326b98e2631/node_modules/@nuxtjs/i18n/dist/runtime/components/SwitchLocalePathLink").then(m => pickExport(m, "default", "SwitchLocalePathLink", "./../../../node_modules/.pnpm/@nuxtjs+i18n@10.6.0_@vue+compiler-dom@3.5.42_db0@0.3.4_esbuild@0.28.2_eslint@10.9.1_jit_882b05db15702ae219b02326b98e2631/node_modules/@nuxtjs/i18n/dist/runtime/components/SwitchLocalePathLink")), + NuxtPage: () => import("./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/pages/runtime/page").then(m => pickExport(m, "default", "NuxtPage", "./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/pages/runtime/page")), + NoScript: () => import("./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/head/runtime/components").then(m => pickExport(m, "NoScript", "NoScript", "./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/head/runtime/components")), + Link: () => import("./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/head/runtime/components").then(m => pickExport(m, "Link", "Link", "./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/head/runtime/components")), + Base: () => import("./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/head/runtime/components").then(m => pickExport(m, "Base", "Base", "./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/head/runtime/components")), + Title: () => import("./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/head/runtime/components").then(m => pickExport(m, "Title", "Title", "./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/head/runtime/components")), + Meta: () => import("./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/head/runtime/components").then(m => pickExport(m, "Meta", "Meta", "./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/head/runtime/components")), + Style: () => import("./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/head/runtime/components").then(m => pickExport(m, "Style", "Style", "./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/head/runtime/components")), + Head: () => import("./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/head/runtime/components").then(m => pickExport(m, "Head", "Head", "./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/head/runtime/components")), + Html: () => import("./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/head/runtime/components").then(m => pickExport(m, "Html", "Html", "./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/head/runtime/components")), + Body: () => import("./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/head/runtime/components").then(m => pickExport(m, "Body", "Body", "./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/head/runtime/components")), + MDC: () => import("./../../../node_modules/.pnpm/@nuxtjs+mdc@0.23.1_magic-string@0.30.21_magicast@0.5.4_oxc-parser@0.141.0_rolldown@1.2._82edceced79f34753b5a516fdfd94d58/node_modules/@nuxtjs/mdc/dist/runtime/components/MDC.vue").then(m => pickExport(m, "default", "MDC", "./../../../node_modules/.pnpm/@nuxtjs+mdc@0.23.1_magic-string@0.30.21_magicast@0.5.4_oxc-parser@0.141.0_rolldown@1.2._82edceced79f34753b5a516fdfd94d58/node_modules/@nuxtjs/mdc/dist/runtime/components/MDC.vue")), + MDCCached: () => import("./../../../node_modules/.pnpm/@nuxtjs+mdc@0.23.1_magic-string@0.30.21_magicast@0.5.4_oxc-parser@0.141.0_rolldown@1.2._82edceced79f34753b5a516fdfd94d58/node_modules/@nuxtjs/mdc/dist/runtime/components/MDCCached.vue").then(m => pickExport(m, "default", "MDCCached", "./../../../node_modules/.pnpm/@nuxtjs+mdc@0.23.1_magic-string@0.30.21_magicast@0.5.4_oxc-parser@0.141.0_rolldown@1.2._82edceced79f34753b5a516fdfd94d58/node_modules/@nuxtjs/mdc/dist/runtime/components/MDCCached.vue")), + MDCRenderer: () => import("./../../../node_modules/.pnpm/@nuxtjs+mdc@0.23.1_magic-string@0.30.21_magicast@0.5.4_oxc-parser@0.141.0_rolldown@1.2._82edceced79f34753b5a516fdfd94d58/node_modules/@nuxtjs/mdc/dist/runtime/components/MDCRenderer.vue").then(m => pickExport(m, "default", "MDCRenderer", "./../../../node_modules/.pnpm/@nuxtjs+mdc@0.23.1_magic-string@0.30.21_magicast@0.5.4_oxc-parser@0.141.0_rolldown@1.2._82edceced79f34753b5a516fdfd94d58/node_modules/@nuxtjs/mdc/dist/runtime/components/MDCRenderer.vue")), + MDCSlot: () => import("./../../../node_modules/.pnpm/@nuxtjs+mdc@0.23.1_magic-string@0.30.21_magicast@0.5.4_oxc-parser@0.141.0_rolldown@1.2._82edceced79f34753b5a516fdfd94d58/node_modules/@nuxtjs/mdc/dist/runtime/components/MDCSlot.vue").then(m => pickExport(m, "default", "MDCSlot", "./../../../node_modules/.pnpm/@nuxtjs+mdc@0.23.1_magic-string@0.30.21_magicast@0.5.4_oxc-parser@0.141.0_rolldown@1.2._82edceced79f34753b5a516fdfd94d58/node_modules/@nuxtjs/mdc/dist/runtime/components/MDCSlot.vue")), + NuxtIsland: () => import("./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-island").then(m => pickExport(m, "default", "NuxtIsland", "./../../../node_modules/.pnpm/nuxt@4.5.2_@babel+plugin-syntax-jsx@7.29.7_@babel+core@7.29.7_supports-color@10.2.2___@_6a8ec549e9d470ce05bfc037ea662c04/node_modules/nuxt/dist/app/components/nuxt-island")), +} +export const globalComponents: string[] = ["ProseA","ProseBlockquote","ProseCode","ProseEm","ProseH1","ProseH5","ProseH6","ProseHr","ProseImg","ProseLi","ProseOl","ProseP","ProseScript","ProseStrong","ProseTbody","ProseTd","ProseTh","ProseThead","ProseTr","ProseUl","Icon"] +export const localComponents: string[] = ["Callout","FileTree","PackageManagers","PageCards","ProseH2","ProseH3","ProseH4","ProsePre","ProseTable","Steps","DuxtBreadcrumb","DuxtCodeBlock","DuxtFooter","DuxtHeader","DuxtLocale","DuxtNavigation","DuxtNavigationLink","DuxtPageNav","DuxtSearch","DuxtSections","DuxtToc","DuxtVersion","NuxtWelcome","NuxtLayout","NuxtErrorBoundary","ClientOnly","DevOnly","ServerPlaceholder","NuxtLink","NuxtLoadingIndicator","NuxtTime","NuxtRouteAnnouncer","NuxtAnnouncer","NuxtImg","NuxtPicture","ContentRenderer","ColorScheme","Alert","AlertDescription","AlertTitle","Badge","Breadcrumb","BreadcrumbEllipsis","BreadcrumbItem","BreadcrumbLink","BreadcrumbList","BreadcrumbPage","BreadcrumbSeparator","Button","Card","CardAction","CardContent","CardDescription","CardFooter","CardHeader","CardTitle","Collapsible","CollapsibleContent","CollapsibleTrigger","Command","CommandDialog","CommandEmpty","CommandGroup","CommandInput","CommandItem","CommandList","CommandSeparator","CommandShortcut","Dialog","DialogClose","DialogContent","DialogDescription","DialogFooter","DialogHeader","DialogOverlay","DialogScrollContent","DialogTitle","DialogTrigger","DropdownMenu","DropdownMenuCheckboxItem","DropdownMenuContent","DropdownMenuGroup","DropdownMenuItem","DropdownMenuLabel","DropdownMenuRadioGroup","DropdownMenuRadioItem","DropdownMenuSeparator","DropdownMenuShortcut","DropdownMenuSub","DropdownMenuSubContent","DropdownMenuSubTrigger","DropdownMenuTrigger","DropdownMenuPortal","Input","NavigationMenu","NavigationMenuContent","NavigationMenuIndicator","NavigationMenuItem","NavigationMenuLink","NavigationMenuList","NavigationMenuTrigger","NavigationMenuViewport","ScrollArea","ScrollBar","Separator","Sheet","SheetClose","SheetContent","SheetDescription","SheetFooter","SheetHeader","SheetTitle","SheetTrigger","Sidebar","SidebarContent","SidebarFooter","SidebarGroup","SidebarGroupAction","SidebarGroupContent","SidebarGroupLabel","SidebarHeader","SidebarInput","SidebarInset","SidebarMenu","SidebarMenuAction","SidebarMenuBadge","SidebarMenuButton","SidebarMenuItem","SidebarMenuSkeleton","SidebarMenuSub","SidebarMenuSubButton","SidebarMenuSubItem","SidebarProvider","SidebarRail","SidebarSeparator","SidebarTrigger","Skeleton","Toaster","Tabs","TabsContent","TabsList","TabsTrigger","Tooltip","TooltipContent","TooltipProvider","TooltipTrigger","InstallButton","NuxtLinkLocale","SwitchLocalePathLink","NuxtPage","NoScript","Link","Base","Title","Meta","Style","Head","Html","Body","MDC","MDCCached","MDCRenderer","MDCSlot","NuxtIsland"] \ No newline at end of file diff --git a/www/.nuxt/content/database.compressed.mjs b/www/.nuxt/content/database.compressed.mjs new file mode 100644 index 00000000..aa7aee2d --- /dev/null +++ b/www/.nuxt/content/database.compressed.mjs @@ -0,0 +1,3 @@ +export const docs_duxt = "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" +export const docs_workflows = "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" +export const docs_workflows_v0_7_0 = "H4sIAAAAAAAAA+1963LbuLbmq+B4n6qcvUtSO/fE2efUOI6TuJPYbttJOt1OuSASkmBTBEOAltV9umoeYp5wnmRmXQCCEmXL187s6T/dsUSRILCwsC7f+tavKxt7m+sHm+Jg/eX7TbH1WmzvHIjNn7f2D/bFUWJyp3J3pPOBEf+hU3Gw+fOB2N3b+rC+90W82/zSEYcrpZLp9HBFvNzZeb+5vg0fWVdWiatK9UmVVpv8cEV8Wt/beLu+B9+etn14dDSSdnR0dLhCD/m4vfXTx82/vxDdrgi3W+msbG3vb+4diK3tg52Z8X1af/9xc1/8x71kpJITW42PUpPYo4kpTwaZmdij09Wjp0er9zpiIDOrOuLerns+GA1/PjKuHOevf/qy+3b/TfVt8yzNvjz9Nll/ubPjjjc2y61dN7zXEfdOH/Ye91a73eH04P2Xn1Y/fKq+HR99MOvbT+2X7vDUPblvH2bvxtsfH0yeyt8OzrbTdfjZ281HP2e7++WTvd/e/fgyd1s/7Z591NnJxl7+cP/+9PGjd7vV5t6b58nZl3v0vmPl5Epn5dXezm69LrNr0vpyc9O1zOq23mnhcjvtMtVcu75BAYCr4c9U2aTUhZtbY3XmVD6/9DqJPxHbH9+/h48zOTWVa/kCpid6XC5P9VDy01gIw7WFdKPm06wyXsZebb5e//j+QNz7/Y97JLZqfINS2T6vQUxbv/4hfPDD6WrvaW/1h/u9YaVTZX+43xvrYSmd6spuqQrTdaYru9ZV/d44BUH7QF8LKeBr4YyQAr6G734/XHHTQh2urB2ujHWux7I8OVzpHK6cyqyCj3/99XBldP9wpfP74YpO+br2xx2u/NE5XFn0tMOVr51fD1cKuBVct5MrvKIjTK6Efz0hnZDC6bHqiYOREgOdKWFHpc5PLN3LlXo4VKWQeSqkOFyBmyYmVf6+lVV2DR52uNLBi9xICdr6+E8cFfyndFYkI5kPlcjlWAmd4/cW/l1Wufjf//N/iclIJyOh6ZeFLJ1wI+lEv1TyxAprxsqNdD4UeiC0g+syNXBiYEqRSafKHr/06EFjAq1ThaXZ2qd/4lUmo3f49XAl0+Gf1pUmH/q321NFJhOF44HtJSbajXiGe/TW4p1SBV7AU9URqcqUU0KdqnJKA67yVJUts3ds+n72hDpLVOFo/mSW9cQ6/l+V4tj0xVhOhcmzqUhkWU5bbgWT6tehfZkWfwtvtfhbq5JSuXN+niuVnvO1HpxzbwfSO5wuviIxeVKVpcoTvgilbP66QpVjbUGt8VBQouavK6vcdkFJ4TXaitw4IbPMTBQKb6nwAX2VmXyIm8Avfo9uVpSKxCvJpLXbOO1roCfzYSWHqjuV40zYkT7R9N+uG6mxsmKo3ajqdzM9HDn/R+r3P41w7XDlb6JH30UqqCjN2IBm7RZlbzrOOiIx4wJk7PAwh3VfE7v+ErG7d3iYm3zt8DAXoqjsiP4lRL+UeTJSdk38mqrTjrBODtXXw8OchBAvjx7kf9Z6f/gCd7440WUyeqVOo+HOv8DR7Bv8j3/akfwv8Tdxutq731s9PMxxFvwc4kzAPOKndNCsHa7gX9ZNM8V//hEvLhwTepibUn2QRXyBLWQerRitls4VPRL/sXZ/4ZX2x2f9Y9Iel16bw5WvX5cdwYPFI3iuXv5CI/CbfNGVn9yzl3Tlmjjvul9+yTfoupmFvcyIHy4e8fGjhDUu7bQlxnvJhz9aZrpoA9zOAB4vN4B63y27br8ut3CpOl3ujp0lJQH1wXK3/HrJuXqyzFyBGrqdpXq6pKxEW/l2BvJsWZn5rvb582VH7Y2Mmxv1dU6X855Q6/TmGfT1K01Lv0RzAUyE99q6VsOFdwtYbqcqFxM0HXJzwbWkDYQ609bZNSHB5HaqhBUHQ1H6C9Dw1VbIvlU5/UvkpmsKsrK1EydKFWQpgzUqdKpypxOZgWWNpiea3d4mXmji7rIhvv92nW5dVGSEcnwAbgdugNQZDDAx47HKnTd+wWlwcgjjm4zQmRhVY5kLiEbYF/7G4WswvnrilSpUnsq+caKU2ip6i341LqwYlGZMZtjFI5eW358M1NpKR4O0I/pT3Eh+rNswK4vt2zWh85EqtaPL2dpzsp+pMAA3UjKt/yqjL0jGZKaHOe0iNXAkYi/RL/960WX7OAyUQbyU3PmWR6WL7jHzXkffKlWpLgkU7IvFRvbRQFrXHZhyIsu0i7+74AelypS0qlvg/y64uKj6mbaj7tDwz0r+wddLvdDLz/tH6xsbm/v7Rwc77za367m6yuz4QeXF+Eqj2d79EA1jTm8coPM7ljqHbdM3qQY5lyeoI1jkLhTxD+aUnU9cxG5RGqcSVONllSnvneRqQj43yrv1As8OZIoOpPfBpW1ZoX+Sp9k9Nv0u3OK/xA/inyCA9Sd+ea0J2uVbpUuV8pODs5+qJJOl8t6+hQiNzofgz+KY0Wc3pHRMllI0YCK1s+jJy3A/6cREZ5nIcd/KstSnqo4x7O7xF32VGPCvxqocKtitvHOjtdhTMg3a4d49ixOCUyVM5YQZ1KpDO6uyQR3JIA8cxxhdihp3aipxXFknJrAqPXEwMTTqRLpkJApligx/tUYDqloDDktvw7CCdLemoAxMVfJlYEfxaeSnODEFSB/dAN3cUqkF/vGesiZjqdO5UxBeAnkjCazd5voJ8/fY2j7YfLO3frC1s330cm99e+Mt/y7TTpUyExN/hJwzF4kmX3lkKts2DRDHgnUsVCnsSJapKLIKjkkUBPiqw4OUYiTztDsptXMqF7JKtasnw+R4Qnw9fycewM51GCI741VGqcOAUBQhwCHumzFtBitkqURfjXSeilLCuQY/zkWqBwNVqtzVAk1xPjxx+bSEUI/m0zExZUk7vyc2cIPMT/vG+/WPrzZ749SvEmwyTetutTPlFHcYPkxJW8HmzcC86auBKZUwhUJlxdsL5IPDirxd7ciUTqBc1iHEodQ5jXG9KLrOnKhcQLwXbBTaoSOZ0mvKXOTFmG4JE2fY1ChK5c8Tb3XANFtnCitYT5N1NP/S7AcdrgSDBVfHqjE8upQQyYRgzgS2tjCTHGOFFgSAjq6LdPAriub5vQQhUlAhsN4dDB45DpzGNhEqiNpCg69Rh5DqNCgIOA1gM3fqwCeu+1ie8Kor6yC4OyxVUbBq+9oW4sQN3eUApO1OTOlG3YE+0/mwOxnpTHWnpurKUnVhQ5C9cYBKwP9G4G8E/Ubgb1DBgfzSb5rx5PWmvKJMGbAM41Co6GcmORFDMM7AIhQyn07kFGLN+GxYVOsjwaikcDtakRiLxmIO+0WPFcptbvAHJEpK0oRJAV7KWnN4c2u4n8jcCzGvuze0IahaH5gQL8DAd96i/ITMJnJqxUjCc4sqy/AQBGGCrQMP0GFDSwd7CCLb6gxse15RjHc7r35tm7uAQbs4XAdGBESVT796FVjxjpO5zKYW5n+iE5olg4F+W2WuJ16Vpjhvy4Rpu9WQ5gXBSHi7r3xBlh3xjC64kKfhe44X3n7sa6lQ4W3Gvs6J/N1J7Ask4XYiVUuHFWtJ/dcMLy4/xcvGF5cOWH5thGIWqvQTXdBxWZTGgqWew2GMucLIAaKMozNVghYEptA+yPIkBUuAfzOQOqODxAn0QCBHi17I3ShIsJZsl3QR6b2uuHfvH/+AhPK98Dckqn/4xz/wk+9X+9XCGb/VnevB+qYwecsJaDzlN6QNrzaM5krPbITDFYpjqbMkq9I272s+QvqPf/CGwOiaFBsmVT+9D1YaWCLtjpxEj8MnVL3ABUPVJpIMkXHvAgPsjWQTWp0VAD45VeSnsk2GBhGAITiJf7giPrPrRgACMHiksJV2ii3Vsc4rB7YzxCtbYk6nqtQDrdLIc9Q5TECOXrx2aKeVKjFlynYhGE2AiMBx5ilELBzZqRDZzBBhJQpprUrZ5s2FPdFFoVKy4HFhgu1bknXrRF/elSapU7n+9deukK2Np45j6Yc53sdFlhkGWdfCg/hTPVijb3rhLqZyReVsD6ZK/Nt/inv3XFkp1myXG1miu7lJ1fzAaB27s2/NY/zVf97BN/g6N1b4tMcC8J8wQlslibL2SoOcGUtjsHAv8Hz9AAVK2Jr4999/XzRtKIJ//PH/iNa/vSzeklZvkMc/1/L9s3Jh7Xv3GhawGhdu+l7naheQUCOTpao8XFmDLQyjuh2z1t2aXb1UKjqojptdwUhV3kL6GvTZzY53eT1+K0nwP2sLtR4y18iX3+wOur+63PzNnEK3s5vuL3UmXHo7LemjXu7dlvVTl9c9lw0u3F/yCLutnXyulXOpF/nuj8HzbLBLvemSASGy6m5pky0dCyJr8mbne0nLNGTAIeL/rTKuBk1EPiE/Cu77b1sfdnf2Dta3D8g7OzzM18VQukXp6qY/yW6XT0ojhteyb9YD3xEzLDK4Z3BLK522A0ioydnkNcOA/Rtymkxbn4ABDzkx+UCXY3DoTM5h9sL43NlYnvjUGfmx8JAqUx2KKA1LpXLMBmBKOzPmhJIjKl2U08GRQXqO1mGj/vNrnU1u+pFo6ecOEnJdJ+1Jl6+Pcs5zPwjXdTXWXdDFOi+g6AOuT7WF1FPKR1YnKmHAIfbN2eHKHyHzFfKCWEvgh3OVSgLO9wiVzWbpbv0lzh0dIwckYqG0Q4BTSAP7JKS0i1BTd/MWm5hoJJxJjW4I2AztN4sHSb1YGhglZFEoWcKOmczjtO7gpWb3rk/rFQbzspSqi5AyY4Bj4IKdC3xpYF7+K1pqiv94nA3sYZm4SmbZ1GupO5yCdRwAZCA9zjxl5cKhNHr/mVocFlkNCUqaD5qzKrvL5VvPpwyfYHH0AIegblGjgjKWY4ix5R6KENWyIQKJXgxD+/irU62gfAM3HTwhhlpIAWv0pysQn407XAma0ADOaFoncYPqpNVakKzGCYDjp54AOLsgFpsDtgcywXcqkC3vOhP6P1wRiQHNyLmaGjsUXtmnb5SQg4FKHGkm7cLpyDEtesDIjTNAjfQoUgrPFj1E9XYEfgef8Jf0+e/dLsVTUzWQVebW/vZk/enDp69ehM9leeI//KP9/mBstd0fPp+//4MHz548XJ+5/7PHm8+eL7o/GGdt94fPW+7/6MHzB5sz99+8v/lo89mC+4NR13Z/+Hz+/qsPH7x+8mDm/s83N16+fr3g/pD5brs/fN5y/9XHGxuPZ+7/9PnLZ/7+Pb5U8I3AehS/JyYz5Zo4leV/zNzy7y8g0D4sTZWnrRd0+8O/vxiY3HVRmNqvqb/naycKYu7nXEwX/P2FU2eum4LjgaCR9l/MXPT3F/yu/x+8IqzwxS8qy5Nz3lKWJ+e/Ilyw3PuFK5d7Obi8/c3+JV8M1e7hijPJ4cra76HePGQYlEQ3vACnd+0Bpvfrf2dQPwxHzVwR7syF8Fz8et/X6F4d07bo1pfFuf3R7oMtun3kl/3x9Q+oYL/nq4Y5eZmYYopnfX3acRkxGJ8ew52o3AE0lnCFYL2NAfwNoMXzwd+xgechy3DOplWibA/Gg3XpVIpP/6VKe/73fK07V7ovKjz3hexBIhbXoHdmaAjW6pLq72FyDldwva5S7A+/K1+Ntj5vvNnd3Xdbm5+epMY8M4OyfP+zet/fUcPdUfL0c/+NfvL+pWFKiUv84o7oDB70ZJp2ZRfhy0RgsJ6Cg45Q+StSFtS3pNhFfcd5GCk6Apjfb9QteSR9llkEVbLRj4grBPkaAZF0gLKbaohI4roGyWOWZY2zDnVVpjCZGYIURV8y1BRDNfWn1snkRKTGw7y1u3mGgW1yMJl6oQXH8E+svqhRDDHKGGkFbELxp/KEvJ+MHVbCXuPMIjAVwc+dCJTsa1LMkKJl7G6tE+ZDWJ2qvixpu2VKnvIWqvKiVAN9prh0YwDqteHBEdYcnHEAWQWuhPOm4Y3G7dwyAXBeefE9AnmIWADmIkToj6BEgYecm9jV4hnogRtKP8NpggsdhPFEqm2BoYK0Iyz8r4LaGVOKAUYb+lME/doRyMU0wJYR6e2h8hW6TW1eDaJcZDlUjrRdCwmDf0k/jmi9z5u6t7JM0QBfyHWwJqp+lbuqS8j3phwFlgkeq1UuoJg5qIlYGYHuIc8rvJLKMS5MAcxzR/hKQekObc5QJgSIbJnbiSpfUFlUeARi9ECg8Afa8chiwZ/bzIjOn+QcXqw1P5Y3wNlelKZQpQOB5xoeeG14OxwNLGDJVUJjAP74ON5YulKfkWYI+CecI5wHVkzg1MJT8AVsT+wrvxySFMWoVANUFb3eDzItf1hdXb3fTXFeWFPaLgaYhxWZYF2AagH4B88dVqOv9rrwwyUF4xUF+wgqPxsJxJD+Ql4SH/lrigroqrTDioVjgv93YyCQfYkXfoiFZF3U8V16Ah+mXYxF2sZbPlzyLTdGBmYfXqyu6kpVpvsKDu4a3H8wUlNcJC4ZNXkqRjIbgDzQuUMbAfRWZDbgCsPeRmXHVDTNEGR0dDWESoIsJ1AZVioS/bHg0oF+phOsMCgHYAz5qldQNdZxYJnLcUs1wGxCHYq0VXmqvTrG1RyWZkIFMsfmYmX7GdbtPHWNu0+HHbePat6XsNTFKxbSex1vr2UGio8h9LN2F0Qp57OWEF6rt0y1+F/Aqu+FHuFPzCovLykLSn1xGyIiFC0uDHCaoBUwUsuapF9iiRxEcAF4bkFNjKBgkDOJWJsoOWNBKmm5Unh+lhmPkSEgp0J+NI9bVLzKT0O2zWt0dppaDQmf/MKsZTAeqEyqLEyGmdv5X0L6mE/FM8gV8024Zhc5vnxNLbqJAhxrPxVUc6jAZZMl8ASwJyAFOh9oQ6BGjmtzwwQ4MZFQFiyhKA0svDvRS3+DcuB8GEDVNFJtmxMV5pre+vAw74LgEBCU56tf6Szt+tehPPth/jdR4gCa9yeTlOcF74brS8rw5cet96+ONnY+fFjffnXRIwSNoy/tSHQTcXh4uPLvjRvAJ9+1zowJm662FjdehHA+9r9WbmW1bMnYJdAb54jTNZTzzaLazoHZxMu5jOjfEBz18oun8iULnG4Ns9rcp9+pIC0JZ73xrbCERms927XFSBOzU9Sxg0AOYauiyBBWlKd1gX2FzDF4wgWXc/54pGMk5EhzPP0WEBeqwVFN8riABbGs8qO8GveVZ4OQY0OjHfd82c8gk0Mb+B2CGhyYEt0TjCXo/JiiqYFuCJwF3H3uYk6hVwZjBBTBZYe/9jIAuAB/KkHlRbX3E3MorEPuWzoIHJyPximJsMIKiUwELloaeBrYc7YAJ2tZP/VJF2Jk6HuHoXZpqF1Tua4Z4HcUPmv4rE/YZxWvqiLTia95sspVhcAgoYARKnlxzAQDYmTOBP5LcPOqghw3z2QCLltMcrSVe6sxrcNQi+Su56+oaT1qMQVgAFNw+smMQDEU+JiYEEX0te28KXR+aoDFAJg5FBq7NHiQpkTmicooLkHepNfo7JY7A1q9dOJEQ/w3OMY1qgVAMAEiiI5/HPOU+Z2YetHSkKmFr0gG1swEiz/+6AKhiSzlqcq60RVAHuZ6cUFxjzaw+O//9teUavD/TgXQDGHrn+av4mLc/CF4WwsbOKQWkxFXFHHOUG0HlqcW+A2QrMBVa836TaqixI+o1hnrSNFrrAmhIayOscFXgE4t23CBeH+MfMU31gzBrT06QPP+i6FbMb0SAGpLpGv4+LQU1fbpCN1GwtWS5bhDHNcSTMmU9OG8R52KzU1Q+oDXPlGkwMEqmkY5szvDh1LkQ8eE4XWgVOWVzhXyaGO6A4P+wQAh/KHz+cg/C6+rrUfqBnxuPO0UF27Ad+Ns1B2OeruNv2Y2WBSbmTZK80BQ25vJF1jG6Nu9IIvBoaa1S4W27hj1OW+reeQBW2xoNYWMljeEpLC6n3k5nbei0jt8jR9DDoXtNhvgMVC5gIM0mETuQBRPVlZRboTYNVA5ypzrJroTnbZxF1I89E4Xp0mD5oHHhFMJWZuwwfrTKJ0RXCDIfYLhiXjrP1U1z53AlEC7DFj2LzBrA8z6F9j0X+sV/xUxmf+yYNPbhvP/+WDWqwFJKVEvqe5oDlyEEY84Gw/HWCcQaw71KZaeoSURAuRwxgE66lT5c9xTi14HKloD/ubAoTH2rwUOereveCHgM4ZDwpUnG1/2vqTFz9u76d44+bK9/sujsx+3PtrT5/ffvXudHfzY3X7V3fil/KlKGOJ5iV/cEcRT56k6Y2znG/zoqrhOuiF57G/4300850sDdZDSnoRmT7UTZioHmMI5Tlof/GPsC7NGy7xe9wDJsZ04TOgvRZxYDOFhnvlNcBcKAGypPLUBV+z3GcfqJTqB1gSLrp2neTZefPW2XNyaqAxAaGY+bQNA17IOnZLyNO4RMIt5bokpzw76fGAuD2xy2S2ZU8MqIlG+tppl3YedBYBRG4VpVmbwQwRSFqq0cMyMzSlNDoN/ccrrIAW8FH0PrwWcz1dXd3M6zu+FFv12669xoUrD7Q+XPH4+vP/q9MnWZ/fbZvqs2vmye7Sx+/zz42niyqO9J9m2cvnDb+v35WcPV7/EL25Xlz1/3rsCapJ1HsNPZciZNH7SDP5cHfFedq+F6cSdd5mRtiPROYXIQVX/R1NHH9TYb6+DGkX71gOjU0L5snpCmEQE0JeIn0xFWuoB5A8lhH4hyVjlLmRIiXh+LFHtqzERH2g4jE2e6AxVS9D/Efn9LMk49kuh4CPamR6fa/HXfeYR99D9RAHnt5vA6PGxE+rN4vjHRWn6mRrbHoFCJ74atYXymXJduD+7BDD2MTrstzLQ0PBP+gKCTPZVxlznHAEyA9aTYVI5SaUSpU9h3iCu2ptdJDy7MI4O6FY6GlH+7Hxkk5aD+QkJU02vFr8EBxV1SkHDmKUbR5YxOhgCHJh8exGBqrWtwWyY1xCFnGZGpj2xgaEUrr1mfv8Ij921hUr0ANCuYcIQl0XIHJ0LC7eVmefLJ8wsI+rH2vpqdTymOdNLbOAcUANcqstYP9oKAbUcbp8gQ6MZKwhMBXi/bVQez838erAisZZkNsmvG3am/xrocjEz4Rfff6BSjzpqVLdoz+pfTOcOBeoNBDZDqaDMiVp2UmvOcQMPOLP5YXmpryvDv/mv9pIb6NAzg8mvI994qjtA3mnXI5gfxGx5aE2EvlwQWj/JzSRsbp+0xOhgqHi3I1Nhf4pT2EYRfwb2cSDoPV8Dvu7cWnmSUGYTqCP6fomCyiSpJRwDyz1uhA7hLVmw4PucE8p1yQirOrAhtfOVZaWy58ErGz0xG3QECbT55LKKMLzkvHVNTG4hgwh6LWj26JMZzTEPRI8bSWB4OYC8wyd+O4S8PlzCSovUKpYYoWEis0jTNl8O3w93Oswf7j8XVCwdJC0bjgbJ1jwW9amRPNWmKkFV4Rc0YdCbpSc2AE6PVlArSz/sGb9S3ouYKRjxeasZsprgekyJoWC+Jy1VkUxFX1FXn2o4YlSCzLhEzVZlUWqr1kJ5UlwpZAGshsrXDwUVit+6LZMzGRkYG4SXsVShLE3JrTFoFIWxkD9QHlsCV9E3IWGHiRM66oG+KMEsxfxKUA7DOqKH0aknw4XttSbQtCHjk/Uf9qng3YJsSw5b4cqoXmiCmxf2JTrkVDHUoYuOTR+MHCqsmEEEn1uRQSqW+vVAO4YSqljAOjlTZaItKlttIeGEYsFpCuhHYiYixe5jtu5pIgvlM9Z0kmLIjBRfVIs4kTlp5VSdavDtcPNyjZKvnYDP9ZhOCtZHqYEt1djpgtBP2Hd2wZ6X0BUuR/wTWpHgOZeQLUChiL4U8ZfncjAHLQ4dc3AFPYRgg8Ij0Ls0Bz2pTS6zGmwzkVMxxo4cs94gZYm4sU5PbDlWkyhvfDQGaeFYDBz5ICdcUkkzF1NRN5uhRGYkKpHUYA8QdVaUipiYczFQEzC+oMnGRUTU67M2NSb087mKsEYzFyx76QdEHBzHmTpVmaiKju86xDEJqr9se9UQ4rhoiNCqG2W7QKkmNVGPR9tm+yW2h2WpUUATqsk0495NRz2Db7Ewglk7H21GyaKfvYrMlkWH3jmPbByNS2ygRbdauKl8NLZhOAX8cfOMLHxfn6ggYca0YvWFZoC9sOoRrahFsQpsLekqwinRHf0bSkdL/WD1wZPu6vMuVA2eG9q4gn89Fwe5nP/aEi35E6d4URzlaqEHpAfY+TB4mk53Pv9yPPjwbuvjU5fufX5gnj3d/fnpJ3Pycu/no8L2JzuDh888PcDyv7ireMuDbqHzLkfYKcpJ1YldO5IcYNnVeYjBY7yqJsa7Zjzl3Kc3AigP8Og4ZyRXj5eECmkuFUd7BezgARgIHLAby2Mwp6kVKuN2w1EqkpGB/kz+QIUDJDBFOg4Dc9k9xCusQm/EgLz7Y3gWwJATBYatoC8VPHhNNHtyiqRyFppPJQ6+thF4lknF4jJ12BeJ6mJ9+7w3c/pPfD/PiodhSYLv5qrFKWv0MON3h41m+mDU27p/BJS90Ra2ISaVGopdNCNAvoGYKEp9ClbWiZo2OjJSVOYUc/hYuw4IRyneaPe26kNrOkGt6SYYUIGVgarwqizgT00cAFOAUYQOggBfRBaJNi+jJ3bAUeTVL9UApncKC4sGkjNEFRAkEI9rMob79TWcI2FDB/6DY9RYWUvFBOeyYqBhkRtmwEPfNZ/ylIyvFSXY4LAHeoEFOsUDaHhWb6jOsqSX4iV29qUGnnANWeCAkupCD+C4kRpLKb2PhxSFMBhvLY8rnfNdeDUulF+ZaUkcmNRbkKfaa47JyKC1T3uVvNtSpqqDgUaKIZjCdXUeDiMfz8/B+xqA18qJ6Rtx6TlJimTNFH9oagPPRdD3/Us7PokTflLLkP8N2bwE1OrVrZJma09bImm4PeqmzfOxy9k4V0nlnNwHsz8VIzPBIGhmyK3H+wDRo9UgAjqH3jbowaJfOdBn3umzKqlK7YhI0o+1fhHvsdpCqZRir7gzGkGKmUuI1aNVoGZl2UsggXlrEhGIlNnQ/JocmLApuD83eJwzxLY5Kl02b7TjUjZXVm40qLLWEZHosnDhyqK8sYsbskd8EEHn098gnE7uQh02BsaUyMyCy4kqA6ObPHL8BI5VWoV6sxQyOYG0Kh0mQ21dOa37hfte3xxU64S6KCkOVFlKLDQqSnMKBjaCBc9cKUWV8x0AP0zDR05mmenUt/O8c5d5/niXNGPx9j5cETvoEmI/ci+2sdY2KOAdL3pFCSdisF1RQvG0kX1zqtCP5qrGU8lJEoxlxYeAAdNWzwaMWt7A9670hKKDOddWnRUGusGG46Ru/Q5rRcdePfV/OZU36FQ2zlmk+sCgqgw41EuTTFPepiG3LecdnGR8hrUcWnfnb55r4c85mOfa9y3+5Pc5uxe7mhfOyvNf5IH87efV9cmnj6X79Ngc7ORv9fHqy+7js6P00/aHpw+qwSe5e5yts295iV/clW95ISEQ+5fbdedkNvP5TKWrruljXpKWCA/EC0Z0A74muGQjMnnmMTj4ZM4tOK5O1kQpMjFlCv4TBKyhsx0l2UpXs2FTTQYj9iNuqABzp/w0FYGFxplYXEtmoKw5h2yACSEfUsxxH15py1FuhJLPtoP5Xc4AqFmW+tiWTvCeNoSNqMGyFaea0h3BqqVEgPeLYH1qA5KZrIRMIfGN9qYcOLQ70FvLpHWB+QvXkOch3IHdUrqBp5WEID7dB97jmvnYSHLIX8+mkU/LGbGYvp9C0OABY/oVOmT3lufvZ8MKPMyb8U6iJDCIbel7c6NFHgrGambCYYmR6ojWkUALMLucUW6EJnB52PImWxqdnIZRP19mTnkzli0wZVtya8zaIx1BHixKPWUWye/jn3OgcKjITGfIwVoTdFgzCaoUiNGitu4yCC17WX5nM3F9WxgF9zD81icWMTOHRewU86n532eakReqbOQySKIBlsNF1xkmaUK1C9EQoZ/WmNMUYh4wHXdlcC8lvw2TW+cKX5fEos5/QgYb09ulUqFKEZYlVmGYfEQ1xwVJYk8dE/c8GvDNrWiQjI3yv3+ZwTeeW+FN5NVgxFkoY8ZCdQbMCtpl0xdiVj4amu3uTNgLDYg5M/ZC86E1NXLTM3SxGbrUm719sDd4ufv+4+bg4f23jz4+f5u+m9ofu/cPdsrtpD/cGe7uvh4k31bdroeVXuIXd2WKPmKqDwXF/JjJoWO/C4cDkowD/x7boxt0qdjYItskUGBI4hqFS69plC43noZl+gjPhmXGdnXzdGMLsXsxfq7GNXog6KAqIaDv1oB7DeIKkIorjY3jdMA5J8tsGkVJKF9YTPEJVa6/VaonXlLIkAAYhPUCq3hQZaDlB3KsEWrBeHqD9Zk5hcCszocZBYs7ItP9UiIGqr4gdHnvAituF2mNgKul4+Nb8cUzfLCea0aKVDrZl8CD6UNa8c8CZawzJktGYEMjshGP/wFazjBq9D0LXSjEMLCVFPB0fYV2K9me4w7CuaZw/1QVmZmC7TJk+iE3UrokLApY/d1El0ml3Sws4nDlY57pE4rgzSRaOnNQWgLZMYKWM7KRvYeY3qqI265hmIrUUTxDZA/VU4FwO+vQbEd0O7w3sDHBgkCf1MMV5O+zTEjawuQLtjHydFMTuPqTOkVwRat8YysgjDxdczO0dmx8OUcTKso71xJiWoZ1pQgvtH8zk7xOx5WKYsMR6APletqwxcL3MBMbW/NeFnJzgYfE1iFebOW0RtHEIMmAzWzEqmPUZSFhjPQ19vMhcnGH8F2E0TJ6mtxFehJdHDFekYFtsA/fjTgbjMgiFnOPHgozHMg2JlClLYvRGkw6e54clq5yzDDwaA1gxzq19MnmxiEDPDMT5VmJKJbN8GpSrsH1TIn3CgQfMUAwybIPWcqa62hu5fbaNABNH29lv/UQSg3ZZGmVdzVg24KCJcwao22nXgZryAUGegutYD9L5goFmYJEQCeGXJG9y1cSbLNygtB6AHjMU9KjwasDZDqmsOf9q5TrlVieaStL/ymyfYnPXNGCAk55ogCm4g3FqGNNPfcAdishSxqTPNMK+lQV3oMoWlBaKO+K0z8BeCCRS2H4r5h6FD29SZsnth7hEOvNbDGaUMdV+Lw5n6wMfhr1ZmN6MU0E/eDT1nsS2axRheLfHZLPIZJomJz+wliHT0mpOCMFipmUDR7LoRwCz5u7S6CAk+YVKYr4QEkHqQY70ahEoroz4qUD/ebPT0cZYYT7e8c8Ok4op4TgcWRld6rA3AlSvuG/yHeuytyz47KfyLHjOSAgZgNT85vKIbpiO030L83kbPKVQPq2A2EK7IzopdlDBHlMCGLHFUEkbKYGUcgrRJ95y9eaQNrmvvfSA7sbDQEOSFsnMjPUyaXQhXNIR9gYhCnWuYvUIthkhCnmkqH0Lxf4xl3ghsVBnHaq3aiYPfg8hXOwElCc/B4LSH86mtk8w74mWDBR5XfoLS/n2cy5zMv5Na1+8584rRe72MtPx6PfPrnJ65+/PT3ZSe9/e7/7du/jm/HO659TtXO8VeZ7g7evu9ur7qds7OGEl/jFXfnZj7ucJOvCVHZNjjya0y6U11F7FI8ppMtoxhvGMV12Tf/64nE0fOvHhC68YEzXK8mcQ+V5K4FHSlByQlFhuV2oCmuBiI1CK5MPBNwPFYhgzfGjQsYyIFIoyV+bkWh5+fY4hNoCK4sLCPmsInAh7YWp90k9zykeKyY4tampX6fINBphNHm1VUR/U2g26saUlAorCGVm13CzMe6EIHOwFw3aVsLqIVoPMwhBggYSiW+7Jb7ubTjynVRJYJos84g6PsU9tQRgHH0KIAwO8r5cP0HGgyrJXIfjVQ8BDYqVUZrQk15thJbCaPLxyYtPk/YkshNwFmeXzRk2BYihOSLAyA3E+tBjuY43vIcCg/nG2lXt+Q3Bn4PZXkikPZjZGJHFO6N2veWqnX9xagGPBm4dTeCdIW09TwkUgd1QBisu8/FJfBtml3y7sN8D+R59RmHRZqlQfQ8MRFgf+KD+Tzq+AGGn/P18HrNZNjZTrDkf1AkOFz+pxeGiMEn9ka+LIxyWtt4Xi9HCQe7Yv+ViKjh2q7zZrtdypXbe4g4e1OsPjjEiFDmWqNFojkq2MYEDJ19IEXo0LgSFmiLBkoDRojrriFXEoVagGUpJFJV5khRTspyGAEXSnru5EbakWShqgfc9A7ArTyTlOoAE0YdmpYs7Gf2HBf4/zS/pzniwfqtjPVGtczEaLQ7QC8AcPfR70KXJIQVvm3DH0umBTDy0llspast+7xjn0HcACQ327tZFrI2rts5o9ekKKwwqzvssDdbMWvGSTo4WC2UANi3HIzI5bBXwWcUaIq1c2InNmqA8VE4v8rMi3TiA5ghRn4nQ1DuiOw9gPOYm8N4ypMWRlCFIV3QGeV6Fxh0h0QsSgZCRQEcPSCWAzZpBDaBCGCGGTCRi5Z0c/uXV3bBXV5+ceG7UQgHaMz4vdV3Y2nZIesnkM8J6FY+n5h26bxcbzvOgvQvN5tY2sXcxbxf7Z8u97/HDN9OH2982Xv8yeHWa97tfVsf9LVe6+1/eHKtHXzZ18ctvRz8lX7JfPE3YJX5xV77ZpfoesJv2jo+l+aYOkeVNv7imx3aNrgxoSl1ipNeB782D9cAakFx5lFGlRaPhpufg4UoXSl9BdgOLf6wqnXdYQitCTq5hrQtky0CR06aCWuQQCUaLiFFJVA/iAxwQBZkptfY4F4cdJkxdj2UKGDuezRBN5WC8pGD8zFRSTWWgA2tmHG0ITuNB53+SMylceCDkE60I6UlfNJZDaxSYmdjOQoBu0Vu+Wwg/rg1V2dpIpC3xN9sPI7QYYeM6+nkUJw7psAwPC6hStWaGuwSyaPPj7/3g+4psuRkXlJtCzrCKMbhsgLXxFTv07Q1j4rnxBbMAlaLyeix3t8bT7wzYkI162vpSRg9O0Xmu0migUOxW0wIRIQV7MQBbrGeFOIGISGAhKhZuX/syWP2SKw/ipgf6Hnz+Gs6ASd9VM9QRgaDHDWjizs/oAHE1BEdGPCeIlWgQWnMthzrKHqYzzXJmNxWnWUtVcBNRxA00e8pAsJJCLfxGvEsbVW2caJtxIm7Gf6Z1Rxw9OZ2+xJpSIqiC4Iu1GLvs6abUmUoqTGt5TTxT7IrMILML2epfxtNCwSudiz6QUqKS9d1cGTqJTcQnJIw1KMFif9+qiACdaGjXDPy+2RN/IqNOScFzoMawzrvs4M9KIA5fRH/D/WsIMtFU5sQhQe5yrME56VsPIUZADkx5EnOa+3BU3f8brhC4zSEhBzUK9evdnfu3EXGv81uwIzjixtZpXLS0R9k2ysexp47FGrgcrjRphSlurFklYjPNUIXG9VwcF6BEmGx7wX57HisvQvsCIBxeCWMbiLuOsb8XOYMfZFgLklC/jHOnUN3+qqWJODPshDPs2PRZPUPcwiceZJqWisMWkDL8q3Trdly7A2IPAnwbLeq5plGkijuBsNAfAc12Yai94hCOB3Pru6zMupTBPef0XcrcXsCbeueTe7E7eOlJ2d/eLJ5/PkjOpvpo8+PxL19Wj38er77dPP3Fvfzw0X38pMzGm7Iw6vGQPcNL/OKuPMOn3bLK8cWGSHls0Q8+Nn1yigESrAp0ifHYY9/Q96uiylY6yuDYYvWOqgxLFeA31/QOLznChn/4FM3jS4326h7iaw7IMepjxDltTp8QgDH3BAmuwXo9QxNtsahFBSwIGRwBO4XWtfS+ZEgmYHMZat3JARKu5R7LXA+UdQBywjngfsyeVxSNIyhqOVGFC8xWUMsv83kmuVeeK85hwzIbUR3GNy/DaQ5eIYO+TDENLl5cOVbb4gipC5YbMyuT2d8TB0BeCKRuDF8LNdRrYiCZDxZ1EBaUB7wjE5qEpoINUwvTm2XFvw6zagZeTNrZA3BkUVCdgleAL0SPtcp9fNZ6gcBzfKxzyRkVXFUYLcxHzZvhYbPkcDKdazA5PYHMtT2UYcjlYbK2zoTMCklAT8ArU/4KKdoCY7mjLKZ0JEc1vbscDktFGG0k/qhy/xSLTC621QMP0x9gdwGMy7Tv+MChr56DZczMMOpB6T8lOkUCe6BrAMVQCgcSmjfx1NL46fsbcZsOwp2Zjj7Dbe0nOeQUZYpOAV3an2IdE/NhxqtAM7ixJQoNcqDRh/El/bU1Sa7PPNFeTBIaey/BjcJUAcg71ZR5YvqIcYYhYoS8BG+5zdmpcgRxkoZtyDcmgkmw57DPFC62J+1sQxpadp6qHN4Y/l3KvMokJjzY/wJVjoC8Nco4YnEgTp6ORlK3Ng2CJQF9x8DyyBTnilfMVLMsxQgG2Pjs2MMLA1OMLMFAyXrcR7BEHCvsCoMyRT0KeKg+0hd1OUW0h9RZNVOkF8ETWma73ndM1lkOK0oRAn4VIIhVTvsUVHto6MX4S+AKDa8XUXly7Cc+TO6UkwNVdicc0Q3ZgB642BnE10jRwvqXIPKuPAW+a0uy6xmGUH7rhZUZYIGhIZrvYuvPH2okzCkIYv7u1B9gtm5qHVRqhA8j1e1Kxb2Ijch9rwwA6eRhN1B0IQ/FET3xGqGulAMf0BESDr4G2xbSdwNeHVjuENKaJBWBnAPRNo7YxsEC48NHyHMEdamqtMoGLDXvBZQmVNFwbo11DlGbFvQ4W94++ThS8lRjkaZMaF+AkPmj9yLfec+DgWdsB7bRYvnjqlAKEueGGGtlHZyBoCiQM+gs9YAG9pnr8gUSl1rL/+Uy37DLXBsVRKdoa8OhaShy0r5pnjatBNoCsT0WGwQNPTmQQYzGTdvvDn3qS7opc171JZ2UBX7197cCFzveV5g51119nnw+nVSy+1v3c7L6sDqxlbr/ZKzvd5//+Onk+LdkdPp+dfj+p012vS/xi7tyvZ914SjrwknWJVNAlV3tLDSj6DInTRfK3GXqWzxBEizyZQDXw4efZzGj66/pcl9iZA13+xkefkuP8hqgWuAAiANNnAQl18IKaI9HLEIxe8JaKCip7blClUiEhdxBVQrM4AdzyT0muactxT2FAYabmCxjhBzkIbj4hPcIvys3rwDKdThDqfkF+8M0P7BxsAJLYew3pLswO1s7/Thl/rBrkEIEKJPkq1BRjJUroTcHqRLqqUG8cO18FNQpC25DrDPMDOeLojiB58lowBTCXGB9zlblKaw8OQoEAcYZifH83FeKEf9ROCSbBp8obtkaKoAInwllWSGnnJhxH7twoJrEKRsy10xjzhjVVdvAPmmDRXzNyENdzPeCIHUGQoxesxFecerNf3om5L5q7As8MGIZAW/aVK6o3EzBEXHT479wpiBHCnei1ganRqc9salZw6qwk7y9KolgtiRxQAPW16xFk1pDt+GSOPjUKFAdG+Qb59dgjXOdAMNmvfmZZmeKhbERm75OTqbxOxToN1Z5qqgamCz0Db/8dWqLfwN34gixD2NRGo0SPbiVZ26Kj+6JbUXTiqMCEWCoMn5IoeibypzGmxRRqXU6EE9Z1BrBOZ+YGf3YZsfLgEEFxyLGS2BXh9DKB0uF4wEs8K6d6FdTS/eEiEA0NwD3gMxUasA6CkGBMFkdkZamKOKvPKVUdI0M3fzq64JS81QttEWEHekBSExd4FdGOUHP52S5vUNj/zfQC76QDUuEsb4NiLF8dyRt620dGzH9KbUlskwuVZeptjPSoiBaBDx7zAZQO0I3IqfzhKtQPVU0tDPKk9rTDAyh2vGhQJNuskyjBiHDr1YjLPhcbcg8RWhs1QAg2nN3C/DlVA4NrxPOCQ99R/QxqUYQeVhE79C9w01du6DRCVd7vbjq+IaA97YFDM3DX9kyw0JwTatfUJo4ntImrIZPhDCtHkMd9C5WdXDWiFu/hzNgplwSZDOF6tCQng4IGL+TMTC1TOHmjLr0wdPGbrJ1CrkxZ4RLmucg9VgajCNUlrkB6oIizx3nuz/x3MOVQHV15qgqyNdu51PfmpC5u+AO8DFK9F8e9e00pQh2U+nsvE17zrnabE4V92KrLQlf0OwJve/OX76EjzHflHN5D2NxJ4o7ndeLveBLzseXNz/+siWPTz692e9nxU/T7NE79/B458fn6dDd/3b84P7+E3W0k/5ox1/YA77EL+7KA37eRcXOXTe6pGfwpen4ZZpU9n59P2kieCWdhJDa+Ki+pue75IgaXu9zPGyWGt31ykgR8YPnXlzoI5t4ZEq3xn0XayoB6nYEhiR118O0Tzh/0TgdSWJvZKYJYuaXfatytxYOVD7iuTDTIziHKlc4KgRpkYPDbucIvRsn3EQnkfNNvVu0z2CM5dTnH6iFpFVyPvOxpwYVvnhk6IaH1GogMo4HXOXXMMCD30pJsKni0x6xyNSEBg5Qyj2dAFMV80iGEBrOXmAUDnTeZHlQqjtCh3d8UzFvE/F0F4XKiVMGLRRcnXViMw2+N8MDqLotAgJwZyi6M7w699lGEGU9zcTLhXb2JBcjbX1nAfSUOG3kGS+DMJGRE0SN035MzE9ZVv/8BBrDRqSKaCbNllFxB3Gf6BqbVFGPMeg6GGoBQz5d+9JKjlRO7VrUjlL5MTkD2f0SaGKYMqSYcvGUMSK7PlcUPpElMxb8Os5D0s/kk20pbUyasuXmWyeAJZYjzFsppuY9I0eAfPDIJuNdJoVT4yLjvKY6KyjyBO1IyPb0kSsfxhmamssnOFogAEoiMRLzBIdzkDOT8IQSzWTmKsZeoTIyUYQ6w0aXAV6doxtioVvZgj6euaGNygEedCxxWjp1apilG3GOwEsF5pHn9/QsDzMw8ms66A1tho4h9MMDPQLRPY0s/E5RaeCwop50ZrYxpulDOTmsBCg3WoQmyZGmkodsGtY79K1y7NDDS2M8hgN8VMRLjn0yUrJ4AW4lRsPqzhT4IDn2/EI6dN7F+82tBDWub3IihUYgzjTYxUDgS0XNhZ0NWKWI9Xa+Ub0nrc1rkeqJdTYWG5RO6JeT6rPMGc2q2n9IITuRVqUf71hzl55WZ7ysMhUCFuWw8jWZ3jnx3ndotDDG1nrYPFhO/aLU2s/vpcB9XU85blSet76vIlHjts3u8Ree0izqBtpM9ANW2zPYU0GHqHLCWpicdf6oyoEqiuK/+Ed9hiWZkhQo7MtFdAC34P5/ltrVvWZjme8ImU3kNDisYY3wjGaXHF3XOqyElQEJkpxvoeCXuEY6RHvGIGSIegYGBRR1f+bUPRPnth5otHLI5g2h8oiL0uPA8bSofVyKljudzHVRnX9/tPkipnIAlFRUrJSF+t8Y135cpUNVpwUGOsuiInRKOFD3TK94LFlSKYWn+MxRZ3JcgE2huJc4bcy6qqFfckcslfu+vs2JIbIR+5fTfjtO+/IGQ2iifq5lEJe0+/M97BeOrIaD/g69+CX9pTkPfklvabH3/udO8MXu/CUmZvputXo3sOXpqjz4XL359HK6/ens/peP+9NnR6/61Wb65NODk6TcHWvvyl/iF3fiykNm6Yy99PUyGWkwCSrMmNKuvXqFcHS3brgbn1mtT5q38sKRq2SJpoVYf7VH0gG4P5Nb6AQDhW1QNeXL0KBaVTrOTlFs3cvFLOdkX4nMWPSPuSNiTckoMxErmQ4Z0pwT8GwW3BibYrcGeOq9KifgaIeKYVPVpVIuKH2qK2kxaQGeJvcBqIU4SDvQ34Mgk8OFNlbaRf+VvFVGhaX1XNW2NtVlQOAXpo3iC1WBl3uWnyylskqiGpE4x8jIj9DhFoMNGTZ9ojksHedg21yombpBOlnXPK9r0AjS2mqsOv5zVgQY0GZuaqI99MYCk55O5/hpIFfRE69mRtZ0ppEUmruaUYc6mEym3ant4o73aysFvSo73koBXpOxRowy/i4wQc9X8p5oPIRPf9D5oJTWlRUKva/t5RRw0FXoSLyI0RGU6QWTgW1ZgLqDntVUOzNGip9g7zgIZASbx40oksp/ldEXtFdlpoeknAF2GmJj/mbnXDXjdp936T4fXRffE8+yr1/pQhCN1rGni+7w6+GKpO9GpRrgV5fsENyIDt5HC+vcJ162u/KFt1sPZ/uFl8YHPo/z6pN0iZ6+y8zKxS1/v8dJuGTTqWUmYrmeVN/jZFyl2cEyM3KJXgjf47RclqNyqd2yHIXl9zgd1yCAWWZmLs8P8z1O0rXqIJeZpquUSX6PE3Vl9Ooyk3RZcOv3OEFXSnIuMzmXyYHeysR8vYlgVlTQENwh8FbASqdDWLZ5nrX9TRHRhsOyKCRzUYxlLnCyyOldUA9wcy9wQcgDQwB4we4DZSf9/d1yPdlKzvaH74fPk/Ljy9em2u6enO5/Onm+3p8U6tPuTxzNuMQvbjeaEYcx6lLs1CSYIEVT/KpxjHA7ktrozxbXOIoFk4fc9DsDscgb7d5WfbGOZ5mNMrfE88IUmgRs5cQbQU0lkoh593i2wV6tzyCFTZWz+ow7CxrKoqShQXvQhb6eEPMjrc3jD7AausCORpjKCu52KPRucF3BZ9TEXZUQzQD5DW3Q+ZHOBPZbygpQ/awMSDXPj+Vmd0Pf95+qqytnMiaWHHhes/3wF15bZUH/Zjr8c1bb3u8NKyhw/4FPD/wjaowxDjm55hvV3UqbPVX44ec8kffjRSEyfv7srPS8mm/ChGPODdPB+nz2QCgOFZpJUD4CMihId6RDApqCGrOD7fV+2Ntcf/Vhky0Q/jcM7wWxABikTggVS1ziPUQXaHcPhVKl/JyFz9jY2T7Y23r58WBr+w37D9EnvXHq68tvL+DzUruJLFOVxzGfRtQmvMDSkR+iCPDF2DeaxqlFf1EmpN4OPvXxFqWCsquY8DKeFZdBJC3EfJ7lkyQK9uxMpr8zt3l9DzVQIEQAdpXDde5gXaDwW0/WP+9NF53C4fh99Pj9xm75+Vvy4Hj18faDk9ONd9nP+9/0y5+mj7IHOwej396Ub59+NBvykW8lsfwvVjorH3dfrR9s1ievzgdG7G8eCKrB+E/hykqJz2839zaFTsV/inuEHajG7Yf0PRzDWDm58vX/AAAkCdgrDwEA" \ No newline at end of file diff --git a/www/.nuxt/content/manifest.ts b/www/.nuxt/content/manifest.ts new file mode 100644 index 00000000..d5d4ab5a --- /dev/null +++ b/www/.nuxt/content/manifest.ts @@ -0,0 +1,75 @@ +export const checksums = { + "docs_duxt": "v3.5.0--Z5sCT9gGa-RAe6nnMqlaoWtD_9oNnR7HOERNc81MTWA", + "docs_workflows": "v3.5.0--TQ9_dTvO8Uv4LqgMQLAay8DXVPhEp9ahKul3KNGtDQ4", + "docs_workflows_v0_7_0": "v3.5.0--gyTLYQ0MVuqj_MoAN7sY-gvt61s3lKmNU2w7azTxNdA" +} +export const checksumsStructure = { + "docs_duxt": "cY12jdAnkQwUxmGB3I0V0TTXMveP9ssYvCz5VOrpPfY", + "docs_workflows": "cshF33POG6AtTmLe-IjziL3JiGGPCJgs5avQ1OmFtj4", + "docs_workflows_v0_7_0": "Pt9fhgX_otrmnFQYPHSGuqExdlY7qwABOOtjCErIPtg" +} + +export const tables = { + "docs_duxt": "_content_docs_duxt", + "docs_workflows": "_content_docs_workflows", + "docs_workflows_v0_7_0": "_content_docs_workflows_v0_7_0", + "info": "_content_info" +} + +export default { + "docs_duxt": { + "type": "page", + "fields": { + "id": "string", + "title": "string", + "body": "json", + "description": "string", + "extension": "string", + "icon": "string", + "layout": "string", + "meta": "json", + "navigation": "boolean", + "path": "string", + "seo": "json", + "stem": "string" + } + }, + "docs_workflows": { + "type": "page", + "fields": { + "id": "string", + "title": "string", + "body": "json", + "description": "string", + "extension": "string", + "icon": "string", + "layout": "string", + "meta": "json", + "navigation": "boolean", + "path": "string", + "seo": "json", + "stem": "string" + } + }, + "docs_workflows_v0_7_0": { + "type": "page", + "fields": { + "id": "string", + "title": "string", + "body": "json", + "description": "string", + "extension": "string", + "icon": "string", + "layout": "string", + "meta": "json", + "navigation": "boolean", + "path": "string", + "seo": "json", + "stem": "string" + } + }, + "info": { + "type": "data", + "fields": {} + } +} \ No newline at end of file diff --git a/www/.nuxt/content/sql_dump.txt b/www/.nuxt/content/sql_dump.txt new file mode 100644 index 00000000..82897988 --- /dev/null +++ b/www/.nuxt/content/sql_dump.txt @@ -0,0 +1,61 @@ +CREATE TABLE IF NOT EXISTS _content_info (id TEXT PRIMARY KEY, "ready" BOOLEAN, "structureVersion" VARCHAR, "version" VARCHAR, "__hash__" TEXT UNIQUE); -- structure +INSERT INTO _content_info VALUES ('checksum_docs_duxt', false, 'cY12jdAnkQwUxmGB3I0V0TTXMveP9ssYvCz5VOrpPfY', 'v3.5.0--Z5sCT9gGa-RAe6nnMqlaoWtD_9oNnR7HOERNc81MTWA', 'zj7H9RSslE9BC8ascPh0RHRCXQUxrRYvhF1_2aZZeBc'); -- meta +DROP TABLE IF EXISTS _content_docs_duxt; -- structure +CREATE TABLE IF NOT EXISTS _content_docs_duxt (id TEXT PRIMARY KEY, "title" VARCHAR, "body" TEXT, "description" VARCHAR, "extension" VARCHAR, "icon" VARCHAR NULL, "layout" VARCHAR NULL, "meta" TEXT, "navigation" BOOLEAN NULL, "path" VARCHAR, "seo" TEXT DEFAULT '{}', "stem" VARCHAR, "__hash__" TEXT UNIQUE); -- structure +INSERT INTO _content_docs_duxt VALUES ('docs_duxt/duxt/getting-started/configuration.md', 'Configuration', '{"type":"minimark","value":[["p",{},"Everything the theme shows is data. Your own ",["code",{},"app/app.config.ts"]," is merged over\nthe layer''s, so overriding one key leaves the rest alone."],["pre",{"className":"language-ts shiki shiki-themes github-light github-dark","code":"export default defineAppConfig({\n duxt: {\n title: ''my project'',\n version: ''v1.4.0'',\n sections: [{ label: ''Guide'', to: ''/guide'', icon: ''lucide:book-open'' }]\n }\n});\n","filename":"app/app.config.ts","language":"ts","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"export"],["span",{"class":"szBVR"}," default"],["span",{"class":"sScJk"}," defineAppConfig"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"}," duxt: {\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," title: "],["span",{"class":"sZZnC"},"''my project''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," version: "],["span",{"class":"sZZnC"},"''v1.4.0''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," sections: [{ label: "],["span",{"class":"sZZnC"},"''Guide''"],["span",{"class":"sVt8B"},", to: "],["span",{"class":"sZZnC"},"''/guide''"],["span",{"class":"sVt8B"},", icon: "],["span",{"class":"sZZnC"},"''lucide:book-open''"],["span",{"class":"sVt8B"}," }]\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"}," }\n"]],["span",{"class":"line","line":7},["span",{"class":"sVt8B"},"});\n"]]]],["h2",{"id":"keys"},"Keys"],["table",{},["thead",{},["tr",{},["th",{"align":"left"},"Key"],["th",{"align":"left"},"What it controls"]]],["tbody",{},["tr",{},["td",{"align":"left"},["code",{},"title"]],["td",{"align":"left"},"The name in the navbar and the SEO title"]],["tr",{},["td",{"align":"left"},["code",{},"version"]],["td",{"align":"left"},"The badge beside it"]],["tr",{},["td",{"align":"left"},["code",{},"sections"]],["td",{"align":"left"},"The second navbar row"]],["tr",{},["td",{"align":"left"},["code",{},"navigation"]],["td",{"align":"left"},"Navbar links; an entry with ",["code",{},"children"]," becomes a dropdown"]],["tr",{},["td",{"align":"left"},["code",{},"links"]],["td",{"align":"left"},"Icon links on the right of the navbar"]],["tr",{},["td",{"align":"left"},["code",{},"landing"]],["td",{"align":"left"},"The hero and feature cards at ",["code",{},"/"]]],["tr",{},["td",{"align":"left"},["code",{},"aside"]],["td",{"align":"left"},"Fixed links under the table of contents"]],["tr",{},["td",{"align":"left"},["code",{},"footer"]],["td",{"align":"left"},"The note and links at the bottom"]]]],["style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}"]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"keys","depth":2,"text":"Keys"}]}}', 'What lives in app.config.ts, and what you can override.', 'md', 'lucide:settings', NULL, '{}', NULL, '/duxt/getting-started/configuration', '{"title":"Configuration","description":"What lives in app.config.ts, and what you can override."}', 'duxt/getting-started/configuration', 'lj0jO29J9MsCdEBCwfApw-yl4w5FowDZv-2pdSCjtDg'); -- lj0jO29J9MsCdEBCwfApw-yl4w5FowDZv-2pdSCjtDg +INSERT INTO _content_docs_duxt VALUES ('docs_duxt/duxt/getting-started/deployment.md', 'Deployment', '{"type":"minimark","value":[["p",{},"A duxt site is a Nuxt application. Anything that runs Nuxt runs it."],["h2",{"id":"static"},"Static"],["p",{},["code",{},"nuxt generate"]," produces a folder of HTML. This is the right default for\ndocumentation: no server, no runtime cost, and every page is cached at the\nedge."],["package-managers",{"command":"run generate"}],["callout",{"title":"Remote sources are read at build time","type":"warning"},["p",{},"A site reading another repository''s ",["code",{},"docs/"]," picks up changes when it builds,\nnot when they are pushed. Rebuild on a schedule, or trigger it from the source\nrepository."]],["h2",{"id":"server"},"Server"],["p",{},["code",{},"nuxt build"]," produces a Node server, which you need if pages must react to a\nrequest — a private repository behind an auth check, for instance."],["h2",{"id":"what-the-build-needs"},"What the build needs"],["ul",{},["li",{},["strong",{},"Node 24."]," The layer uses ",["code",{},"node:sqlite"]," rather than a native driver."],["li",{},["strong",{},"Network access to your sources"],", if any of them are remote repositories."],["li",{},["strong",{},"A token"],", for private ones. Content reads it from the collection''s ",["code",{},"auth"],"."]],["h2",{"id":"what-the-site-serves-besides-pages"},"What the site serves besides pages"],["table",{},["thead",{},["tr",{},["th",{"align":"left"},"Path"],["th",{"align":"left"},"What it is"]]],["tbody",{},["tr",{},["td",{"align":"left"},["code",{},"/llms.txt"]],["td",{"align":"left"},"The documentation as a Markdown index, per llmstxt.org"]],["tr",{},["td",{"align":"left"},["code",{},"/mcp"]],["td",{"align":"left"},"An MCP server over the same content — ",["code",{},"list_pages"],", ",["code",{},"search_docs"],", ",["code",{},"read_page"]]]]],["p",{},"Both are generated from the collection the pages render from, so neither can\ndrift from what is published."]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"static","depth":2,"text":"Static"},{"id":"server","depth":2,"text":"Server"},{"id":"what-the-build-needs","depth":2,"text":"What the build needs"},{"id":"what-the-site-serves-besides-pages","depth":2,"text":"What the site serves besides pages"}]}}', 'Where a duxt site can run, and what it needs there.', 'md', 'lucide:cloud-upload', NULL, '{}', NULL, '/duxt/getting-started/deployment', '{"title":"Deployment","description":"Where a duxt site can run, and what it needs there."}', 'duxt/getting-started/deployment', 'ue7UqIRBoSAXRNCVm8hrcSF0DiwSNMRqX8B3dHBG78w'); -- ue7UqIRBoSAXRNCVm8hrcSF0DiwSNMRqX8B3dHBG78w +INSERT INTO _content_docs_duxt VALUES ('docs_duxt/duxt/getting-started/index.md', 'Introduction', '{"type":"minimark","value":[["p",{},"duxt is a Nuxt layer. You extend it, put Markdown in ",["code",{},"docs/"],", and you have a\ndocumentation site — navigation, table of contents, theme and search included."],["p",{},"Where it differs from a template is what happens next: the same layer reads\n",["code",{},"docs/"]," from ",["strong",{},"other repositories"],", and from ",["strong",{},"tags"]," of them, so one site can\nserve many projects at several versions without a collection declared by hand\nfor each."],["page-cards",{}],["callout",{"title":"Early days","type":"warning"},["p",{},"Nothing here is decided. The layer works, the theme is being built, and whether\nthis carries a public project is still an open question."]]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}}', 'A Nuxt layer that turns a repository''s docs folder into a documentation site.', 'md', 'lucide:rocket', NULL, '{}', NULL, '/duxt/getting-started', '{"title":"Introduction","description":"A Nuxt layer that turns a repository''s docs folder into a documentation site."}', 'duxt/getting-started/index', '0KI_eIwrQyXQabXAFSm-pd-BXNxsXXMZV9Ec8HRt7T4'); -- 0KI_eIwrQyXQabXAFSm-pd-BXNxsXXMZV9Ec8HRt7T4 +INSERT INTO _content_docs_duxt VALUES ('docs_duxt/duxt/getting-started/installation.md', 'Installation', '{"type":"minimark","value":[["h2",{"id":"add-the-dependency"},"Add the dependency"],["package-managers",{"command":"add -D @kirchdev/duxt"}],["h2",{"id":"extend-the-layer"},"Extend the layer"],["pre",{"className":"language-ts shiki shiki-themes github-light github-dark","code":"export default defineNuxtConfig({\n extends: [''@kirchdev/duxt'']\n});\n","filename":"nuxt.config.ts","language":"ts","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"export"],["span",{"class":"szBVR"}," default"],["span",{"class":"sScJk"}," defineNuxtConfig"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"}," extends: ["],["span",{"class":"sZZnC"},"''@kirchdev/duxt''"],["span",{"class":"sVt8B"},"]\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"},"});\n"]]]],["h2",{"id":"write-your-docs"},"Write your docs"],["p",{},"Markdown goes in ",["code",{},"docs/"]," at the root of your repository. A file becomes a page,\na folder becomes a section, and frontmatter carries the title, description and\nicon:"],["pre",{"className":"language-md shiki shiki-themes github-light github-dark","code":"---\ntitle: Introduction\ndescription: What this project is.\nicon: lucide:rocket\n---\n\nYour first page.\n","filename":"docs/getting-started/index.md","language":"md","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sq-ep"},"---\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"},"title: Introduction\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"},"description: What this project is.\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"},"icon: lucide:rocket\n"]],["span",{"class":"line","line":5},["span",{"class":"sq-ep"},"---\n"]],["span",{"class":"line","line":6},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":7},["span",{"class":"sVt8B"},"Your first page.\n"]]]],["callout",{"title":"Nothing else is required","type":"tip"},["p",{},"The navbar, the sidebar, the table of contents and the landing page all come\nfrom the layer''s ",["code",{},"app.config.ts"]," — override the parts you disagree with."]],["style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sq-ep, html code.shiki .sq-ep{--shiki-default:#005CC5;--shiki-default-font-weight:bold;--shiki-dark:#79B8FF;--shiki-dark-font-weight:bold}"]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"add-the-dependency","depth":2,"text":"Add the dependency"},{"id":"extend-the-layer","depth":2,"text":"Extend the layer"},{"id":"write-your-docs","depth":2,"text":"Write your docs"}]}}', 'Add the layer, extend it, write Markdown.', 'md', 'lucide:download', NULL, '{}', NULL, '/duxt/getting-started/installation', '{"title":"Installation","description":"Add the layer, extend it, write Markdown."}', 'duxt/getting-started/installation', '0K6rpImAZ78CE2bCu95dhpCN6zKErHM9U140XDKOc8o'); -- 0K6rpImAZ78CE2bCu95dhpCN6zKErHM9U140XDKOc8o +INSERT INTO _content_docs_duxt VALUES ('docs_duxt/duxt/guide/concepts/collections.md', 'Collections', '{"type":"minimark","value":[["p",{},"A collection is Content''s unit of sourcing: a glob, a place to read it from, and\na schema. The layer declares one for your ",["code",{},"docs/"]," folder, so the common case\nneeds no configuration."],["h2",{"id":"what-the-layer-declares"},"What the layer declares"],["pre",{"className":"language-ts shiki shiki-themes github-light github-dark","code":"docs: defineCollection({\n type: ''page'',\n source: {\n include: ''**/*.md'',\n cwd: join(repositoryRoot(), ''docs''),\n prefix: '''',\n },\n})\n","filename":"content.config.ts","language":"ts","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sScJk"},"docs"],["span",{"class":"sVt8B"},": "],["span",{"class":"sScJk"},"defineCollection"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"}," type: "],["span",{"class":"sZZnC"},"''page''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," source: {\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," include: "],["span",{"class":"sZZnC"},"''**/*.md''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," cwd: "],["span",{"class":"sScJk"},"join"],["span",{"class":"sVt8B"},"("],["span",{"class":"sScJk"},"repositoryRoot"],["span",{"class":"sVt8B"},"(), "],["span",{"class":"sZZnC"},"''docs''"],["span",{"class":"sVt8B"},"),\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"}," prefix: "],["span",{"class":"sZZnC"},"''''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":7},["span",{"class":"sVt8B"}," },\n"]],["span",{"class":"line","line":8},["span",{"class":"sVt8B"},"})\n"]]]],["h2",{"id":"why-the-path-is-absolute"},"Why the path is absolute"],["p",{},"Content resolves a collection against the rootDir of the ",["strong",{},"layer"]," that declared\nit, not the project extending it. A relative path in the layer points into the\nlayer. The absolute path is computed at load time, which works because the\nconfig is executed rather than read."],["callout",{"title":"Do not make this relative","type":"danger"},["p",{},"It will appear to work in the layer''s own site and break in every consumer."]],["style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}"]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"what-the-layer-declares","depth":2,"text":"What the layer declares"},{"id":"why-the-path-is-absolute","depth":2,"text":"Why the path is absolute"}]}}', 'What Content builds, and what the layer declares for you.', 'md', 'lucide:database', NULL, '{}', NULL, '/duxt/guide/concepts/collections', '{"title":"Collections","description":"What Content builds, and what the layer declares for you."}', 'duxt/guide/concepts/collections', '5QGpKCYqb9vAmehmBmrQTEqXOzjbkllbyj-ygFbZ41s'); -- 5QGpKCYqb9vAmehmBmrQTEqXOzjbkllbyj-ygFbZ41s +INSERT INTO _content_docs_duxt VALUES ('docs_duxt/duxt/guide/concepts/layers.md', 'Layers', '{"type":"minimark","value":[["p",{},"duxt is a layer, not a template. You extend it and every file it ships becomes\noverridable by putting a file of the same name in your own project."],["h2",{"id":"overriding-a-component"},"Overriding a component"],["p",{},"Drop ",["code",{},"app/components/DuxtHeader.vue"]," into your project and yours wins. No\nconfiguration, no slot to thread a value through."],["h2",{"id":"overriding-a-token"},"Overriding a token"],["p",{},"The palette is CSS variables. Redefine one in your own stylesheet:"],["pre",{"className":"language-css shiki shiki-themes github-light github-dark","code":":root {\n --primary: oklch(0.55 0.2 260);\n}\n","language":"css","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sScJk"},":root"],["span",{"class":"sVt8B"}," {\n"]],["span",{"class":"line","line":2},["span",{"class":"s4XuR"}," --primary"],["span",{"class":"sVt8B"},": "],["span",{"class":"sj4cs"},"oklch"],["span",{"class":"sVt8B"},"("],["span",{"class":"sj4cs"},"0.55"],["span",{"class":"sj4cs"}," 0.2"],["span",{"class":"sj4cs"}," 260"],["span",{"class":"sVt8B"},");\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"},"}\n"]]]],["h2",{"id":"what-layers-make-harder"},"What layers make harder"],["p",{},"Every path inside the layer resolves against the ",["strong",{},"consumer"]," unless it is made\nabsolute. Stylesheet entries, component directories and collection paths have\nall needed that treatment."],["style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}"]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"overriding-a-component","depth":2,"text":"Overriding a component"},{"id":"overriding-a-token","depth":2,"text":"Overriding a token"},{"id":"what-layers-make-harder","depth":2,"text":"What layers make harder"}]}}', 'What a Nuxt layer gives you, and what it takes away.', 'md', 'lucide:layers', NULL, '{}', NULL, '/duxt/guide/concepts/layers', '{"title":"Layers","description":"What a Nuxt layer gives you, and what it takes away."}', 'duxt/guide/concepts/layers', 'GXRw98kFh1EUpyZshhW9lQECtmkxY-izr2bbiIIf-nc'); -- GXRw98kFh1EUpyZshhW9lQECtmkxY-izr2bbiIIf-nc +INSERT INTO _content_docs_duxt VALUES ('docs_duxt/duxt/guide/concepts/sources.md', 'Sources', '{"type":"minimark","value":[["p",{},"Content can already read a collection from a git repository, at a branch or at a\ntag, with auth for private ones and hash-based caching. duxt does not reimplement\nthat — it removes the boilerplate of declaring one collection per version and\nrepository."],["h2",{"id":"today"},"Today"],["p",{},"The mechanism, used directly:"],["pre",{"className":"language-ts shiki shiki-themes github-light github-dark","code":"defineCollection({\n type: ''page'',\n source: {\n repository: { url: ''https://github.com/kirchDev/workflows'', tag: ''v0.7.0'' },\n include: ''docs/**/*.md'',\n prefix: ''/v0.7.0'',\n },\n})\n","filename":"content.config.ts","language":"ts","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sScJk"},"defineCollection"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"}," type: "],["span",{"class":"sZZnC"},"''page''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," source: {\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," repository: { url: "],["span",{"class":"sZZnC"},"''https://github.com/kirchDev/workflows''"],["span",{"class":"sVt8B"},", tag: "],["span",{"class":"sZZnC"},"''v0.7.0''"],["span",{"class":"sVt8B"}," },\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," include: "],["span",{"class":"sZZnC"},"''docs/**/*.md''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"}," prefix: "],["span",{"class":"sZZnC"},"''/v0.7.0''"],["span",{"class":"sVt8B"},",\n"]],["span",{"class":"line","line":7},["span",{"class":"sVt8B"}," },\n"]],["span",{"class":"line","line":8},["span",{"class":"sVt8B"},"})\n"]]]],["h2",{"id":"the-shorthand"},"The shorthand"],["p",{},"Not built yet. The shape being aimed at:"],["pre",{"className":"language-ts shiki shiki-themes github-light github-dark","code":"sources: [\n { path: ''docs'' },\n { path: ''docs'', refs: [''v1.x'', ''v2.x'', ''main''] },\n { repo: ''kirchDev/app'', path: ''docs'' },\n]\n","language":"ts","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sScJk"},"sources"],["span",{"class":"sVt8B"},": [\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"}," { path: "],["span",{"class":"sZZnC"},"''docs''"],["span",{"class":"sVt8B"}," },\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," { path: "],["span",{"class":"sZZnC"},"''docs''"],["span",{"class":"sVt8B"},", refs: ["],["span",{"class":"sZZnC"},"''v1.x''"],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"''v2.x''"],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"''main''"],["span",{"class":"sVt8B"},"] },\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"}," { repo: "],["span",{"class":"sZZnC"},"''kirchDev/app''"],["span",{"class":"sVt8B"},", path: "],["span",{"class":"sZZnC"},"''docs''"],["span",{"class":"sVt8B"}," },\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"},"]\n"]]]],["p",{},"Three versions across fourteen repositories is 42 collections by hand. That\nnumber is the whole argument for the shorthand."],["style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}"]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"today","depth":2,"text":"Today"},{"id":"the-shorthand","depth":2,"text":"The shorthand"}]}}', 'One repository, several repositories, several versions.', 'md', 'lucide:git-branch', NULL, '{}', NULL, '/duxt/guide/concepts/sources', '{"title":"Sources","description":"One repository, several repositories, several versions."}', 'duxt/guide/concepts/sources', 'XeHUNrfRmfv-106EZXWbI-FjZ0JjUDdNP1i43neCpEw'); -- XeHUNrfRmfv-106EZXWbI-FjZ0JjUDdNP1i43neCpEw +INSERT INTO _content_docs_duxt VALUES ('docs_duxt/duxt/guide/index.md', 'Guide', '{"type":"minimark","value":[["p",{},"The getting-started pages take you from nothing to a running site. These go\ninto what the pieces are and where the seams sit."],["page-cards",{}],["callout",{"title":"Read the concepts first","type":"tip"},["p",{},"Sources and collections explain most of what the rest of the guide assumes."]]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}}', 'How the layer works, and how to bend it.', 'md', 'lucide:book-open', NULL, '{}', NULL, '/duxt/guide', '{"title":"Guide","description":"How the layer works, and how to bend it."}', 'duxt/guide/index', '-_gi4P75jGz7er_OgoCjvr4kCc5o1g0V6OesQtJ5xy4'); -- -_gi4P75jGz7er_OgoCjvr4kCc5o1g0V6OesQtJ5xy4 +INSERT INTO _content_docs_duxt VALUES ('docs_duxt/duxt/guide/recipes/multi-repo.md', 'Documentation across repositories', '{"type":"minimark","value":[["p",{},"Each source repository holds nothing but Markdown. The site declares one\ncollection per repository and gives each its own prefix:"],["file-tree",{":tree":"[{\"name\":\"content.config.ts\"},{\"name\":\"nuxt.config.ts\"},{\"name\":\"package.json\"}]","title":"the site"}],["p",{},"The source repositories stay free of Nuxt entirely — which is what makes this\nwork for a Go or PHP project."]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}}', 'One site, many projects.', 'md', 'lucide:folder-git', NULL, '{}', NULL, '/duxt/guide/recipes/multi-repo', '{"title":"Documentation across repositories","description":"One site, many projects."}', 'duxt/guide/recipes/multi-repo', 'ZKzc63Zqdezhif8iPc03p1bwlr5_emURNNAhBZZc83Y'); -- ZKzc63Zqdezhif8iPc03p1bwlr5_emURNNAhBZZc83Y +INSERT INTO _content_docs_duxt VALUES ('docs_duxt/duxt/guide/recipes/versioned-docs.md', 'Versioned docs', '{"type":"minimark","value":[["p",{},"Point a collection at a tag and it becomes a version. The URL prefix keeps them\napart:"],["pre",{"className":"language-ts shiki shiki-themes github-light github-dark","code":"const versions = [''v1.x'', ''v2.x'', ''main'']\n","filename":"content.config.ts","language":"ts","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," versions"],["span",{"class":"szBVR"}," ="],["span",{"class":"sVt8B"}," ["],["span",{"class":"sZZnC"},"''v1.x''"],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"''v2.x''"],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"''main''"],["span",{"class":"sVt8B"},"]\n"]]]],["callout",{"title":"A page can be missing from a version","type":"warning"},["p",{},"Linking between versions needs a fallback rule for a page that only exists in\none of them. That rule is not designed yet."]],["style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}"]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}}', 'Serving several versions of the same documentation.', 'md', 'lucide:git-compare', NULL, '{}', NULL, '/duxt/guide/recipes/versioned-docs', '{"title":"Versioned docs","description":"Serving several versions of the same documentation."}', 'duxt/guide/recipes/versioned-docs', 'VvWdy9uqeZP67FXh-CJBaB-lrK33bhnZAjPXsBH-Qo4'); -- VvWdy9uqeZP67FXh-CJBaB-lrK33bhnZAjPXsBH-Qo4 +INSERT INTO _content_docs_duxt VALUES ('docs_duxt/duxt/index.md', 'Documentation', '{"type":"minimark","value":[["p",{},"Everything duxt can do, in four parts. Start on the left, or pick the part you\ncame for."],["page-cards",{}],["callout",{"title":"Early days","type":"warning"},["p",{},"Nothing here is decided. The layer works, the theme is being built, and whether\nthis carries a public project is still an open question."]]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}}', 'A Nuxt layer that turns a repository''s docs folder into a documentation site.', 'md', 'lucide:book-open-text', NULL, '{}', false, '/duxt', '{"title":"Documentation","description":"A Nuxt layer that turns a repository''s docs folder into a documentation site."}', 'duxt/index', 'Z_ZWdWAlFBTJU3btgafK2K8rGYj6XNMG70h3fPzIa9E'); -- Z_ZWdWAlFBTJU3btgafK2K8rGYj6XNMG70h3fPzIa9E +INSERT INTO _content_docs_duxt VALUES ('docs_duxt/duxt/reference/components.md', 'Layer components', '{"type":"minimark","value":[["p",{},"Every component below lives in the layer''s ",["code",{},"app/components/"],". Nuxt resolves a\nconsumer''s own file of the same name first, so replacing one is creating it —\nno configuration, no slot to thread a value through."],["callout",{"title":"Configure before you replace","type":"tip"},["p",{},"Most of what these render comes from ",["code",{},"app.config.ts"],". Replacing a component to\nchange a label is more than the job needs."]],["h2",{"id":"duxtheader"},"DuxtHeader"],["p",{},"The navbar: title, version badge, navigation with dropdowns, search, version\nswitcher, icon links, theme toggle, and the mobile sheet holding all of it."],["p",{},"Reads ",["code",{},"title"],", ",["code",{},"version"],", ",["code",{},"navigation"],", ",["code",{},"links"]," from the config."],["h2",{"id":"duxtsections"},"DuxtSections"],["p",{},"The second navbar row — one entry per ",["code",{},"sections"]," item. Hidden below ",["code",{},"lg"],",\nwhere the mobile sheet lists the same entries."],["h2",{"id":"duxtnavigation"},"DuxtNavigation"],["p",{},"The docs tree in the sidebar. Groups collapse; the group holding the current\npage opens on every navigation."],["table",{},["thead",{},["tr",{},["th",{"align":"left"},"Prop"],["th",{"align":"left"},"Type"],["th",{"align":"left"},"What it does"]]],["tbody",{},["tr",{},["td",{"align":"left"},["code",{},"items"]],["td",{"align":"left"},["code",{},"ContentNavigationItem[]"]],["td",{"align":"left"},"The branch to render"]]]],["h2",{"id":"duxtnavigationlink"},"DuxtNavigationLink"],["p",{},"One entry in that tree. Recurses back into ",["code",{},"DuxtNavigation"]," for a nested group."],["h2",{"id":"duxttoc"},"DuxtToc"],["p",{},"The right column: the page''s own headings, with the current one marked, and\nthe fixed ",["code",{},"aside"]," links below them."],["table",{},["thead",{},["tr",{},["th",{"align":"left"},"Prop"],["th",{"align":"left"},"Type"],["th",{"align":"left"},"What it does"]]],["tbody",{},["tr",{},["td",{"align":"left"},["code",{},"links"]],["td",{"align":"left"},["code",{},"{ id, text, depth, children? }[]"]],["td",{"align":"left"},"Page headings"]]]],["h2",{"id":"duxtbreadcrumb"},"DuxtBreadcrumb"],["p",{},"The trail from section to page. Switched off with ",["code",{},"breadcrumb: false"],"."],["table",{},["thead",{},["tr",{},["th",{"align":"left"},"Prop"],["th",{"align":"left"},"Type"],["th",{"align":"left"},"What it does"]]],["tbody",{},["tr",{},["td",{"align":"left"},["code",{},"path"]],["td",{"align":"left"},["code",{},"string"]],["td",{"align":"left"},"The page to build a trail for"]]]],["h2",{"id":"duxtpagenav"},"DuxtPageNav"],["p",{},"Previous and next, bounded to the current section."],["table",{},["thead",{},["tr",{},["th",{"align":"left"},"Prop"],["th",{"align":"left"},"Type"],["th",{"align":"left"},"What it does"]]],["tbody",{},["tr",{},["td",{"align":"left"},["code",{},"path"]],["td",{"align":"left"},["code",{},"string"]],["td",{"align":"left"},"The current page"]]]],["h2",{"id":"duxtsearch"},"DuxtSearch"],["p",{},"The ⌘K dialog. Fetches the index on first open."],["h2",{"id":"duxtversionswitcher"},"DuxtVersionSwitcher"],["p",{},"Shown when ",["code",{},"versions"]," holds more than one entry. Keeps the current page and\nswaps its version prefix."],["h2",{"id":"duxtcodeblock"},"DuxtCodeBlock"],["p",{},"The card around a code fence: filename bar, language icon, copy button."],["table",{},["thead",{},["tr",{},["th",{"align":"left"},"Prop"],["th",{"align":"left"},"Type"],["th",{"align":"left"},"What it does"]]],["tbody",{},["tr",{},["td",{"align":"left"},["code",{},"code"]],["td",{"align":"left"},["code",{},"string"]],["td",{"align":"left"},"Raw source, for the copy button and as a fallback"]],["tr",{},["td",{"align":"left"},["code",{},"language"]],["td",{"align":"left"},["code",{},"string"]],["td",{"align":"left"},"Picks the icon when there is no filename"]],["tr",{},["td",{"align":"left"},["code",{},"filename"]],["td",{"align":"left"},["code",{},"string"]],["td",{"align":"left"},"Shown in the header, picks the icon"]]]],["h2",{"id":"duxtfooter"},"DuxtFooter"],["p",{},"Columns, the note, and the legal row a consumer fills. The layer ships the row\nempty on purpose: an imprint belongs to whoever runs the site."]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"duxtheader","depth":2,"text":"DuxtHeader"},{"id":"duxtsections","depth":2,"text":"DuxtSections"},{"id":"duxtnavigation","depth":2,"text":"DuxtNavigation"},{"id":"duxtnavigationlink","depth":2,"text":"DuxtNavigationLink"},{"id":"duxttoc","depth":2,"text":"DuxtToc"},{"id":"duxtbreadcrumb","depth":2,"text":"DuxtBreadcrumb"},{"id":"duxtpagenav","depth":2,"text":"DuxtPageNav"},{"id":"duxtsearch","depth":2,"text":"DuxtSearch"},{"id":"duxtversionswitcher","depth":2,"text":"DuxtVersionSwitcher"},{"id":"duxtcodeblock","depth":2,"text":"DuxtCodeBlock"},{"id":"duxtfooter","depth":2,"text":"DuxtFooter"}]}}', 'The chrome you can replace by dropping a file of the same name.', 'md', 'lucide:layout-panel-left', NULL, '{}', NULL, '/duxt/reference/components', '{"title":"Layer components","description":"The chrome you can replace by dropping a file of the same name."}', 'duxt/reference/components', 'z9QtARwt1gAXQGx8ETZeV_HWFjNHIio51lIbuQuklbU'); -- z9QtARwt1gAXQGx8ETZeV_HWFjNHIio51lIbuQuklbU +INSERT INTO _content_docs_duxt VALUES ('docs_duxt/duxt/reference/composables.md', 'Composables', '{"type":"minimark","value":[["p",{},"Auto-imported, like every composable in a Nuxt layer."],["h2",{"id":"useduxtconfig"},"useDuxtConfig()"],["p",{},"The layer''s defaults with the consumer''s ",["code",{},"app.config.ts"]," merged over them."],["pre",{"className":"language-ts shiki shiki-themes github-light github-dark","code":"const duxt = useDuxtConfig()\nduxt.title // ''duxt''\n","language":"ts","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," duxt"],["span",{"class":"szBVR"}," ="],["span",{"class":"sScJk"}," useDuxtConfig"],["span",{"class":"sVt8B"},"()\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"},"duxt.title "],["span",{"class":"sJ8bj"},"// ''duxt''\n"]]]],["p",{},"Read this rather than ",["code",{},"useAppConfig().duxt"],". Nuxt merges app.config with defu,\nwhich ",["strong",{},"concatenates arrays"]," — a consumer setting ",["code",{},"navigation"]," would get the\nlayer''s entries appended to its own. This merge replaces arrays and merges\nobjects key by key."],["h2",{"id":"useduxtsectionnavigation"},"useDuxtSection(navigation)"],["p",{},"The section the current route belongs to, and the branch of the tree it owns."],["pre",{"className":"language-ts shiki shiki-themes github-light github-dark","code":"const { data: navigation } = await useAsyncData(''nav'', () =>\n queryCollectionNavigation(''docs''))\n\nconst { section, items } = useDuxtSection(navigation)\n","language":"ts","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"const"],["span",{"class":"sVt8B"}," { "],["span",{"class":"s4XuR"},"data"],["span",{"class":"sVt8B"},": "],["span",{"class":"sj4cs"},"navigation"],["span",{"class":"sVt8B"}," } "],["span",{"class":"szBVR"},"="],["span",{"class":"szBVR"}," await"],["span",{"class":"sScJk"}," useAsyncData"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''nav''"],["span",{"class":"sVt8B"},", () "],["span",{"class":"szBVR"},"=>\n"]],["span",{"class":"line","line":2},["span",{"class":"sScJk"}," queryCollectionNavigation"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''docs''"],["span",{"class":"sVt8B"},"))\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"szBVR"},"const"],["span",{"class":"sVt8B"}," { "],["span",{"class":"sj4cs"},"section"],["span",{"class":"sVt8B"},", "],["span",{"class":"sj4cs"},"items"],["span",{"class":"sVt8B"}," } "],["span",{"class":"szBVR"},"="],["span",{"class":"sScJk"}," useDuxtSection"],["span",{"class":"sVt8B"},"(navigation)\n"]]]],["table",{},["thead",{},["tr",{},["th",{"align":"left"},"Returns"],["th",{"align":"left"},"Type"],["th",{"align":"left"},"What it is"]]],["tbody",{},["tr",{},["td",{"align":"left"},["code",{},"section"]],["td",{"align":"left"},["code",{},"DuxtLink | undefined"]],["td",{"align":"left"},"The matching ",["code",{},"sections"]," entry"]],["tr",{},["td",{"align":"left"},["code",{},"items"]],["td",{"align":"left"},["code",{},"ContentNavigationItem[]"]],["td",{"align":"left"},"That section''s pages, or everything"]]]],["h2",{"id":"useduxttoast"},"useDuxtToast()"],["p",{},"Toasts, without importing the toast library."],["pre",{"className":"language-ts shiki shiki-themes github-light github-dark","code":"const toast = useDuxtToast()\ntoast.success(''Copied to clipboard'')\ntoast.error(''Could not copy'', ''The clipboard is unavailable here.'')\n","language":"ts","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," toast"],["span",{"class":"szBVR"}," ="],["span",{"class":"sScJk"}," useDuxtToast"],["span",{"class":"sVt8B"},"()\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"},"toast."],["span",{"class":"sScJk"},"success"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''Copied to clipboard''"],["span",{"class":"sVt8B"},")\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"},"toast."],["span",{"class":"sScJk"},"error"],["span",{"class":"sVt8B"},"("],["span",{"class":"sZZnC"},"''Could not copy''"],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"''The clipboard is unavailable here.''"],["span",{"class":"sVt8B"},")\n"]]]],["p",{},["code",{},"success"],", ",["code",{},"info"],", ",["code",{},"warning"],", ",["code",{},"error"],", ",["code",{},"loading"]," and ",["code",{},"dismiss"],". Each level has\nits own icon and status colour. Replace this one composable to swap the\nnotification system for the whole layer."],["h2",{"id":"usepackagemanager"},"usePackageManager()"],["p",{},"The reader''s chosen package manager, as a cookie."],["pre",{"className":"language-ts shiki shiki-themes github-light github-dark","code":"const manager = usePackageManager() // Ref\n","language":"ts","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," manager"],["span",{"class":"szBVR"}," ="],["span",{"class":"sScJk"}," usePackageManager"],["span",{"class":"sVt8B"},"() "],["span",{"class":"sJ8bj"},"// Ref\n"]]]],["p",{},"A cookie rather than localStorage so the server renders the right tab — see\n",["a",{"href":"/getting-started/installation"},"Installation"],". First-party, no identifier, no\nconsent banner needed."],["h2",{"id":"useactiveheadingids"},"useActiveHeading(ids)"],["p",{},"The heading currently in view, for marking a table of contents."],["pre",{"className":"language-ts shiki shiki-themes github-light github-dark","code":"const active = useActiveHeading(computed(() => [''intro'', ''usage'']))\n","language":"ts","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"const"],["span",{"class":"sj4cs"}," active"],["span",{"class":"szBVR"}," ="],["span",{"class":"sScJk"}," useActiveHeading"],["span",{"class":"sVt8B"},"("],["span",{"class":"sScJk"},"computed"],["span",{"class":"sVt8B"},"(() "],["span",{"class":"szBVR"},"=>"],["span",{"class":"sVt8B"}," ["],["span",{"class":"sZZnC"},"''intro''"],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"''usage''"],["span",{"class":"sVt8B"},"]))\n"]]]],["h2",{"id":"highlightshellcode"},"highlightShell(code)"],["p",{},"Highlights a shell command with the same themes as the Markdown fences. Runs on\nthe server through ",["code",{},"useAsyncData"],", so the highlighter stays out of the client\nbundle."],["h2",{"id":"fileiconname-foldericonopen"},"fileIcon(name) / folderIcon(open)"],["p",{},"The icon for a filename, language id or folder. Used by the code block header\nand the file tree, so the same file looks the same in both."],["style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}"]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"useduxtconfig","depth":2,"text":"useDuxtConfig()"},{"id":"useduxtsectionnavigation","depth":2,"text":"useDuxtSection(navigation)"},{"id":"useduxttoast","depth":2,"text":"useDuxtToast()"},{"id":"usepackagemanager","depth":2,"text":"usePackageManager()"},{"id":"useactiveheadingids","depth":2,"text":"useActiveHeading(ids)"},{"id":"highlightshellcode","depth":2,"text":"highlightShell(code)"},{"id":"fileiconname-foldericonopen","depth":2,"text":"fileIcon(name) / folderIcon(open)"}]}}', 'The functions the layer exposes to a consumer''s own components.', 'md', 'lucide:function-square', NULL, '{}', NULL, '/duxt/reference/composables', '{"title":"Composables","description":"The functions the layer exposes to a consumer''s own components."}', 'duxt/reference/composables', 'Y0RweLEoa20QQXQ7bVjMiH3Wdz18cyF0oF7YXqCX0qo'); -- Y0RweLEoa20QQXQ7bVjMiH3Wdz18cyF0oF7YXqCX0qo +INSERT INTO _content_docs_duxt VALUES ('docs_duxt/duxt/reference/index.md', 'Reference', '{"type":"minimark","value":[["p",{},"What a consumer can call, override or configure. A name documented here is\npart of the public surface: renaming it is a breaking change."],["page-cards",{}]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}}', 'Every part of the layer''s public surface — components, MDC blocks and composables.', 'md', 'lucide:list', NULL, '{}', NULL, '/duxt/reference', '{"title":"Reference","description":"Every part of the layer''s public surface — components, MDC blocks and composables."}', 'duxt/reference/index', '1lmypga1r8AWLpQXXiMuEo7bP8gYkCpGQ31SaZbfxC0'); -- 1lmypga1r8AWLpQXXiMuEo7bP8gYkCpGQ31SaZbfxC0 +INSERT INTO _content_docs_duxt VALUES ('docs_duxt/duxt/reference/mdc-components.md', 'MDC components', '{"type":"minimark","value":[["p",{},"Anything in ",["code",{},"app/components/content/"]," is callable from Markdown. These ship\nwith the layer."],["h2",{"id":"callout"},"Callout"],["callout",{"title":"A callout","type":"tip"},["p",{},"Body text, rendered as Markdown."]],["pre",{"className":"language-md shiki shiki-themes github-light github-dark","code":"::callout{type=\"warning\" title=\"Careful\"}\nBody text.\n::\n","language":"md","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sVt8B"},"::callout{type=\"warning\" title=\"Careful\"}\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"},"Body text.\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"},"::\n"]]]],["table",{},["thead",{},["tr",{},["th",{"align":"left"},"Prop"],["th",{"align":"left"},"Type"],["th",{"align":"left"},"Default"],["th",{"align":"left"},"What it does"]]],["tbody",{},["tr",{},["td",{"align":"left"},["code",{},"type"]],["td",{"align":"left"},["code",{},"info"]," | ",["code",{},"tip"]," | ",["code",{},"warning"]," | ",["code",{},"danger"]],["td",{"align":"left"},["code",{},"info"]],["td",{"align":"left"},"Icon and accent colour"]],["tr",{},["td",{"align":"left"},["code",{},"title"]],["td",{"align":"left"},["code",{},"string"]],["td",{"align":"left"},"—"],["td",{"align":"left"},"Bold line above the body"]],["tr",{},["td",{"align":"left"},["code",{},"icon"]],["td",{"align":"left"},["code",{},"string"]],["td",{"align":"left"},"by type"],["td",{"align":"left"},"Overrides the icon"]]]],["p",{},"The body is the default slot: any Markdown, including nested components."],["h2",{"id":"packagemanagers"},"PackageManagers"],["package-managers",{"command":"add -D @kirchdev/duxt"}],["pre",{"className":"language-md shiki shiki-themes github-light github-dark","code":"::package-managers{command=\"add -D @kirchdev/duxt\"}\n::\n","language":"md","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sVt8B"},"::package-managers{command=\"add -D @kirchdev/duxt\"}\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"},"::\n"]]]],["table",{},["thead",{},["tr",{},["th",{"align":"left"},"Prop"],["th",{"align":"left"},"Type"],["th",{"align":"left"},"Default"],["th",{"align":"left"},"What it does"]]],["tbody",{},["tr",{},["td",{"align":"left"},["code",{},"command"]],["td",{"align":"left"},["code",{},"string"]],["td",{"align":"left"},"required"],["td",{"align":"left"},"Written once, rendered per manager"]],["tr",{},["td",{"align":"left"},["code",{},"managers"]],["td",{"align":"left"},["code",{},"string[]"]],["td",{"align":"left"},["code",{},"packageManagers"]],["td",{"align":"left"},"Overrides the site-wide list for this block only"]]]],["p",{},["code",{},"npm"],"''s ",["code",{},"install"],", ",["code",{},"npx"],", ",["code",{},"yarn dlx"]," and ",["code",{},"bunx"]," are substituted for you. The\nreader''s choice is remembered in a cookie, so the server renders the right tab."],["h2",{"id":"filetree"},"FileTree"],["file-tree",{":tree":"[{\"name\":\"docs/\",\"children\":[{\"name\":\"index.md\"}]},{\"name\":\"nuxt.config.ts\"}]","title":"example/"}],["pre",{"className":"language-md shiki shiki-themes github-light github-dark","code":"::file-tree{title=\"example/\"}\n---\ntree:\n - name: docs/\n children:\n - name: index.md\n - name: nuxt.config.ts\n---\n::\n","language":"md","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sVt8B"},"::file-tree{title=\"example/\"}\n"]],["span",{"class":"line","line":2},["span",{"class":"sq-ep"},"---\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"},"tree:\n"]],["span",{"class":"line","line":4},["span",{"class":"s4XuR"}," -"],["span",{"class":"sVt8B"}," name: docs/\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," children:\n"]],["span",{"class":"line","line":6},["span",{"class":"s4XuR"}," -"],["span",{"class":"sVt8B"}," name: index.md\n"]],["span",{"class":"line","line":7},["span",{"class":"s4XuR"}," -"],["span",{"class":"sVt8B"}," name: nuxt.config.ts\n"]],["span",{"class":"line","line":8},["span",{"class":"sq-ep"},"---\n"]],["span",{"class":"line","line":9},["span",{"class":"sVt8B"},"::\n"]]]],["table",{},["thead",{},["tr",{},["th",{"align":"left"},"Prop"],["th",{"align":"left"},"Type"],["th",{"align":"left"},"Default"],["th",{"align":"left"},"What it does"]]],["tbody",{},["tr",{},["td",{"align":"left"},["code",{},"tree"]],["td",{"align":"left"},["code",{},"{ name, children? }[]"]],["td",{"align":"left"},["code",{},"[]"]],["td",{"align":"left"},"The structure"]],["tr",{},["td",{"align":"left"},["code",{},"title"]],["td",{"align":"left"},["code",{},"string"]],["td",{"align":"left"},"—"],["td",{"align":"left"},"Header above the tree"]]]],["p",{},"A name ending in ",["code",{},"/"],", or one with children, is a directory. File icons follow\nthe extension."],["h2",{"id":"steps"},"Steps"],["steps",{},["ol",{},["li",{},"Write an ordered list."],["li",{},"Wrap it."]]],["pre",{"className":"language-md shiki shiki-themes github-light github-dark","code":"::steps\n1. Write an ordered list.\n2. Wrap it.\n::\n","language":"md","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sVt8B"},"::steps\n"]],["span",{"class":"line","line":2},["span",{"class":"s4XuR"},"1."],["span",{"class":"sVt8B"}," Write an ordered list.\n"]],["span",{"class":"line","line":3},["span",{"class":"s4XuR"},"2."],["span",{"class":"sVt8B"}," Wrap it.\n"]],["span",{"class":"line","line":4},["span",{"class":"sVt8B"},"::\n"]]]],["p",{},"No props — it numbers whatever list it wraps."],["h2",{"id":"pagecards"},"PageCards"],["p",{},"Renders one card per child of the current section, from the navigation. Used on\na section''s index page."],["table",{},["thead",{},["tr",{},["th",{"align":"left"},"Prop"],["th",{"align":"left"},"Type"],["th",{"align":"left"},"Default"],["th",{"align":"left"},"What it does"]]],["tbody",{},["tr",{},["td",{"align":"left"},["code",{},"path"]],["td",{"align":"left"},["code",{},"string"]],["td",{"align":"left"},"current route"],["td",{"align":"left"},"Which section''s children to show"]]]],["h2",{"id":"prose-overrides"},"Prose overrides"],["p",{},["code",{},"ProseH2"],", ",["code",{},"ProseH3"],", ",["code",{},"ProseH4"]," add anchor links; ",["code",{},"ProsePre"]," adds the filename\nbar and copy button. Replace any of them by putting a file of the same name in\nyour own ",["code",{},"components/content/"],"."],["style",{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sq-ep, html code.shiki .sq-ep{--shiki-default:#005CC5;--shiki-default-font-weight:bold;--shiki-dark:#79B8FF;--shiki-dark-font-weight:bold}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}"]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"callout","depth":2,"text":"Callout"},{"id":"packagemanagers","depth":2,"text":"PackageManagers"},{"id":"filetree","depth":2,"text":"FileTree"},{"id":"steps","depth":2,"text":"Steps"},{"id":"pagecards","depth":2,"text":"PageCards"},{"id":"prose-overrides","depth":2,"text":"Prose overrides"}]}}', 'The blocks a Markdown page can call, with their props.', 'md', 'lucide:blocks', NULL, '{}', NULL, '/duxt/reference/mdc-components', '{"title":"MDC components","description":"The blocks a Markdown page can call, with their props."}', 'duxt/reference/mdc-components', '6KsWDuRlcJegvGkpb--VoeSFQUYJ4LD_7UoyFRbltzk'); -- 6KsWDuRlcJegvGkpb--VoeSFQUYJ4LD_7UoyFRbltzk +INSERT INTO _content_docs_duxt VALUES ('docs_duxt/duxt/reference/sources.md', 'duxtSources()', '{"type":"minimark","value":[["p",{},"Declaring one collection per version and repository by hand does not scale —\nthree versions across fourteen repositories is 42 declarations. ",["code",{},"duxtSources"],"\ngenerates them from a list."],["pre",{"className":"language-ts shiki shiki-themes github-light github-dark","code":"import { defineContentConfig } from ''@nuxt/content''\nimport { duxtSources } from ''@kirchdev/duxt/sources''\n\nexport default defineContentConfig({\n collections: duxtSources([\n { path: ''docs'' },\n { path: ''docs'', refs: [''v1.x'', ''v2.x'', ''main''] },\n { repo: ''kirchDev/app'', path: ''docs'' },\n ]),\n})\n","filename":"content.config.ts","language":"ts","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"szBVR"},"import"],["span",{"class":"sVt8B"}," { defineContentConfig } "],["span",{"class":"szBVR"},"from"],["span",{"class":"sZZnC"}," ''@nuxt/content''\n"]],["span",{"class":"line","line":2},["span",{"class":"szBVR"},"import"],["span",{"class":"sVt8B"}," { duxtSources } "],["span",{"class":"szBVR"},"from"],["span",{"class":"sZZnC"}," ''@kirchdev/duxt/sources''\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"szBVR"},"export"],["span",{"class":"szBVR"}," default"],["span",{"class":"sScJk"}," defineContentConfig"],["span",{"class":"sVt8B"},"({\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"}," collections: "],["span",{"class":"sScJk"},"duxtSources"],["span",{"class":"sVt8B"},"([\n"]],["span",{"class":"line","line":6},["span",{"class":"sVt8B"}," { path: "],["span",{"class":"sZZnC"},"''docs''"],["span",{"class":"sVt8B"}," },\n"]],["span",{"class":"line","line":7},["span",{"class":"sVt8B"}," { path: "],["span",{"class":"sZZnC"},"''docs''"],["span",{"class":"sVt8B"},", refs: ["],["span",{"class":"sZZnC"},"''v1.x''"],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"''v2.x''"],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"''main''"],["span",{"class":"sVt8B"},"] },\n"]],["span",{"class":"line","line":8},["span",{"class":"sVt8B"}," { repo: "],["span",{"class":"sZZnC"},"''kirchDev/app''"],["span",{"class":"sVt8B"},", path: "],["span",{"class":"sZZnC"},"''docs''"],["span",{"class":"sVt8B"}," },\n"]],["span",{"class":"line","line":9},["span",{"class":"sVt8B"}," ]),\n"]],["span",{"class":"line","line":10},["span",{"class":"sVt8B"},"})\n"]]]],["h2",{"id":"a-source"},"A source"],["table",{},["thead",{},["tr",{},["th",{"align":"left"},"Key"],["th",{"align":"left"},"Type"],["th",{"align":"left"},"Default"],["th",{"align":"left"},"What it does"]]],["tbody",{},["tr",{},["td",{"align":"left"},["code",{},"path"]],["td",{"align":"left"},["code",{},"string"]],["td",{"align":"left"},["code",{},"docs"]],["td",{"align":"left"},"Folder holding the Markdown"]],["tr",{},["td",{"align":"left"},["code",{},"repo"]],["td",{"align":"left"},["code",{},"string"]],["td",{"align":"left"},"this repository"],["td",{"align":"left"},["code",{},"owner/name"]," or a full git URL"]],["tr",{},["td",{"align":"left"},["code",{},"refs"]],["td",{"align":"left"},["code",{},"string[]"]],["td",{"align":"left"},"the checkout"],["td",{"align":"left"},"Branches or tags published as versions"]],["tr",{},["td",{"align":"left"},["code",{},"label"]],["td",{"align":"left"},["code",{},"string"]],["td",{"align":"left"},"the ref"],["td",{"align":"left"},"Shown in the switcher and used in the URL"]],["tr",{},["td",{"align":"left"},["code",{},"slug"]],["td",{"align":"left"},["code",{},"string"]],["td",{"align":"left"},"the repo name"],["td",{"align":"left"},"Segment used in the URL for this repository"]]]],["h2",{"id":"options"},"Options"],["table",{},["thead",{},["tr",{},["th",{"align":"left"},"Key"],["th",{"align":"left"},"Type"],["th",{"align":"left"},"Default"],["th",{"align":"left"},"What it does"]]],["tbody",{},["tr",{},["td",{"align":"left"},["code",{},"showRepo"]],["td",{"align":"left"},["code",{},"boolean"]],["td",{"align":"left"},"more than one repo"],["td",{"align":"left"},"Forces a repository segment"]],["tr",{},["td",{"align":"left"},["code",{},"showVersion"]],["td",{"align":"left"},["code",{},"boolean"]],["td",{"align":"left"},"more than one ref"],["td",{"align":"left"},"Forces a version segment"]],["tr",{},["td",{"align":"left"},["code",{},"defaultRef"]],["td",{"align":"left"},["code",{},"string"]],["td",{"align":"left"},"the first ref"],["td",{"align":"left"},"The ref served without a version prefix"]]]],["h2",{"id":"the-url-scheme"},"The URL scheme"],["pre",{"className":["language-text"],"code":"domain.tld////…/\n","language":"text"},["code",{"__ignoreMap":""},"domain.tld////…/\n"]],["p",{},"Both prefixes are switched on by the ",["strong",{},"shape of the list"],", not per request: a\nrepository segment appears once there is more than one repository, a version\nsegment once there is more than one version. A single unversioned source\ntherefore serves ",["code",{},"/guide/deploying"],", and nothing in the URL says that\nrepositories or versions exist at all."],["p",{},"Deciding at build time is what keeps the scheme routable. Were both prefixes\noptional per request, ",["code",{},"/guide/…"]," could be a folder, a repository or a version."],["callout",{"title":"Name collisions are rejected, not resolved","type":"warning"},["p",{},"With a prefix active, a docs folder named like a repository or a version would\nbe ambiguous. ",["code",{},"duxtSources"]," throws at build rather than picking one silently —\ngive the source a ",["code",{},"slug"]," or a ",["code",{},"label"],"."]],["h2",{"id":"a-missing-page"},"A missing page"],["p",{},"A page absent from the version being read is a ",["strong",{},"404"],", not a redirect. The\nerror page names the versions that do have it and links them. Sending the\nreader to another version''s copy would leave them reading something they did\nnot ask for, believing they did."],["style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}"]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"a-source","depth":2,"text":"A source"},{"id":"options","depth":2,"text":"Options"},{"id":"the-url-scheme","depth":2,"text":"The URL scheme"},{"id":"a-missing-page","depth":2,"text":"A missing page"}]}}', 'Turn a compact source list into Content collections.', 'md', 'lucide:git-branch', NULL, '{}', NULL, '/duxt/reference/sources', '{"title":"duxtSources()","description":"Turn a compact source list into Content collections."}', 'duxt/reference/sources', 'PWm2EQrhrbIwpYfCHJTVY2gYPipmk8eSlZd6lTVjFks'); -- PWm2EQrhrbIwpYfCHJTVY2gYPipmk8eSlZd6lTVjFks +INSERT INTO _content_docs_duxt VALUES ('docs_duxt/duxt/structure/components.md', 'Components in Markdown', '{"type":"minimark","value":[["p",{},"Content ships MDC, so a page calls a component with block syntax:"],["pre",{"className":"language-md shiki shiki-themes github-light github-dark","code":"::callout{type=\"tip\" title=\"A callout\"}\nMarkdown inside a Vue component.\n::\n","language":"md","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sVt8B"},"::callout{type=\"tip\" title=\"A callout\"}\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"},"Markdown inside a Vue component.\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"},"::\n"]]]],["callout",{"title":"A callout","type":"tip"},["p",{},"Markdown inside a Vue component."]],["h2",{"id":"what-ships-with-the-layer"},"What ships with the layer"],["h3",{"id":"callout"},"Callout"],["p",{},"Four intents — ",["code",{},"info"],", ",["code",{},"tip"],", ",["code",{},"warning"],", ",["code",{},"danger"],"."],["callout",{"title":"Danger","type":"danger"},["p",{},"For the things that lose data."]],["h3",{"id":"package-managers"},"Package managers"],["p",{},"One command, every manager — and the reader''s choice is remembered across\npages, in localStorage rather than a cookie: it never leaves the browser and\nidentifies nobody."],["package-managers",{"command":"dlx nuxi@latest init my-docs"}],["h3",{"id":"file-tree"},"File tree"],["p",{},"Icons follow the extension, so a ",["code",{},".ts"]," file looks like a ",["code",{},".ts"]," file:"],["file-tree",{":tree":"[{\"name\":\"app/\",\"children\":[{\"name\":\"components/\",\"children\":[{\"name\":\"DuxtHeader.vue\"}]},{\"name\":\"pages/\",\"children\":[{\"name\":\"index.vue\"}]}]},{\"name\":\"docs/\",\"children\":[{\"name\":\"index.md\"}]},{\"name\":\"nuxt.config.ts\"},{\"name\":\"package.json\"}]"}],["h3",{"id":"steps"},"Steps"],["steps",{},["ol",{},["li",{},"Write the list."],["li",{},"Wrap it in ",["code",{},"::steps"],"."],["li",{},"It numbers itself."]]],["h3",{"id":"toasts"},"Toasts"],["p",{},"Copying a code block raises one. Four levels, each with its own icon and\nstatus colour: ",["code",{},"success"],", ",["code",{},"info"],", ",["code",{},"warning"],", ",["code",{},"error"],". Components call\n",["code",{},"useDuxtToast()"]," rather than importing the toast library, so replacing the\nnotification system means replacing one composable."],["h2",{"id":"your-own-components"},"Your own components"],["p",{},"Anything in ",["code",{},"components/content/"]," is available the same way, including\ncomponents your project adds on top of the layer."],["callout",{"title":"Keep oxfmt away from docs/","type":"warning"},["p",{},"A Markdown formatter rewrites a component block''s YAML props into a list and\nindents its closing ",["code",{},"::"],", which turns the component back into literal text.\nThis repo excludes ",["code",{},"docs/"]," in ",["code",{},".oxfmtrc.json"]," and in ",["code",{},"lint-staged.config.ts"],"."]],["style",{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}"]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"what-ships-with-the-layer","depth":2,"text":"What ships with the layer","children":[{"id":"callout","depth":3,"text":"Callout"},{"id":"package-managers","depth":3,"text":"Package managers"},{"id":"file-tree","depth":3,"text":"File tree"},{"id":"steps","depth":3,"text":"Steps"},{"id":"toasts","depth":3,"text":"Toasts"}]},{"id":"your-own-components","depth":2,"text":"Your own components"}]}}', 'MDC lets a Markdown page call a Vue component. No MDX, no module.', 'md', 'lucide:blocks', NULL, '{}', NULL, '/duxt/structure/components', '{"title":"Components in Markdown","description":"MDC lets a Markdown page call a Vue component. No MDX, no module."}', 'duxt/structure/components', 'EkrdaUu4ntwbxVSGWJXUH-bAxqGJ4gxTuFqxov2jx7o'); -- EkrdaUu4ntwbxVSGWJXUH-bAxqGJ4gxTuFqxov2jx7o +INSERT INTO _content_docs_duxt VALUES ('docs_duxt/duxt/structure/index.md', 'Where your docs live', '{"type":"minimark","value":[["p",{},"Your Markdown stays in ",["code",{},"docs/"]," at the root of your repository. Where the ",["em",{},"site"],"\nlives is a separate question, and there are two answers."],["h2",{"id":"the-site-lives-elsewhere"},"The site lives elsewhere"],["p",{},"Your repository holds nothing but Markdown — no Nuxt, no ",["code",{},"package.json"],", no npm\ndependencies. A separate site reads ",["code",{},"docs/"]," straight from git, at a branch or at\na tag. This is the only sane option for a Go, PHP or Rust repository, and it is\nwhat lets one site serve many projects."],["h2",{"id":"the-site-lives-beside-your-docs"},"The site lives beside your docs"],["p",{},"A folder in the same repository holds the site, and ",["code",{},"docs/"]," stays at the root\nwhere a reader on GitHub expects it. Sensible when the repository is JavaScript\nanyway and the docs deploy together with the code. That is the arrangement this\nrepository itself uses: ",["code",{},"docs/"]," here, ",["code",{},"www/"]," beside it."],["file-tree",{":tree":"[{\"name\":\"docs/\",\"children\":[{\"name\":\"index.md\"},{\"name\":\"guides/\",\"children\":[{\"name\":\"deploying.md\"}]}]},{\"name\":\"nuxt.config.ts\"},{\"name\":\"package.json\"}]","title":"your-project/"}],["p",{},"In both cases the layer resolves ",["code",{},"docs/"]," against the ",["strong",{},"repository"]," root, not\nagainst the directory the site happens to run in."],["h2",{"id":"in-this-section"},"In this section"],["page-cards",{}]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"the-site-lives-elsewhere","depth":2,"text":"The site lives elsewhere"},{"id":"the-site-lives-beside-your-docs","depth":2,"text":"The site lives beside your docs"},{"id":"in-this-section","depth":2,"text":"In this section"}]}}', 'The two ways a project can carry a documentation site.', 'md', 'lucide:folder-tree', NULL, '{}', NULL, '/duxt/structure', '{"title":"Where your docs live","description":"The two ways a project can carry a documentation site."}', 'duxt/structure/index', '2VN8wZouSzFEkTyb8g2vMNlFY5Srsnf00atv_GVpbJI'); -- 2VN8wZouSzFEkTyb8g2vMNlFY5Srsnf00atv_GVpbJI +UPDATE _content_info SET ready = true WHERE id = 'checksum_docs_duxt'; -- meta +CREATE TABLE IF NOT EXISTS _content_info (id TEXT PRIMARY KEY, "ready" BOOLEAN, "structureVersion" VARCHAR, "version" VARCHAR, "__hash__" TEXT UNIQUE); -- structure +INSERT INTO _content_info VALUES ('checksum_docs_workflows', false, 'cshF33POG6AtTmLe-IjziL3JiGGPCJgs5avQ1OmFtj4', 'v3.5.0--TQ9_dTvO8Uv4LqgMQLAay8DXVPhEp9ahKul3KNGtDQ4', 'vy7797xRZw1pIuD0cIKa_JCzoGf4HdFgZThl-oJugN4'); -- meta +DROP TABLE IF EXISTS _content_docs_workflows; -- structure +CREATE TABLE IF NOT EXISTS _content_docs_workflows (id TEXT PRIMARY KEY, "title" VARCHAR, "body" TEXT, "description" VARCHAR, "extension" VARCHAR, "icon" VARCHAR NULL, "layout" VARCHAR NULL, "meta" TEXT, "navigation" BOOLEAN NULL, "path" VARCHAR, "seo" TEXT DEFAULT '{}', "stem" VARCHAR, "__hash__" TEXT UNIQUE); -- structure +INSERT INTO _content_docs_workflows VALUES ('docs_workflows/workflows/1.guides/1.migrate-a-repo-to-a-stub.md', 'Migrate a repo to a stub', '{"type":"minimark","value":[["h1",{"id":"migrate-a-repo-to-a-stub"},"Migrate a repo to a stub"],["p",{},"One repo, one workflow at a time. The file shrinks to a trigger and a ",["code",{},"uses:"],", and the checks the repo reports change name in the same run — which is the part that breaks something if it is left for later."],["h2",{"id":"steps"},"Steps"],["ol",{},["li",{},["strong",{},"Replace the body with a stub."]," Keep the trigger, delete everything under ",["code",{},"jobs:"]," except the call. A caller job may only carry ",["code",{},"name"],", ",["code",{},"uses"],", ",["code",{},"with"],", ",["code",{},"secrets"],", ",["code",{},"needs"],", ",["code",{},"if"],", ",["code",{},"strategy"],", ",["code",{},"concurrency"]," and ",["code",{},"permissions"]," — ",["code",{},"runs-on"]," is not allowed there and belongs to the body.",["pre",{"className":"language-yaml shiki shiki-themes github-light github-dark","code":"# .github/workflows/promotion-pr.yml, complete\nname: Promotion PR\non:\n push:\n branches: [dev, stage]\njobs:\n promotion-pr:\n name: Promotion PR\n uses: kirchDev/workflows/.github/workflows/_promotion-pr.yml@ # v0.1.0\n","language":"yaml","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# .github/workflows/promotion-pr.yml, complete\n"]],["span",{"class":"line","line":2},["span",{"class":"s9eBZ"},"name"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"Promotion PR\n"]],["span",{"class":"line","line":3},["span",{"class":"sj4cs"},"on"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":4},["span",{"class":"s9eBZ"}," push"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":5},["span",{"class":"s9eBZ"}," branches"],["span",{"class":"sVt8B"},": ["],["span",{"class":"sZZnC"},"dev"],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"stage"],["span",{"class":"sVt8B"},"]\n"]],["span",{"class":"line","line":6},["span",{"class":"s9eBZ"},"jobs"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":7},["span",{"class":"s9eBZ"}," promotion-pr"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":8},["span",{"class":"s9eBZ"}," name"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"Promotion PR\n"]],["span",{"class":"line","line":9},["span",{"class":"s9eBZ"}," uses"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"kirchDev/workflows/.github/workflows/_promotion-pr.yml@"],["span",{"class":"sJ8bj"}," # v0.1.0\n"]]]],["br",{}],"List ",["code",{},"stage"]," even where no ",["code",{},"stage"]," branch exists: a filter naming a branch that is absent is a no-op, and it keeps the stub identical in every repo."],["li",{},["strong",{},"Pin the SHA, and put the version in a trailing comment."]," The tag is what a human reads; the SHA is what runs. Dependabot raises the bumps from there."],["li",{},["strong",{},"Pass the secrets the body needs, by name."]," Never ",["code",{},"secrets: inherit"],".",["table",{},["thead",{},["tr",{},["th",{"align":"left"},"Body"],["th",{"align":"left"},"Secret"]]],["tbody",{},["tr",{},["td",{"align":"left"},["code",{},"_queue-branch.yml"],", ",["code",{},"_fast-forward-queue.yml"],", ",["code",{},"_release-please.yml"],", ",["code",{},"_publish-goreleaser.yml"]],["td",{"align":"left"},["code",{},"BWS_ACCESS_TOKEN"]]],["tr",{},["td",{"align":"left"},["code",{},"_publish-npm.yml"]],["td",{"align":"left"},["code",{},"NPM_TOKEN"]]]]],["br",{}],"The remaining bodies take no secrets."],["li",{},["strong",{},"Move the branch-protection rule to the new check names."]," A called job reports as ",["code",{}," / "],", so every required check the repo declares changes string. A rule left on the old name waits for a check that will never arrive, and the PR never becomes mergeable.",["br",{}],"Read the body''s job names out of the body itself and the caller name out of the stub you just wrote. Two that catch people out:",["ul",{},["li",{},["code",{},"_fast-forward-queue.yml"]," reports ",["strong",{},"four"]," jobs where the old copies reported three — ",["code",{},"Resolve the integration branch"]," is where the ",["code",{},"INTEGRATION_BRANCH"]," literal went."],["li",{},["code",{},"_ci-lighthouse.yml"]," reports one job per shard plus a merge job, where a hand-written audit reported one."]]],["li",{},["strong",{},"Take the fix that comes with the body."]," Some repos are behind rather than different, and the migration is what carries the correction. Check ",["code",{},"CLAUDE.md"]," in this repository for the measured list before opening the PR — a repo on the short queue workflow gains the App-token path it never had, and an npm repo without the prerelease-version fix stops publishing a ",["code",{},"dev"]," version that semver ranks below its own latest release."],["li",{},["strong",{},"Delete the old file''s body, not the file."]," The stub keeps the filename every other repo uses, which is what makes the estate greppable."]],["h2",{"id":"three-triggers-worth-fixing-while-you-are-here"},"Three triggers worth fixing while you are here"],["p",{},"A migration is the moment the trigger block gets read anyway. Three things in the copied ones cost runner time for nothing, and each is a line:"],["p",{},["strong",{},"Scan on the release branch only."]," A push to an integration branch always has a pull request open on it, and that PR run examines the same tree — so ",["code",{},"push: branches: [main, dev]"]," runs the analysis twice for one result. Drop ",["code",{},"dev"],":"],["pre",{"className":"language-yaml shiki shiki-themes github-light github-dark","code":"on:\n push:\n branches: [main]\n pull_request:\n branches: [main, dev]\n","language":"yaml","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sj4cs"},"on"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":2},["span",{"class":"s9eBZ"}," push"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":3},["span",{"class":"s9eBZ"}," branches"],["span",{"class":"sVt8B"},": ["],["span",{"class":"sZZnC"},"main"],["span",{"class":"sVt8B"},"]\n"]],["span",{"class":"line","line":4},["span",{"class":"s9eBZ"}," pull_request"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":5},["span",{"class":"s9eBZ"}," branches"],["span",{"class":"sVt8B"},": ["],["span",{"class":"sZZnC"},"main"],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"dev"],["span",{"class":"sVt8B"},"]\n"]]]],["p",{},["strong",{},"Skip what prose cannot break."]," A change touching only Markdown cannot fail a lint or a typecheck:"],["pre",{"className":"language-yaml shiki shiki-themes github-light github-dark","code":"paths-ignore:\n - ''**.md''\n - ''docs/**''\n","language":"yaml","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"s9eBZ"},"paths-ignore"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"}," - "],["span",{"class":"sZZnC"},"''**.md''\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," - "],["span",{"class":"sZZnC"},"''docs/**''\n"]]]],["p",{},"Never exclude ",["code",{},".github/workflows/**"]," from a CodeQL trigger — the ",["code",{},"actions"]," language is what scans them."],["p",{},["strong",{},"Gate the expensive jobs on the tree marker."]," Where a repo runs a suite worth minutes, put ",["code",{},"_verified.yml"]," in front of it and record the result at the end. A tree that already passed is then skipped whichever trigger brings it back:"],["pre",{"className":"language-yaml shiki shiki-themes github-light github-dark","code":"jobs:\n verified:\n uses: kirchDev/workflows/.github/workflows/_verified.yml@\n\n test:\n needs: verified\n if: needs.verified.outputs.skip != ''true''\n uses: kirchDev/workflows/.github/workflows/_ci-node.yml@\n\n record-verified:\n needs: [verified, test]\n if: needs.test.result == ''success''\n uses: kirchDev/workflows/.github/workflows/_record-verified.yml@\n with:\n tree: ${{ needs.verified.outputs.tree }}\n","language":"yaml","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"s9eBZ"},"jobs"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":2},["span",{"class":"s9eBZ"}," verified"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":3},["span",{"class":"s9eBZ"}," uses"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"kirchDev/workflows/.github/workflows/_verified.yml@\n"]],["span",{"class":"line","line":4},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":5},["span",{"class":"s9eBZ"}," test"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":6},["span",{"class":"s9eBZ"}," needs"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"verified\n"]],["span",{"class":"line","line":7},["span",{"class":"s9eBZ"}," if"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"needs.verified.outputs.skip != ''true''\n"]],["span",{"class":"line","line":8},["span",{"class":"s9eBZ"}," uses"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"kirchDev/workflows/.github/workflows/_ci-node.yml@\n"]],["span",{"class":"line","line":9},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":10},["span",{"class":"s9eBZ"}," record-verified"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":11},["span",{"class":"s9eBZ"}," needs"],["span",{"class":"sVt8B"},": ["],["span",{"class":"sZZnC"},"verified"],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"test"],["span",{"class":"sVt8B"},"]\n"]],["span",{"class":"line","line":12},["span",{"class":"s9eBZ"}," if"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"needs.test.result == ''success''\n"]],["span",{"class":"line","line":13},["span",{"class":"s9eBZ"}," uses"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"kirchDev/workflows/.github/workflows/_record-verified.yml@\n"]],["span",{"class":"line","line":14},["span",{"class":"s9eBZ"}," with"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":15},["span",{"class":"s9eBZ"}," tree"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"${{ needs.verified.outputs.tree }}\n"]]]],["blockquote",{},["p",{},["span",{},"!IMPORTANT"],"\nA gated job reports as ",["strong",{},"skipped"],", not as passed. Whether a skipped job satisfies a required check is not verified for this estate — confirm it on one repo before making the marker a rule, or a green run will look blocked."]],["h2",{"id":"checklist"},"Checklist"],["ul",{"className":["contains-task-list"]},["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," The workflow file contains a trigger and a ",["code",{},"uses:"],", and nothing else."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," The ",["code",{},"uses:"]," names a commit SHA with the version as a trailing comment."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," Every secret the body declares is passed by name; ",["code",{},"secrets: inherit"]," appears nowhere."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," Every required check in the repo''s branch protection matches a ",["code",{}," / "]," name that the new run actually reports."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," A run has completed green on the branch, and the check names in it match the rule."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," Any fix the body carries for this repo is named in the PR description, so the change is reviewed as a fix rather than a port."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," The ",["code",{},"push"]," trigger of any analysis workflow names the release branch only, so one change is not scanned twice."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," A ",["code",{},"paths-ignore"]," covers prose where the workflow cannot be affected by it."]],["style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}"]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"steps","depth":2,"text":"Steps"},{"id":"three-triggers-worth-fixing-while-you-are-here","depth":2,"text":"Three triggers worth fixing while you are here"},{"id":"checklist","depth":2,"text":"Checklist"}]}}', 'Replace a repo copy of a workflow with a call to the central body, and move its branch-protection rule to the check names the call produces.', 'md', NULL, NULL, '{}', NULL, '/workflows/guides/migrate-a-repo-to-a-stub', '{"title":"Migrate a repo to a stub","description":"Replace a repo copy of a workflow with a call to the central body, and move its branch-protection rule to the check names the call produces."}', 'workflows/1.guides/1.migrate-a-repo-to-a-stub', '4l2AFobHONzmXJA62L0dZQC1zrax6h-Ll2Ac4nHPhD0'); -- 4l2AFobHONzmXJA62L0dZQC1zrax6h-Ll2Ac4nHPhD0 +INSERT INTO _content_docs_workflows VALUES ('docs_workflows/workflows/1.guides/2.add-a-body.md', 'Add a body', '{"type":"minimark","value":[["h1",{"id":"add-a-body"},"Add a body"],["p",{},"A body runs in every repo that calls it, so the question to hold throughout is what a repo on a different branch topology, a different runner or a different stack does with it."],["h2",{"id":"steps"},"Steps"],["ol",{},["li",{},["strong",{},"Name the file ",["code",{},"_.yml"],"."]," The underscore marks a file that never runs on its own, keeps the bodies together in the Actions sidebar, and leaves the unprefixed name free for this repository''s own stub."],["li",{},["strong",{},"Give it ",["code",{},"on: workflow_call"]," and nothing else."]," A body has no trigger of its own. Anything that has to be dispatched, scheduled or fired by a push stays in the stub — a reusable workflow cannot be the target of a ",["code",{},"workflow_dispatch"],"."],["li",{},["strong",{},"Hardcode ",["code",{},"runs-on: ubuntu-latest"],"."]," A caller cannot set it, and making it an input has not been needed."],["li",{},["strong",{},"Derive what the repo can answer; take an input only for what it cannot."]," The branch topology, the owner and the check list are properties of the calling repo — read them. A version matrix or a language set is not, so those are inputs. See ",["a",{"href":"../adr/0001-derive-a-bodys-configuration-from-the-repo"},"ADR-0001"],"."],["li",{},["strong",{},"Declare each secret the body needs under ",["code",{},"secrets:"],"."]," Named, never inherited — see ",["a",{"href":"../adr/0003-name-every-secret-a-stub-passes"},"ADR-0003"],"."],["li",{},["strong",{},"Choose the job names deliberately."]," They are the second half of every caller''s check names, so a rename breaks required checks in every calling repo at once. Treat them as a public interface from the first commit, and prefer a name that survives the body growing a job."],["li",{},["strong",{},"Write this repository''s own stub for it."]," Same filename other repos use, with a local path:",["pre",{"className":"language-yaml shiki shiki-themes github-light github-dark","code":"jobs:\n promotion-pr:\n uses: ./.github/workflows/_promotion-pr.yml\n","language":"yaml","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"s9eBZ"},"jobs"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":2},["span",{"class":"s9eBZ"}," promotion-pr"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":3},["span",{"class":"s9eBZ"}," uses"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"./.github/workflows/_promotion-pr.yml\n"]]]],["br",{}],"The body then runs here on every change, so a broken one fails at home before it reaches a caller."],["li",{},["strong",{},"Pass every command input through ",["code",{},"env:"],", never into the ",["code",{},"run:"]," block."]," An interpolated ",["code",{},"${{ inputs.x }}"]," becomes part of the script text before the shell parses it, so a value can break out of the command it was meant to be:",["pre",{"className":"language-yaml shiki shiki-themes github-light github-dark","code":"# wrong — the value is interpolated into the script\n- run: ${{ inputs.build-command }}\n\n# right — the value stays a value\n- env:\n BUILD_COMMAND: ${{ inputs.build-command }}\n run: bash -c \"$BUILD_COMMAND\"\n","language":"yaml","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# wrong — the value is interpolated into the script\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"},"- "],["span",{"class":"s9eBZ"},"run"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"${{ inputs.build-command }}\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"# right — the value stays a value\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"},"- "],["span",{"class":"s9eBZ"},"env"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":6},["span",{"class":"s9eBZ"}," BUILD_COMMAND"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"${{ inputs.build-command }}\n"]],["span",{"class":"line","line":7},["span",{"class":"s9eBZ"}," run"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"bash -c \"$BUILD_COMMAND\"\n"]]]],["br",{}],"This holds for anything the caller supplies and for the mutable parts of the ",["code",{},"github"]," context — ",["code",{},"ref_name"]," and ",["code",{},"run_number"]," among them. CodeQL flags the interpolated form as code injection, and it is right to."],["li",{},["strong",{},"Do not call the repository''s composite action from the body."]," A relative ",["code",{},"uses:"]," resolves against the caller''s workspace — see ",["a",{"href":"../adr/0006-keep-the-composite-action-out-of-the-bodies"},"ADR-0006"],". Duplicate the setup steps instead."],["li",{},["strong",{},"Give the concurrency group this body''s own name."]," In a called workflow ",["code",{},"github.workflow"]," is the ",["em",{},"caller''s"]," name, so two bodies the same caller invokes share one group and cancel each other — the second to start kills the first, and the run reports a job that never ran:",["pre",{"className":"language-yaml shiki shiki-themes github-light github-dark","code":"concurrency:\n group: ${{ github.workflow }}-ci-laravel-${{ github.event.pull_request.number || github.ref }}\n","language":"yaml","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"s9eBZ"},"concurrency"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":2},["span",{"class":"s9eBZ"}," group"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"${{ github.workflow }}-ci-laravel-${{ github.event.pull_request.number || github.ref }}\n"]]]]],["li",{},["strong",{},"Run the linters."]," ",["code",{},"pnpm lint:actions"]," runs actionlint over every workflow and needs Docker; ",["code",{},"pnpm check"]," runs it as part of the gate."]],["h2",{"id":"checklist"},"Checklist"],["ul",{"className":["contains-task-list"]},["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," The file is named ",["code",{},"_.yml"]," and its only trigger is ",["code",{},"workflow_call"],"."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," ",["code",{},"runs-on"]," is fixed in the body, and no caller is asked to supply it."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," Every input is something the body genuinely cannot read from the repo it runs in."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," Every secret is declared by name in the body and passed by name in the stub."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," No ",["code",{},"run:"]," block interpolates an input or a mutable ",["code",{},"github"]," value; each travels through ",["code",{},"env:"],"."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," The concurrency group names this body, so it cannot cancel a sibling the same caller invoked."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," Job names are ones you are willing to keep, because renaming one is an estate-wide branch-protection change."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," This repository carries a stub calling the body by local path, and it has run green."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," ",["code",{},"pnpm check"]," passes."]],["style",{},"html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}"]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"steps","depth":2,"text":"Steps"},{"id":"checklist","depth":2,"text":"Checklist"}]}}', 'Write a new reusable workflow that other repos call, without giving callers a value they have to keep correct.', 'md', NULL, NULL, '{}', NULL, '/workflows/guides/add-a-body', '{"title":"Add a body","description":"Write a new reusable workflow that other repos call, without giving callers a value they have to keep correct."}', 'workflows/1.guides/2.add-a-body', 'mVkh4fiumClCxdFtHnbUjTSYqk1TvbVM1C8jqA_Vb8U'); -- mVkh4fiumClCxdFtHnbUjTSYqk1TvbVM1C8jqA_Vb8U +INSERT INTO _content_docs_workflows VALUES ('docs_workflows/workflows/1.guides/index.md', 'Guides', '{"type":"minimark","value":[["h1",{"id":"guides"},"Guides"],["p",{},"Both tasks change something outside this repository — the first changes another repo''s checks, the second changes what every caller runs. Each page ends with a checklist for that reason."],["ul",{},["li",{},["a",{"href":"migrate-a-repo-to-a-stub"},"Migrate a repo to a stub"]," — replace a copied workflow with a call, without stranding a branch-protection rule."],["li",{},["a",{"href":"add-a-body"},"Add a body"]," — write a new reusable workflow that other repos can call."]]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}}', 'The two tasks this repository asks of a person: moving a repo onto a body, and writing a new one.', 'md', NULL, NULL, '{}', NULL, '/workflows/guides', '{"title":"Guides","description":"The two tasks this repository asks of a person: moving a repo onto a body, and writing a new one."}', 'workflows/1.guides/index', 'vzl2SCq8UtnjQ4iPO7sypYIu_TUB8lGT1anQogyiifQ'); -- vzl2SCq8UtnjQ4iPO7sypYIu_TUB8lGT1anQogyiifQ +INSERT INTO _content_docs_workflows VALUES ('docs_workflows/workflows/99.adr/0001-derive-a-bodys-configuration-from-the-repo.md', 'Derive a body''s configuration from the repo', '{"type":"minimark","value":[["h1",{"id":"adr-0001-derive-a-bodys-configuration-from-the-repo"},"ADR-0001 — Derive a body''s configuration from the repo"],["h2",{"id":"context"},"Context"],["p",{},"The bodies replace workflow files that had been copied into every repo and had drifted apart. Counting the copies made them look irreconcilable — the fast-forward queue workflow existed in eight versions — but the differences between them were not eight problems. They were the integration branch name, a per-owner secret identifier, a runner label, and a group of repos that had never received a fix."],["p",{},"Each of those first values is something the repo already answers. The branch name is decided by the trigger that let the run start; the owner is on every event payload. Carried as a literal, the owner-specific identifier was wrong in several repos at once — a mismatch that resolves for nobody, silently, and surfaces only when someone dispatches the workflow."],["p",{},"A value that a caller supplies is a value the caller maintains, and a maintained value in every repo is the copy this repository exists to remove, one file smaller."],["h2",{"id":"decision"},"Decision"],["p",{},"A body reads what the repo it runs in can tell it. An input exists only for what a body genuinely cannot know — the languages an analysis should cover, the versions a matrix should span."],["p",{},"Where a body cannot read a value from the event it is triggered by, it resolves it in a job of its own and hands it to the rest through ",["code",{},"needs"],", rather than accepting it from the caller."],["h2",{"id":"consequences"},"Consequences"],["p",{},"Every calling repo carries the same stub for the same workflow, so two stubs that differ mark a real difference rather than an accident of when they were copied."],["p",{},"A repo changes its behaviour by changing itself. Creating an integration branch moves it to another branch topology and no workflow file changes anywhere — which is the property being bought, and also the surprise: nothing in the stub says the topology is a decision."],["p",{},"A whole class of error stops being possible instead of being fixed in each place it occurred."],["p",{},"The cost is paid at the body: deriving a value takes a job or a step that an input would not have needed, that job''s name becomes part of every caller''s check names, and a body is harder to exercise in isolation because it now depends on the shape of the repo around it. A repo that wants to deviate from what its own state implies cannot do so from the call site at all."],["h2",{"id":"alternatives-considered"},"Alternatives considered"],["p",{},["strong",{},"An input per value."]," Correct, conventional, and the way most reusable workflows are written. It hands each caller a value to keep in step with its own trigger — which is what the copies were doing, expressed in fewer lines."],["p",{},["strong",{},"A configuration file in the calling repo."]," The same objection, one level up, plus a second file to keep in step with the first."],["p",{},["strong",{},"One body per topology."]," This is where the eight variants came from."]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"context","depth":2,"text":"Context"},{"id":"decision","depth":2,"text":"Decision"},{"id":"consequences","depth":2,"text":"Consequences"},{"id":"alternatives-considered","depth":2,"text":"Alternatives considered"}]}}', 'A body reads the values that differ per repo out of the repo it runs in, and accepts an input only for what it cannot know.', 'md', NULL, NULL, '{"status":"accepted","date":"2026-09-01"}', NULL, '/workflows/adr/0001-derive-a-bodys-configuration-from-the-repo', '{"title":"Derive a body''s configuration from the repo","description":"A body reads the values that differ per repo out of the repo it runs in, and accepts an input only for what it cannot know."}', 'workflows/99.adr/0001-derive-a-bodys-configuration-from-the-repo', 'rg-w-4nPVvx2hi5yjLYHNinKpgdxf7m_kJip23oXoVU'); -- rg-w-4nPVvx2hi5yjLYHNinKpgdxf7m_kJip23oXoVU +INSERT INTO _content_docs_workflows VALUES ('docs_workflows/workflows/99.adr/0002-pin-callers-to-a-commit-sha.md', 'Pin callers to a commit SHA', '{"type":"minimark","value":[["h1",{"id":"adr-0002-pin-callers-to-a-commit-sha"},"ADR-0002 — Pin callers to a commit SHA"],["h2",{"id":"context"},"Context"],["p",{},"A caller has to name a ref. A moving major tag is the conventional choice and the one the marketplace actions themselves offer, and this repository can move such a tag: release-please cuts exact tags, and the release workflow can force-push ",["code",{},"v"]," onto each one."],["p",{},"What makes the choice not obvious is what some of these bodies do. The queue workflows read a private key out of the secret vault and mint a GitHub App token whose entire purpose is to bypass a merge gate on an integration branch. On a moving ref, anyone able to push a commit here would be able to change what that token is used for in every repo that calls it, with no review in any of them."],["h2",{"id":"decision"},"Decision"],["p",{},"Caller stubs pin a full commit SHA, with the version as a trailing comment. Bumps arrive as dependency-bot pull requests, and reviewing one of those is the gate."],["p",{},"The moving ",["code",{},"v"]," alias is published for callers who want the other trade, but it is opt-in per repository and off by default."],["h2",{"id":"consequences"},"Consequences"],["p",{},"Write access to this repository is not, by itself, write access to every repository in the estate. A change reaches a caller only when someone merges the bump."],["p",{},"Every repo is therefore behind by however long its bump PR sits, including for a fix, and a security fix reaches the estate at the speed of review rather than at the speed of a push."],["p",{},"The trailing comment is the only thing that tells a human which version a stub is on, and nothing enforces that it stays truthful."],["p",{},"The alias defaults to off because moving a tag is a hazard where something else reads the tag list as a version list — for a published package the registry version is what resolves, and for a Terraform provider an extra unversioned tag is not valid semver at all."],["h2",{"id":"alternatives-considered"},"Alternatives considered"],["p",{},["strong",{},"A moving major tag as the default."]," One less thing for every repo to bump, at the price of the review gate above. It stays available to any repo that opts in."],["p",{},["strong",{},"A branch as the ref."]," The same exposure with no version information at all."]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"context","depth":2,"text":"Context"},{"id":"decision","depth":2,"text":"Decision"},{"id":"consequences","depth":2,"text":"Consequences"},{"id":"alternatives-considered","depth":2,"text":"Alternatives considered"}]}}', 'Caller stubs reference a body by commit SHA with the version as a trailing comment; the moving major alias is published but opt-in and off by default.', 'md', NULL, NULL, '{"status":"accepted","date":"2026-09-01"}', NULL, '/workflows/adr/0002-pin-callers-to-a-commit-sha', '{"title":"Pin callers to a commit SHA","description":"Caller stubs reference a body by commit SHA with the version as a trailing comment; the moving major alias is published but opt-in and off by default."}', 'workflows/99.adr/0002-pin-callers-to-a-commit-sha', 'qoX_2T8G_xQCIozdItIRh-lOYWy1g5DqDrQNxvWJ02c'); -- qoX_2T8G_xQCIozdItIRh-lOYWy1g5DqDrQNxvWJ02c +INSERT INTO _content_docs_workflows VALUES ('docs_workflows/workflows/99.adr/0003-name-every-secret-a-stub-passes.md', 'Name every secret a stub passes', '{"type":"minimark","value":[["h1",{"id":"adr-0003-name-every-secret-a-stub-passes"},"ADR-0003 — Name every secret a stub passes"],["h2",{"id":"context"},"Context"],["p",{},"A caller can hand a reusable workflow everything it holds in one word. That word is shorter than a block naming each secret, and it never needs touching again when a body grows a new requirement."],["p",{},"It also decides, once, that every secret the repository acquires from then on is visible to every body it calls — including secrets added long after anyone last read the stub, and including bodies added to the call after that."],["h2",{"id":"decision"},"Decision"],["p",{},"A stub passes exactly the secrets its body declares, one key at a time. ",["code",{},"secrets: inherit"]," is not used."],["h2",{"id":"consequences"},"Consequences"],["p",{},"What a body can reach is stated in the file that grants it, so the answer to what a workflow can read is the stub itself rather than the repository''s whole secret list."],["p",{},"A body that starts needing another secret cannot get it silently: every caller has to be edited, which is a visible change and a reviewed one."],["p",{},"That is also the cost — such a change is a pull request per calling repo, and until each lands the body fails there rather than degrading."],["h2",{"id":"alternatives-considered"},"Alternatives considered"],["p",{},["strong",{},["code",{},"secrets: inherit"],"."]," One line per stub instead of two or three, and no edit when a body''s needs change. Rejected for exactly the second property."]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"context","depth":2,"text":"Context"},{"id":"decision","depth":2,"text":"Decision"},{"id":"consequences","depth":2,"text":"Consequences"},{"id":"alternatives-considered","depth":2,"text":"Alternatives considered"}]}}', 'A caller passes each secret a body needs explicitly; secrets: inherit is not used.', 'md', NULL, NULL, '{"status":"accepted","date":"2026-09-01"}', NULL, '/workflows/adr/0003-name-every-secret-a-stub-passes', '{"title":"Name every secret a stub passes","description":"A caller passes each secret a body needs explicitly; secrets: inherit is not used."}', 'workflows/99.adr/0003-name-every-secret-a-stub-passes', 'WJlw227fLg_N6t37AIl5DN3V4hSomZkRaH6un4rd4io'); -- WJlw227fLg_N6t37AIl5DN3V4hSomZkRaH6un4rd4io +INSERT INTO _content_docs_workflows VALUES ('docs_workflows/workflows/99.adr/0004-compose-ci-from-bodies-that-are-jobs.md', 'Compose CI from bodies that are jobs', '{"type":"minimark","value":[["h1",{"id":"adr-0004-compose-ci-from-bodies-that-are-jobs"},"ADR-0004 — Compose CI from bodies that are jobs"],["h2",{"id":"context"},"Context"],["p",{},"CI was the workflow that had drifted furthest: measured across the estate, nearly every repo''s copy was unique. Behind that were a handful of families — repos running a single gate, libraries running a typecheck-test-build set, packages running a version matrix against a database, providers running a language toolchain — and a few repos with pipelines that genuinely belong to them, carrying deploy stages and their own short-circuits."],["p",{},"Unlike the queue workflows, the differences here are not values a body can look up. Whether a repo needs a database, which toolchain it installs and what \"tested\" means for it are properties of its stack, not of its state."],["h2",{"id":"decision"},"Decision"],["p",{},"A CI body is a ",["strong",{},"job"]," that a caller composes into a pipeline it still owns, and there is one body per family rather than one body for CI."],["p",{},"Inputs on such a body say what the body cannot know — which versions a matrix spans, which paths a filter watches. They never say which parts of the body to skip."],["h2",{"id":"consequences"},"Consequences"],["p",{},"A repo keeps its own pipeline and its own graph: it decides what runs, in which order, and what a short-circuit is allowed to stand for. The bodies it calls do not need to know about each other."],["p",{},"Repos with pipelines of their own are not special cases to be worked around — they compose from the same pieces as everyone else, which is why the pieces were cut at job boundaries in the first place."],["p",{},"Adding a family means adding a body. Writing one before a second caller exists is a cost taken deliberately, and only where a named repo would otherwise start by copying the first one."],["p",{},"A caller''s pipeline is longer than a single ",["code",{},"uses:"]," line, and the composition itself — which job needs which, what gates on what — is the one thing that can still drift between repos."],["h2",{"id":"alternatives-considered"},"Alternatives considered"],["p",{},["strong",{},"One CI body with feature switches"]," — flags for running tests, for needing a database, for a coverage step. It works. It also turns every stub into a configuration file of a dozen keys, which is the drift this repository removes, reappearing one level up. It would still have left the repos with their own pipelines as special cases, and those carry the most logic."],["p",{},["strong",{},"One body per repo."]," The starting point, and what was being replaced."]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"context","depth":2,"text":"Context"},{"id":"decision","depth":2,"text":"Decision"},{"id":"consequences","depth":2,"text":"Consequences"},{"id":"alternatives-considered","depth":2,"text":"Alternatives considered"}]}}', 'A CI body is a job the caller composes into its own pipeline, never one body with switches for the parts a repo does not run.', 'md', NULL, NULL, '{"status":"accepted","date":"2026-09-01"}', NULL, '/workflows/adr/0004-compose-ci-from-bodies-that-are-jobs', '{"title":"Compose CI from bodies that are jobs","description":"A CI body is a job the caller composes into its own pipeline, never one body with switches for the parts a repo does not run."}', 'workflows/99.adr/0004-compose-ci-from-bodies-that-are-jobs', 'BYTUKGhoE40NFWDLcgZFJKEnazE5uV65NLhbKpz95mc'); -- BYTUKGhoE40NFWDLcgZFJKEnazE5uV65NLhbKpz95mc +INSERT INTO _content_docs_workflows VALUES ('docs_workflows/workflows/99.adr/0005-publish-with-one-body-per-target.md', 'Publish with one body per target', '{"type":"minimark","value":[["h1",{"id":"adr-0005-publish-with-one-body-per-target"},"ADR-0005 — Publish with one body per target"],["h2",{"id":"context"},"Context"],["p",{},"The release workflow and the publish step arrived as one file in every repo that had them. Most repos that cut releases publish nothing at all — they exist to be depended on by their own tags, or they deploy instead. The ones that do publish split by target, and the targets need different credentials: a registry token for one, a signing key out of the vault for another."],["p",{},"A single body serving all of them would have to make every credential optional, which erases the signal of which one a repo actually needs, and would ask the repos that publish nothing to carry inputs they have no use for."],["h2",{"id":"decision"},"Decision"],["p",{},"Releasing is one body. Publishing is a separate body per target, and the caller composes the one it needs, gated on whether a release was actually created."],["h2",{"id":"consequences"},"Consequences"],["p",{},"A repo that publishes nothing calls one body and passes one secret. A repo that publishes states which target it publishes to by which body it calls — the stub says what the repo is."],["p",{},"Adding a target means adding a body, not adding a branch to an existing one, and the repos that do not use it are unaffected by its existence."],["p",{},"The caller now writes the wiring between the two jobs, so the gate on \"a release was created\" is stated once per repo rather than once in a body. That wiring is duplicated across the repos publishing to the same target, and it is the piece that could drift."],["p",{},"Repos that deploy rather than publish keep their own jobs. Those touch environments rather than artifacts, and centralising them was never in question."],["h2",{"id":"alternatives-considered"},"Alternatives considered"],["p",{},["strong",{},"One body with a ",["code",{},"target"]," input."]," Every secret optional, every publishing repo passing a flag, and the repos that publish nothing carrying the surface anyway."],["p",{},["strong",{},"Publishing folded into the release body."]," The same problem with fewer files, and it would have made the release body untouchable for the majority of callers that only want a tag."]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"context","depth":2,"text":"Context"},{"id":"decision","depth":2,"text":"Decision"},{"id":"consequences","depth":2,"text":"Consequences"},{"id":"alternatives-considered","depth":2,"text":"Alternatives considered"}]}}', 'Releasing and publishing are separate bodies, and a caller composes the publish body its target needs.', 'md', NULL, NULL, '{"status":"accepted","date":"2026-09-01"}', NULL, '/workflows/adr/0005-publish-with-one-body-per-target', '{"title":"Publish with one body per target","description":"Releasing and publishing are separate bodies, and a caller composes the publish body its target needs."}', 'workflows/99.adr/0005-publish-with-one-body-per-target', 'kXluGJNfjk4_8zgc0mGXxcYna3Lk_Hje5NdZnNMcgRQ'); -- kXluGJNfjk4_8zgc0mGXxcYna3Lk_Hje5NdZnNMcgRQ +INSERT INTO _content_docs_workflows VALUES ('docs_workflows/workflows/99.adr/0006-keep-the-composite-action-out-of-the-bodies.md', 'Keep the composite action out of the bodies', '{"type":"minimark","value":[["h1",{"id":"adr-0006-keep-the-composite-action-out-of-the-bodies"},"ADR-0006 — Keep the composite action out of the bodies"],["h2",{"id":"context"},"Context"],["p",{},"A reusable workflow is taken whole. A caller cannot replace one of its steps or insert another, so a repo needing \"that body plus one thing\" has to write its own job — which is why the setup those bodies open with also exists as a composite action it can call."],["p",{},"Using that same action inside the bodies looks like the obvious next step, and it is a trap. A relative ",["code",{},"uses:"]," inside a reusable workflow resolves against the ",["strong",{},"caller''s"]," workspace, not against the repository the body lives in, so a body cannot say ",["code",{},"./"],". It would have to name this repository and a ref in full — and ",["code",{},"uses:"]," accepts no expression, so that ref could not be the one the caller pinned. It would be a literal, fixed at the time the body was written."],["p",{},"A caller pinning a body to one commit would then run a body from that commit and a setup action from a different one, with nothing anywhere saying so."],["h2",{"id":"decision"},"Decision"],["p",{},"The bodies do not call the composite action. They repeat the few setup steps inline. The action exists for callers writing their own jobs."],["h2",{"id":"consequences"},"Consequences"],["p",{},"A pinned SHA means what it appears to mean: everything the run executes out of this repository comes from that commit."],["p",{},"The setup steps exist in both places, so a change to how the toolchain is set up has to be made in the bodies and in the action, and nothing checks that the two agree."],["p",{},"A repo that needs a body plus one step writes its own job around the action instead of forking the body, which keeps the fork pressure off the bodies."],["h2",{"id":"alternatives-considered"},"Alternatives considered"],["p",{},["strong",{},"Calling the action with a hardcoded ref."]," Removes the duplication and introduces a pin that lies. The duplication is a handful of lines; the pin would be a silent inconsistency at every caller."],["p",{},["strong",{},"Making the setup its own reusable workflow."]," A workflow cannot be a step inside a job, so this does not address the case at all."]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"context","depth":2,"text":"Context"},{"id":"decision","depth":2,"text":"Decision"},{"id":"consequences","depth":2,"text":"Consequences"},{"id":"alternatives-considered","depth":2,"text":"Alternatives considered"}]}}', 'The shared setup exists as a composite action for callers, but the bodies duplicate the steps rather than calling it.', 'md', NULL, NULL, '{"status":"accepted","date":"2026-09-01"}', NULL, '/workflows/adr/0006-keep-the-composite-action-out-of-the-bodies', '{"title":"Keep the composite action out of the bodies","description":"The shared setup exists as a composite action for callers, but the bodies duplicate the steps rather than calling it."}', 'workflows/99.adr/0006-keep-the-composite-action-out-of-the-bodies', '1wycsSf9VqQKwvR-GpXpFjvjDpWmOmXWuVOIC9Vkv9o'); -- 1wycsSf9VqQKwvR-GpXpFjvjDpWmOmXWuVOIC9Vkv9o +INSERT INTO _content_docs_workflows VALUES ('docs_workflows/workflows/99.adr/0007-run-the-gate-as-one-job-with-a-step-per-check.md', 'Run the gate as one job with a step per check', '{"type":"minimark","value":[["h1",{"id":"adr-0007-run-the-gate-as-one-job-with-a-step-per-check"},"ADR-0007 — Run the gate as one job with a step per check"],["h2",{"id":"context"},"Context"],["p",{},"For the repos whose CI is a set of independent checks, the copied workflows listed those checks a second time as steps — the same commands the package manifest''s gate script already chained, kept in step by hand."],["p",{},"Deriving the list from the gate script removes that second copy, and it also decides nothing about how the tasks then run. Two shapes were available: fan them out over a matrix so each reports as its own job, or run them as steps of one job."],["p",{},"The tasks in question are short. A run for these repos is dominated by checkout and dependency install, not by the checks themselves."],["h2",{"id":"decision"},"Decision"],["p",{},"The gate body splits the repo''s gate script into its task calls, expanding a task that chains another aggregate, and runs the result as ",["strong",{},"steps of a single job"],". Each task gets its own log group and its own error line, so a failed run names the check that failed."],["h2",{"id":"consequences"},"Consequences"],["p",{},"The check list follows the repo. A repo adds a check by editing its gate script, and CI picks it up with no workflow change — which is what carries the checks that exist in only one repo, without any of them being named here."],["p",{},"A run costs one checkout and one install rather than one per task."],["p",{},"What is given up is granularity at the job level: the whole gate is one check name, so a single aspect of it cannot be required on its own, and the tasks do not run in parallel. The first task to fail ends the job, so a run reports one failure rather than all of them."],["p",{},"A task that takes arguments is left unexpanded, because running it on its own would not be the same command."],["h2",{"id":"alternatives-considered"},"Alternatives considered"],["p",{},["strong",{},"A matrix, one job per task."]," It gives each check its own name and lets any one of them be required alone. Jobs share nothing — separate runner, separate filesystem, separate dependency tree — so n tasks cost n checkouts and n installs. For a gate of short tasks that makes the run slower while occupying several runners instead of one. The trade reverses where a single task runs for minutes, which is why the bodies for the heavier stacks do use a matrix."],["p",{},["strong",{},"Running the gate script as one command."]," One step, no derivation, and a red build that does not say which check failed."]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"context","depth":2,"text":"Context"},{"id":"decision","depth":2,"text":"Decision"},{"id":"consequences","depth":2,"text":"Consequences"},{"id":"alternatives-considered","depth":2,"text":"Alternatives considered"}]}}', 'The gate body derives its task list from the repo package manifest and runs the tasks as steps of a single job rather than fanning them over a matrix.', 'md', NULL, NULL, '{"status":"accepted","date":"2026-09-01"}', NULL, '/workflows/adr/0007-run-the-gate-as-one-job-with-a-step-per-check', '{"title":"Run the gate as one job with a step per check","description":"The gate body derives its task list from the repo package manifest and runs the tasks as steps of a single job rather than fanning them over a matrix."}', 'workflows/99.adr/0007-run-the-gate-as-one-job-with-a-step-per-check', 'XM4JBXHiGAFpE0wgeL8fOfeI5QrfuA_vEMTemyaY_u0'); -- XM4JBXHiGAFpE0wgeL8fOfeI5QrfuA_vEMTemyaY_u0 +INSERT INTO _content_docs_workflows VALUES ('docs_workflows/workflows/99.adr/0008-give-each-reporter-its-own-comment-thread.md', 'Give each reporter its own comment thread', '{"type":"minimark","value":[["h1",{"id":"adr-0008-give-each-reporter-its-own-comment-thread"},"ADR-0008 — Give each reporter its own comment thread"],["h2",{"id":"context"},"Context"],["p",{},"Two of the bodies write results back to a pull request: coverage, and the performance audit. The repository they were derived from had collected both into a single comment, and said why — a second reporting job beside it would open a second thread, and a pull request carrying a thread per metric is one nobody reads."],["p",{},"That reasoning holds for a pipeline written in one file. It does not survive being split into bodies that repos compose independently. A repo calling the coverage body alongside the combined job would get the second thread anyway, because the two know nothing about each other; and coupling them so they do not would mean one body reading another''s output, which is the shape the split was meant to avoid. Either the reporters share a marker and are no longer independent, or they are independent and there is more than one thread."],["h2",{"id":"decision"},"Decision"],["p",{},"Each reporting body owns its own sticky marker and posts under it alone. Coverage keeps the marker its action already writes; the audit posts under its own. Neither body knows the other exists."],["h2",{"id":"consequences"},"Consequences"],["p",{},"A pull request in a repo that runs both carries two comment threads instead of one. That is the cost, and it is paid on every such pull request."],["p",{},"What it buys is that either body can be adopted without the other, dropped without touching the other, and changed without a second body''s output shifting. It also removes the last reason the combined job could not be replaced: it was blocked by this coupling rather than by a missing second caller."],["p",{},"The markers now have to stay distinct by convention, since nothing enforces it — a body colliding with another''s marker would silently overwrite its report."],["h2",{"id":"alternatives-considered"},"Alternatives considered"],["p",{},["strong",{},"One shared marker, written by whichever body runs last."]," Keeps a single thread, and makes the last writer responsible for content it did not produce — a body would have to read another''s artifact to avoid erasing it. The coupling that was being removed, reintroduced at the comment level."],["p",{},["strong",{},"One reporting body aggregating the others."]," A single thread again, at the price of a body that must know every reporter that exists, and must be extended before any new one can report anything."]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"context","depth":2,"text":"Context"},{"id":"decision","depth":2,"text":"Decision"},{"id":"consequences","depth":2,"text":"Consequences"},{"id":"alternatives-considered","depth":2,"text":"Alternatives considered"}]}}', 'A body that reports to a pull request owns its own sticky marker, rather than several reporters sharing one comment.', 'md', NULL, NULL, '{"status":"accepted","date":"2026-09-01"}', NULL, '/workflows/adr/0008-give-each-reporter-its-own-comment-thread', '{"title":"Give each reporter its own comment thread","description":"A body that reports to a pull request owns its own sticky marker, rather than several reporters sharing one comment."}', 'workflows/99.adr/0008-give-each-reporter-its-own-comment-thread', 'ziw535s2BtFPR8nyG8cB_M6x6x8OFR3Y5zIfaZdgaz8'); -- ziw535s2BtFPR8nyG8cB_M6x6x8OFR3Y5zIfaZdgaz8 +INSERT INTO _content_docs_workflows VALUES ('docs_workflows/workflows/99.adr/0009-write-a-body-before-its-second-caller.md', 'Write a body before its second caller', '{"type":"minimark","value":[["h1",{"id":"adr-0009-write-a-body-before-its-second-caller"},"ADR-0009 — Write a body before its second caller"],["h2",{"id":"context"},"Context"],["p",{},"The case for centralising a workflow is that several repos carry the same one. Where only a single repo has it, that case is absent: a body written for one caller generalises a shape nobody has met twice, and the input it takes may be the wrong seam."],["p",{},"Refusing every such body has its own cost, and it falls on a repo that does not exist yet. The next repo of a given kind starts from the only version available — a copy, taken whole, from whichever repo happened to have one. A long pipeline copied once is a second variant from its first commit, and the estate''s own history is the argument: every workflow being centralised here reached its variant count exactly that way."],["p",{},"Both failure modes are real, so the question is which repo pays: a body generalised too early, or a copy made too late."],["h2",{"id":"decision"},"Decision"],["p",{},"A body may be written for a single caller when a ",["strong",{},"named"]," repo is known to need it next — one that exists, or one a template is expected to produce. The reasoning goes in the body''s own header, naming that repo, so a later reader can tell a considered exception from an oversight."],["p",{},"Where no such repo can be named, one instance is not a pattern and no body is written."],["h2",{"id":"consequences"},"Consequences"],["p",{},"A body written this way has had its interface guessed once rather than observed twice. The second caller is likely to need an input that is not there, and adding it is cheap; discovering that the seam itself is wrong is not."],["p",{},"Migrating the first caller onto such a body may rename its checks, which is a branch-protection change in that repo. Accepted deliberately: it happens once, and it happens anyway during the migration."],["p",{},"The rule can be argued into anything, since any repo might one day need any workflow. The requirement that the next caller be ",["em",{},"named"]," is what keeps it a decision rather than a preference — an unnamed one is a hunch, and a hunch does not clear the bar."],["h2",{"id":"alternatives-considered"},"Alternatives considered"],["p",{},["strong",{},"Wait for the second caller, always."]," The rule as it would read without this record. It is right in the common case and wrong exactly where the second caller is a large repo whose copy would be made before anyone noticed."],["p",{},["strong",{},"Write every body speculatively."]," Removes the judgement, and fills the repository with interfaces shaped by a single example, each of which has to be broken when a real second caller arrives."]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"context","depth":2,"text":"Context"},{"id":"decision","depth":2,"text":"Decision"},{"id":"consequences","depth":2,"text":"Consequences"},{"id":"alternatives-considered","depth":2,"text":"Alternatives considered"}]}}', 'A body may be written for a single caller when a specific repo is known to need it next, and the reasoning is recorded with the body.', 'md', NULL, NULL, '{"status":"accepted","date":"2026-09-01"}', NULL, '/workflows/adr/0009-write-a-body-before-its-second-caller', '{"title":"Write a body before its second caller","description":"A body may be written for a single caller when a specific repo is known to need it next, and the reasoning is recorded with the body."}', 'workflows/99.adr/0009-write-a-body-before-its-second-caller', 'S8vRgfxmlypC7P2UONNLFtNvQ_FRMk60zQZlKLU5Qwc'); -- S8vRgfxmlypC7P2UONNLFtNvQ_FRMk60zQZlKLU5Qwc +INSERT INTO _content_docs_workflows VALUES ('docs_workflows/workflows/99.adr/index.md', 'Architecture decisions', '{"type":"minimark","value":[["h1",{"id":"architecture-decisions"},"Architecture decisions"],["p",{},"A decision earns an ADR when it constrains work that comes later and its reasoning would otherwise be lost: a choice between real alternatives, a convention every part of the project has to follow, a trade-off that looks like a mistake until the reason is known. Records are append-only — a reversed decision is written as a new ADR that supersedes the old one, never as an edit to it."],["p",{},"This log holds decisions about ",["strong",{},"this repository"],": what a body may assume, what a caller must state, and where the boundary between the two runs. Decisions about the estate''s provisioned state — branch protection, the queue App, the secret mirror — belong to ",["code",{},"kirchDev/infrastructure"]," and are recorded there; the bodies here implement them and cite them by id."],["table",{},["thead",{},["tr",{},["th",{"align":"left"},"ADR"],["th",{"align":"left"},"Decision"],["th",{"align":"left"},"Status"],["th",{"align":"left"},"Date"]]],["tbody",{},["tr",{},["td",{"align":"left"},["a",{"href":"0001-derive-a-bodys-configuration-from-the-repo"},"ADR-0001"]],["td",{"align":"left"},"Derive a body''s configuration from the repo"],["td",{"align":"left"},"Accepted"],["td",{"align":"left"},"2026-09-01"]],["tr",{},["td",{"align":"left"},["a",{"href":"0002-pin-callers-to-a-commit-sha"},"ADR-0002"]],["td",{"align":"left"},"Pin callers to a commit SHA"],["td",{"align":"left"},"Accepted"],["td",{"align":"left"},"2026-09-01"]],["tr",{},["td",{"align":"left"},["a",{"href":"0003-name-every-secret-a-stub-passes"},"ADR-0003"]],["td",{"align":"left"},"Name every secret a stub passes"],["td",{"align":"left"},"Accepted"],["td",{"align":"left"},"2026-09-01"]],["tr",{},["td",{"align":"left"},["a",{"href":"0004-compose-ci-from-bodies-that-are-jobs"},"ADR-0004"]],["td",{"align":"left"},"Compose CI from bodies that are jobs"],["td",{"align":"left"},"Accepted"],["td",{"align":"left"},"2026-09-01"]],["tr",{},["td",{"align":"left"},["a",{"href":"0005-publish-with-one-body-per-target"},"ADR-0005"]],["td",{"align":"left"},"Publish with one body per target"],["td",{"align":"left"},"Accepted"],["td",{"align":"left"},"2026-09-01"]],["tr",{},["td",{"align":"left"},["a",{"href":"0006-keep-the-composite-action-out-of-the-bodies"},"ADR-0006"]],["td",{"align":"left"},"Keep the composite action out of the bodies"],["td",{"align":"left"},"Accepted"],["td",{"align":"left"},"2026-09-01"]],["tr",{},["td",{"align":"left"},["a",{"href":"0007-run-the-gate-as-one-job-with-a-step-per-check"},"ADR-0007"]],["td",{"align":"left"},"Run the gate as one job with a step per check"],["td",{"align":"left"},"Accepted"],["td",{"align":"left"},"2026-09-01"]],["tr",{},["td",{"align":"left"},["a",{"href":"0008-give-each-reporter-its-own-comment-thread"},"ADR-0008"]],["td",{"align":"left"},"Give each reporter its own comment thread"],["td",{"align":"left"},"Accepted"],["td",{"align":"left"},"2026-09-01"]],["tr",{},["td",{"align":"left"},["a",{"href":"0009-write-a-body-before-its-second-caller"},"ADR-0009"]],["td",{"align":"left"},"Write a body before its second caller"],["td",{"align":"left"},"Accepted"],["td",{"align":"left"},"2026-09-01"]]]]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}}', 'The decision log — every architecture decision recorded for this repository.', 'md', NULL, NULL, '{}', NULL, '/workflows/adr', '{"title":"Architecture decisions","description":"The decision log — every architecture decision recorded for this repository."}', 'workflows/99.adr/index', '9DjjHnYdLrzkurso8t8tRJQUyC5-9nN5WvDMKNPm41Y'); -- 9DjjHnYdLrzkurso8t8tRJQUyC5-9nN5WvDMKNPm41Y +INSERT INTO _content_docs_workflows VALUES ('docs_workflows/workflows/index.md', 'workflows documentation', '{"type":"minimark","value":[["h1",{"id":"workflows"},"workflows"],["p",{},"This repository holds the estate''s reusable GitHub Actions workflow bodies. Every other repo carries a thin caller stub instead of its own copy, so a fix lands once and reaches each repo on its next bump."],["p",{},"These pages cover the two tasks the repository asks of a person — moving a repo onto a body, and writing a new one — and the decision log behind them."],["h2",{"id":"sections"},"Sections"],["ul",{},["li",{},["a",{"href":"1.guides/"},"Guides"]," — migrating a repo onto a stub, and adding a body."],["li",{},["a",{"href":"99.adr/"},"Architecture decisions"]," — the decision log."]],["p",{},"What the bodies do, how a stub looks and what each one needs is in the ",["a",{"href":"../README"},"README"],"; how to set the repo up and get a PR landed is in ",["a",{"href":"../CONTRIBUTING"},"CONTRIBUTING.md"],". Decisions about the estate''s provisioned state — branch protection, the queue App, the Bitwarden mirror — are recorded in ",["code",{},"kirchDev/infrastructure"],", not here."]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"sections","depth":2,"text":"Sections"}]}}', 'How a repo moves onto the central reusable workflow bodies, how a new body is written, and the decisions that govern both.', 'md', NULL, NULL, '{}', NULL, '/workflows', '{"title":"workflows documentation","description":"How a repo moves onto the central reusable workflow bodies, how a new body is written, and the decisions that govern both."}', 'workflows/index', '2F4Y87gP8kLQW0fz5eaLeL9APZztdqv_1Nf6kU7CTw0'); -- 2F4Y87gP8kLQW0fz5eaLeL9APZztdqv_1Nf6kU7CTw0 +UPDATE _content_info SET ready = true WHERE id = 'checksum_docs_workflows'; -- meta +CREATE TABLE IF NOT EXISTS _content_info (id TEXT PRIMARY KEY, "ready" BOOLEAN, "structureVersion" VARCHAR, "version" VARCHAR, "__hash__" TEXT UNIQUE); -- structure +INSERT INTO _content_info VALUES ('checksum_docs_workflows_v0_7_0', false, 'Pt9fhgX_otrmnFQYPHSGuqExdlY7qwABOOtjCErIPtg', 'v3.5.0--gyTLYQ0MVuqj_MoAN7sY-gvt61s3lKmNU2w7azTxNdA', 'HE4XlPSr6RzKJBntIQPxUilkCRn3S1y54KPuERG9cxY'); -- meta +DROP TABLE IF EXISTS _content_docs_workflows_v0_7_0; -- structure +CREATE TABLE IF NOT EXISTS _content_docs_workflows_v0_7_0 (id TEXT PRIMARY KEY, "title" VARCHAR, "body" TEXT, "description" VARCHAR, "extension" VARCHAR, "icon" VARCHAR NULL, "layout" VARCHAR NULL, "meta" TEXT, "navigation" BOOLEAN NULL, "path" VARCHAR, "seo" TEXT DEFAULT '{}', "stem" VARCHAR, "__hash__" TEXT UNIQUE); -- structure +INSERT INTO _content_docs_workflows_v0_7_0 VALUES ('docs_workflows_v0_7_0/workflows/v0.7.0/1.guides/1.migrate-a-repo-to-a-stub.md', 'Migrate a repo to a stub', '{"type":"minimark","value":[["h1",{"id":"migrate-a-repo-to-a-stub"},"Migrate a repo to a stub"],["p",{},"One repo, one workflow at a time. The file shrinks to a trigger and a ",["code",{},"uses:"],", and the checks the repo reports change name in the same run — which is the part that breaks something if it is left for later."],["h2",{"id":"steps"},"Steps"],["ol",{},["li",{},["strong",{},"Replace the body with a stub."]," Keep the trigger, delete everything under ",["code",{},"jobs:"]," except the call. A caller job may only carry ",["code",{},"name"],", ",["code",{},"uses"],", ",["code",{},"with"],", ",["code",{},"secrets"],", ",["code",{},"needs"],", ",["code",{},"if"],", ",["code",{},"strategy"],", ",["code",{},"concurrency"]," and ",["code",{},"permissions"]," — ",["code",{},"runs-on"]," is not allowed there and belongs to the body.",["pre",{"className":"language-yaml shiki shiki-themes github-light github-dark","code":"# .github/workflows/promotion-pr.yml, complete\nname: Promotion PR\non:\n push:\n branches: [dev, stage]\njobs:\n promotion-pr:\n name: Promotion PR\n uses: kirchDev/workflows/.github/workflows/_promotion-pr.yml@ # v0.1.0\n","language":"yaml","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# .github/workflows/promotion-pr.yml, complete\n"]],["span",{"class":"line","line":2},["span",{"class":"s9eBZ"},"name"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"Promotion PR\n"]],["span",{"class":"line","line":3},["span",{"class":"sj4cs"},"on"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":4},["span",{"class":"s9eBZ"}," push"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":5},["span",{"class":"s9eBZ"}," branches"],["span",{"class":"sVt8B"},": ["],["span",{"class":"sZZnC"},"dev"],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"stage"],["span",{"class":"sVt8B"},"]\n"]],["span",{"class":"line","line":6},["span",{"class":"s9eBZ"},"jobs"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":7},["span",{"class":"s9eBZ"}," promotion-pr"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":8},["span",{"class":"s9eBZ"}," name"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"Promotion PR\n"]],["span",{"class":"line","line":9},["span",{"class":"s9eBZ"}," uses"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"kirchDev/workflows/.github/workflows/_promotion-pr.yml@"],["span",{"class":"sJ8bj"}," # v0.1.0\n"]]]],["br",{}],"List ",["code",{},"stage"]," even where no ",["code",{},"stage"]," branch exists: a filter naming a branch that is absent is a no-op, and it keeps the stub identical in every repo."],["li",{},["strong",{},"Pin the SHA, and put the version in a trailing comment."]," The tag is what a human reads; the SHA is what runs. Dependabot raises the bumps from there."],["li",{},["strong",{},"Pass the secrets the body needs, by name."]," Never ",["code",{},"secrets: inherit"],".",["table",{},["thead",{},["tr",{},["th",{"align":"left"},"Body"],["th",{"align":"left"},"Secret"]]],["tbody",{},["tr",{},["td",{"align":"left"},["code",{},"_queue-branch.yml"],", ",["code",{},"_fast-forward-queue.yml"],", ",["code",{},"_release-please.yml"],", ",["code",{},"_publish-goreleaser.yml"]],["td",{"align":"left"},["code",{},"BWS_ACCESS_TOKEN"]]],["tr",{},["td",{"align":"left"},["code",{},"_publish-npm.yml"]],["td",{"align":"left"},["code",{},"NPM_TOKEN"]]]]],["br",{}],"The remaining bodies take no secrets."],["li",{},["strong",{},"Move the branch-protection rule to the new check names."]," A called job reports as ",["code",{}," / "],", so every required check the repo declares changes string. A rule left on the old name waits for a check that will never arrive, and the PR never becomes mergeable.",["br",{}],"Read the body''s job names out of the body itself and the caller name out of the stub you just wrote. Two that catch people out:",["ul",{},["li",{},["code",{},"_fast-forward-queue.yml"]," reports ",["strong",{},"four"]," jobs where the old copies reported three — ",["code",{},"Resolve the integration branch"]," is where the ",["code",{},"INTEGRATION_BRANCH"]," literal went."],["li",{},["code",{},"_ci-lighthouse.yml"]," reports one job per shard plus a merge job, where a hand-written audit reported one."]]],["li",{},["strong",{},"Take the fix that comes with the body."]," Some repos are behind rather than different, and the migration is what carries the correction. Check ",["code",{},"CLAUDE.md"]," in this repository for the measured list before opening the PR — a repo on the short queue workflow gains the App-token path it never had, and an npm repo without the prerelease-version fix stops publishing a ",["code",{},"dev"]," version that semver ranks below its own latest release."],["li",{},["strong",{},"Delete the old file''s body, not the file."]," The stub keeps the filename every other repo uses, which is what makes the estate greppable."]],["h2",{"id":"three-triggers-worth-fixing-while-you-are-here"},"Three triggers worth fixing while you are here"],["p",{},"A migration is the moment the trigger block gets read anyway. Three things in the copied ones cost runner time for nothing, and each is a line:"],["p",{},["strong",{},"Scan on the release branch only."]," A push to an integration branch always has a pull request open on it, and that PR run examines the same tree — so ",["code",{},"push: branches: [main, dev]"]," runs the analysis twice for one result. Drop ",["code",{},"dev"],":"],["pre",{"className":"language-yaml shiki shiki-themes github-light github-dark","code":"on:\n push:\n branches: [main]\n pull_request:\n branches: [main, dev]\n","language":"yaml","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sj4cs"},"on"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":2},["span",{"class":"s9eBZ"}," push"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":3},["span",{"class":"s9eBZ"}," branches"],["span",{"class":"sVt8B"},": ["],["span",{"class":"sZZnC"},"main"],["span",{"class":"sVt8B"},"]\n"]],["span",{"class":"line","line":4},["span",{"class":"s9eBZ"}," pull_request"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":5},["span",{"class":"s9eBZ"}," branches"],["span",{"class":"sVt8B"},": ["],["span",{"class":"sZZnC"},"main"],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"dev"],["span",{"class":"sVt8B"},"]\n"]]]],["p",{},["strong",{},"Skip what prose cannot break."]," A change touching only Markdown cannot fail a lint or a typecheck:"],["pre",{"className":"language-yaml shiki shiki-themes github-light github-dark","code":"paths-ignore:\n - ''**.md''\n - ''docs/**''\n","language":"yaml","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"s9eBZ"},"paths-ignore"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"}," - "],["span",{"class":"sZZnC"},"''**.md''\n"]],["span",{"class":"line","line":3},["span",{"class":"sVt8B"}," - "],["span",{"class":"sZZnC"},"''docs/**''\n"]]]],["p",{},"Never exclude ",["code",{},".github/workflows/**"]," from a CodeQL trigger — the ",["code",{},"actions"]," language is what scans them."],["p",{},["strong",{},"Gate the expensive jobs on the tree marker."]," Where a repo runs a suite worth minutes, put ",["code",{},"_verified.yml"]," in front of it and record the result at the end. A tree that already passed is then skipped whichever trigger brings it back:"],["pre",{"className":"language-yaml shiki shiki-themes github-light github-dark","code":"jobs:\n verified:\n uses: kirchDev/workflows/.github/workflows/_verified.yml@\n\n test:\n needs: verified\n if: needs.verified.outputs.skip != ''true''\n uses: kirchDev/workflows/.github/workflows/_ci-node.yml@\n\n record-verified:\n needs: [verified, test]\n if: needs.test.result == ''success''\n uses: kirchDev/workflows/.github/workflows/_record-verified.yml@\n with:\n tree: ${{ needs.verified.outputs.tree }}\n","language":"yaml","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"s9eBZ"},"jobs"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":2},["span",{"class":"s9eBZ"}," verified"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":3},["span",{"class":"s9eBZ"}," uses"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"kirchDev/workflows/.github/workflows/_verified.yml@\n"]],["span",{"class":"line","line":4},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":5},["span",{"class":"s9eBZ"}," test"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":6},["span",{"class":"s9eBZ"}," needs"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"verified\n"]],["span",{"class":"line","line":7},["span",{"class":"s9eBZ"}," if"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"needs.verified.outputs.skip != ''true''\n"]],["span",{"class":"line","line":8},["span",{"class":"s9eBZ"}," uses"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"kirchDev/workflows/.github/workflows/_ci-node.yml@\n"]],["span",{"class":"line","line":9},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":10},["span",{"class":"s9eBZ"}," record-verified"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":11},["span",{"class":"s9eBZ"}," needs"],["span",{"class":"sVt8B"},": ["],["span",{"class":"sZZnC"},"verified"],["span",{"class":"sVt8B"},", "],["span",{"class":"sZZnC"},"test"],["span",{"class":"sVt8B"},"]\n"]],["span",{"class":"line","line":12},["span",{"class":"s9eBZ"}," if"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"needs.test.result == ''success''\n"]],["span",{"class":"line","line":13},["span",{"class":"s9eBZ"}," uses"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"kirchDev/workflows/.github/workflows/_record-verified.yml@\n"]],["span",{"class":"line","line":14},["span",{"class":"s9eBZ"}," with"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":15},["span",{"class":"s9eBZ"}," tree"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"${{ needs.verified.outputs.tree }}\n"]]]],["blockquote",{},["p",{},["span",{},"!IMPORTANT"],"\nA gated job reports as ",["strong",{},"skipped"],", not as passed. Whether a skipped job satisfies a required check is not verified for this estate — confirm it on one repo before making the marker a rule, or a green run will look blocked."]],["h2",{"id":"checklist"},"Checklist"],["ul",{"className":["contains-task-list"]},["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," The workflow file contains a trigger and a ",["code",{},"uses:"],", and nothing else."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," The ",["code",{},"uses:"]," names a commit SHA with the version as a trailing comment."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," Every secret the body declares is passed by name; ",["code",{},"secrets: inherit"]," appears nowhere."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," Every required check in the repo''s branch protection matches a ",["code",{}," / "]," name that the new run actually reports."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," A run has completed green on the branch, and the check names in it match the rule."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," Any fix the body carries for this repo is named in the PR description, so the change is reviewed as a fix rather than a port."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," The ",["code",{},"push"]," trigger of any analysis workflow names the release branch only, so one change is not scanned twice."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," A ",["code",{},"paths-ignore"]," covers prose where the workflow cannot be affected by it."]],["style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}"]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"steps","depth":2,"text":"Steps"},{"id":"three-triggers-worth-fixing-while-you-are-here","depth":2,"text":"Three triggers worth fixing while you are here"},{"id":"checklist","depth":2,"text":"Checklist"}]}}', 'Replace a repo copy of a workflow with a call to the central body, and move its branch-protection rule to the check names the call produces.', 'md', NULL, NULL, '{}', NULL, '/workflows/v0.7.0/guides/migrate-a-repo-to-a-stub', '{"title":"Migrate a repo to a stub","description":"Replace a repo copy of a workflow with a call to the central body, and move its branch-protection rule to the check names the call produces."}', 'workflows/v0.7.0/1.guides/1.migrate-a-repo-to-a-stub', 'rDhIWCGPPStIEV6doo8ofrrLXeLbOegPhc7WbGi6LBo'); -- rDhIWCGPPStIEV6doo8ofrrLXeLbOegPhc7WbGi6LBo +INSERT INTO _content_docs_workflows_v0_7_0 VALUES ('docs_workflows_v0_7_0/workflows/v0.7.0/1.guides/2.add-a-body.md', 'Add a body', '{"type":"minimark","value":[["h1",{"id":"add-a-body"},"Add a body"],["p",{},"A body runs in every repo that calls it, so the question to hold throughout is what a repo on a different branch topology, a different runner or a different stack does with it."],["h2",{"id":"steps"},"Steps"],["ol",{},["li",{},["strong",{},"Name the file ",["code",{},"_.yml"],"."]," The underscore marks a file that never runs on its own, keeps the bodies together in the Actions sidebar, and leaves the unprefixed name free for this repository''s own stub."],["li",{},["strong",{},"Give it ",["code",{},"on: workflow_call"]," and nothing else."]," A body has no trigger of its own. Anything that has to be dispatched, scheduled or fired by a push stays in the stub — a reusable workflow cannot be the target of a ",["code",{},"workflow_dispatch"],"."],["li",{},["strong",{},"Hardcode ",["code",{},"runs-on: ubuntu-latest"],"."]," A caller cannot set it, and making it an input has not been needed."],["li",{},["strong",{},"Derive what the repo can answer; take an input only for what it cannot."]," The branch topology, the owner and the check list are properties of the calling repo — read them. A version matrix or a language set is not, so those are inputs. See ",["a",{"href":"../adr/0001-derive-a-bodys-configuration-from-the-repo"},"ADR-0001"],"."],["li",{},["strong",{},"Declare each secret the body needs under ",["code",{},"secrets:"],"."]," Named, never inherited — see ",["a",{"href":"../adr/0003-name-every-secret-a-stub-passes"},"ADR-0003"],"."],["li",{},["strong",{},"Choose the job names deliberately."]," They are the second half of every caller''s check names, so a rename breaks required checks in every calling repo at once. Treat them as a public interface from the first commit, and prefer a name that survives the body growing a job."],["li",{},["strong",{},"Write this repository''s own stub for it."]," Same filename other repos use, with a local path:",["pre",{"className":"language-yaml shiki shiki-themes github-light github-dark","code":"jobs:\n promotion-pr:\n uses: ./.github/workflows/_promotion-pr.yml\n","language":"yaml","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"s9eBZ"},"jobs"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":2},["span",{"class":"s9eBZ"}," promotion-pr"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":3},["span",{"class":"s9eBZ"}," uses"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"./.github/workflows/_promotion-pr.yml\n"]]]],["br",{}],"The body then runs here on every change, so a broken one fails at home before it reaches a caller."],["li",{},["strong",{},"Pass every command input through ",["code",{},"env:"],", never into the ",["code",{},"run:"]," block."]," An interpolated ",["code",{},"${{ inputs.x }}"]," becomes part of the script text before the shell parses it, so a value can break out of the command it was meant to be:",["pre",{"className":"language-yaml shiki shiki-themes github-light github-dark","code":"# wrong — the value is interpolated into the script\n- run: ${{ inputs.build-command }}\n\n# right — the value stays a value\n- env:\n BUILD_COMMAND: ${{ inputs.build-command }}\n run: bash -c \"$BUILD_COMMAND\"\n","language":"yaml","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"sJ8bj"},"# wrong — the value is interpolated into the script\n"]],["span",{"class":"line","line":2},["span",{"class":"sVt8B"},"- "],["span",{"class":"s9eBZ"},"run"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"${{ inputs.build-command }}\n"]],["span",{"class":"line","line":3},["span",{"emptyLinePlaceholder":true},"\n"]],["span",{"class":"line","line":4},["span",{"class":"sJ8bj"},"# right — the value stays a value\n"]],["span",{"class":"line","line":5},["span",{"class":"sVt8B"},"- "],["span",{"class":"s9eBZ"},"env"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":6},["span",{"class":"s9eBZ"}," BUILD_COMMAND"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"${{ inputs.build-command }}\n"]],["span",{"class":"line","line":7},["span",{"class":"s9eBZ"}," run"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"bash -c \"$BUILD_COMMAND\"\n"]]]],["br",{}],"This holds for anything the caller supplies and for the mutable parts of the ",["code",{},"github"]," context — ",["code",{},"ref_name"]," and ",["code",{},"run_number"]," among them. CodeQL flags the interpolated form as code injection, and it is right to."],["li",{},["strong",{},"Do not call the repository''s composite action from the body."]," A relative ",["code",{},"uses:"]," resolves against the caller''s workspace — see ",["a",{"href":"../adr/0006-keep-the-composite-action-out-of-the-bodies"},"ADR-0006"],". Duplicate the setup steps instead."],["li",{},["strong",{},"Give the concurrency group this body''s own name."]," In a called workflow ",["code",{},"github.workflow"]," is the ",["em",{},"caller''s"]," name, so two bodies the same caller invokes share one group and cancel each other — the second to start kills the first, and the run reports a job that never ran:",["pre",{"className":"language-yaml shiki shiki-themes github-light github-dark","code":"concurrency:\n group: ${{ github.workflow }}-ci-laravel-${{ github.event.pull_request.number || github.ref }}\n","language":"yaml","meta":"","style":""},["code",{"__ignoreMap":""},["span",{"class":"line","line":1},["span",{"class":"s9eBZ"},"concurrency"],["span",{"class":"sVt8B"},":\n"]],["span",{"class":"line","line":2},["span",{"class":"s9eBZ"}," group"],["span",{"class":"sVt8B"},": "],["span",{"class":"sZZnC"},"${{ github.workflow }}-ci-laravel-${{ github.event.pull_request.number || github.ref }}\n"]]]]],["li",{},["strong",{},"Run the linters."]," ",["code",{},"pnpm lint:actions"]," runs actionlint over every workflow and needs Docker; ",["code",{},"pnpm check"]," runs it as part of the gate."]],["h2",{"id":"checklist"},"Checklist"],["ul",{"className":["contains-task-list"]},["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," The file is named ",["code",{},"_.yml"]," and its only trigger is ",["code",{},"workflow_call"],"."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," ",["code",{},"runs-on"]," is fixed in the body, and no caller is asked to supply it."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," Every input is something the body genuinely cannot read from the repo it runs in."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," Every secret is declared by name in the body and passed by name in the stub."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," No ",["code",{},"run:"]," block interpolates an input or a mutable ",["code",{},"github"]," value; each travels through ",["code",{},"env:"],"."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," The concurrency group names this body, so it cannot cancel a sibling the same caller invoked."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," Job names are ones you are willing to keep, because renaming one is an estate-wide branch-protection change."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," This repository carries a stub calling the body by local path, and it has run green."],["li",{"className":["task-list-item"]},["input",{"disabled":true,"type":"checkbox"}]," ",["code",{},"pnpm check"]," passes."]],["style",{},"html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}"]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"steps","depth":2,"text":"Steps"},{"id":"checklist","depth":2,"text":"Checklist"}]}}', 'Write a new reusable workflow that other repos call, without giving callers a value they have to keep correct.', 'md', NULL, NULL, '{}', NULL, '/workflows/v0.7.0/guides/add-a-body', '{"title":"Add a body","description":"Write a new reusable workflow that other repos call, without giving callers a value they have to keep correct."}', 'workflows/v0.7.0/1.guides/2.add-a-body', 'kCYRYdpXNPdRmcYNAZ4xJIUsv91KKFlTJ-ND-CZrQuc'); -- kCYRYdpXNPdRmcYNAZ4xJIUsv91KKFlTJ-ND-CZrQuc +INSERT INTO _content_docs_workflows_v0_7_0 VALUES ('docs_workflows_v0_7_0/workflows/v0.7.0/1.guides/index.md', 'Guides', '{"type":"minimark","value":[["h1",{"id":"guides"},"Guides"],["p",{},"Both tasks change something outside this repository — the first changes another repo''s checks, the second changes what every caller runs. Each page ends with a checklist for that reason."],["ul",{},["li",{},["a",{"href":"migrate-a-repo-to-a-stub"},"Migrate a repo to a stub"]," — replace a copied workflow with a call, without stranding a branch-protection rule."],["li",{},["a",{"href":"add-a-body"},"Add a body"]," — write a new reusable workflow that other repos can call."]]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}}', 'The two tasks this repository asks of a person: moving a repo onto a body, and writing a new one.', 'md', NULL, NULL, '{}', NULL, '/workflows/v0.7.0/guides', '{"title":"Guides","description":"The two tasks this repository asks of a person: moving a repo onto a body, and writing a new one."}', 'workflows/v0.7.0/1.guides/index', '59g1Dv6IWtzEd8uOYP_CP9W5yctr_R6lNetn3qA1aWo'); -- 59g1Dv6IWtzEd8uOYP_CP9W5yctr_R6lNetn3qA1aWo +INSERT INTO _content_docs_workflows_v0_7_0 VALUES ('docs_workflows_v0_7_0/workflows/v0.7.0/99.adr/0001-derive-a-bodys-configuration-from-the-repo.md', 'Derive a body''s configuration from the repo', '{"type":"minimark","value":[["h1",{"id":"adr-0001-derive-a-bodys-configuration-from-the-repo"},"ADR-0001 — Derive a body''s configuration from the repo"],["h2",{"id":"context"},"Context"],["p",{},"The bodies replace workflow files that had been copied into every repo and had drifted apart. Counting the copies made them look irreconcilable — the fast-forward queue workflow existed in eight versions — but the differences between them were not eight problems. They were the integration branch name, a per-owner secret identifier, a runner label, and a group of repos that had never received a fix."],["p",{},"Each of those first values is something the repo already answers. The branch name is decided by the trigger that let the run start; the owner is on every event payload. Carried as a literal, the owner-specific identifier was wrong in several repos at once — a mismatch that resolves for nobody, silently, and surfaces only when someone dispatches the workflow."],["p",{},"A value that a caller supplies is a value the caller maintains, and a maintained value in every repo is the copy this repository exists to remove, one file smaller."],["h2",{"id":"decision"},"Decision"],["p",{},"A body reads what the repo it runs in can tell it. An input exists only for what a body genuinely cannot know — the languages an analysis should cover, the versions a matrix should span."],["p",{},"Where a body cannot read a value from the event it is triggered by, it resolves it in a job of its own and hands it to the rest through ",["code",{},"needs"],", rather than accepting it from the caller."],["h2",{"id":"consequences"},"Consequences"],["p",{},"Every calling repo carries the same stub for the same workflow, so two stubs that differ mark a real difference rather than an accident of when they were copied."],["p",{},"A repo changes its behaviour by changing itself. Creating an integration branch moves it to another branch topology and no workflow file changes anywhere — which is the property being bought, and also the surprise: nothing in the stub says the topology is a decision."],["p",{},"A whole class of error stops being possible instead of being fixed in each place it occurred."],["p",{},"The cost is paid at the body: deriving a value takes a job or a step that an input would not have needed, that job''s name becomes part of every caller''s check names, and a body is harder to exercise in isolation because it now depends on the shape of the repo around it. A repo that wants to deviate from what its own state implies cannot do so from the call site at all."],["h2",{"id":"alternatives-considered"},"Alternatives considered"],["p",{},["strong",{},"An input per value."]," Correct, conventional, and the way most reusable workflows are written. It hands each caller a value to keep in step with its own trigger — which is what the copies were doing, expressed in fewer lines."],["p",{},["strong",{},"A configuration file in the calling repo."]," The same objection, one level up, plus a second file to keep in step with the first."],["p",{},["strong",{},"One body per topology."]," This is where the eight variants came from."]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"context","depth":2,"text":"Context"},{"id":"decision","depth":2,"text":"Decision"},{"id":"consequences","depth":2,"text":"Consequences"},{"id":"alternatives-considered","depth":2,"text":"Alternatives considered"}]}}', 'A body reads the values that differ per repo out of the repo it runs in, and accepts an input only for what it cannot know.', 'md', NULL, NULL, '{"status":"accepted","date":"2026-09-01"}', NULL, '/workflows/v0.7.0/adr/0001-derive-a-bodys-configuration-from-the-repo', '{"title":"Derive a body''s configuration from the repo","description":"A body reads the values that differ per repo out of the repo it runs in, and accepts an input only for what it cannot know."}', 'workflows/v0.7.0/99.adr/0001-derive-a-bodys-configuration-from-the-repo', 'rOMf7dyOWZjfMKIU7tdRW2o87PX7VokBRX_psbwOf38'); -- rOMf7dyOWZjfMKIU7tdRW2o87PX7VokBRX_psbwOf38 +INSERT INTO _content_docs_workflows_v0_7_0 VALUES ('docs_workflows_v0_7_0/workflows/v0.7.0/99.adr/0002-pin-callers-to-a-commit-sha.md', 'Pin callers to a commit SHA', '{"type":"minimark","value":[["h1",{"id":"adr-0002-pin-callers-to-a-commit-sha"},"ADR-0002 — Pin callers to a commit SHA"],["h2",{"id":"context"},"Context"],["p",{},"A caller has to name a ref. A moving major tag is the conventional choice and the one the marketplace actions themselves offer, and this repository can move such a tag: release-please cuts exact tags, and the release workflow can force-push ",["code",{},"v"]," onto each one."],["p",{},"What makes the choice not obvious is what some of these bodies do. The queue workflows read a private key out of the secret vault and mint a GitHub App token whose entire purpose is to bypass a merge gate on an integration branch. On a moving ref, anyone able to push a commit here would be able to change what that token is used for in every repo that calls it, with no review in any of them."],["h2",{"id":"decision"},"Decision"],["p",{},"Caller stubs pin a full commit SHA, with the version as a trailing comment. Bumps arrive as dependency-bot pull requests, and reviewing one of those is the gate."],["p",{},"The moving ",["code",{},"v"]," alias is published for callers who want the other trade, but it is opt-in per repository and off by default."],["h2",{"id":"consequences"},"Consequences"],["p",{},"Write access to this repository is not, by itself, write access to every repository in the estate. A change reaches a caller only when someone merges the bump."],["p",{},"Every repo is therefore behind by however long its bump PR sits, including for a fix, and a security fix reaches the estate at the speed of review rather than at the speed of a push."],["p",{},"The trailing comment is the only thing that tells a human which version a stub is on, and nothing enforces that it stays truthful."],["p",{},"The alias defaults to off because moving a tag is a hazard where something else reads the tag list as a version list — for a published package the registry version is what resolves, and for a Terraform provider an extra unversioned tag is not valid semver at all."],["h2",{"id":"alternatives-considered"},"Alternatives considered"],["p",{},["strong",{},"A moving major tag as the default."]," One less thing for every repo to bump, at the price of the review gate above. It stays available to any repo that opts in."],["p",{},["strong",{},"A branch as the ref."]," The same exposure with no version information at all."]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"context","depth":2,"text":"Context"},{"id":"decision","depth":2,"text":"Decision"},{"id":"consequences","depth":2,"text":"Consequences"},{"id":"alternatives-considered","depth":2,"text":"Alternatives considered"}]}}', 'Caller stubs reference a body by commit SHA with the version as a trailing comment; the moving major alias is published but opt-in and off by default.', 'md', NULL, NULL, '{"status":"accepted","date":"2026-09-01"}', NULL, '/workflows/v0.7.0/adr/0002-pin-callers-to-a-commit-sha', '{"title":"Pin callers to a commit SHA","description":"Caller stubs reference a body by commit SHA with the version as a trailing comment; the moving major alias is published but opt-in and off by default."}', 'workflows/v0.7.0/99.adr/0002-pin-callers-to-a-commit-sha', '9ZaTazX0AwVUrtV5oTOnHij0B-5x_dVNM72ufVaPjlA'); -- 9ZaTazX0AwVUrtV5oTOnHij0B-5x_dVNM72ufVaPjlA +INSERT INTO _content_docs_workflows_v0_7_0 VALUES ('docs_workflows_v0_7_0/workflows/v0.7.0/99.adr/0003-name-every-secret-a-stub-passes.md', 'Name every secret a stub passes', '{"type":"minimark","value":[["h1",{"id":"adr-0003-name-every-secret-a-stub-passes"},"ADR-0003 — Name every secret a stub passes"],["h2",{"id":"context"},"Context"],["p",{},"A caller can hand a reusable workflow everything it holds in one word. That word is shorter than a block naming each secret, and it never needs touching again when a body grows a new requirement."],["p",{},"It also decides, once, that every secret the repository acquires from then on is visible to every body it calls — including secrets added long after anyone last read the stub, and including bodies added to the call after that."],["h2",{"id":"decision"},"Decision"],["p",{},"A stub passes exactly the secrets its body declares, one key at a time. ",["code",{},"secrets: inherit"]," is not used."],["h2",{"id":"consequences"},"Consequences"],["p",{},"What a body can reach is stated in the file that grants it, so the answer to what a workflow can read is the stub itself rather than the repository''s whole secret list."],["p",{},"A body that starts needing another secret cannot get it silently: every caller has to be edited, which is a visible change and a reviewed one."],["p",{},"That is also the cost — such a change is a pull request per calling repo, and until each lands the body fails there rather than degrading."],["h2",{"id":"alternatives-considered"},"Alternatives considered"],["p",{},["strong",{},["code",{},"secrets: inherit"],"."]," One line per stub instead of two or three, and no edit when a body''s needs change. Rejected for exactly the second property."]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"context","depth":2,"text":"Context"},{"id":"decision","depth":2,"text":"Decision"},{"id":"consequences","depth":2,"text":"Consequences"},{"id":"alternatives-considered","depth":2,"text":"Alternatives considered"}]}}', 'A caller passes each secret a body needs explicitly; secrets: inherit is not used.', 'md', NULL, NULL, '{"status":"accepted","date":"2026-09-01"}', NULL, '/workflows/v0.7.0/adr/0003-name-every-secret-a-stub-passes', '{"title":"Name every secret a stub passes","description":"A caller passes each secret a body needs explicitly; secrets: inherit is not used."}', 'workflows/v0.7.0/99.adr/0003-name-every-secret-a-stub-passes', 'H2RfBPLUEf31H4U9HdKysJ-1TOrNcbgOgPPFfcq0tPo'); -- H2RfBPLUEf31H4U9HdKysJ-1TOrNcbgOgPPFfcq0tPo +INSERT INTO _content_docs_workflows_v0_7_0 VALUES ('docs_workflows_v0_7_0/workflows/v0.7.0/99.adr/0004-compose-ci-from-bodies-that-are-jobs.md', 'Compose CI from bodies that are jobs', '{"type":"minimark","value":[["h1",{"id":"adr-0004-compose-ci-from-bodies-that-are-jobs"},"ADR-0004 — Compose CI from bodies that are jobs"],["h2",{"id":"context"},"Context"],["p",{},"CI was the workflow that had drifted furthest: measured across the estate, nearly every repo''s copy was unique. Behind that were a handful of families — repos running a single gate, libraries running a typecheck-test-build set, packages running a version matrix against a database, providers running a language toolchain — and a few repos with pipelines that genuinely belong to them, carrying deploy stages and their own short-circuits."],["p",{},"Unlike the queue workflows, the differences here are not values a body can look up. Whether a repo needs a database, which toolchain it installs and what \"tested\" means for it are properties of its stack, not of its state."],["h2",{"id":"decision"},"Decision"],["p",{},"A CI body is a ",["strong",{},"job"]," that a caller composes into a pipeline it still owns, and there is one body per family rather than one body for CI."],["p",{},"Inputs on such a body say what the body cannot know — which versions a matrix spans, which paths a filter watches. They never say which parts of the body to skip."],["h2",{"id":"consequences"},"Consequences"],["p",{},"A repo keeps its own pipeline and its own graph: it decides what runs, in which order, and what a short-circuit is allowed to stand for. The bodies it calls do not need to know about each other."],["p",{},"Repos with pipelines of their own are not special cases to be worked around — they compose from the same pieces as everyone else, which is why the pieces were cut at job boundaries in the first place."],["p",{},"Adding a family means adding a body. Writing one before a second caller exists is a cost taken deliberately, and only where a named repo would otherwise start by copying the first one."],["p",{},"A caller''s pipeline is longer than a single ",["code",{},"uses:"]," line, and the composition itself — which job needs which, what gates on what — is the one thing that can still drift between repos."],["h2",{"id":"alternatives-considered"},"Alternatives considered"],["p",{},["strong",{},"One CI body with feature switches"]," — flags for running tests, for needing a database, for a coverage step. It works. It also turns every stub into a configuration file of a dozen keys, which is the drift this repository removes, reappearing one level up. It would still have left the repos with their own pipelines as special cases, and those carry the most logic."],["p",{},["strong",{},"One body per repo."]," The starting point, and what was being replaced."]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"context","depth":2,"text":"Context"},{"id":"decision","depth":2,"text":"Decision"},{"id":"consequences","depth":2,"text":"Consequences"},{"id":"alternatives-considered","depth":2,"text":"Alternatives considered"}]}}', 'A CI body is a job the caller composes into its own pipeline, never one body with switches for the parts a repo does not run.', 'md', NULL, NULL, '{"status":"accepted","date":"2026-09-01"}', NULL, '/workflows/v0.7.0/adr/0004-compose-ci-from-bodies-that-are-jobs', '{"title":"Compose CI from bodies that are jobs","description":"A CI body is a job the caller composes into its own pipeline, never one body with switches for the parts a repo does not run."}', 'workflows/v0.7.0/99.adr/0004-compose-ci-from-bodies-that-are-jobs', '4zVtwFXq7kOd1qLPHRUGmOFXdeOjIrnRfHF-N0tQlm8'); -- 4zVtwFXq7kOd1qLPHRUGmOFXdeOjIrnRfHF-N0tQlm8 +INSERT INTO _content_docs_workflows_v0_7_0 VALUES ('docs_workflows_v0_7_0/workflows/v0.7.0/99.adr/0005-publish-with-one-body-per-target.md', 'Publish with one body per target', '{"type":"minimark","value":[["h1",{"id":"adr-0005-publish-with-one-body-per-target"},"ADR-0005 — Publish with one body per target"],["h2",{"id":"context"},"Context"],["p",{},"The release workflow and the publish step arrived as one file in every repo that had them. Most repos that cut releases publish nothing at all — they exist to be depended on by their own tags, or they deploy instead. The ones that do publish split by target, and the targets need different credentials: a registry token for one, a signing key out of the vault for another."],["p",{},"A single body serving all of them would have to make every credential optional, which erases the signal of which one a repo actually needs, and would ask the repos that publish nothing to carry inputs they have no use for."],["h2",{"id":"decision"},"Decision"],["p",{},"Releasing is one body. Publishing is a separate body per target, and the caller composes the one it needs, gated on whether a release was actually created."],["h2",{"id":"consequences"},"Consequences"],["p",{},"A repo that publishes nothing calls one body and passes one secret. A repo that publishes states which target it publishes to by which body it calls — the stub says what the repo is."],["p",{},"Adding a target means adding a body, not adding a branch to an existing one, and the repos that do not use it are unaffected by its existence."],["p",{},"The caller now writes the wiring between the two jobs, so the gate on \"a release was created\" is stated once per repo rather than once in a body. That wiring is duplicated across the repos publishing to the same target, and it is the piece that could drift."],["p",{},"Repos that deploy rather than publish keep their own jobs. Those touch environments rather than artifacts, and centralising them was never in question."],["h2",{"id":"alternatives-considered"},"Alternatives considered"],["p",{},["strong",{},"One body with a ",["code",{},"target"]," input."]," Every secret optional, every publishing repo passing a flag, and the repos that publish nothing carrying the surface anyway."],["p",{},["strong",{},"Publishing folded into the release body."]," The same problem with fewer files, and it would have made the release body untouchable for the majority of callers that only want a tag."]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"context","depth":2,"text":"Context"},{"id":"decision","depth":2,"text":"Decision"},{"id":"consequences","depth":2,"text":"Consequences"},{"id":"alternatives-considered","depth":2,"text":"Alternatives considered"}]}}', 'Releasing and publishing are separate bodies, and a caller composes the publish body its target needs.', 'md', NULL, NULL, '{"status":"accepted","date":"2026-09-01"}', NULL, '/workflows/v0.7.0/adr/0005-publish-with-one-body-per-target', '{"title":"Publish with one body per target","description":"Releasing and publishing are separate bodies, and a caller composes the publish body its target needs."}', 'workflows/v0.7.0/99.adr/0005-publish-with-one-body-per-target', 'j3Gy3NqCFZfDvnb-Y0mbItrt1YGje4YEipZz_QcYlZc'); -- j3Gy3NqCFZfDvnb-Y0mbItrt1YGje4YEipZz_QcYlZc +INSERT INTO _content_docs_workflows_v0_7_0 VALUES ('docs_workflows_v0_7_0/workflows/v0.7.0/99.adr/0006-keep-the-composite-action-out-of-the-bodies.md', 'Keep the composite action out of the bodies', '{"type":"minimark","value":[["h1",{"id":"adr-0006-keep-the-composite-action-out-of-the-bodies"},"ADR-0006 — Keep the composite action out of the bodies"],["h2",{"id":"context"},"Context"],["p",{},"A reusable workflow is taken whole. A caller cannot replace one of its steps or insert another, so a repo needing \"that body plus one thing\" has to write its own job — which is why the setup those bodies open with also exists as a composite action it can call."],["p",{},"Using that same action inside the bodies looks like the obvious next step, and it is a trap. A relative ",["code",{},"uses:"]," inside a reusable workflow resolves against the ",["strong",{},"caller''s"]," workspace, not against the repository the body lives in, so a body cannot say ",["code",{},"./"],". It would have to name this repository and a ref in full — and ",["code",{},"uses:"]," accepts no expression, so that ref could not be the one the caller pinned. It would be a literal, fixed at the time the body was written."],["p",{},"A caller pinning a body to one commit would then run a body from that commit and a setup action from a different one, with nothing anywhere saying so."],["h2",{"id":"decision"},"Decision"],["p",{},"The bodies do not call the composite action. They repeat the few setup steps inline. The action exists for callers writing their own jobs."],["h2",{"id":"consequences"},"Consequences"],["p",{},"A pinned SHA means what it appears to mean: everything the run executes out of this repository comes from that commit."],["p",{},"The setup steps exist in both places, so a change to how the toolchain is set up has to be made in the bodies and in the action, and nothing checks that the two agree."],["p",{},"A repo that needs a body plus one step writes its own job around the action instead of forking the body, which keeps the fork pressure off the bodies."],["h2",{"id":"alternatives-considered"},"Alternatives considered"],["p",{},["strong",{},"Calling the action with a hardcoded ref."]," Removes the duplication and introduces a pin that lies. The duplication is a handful of lines; the pin would be a silent inconsistency at every caller."],["p",{},["strong",{},"Making the setup its own reusable workflow."]," A workflow cannot be a step inside a job, so this does not address the case at all."]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"context","depth":2,"text":"Context"},{"id":"decision","depth":2,"text":"Decision"},{"id":"consequences","depth":2,"text":"Consequences"},{"id":"alternatives-considered","depth":2,"text":"Alternatives considered"}]}}', 'The shared setup exists as a composite action for callers, but the bodies duplicate the steps rather than calling it.', 'md', NULL, NULL, '{"status":"accepted","date":"2026-09-01"}', NULL, '/workflows/v0.7.0/adr/0006-keep-the-composite-action-out-of-the-bodies', '{"title":"Keep the composite action out of the bodies","description":"The shared setup exists as a composite action for callers, but the bodies duplicate the steps rather than calling it."}', 'workflows/v0.7.0/99.adr/0006-keep-the-composite-action-out-of-the-bodies', 'SNEp9WTcxyi_EUjZY0jXm0HEvZtBMUtUVeoCGrpoe5g'); -- SNEp9WTcxyi_EUjZY0jXm0HEvZtBMUtUVeoCGrpoe5g +INSERT INTO _content_docs_workflows_v0_7_0 VALUES ('docs_workflows_v0_7_0/workflows/v0.7.0/99.adr/0007-run-the-gate-as-one-job-with-a-step-per-check.md', 'Run the gate as one job with a step per check', '{"type":"minimark","value":[["h1",{"id":"adr-0007-run-the-gate-as-one-job-with-a-step-per-check"},"ADR-0007 — Run the gate as one job with a step per check"],["h2",{"id":"context"},"Context"],["p",{},"For the repos whose CI is a set of independent checks, the copied workflows listed those checks a second time as steps — the same commands the package manifest''s gate script already chained, kept in step by hand."],["p",{},"Deriving the list from the gate script removes that second copy, and it also decides nothing about how the tasks then run. Two shapes were available: fan them out over a matrix so each reports as its own job, or run them as steps of one job."],["p",{},"The tasks in question are short. A run for these repos is dominated by checkout and dependency install, not by the checks themselves."],["h2",{"id":"decision"},"Decision"],["p",{},"The gate body splits the repo''s gate script into its task calls, expanding a task that chains another aggregate, and runs the result as ",["strong",{},"steps of a single job"],". Each task gets its own log group and its own error line, so a failed run names the check that failed."],["h2",{"id":"consequences"},"Consequences"],["p",{},"The check list follows the repo. A repo adds a check by editing its gate script, and CI picks it up with no workflow change — which is what carries the checks that exist in only one repo, without any of them being named here."],["p",{},"A run costs one checkout and one install rather than one per task."],["p",{},"What is given up is granularity at the job level: the whole gate is one check name, so a single aspect of it cannot be required on its own, and the tasks do not run in parallel. The first task to fail ends the job, so a run reports one failure rather than all of them."],["p",{},"A task that takes arguments is left unexpanded, because running it on its own would not be the same command."],["h2",{"id":"alternatives-considered"},"Alternatives considered"],["p",{},["strong",{},"A matrix, one job per task."]," It gives each check its own name and lets any one of them be required alone. Jobs share nothing — separate runner, separate filesystem, separate dependency tree — so n tasks cost n checkouts and n installs. For a gate of short tasks that makes the run slower while occupying several runners instead of one. The trade reverses where a single task runs for minutes, which is why the bodies for the heavier stacks do use a matrix."],["p",{},["strong",{},"Running the gate script as one command."]," One step, no derivation, and a red build that does not say which check failed."]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"context","depth":2,"text":"Context"},{"id":"decision","depth":2,"text":"Decision"},{"id":"consequences","depth":2,"text":"Consequences"},{"id":"alternatives-considered","depth":2,"text":"Alternatives considered"}]}}', 'The gate body derives its task list from the repo package manifest and runs the tasks as steps of a single job rather than fanning them over a matrix.', 'md', NULL, NULL, '{"status":"accepted","date":"2026-09-01"}', NULL, '/workflows/v0.7.0/adr/0007-run-the-gate-as-one-job-with-a-step-per-check', '{"title":"Run the gate as one job with a step per check","description":"The gate body derives its task list from the repo package manifest and runs the tasks as steps of a single job rather than fanning them over a matrix."}', 'workflows/v0.7.0/99.adr/0007-run-the-gate-as-one-job-with-a-step-per-check', 't-09cWvwua-z-Wc03uksue16mi1-9JVkjzchvL0gLQE'); -- t-09cWvwua-z-Wc03uksue16mi1-9JVkjzchvL0gLQE +INSERT INTO _content_docs_workflows_v0_7_0 VALUES ('docs_workflows_v0_7_0/workflows/v0.7.0/99.adr/0008-give-each-reporter-its-own-comment-thread.md', 'Give each reporter its own comment thread', '{"type":"minimark","value":[["h1",{"id":"adr-0008-give-each-reporter-its-own-comment-thread"},"ADR-0008 — Give each reporter its own comment thread"],["h2",{"id":"context"},"Context"],["p",{},"Two of the bodies write results back to a pull request: coverage, and the performance audit. The repository they were derived from had collected both into a single comment, and said why — a second reporting job beside it would open a second thread, and a pull request carrying a thread per metric is one nobody reads."],["p",{},"That reasoning holds for a pipeline written in one file. It does not survive being split into bodies that repos compose independently. A repo calling the coverage body alongside the combined job would get the second thread anyway, because the two know nothing about each other; and coupling them so they do not would mean one body reading another''s output, which is the shape the split was meant to avoid. Either the reporters share a marker and are no longer independent, or they are independent and there is more than one thread."],["h2",{"id":"decision"},"Decision"],["p",{},"Each reporting body owns its own sticky marker and posts under it alone. Coverage keeps the marker its action already writes; the audit posts under its own. Neither body knows the other exists."],["h2",{"id":"consequences"},"Consequences"],["p",{},"A pull request in a repo that runs both carries two comment threads instead of one. That is the cost, and it is paid on every such pull request."],["p",{},"What it buys is that either body can be adopted without the other, dropped without touching the other, and changed without a second body''s output shifting. It also removes the last reason the combined job could not be replaced: it was blocked by this coupling rather than by a missing second caller."],["p",{},"The markers now have to stay distinct by convention, since nothing enforces it — a body colliding with another''s marker would silently overwrite its report."],["h2",{"id":"alternatives-considered"},"Alternatives considered"],["p",{},["strong",{},"One shared marker, written by whichever body runs last."]," Keeps a single thread, and makes the last writer responsible for content it did not produce — a body would have to read another''s artifact to avoid erasing it. The coupling that was being removed, reintroduced at the comment level."],["p",{},["strong",{},"One reporting body aggregating the others."]," A single thread again, at the price of a body that must know every reporter that exists, and must be extended before any new one can report anything."]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"context","depth":2,"text":"Context"},{"id":"decision","depth":2,"text":"Decision"},{"id":"consequences","depth":2,"text":"Consequences"},{"id":"alternatives-considered","depth":2,"text":"Alternatives considered"}]}}', 'A body that reports to a pull request owns its own sticky marker, rather than several reporters sharing one comment.', 'md', NULL, NULL, '{"status":"accepted","date":"2026-09-01"}', NULL, '/workflows/v0.7.0/adr/0008-give-each-reporter-its-own-comment-thread', '{"title":"Give each reporter its own comment thread","description":"A body that reports to a pull request owns its own sticky marker, rather than several reporters sharing one comment."}', 'workflows/v0.7.0/99.adr/0008-give-each-reporter-its-own-comment-thread', 'YGJZIajkVGSblpQyl4Kt3jOJ9dgt1qj21S6e_OdJsmY'); -- YGJZIajkVGSblpQyl4Kt3jOJ9dgt1qj21S6e_OdJsmY +INSERT INTO _content_docs_workflows_v0_7_0 VALUES ('docs_workflows_v0_7_0/workflows/v0.7.0/99.adr/0009-write-a-body-before-its-second-caller.md', 'Write a body before its second caller', '{"type":"minimark","value":[["h1",{"id":"adr-0009-write-a-body-before-its-second-caller"},"ADR-0009 — Write a body before its second caller"],["h2",{"id":"context"},"Context"],["p",{},"The case for centralising a workflow is that several repos carry the same one. Where only a single repo has it, that case is absent: a body written for one caller generalises a shape nobody has met twice, and the input it takes may be the wrong seam."],["p",{},"Refusing every such body has its own cost, and it falls on a repo that does not exist yet. The next repo of a given kind starts from the only version available — a copy, taken whole, from whichever repo happened to have one. A long pipeline copied once is a second variant from its first commit, and the estate''s own history is the argument: every workflow being centralised here reached its variant count exactly that way."],["p",{},"Both failure modes are real, so the question is which repo pays: a body generalised too early, or a copy made too late."],["h2",{"id":"decision"},"Decision"],["p",{},"A body may be written for a single caller when a ",["strong",{},"named"]," repo is known to need it next — one that exists, or one a template is expected to produce. The reasoning goes in the body''s own header, naming that repo, so a later reader can tell a considered exception from an oversight."],["p",{},"Where no such repo can be named, one instance is not a pattern and no body is written."],["h2",{"id":"consequences"},"Consequences"],["p",{},"A body written this way has had its interface guessed once rather than observed twice. The second caller is likely to need an input that is not there, and adding it is cheap; discovering that the seam itself is wrong is not."],["p",{},"Migrating the first caller onto such a body may rename its checks, which is a branch-protection change in that repo. Accepted deliberately: it happens once, and it happens anyway during the migration."],["p",{},"The rule can be argued into anything, since any repo might one day need any workflow. The requirement that the next caller be ",["em",{},"named"]," is what keeps it a decision rather than a preference — an unnamed one is a hunch, and a hunch does not clear the bar."],["h2",{"id":"alternatives-considered"},"Alternatives considered"],["p",{},["strong",{},"Wait for the second caller, always."]," The rule as it would read without this record. It is right in the common case and wrong exactly where the second caller is a large repo whose copy would be made before anyone noticed."],["p",{},["strong",{},"Write every body speculatively."]," Removes the judgement, and fills the repository with interfaces shaped by a single example, each of which has to be broken when a real second caller arrives."]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"context","depth":2,"text":"Context"},{"id":"decision","depth":2,"text":"Decision"},{"id":"consequences","depth":2,"text":"Consequences"},{"id":"alternatives-considered","depth":2,"text":"Alternatives considered"}]}}', 'A body may be written for a single caller when a specific repo is known to need it next, and the reasoning is recorded with the body.', 'md', NULL, NULL, '{"status":"accepted","date":"2026-09-01"}', NULL, '/workflows/v0.7.0/adr/0009-write-a-body-before-its-second-caller', '{"title":"Write a body before its second caller","description":"A body may be written for a single caller when a specific repo is known to need it next, and the reasoning is recorded with the body."}', 'workflows/v0.7.0/99.adr/0009-write-a-body-before-its-second-caller', 'yK0uKfsrv0aTWuGVByNVx1YUSy8_DbuEd6V2kcrPmiY'); -- yK0uKfsrv0aTWuGVByNVx1YUSy8_DbuEd6V2kcrPmiY +INSERT INTO _content_docs_workflows_v0_7_0 VALUES ('docs_workflows_v0_7_0/workflows/v0.7.0/99.adr/index.md', 'Architecture decisions', '{"type":"minimark","value":[["h1",{"id":"architecture-decisions"},"Architecture decisions"],["p",{},"A decision earns an ADR when it constrains work that comes later and its reasoning would otherwise be lost: a choice between real alternatives, a convention every part of the project has to follow, a trade-off that looks like a mistake until the reason is known. Records are append-only — a reversed decision is written as a new ADR that supersedes the old one, never as an edit to it."],["p",{},"This log holds decisions about ",["strong",{},"this repository"],": what a body may assume, what a caller must state, and where the boundary between the two runs. Decisions about the estate''s provisioned state — branch protection, the queue App, the secret mirror — belong to ",["code",{},"kirchDev/infrastructure"]," and are recorded there; the bodies here implement them and cite them by id."],["table",{},["thead",{},["tr",{},["th",{"align":"left"},"ADR"],["th",{"align":"left"},"Decision"],["th",{"align":"left"},"Status"],["th",{"align":"left"},"Date"]]],["tbody",{},["tr",{},["td",{"align":"left"},["a",{"href":"0001-derive-a-bodys-configuration-from-the-repo"},"ADR-0001"]],["td",{"align":"left"},"Derive a body''s configuration from the repo"],["td",{"align":"left"},"Accepted"],["td",{"align":"left"},"2026-09-01"]],["tr",{},["td",{"align":"left"},["a",{"href":"0002-pin-callers-to-a-commit-sha"},"ADR-0002"]],["td",{"align":"left"},"Pin callers to a commit SHA"],["td",{"align":"left"},"Accepted"],["td",{"align":"left"},"2026-09-01"]],["tr",{},["td",{"align":"left"},["a",{"href":"0003-name-every-secret-a-stub-passes"},"ADR-0003"]],["td",{"align":"left"},"Name every secret a stub passes"],["td",{"align":"left"},"Accepted"],["td",{"align":"left"},"2026-09-01"]],["tr",{},["td",{"align":"left"},["a",{"href":"0004-compose-ci-from-bodies-that-are-jobs"},"ADR-0004"]],["td",{"align":"left"},"Compose CI from bodies that are jobs"],["td",{"align":"left"},"Accepted"],["td",{"align":"left"},"2026-09-01"]],["tr",{},["td",{"align":"left"},["a",{"href":"0005-publish-with-one-body-per-target"},"ADR-0005"]],["td",{"align":"left"},"Publish with one body per target"],["td",{"align":"left"},"Accepted"],["td",{"align":"left"},"2026-09-01"]],["tr",{},["td",{"align":"left"},["a",{"href":"0006-keep-the-composite-action-out-of-the-bodies"},"ADR-0006"]],["td",{"align":"left"},"Keep the composite action out of the bodies"],["td",{"align":"left"},"Accepted"],["td",{"align":"left"},"2026-09-01"]],["tr",{},["td",{"align":"left"},["a",{"href":"0007-run-the-gate-as-one-job-with-a-step-per-check"},"ADR-0007"]],["td",{"align":"left"},"Run the gate as one job with a step per check"],["td",{"align":"left"},"Accepted"],["td",{"align":"left"},"2026-09-01"]],["tr",{},["td",{"align":"left"},["a",{"href":"0008-give-each-reporter-its-own-comment-thread"},"ADR-0008"]],["td",{"align":"left"},"Give each reporter its own comment thread"],["td",{"align":"left"},"Accepted"],["td",{"align":"left"},"2026-09-01"]],["tr",{},["td",{"align":"left"},["a",{"href":"0009-write-a-body-before-its-second-caller"},"ADR-0009"]],["td",{"align":"left"},"Write a body before its second caller"],["td",{"align":"left"},"Accepted"],["td",{"align":"left"},"2026-09-01"]]]]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[]}}', 'The decision log — every architecture decision recorded for this repository.', 'md', NULL, NULL, '{}', NULL, '/workflows/v0.7.0/adr', '{"title":"Architecture decisions","description":"The decision log — every architecture decision recorded for this repository."}', 'workflows/v0.7.0/99.adr/index', 'wP2eswbSPrAcIcxSgLg9crUBFouN-kvSVk9AbwpeVPQ'); -- wP2eswbSPrAcIcxSgLg9crUBFouN-kvSVk9AbwpeVPQ +INSERT INTO _content_docs_workflows_v0_7_0 VALUES ('docs_workflows_v0_7_0/workflows/v0.7.0/index.md', 'workflows documentation', '{"type":"minimark","value":[["h1",{"id":"workflows"},"workflows"],["p",{},"This repository holds the estate''s reusable GitHub Actions workflow bodies. Every other repo carries a thin caller stub instead of its own copy, so a fix lands once and reaches each repo on its next bump."],["p",{},"These pages cover the two tasks the repository asks of a person — moving a repo onto a body, and writing a new one — and the decision log behind them."],["h2",{"id":"sections"},"Sections"],["ul",{},["li",{},["a",{"href":"1.guides/"},"Guides"]," — migrating a repo onto a stub, and adding a body."],["li",{},["a",{"href":"99.adr/"},"Architecture decisions"]," — the decision log."]],["p",{},"What the bodies do, how a stub looks and what each one needs is in the ",["a",{"href":"../README"},"README"],"; how to set the repo up and get a PR landed is in ",["a",{"href":"../CONTRIBUTING"},"CONTRIBUTING.md"],". Decisions about the estate''s provisioned state — branch protection, the queue App, the Bitwarden mirror — are recorded in ",["code",{},"kirchDev/infrastructure"],", not here."]],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"sections","depth":2,"text":"Sections"}]}}', 'How a repo moves onto the central reusable workflow bodies, how a new body is written, and the decisions that govern both.', 'md', NULL, NULL, '{}', NULL, '/workflows/v0.7.0', '{"title":"workflows documentation","description":"How a repo moves onto the central reusable workflow bodies, how a new body is written, and the decisions that govern both."}', 'workflows/v0.7.0/index', '45LCPrWqc2j05N2kvCKlXSqiBQy4l2OThzGrH7UoCa4'); -- 45LCPrWqc2j05N2kvCKlXSqiBQy4l2OThzGrH7UoCa4 +UPDATE _content_info SET ready = true WHERE id = 'checksum_docs_workflows_v0_7_0'; -- meta \ No newline at end of file diff --git a/www/.nuxt/content/types.d.ts b/www/.nuxt/content/types.d.ts new file mode 100644 index 00000000..14e63bad --- /dev/null +++ b/www/.nuxt/content/types.d.ts @@ -0,0 +1,34 @@ +import type { PageCollectionItemBase, DataCollectionItemBase } from '@nuxt/content' + +declare module '@nuxt/content' { + interface DocsDuxtCollectionItem extends PageCollectionItemBase { + icon?: string + layout?: string + navigation?: boolean + } + + interface DocsWorkflowsCollectionItem extends PageCollectionItemBase { + icon?: string + layout?: string + navigation?: boolean + } + + interface DocsWorkflowsV070CollectionItem extends PageCollectionItemBase { + icon?: string + layout?: string + navigation?: boolean + } + + + interface PageCollections { + docs_duxt: DocsDuxtCollectionItem + docs_workflows: DocsWorkflowsCollectionItem + docs_workflows_v0_7_0: DocsWorkflowsV070CollectionItem + } + + interface Collections { + docs_duxt: DocsDuxtCollectionItem + docs_workflows: DocsWorkflowsCollectionItem + docs_workflows_v0_7_0: DocsWorkflowsV070CollectionItem + } +} diff --git a/www/.nuxt/dev/index.mjs b/www/.nuxt/dev/index.mjs new file mode 100644 index 00000000..c3cd82d4 --- /dev/null +++ b/www/.nuxt/dev/index.mjs @@ -0,0 +1,3351 @@ +import process from 'node:process';globalThis._importMeta_={url:import.meta.url,env:process.env};import { tmpdir } from 'node:os'; +import { defineEventHandler, handleCacheHeaders, splitCookiesString, createEvent, fetchWithEvent, isEvent, eventHandler, setHeaders, createError, sendRedirect, proxyRequest, getRequestHeader, setResponseHeaders, setResponseStatus, send, getRequestHeaders, setResponseHeader, appendResponseHeader, getRequestURL, getResponseHeader, removeResponseHeader, getQuery as getQuery$1, getRequestWebStream, createApp, createRouter as createRouter$1, toNodeListener, lazyEventHandler, getResponseStatus, getRouterParam, readBody, getResponseStatusText } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/h3@1.15.11/node_modules/h3/dist/index.mjs'; +import { Server } from 'node:http'; +import { resolve, dirname, join } from 'node:path'; +import nodeCrypto from 'node:crypto'; +import { parentPort, threadId } from 'node:worker_threads'; +import { escapeHtml } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/@vue+shared@3.5.42/node_modules/@vue/shared/dist/shared.cjs.js'; +import viteNodeEntry_mjs from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/@nuxt+vite-builder@4.5.2_a55ba682e03276483786c88b5142260c/node_modules/@nuxt/vite-builder/dist/vite-node-entry.mjs'; +import { viteNodeFetch } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/@nuxt+vite-builder@4.5.2_a55ba682e03276483786c88b5142260c/node_modules/@nuxt/vite-builder/dist/vite-node.mjs'; +import { parseURL, withoutBase, joinURL, getQuery, withQuery, withTrailingSlash, decodePath, withLeadingSlash, withoutTrailingSlash, encodePath, joinRelativeURL } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/ufo@1.6.4/node_modules/ufo/dist/index.mjs'; +import destr, { destr as destr$1 } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/destr@2.0.5/node_modules/destr/dist/index.mjs'; +import { createHooks } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/hookable@5.5.3/node_modules/hookable/dist/index.mjs'; +import { createFetch, Headers as Headers$1 } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/ofetch@1.5.1/node_modules/ofetch/dist/node.mjs'; +import { fetchNodeRequestHandler, callNodeRequestHandler } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/node-mock-http@1.0.5/node_modules/node-mock-http/dist/index.mjs'; +import { createStorage, prefixStorage } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/unstorage@1.17.5_db0@0.3.4_ioredis@5.11.1_supports-color@10.2.2_/node_modules/unstorage/dist/index.mjs'; +import unstorage_47drivers_47fs from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/unstorage@1.17.5_db0@0.3.4_ioredis@5.11.1_supports-color@10.2.2_/node_modules/unstorage/drivers/fs.mjs'; +import { digest, hash as hash$1 } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/ohash@2.0.12/node_modules/ohash/dist/index.mjs'; +import { klona } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/klona@2.0.6/node_modules/klona/dist/index.mjs'; +import defu, { defuFn } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/defu@6.1.7/node_modules/defu/dist/defu.mjs'; +import { snakeCase } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/scule@1.3.0/node_modules/scule/dist/index.mjs'; +import { getContext } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/unctx@2.5.0/node_modules/unctx/dist/index.mjs'; +import { toRouteMatcher, createRouter } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/radix3@1.1.2/node_modules/radix3/dist/index.mjs'; +import { readFile } from 'node:fs/promises'; +import consola, { consola as consola$1 } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/consola@3.4.2/node_modules/consola/dist/index.mjs'; +import { ErrorParser } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/youch-core@0.3.3/node_modules/youch-core/build/index.js'; +import { Youch } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/youch@4.1.1/node_modules/youch/build/index.js'; +import { SourceMapConsumer } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/source-map@0.7.6/node_modules/source-map/source-map.js'; +import { defineDiagnostics, createConsoleReporter } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/nostics@1.2.0/node_modules/nostics/dist/index.mjs'; +import { ansiFormatter } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/nostics@1.2.0/node_modules/nostics/dist/formatters/ansi.mjs'; +import { AsyncLocalStorage } from 'node:async_hooks'; +import { stringify, uneval } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/devalue@5.9.2/node_modules/devalue/index.js'; +import { getContext as getContext$1 } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/unctx@3.0.1_magic-string@1.2.3_oxc-parser@0.141.0_rolldown@1.2.6_unplugin@3.3.0_esbuild_3dedeae4c4d2333b554e071fe7839713/node_modules/unctx/dist/index.mjs'; +import { captureRawStackTrace, parseRawStackTrace } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/errx@0.1.2/node_modules/errx/dist/index.mjs'; +import { isVNode, isRef, toValue } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/vue@3.5.42_typescript@6.0.3/node_modules/vue/index.mjs'; +import _wH6JrtIxmaSoA8lCPWFnE9z4lQeXW6H5z3l5aymEQw from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/@nuxt+vite-builder@4.5.2_a55ba682e03276483786c88b5142260c/node_modules/@nuxt/vite-builder/dist/fix-stacktrace.mjs'; +import { promises } from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import { dirname as dirname$1, resolve as resolve$1 } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/pathe@2.0.3/node_modules/pathe/dist/index.mjs'; +import { createRenderer, getRequestDependencies, getPreloadLinks, getPrefetchLinks } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/vue-bundle-renderer@2.3.2/node_modules/vue-bundle-renderer/dist/runtime.mjs'; +import { renderToString } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/vue@3.5.42_typescript@6.0.3/node_modules/vue/server-renderer/index.mjs'; +import { createHead as createHead$1, propsToString, renderSSRHead } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/unhead@3.4.0_esbuild@0.28.2_rolldown@1.2.6_rollup@4.63.1_vite@8.2.2_@types+node@26.4.0__dc5f77df5e9445d1ad9c8f2cfb2ecd4b/node_modules/unhead/dist/server.mjs'; +import { walkResolver } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/unhead@3.4.0_esbuild@0.28.2_rolldown@1.2.6_rollup@4.63.1_vite@8.2.2_@types+node@26.4.0__dc5f77df5e9445d1ad9c8f2cfb2ecd4b/node_modules/unhead/dist/utils.mjs'; +import { DeprecationsPlugin } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/unhead@3.4.0_esbuild@0.28.2_rolldown@1.2.6_rollup@4.63.1_vite@8.2.2_@types+node@26.4.0__dc5f77df5e9445d1ad9c8f2cfb2ecd4b/node_modules/unhead/dist/legacy.mjs'; +import { PromisesPlugin, TemplateParamsPlugin, AliasSortingPlugin } from 'file:///root/projects/comGithub/kirchDev/duxt/node_modules/.pnpm/unhead@3.4.0_esbuild@0.28.2_rolldown@1.2.6_rollup@4.63.1_vite@8.2.2_@types+node@26.4.0__dc5f77df5e9445d1ad9c8f2cfb2ecd4b/node_modules/unhead/dist/plugins.mjs'; + +const serverAssets = [{"baseName":"server","dir":"/root/projects/comGithub/kirchDev/duxt/www/server/assets"}]; + +const assets$1 = createStorage(); + +for (const asset of serverAssets) { + assets$1.mount(asset.baseName, unstorage_47drivers_47fs({ base: asset.dir, ignore: (asset?.ignore || []) })); +} + +const storage = createStorage({}); + +storage.mount('/assets', assets$1); + +storage.mount('root', unstorage_47drivers_47fs({"driver":"fs","readOnly":true,"base":"/root/projects/comGithub/kirchDev/duxt/www","watchOptions":{"ignored":[null]}})); +storage.mount('src', unstorage_47drivers_47fs({"driver":"fs","readOnly":true,"base":"/root/projects/comGithub/kirchDev/duxt/www/server","watchOptions":{"ignored":[null]}})); +storage.mount('build', unstorage_47drivers_47fs({"driver":"fs","readOnly":false,"base":"/root/projects/comGithub/kirchDev/duxt/www/.nuxt"})); +storage.mount('cache', unstorage_47drivers_47fs({"driver":"fs","readOnly":false,"base":"/root/projects/comGithub/kirchDev/duxt/www/.nuxt/cache"})); +storage.mount('data', unstorage_47drivers_47fs({"driver":"fs","base":"/root/projects/comGithub/kirchDev/duxt/www/.data/kv"})); + +function useStorage(base = "") { + return base ? prefixStorage(storage, base) : storage; +} + +const Hasher = /* @__PURE__ */ (() => { + class Hasher2 { + buff = ""; + #context = /* @__PURE__ */ new Map(); + write(str) { + this.buff += str; + } + dispatch(value) { + const type = value === null ? "null" : typeof value; + return this[type](value); + } + object(object) { + if (object && typeof object.toJSON === "function") { + return this.object(object.toJSON()); + } + const objString = Object.prototype.toString.call(object); + let objType = ""; + const objectLength = objString.length; + objType = objectLength < 10 ? "unknown:[" + objString + "]" : objString.slice(8, objectLength - 1); + objType = objType.toLowerCase(); + let objectNumber = null; + if ((objectNumber = this.#context.get(object)) === void 0) { + this.#context.set(object, this.#context.size); + } else { + return this.dispatch("[CIRCULAR:" + objectNumber + "]"); + } + if (typeof Buffer !== "undefined" && Buffer.isBuffer && Buffer.isBuffer(object)) { + this.write("buffer:"); + return this.write(object.toString("utf8")); + } + if (objType !== "object" && objType !== "function" && objType !== "asyncfunction") { + if (this[objType]) { + this[objType](object); + } else { + this.unknown(object, objType); + } + } else { + const keys = Object.keys(object).sort(); + const extraKeys = []; + this.write("object:" + (keys.length + extraKeys.length) + ":"); + const dispatchForKey = (key) => { + this.dispatch(key); + this.write(":"); + this.dispatch(object[key]); + this.write(","); + }; + for (const key of keys) { + dispatchForKey(key); + } + for (const key of extraKeys) { + dispatchForKey(key); + } + } + } + array(arr, unordered) { + unordered = unordered === void 0 ? false : unordered; + this.write("array:" + arr.length + ":"); + if (!unordered || arr.length <= 1) { + for (const entry of arr) { + this.dispatch(entry); + } + return; + } + const contextAdditions = /* @__PURE__ */ new Map(); + const entries = arr.map((entry) => { + const hasher = new Hasher2(); + hasher.dispatch(entry); + for (const [key, value] of hasher.#context) { + contextAdditions.set(key, value); + } + return hasher.toString(); + }); + this.#context = contextAdditions; + entries.sort(); + return this.array(entries, false); + } + date(date) { + return this.write("date:" + date.toJSON()); + } + symbol(sym) { + return this.write("symbol:" + sym.toString()); + } + unknown(value, type) { + this.write(type); + if (!value) { + return; + } + this.write(":"); + if (value && typeof value.entries === "function") { + return this.array( + [...value.entries()], + true + /* ordered */ + ); + } + } + error(err) { + return this.write("error:" + err.toString()); + } + boolean(bool) { + return this.write("bool:" + bool); + } + string(string) { + this.write("string:" + string.length + ":"); + this.write(string); + } + function(fn) { + this.write("fn:"); + if (isNativeFunction(fn)) { + this.dispatch("[native]"); + } else { + this.dispatch(fn.toString()); + } + } + number(number) { + return this.write("number:" + number); + } + null() { + return this.write("Null"); + } + undefined() { + return this.write("Undefined"); + } + regexp(regex) { + return this.write("regex:" + regex.toString()); + } + arraybuffer(arr) { + this.write("arraybuffer:"); + return this.dispatch(new Uint8Array(arr)); + } + url(url) { + return this.write("url:" + url.toString()); + } + map(map) { + this.write("map:"); + const arr = [...map]; + return this.array(arr, false); + } + set(set) { + this.write("set:"); + const arr = [...set]; + return this.array(arr, false); + } + bigint(number) { + return this.write("bigint:" + number.toString()); + } + } + for (const type of [ + "uint8array", + "uint8clampedarray", + "unt8array", + "uint16array", + "unt16array", + "uint32array", + "unt32array", + "float32array", + "float64array" + ]) { + Hasher2.prototype[type] = function(arr) { + this.write(type + ":"); + return this.array([...arr], false); + }; + } + function isNativeFunction(f) { + if (typeof f !== "function") { + return false; + } + return Function.prototype.toString.call(f).slice( + -15 + /* "[native code] }".length */ + ) === "[native code] }"; + } + return Hasher2; +})(); +function serialize(object) { + const hasher = new Hasher(); + hasher.dispatch(object); + return hasher.buff; +} +function hash(value) { + return digest(typeof value === "string" ? value : serialize(value)).replace(/[-_]/g, "").slice(0, 10); +} + +function defaultCacheOptions() { + return { + name: "_", + base: "/cache", + swr: true, + maxAge: 1 + }; +} +function defineCachedFunction(fn, opts = {}) { + opts = { ...defaultCacheOptions(), ...opts }; + const pending = {}; + const group = opts.group || "nitro/functions"; + const name = opts.name || fn.name || "_"; + const integrity = opts.integrity || hash([fn, opts]); + const validate = opts.validate || ((entry) => entry.value !== void 0); + async function get(key, resolver, shouldInvalidateCache, event) { + const cacheKey = [opts.base, group, name, key + ".json"].filter(Boolean).join(":").replace(/:\/$/, ":index"); + let entry = await useStorage().getItem(cacheKey).catch((error) => { + console.error(`[cache] Cache read error.`, error); + useNitroApp().captureError(error, { event, tags: ["cache"] }); + }) || {}; + if (typeof entry !== "object") { + entry = {}; + const error = new Error("Malformed data read from cache."); + console.error("[cache]", error); + useNitroApp().captureError(error, { event, tags: ["cache"] }); + } + const ttl = (opts.maxAge ?? 0) * 1e3; + if (ttl) { + entry.expires = Date.now() + ttl; + } + const expired = shouldInvalidateCache || entry.integrity !== integrity || ttl && Date.now() - (entry.mtime || 0) > ttl || validate(entry) === false; + const _resolve = async () => { + const isPending = pending[key]; + if (!isPending) { + if (entry.value !== void 0 && (opts.staleMaxAge || 0) >= 0 && opts.swr === false) { + entry.value = void 0; + entry.integrity = void 0; + entry.mtime = void 0; + entry.expires = void 0; + } + pending[key] = Promise.resolve(resolver()); + } + try { + entry.value = await pending[key]; + } catch (error) { + if (!isPending) { + delete pending[key]; + } + throw error; + } + if (!isPending) { + entry.mtime = Date.now(); + entry.integrity = integrity; + delete pending[key]; + if (validate(entry) !== false) { + let setOpts; + if (opts.maxAge && !opts.swr) { + setOpts = { ttl: opts.maxAge }; + } + const promise = useStorage().setItem(cacheKey, entry, setOpts).catch((error) => { + console.error(`[cache] Cache write error.`, error); + useNitroApp().captureError(error, { event, tags: ["cache"] }); + }); + if (event?.waitUntil) { + event.waitUntil(promise); + } + } + } + }; + const _resolvePromise = expired ? _resolve() : Promise.resolve(); + if (entry.value === void 0) { + await _resolvePromise; + } else if (expired && event && event.waitUntil) { + event.waitUntil(_resolvePromise); + } + if (opts.swr && validate(entry) !== false) { + _resolvePromise.catch((error) => { + console.error(`[cache] SWR handler error.`, error); + useNitroApp().captureError(error, { event, tags: ["cache"] }); + }); + return entry; + } + return _resolvePromise.then(() => entry); + } + return async (...args) => { + const shouldBypassCache = await opts.shouldBypassCache?.(...args); + if (shouldBypassCache) { + return fn(...args); + } + const key = await (opts.getKey || getKey)(...args); + const shouldInvalidateCache = await opts.shouldInvalidateCache?.(...args); + const entry = await get( + key, + () => fn(...args), + shouldInvalidateCache, + args[0] && isEvent(args[0]) ? args[0] : void 0 + ); + let value = entry.value; + if (opts.transform) { + value = await opts.transform(entry, ...args) || value; + } + return value; + }; +} +function cachedFunction(fn, opts = {}) { + return defineCachedFunction(fn, opts); +} +function getKey(...args) { + return args.length > 0 ? hash(args) : ""; +} +function escapeKey(key) { + return String(key).replace(/\W/g, ""); +} +function defineCachedEventHandler(handler, opts = defaultCacheOptions()) { + const variableHeaderNames = (opts.varies || []).filter(Boolean).map((h) => h.toLowerCase()).sort(); + const _opts = { + ...opts, + getKey: async (event) => { + const customKey = await opts.getKey?.(event); + if (customKey) { + return escapeKey(customKey); + } + const _path = event.node.req.originalUrl || event.node.req.url || event.path; + let _pathname; + try { + _pathname = escapeKey(decodeURI(parseURL(_path).pathname)).slice(0, 16) || "index"; + } catch { + _pathname = "-"; + } + const _hashedPath = `${_pathname}.${hash(_path)}`; + const _headers = variableHeaderNames.map((header) => [header, event.node.req.headers[header]]).map(([name, value]) => `${escapeKey(name)}.${hash(value)}`); + return [_hashedPath, ..._headers].join(":"); + }, + validate: (entry) => { + if (!entry.value) { + return false; + } + if (entry.value.code >= 400) { + return false; + } + if (entry.value.body === void 0) { + return false; + } + if (entry.value.headers.etag === "undefined" || entry.value.headers["last-modified"] === "undefined") { + return false; + } + return true; + }, + group: opts.group || "nitro/handlers", + integrity: opts.integrity || hash([handler, opts]) + }; + const _cachedHandler = cachedFunction( + async (incomingEvent) => { + const variableHeaders = {}; + for (const header of variableHeaderNames) { + const value = incomingEvent.node.req.headers[header]; + if (value !== void 0) { + variableHeaders[header] = value; + } + } + const reqProxy = cloneWithProxy(incomingEvent.node.req, { + headers: variableHeaders + }); + const resHeaders = {}; + let _resSendBody; + const resProxy = cloneWithProxy(incomingEvent.node.res, { + statusCode: 200, + writableEnded: false, + writableFinished: false, + headersSent: false, + closed: false, + getHeader(name) { + return resHeaders[name]; + }, + setHeader(name, value) { + resHeaders[name] = value; + return this; + }, + getHeaderNames() { + return Object.keys(resHeaders); + }, + hasHeader(name) { + return name in resHeaders; + }, + removeHeader(name) { + delete resHeaders[name]; + }, + getHeaders() { + return resHeaders; + }, + end(chunk, arg2, arg3) { + if (typeof chunk === "string") { + _resSendBody = chunk; + } + if (typeof arg2 === "function") { + arg2(); + } + if (typeof arg3 === "function") { + arg3(); + } + return this; + }, + write(chunk, arg2, arg3) { + if (typeof chunk === "string") { + _resSendBody = chunk; + } + if (typeof arg2 === "function") { + arg2(void 0); + } + if (typeof arg3 === "function") { + arg3(); + } + return true; + }, + writeHead(statusCode, headers2) { + this.statusCode = statusCode; + if (headers2) { + if (Array.isArray(headers2) || typeof headers2 === "string") { + throw new TypeError("Raw headers is not supported."); + } + for (const header in headers2) { + const value = headers2[header]; + if (value !== void 0) { + this.setHeader( + header, + value + ); + } + } + } + return this; + } + }); + const event = createEvent(reqProxy, resProxy); + event.fetch = (url, fetchOptions) => fetchWithEvent(event, url, fetchOptions, { + fetch: useNitroApp().localFetch + }); + event.$fetch = (url, fetchOptions) => fetchWithEvent(event, url, fetchOptions, { + fetch: globalThis.$fetch + }); + event.waitUntil = incomingEvent.waitUntil; + event.context = incomingEvent.context; + event.context.cache = { + options: _opts + }; + const body = await handler(event) || _resSendBody; + const headers = event.node.res.getHeaders(); + headers.etag = String( + headers.Etag || headers.etag || `W/"${hash(body)}"` + ); + headers["last-modified"] = String( + headers["Last-Modified"] || headers["last-modified"] || (/* @__PURE__ */ new Date()).toUTCString() + ); + const cacheControl = []; + if (opts.swr) { + if (opts.maxAge) { + cacheControl.push(`s-maxage=${opts.maxAge}`); + } + if (opts.staleMaxAge) { + cacheControl.push(`stale-while-revalidate=${opts.staleMaxAge}`); + } else { + cacheControl.push("stale-while-revalidate"); + } + } else if (opts.maxAge) { + cacheControl.push(`max-age=${opts.maxAge}`); + } + if (cacheControl.length > 0) { + headers["cache-control"] = cacheControl.join(", "); + } + const cacheEntry = { + code: event.node.res.statusCode, + headers, + body + }; + return cacheEntry; + }, + _opts + ); + return defineEventHandler(async (event) => { + if (opts.headersOnly) { + if (handleCacheHeaders(event, { maxAge: opts.maxAge })) { + return; + } + return handler(event); + } + const response = await _cachedHandler( + event + ); + if (event.node.res.headersSent || event.node.res.writableEnded) { + return response.body; + } + if (handleCacheHeaders(event, { + modifiedTime: new Date(response.headers["last-modified"]), + etag: response.headers.etag, + maxAge: opts.maxAge + })) { + return; + } + event.node.res.statusCode = response.code; + for (const name in response.headers) { + const value = response.headers[name]; + if (name === "set-cookie") { + event.node.res.appendHeader( + name, + splitCookiesString(value) + ); + } else { + if (value !== void 0) { + event.node.res.setHeader(name, value); + } + } + } + return response.body; + }); +} +function cloneWithProxy(obj, overrides) { + return new Proxy(obj, { + get(target, property, receiver) { + if (property in overrides) { + return overrides[property]; + } + return Reflect.get(target, property, receiver); + }, + set(target, property, value, receiver) { + if (property in overrides) { + overrides[property] = value; + return true; + } + return Reflect.set(target, property, value, receiver); + } + }); +} +const cachedEventHandler = defineCachedEventHandler; + +const inlineAppConfig = {}; + + + +const appConfig = defuFn(inlineAppConfig); + +function getEnv(key, opts) { + const envKey = snakeCase(key).toUpperCase(); + return destr( + process.env[opts.prefix + envKey] ?? process.env[opts.altPrefix + envKey] + ); +} +function _isObject(input) { + return typeof input === "object" && !Array.isArray(input); +} +function applyEnv(obj, opts, parentKey = "") { + for (const key in obj) { + const subKey = parentKey ? `${parentKey}_${key}` : key; + const envValue = getEnv(subKey, opts); + if (_isObject(obj[key])) { + if (_isObject(envValue)) { + obj[key] = { ...obj[key], ...envValue }; + applyEnv(obj[key], opts, subKey); + } else if (envValue === void 0) { + applyEnv(obj[key], opts, subKey); + } else { + obj[key] = envValue ?? obj[key]; + } + } else { + obj[key] = envValue ?? obj[key]; + } + if (opts.envExpansion && typeof obj[key] === "string") { + obj[key] = _expandFromEnv(obj[key]); + } + } + return obj; +} +const envExpandRx = /\{\{([^{}]*)\}\}/g; +function _expandFromEnv(value) { + return value.replace(envExpandRx, (match, key) => { + return process.env[key] || match; + }); +} + +const _inlineRuntimeConfig = { + "app": { + "baseURL": "/", + "buildId": "dev", + "buildAssetsDir": "/_nuxt/", + "cdnURL": "" + }, + "nitro": { + "envPrefix": "NUXT_", + "routeRules": { + "/__nuxt_error": { + "cache": false + }, + "/_nuxt/builds/meta/**": { + "headers": { + "cache-control": "public, max-age=31536000, immutable" + } + }, + "/_nuxt/builds/**": { + "headers": { + "cache-control": "public, max-age=1, immutable" + } + } + } + }, + "public": {} +}; +const envOptions = { + prefix: "NITRO_", + altPrefix: _inlineRuntimeConfig.nitro.envPrefix ?? process.env.NITRO_ENV_PREFIX ?? "_", + envExpansion: _inlineRuntimeConfig.nitro.envExpansion ?? process.env.NITRO_ENV_EXPANSION ?? false +}; +const _sharedRuntimeConfig = _deepFreeze( + applyEnv(klona(_inlineRuntimeConfig), envOptions) +); +function useRuntimeConfig(event) { + if (!event) { + return _sharedRuntimeConfig; + } + if (event.context.nitro.runtimeConfig) { + return event.context.nitro.runtimeConfig; + } + const runtimeConfig = klona(_inlineRuntimeConfig); + applyEnv(runtimeConfig, envOptions); + event.context.nitro.runtimeConfig = runtimeConfig; + return runtimeConfig; +} +_deepFreeze(klona(appConfig)); +function _deepFreeze(object) { + const propNames = Object.getOwnPropertyNames(object); + for (const name of propNames) { + const value = object[name]; + if (value && typeof value === "object") { + _deepFreeze(value); + } + } + return Object.freeze(object); +} +new Proxy(/* @__PURE__ */ Object.create(null), { + get: (_, prop) => { + console.warn( + "Please use `useRuntimeConfig()` instead of accessing config directly." + ); + const runtimeConfig = useRuntimeConfig(); + if (prop in runtimeConfig) { + return runtimeConfig[prop]; + } + return void 0; + } +}); + +getContext("nitro-app", { + asyncContext: false, + AsyncLocalStorage: void 0 +}); + +function isPathInScope(pathname, base) { + let canonical; + try { + const pre = pathname.replace(/%2f/gi, "/").replace(/%5c/gi, "\\"); + canonical = new URL(pre, "http://_").pathname; + } catch { + return false; + } + return !base || canonical === base || canonical.startsWith(base + "/"); +} + +const config = useRuntimeConfig(); +const _routeRulesMatcher = toRouteMatcher( + createRouter({ routes: config.nitro.routeRules }) +); +function createRouteRulesHandler(ctx) { + return eventHandler((event) => { + const routeRules = getRouteRules(event); + if (routeRules.headers) { + setHeaders(event, routeRules.headers); + } + if (routeRules.redirect) { + let target = routeRules.redirect.to; + if (target.endsWith("/**")) { + let targetPath = event.path; + const strpBase = routeRules.redirect._redirectStripBase; + if (strpBase) { + if (!isPathInScope(event.path.split("?")[0], strpBase)) { + throw createError({ statusCode: 400 }); + } + targetPath = withoutBase(targetPath, strpBase); + } else if (targetPath.startsWith("//")) { + targetPath = targetPath.replace(/^\/+/, "/"); + } + target = joinURL(target.slice(0, -3), targetPath); + } else if (event.path.includes("?")) { + const query = getQuery(event.path); + target = withQuery(target, query); + } + return sendRedirect(event, target, routeRules.redirect.statusCode); + } + if (routeRules.proxy) { + let target = routeRules.proxy.to; + if (target.endsWith("/**")) { + let targetPath = event.path; + const strpBase = routeRules.proxy._proxyStripBase; + if (strpBase) { + if (!isPathInScope(event.path.split("?")[0], strpBase)) { + throw createError({ statusCode: 400 }); + } + targetPath = withoutBase(targetPath, strpBase); + } else if (targetPath.startsWith("//")) { + targetPath = targetPath.replace(/^\/+/, "/"); + } + target = joinURL(target.slice(0, -3), targetPath); + } else if (event.path.includes("?")) { + const query = getQuery(event.path); + target = withQuery(target, query); + } + return proxyRequest(event, target, { + fetch: ctx.localFetch, + ...routeRules.proxy + }); + } + }); +} +function getRouteRules(event) { + event.context._nitro = event.context._nitro || {}; + if (!event.context._nitro.routeRules) { + event.context._nitro.routeRules = getRouteRulesForPath( + withoutBase(event.path.split("?")[0], useRuntimeConfig().app.baseURL) + ); + } + return event.context._nitro.routeRules; +} +function getRouteRulesForPath(path) { + return defu({}, ..._routeRulesMatcher.matchAll(path).reverse()); +} + +function _captureError(error, type) { + console.error(`[${type}]`, error); + useNitroApp().captureError(error, { tags: [type] }); +} +function trapUnhandledNodeErrors() { + process.on( + "unhandledRejection", + (error) => _captureError(error, "unhandledRejection") + ); + process.on( + "uncaughtException", + (error) => _captureError(error, "uncaughtException") + ); +} +function joinHeaders(value) { + return Array.isArray(value) ? value.join(", ") : String(value); +} +function normalizeFetchResponse(response) { + if (!response.headers.has("set-cookie")) { + return response; + } + return new Response(response.body, { + status: response.status, + statusText: response.statusText, + headers: normalizeCookieHeaders(response.headers) + }); +} +function normalizeCookieHeader(header = "") { + return splitCookiesString(joinHeaders(header)); +} +function normalizeCookieHeaders(headers) { + const outgoingHeaders = new Headers(); + for (const [name, header] of headers) { + if (name === "set-cookie") { + for (const cookie of normalizeCookieHeader(header)) { + outgoingHeaders.append("set-cookie", cookie); + } + } else { + outgoingHeaders.set(name, joinHeaders(header)); + } + } + return outgoingHeaders; +} + +//#region src/runtime/utils/error.ts +/** +* Nitro internal functions extracted from https://github.com/nitrojs/nitro/blob/v2/src/runtime/internal/utils.ts +*/ +function isJsonRequest(event) { + if (hasReqHeader(event, "accept", "text/html")) return false; + return hasReqHeader(event, "accept", "application/json") || hasReqHeader(event, "user-agent", "curl/") || hasReqHeader(event, "user-agent", "httpie/") || hasReqHeader(event, "sec-fetch-mode", "cors") || event.path.startsWith("/api/") || event.path.endsWith(".json"); +} +function hasReqHeader(event, name, includes) { + const value = getRequestHeader(event, name); + return !!(value && typeof value === "string" && value.toLowerCase().includes(includes)); +} + +//#region src/runtime/utils/dev.ts +const iframeStorageBridge = (nonce) => ` +(function () { + const NONCE = ${JSON.stringify(nonce)}; + const memoryStore = Object.create(null); + + const post = (type, payload) => { + window.parent.postMessage({ type, nonce: NONCE, ...payload }, '*'); + }; + + const isValid = (data) => data && data.nonce === NONCE; + + const mockStorage = { + getItem(key) { + return Object.hasOwn(memoryStore, key) + ? memoryStore[key] + : null; + }, + setItem(key, value) { + const v = String(value); + memoryStore[key] = v; + post('storage-set', { key, value: v }); + }, + removeItem(key) { + delete memoryStore[key]; + post('storage-remove', { key }); + }, + clear() { + for (const key of Object.keys(memoryStore)) + delete memoryStore[key]; + post('storage-clear', {}); + }, + key(index) { + const keys = Object.keys(memoryStore); + return keys[index] ?? null; + }, + get length() { + return Object.keys(memoryStore).length; + } + }; + + const defineLocalStorage = () => { + try { + Object.defineProperty(window, 'localStorage', { + value: mockStorage, + writable: false, + configurable: true + }); + } catch { + window.localStorage = mockStorage; + } + }; + + defineLocalStorage(); + + window.addEventListener('message', (event) => { + const data = event.data; + if (!isValid(data) || data.type !== 'storage-sync-data') return; + + const incoming = data.data || {}; + for (const key of Object.keys(incoming)) + memoryStore[key] = incoming[key]; + + if (typeof window.initTheme === 'function') + window.initTheme(); + window.dispatchEvent(new Event('storage-ready')); + }); + + // Clipboard API is unavailable in data: URL iframe, so we use postMessage + document.addEventListener('DOMContentLoaded', function() { + window.copyErrorMessage = function(button) { + post('clipboard-copy', { text: button.dataset.errorText }); + button.classList.add('copied'); + setTimeout(function() { button.classList.remove('copied'); }, 2000); + }; + }); + + post('storage-sync-request', {}); +})(); +`; +const parentStorageBridge = (nonce) => ` +(function () { + const host = document.querySelector('nuxt-error-overlay'); + if (!host) return; + + const NONCE = ${JSON.stringify(nonce)}; + const isValid = (data) => data && data.nonce === NONCE; + + // Handle clipboard copy from iframe + window.addEventListener('message', function(e) { + if (isValid(e.data) && e.data.type === 'clipboard-copy') { + navigator.clipboard.writeText(e.data.text).catch(function() {}); + } + }); + + const collectLocalStorage = () => { + const all = {}; + for (let i = 0; i < localStorage.length; i++) { + const k = localStorage.key(i); + if (k != null) all[k] = localStorage.getItem(k); + } + return all; + }; + + const attachWhenReady = () => { + const root = host.shadowRoot; + if (!root) + return false; + const iframe = root.getElementById('frame'); + if (!iframe || !iframe.contentWindow) + return false; + + const handlers = { + 'storage-set': (d) => localStorage.setItem(d.key, d.value), + 'storage-remove': (d) => localStorage.removeItem(d.key), + 'storage-clear': () => localStorage.clear(), + 'storage-sync-request': () => { + iframe.contentWindow.postMessage({ + type: 'storage-sync-data', + data: collectLocalStorage(), + nonce: NONCE + }, '*'); + } + }; + + window.addEventListener('message', (event) => { + const data = event.data; + if (!isValid(data)) return; + const fn = handlers[data.type]; + if (fn) fn(data); + }); + + return true; + }; + + if (attachWhenReady()) + return; + + const obs = new MutationObserver(() => { + if (attachWhenReady()) + obs.disconnect(); + }); + + obs.observe(host, { childList: true, subtree: true }); +})(); +`; +const errorCSS = ` +:host { + --preview-width: 240px; + --preview-height: 180px; + --base-width: 1200px; + --base-height: 900px; + --z-base: 999999998; + --error-pip-left: auto; + --error-pip-top: auto; + --error-pip-right: 5px; + --error-pip-bottom: 5px; + --error-pip-origin: bottom right; + --app-preview-left: auto; + --app-preview-top: auto; + --app-preview-right: 5px; + --app-preview-bottom: 5px; + all: initial; + display: contents; +} +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; +} +#frame { + position: fixed; + left: 0; + top: 0; + width: 100vw; + height: 100vh; + border: none; + z-index: var(--z-base); +} +#frame[inert] { + left: var(--error-pip-left); + top: var(--error-pip-top); + right: var(--error-pip-right); + bottom: var(--error-pip-bottom); + width: var(--base-width); + height: var(--base-height); + transform: scale(calc(240 / 1200)); + transform-origin: var(--error-pip-origin); + overflow: hidden; + border-radius: calc(1200 * 8px / 240); +} +#preview { + position: fixed; + left: var(--app-preview-left); + top: var(--app-preview-top); + right: var(--app-preview-right); + bottom: var(--app-preview-bottom); + width: var(--preview-width); + height: var(--preview-height); + overflow: hidden; + border-radius: 6px; + pointer-events: none; + z-index: var(--z-base); + background: white; + display: none; +} +#preview iframe { + transform-origin: var(--error-pip-origin); +} +#frame:not([inert]) + #preview { + display: block; +} +#toggle { + position: fixed; + left: var(--app-preview-left); + top: var(--app-preview-top); + right: calc(var(--app-preview-right) - 3px); + bottom: calc(var(--app-preview-bottom) - 3px); + width: var(--preview-width); + height: var(--preview-height); + background: none; + border: 3px solid #00DC82; + border-radius: 8px; + cursor: pointer; + opacity: 0.8; + transition: opacity 0.2s, box-shadow 0.2s; + z-index: calc(var(--z-base) + 1); + display: flex; + align-items: center; + justify-content: center; +} +#toggle:hover, +#toggle:focus { + opacity: 1; + box-shadow: 0 0 20px rgba(0, 220, 130, 0.6); +} +#toggle:focus-visible { + outline: 3px solid #00DC82; + outline-offset: 0; + box-shadow: 0 0 24px rgba(0, 220, 130, 0.8); +} +#frame[inert] ~ #toggle { + left: var(--error-pip-left); + top: var(--error-pip-top); + right: calc(var(--error-pip-right) - 3px); + bottom: calc(var(--error-pip-bottom) - 3px); + cursor: grab; +} +:host(.dragging) #frame[inert] ~ #toggle { + cursor: grabbing; +} +#frame:not([inert]) ~ #toggle, +#frame:not([inert]) + #preview { + cursor: grab; +} +:host(.dragging-preview) #frame:not([inert]) ~ #toggle, +:host(.dragging-preview) #frame:not([inert]) + #preview { + cursor: grabbing; +} + +#pip-close { + position: absolute; + top: 6px; + right: 6px; + width: 24px; + height: 24px; + border-radius: 50%; + border: none; + background: rgba(0, 0, 0, 0.75); + color: #fff; + font-size: 16px; + line-height: 1; + display: inline-flex; + align-items: center; + justify-content: center; + cursor: pointer; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); + pointer-events: auto; +} +#pip-close:focus-visible { + outline: 2px solid #00DC82; + outline-offset: 2px; +} + +#pip-restore { + position: fixed; + right: 16px; + bottom: 16px; + padding: 8px 14px; + border-radius: 999px; + border: 2px solid #00DC82; + background: #111; + color: #fff; + font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif; + font-size: 14px; + display: inline-flex; + align-items: center; + gap: 6px; + z-index: calc(var(--z-base) + 2); + cursor: grab; +} +#pip-restore:focus-visible { + outline: 2px solid #00DC82; + outline-offset: 2px; +} +:host(.dragging-restore) #pip-restore { + cursor: grabbing; +} + +#frame[hidden], +#toggle[hidden], +#preview[hidden], +#pip-restore[hidden], +#pip-close[hidden] { + display: none !important; +} + +@media (prefers-reduced-motion: reduce) { + #toggle { + transition: none; + } +} +`; +function webComponentScript(base64HTML, startMinimized) { + return ` +(function () { + try { + // ========================= + // Host + Shadow + // ========================= + const host = document.querySelector('nuxt-error-overlay'); + if (!host) + return; + const shadow = host.attachShadow({ mode: 'open' }); + + // ========================= + // DOM helpers + // ========================= + const el = (tag) => document.createElement(tag); + const on = (node, type, fn, opts) => node.addEventListener(type, fn, opts); + const hide = (node, v) => node.toggleAttribute('hidden', !!v); + const setVar = (name, value) => host.style.setProperty(name, value); + const unsetVar = (name) => host.style.removeProperty(name); + + // ========================= + // Create DOM + // ========================= + const style = el('style'); + style.textContent = ${JSON.stringify(errorCSS)}; + + const iframe = el('iframe'); + iframe.id = 'frame'; + iframe.src = 'data:text/html;base64,${base64HTML}'; + iframe.title = 'Detailed error stack trace'; + iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin allow-top-navigation-by-user-activation'); + + const preview = el('div'); + preview.id = 'preview'; + + const toggle = el('div'); + toggle.id = 'toggle'; + toggle.setAttribute('aria-expanded', 'true'); + toggle.setAttribute('role', 'button'); + toggle.setAttribute('tabindex', '0'); + toggle.innerHTML = 'Toggle detailed error view'; + + const liveRegion = el('div'); + liveRegion.setAttribute('role', 'status'); + liveRegion.setAttribute('aria-live', 'polite'); + liveRegion.className = 'sr-only'; + + const pipCloseButton = el('button'); + pipCloseButton.id = 'pip-close'; + pipCloseButton.setAttribute('type', 'button'); + pipCloseButton.setAttribute('aria-label', 'Hide error preview overlay'); + pipCloseButton.innerHTML = '×'; + pipCloseButton.hidden = true; + toggle.appendChild(pipCloseButton); + + const pipRestoreButton = el('button'); + pipRestoreButton.id = 'pip-restore'; + pipRestoreButton.setAttribute('type', 'button'); + pipRestoreButton.setAttribute('aria-label', 'Show error overlay'); + pipRestoreButton.innerHTML = 'Show error overlay'; + pipRestoreButton.hidden = true; + + // Order matters: #frame + #preview adjacency + shadow.appendChild(style); + shadow.appendChild(liveRegion); + shadow.appendChild(iframe); + shadow.appendChild(preview); + shadow.appendChild(toggle); + shadow.appendChild(pipRestoreButton); + + // ========================= + // Constants / keys + // ========================= + const POS_KEYS = { + position: 'nuxt-error-overlay:position', + hiddenPretty: 'nuxt-error-overlay:error-pip:hidden', + hiddenPreview: 'nuxt-error-overlay:app-preview:hidden' + }; + + const CSS_VARS = { + pip: { + left: '--error-pip-left', + top: '--error-pip-top', + right: '--error-pip-right', + bottom: '--error-pip-bottom' + }, + preview: { + left: '--app-preview-left', + top: '--app-preview-top', + right: '--app-preview-right', + bottom: '--app-preview-bottom' + } + }; + + const MIN_GAP = 5; + const DRAG_THRESHOLD = 2; + + // ========================= + // Local storage safe access + state + // ========================= + let storageReady = true; + let isPrettyHidden = false; + let isPreviewHidden = false; + + const safeGet = (k) => { + try { + return localStorage.getItem(k); + } catch { + return null; + } + }; + + const safeSet = (k, v) => { + if (!storageReady) + return; + try { + localStorage.setItem(k, v); + } catch {} + }; + + // ========================= + // Sizing helpers + // ========================= + const vvSize = () => { + const v = window.visualViewport; + return v ? { w: v.width, h: v.height } : { w: window.innerWidth, h: window.innerHeight }; + }; + + const previewSize = () => { + const styles = getComputedStyle(host); + const w = parseFloat(styles.getPropertyValue('--preview-width')) || 240; + const h = parseFloat(styles.getPropertyValue('--preview-height')) || 180; + return { w, h }; + }; + + const sizeForTarget = (target) => { + if (!target) + return previewSize(); + const rect = target.getBoundingClientRect(); + if (rect.width && rect.height) + return { w: rect.width, h: rect.height }; + return previewSize(); + }; + + // ========================= + // Dock model + offset/alignment calculations + // ========================= + const dock = { edge: null, offset: null, align: null, gap: null }; + + const maxOffsetFor = (edge, size) => { + const vv = vvSize(); + if (edge === 'left' || edge === 'right') + return Math.max(MIN_GAP, vv.h - size.h - MIN_GAP); + return Math.max(MIN_GAP, vv.w - size.w - MIN_GAP); + }; + + const clampOffset = (edge, value, size) => { + const max = maxOffsetFor(edge, size); + return Math.min(Math.max(value, MIN_GAP), max); + }; + + const updateDockAlignment = (size) => { + if (!dock.edge || dock.offset == null) + return; + const max = maxOffsetFor(dock.edge, size); + if (dock.offset <= max / 2) { + dock.align = 'start'; + dock.gap = dock.offset; + } else { + dock.align = 'end'; + dock.gap = Math.max(0, max - dock.offset); + } + }; + + const appliedOffsetFor = (size) => { + if (!dock.edge || dock.offset == null) + return null; + const max = maxOffsetFor(dock.edge, size); + + if (dock.align === 'end' && typeof dock.gap === 'number') { + return clampOffset(dock.edge, max - dock.gap, size); + } + if (dock.align === 'start' && typeof dock.gap === 'number') { + return clampOffset(dock.edge, dock.gap, size); + } + return clampOffset(dock.edge, dock.offset, size); + }; + + const nearestEdgeAt = (x, y) => { + const { w, h } = vvSize(); + const d = { left: x, right: w - x, top: y, bottom: h - y }; + return Object.keys(d).reduce((a, b) => (d[a] < d[b] ? a : b)); + }; + + const cornerDefaultDock = () => { + const vv = vvSize(); + const size = previewSize(); + const offset = Math.max(MIN_GAP, vv.w - size.w - MIN_GAP); + return { edge: 'bottom', offset }; + }; + + const currentTransformOrigin = () => { + if (!dock.edge) return null; + if (dock.edge === 'left' || dock.edge === 'top') + return 'top left'; + if (dock.edge === 'right') + return 'top right'; + return 'bottom left'; + }; + + // ========================= + // Persist / load dock + // ========================= + const loadDock = () => { + const raw = safeGet(POS_KEYS.position); + if (!raw) + return; + try { + const parsed = JSON.parse(raw); + const { edge, offset, align, gap } = parsed || {}; + if (!['left', 'right', 'top', 'bottom'].includes(edge)) + return; + if (typeof offset !== 'number') + return; + + dock.edge = edge; + dock.offset = clampOffset(edge, offset, previewSize()); + dock.align = align === 'start' || align === 'end' ? align : null; + dock.gap = typeof gap === 'number' ? gap : null; + + if (!dock.align || dock.gap == null) + updateDockAlignment(previewSize()); + } catch {} + }; + + const persistDock = () => { + if (!dock.edge || dock.offset == null) + return; + safeSet(POS_KEYS.position, JSON.stringify({ + edge: dock.edge, + offset: dock.offset, + align: dock.align, + gap: dock.gap + })); + }; + + // ========================= + // Apply dock + // ========================= + const dockToVars = (vars) => ({ + set: (side, v) => host.style.setProperty(vars[side], v), + clear: (side) => host.style.removeProperty(vars[side]) + }); + + const dockToEl = (node) => ({ + set: (side, v) => { node.style[side] = v; }, + clear: (side) => { node.style[side] = ''; } + }); + + const applyDock = (target, size, opts) => { + if (!dock.edge || dock.offset == null) { + target.clear('left'); + target.clear('top'); + target.clear('right'); + target.clear('bottom'); + return; + } + + target.set('left', 'auto'); + target.set('top', 'auto'); + target.set('right', 'auto'); + target.set('bottom', 'auto'); + + const applied = appliedOffsetFor(size); + + if (dock.edge === 'left') { + target.set('left', MIN_GAP + 'px'); + target.set('top', applied + 'px'); + } else if (dock.edge === 'right') { + target.set('right', MIN_GAP + 'px'); + target.set('top', applied + 'px'); + } else if (dock.edge === 'top') { + target.set('top', MIN_GAP + 'px'); + target.set('left', applied + 'px'); + } else { + target.set('bottom', MIN_GAP + 'px'); + target.set('left', applied + 'px'); + } + + if (!opts || opts.persist !== false) + persistDock(); + }; + + const applyDockAll = (opts) => { + applyDock(dockToVars(CSS_VARS.pip), previewSize(), opts); + applyDock(dockToVars(CSS_VARS.preview), previewSize(), opts); + applyDock(dockToEl(pipRestoreButton), sizeForTarget(pipRestoreButton), opts); + }; + + const repaintToDock = () => { + if (!dock.edge || dock.offset == null) + return; + const origin = currentTransformOrigin(); + if (origin) + setVar('--error-pip-origin', origin); + else + unsetVar('--error-pip-origin'); + applyDockAll({ persist: false }); + }; + + // ========================= + // Hidden state + UI + // ========================= + const loadHidden = () => { + const rawPretty = safeGet(POS_KEYS.hiddenPretty); + if (rawPretty != null) + isPrettyHidden = rawPretty === '1' || rawPretty === 'true'; + const rawPreview = safeGet(POS_KEYS.hiddenPreview); + if (rawPreview != null) + isPreviewHidden = rawPreview === '1' || rawPreview === 'true'; + }; + + const setPrettyHidden = (v) => { + isPrettyHidden = !!v; + safeSet(POS_KEYS.hiddenPretty, isPrettyHidden ? '1' : '0'); + updateUI(); + }; + + const setPreviewHidden = (v) => { + isPreviewHidden = !!v; + safeSet(POS_KEYS.hiddenPreview, isPreviewHidden ? '1' : '0'); + updateUI(); + }; + + const isMinimized = () => iframe.hasAttribute('inert'); + + const setMinimized = (v) => { + if (v) { + iframe.setAttribute('inert', ''); + toggle.setAttribute('aria-expanded', 'false'); + } else { + iframe.removeAttribute('inert'); + toggle.setAttribute('aria-expanded', 'true'); + } + }; + + const setRestoreLabel = (kind) => { + if (kind === 'pretty') { + pipRestoreButton.innerHTML = 'Show error overlay'; + pipRestoreButton.setAttribute('aria-label', 'Show error overlay'); + } else { + pipRestoreButton.innerHTML = 'Show error page'; + pipRestoreButton.setAttribute('aria-label', 'Show error page'); + } + }; + + const updateUI = () => { + const minimized = isMinimized(); + const showPiP = minimized && !isPrettyHidden; + const showPreview = !minimized && !isPreviewHidden; + const pipHiddenByUser = minimized && isPrettyHidden; + const previewHiddenByUser = !minimized && isPreviewHidden; + const showToggle = minimized ? showPiP : showPreview; + const showRestore = pipHiddenByUser || previewHiddenByUser; + + hide(iframe, pipHiddenByUser); + hide(preview, !showPreview); + hide(toggle, !showToggle); + hide(pipCloseButton, !showToggle); + hide(pipRestoreButton, !showRestore); + + pipCloseButton.setAttribute('aria-label', minimized ? 'Hide error overlay' : 'Hide error page preview'); + + if (pipHiddenByUser) + setRestoreLabel('pretty'); + else if (previewHiddenByUser) + setRestoreLabel('preview'); + + host.classList.toggle('pip-hidden', isPrettyHidden); + host.classList.toggle('preview-hidden', isPreviewHidden); + }; + + // ========================= + // Preview snapshot + // ========================= + const updatePreview = () => { + try { + let previewIframe = preview.querySelector('iframe'); + if (!previewIframe) { + previewIframe = el('iframe'); + previewIframe.style.cssText = 'width: 1200px; height: 900px; transform: scale(0.2); transform-origin: top left; border: none;'; + previewIframe.setAttribute('sandbox', 'allow-scripts allow-same-origin'); + preview.appendChild(previewIframe); + } + + const doctype = document.doctype ? '' : ''; + const cleanedHTML = document.documentElement.outerHTML + .replace(/]*>.*?<\\/nuxt-error-overlay>/gs, '') + .replace(/]*>.*?<\\/script>/gs, ''); + + const iframeDoc = previewIframe.contentDocument || previewIframe.contentWindow.document; + iframeDoc.open(); + iframeDoc.write(doctype + cleanedHTML); + iframeDoc.close(); + } catch (err) { + console.error('Failed to update preview:', err); + } + }; + + // ========================= + // View toggling + // ========================= + const toggleView = () => { + if (isMinimized()) { + updatePreview(); + setMinimized(false); + liveRegion.textContent = 'Showing detailed error view'; + setTimeout(() => { + try { + iframe.contentWindow.focus(); + } catch {} + }, 100); + } else { + setMinimized(true); + liveRegion.textContent = 'Showing error page'; + repaintToDock(); + void iframe.offsetWidth; + } + updateUI(); + }; + + // ========================= + // Dragging (unified, rAF throttled) + // ========================= + let drag = null; + let rafId = null; + let suppressToggleClick = false; + let suppressRestoreClick = false; + + const beginDrag = (e) => { + if (drag) + return; + + if (!dock.edge || dock.offset == null) { + const def = cornerDefaultDock(); + dock.edge = def.edge; + dock.offset = def.offset; + updateDockAlignment(previewSize()); + } + + const isRestoreTarget = e.currentTarget === pipRestoreButton; + + drag = { + kind: isRestoreTarget ? 'restore' : (isMinimized() ? 'pip' : 'preview'), + pointerId: e.pointerId, + startX: e.clientX, + startY: e.clientY, + lastX: e.clientX, + lastY: e.clientY, + moved: false, + target: e.currentTarget + }; + + drag.target.setPointerCapture(e.pointerId); + + if (drag.kind === 'restore') + host.classList.add('dragging-restore'); + else + host.classList.add(drag.kind === 'pip' ? 'dragging' : 'dragging-preview'); + + e.preventDefault(); + }; + + const moveDrag = (e) => { + if (!drag || drag.pointerId !== e.pointerId) + return; + + drag.lastX = e.clientX; + drag.lastY = e.clientY; + + const dx = drag.lastX - drag.startX; + const dy = drag.lastY - drag.startY; + + if (!drag.moved && (Math.abs(dx) > DRAG_THRESHOLD || Math.abs(dy) > DRAG_THRESHOLD)) { + drag.moved = true; + } + + if (!drag.moved) + return; + if (rafId) + return; + + rafId = requestAnimationFrame(() => { + rafId = null; + + const edge = nearestEdgeAt(drag.lastX, drag.lastY); + const size = sizeForTarget(drag.target); + + let offset; + if (edge === 'left' || edge === 'right') { + const top = drag.lastY - (size.h / 2); + offset = clampOffset(edge, Math.round(top), size); + } else { + const left = drag.lastX - (size.w / 2); + offset = clampOffset(edge, Math.round(left), size); + } + + dock.edge = edge; + dock.offset = offset; + updateDockAlignment(size); + + const origin = currentTransformOrigin(); + setVar('--error-pip-origin', origin || 'bottom right'); + + applyDockAll({ persist: false }); + }); + }; + + const endDrag = (e) => { + if (!drag || drag.pointerId !== e.pointerId) + return; + + const endedKind = drag.kind; + drag.target.releasePointerCapture(e.pointerId); + + if (endedKind === 'restore') + host.classList.remove('dragging-restore'); + else + host.classList.remove(endedKind === 'pip' ? 'dragging' : 'dragging-preview'); + + const didMove = drag.moved; + drag = null; + + if (didMove) { + persistDock(); + if (endedKind === 'restore') + suppressRestoreClick = true; + else + suppressToggleClick = true; + e.preventDefault(); + e.stopPropagation(); + } + }; + + const bindDragTarget = (node) => { + on(node, 'pointerdown', beginDrag); + on(node, 'pointermove', moveDrag); + on(node, 'pointerup', endDrag); + on(node, 'pointercancel', endDrag); + }; + + bindDragTarget(toggle); + bindDragTarget(pipRestoreButton); + + // ========================= + // Events (toggle / close / restore) + // ========================= + on(toggle, 'click', (e) => { + if (suppressToggleClick) { + e.preventDefault(); + suppressToggleClick = false; + return; + } + toggleView(); + }); + + on(toggle, 'keydown', (e) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + toggleView(); + } + }); + + on(pipCloseButton, 'click', (e) => { + e.preventDefault(); + e.stopPropagation(); + if (isMinimized()) + setPrettyHidden(true); + else + setPreviewHidden(true); + }); + + on(pipCloseButton, 'pointerdown', (e) => { + e.stopPropagation(); + }); + + on(pipRestoreButton, 'click', (e) => { + if (suppressRestoreClick) { + e.preventDefault(); + suppressRestoreClick = false; + return; + } + e.preventDefault(); + e.stopPropagation(); + if (isMinimized()) + setPrettyHidden(false); + else + setPreviewHidden(false); + }); + + // ========================= + // Lifecycle: load / sync / repaint + // ========================= + const loadState = () => { + loadDock(); + loadHidden(); + + if (isPrettyHidden && !isMinimized()) + setMinimized(true); + + updateUI(); + repaintToDock(); + }; + + loadState(); + + on(window, 'storage-ready', () => { + storageReady = true; + loadState(); + }); + + const onViewportChange = () => repaintToDock(); + + on(window, 'resize', onViewportChange); + + if (window.visualViewport) { + on(window.visualViewport, 'resize', onViewportChange); + on(window.visualViewport, 'scroll', onViewportChange); + } + + // initial preview + setTimeout(updatePreview, 100); + + // initial minimized option + if (${startMinimized}) { + setMinimized(true); + repaintToDock(); + void iframe.offsetWidth; + updateUI(); + } + } catch (err) { + console.error('Failed to initialize Nuxt error overlay:', err); + } +})(); +`; +} +function generateErrorOverlayHTML(html, options) { + const nonce = Array.from(crypto.getRandomValues(/* @__PURE__ */ new Uint8Array(16)), (b) => b.toString(16).padStart(2, "0")).join(""); + const errorPage = html.replace("", `