From a2330b22e2c0725b63970a2232dbf29189362cb9 Mon Sep 17 00:00:00 2001 From: Codex Bot Date: Sun, 25 Oct 2026 21:13:43 +0800 Subject: [PATCH] Restructure into Wiki, Studio and Python monorepo with scoped CI --- .dockerignore | 9 +- .gitea/workflows/ci.yml | 72 - .gitea/workflows/python.yml | 26 + .gitea/workflows/studio.yml | 28 + .gitea/workflows/wiki.yml | 43 + .gitignore | 4 + Dockerfile | 15 +- README.md | 131 +- apps/python/Dockerfile | 8 + apps/python/pyproject.toml | 12 + apps/python/src/prompt_tools/__init__.py | 0 apps/python/src/prompt_tools/export.py | 70 + apps/python/tests/test_export.py | 13 + apps/studio/Dockerfile | 15 + next-env.d.ts => apps/studio/next-env.d.ts | 0 apps/studio/next.config.ts | 3 + apps/studio/package.json | 25 + apps/studio/pnpm-lock.yaml | 1030 ++++++ .../studio/postcss.config.mjs | 0 apps/studio/src/content/ideas.ts | 3 + apps/studio/src/pages/_app.tsx | 3 + apps/studio/src/pages/api/export/[slug].ts | 3 + apps/studio/src/pages/api/index.ts | 3 + apps/studio/src/pages/ideas/[slug].tsx | 7 + apps/studio/src/pages/index.tsx | 3 + apps/studio/src/styles/globals.css | 2 + tsconfig.json => apps/studio/tsconfig.json | 0 .env.example => apps/wiki/.env.example | 0 apps/wiki/Dockerfile | 33 + {db => apps/wiki/db}/001_library.sql | 0 {db => apps/wiki/db}/002_page_snapshots.sql | 0 apps/wiki/next-env.d.ts | 7 + next.config.ts => apps/wiki/next.config.ts | 2 +- apps/wiki/package.json | 45 + apps/wiki/pnpm-lock.yaml | 1826 +++++++++++ apps/wiki/postcss.config.mjs | 3 + {public => apps/wiki/public}/brand-mark.svg | 0 .../wiki/public}/learning-skills/cover.png | Bin .../wiki/public}/learning-skills/cover.svg | 0 {public => apps/wiki/public}/llms.txt | 0 .../skills/shadow-puppet/dancer-example.png | Bin .../skills/shadow-puppet/egret-example.png | Bin .../skills/street-people/reference.png | Bin .../public}/skills/street-people/sample.png | Bin {scripts => apps/wiki/scripts}/bootstrap.ts | 0 .../wiki/scripts}/container-health.mjs | 0 .../wiki/scripts}/import-character-packs.mjs | 0 .../wiki/scripts}/prepare-standalone.mjs | 0 .../wiki/scripts}/publish-learning-series.ts | 0 {scripts => apps/wiki/scripts}/smoke.mjs | 0 .../wiki/scripts}/wait-snapshots.mjs | 0 .../wiki/seed}/characters/extraction.json | 0 .../seed}/characters/original/01-florist.png | Bin .../seed}/characters/original/02-reader.png | Bin .../seed}/characters/original/03-cyclist.png | Bin .../seed}/characters/original/04-coffee.png | Bin .../wiki/seed}/characters/packs.json | 0 .../wiki/seed}/characters/prompts.json | 0 .../seed}/characters/reference/01-basket.png | Bin .../seed}/characters/reference/02-phone.png | Bin .../seed}/characters/reference/03-coffee.png | Bin .../characters/reference/04-red-coat.png | Bin .../characters/reference/05-blue-dogs.png | Bin .../characters/reference/06-dark-dog.png | Bin .../seed}/characters/reference/07-pockets.png | Bin .../characters/reference/08-blue-board.png | Bin .../characters/reference/09-scarf-dog.png | Bin .../seed}/characters/reference/10-elder.png | Bin .../characters/reference/11-long-coat.png | Bin .../seed}/characters/reference/12-trolley.png | Bin .../seed}/characters/reference/13-bucket.png | Bin .../seed}/characters/reference/14-curly.png | Bin .../characters/reference/15-red-walk.png | Bin .../wiki/src}/components/ArticleGallery.tsx | 0 {src => apps/wiki/src}/components/Feed.tsx | 0 .../wiki/src}/components/GuidanceIndex.tsx | 0 {src => apps/wiki/src}/components/Shell.tsx | 4 +- .../wiki/src}/components/SkillCard.tsx | 0 .../wiki/src}/components/SkillDocs.tsx | 0 .../src}/content/learning-skills/Series.tsx | 0 .../src}/content/learning-skills/cover.ts | 0 .../wiki/src}/content/learning-skills/data.ts | 0 {src => apps/wiki/src}/content/registry.tsx | 0 .../wiki/src}/content/skills/catalog.ts | 0 .../wiki/src}/content/skills/guidance.ts | 0 .../wiki/src}/content/skills/shadow-puppet.ts | 0 apps/wiki/src/content/wiki.ts | 11 + {src => apps/wiki/src}/lib/api.ts | 0 {src => apps/wiki/src}/lib/character-image.ts | 0 {src => apps/wiki/src}/lib/db.ts | 0 {src => apps/wiki/src}/lib/health.ts | 0 {src => apps/wiki/src}/lib/library.ts | 0 .../wiki/src}/lib/markdown-response.ts | 0 {src => apps/wiki/src}/lib/model.ts | 0 {src => apps/wiki/src}/lib/probe.ts | 0 .../wiki/src}/lib/publish-learning-series.ts | 0 {src => apps/wiki/src}/lib/snapshots.ts | 0 {src => apps/wiki/src}/lib/storage.ts | 0 {src => apps/wiki/src}/lib/street-people.ts | 0 {src => apps/wiki/src}/lib/write.ts | 0 .../src}/pages/[section]/[[...taxonomy]].tsx | 0 {src => apps/wiki/src}/pages/_app.tsx | 0 .../wiki/src}/pages/api/agent-index.ts | 0 {src => apps/wiki/src}/pages/api/feed.ts | 0 .../src}/pages/api/guidance/[[...path]].ts | 0 {src => apps/wiki/src}/pages/api/health.ts | 0 .../wiki/src}/pages/api/media/[id].ts | 0 .../src}/pages/api/posts/[slug]/snapshots.ts | 0 .../wiki/src}/pages/api/posts/index.ts | 0 {src => apps/wiki/src}/pages/api/ready.ts | 0 .../pages/api/skill-docs/[skill]/[doc].ts | 0 .../api/skill-docs/street-people/[doc].ts | 0 .../src}/pages/api/skills/street-people.ts | 0 {src => apps/wiki/src}/pages/api/tags.ts | 0 {src => apps/wiki/src}/pages/api/upload.ts | 0 apps/wiki/src/pages/api/wiki-index.ts | 3 + apps/wiki/src/pages/api/wiki-post/[slug].ts | 3 + apps/wiki/src/pages/api/wiki/[key].ts | 4 + apps/wiki/src/pages/index.tsx | 7 + .../wiki/src}/pages/library/import.tsx | 0 {src => apps/wiki/src}/pages/p/[slug].tsx | 2 +- .../wiki/src}/pages/p/[slug]/pages/[page].tsx | 0 .../wiki/src}/pages/skills/[[...path]].tsx | 0 {src => apps/wiki/src}/pages/tools/doodle.tsx | 0 .../pages/tools/skills/[skill]/[[...doc]].tsx | 0 .../wiki/src}/pages/tools/skills/index.tsx | 0 .../src}/pages/tools/skills/street-people.tsx | 0 .../tools/skills/street-people/[doc].tsx | 0 apps/wiki/src/pages/wiki/[key].tsx | 10 + {src => apps/wiki/src}/styles/globals.css | 3 + .../wiki/src}/styles/learning-series.css | 0 {src => apps/wiki/src}/styles/skill-docs.css | 0 {src => apps/wiki/src}/worker.ts | 0 {tests => apps/wiki/tests}/health.test.ts | 0 .../wiki/tests}/integration.test.ts | 0 .../wiki/tests}/learning-series.test.ts | 0 {tests => apps/wiki/tests}/model.test.ts | 0 {tests => apps/wiki/tests}/skill-docs.test.ts | 0 apps/wiki/tests/wiki.test.ts | 5 + apps/wiki/tsconfig.json | 21 + docs/monorepo.md | 17 + docs/stage-files.md | 153 + package-lock.json | 2871 ----------------- package.json | 46 +- pnpm-lock.yaml | 9 + pnpm-workspace.yaml | 8 + scripts/deploy-python.sh | 7 + scripts/deploy-studio.sh | 21 + scripts/deploy-web.sh | 92 - scripts/release-mode.sh | 20 - src/pages/index.tsx | 8 - tests/release-mode.sh | 43 - 152 files changed, 3525 insertions(+), 3287 deletions(-) delete mode 100644 .gitea/workflows/ci.yml create mode 100644 .gitea/workflows/python.yml create mode 100644 .gitea/workflows/studio.yml create mode 100644 .gitea/workflows/wiki.yml create mode 100644 apps/python/Dockerfile create mode 100644 apps/python/pyproject.toml create mode 100644 apps/python/src/prompt_tools/__init__.py create mode 100644 apps/python/src/prompt_tools/export.py create mode 100644 apps/python/tests/test_export.py create mode 100644 apps/studio/Dockerfile rename next-env.d.ts => apps/studio/next-env.d.ts (100%) create mode 100644 apps/studio/next.config.ts create mode 100644 apps/studio/package.json create mode 100644 apps/studio/pnpm-lock.yaml rename postcss.config.mjs => apps/studio/postcss.config.mjs (100%) create mode 100644 apps/studio/src/content/ideas.ts create mode 100644 apps/studio/src/pages/_app.tsx create mode 100644 apps/studio/src/pages/api/export/[slug].ts create mode 100644 apps/studio/src/pages/api/index.ts create mode 100644 apps/studio/src/pages/ideas/[slug].tsx create mode 100644 apps/studio/src/pages/index.tsx create mode 100644 apps/studio/src/styles/globals.css rename tsconfig.json => apps/studio/tsconfig.json (100%) rename .env.example => apps/wiki/.env.example (100%) create mode 100644 apps/wiki/Dockerfile rename {db => apps/wiki/db}/001_library.sql (100%) rename {db => apps/wiki/db}/002_page_snapshots.sql (100%) create mode 100644 apps/wiki/next-env.d.ts rename next.config.ts => apps/wiki/next.config.ts (91%) create mode 100644 apps/wiki/package.json create mode 100644 apps/wiki/pnpm-lock.yaml create mode 100644 apps/wiki/postcss.config.mjs rename {public => apps/wiki/public}/brand-mark.svg (100%) rename {public => apps/wiki/public}/learning-skills/cover.png (100%) rename {public => apps/wiki/public}/learning-skills/cover.svg (100%) rename {public => apps/wiki/public}/llms.txt (100%) rename {public => apps/wiki/public}/skills/shadow-puppet/dancer-example.png (100%) rename {public => apps/wiki/public}/skills/shadow-puppet/egret-example.png (100%) rename {public => apps/wiki/public}/skills/street-people/reference.png (100%) rename {public => apps/wiki/public}/skills/street-people/sample.png (100%) rename {scripts => apps/wiki/scripts}/bootstrap.ts (100%) rename {scripts => apps/wiki/scripts}/container-health.mjs (100%) rename {scripts => apps/wiki/scripts}/import-character-packs.mjs (100%) rename {scripts => apps/wiki/scripts}/prepare-standalone.mjs (100%) rename {scripts => apps/wiki/scripts}/publish-learning-series.ts (100%) rename {scripts => apps/wiki/scripts}/smoke.mjs (100%) rename {scripts => apps/wiki/scripts}/wait-snapshots.mjs (100%) rename {seed => apps/wiki/seed}/characters/extraction.json (100%) rename {seed => apps/wiki/seed}/characters/original/01-florist.png (100%) rename {seed => apps/wiki/seed}/characters/original/02-reader.png (100%) rename {seed => apps/wiki/seed}/characters/original/03-cyclist.png (100%) rename {seed => apps/wiki/seed}/characters/original/04-coffee.png (100%) rename {seed => apps/wiki/seed}/characters/packs.json (100%) rename {seed => apps/wiki/seed}/characters/prompts.json (100%) rename {seed => apps/wiki/seed}/characters/reference/01-basket.png (100%) rename {seed => apps/wiki/seed}/characters/reference/02-phone.png (100%) rename {seed => apps/wiki/seed}/characters/reference/03-coffee.png (100%) rename {seed => apps/wiki/seed}/characters/reference/04-red-coat.png (100%) rename {seed => apps/wiki/seed}/characters/reference/05-blue-dogs.png (100%) rename {seed => apps/wiki/seed}/characters/reference/06-dark-dog.png (100%) rename {seed => apps/wiki/seed}/characters/reference/07-pockets.png (100%) rename {seed => apps/wiki/seed}/characters/reference/08-blue-board.png (100%) rename {seed => apps/wiki/seed}/characters/reference/09-scarf-dog.png (100%) rename {seed => apps/wiki/seed}/characters/reference/10-elder.png (100%) rename {seed => apps/wiki/seed}/characters/reference/11-long-coat.png (100%) rename {seed => apps/wiki/seed}/characters/reference/12-trolley.png (100%) rename {seed => apps/wiki/seed}/characters/reference/13-bucket.png (100%) rename {seed => apps/wiki/seed}/characters/reference/14-curly.png (100%) rename {seed => apps/wiki/seed}/characters/reference/15-red-walk.png (100%) rename {src => apps/wiki/src}/components/ArticleGallery.tsx (100%) rename {src => apps/wiki/src}/components/Feed.tsx (100%) rename {src => apps/wiki/src}/components/GuidanceIndex.tsx (100%) rename {src => apps/wiki/src}/components/Shell.tsx (95%) rename {src => apps/wiki/src}/components/SkillCard.tsx (100%) rename {src => apps/wiki/src}/components/SkillDocs.tsx (100%) rename {src => apps/wiki/src}/content/learning-skills/Series.tsx (100%) rename {src => apps/wiki/src}/content/learning-skills/cover.ts (100%) rename {src => apps/wiki/src}/content/learning-skills/data.ts (100%) rename {src => apps/wiki/src}/content/registry.tsx (100%) rename {src => apps/wiki/src}/content/skills/catalog.ts (100%) rename {src => apps/wiki/src}/content/skills/guidance.ts (100%) rename {src => apps/wiki/src}/content/skills/shadow-puppet.ts (100%) create mode 100644 apps/wiki/src/content/wiki.ts rename {src => apps/wiki/src}/lib/api.ts (100%) rename {src => apps/wiki/src}/lib/character-image.ts (100%) rename {src => apps/wiki/src}/lib/db.ts (100%) rename {src => apps/wiki/src}/lib/health.ts (100%) rename {src => apps/wiki/src}/lib/library.ts (100%) rename {src => apps/wiki/src}/lib/markdown-response.ts (100%) rename {src => apps/wiki/src}/lib/model.ts (100%) rename {src => apps/wiki/src}/lib/probe.ts (100%) rename {src => apps/wiki/src}/lib/publish-learning-series.ts (100%) rename {src => apps/wiki/src}/lib/snapshots.ts (100%) rename {src => apps/wiki/src}/lib/storage.ts (100%) rename {src => apps/wiki/src}/lib/street-people.ts (100%) rename {src => apps/wiki/src}/lib/write.ts (100%) rename {src => apps/wiki/src}/pages/[section]/[[...taxonomy]].tsx (100%) rename {src => apps/wiki/src}/pages/_app.tsx (100%) rename {src => apps/wiki/src}/pages/api/agent-index.ts (100%) rename {src => apps/wiki/src}/pages/api/feed.ts (100%) rename {src => apps/wiki/src}/pages/api/guidance/[[...path]].ts (100%) rename {src => apps/wiki/src}/pages/api/health.ts (100%) rename {src => apps/wiki/src}/pages/api/media/[id].ts (100%) rename {src => apps/wiki/src}/pages/api/posts/[slug]/snapshots.ts (100%) rename {src => apps/wiki/src}/pages/api/posts/index.ts (100%) rename {src => apps/wiki/src}/pages/api/ready.ts (100%) rename {src => apps/wiki/src}/pages/api/skill-docs/[skill]/[doc].ts (100%) rename {src => apps/wiki/src}/pages/api/skill-docs/street-people/[doc].ts (100%) rename {src => apps/wiki/src}/pages/api/skills/street-people.ts (100%) rename {src => apps/wiki/src}/pages/api/tags.ts (100%) rename {src => apps/wiki/src}/pages/api/upload.ts (100%) create mode 100644 apps/wiki/src/pages/api/wiki-index.ts create mode 100644 apps/wiki/src/pages/api/wiki-post/[slug].ts create mode 100644 apps/wiki/src/pages/api/wiki/[key].ts create mode 100644 apps/wiki/src/pages/index.tsx rename {src => apps/wiki/src}/pages/library/import.tsx (100%) rename {src => apps/wiki/src}/pages/p/[slug].tsx (93%) rename {src => apps/wiki/src}/pages/p/[slug]/pages/[page].tsx (100%) rename {src => apps/wiki/src}/pages/skills/[[...path]].tsx (100%) rename {src => apps/wiki/src}/pages/tools/doodle.tsx (100%) rename {src => apps/wiki/src}/pages/tools/skills/[skill]/[[...doc]].tsx (100%) rename {src => apps/wiki/src}/pages/tools/skills/index.tsx (100%) rename {src => apps/wiki/src}/pages/tools/skills/street-people.tsx (100%) rename {src => apps/wiki/src}/pages/tools/skills/street-people/[doc].tsx (100%) create mode 100644 apps/wiki/src/pages/wiki/[key].tsx rename {src => apps/wiki/src}/styles/globals.css (91%) rename {src => apps/wiki/src}/styles/learning-series.css (100%) rename {src => apps/wiki/src}/styles/skill-docs.css (100%) rename {src => apps/wiki/src}/worker.ts (100%) rename {tests => apps/wiki/tests}/health.test.ts (100%) rename {tests => apps/wiki/tests}/integration.test.ts (100%) rename {tests => apps/wiki/tests}/learning-series.test.ts (100%) rename {tests => apps/wiki/tests}/model.test.ts (100%) rename {tests => apps/wiki/tests}/skill-docs.test.ts (100%) create mode 100644 apps/wiki/tests/wiki.test.ts create mode 100644 apps/wiki/tsconfig.json create mode 100644 docs/monorepo.md create mode 100644 docs/stage-files.md delete mode 100644 package-lock.json create mode 100644 pnpm-lock.yaml create mode 100644 pnpm-workspace.yaml create mode 100644 scripts/deploy-python.sh create mode 100644 scripts/deploy-studio.sh delete mode 100644 scripts/deploy-web.sh delete mode 100644 scripts/release-mode.sh delete mode 100644 src/pages/index.tsx delete mode 100644 tests/release-mode.sh diff --git a/.dockerignore b/.dockerignore index 45ad5b1..103c281 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,7 +1,7 @@ .git -.next -node_modules -dist +**/.next +**/node_modules +**/dist coverage .env .env.* @@ -16,3 +16,6 @@ coverage /.gitea /README.md /AGENTS.md + +**/__pycache__ +**/.venv diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml deleted file mode 100644 index 778d127..0000000 --- a/.gitea/workflows/ci.yml +++ /dev/null @@ -1,72 +0,0 @@ -name: PROMPT Docker CI and deployment - -on: - push: - branches: [main] - paths: - - '**' - - '!docs/**' - - '!**/*.md' - - 'public/**' - pull_request: - paths: - - '**' - - '!docs/**' - - '!**/*.md' - - 'public/**' - workflow_dispatch: - -jobs: - verify-and-deploy: - runs-on: ces-control - timeout-minutes: 45 - env: - PROMPT_IMAGE: prompt:${{ gitea.sha }} - PROMPT_TEST_IMAGE: prompt-tests:${{ gitea.sha }} - RELEASE_SHA: ${{ gitea.sha }} - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Verify release classification policy - run: bash tests/release-mode.sh - - name: Choose full or Web-only release - id: release - run: | - set -eu - mode=full - if [ "${{ gitea.event_name }}" = push ] && [ "${{ gitea.ref }}" = refs/heads/main ]; then - mode=$(bash scripts/release-mode.sh) - if [ "$mode" = web ]; then - image=$(sed -n 's/^PROMPT_IMAGE=//p' /opt/prompt/current/release.env) - if ! docker image inspect "prompt-tests:${image#prompt:}" >/dev/null 2>&1; then mode=full; fi - fi - fi - echo "mode=$mode" >> "$GITHUB_OUTPUT" - echo "Release mode: $mode" - - name: Build and deploy Web using the existing Docker environment - if: steps.release.outputs.mode == 'web' - run: bash scripts/deploy-web.sh "$RELEASE_SHA" - - name: Check preinstalled Docker Engine and Compose - if: steps.release.outputs.mode != 'web' - run: | - set -eu - command -v docker - docker compose version - docker info >/dev/null - - name: Validate the Compose configuration - if: steps.release.outputs.mode != 'web' - run: docker compose --env-file .env.example config --quiet - - name: Type check, unit tests, production build and smoke test inside Docker - if: steps.release.outputs.mode != 'web' - run: docker build --target integration -t "$PROMPT_TEST_IMAGE" . - - name: Build non-root production image with bundled FFmpeg - if: steps.release.outputs.mode != 'web' - run: docker build --target runtime -t "$PROMPT_IMAGE" . - - name: Test the complete isolated Docker stack - if: steps.release.outputs.mode != 'web' - run: bash scripts/integration.sh - - name: Deploy the persistent Docker Compose stack - if: steps.release.outputs.mode != 'web' && gitea.ref == 'refs/heads/main' && (gitea.event_name == 'push' || gitea.event_name == 'workflow_dispatch') - run: bash scripts/deploy.sh "$RELEASE_SHA" diff --git a/.gitea/workflows/python.yml b/.gitea/workflows/python.yml new file mode 100644 index 0000000..56b6f35 --- /dev/null +++ b/.gitea/workflows/python.yml @@ -0,0 +1,26 @@ +name: python CI and deployment +on: + push: + branches: [main] + paths: + - 'apps/python/**' + - '.gitea/workflows/python.yml' + pull_request: + paths: + - 'apps/python/**' + - '.gitea/workflows/python.yml' + workflow_dispatch: + +jobs: + verify-and-deploy: + runs-on: ces-control + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Build and verify python + run: docker build -f apps/python/Dockerfile -t "prompt-python:${{ gitea.sha }}" . + - name: Release python + if: gitea.ref == 'refs/heads/main' && (gitea.event_name == 'push' || gitea.event_name == 'workflow_dispatch') + run: bash scripts/deploy-python.sh "${{ gitea.sha }}" diff --git a/.gitea/workflows/studio.yml b/.gitea/workflows/studio.yml new file mode 100644 index 0000000..0697c4b --- /dev/null +++ b/.gitea/workflows/studio.yml @@ -0,0 +1,28 @@ +name: studio CI and deployment +on: + push: + branches: [main] + paths: + - 'apps/studio/**' + - '.gitea/workflows/studio.yml' + - 'pnpm-workspace.yaml' + pull_request: + paths: + - 'apps/studio/**' + - '.gitea/workflows/studio.yml' + - 'pnpm-workspace.yaml' + workflow_dispatch: + +jobs: + verify-and-deploy: + runs-on: ces-control + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Build and verify studio + run: docker build -f apps/studio/Dockerfile -t "prompt-studio:${{ gitea.sha }}" . + - name: Release studio + if: gitea.ref == 'refs/heads/main' && (gitea.event_name == 'push' || gitea.event_name == 'workflow_dispatch') + run: bash scripts/deploy-studio.sh "${{ gitea.sha }}" diff --git a/.gitea/workflows/wiki.yml b/.gitea/workflows/wiki.yml new file mode 100644 index 0000000..11f4581 --- /dev/null +++ b/.gitea/workflows/wiki.yml @@ -0,0 +1,43 @@ +name: wiki CI and deployment +on: + push: + branches: [main] + paths: + - 'apps/wiki/**' + - '.gitea/workflows/wiki.yml' + - 'Dockerfile' + - 'compose.yml' + - 'scripts/**' + - 'pnpm-workspace.yaml' + pull_request: + paths: + - 'apps/wiki/**' + - '.gitea/workflows/wiki.yml' + - 'Dockerfile' + - 'compose.yml' + - 'scripts/**' + - 'pnpm-workspace.yaml' + workflow_dispatch: + +jobs: + verify-and-deploy: + runs-on: ces-control + timeout-minutes: 45 + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Validate configuration + run: docker compose --env-file apps/wiki/.env.example config --quiet + - name: Build and verify Wiki + run: docker build --target integration -t "prompt-tests:${{ gitea.sha }}" . + - name: Build runtime + run: docker build --target runtime -t "prompt:${{ gitea.sha }}" . + - name: Integration stack + env: + PROMPT_IMAGE: prompt:${{ gitea.sha }} + PROMPT_TEST_IMAGE: prompt-tests:${{ gitea.sha }} + run: bash scripts/integration.sh + - name: Deploy Wiki + if: gitea.ref == 'refs/heads/main' && (gitea.event_name == 'push' || gitea.event_name == 'workflow_dispatch') + run: bash scripts/deploy.sh "${{ gitea.sha }}" diff --git a/.gitignore b/.gitignore index b563a6b..5469066 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,7 @@ coverage/ *.tsbuildinfo .DS_Store dist/ + +__pycache__/ +*.egg-info/ +.venv/ diff --git a/Dockerfile b/Dockerfile index eaac23c..6f004ea 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,13 +6,14 @@ RUN apt-get update \ && rm -rf /var/lib/apt/lists/* FROM base AS dependencies -COPY package.json package-lock.json ./ -RUN npm ci +RUN corepack enable && corepack prepare pnpm@11.25.0 --activate +COPY apps/wiki/package.json apps/wiki/pnpm-lock.yaml ./ +RUN pnpm install --frozen-lockfile FROM dependencies AS build # .dockerignore excludes docs and operational notes without extra legacy COPY snapshots. -COPY . . -RUN npm run typecheck && npm test && npm run build && npm run test:smoke +COPY apps/wiki/ . +RUN pnpm typecheck && pnpm test && pnpm build && pnpm test:smoke FROM build AS integration USER node @@ -24,9 +25,9 @@ ENV NODE_ENV=production HOSTNAME=0.0.0.0 PORT=3000 \ COPY --from=build --chown=node:node /app/.next/standalone/ ./ COPY --from=build --chown=node:node /app/dist/worker.cjs /app/dist/bootstrap.cjs /app/dist/publish-learning-series.cjs ./ COPY --from=build --chown=node:node /app/db/ ./db/ -COPY --chown=node:node scripts/container-health.mjs scripts/wait-snapshots.mjs ./ -COPY --chown=node:node scripts/import-character-packs.mjs ./scripts/import-character-packs.mjs -COPY --chown=node:node seed/characters/ ./seed/characters/ +COPY --chown=node:node apps/wiki/scripts/container-health.mjs apps/wiki/scripts/wait-snapshots.mjs ./ +COPY --chown=node:node apps/wiki/scripts/import-character-packs.mjs ./scripts/import-character-packs.mjs +COPY --chown=node:node apps/wiki/seed/characters/ ./seed/characters/ USER node EXPOSE 3000 CMD ["node", "server.js"] diff --git a/README.md b/README.md index d4d6af4..73beeb9 100644 --- a/README.md +++ b/README.md @@ -1,130 +1,5 @@ -# PROMPT +# PROMPT monorepo -仓库名:Probably Rendering One More Pixel Tonight。其余命名使用 PROMPT / `prompt`。 +Wiki、创作站和 Python 导出工具。 -自己的素材与创作工作台:Next.js Pages Router、React、TypeScript、Tailwind CSS、Node.js 24。中文界面包含瀑布流、日期贡献热力图、素材导入、多媒体详情、分类管理、独立素材架与线条图形工具。没有创建作品的按钮;图文和动态作品由代码实现。 - -## 全 Docker 启动 - -本机只需 Docker Engine / Docker Desktop 和 Compose v2。Node、npm、FFmpeg、迁移程序、网站与后台处理都在镜像里。 - -```bash -cp .env.example .env -# 修改 .env 中的三个密码 / 密钥,不能使用示例值。 -docker build --target runtime -t prompt:local . -docker compose --env-file .env up -d --wait postgres objects -docker compose --env-file .env run --rm migrate -docker compose --env-file .env up -d --wait web worker -``` - -访问 `http://localhost:18131`。图片与其他文件保存在 S3 对象卷,文字、分类、素材包引用和任务保存在 PostgreSQL 卷;停止、重建应用容器不会删除这些数据。 - -| 容器服务 | 职责 | -| --- | --- | -| `web` | Next.js 页面、API、素材上传/读取;宿主机 18131 → 容器 3000 | -| `worker` | FFmpeg 音画分离、封面与音轨处理;没有 HTTP 端口 | -| `postgres` | PostgreSQL 元数据和文字;兼容维护用回环端口 18132 | -| `objects` | RustFS 私有 S3 对象存储;兼容维护用回环端口 18133,控制台关闭 | -| `migrate` | 一次性数据库迁移与对象桶初始化,执行后退出 | -| `tests` | CI 的一次性集成测试执行器,执行后退出 | - -四个常驻服务使用 `restart: unless-stopped`,Web 和 worker 以非 root 用户运行。worker 通过心跳检查存活;Web 健康检查同时验证当前版本、数据库和 S3。 - -## 页面与数据 - -- `/`:所有非空素材包与已注册代码作品,按创建时间倒序;顶部为过去一年的贡献汇总。 -- `/images`、`/videos`、`/audio`:图片、视频、声音收藏。 -- `/articles`、`/motion`:代码编写的图文与动态作品。 -- 上述五类路径可以附加标签树路径,如 `/images/style/white-line`;父分类会包含后代分类的内容。 -- `/p/`:素材包的稳定详情地址,不随标签改变。多图切换、多视频及其关联音轨、多声音均可展示。 -- `/library/import`:导入同一类型的一组文件和说明,自动收为一份收藏。支持最多 16 个文件,单个 250 MB,总计 1 GB。 -- `/tools/doodle`:手绘线条造型参考,可选色、复制和下载透明 SVG。不是 AI 图片编辑器。 - -素材库不插入演示或占位帖子。空分类显示简洁的空状态;空素材包不进入任何瀑布流。分页游标由时间与 UUID 组成,重复时间戳下仍稳定。 - -详细模型见 `docs/data-model.md`。应用容器通过 Docker 网络的 `postgres:5432` 和 `objects:9000` 访问存储,不使用宿主机回环地址。浏览器通过应用访问媒体,支持 Range 分段读取。 - -视频原件保持不变,后台生成无声 MP4、封面,以及存在声音时的 M4A 音轨。音轨记录在 `asset_variants`,始终属于原视频;不会生成独立声音资产。后台单任务处理,使用数据库锁领取任务,失败重试三次,支持超时任务恢复。FFmpeg 禁止输入网络协议。 - -## 编程加入素材包与作品 - -`POST /api/posts` 接收 `kind`、`title`、可选 `slug`、`assets: [{id, role?}]`、`tags: [tagId]`、`text`、`coverAssetId` 和 `pageKey`。`role` 为 `content` 或 `caption`。素材和说明文字都可以通过 ID 引用已有资产;`text` 是创建新文字资产的快捷方式。引用不会复制原文件。 - -`POST /api/tags` 接收 `name`、`slug` 和可选 `parentId`。 - -图文或动态作品需要先在 `src/content/registry.tsx` 注册 React 组件与类型,再通过 API 创建引用对应 `pageKey` 的素材包。封面引用普通图片资产。动态作品的 React 组件就是画面本身,不会被强制套入视频播放器。未注册的页面不会出现在瀑布流中,也不会执行数据库中的任意路径或脚本。 - -当前不内置作品模板或视频导出引擎;后续一起确定设计系统和制作方案。 - -## 贡献记录 - -`contribution_events` 保存细分的 `kind`、对象类型、对象 ID、数量、发生时间、元数据和可选幂等键。显示时按上海时区汇总所有类型。当前没有将上传、分类或保存动作自动算作贡献;触发规则留待确定。没有随机或伪造热力图数据。 - -## CI/CD 与生产部署 - -`.gitea/workflows/ci.yml` 使用 `runs-on: ces-control`。依赖安装、类型检查、单元测试、生产构建、启动检查都在 Docker 构建阶段运行。集成测试启动隔离的完整容器栈,并由测试容器请求真实的非 root Web / worker 容器,验证 PostgreSQL、RustFS、上传、共享引用和音画分离。 - -main 上的 push 或手动运行,在全部检查通过后才发布。测试环境使用独立 Compose 项目、随机端口和随机凭据;测试结束只删除它自己的容器和卷。 - -生产使用固定 Compose project `prompt`,复用原有 `prompt_postgres_data` 和 `prompt_objects` 卷,以及 `/etc/prompt.env` 的凭据。由旧部署升级时,发布脚本会停用 `prompt.service`、`prompt-worker.service`,由容器接管运行;宿主机无需项目专用的 Node/FFmpeg 进程。旧发布目录留作首次迁移失败时的回退依据。 - -| 项目 | 值 | -| --- | --- | -| 生产运行 | Docker Compose:web、worker、postgres、objects | -| 网站端口 | `18131`,映射到 Web 容器 3000 | -| 应用镜像 | `prompt:`;回退使用上一版镜像 | -| 发布清单 | `/opt/prompt/releases//compose.yml` 和 `release.env` | -| 当前发布 | `/opt/prompt/current` 原子软链接 | -| 密钥 | `/etc/prompt.env`,保留既有凭据,新建时随机生成;不进代码和日志 | -| 持久数据 | Docker named volumes,不随应用发布删除 | -| 数据库备份 | `/var/lib/prompt/backups`,每次发布前备份,保留最近 10 份 | - -发布使用宿主机文件锁串行执行,自动跳过已落后的提交。先备份、迁移,再切换 Web / worker;新版本失败时恢复上一版容器,首次迁移失败时可恢复原先的宿主机服务。生产发布从不执行 `down -v`。对象卷需要独立快照,数据库 dump 不能代替对象备份。 - -在服务器上维护当前版本: - -```bash -cd /opt/prompt/current -sudo docker compose -p prompt --env-file /etc/prompt.env --env-file release.env ps -sudo docker compose -p prompt --env-file /etc/prompt.env --env-file release.env logs --tail 100 web worker -sudo docker compose -p prompt --env-file /etc/prompt.env --env-file release.env exec web node container-health.mjs -``` - -`GET /api/health` 返回应用版本;`GET /api/ready` 检查数据库与对象存储。 - -## 内网与公网访问 - -`172.31.212.211` 是服务器内网 IP,不能作为公网入口。Web 端口默认映射为 `0.0.0.0:18131:3000`;公网访问仍需要实例绑定公网 IP / EIP 或反向代理,并配置相应安全组和防火墙。Docker 化不会使内网 IP 自动变成公网 IP。本项目不会擅自修改云安全组或开放数据库/S3 的公网端口。 - -## 独立运行 CI 验证 - -```bash -docker build --target integration -t prompt:tests . -docker build --target runtime -t prompt:local . -PROMPT_IMAGE=prompt:local PROMPT_TEST_IMAGE=prompt:tests bash scripts/integration.sh -``` - -整个验证过程无需在宿主机安装 Node.js、PostgreSQL、S3 或 FFmpeg。runner 仅需 Docker Engine、Compose、Git、Bash、flock 和管理 Docker/旧服务所需的权限。 - -## 街头小人技能与 Agent 接口 - -导航「工具 → 技能」打开 `/tools/skills`,`/tools/skills/street-people` 包含风格约定、提示词、上传示例和两个独立图包入口。 - -把 `GET /api/skills/street-people` 的完整地址交给有绘图工具的 coding agent。GET 返回 JSON 规范,`?format=md` 返回 Markdown。agent 用自己的绘图能力生成单人透明 PNG,再向同一地址 POST multipart/form-data,字段 `files` 可重复,`title`、`description`、`tags` 和 `slug` 可选。网站不调用外部模型,也不需要模型密钥。PNG 必须有真实透明与接近不透明的像素(alpha ≥250),最多 4000 万像素,其余上传数量和大小限制与导入页一致。成功返回 post 地址和可复用素材 ID。 - -`seed/characters` 存放本次参考图提取 15 张、新生成测试 4 张及来源说明。部署健康检查后通过 `scripts/import-character-packs.mjs` 调用真实上传接口写入 PostgreSQL/S3,生成 `/p/street-people-reference` 与 `/p/street-people-original` 两个独立 post。已有同 slug 时跳过,重发版不重复导入。原图提取由 imagegen 执行,可能重建细节,并非逐像素无损裁剪。 - - -## 网页原稿、截图与技能文档 - -图文笔记中的每张图片拥有独立网页:`/p//pages/1` 至 `/pages/8`。笔记页展示真实服务器截图,可刷新一张或全部,并单独打开 HTML 原稿。截图由 Docker worker 内 Chromium 生成并存入私有 S3,发布会等待当版全部 24 张截图完成。数据与任务结构见 `db/002_page_snapshots.sql`,详细行为见 `docs/learning-series.md`。 - -工具栏首项为技能;素材库与分类管理页面已移除,已有素材、标签、导入和数据 API 保留。技能使用瀑布卡片,首页也混排展示。 - -交给 agent 的入口为 `/skills/street-people/SKILL.md`,后续子文档为 `style.md`、`upload.md`、`checks.md`;纯文本只通过链接引用图片、文档和 API。人类阅读入口 `/tools/skills/street-people` 和对应子页面使用相同文档数据。右侧资源面板分类收录全部文档、图片和 API,支持预览与打开;不会执行 POST,也不展示与技能流程无关的测试图包。旧 JSON API 和 `?format=md` 兼容保留,后者返回相同入口文档。 - -## 照片入皮影 - -技能目录和首页新增「照片入皮影」,入口网页 `/tools/skills/shadow-puppet`,Agent 入口纯文本 `/skills/shadow-puppet/SKILL.md`。网页与纯文本共用 `src/content/skills/shadow-puppet.ts` 的五份文档:入口、制作流程、画面语法、完整提示词、验收与上传。侧栏包含五份文档、用户提供的白鹭/舞者两张完成示例,以及通用图片上传和媒体读取两个 API。示例被明确标记为风格参考,不当作原始照片重新嵌套。 - -每张原片独立输出不透明 3:4 海报,上下高度严格 1:1:上半保真摄影,下半是一幕一偶的暖灯宣纸皮影。Agent 使用自己的图像工具逐张制作与验收,完成后调用 `POST /api/upload`;不使用街头小人的透明 PNG 接口。资源面板只展示 API 说明,不执行上传或直接请求未替换参数的媒体地址模板。阅读器和纯文本文档路由按技能注册表读取,后续可继续增加技能。 +详见 [项目结构与运行方式](docs/monorepo.md)。 diff --git a/apps/python/Dockerfile b/apps/python/Dockerfile new file mode 100644 index 0000000..7a025c0 --- /dev/null +++ b/apps/python/Dockerfile @@ -0,0 +1,8 @@ +FROM python:3.12-slim +RUN apt-get update && apt-get install -y --no-install-recommends ffmpeg fonts-noto-cjk && rm -rf /var/lib/apt/lists/* +WORKDIR /app +COPY apps/python/ . +RUN pip install --no-cache-dir . && python -m unittest discover -s tests -v +RUN useradd --create-home exporter +USER exporter +ENTRYPOINT ["prompt-export"] diff --git a/apps/python/pyproject.toml b/apps/python/pyproject.toml new file mode 100644 index 0000000..5a4fe45 --- /dev/null +++ b/apps/python/pyproject.toml @@ -0,0 +1,12 @@ +[build-system] +requires = ["setuptools==75.8.0"] +build-backend = "setuptools.build_meta" +[project] +name = "prompt-tools" +version = "0.1.0" +requires-python = ">=3.12" +dependencies = ["Pillow==11.1.0"] +[project.scripts] +prompt-export = "prompt_tools.export:main" +[tool.setuptools.packages.find] +where = ["src"] diff --git a/apps/python/src/prompt_tools/__init__.py b/apps/python/src/prompt_tools/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/python/src/prompt_tools/export.py b/apps/python/src/prompt_tools/export.py new file mode 100644 index 0000000..031173c --- /dev/null +++ b/apps/python/src/prompt_tools/export.py @@ -0,0 +1,70 @@ +"""Render a Studio JSON bundle into PNG slides and optionally MP4.""" +import argparse +import json +import subprocess +from pathlib import Path +from PIL import Image, ImageDraw, ImageFont + + +def validate(bundle): + if bundle.get("version") != 1 or not isinstance(bundle.get("slides"), list) or not bundle["slides"]: + raise ValueError("Expected a version 1 Studio bundle with slides") + for slide in bundle["slides"]: + if not all(isinstance(slide.get(k), str) for k in ("heading", "body", "color")): + raise ValueError("Invalid slide") + return bundle["slides"] + + +def wrap(draw, text, font, width): + lines = [] + for paragraph in text.split("\n"): + line = "" + for char in paragraph: + if line and draw.textlength(line + char, font=font) > width: + lines.append(line) + line = "" + line += char + lines.append(line) + return lines + + +def render(bundle, output, font_path): + slides = validate(bundle) + output.mkdir(parents=True, exist_ok=True) + heading = ImageFont.truetype(str(font_path), 76) + body = ImageFont.truetype(str(font_path), 38) + for index, slide in enumerate(slides, 1): + image = Image.new("RGB", (1080, 1440), slide["color"]) + draw = ImageDraw.Draw(image) + draw.text((80, 80), f"PROMPT / {index:02}", font=body, fill="#353535") + y = 330 + for text, font, gap in [(slide["heading"], heading, 108), (slide["body"], body, 65)]: + for line in wrap(draw, text, font, 920): + if y + gap > 1360: + raise ValueError(f"Slide {index} overflows; split the text into more slides") + draw.text((80, y), line, font=font, fill="#242424") + y += gap + y += 70 + image.save(output / f"slide-{index:03}.png") + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("bundle", type=Path) + parser.add_argument("--output", type=Path, required=True) + parser.add_argument("--font", type=Path, required=True, help="CJK font TTF/OTF/TTC") + parser.add_argument("--video", action="store_true") + args = parser.parse_args() + bundle = json.loads(args.bundle.read_text()) + render(bundle, args.output, args.font) + if args.video: + # Use an explicit temporary input sequence so old PNGs cannot leak into a video. + import tempfile + import shutil + with tempfile.TemporaryDirectory() as staging: + for index in range(1, len(bundle["slides"]) + 1): + shutil.copy(args.output / f"slide-{index:03}.png", Path(staging) / f"slide-{index:03}.png") + subprocess.run(["ffmpeg", "-y", "-framerate", "1/4", "-i", str(Path(staging) / "slide-%03d.png"), "-vf", "fps=30,format=yuv420p", "-c:v", "libx264", "-movflags", "+faststart", str(args.output / "video.mp4")], check=True) + +if __name__ == "__main__": + main() diff --git a/apps/python/tests/test_export.py b/apps/python/tests/test_export.py new file mode 100644 index 0000000..8edf8b2 --- /dev/null +++ b/apps/python/tests/test_export.py @@ -0,0 +1,13 @@ +import unittest +from prompt_tools.export import validate, wrap +class ExportTests(unittest.TestCase): + def test_bad_bundle(self): + for bundle in [{}, {"version": 1, "slides": []}, {"version": 1, "slides": [{}]}]: + with self.assertRaises(ValueError): validate(bundle) + def test_wrap_preserves_content(self): + class Draw: + def textlength(self, text, font): return len(text) + self.assertEqual(wrap(Draw(), "中文内容测试", None, 3), ["中文内", "容测试"]) + def test_valid_bundle(self): + slides = [{"heading": "标题", "body": "正文", "color": "#fff"}] + self.assertEqual(validate({"version": 1, "slides": slides}), slides) diff --git a/apps/studio/Dockerfile b/apps/studio/Dockerfile new file mode 100644 index 0000000..4a7b5fd --- /dev/null +++ b/apps/studio/Dockerfile @@ -0,0 +1,15 @@ +FROM node:24-bookworm-slim AS build +WORKDIR /app +RUN corepack enable && corepack prepare pnpm@11.25.0 --activate +COPY apps/studio/package.json apps/studio/pnpm-lock.yaml ./ +RUN pnpm install --frozen-lockfile +COPY apps/studio/ . +RUN pnpm typecheck && pnpm build +FROM node:24-bookworm-slim +WORKDIR /app +ENV NODE_ENV=production HOSTNAME=0.0.0.0 PORT=3000 +COPY --from=build --chown=node:node /app/.next/standalone/ ./ +COPY --from=build --chown=node:node /app/.next/static/ ./.next/static/ +USER node +EXPOSE 3000 +CMD ["node", "server.js"] diff --git a/next-env.d.ts b/apps/studio/next-env.d.ts similarity index 100% rename from next-env.d.ts rename to apps/studio/next-env.d.ts diff --git a/apps/studio/next.config.ts b/apps/studio/next.config.ts new file mode 100644 index 0000000..8f5d18f --- /dev/null +++ b/apps/studio/next.config.ts @@ -0,0 +1,3 @@ +import type { NextConfig } from "next"; +const config: NextConfig = { output: "standalone", outputFileTracingRoot: process.cwd(), poweredByHeader: false }; +export default config; diff --git a/apps/studio/package.json b/apps/studio/package.json new file mode 100644 index 0000000..24af072 --- /dev/null +++ b/apps/studio/package.json @@ -0,0 +1,25 @@ +{ + "name": "@prompt/studio", + "private": true, + "scripts": { + "dev": "next dev -p 3001", + "build": "next build", + "start": "next start", + "typecheck": "next typegen && tsc --noEmit" + }, + "dependencies": { + "next": "16.4.2", + "react": "19.3.1", + "react-dom": "19.3.1", + "lucide-react": "1.61.0" + }, + "devDependencies": { + "@tailwindcss/postcss": "4.3.3", + "@types/node": "24.19.2", + "@types/react": "19.3.0", + "@types/react-dom": "19.3.0", + "tailwindcss": "4.3.3", + "typescript": "5.9.3" + }, + "packageManager": "pnpm@11.25.0" +} diff --git a/apps/studio/pnpm-lock.yaml b/apps/studio/pnpm-lock.yaml new file mode 100644 index 0000000..5def37e --- /dev/null +++ b/apps/studio/pnpm-lock.yaml @@ -0,0 +1,1030 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + lucide-react: + specifier: 1.61.0 + version: 1.61.0(@types/react@19.3.0)(react@19.3.1) + next: + specifier: 16.4.2 + version: 16.4.2(@types/node@24.19.2)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + react: + specifier: 19.3.1 + version: 19.3.1 + react-dom: + specifier: 19.3.1 + version: 19.3.1(react@19.3.1) + devDependencies: + '@tailwindcss/postcss': + specifier: 4.3.3 + version: 4.3.3 + '@types/node': + specifier: 24.19.2 + version: 24.19.2 + '@types/react': + specifier: 19.3.0 + version: 19.3.0 + '@types/react-dom': + specifier: 19.3.0 + version: 19.3.0(@types/react@19.3.0) + tailwindcss: + specifier: 4.3.3 + version: 4.3.3 + typescript: + specifier: 5.9.3 + version: 5.9.3 + +packages: + + '@alloc/quick-lru@5.3.0': + resolution: {integrity: sha512-U4+70Pc5ZS9osnCBCE5Jha/ciHM+Yp+CNMNC/7HvYbNRk1Ldd+f7qO65W5qfhu/TCv+/ozljlXXe9Nj8419DMA==} + engines: {node: '>=10'} + + '@emnapi/runtime@1.11.3': + resolution: {integrity: sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==} + + '@img/colour@1.1.0': + resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==} + engines: {node: '>=18'} + + '@img/sharp-darwin-arm64@0.35.5': + resolution: {integrity: sha512-QRUlFQ0WxvdWyqqG/WtI3iupfD5rBzmCHXSdPsY91sAtVtTo7Q4cb6zOccZ3gqEqkr0f1As1ehLqmEpDsRf+lg==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.35.5': + resolution: {integrity: sha512-+BR255RhDlpygUpOc/Jdt1nT6DQ3XG/ERo5wbcdOf5Q320dKtPCKPLR1LJs9VGXRaMa8l1uUa0tkCNOXiAxZUw==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [darwin] + + '@img/sharp-freebsd-wasm32@0.35.5': + resolution: {integrity: sha512-Y/z91nEZ4uIBX5X3nfTovjU9lHNKFYbL2lpHCLVNmXQK03VIZvXBBt0KxbPGp2SdGSF+2mQU4e+hQaWOt86iAw==} + engines: {node: '>=20.9.0'} + os: [freebsd] + + '@img/sharp-libvips-darwin-arm64@1.3.4': + resolution: {integrity: sha512-5R89nBYiRdUlSWJxPhO+GVtaXzXSxKnRu/xqMn3KTA3L9EB9Oy/P+Nn2f2vlhPuUdy/Zusb2DarbyTpGCfEDuw==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.3.4': + resolution: {integrity: sha512-iR2OKH80yi0U+dUplyh3/xdpFvps6YkCwsXenIJxqxR1v9o+xtKTGbS9H7cps+2Vxjc8B1j96p75NmTGjIhtpQ==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.3.4': + resolution: {integrity: sha512-Y3dgX/6lE2QhQb+Gxy0WZxfg9MEm/JBjamZpS2IklP7xIQoKN4hzAm7KcMVGtaVDt3neE9OKBC7vAfonA/Lr1A==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-arm@1.3.4': + resolution: {integrity: sha512-LmRtTsOHuvM2+wlO2Db37dx5MiZhB0FvSunciw48YjdOkZz9KAiRbm8ujeMOA1INqmei5NapFxYEK1D1ZSidmw==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-ppc64@1.3.4': + resolution: {integrity: sha512-Le6boB8Tai0Nis+gIxIpKx68UDVVIqdR8Tin5Yf1z2LJJQLDJvCDRqRu+jC2qCoD+eIomonmOwB4smBRxfVpYQ==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-riscv64@1.3.4': + resolution: {integrity: sha512-aHkkIEHPRdQEegJN20MLmGtxYD9R2wQr3Cwpddnu5+YKMt6Uzax7S9h5gpZTo8wyrGuZSlfQ63OevL5mTyOC7Q==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-s390x@1.3.4': + resolution: {integrity: sha512-ra/mB6MikESDUO7Yg+Mi95bFBb9GsObURuhnOv3OqknjGe9sZrG8tCe9q0xSIGrtLgvgw0gKnFWcK4blSgQOuQ==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-x64@1.3.4': + resolution: {integrity: sha512-GJ//SSXbnwSDes02umB3nDJLFcQzw8a18V8fyhqr6tV515tOEMdImjjxj1AoafMRz56F3PHgftnj1QEKSU1zkw==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linuxmusl-arm64@1.3.4': + resolution: {integrity: sha512-hvulFwtjUcagsis6BBxHwGFwWoNZjgYmULGVrZcyfNbjA8hKILbRxGg15/7w5HDyXHXUos/j6baAWqnCyQ2DWA==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@img/sharp-libvips-linuxmusl-x64@1.3.4': + resolution: {integrity: sha512-6zXKeE/p39I1AmA3cJG35eyBGNqNddLnUXjhwBnsGjFPWqf5VKkDBEqaEkPDoTEtkxwi2vv8Tcr2mDyP4So7Fg==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@img/sharp-linux-arm64@0.35.5': + resolution: {integrity: sha512-LYVx5JTsOM2CBzmxreh+nl64/3H6Xb09iSLknqH47z2T2DFFxDeFLP5y4dJwe6H7uGQlHPyEEtIqyo3DYsRwdQ==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-arm@0.35.5': + resolution: {integrity: sha512-LEaXK2WdXVK5ykcw0buWyPMsmLLL2vpHLD6yrNSW+JGEL3BZPA4tpKN6iaMc4AxTTAoaX/sU1rOL51lcIz48ZQ==} + engines: {node: '>=20.9.0'} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-ppc64@0.35.5': + resolution: {integrity: sha512-QVxAAq8evVRI9ia2vqgwrmWucn5Dfv+JdWzj75pD8omHLPSP7f8p20O8jxzjCcuCEQEOtYOZUmX1hkiZ0kdevA==} + engines: {node: '>=20.9.0'} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-riscv64@0.35.5': + resolution: {integrity: sha512-LtdreXguaavKODPIfzJ4kffx7UNt1omwtK0rch4EBbbSTXPnxWmYSayXdLJw0fJzQ97kHt1gL/yh4tvU+nCyRQ==} + engines: {node: '>=20.9.0'} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-s390x@0.35.5': + resolution: {integrity: sha512-UZasTOFiYzotTsGOCu42BfUzP6Tu6Do/947iRm1RsLKvlllxwGcn4RN27LibGWceix4Y+Pmw3jsnTcCQIgWjqA==} + engines: {node: '>=20.9.0'} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-x64@0.35.5': + resolution: {integrity: sha512-SxFtLTeJInhAA9Q836kux2vZNeOBQEx658qvbboZScr0wIARym3IcGmW7KpVD5sbVg0Ojy+udFQdayYIZyoNog==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@img/sharp-linuxmusl-arm64@0.35.5': + resolution: {integrity: sha512-9HbMclmI1zlNkFRs3z9/eBtDjfD0sGlrX1z6b1qwmiFY5ElDLh4BC0LPBdVp7z1DXFiKlIcznf+ZlsuZzLxQqg==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@img/sharp-linuxmusl-x64@0.35.5': + resolution: {integrity: sha512-4KOphqB035HrVdqLZfCgMzzERrQkkzOwRhl4OAkRO1YCldbaFjySXMaK534Mo0V+LndnlJk+sbUyLeU0ULyD1A==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@img/sharp-wasm32@0.35.5': + resolution: {integrity: sha512-Ptsga1su4tQx+LLF1ECS9U6nz5kmrXKo6XVbtR48Ke3ZRxxgaWBu7IDtEe1quo8hiupwm6WFqxVlXaSf7IINGQ==} + engines: {node: '>=20.9.0'} + + '@img/sharp-webcontainers-wasm32@0.35.5': + resolution: {integrity: sha512-hfhF/FmoQyTUkA0bIKFOtw536BQSeBMe6BF6QyWlrPxT754+TFLaZ7sKKTfvvM0yJgKgaYTwnFCIZ/GuDw5SUA==} + engines: {node: '>=20.9.0'} + cpu: [wasm32] + + '@img/sharp-win32-arm64@0.35.5': + resolution: {integrity: sha512-X4t7g+7ZA5DKblCBEXGjUqqemj4vczING/5viFwAL8h4N3qYeyjwdCvRLHi4EdOUI+2Z7UFlp1VM+p/AuEtm6Q==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [win32] + + '@img/sharp-win32-ia32@0.35.5': + resolution: {integrity: sha512-5Zm82LoBc43nhwNybZlG7Y1KO//Zhsn306fQl29ZOuStHLGTo3BWL83q3cznX0poxSAMuYL1On/BHBxkBeKr6A==} + engines: {node: ^20.9.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.35.5': + resolution: {integrity: sha512-x76eH0vEiHlcMQu8Y8IenntaACtddpT6W0wmXtWrnKcnKI7ME5DdgqhAD6SEWOEl1v2zDvkZDhFA9KnURwpfqg==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [win32] + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.6.0': + resolution: {integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@next/env@16.4.2': + resolution: {integrity: sha512-nTUTFH7G5/J/fmpkjVLegOkqyKOP0CEsJcMsyO4UCYeN1su+YMW/MfaSErnJskL7XM+UDK6aTvslxsRCyya/sA==} + + '@next/swc-darwin-arm64@16.4.2': + resolution: {integrity: sha512-ONkhFvZNFWlsEHOM/81AtxdyuJP2KRYKYR0JxPwvcu1AuPMMMgcL+wW2luldJvMtZwKtUxoSkCychW5wIeoYSw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@next/swc-darwin-x64@16.4.2': + resolution: {integrity: sha512-luPCMbOsCoaF+kXJEUjmjmOZg1lC3BflhmUu+ZmW4tBu2vW/4AXak8JBFvePizGkxVmNiAw/r9ra+6UviCWtWQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@next/swc-linux-arm64-gnu@16.4.2': + resolution: {integrity: sha512-xhwFTAncJyaCNy5KqKKuKaIIdCy1/1ZV1s5S1G0hhT7wGMkDTlfJ6aQbfRFnIG/s3/kDrxQ8aycVe+c5QnP8ow==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@next/swc-linux-arm64-musl@16.4.2': + resolution: {integrity: sha512-T1PNmfbPcxr5ndtWUL/3wQtLXsz808lq6sc2GrNT5k2oquF7UyqZddHSuAewHVsWsGXe6nsl9HoN1YNriVjuSg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@next/swc-linux-x64-gnu@16.4.2': + resolution: {integrity: sha512-N9cDUOCGtkJG5PNKDFZUF3xXndrJJcpLp121uAGjIGvO/U2p9tfdNOM9htj7+5f72l0m8rMw/cvYacUJBQoudg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@next/swc-linux-x64-musl@16.4.2': + resolution: {integrity: sha512-yY2uh1YhX6ufuYy2FCbw1dqblbhI57GLYAJfCkqD9auTv6pLrH67Uccjc3QMKBeCYAG6lkgu08ExmX1bbjejjQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@next/swc-win32-arm64-msvc@16.4.2': + resolution: {integrity: sha512-j/ArWRIHpMMB6wYLMhr2puTguBt70lNU/Cmjl9p6dTDE8DGknYJMP9PdwPk2dqpCNL/KIX9yfngDvIesxJPmsg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@next/swc-win32-x64-msvc@16.4.2': + resolution: {integrity: sha512-AA4edyWHDko3NCSo0x6GomsdgFb0oR1J3MXU1b5xt6FRFg4AucrMPW3S0hCe/9onU0O1BbpGQBsqo1r0Gneu1g==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@swc/helpers@0.5.23': + resolution: {integrity: sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==} + + '@tailwindcss/node@4.3.3': + resolution: {integrity: sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==} + + '@tailwindcss/oxide-android-arm64@4.3.3': + resolution: {integrity: sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.3.3': + resolution: {integrity: sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.3.3': + resolution: {integrity: sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.3.3': + resolution: {integrity: sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3': + resolution: {integrity: sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==} + engines: {node: '>= 20'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.3.3': + resolution: {integrity: sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@tailwindcss/oxide-linux-arm64-musl@4.3.3': + resolution: {integrity: sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@tailwindcss/oxide-linux-x64-gnu@4.3.3': + resolution: {integrity: sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@tailwindcss/oxide-linux-x64-musl@4.3.3': + resolution: {integrity: sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@tailwindcss/oxide-wasm32-wasi@4.3.3': + resolution: {integrity: sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + + '@tailwindcss/oxide-win32-arm64-msvc@4.3.3': + resolution: {integrity: sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [win32] + + '@tailwindcss/oxide-win32-x64-msvc@4.3.3': + resolution: {integrity: sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [win32] + + '@tailwindcss/oxide@4.3.3': + resolution: {integrity: sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==} + engines: {node: '>= 20'} + + '@tailwindcss/postcss@4.3.3': + resolution: {integrity: sha512-JTSZZGQi1AyKirbLN3azmjVzef92tcX7h+iSqPdaeStyFpGpDlKvvpxeOE8njhbUanbRwr3z8DyzhICWnMtQeg==} + + '@types/node@24.19.2': + resolution: {integrity: sha512-93d49wCWJkCyN87MxLpNN6KXPCwFw7bVUg79mGUV1OS40JGWwVCr8n61DXCSqz7CV6/VfPkb7xec7uP2M+QHWQ==} + + '@types/react-dom@19.3.0': + resolution: {integrity: sha512-ZI7bU42mZXXKHn/qNLEw2IrbiINU7X5+vfgdixBHkCNpYWXjKgfQ/P+uyGb5CjOLB9UcnTeg3rylQtV2hym44Q==} + peerDependencies: + '@types/react': ^19.3.0 + + '@types/react@19.3.0': + resolution: {integrity: sha512-N0rFCuH9YoxG9/m61l9MfpJKfmLOVU0em7ipIz6TRgSSkvReLB9vL85GB+yr8Bs5leqpvg96JSwF4ZS1s4viQg==} + + baseline-browser-mapping@2.11.32: + resolution: {integrity: sha512-UvuxFU9P3hM29LrQdwu0cD6w6/+SFr+UlB9s/knI7+O2rK9xFxKUwSDWxGdbbqQ9/V7BJ5s0NI5nQAE4uJp3gQ==} + engines: {node: '>=6.0.0'} + hasBin: true + + caniuse-lite@1.0.30001819: + resolution: {integrity: sha512-LFUqIIAwpzsIuevnKnsR9qnStBcgzPShTX61lBwN9uFkkf8o8zLiebEjbW8AYtZiF+1YKDWfdt/pWDtMuG8Xwg==} + + client-only@0.0.1: + resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + enhanced-resolve@5.26.0: + resolution: {integrity: sha512-9vhedylFonb2YGogzUKX6+Ja72gOJbN1QHAqdrvqLwhdl/QWbKopzoUC9EbQNVsAns/bx/4uyqalrQAoy1IByw==} + engines: {node: '>=10.13.0'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} + hasBin: true + + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + + lucide-react@1.61.0: + resolution: {integrity: sha512-v2SQPPPNjnr+BlhL9Spuzmo5yR+hLkftfuE4E3jaxdNPgSH0hJKPcLJBP7yAta87jQNPsSERS59PJjCJ/CorBA==} + peerDependencies: + '@types/react': '*' + react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + nanoid@3.3.20: + resolution: {integrity: sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + next@16.4.2: + resolution: {integrity: sha512-r+oBJojfefUjOiWkBhXgLS+igxX/7BWyK59uHnyOyplMSLtBZ+QLP3okrdYTbrfrbrmNTVWLBPaHDX9KRaIt3w==} + engines: {node: '>=20.9.0'} + hasBin: true + peerDependencies: + '@opentelemetry/api': ^1.1.0 + '@playwright/test': ^1.51.1 + babel-plugin-react-compiler: '*' + react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 + react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 + sass: ^1.3.0 + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + '@playwright/test': + optional: true + babel-plugin-react-compiler: + optional: true + sass: + optional: true + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + postcss@8.5.23: + resolution: {integrity: sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==} + engines: {node: ^10 || ^12 || >=14} + + postcss@8.5.31: + resolution: {integrity: sha512-YUbWYCgErwnMAVkjUnYa+KlMBzGpHwiIt/DE7f0G33AuX2LH9UcTk6KgWxd3zRU+pN3u/C+Xl3EnMLM4Hea7Sg==} + engines: {node: ^10 || ^12 || >=14} + + react-dom@19.3.1: + resolution: {integrity: sha512-Y0bARz53lhEC1NMCASs0/j+faB/zqt3R8hpvg1e8+61ZVJ4UL0UdC4cBbXfZMcIuhrfgeILTLe+ZeBCavQPtKQ==} + peerDependencies: + react: ^19.3.1 + + react@19.3.1: + resolution: {integrity: sha512-QNhWdt7nrgVWWQG58QuGsAR3jv3Hbe4mb4vz7w2csnHavciZJgda1CPNaldF6eVxv90ud3jUXpKlHL69gO38yw==} + engines: {node: '>=0.10.0'} + + scheduler@0.28.0: + resolution: {integrity: sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw==} + + semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} + engines: {node: '>=10'} + hasBin: true + + sharp@0.35.5: + resolution: {integrity: sha512-Ywn4OnzGukp7CDMrp08RQ50YKmuwG47brZgIVPTvBaaAfQlRlygrRqSrxdCiL9M+LlzLBiJ68IR1QqvzHyjC7g==} + engines: {node: '>=20.9.0'} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + source-map-js@1.2.2: + resolution: {integrity: sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==} + engines: {node: '>=0.10.0'} + + styled-jsx@5.1.6: + resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} + engines: {node: '>= 12.0.0'} + peerDependencies: + '@babel/core': '*' + babel-plugin-macros: '*' + react: '>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0' + peerDependenciesMeta: + '@babel/core': + optional: true + babel-plugin-macros: + optional: true + + tailwindcss@4.3.3: + resolution: {integrity: sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==} + + tapable@2.3.3: + resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} + engines: {node: '>=6'} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@7.24.6: + resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} + +snapshots: + + '@alloc/quick-lru@5.3.0': {} + + '@emnapi/runtime@1.11.3': + dependencies: + tslib: 2.8.1 + optional: true + + '@img/colour@1.1.0': + optional: true + + '@img/sharp-darwin-arm64@0.35.5': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.3.4 + optional: true + + '@img/sharp-darwin-x64@0.35.5': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.3.4 + optional: true + + '@img/sharp-freebsd-wasm32@0.35.5': + dependencies: + '@img/sharp-wasm32': 0.35.5 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.3.4': + optional: true + + '@img/sharp-libvips-darwin-x64@1.3.4': + optional: true + + '@img/sharp-libvips-linux-arm64@1.3.4': + optional: true + + '@img/sharp-libvips-linux-arm@1.3.4': + optional: true + + '@img/sharp-libvips-linux-ppc64@1.3.4': + optional: true + + '@img/sharp-libvips-linux-riscv64@1.3.4': + optional: true + + '@img/sharp-libvips-linux-s390x@1.3.4': + optional: true + + '@img/sharp-libvips-linux-x64@1.3.4': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.3.4': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.3.4': + optional: true + + '@img/sharp-linux-arm64@0.35.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.3.4 + optional: true + + '@img/sharp-linux-arm@0.35.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.3.4 + optional: true + + '@img/sharp-linux-ppc64@0.35.5': + optionalDependencies: + '@img/sharp-libvips-linux-ppc64': 1.3.4 + optional: true + + '@img/sharp-linux-riscv64@0.35.5': + optionalDependencies: + '@img/sharp-libvips-linux-riscv64': 1.3.4 + optional: true + + '@img/sharp-linux-s390x@0.35.5': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.3.4 + optional: true + + '@img/sharp-linux-x64@0.35.5': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.3.4 + optional: true + + '@img/sharp-linuxmusl-arm64@0.35.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.3.4 + optional: true + + '@img/sharp-linuxmusl-x64@0.35.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.3.4 + optional: true + + '@img/sharp-wasm32@0.35.5': + dependencies: + '@emnapi/runtime': 1.11.3 + optional: true + + '@img/sharp-webcontainers-wasm32@0.35.5': + dependencies: + '@img/sharp-wasm32': 0.35.5 + optional: true + + '@img/sharp-win32-arm64@0.35.5': + optional: true + + '@img/sharp-win32-ia32@0.35.5': + optional: true + + '@img/sharp-win32-x64@0.35.5': + optional: true + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.6.0 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.6.0': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.6.0 + + '@next/env@16.4.2': {} + + '@next/swc-darwin-arm64@16.4.2': + optional: true + + '@next/swc-darwin-x64@16.4.2': + optional: true + + '@next/swc-linux-arm64-gnu@16.4.2': + optional: true + + '@next/swc-linux-arm64-musl@16.4.2': + optional: true + + '@next/swc-linux-x64-gnu@16.4.2': + optional: true + + '@next/swc-linux-x64-musl@16.4.2': + optional: true + + '@next/swc-win32-arm64-msvc@16.4.2': + optional: true + + '@next/swc-win32-x64-msvc@16.4.2': + optional: true + + '@swc/helpers@0.5.23': + dependencies: + tslib: 2.8.1 + + '@tailwindcss/node@4.3.3': + dependencies: + '@jridgewell/remapping': 2.3.5 + enhanced-resolve: 5.26.0 + jiti: 2.7.0 + lightningcss: 1.32.0 + magic-string: 0.30.21 + source-map-js: 1.2.2 + tailwindcss: 4.3.3 + + '@tailwindcss/oxide-android-arm64@4.3.3': + optional: true + + '@tailwindcss/oxide-darwin-arm64@4.3.3': + optional: true + + '@tailwindcss/oxide-darwin-x64@4.3.3': + optional: true + + '@tailwindcss/oxide-freebsd-x64@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-arm64-gnu@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-arm64-musl@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-x64-gnu@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-x64-musl@4.3.3': + optional: true + + '@tailwindcss/oxide-wasm32-wasi@4.3.3': + optional: true + + '@tailwindcss/oxide-win32-arm64-msvc@4.3.3': + optional: true + + '@tailwindcss/oxide-win32-x64-msvc@4.3.3': + optional: true + + '@tailwindcss/oxide@4.3.3': + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.3.3 + '@tailwindcss/oxide-darwin-arm64': 4.3.3 + '@tailwindcss/oxide-darwin-x64': 4.3.3 + '@tailwindcss/oxide-freebsd-x64': 4.3.3 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.3 + '@tailwindcss/oxide-linux-arm64-gnu': 4.3.3 + '@tailwindcss/oxide-linux-arm64-musl': 4.3.3 + '@tailwindcss/oxide-linux-x64-gnu': 4.3.3 + '@tailwindcss/oxide-linux-x64-musl': 4.3.3 + '@tailwindcss/oxide-wasm32-wasi': 4.3.3 + '@tailwindcss/oxide-win32-arm64-msvc': 4.3.3 + '@tailwindcss/oxide-win32-x64-msvc': 4.3.3 + + '@tailwindcss/postcss@4.3.3': + dependencies: + '@alloc/quick-lru': 5.3.0 + '@tailwindcss/node': 4.3.3 + '@tailwindcss/oxide': 4.3.3 + postcss: 8.5.31 + tailwindcss: 4.3.3 + + '@types/node@24.19.2': + dependencies: + undici-types: 7.24.6 + + '@types/react-dom@19.3.0(@types/react@19.3.0)': + dependencies: + '@types/react': 19.3.0 + + '@types/react@19.3.0': + dependencies: + csstype: 3.2.3 + + baseline-browser-mapping@2.11.32: {} + + caniuse-lite@1.0.30001819: {} + + client-only@0.0.1: {} + + csstype@3.2.3: {} + + detect-libc@2.1.2: {} + + enhanced-resolve@5.26.0: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.3 + + graceful-fs@4.2.11: {} + + jiti@2.7.0: {} + + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + + lucide-react@1.61.0(@types/react@19.3.0)(react@19.3.1): + dependencies: + react: 19.3.1 + optionalDependencies: + '@types/react': 19.3.0 + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.6.0 + + nanoid@3.3.20: {} + + next@16.4.2(@types/node@24.19.2)(react-dom@19.3.1(react@19.3.1))(react@19.3.1): + dependencies: + '@next/env': 16.4.2 + '@swc/helpers': 0.5.23 + baseline-browser-mapping: 2.11.32 + caniuse-lite: 1.0.30001819 + postcss: 8.5.23 + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + styled-jsx: 5.1.6(react@19.3.1) + optionalDependencies: + '@next/swc-darwin-arm64': 16.4.2 + '@next/swc-darwin-x64': 16.4.2 + '@next/swc-linux-arm64-gnu': 16.4.2 + '@next/swc-linux-arm64-musl': 16.4.2 + '@next/swc-linux-x64-gnu': 16.4.2 + '@next/swc-linux-x64-musl': 16.4.2 + '@next/swc-win32-arm64-msvc': 16.4.2 + '@next/swc-win32-x64-msvc': 16.4.2 + sharp: 0.35.5(@types/node@24.19.2) + transitivePeerDependencies: + - '@babel/core' + - '@types/node' + - babel-plugin-macros + + picocolors@1.1.1: {} + + postcss@8.5.23: + dependencies: + nanoid: 3.3.20 + picocolors: 1.1.1 + source-map-js: 1.2.2 + + postcss@8.5.31: + dependencies: + nanoid: 3.3.20 + picocolors: 1.1.1 + source-map-js: 1.2.2 + + react-dom@19.3.1(react@19.3.1): + dependencies: + react: 19.3.1 + scheduler: 0.28.0 + + react@19.3.1: {} + + scheduler@0.28.0: {} + + semver@7.8.5: + optional: true + + sharp@0.35.5(@types/node@24.19.2): + dependencies: + '@img/colour': 1.1.0 + detect-libc: 2.1.2 + semver: 7.8.5 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.35.5 + '@img/sharp-darwin-x64': 0.35.5 + '@img/sharp-freebsd-wasm32': 0.35.5 + '@img/sharp-libvips-darwin-arm64': 1.3.4 + '@img/sharp-libvips-darwin-x64': 1.3.4 + '@img/sharp-libvips-linux-arm': 1.3.4 + '@img/sharp-libvips-linux-arm64': 1.3.4 + '@img/sharp-libvips-linux-ppc64': 1.3.4 + '@img/sharp-libvips-linux-riscv64': 1.3.4 + '@img/sharp-libvips-linux-s390x': 1.3.4 + '@img/sharp-libvips-linux-x64': 1.3.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.3.4 + '@img/sharp-libvips-linuxmusl-x64': 1.3.4 + '@img/sharp-linux-arm': 0.35.5 + '@img/sharp-linux-arm64': 0.35.5 + '@img/sharp-linux-ppc64': 0.35.5 + '@img/sharp-linux-riscv64': 0.35.5 + '@img/sharp-linux-s390x': 0.35.5 + '@img/sharp-linux-x64': 0.35.5 + '@img/sharp-linuxmusl-arm64': 0.35.5 + '@img/sharp-linuxmusl-x64': 0.35.5 + '@img/sharp-webcontainers-wasm32': 0.35.5 + '@img/sharp-win32-arm64': 0.35.5 + '@img/sharp-win32-ia32': 0.35.5 + '@img/sharp-win32-x64': 0.35.5 + '@types/node': 24.19.2 + optional: true + + source-map-js@1.2.2: {} + + styled-jsx@5.1.6(react@19.3.1): + dependencies: + client-only: 0.0.1 + react: 19.3.1 + + tailwindcss@4.3.3: {} + + tapable@2.3.3: {} + + tslib@2.8.1: {} + + typescript@5.9.3: {} + + undici-types@7.24.6: {} diff --git a/postcss.config.mjs b/apps/studio/postcss.config.mjs similarity index 100% rename from postcss.config.mjs rename to apps/studio/postcss.config.mjs diff --git a/apps/studio/src/content/ideas.ts b/apps/studio/src/content/ideas.ts new file mode 100644 index 0000000..02c51a4 --- /dev/null +++ b/apps/studio/src/content/ideas.ts @@ -0,0 +1,3 @@ +export type Idea = {slug:string; title:string; summary:string; slides:{heading:string;body:string;color:string}[]}; +// Add a page here; the page, AI text and export bundle share this source. +export const ideas:Idea[]=[{slug:'first-idea',title:'把一个想法,变成一组画面',summary:'从一句话出发,写成页面,再导出为图文或视频。',slides:[{heading:'先捕捉,再打磨',body:'把今天的灵感写下来。不用急着完整,先留下那个让你心动的瞬间。',color:'#ffe5df'},{heading:'让每一页只讲一件事',body:'一个标题,一段解释,一个值得被记住的画面。',color:'#e2e9e1'},{heading:'选择你的表达方式',body:'导出图文长页,或用 Python 将画面制作成视频。',color:'#eee5f5'}]}]; diff --git a/apps/studio/src/pages/_app.tsx b/apps/studio/src/pages/_app.tsx new file mode 100644 index 0000000..f7a5d61 --- /dev/null +++ b/apps/studio/src/pages/_app.tsx @@ -0,0 +1,3 @@ +import type { AppProps } from "next/app"; +import "../styles/globals.css"; +export default function App({Component,pageProps}:AppProps){return ;} diff --git a/apps/studio/src/pages/api/export/[slug].ts b/apps/studio/src/pages/api/export/[slug].ts new file mode 100644 index 0000000..1b2451f --- /dev/null +++ b/apps/studio/src/pages/api/export/[slug].ts @@ -0,0 +1,3 @@ +import type {NextApiRequest,NextApiResponse} from 'next'; +import {ideas} from '../../../content/ideas'; +export default function handler(req:NextApiRequest,res:NextApiResponse){if(req.method!=='GET')return res.status(405).end();const idea=ideas.find(i=>i.slug===req.query.slug);if(!idea)return res.status(404).end();if(req.query.format==='markdown'){res.setHeader('Content-Type','text/markdown; charset=utf-8');return res.send('# '+idea.title+'\n\n'+idea.summary+'\n\n'+idea.slides.map(s=>'## '+s.heading+'\n\n'+s.body).join('\n\n'));}res.setHeader('Content-Disposition',`attachment; filename="${idea.slug}.json"`);return res.json({version:1,...idea});} diff --git a/apps/studio/src/pages/api/index.ts b/apps/studio/src/pages/api/index.ts new file mode 100644 index 0000000..de07d5f --- /dev/null +++ b/apps/studio/src/pages/api/index.ts @@ -0,0 +1,3 @@ +import type {NextApiRequest,NextApiResponse} from 'next'; +import {ideas} from '../../content/ideas'; +export default function handler(_:NextApiRequest,res:NextApiResponse){res.setHeader('Content-Type','text/markdown; charset=utf-8');res.send('# 创作站\n\n'+ideas.map(i=>`- [${i.title}](/ideas/${i.slug}) · [正文](/api/export/${i.slug}?format=markdown)`).join('\n'));} diff --git a/apps/studio/src/pages/ideas/[slug].tsx b/apps/studio/src/pages/ideas/[slug].tsx new file mode 100644 index 0000000..26afce1 --- /dev/null +++ b/apps/studio/src/pages/ideas/[slug].tsx @@ -0,0 +1,7 @@ +import type {GetStaticPaths,GetStaticProps} from 'next'; +import Head from 'next/head'; +import Link from 'next/link'; +import {ideas,type Idea} from '../../content/ideas'; +export default function IdeaPage({idea}:{idea:Idea}){return
{idea.title} · 创作站
← 我的创作导出内容包 ↓Markdown ↓

{idea.title}

{idea.summary}

{idea.slides.map((s,i)=>
PROMPT STUDIO / {String(i+1).padStart(2,'0')}

{s.heading}

{s.body}

记录灵感 · 自由表达
)}
} +export const getStaticPaths:GetStaticPaths=async()=>({paths:ideas.map(i=>({params:{slug:i.slug}})),fallback:false}); +export const getStaticProps:GetStaticProps=async({params})=>{const idea=ideas.find(i=>i.slug===params?.slug);return idea?{props:{idea}}:{notFound:true}}; diff --git a/apps/studio/src/pages/index.tsx b/apps/studio/src/pages/index.tsx new file mode 100644 index 0000000..3ee6974 --- /dev/null +++ b/apps/studio/src/pages/index.tsx @@ -0,0 +1,3 @@ +import Link from 'next/link'; +import {ideas} from '../content/ideas'; +export default function Home(){return
YOUR CREATIVE WORKSPACE

今天,想表达什么?

一个页面,装下一个想法。让内容慢慢长成作品。

{ideas.map(i=>
{i.title}

{i.title}

{i.summary}

打开创作 →)}

新增作品:在 src/content/ideas.ts 添加内容,页面与导出会同步生成。

} diff --git a/apps/studio/src/styles/globals.css b/apps/studio/src/styles/globals.css new file mode 100644 index 0000000..1962a04 --- /dev/null +++ b/apps/studio/src/styles/globals.css @@ -0,0 +1,2 @@ +@import "tailwindcss"; +*{box-sizing:border-box}body{margin:0;color:#242424;background:#faf9f7;font-family:Arial,"PingFang SC",sans-serif}a{color:inherit;text-decoration:none}button,a{cursor:pointer}button{border:0;padding:12px 22px;border-radius:24px}.workspace{display:grid;grid-template-columns:240px 1fr;min-height:100vh}aside{padding:38px 26px;border-right:1px solid #eee;background:white}aside a{display:block;margin-top:30px}.logo{color:#ff2442}section{padding:70px 6vw}h1{font-size:40px;letter-spacing:-1.5px}section>p,.hint{color:#888}.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,340px));gap:24px;margin-top:45px}.card{background:white;padding:14px;border-radius:22px;border:1px solid #eee}.cover{background:#ffe5df;aspect-ratio:4/5;border-radius:14px;padding:36px;display:flex;align-items:center;font-size:35px;font-weight:bold}.card h2{font-size:18px}.card p{line-height:1.8;color:#888}.card span{color:#ff2442}.hint{margin-top:40px;font-size:13px}.editor{max-width:1200px;margin:auto;padding:30px}header{display:flex;align-items:center;gap:24px}header a:first-child{margin-right:auto}.slides{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;margin-top:40px}.slide{aspect-ratio:3/4;padding:35px;border-radius:20px;display:flex;flex-direction:column}.slide h2{font-size:38px;margin-top:auto}.slide p{line-height:1.9}.slide footer{margin-top:auto;font-size:12px}@media(max-width:760px){.workspace{grid-template-columns:1fr}aside{border-bottom:1px solid #eee}aside a{display:inline-block;margin:20px 20px 0 0}section{padding:30px}.slides{grid-template-columns:1fr}header{flex-wrap:wrap}h1{font-size:30px}}@media print{header{display:none}.slides{display:block}.slide{width:180mm;height:240mm;break-after:page;print-color-adjust:exact;border-radius:0}.editor>h1,.editor>p{display:none}} diff --git a/tsconfig.json b/apps/studio/tsconfig.json similarity index 100% rename from tsconfig.json rename to apps/studio/tsconfig.json diff --git a/.env.example b/apps/wiki/.env.example similarity index 100% rename from .env.example rename to apps/wiki/.env.example diff --git a/apps/wiki/Dockerfile b/apps/wiki/Dockerfile new file mode 100644 index 0000000..6f004ea --- /dev/null +++ b/apps/wiki/Dockerfile @@ -0,0 +1,33 @@ +FROM node:24-bookworm-slim AS base +ENV NEXT_TELEMETRY_DISABLED=1 +WORKDIR /app +RUN apt-get update \ + && apt-get install -y --no-install-recommends ffmpeg ca-certificates chromium fonts-noto-cjk \ + && rm -rf /var/lib/apt/lists/* + +FROM base AS dependencies +RUN corepack enable && corepack prepare pnpm@11.25.0 --activate +COPY apps/wiki/package.json apps/wiki/pnpm-lock.yaml ./ +RUN pnpm install --frozen-lockfile + +FROM dependencies AS build +# .dockerignore excludes docs and operational notes without extra legacy COPY snapshots. +COPY apps/wiki/ . +RUN pnpm typecheck && pnpm test && pnpm build && pnpm test:smoke + +FROM build AS integration +USER node +CMD ["npm", "run", "test:integration"] + +FROM base AS runtime +ENV NODE_ENV=production HOSTNAME=0.0.0.0 PORT=3000 \ + FFMPEG_PATH=/usr/bin/ffmpeg FFPROBE_PATH=/usr/bin/ffprobe +COPY --from=build --chown=node:node /app/.next/standalone/ ./ +COPY --from=build --chown=node:node /app/dist/worker.cjs /app/dist/bootstrap.cjs /app/dist/publish-learning-series.cjs ./ +COPY --from=build --chown=node:node /app/db/ ./db/ +COPY --chown=node:node apps/wiki/scripts/container-health.mjs apps/wiki/scripts/wait-snapshots.mjs ./ +COPY --chown=node:node apps/wiki/scripts/import-character-packs.mjs ./scripts/import-character-packs.mjs +COPY --chown=node:node apps/wiki/seed/characters/ ./seed/characters/ +USER node +EXPOSE 3000 +CMD ["node", "server.js"] diff --git a/db/001_library.sql b/apps/wiki/db/001_library.sql similarity index 100% rename from db/001_library.sql rename to apps/wiki/db/001_library.sql diff --git a/db/002_page_snapshots.sql b/apps/wiki/db/002_page_snapshots.sql similarity index 100% rename from db/002_page_snapshots.sql rename to apps/wiki/db/002_page_snapshots.sql diff --git a/apps/wiki/next-env.d.ts b/apps/wiki/next-env.d.ts new file mode 100644 index 0000000..15849f6 --- /dev/null +++ b/apps/wiki/next-env.d.ts @@ -0,0 +1,7 @@ +/// +/// +import "./.next/types/routes.d.ts"; +import "./.next/types/root-params.d.ts"; + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/pages/api-reference/config/typescript for more information. diff --git a/next.config.ts b/apps/wiki/next.config.ts similarity index 91% rename from next.config.ts rename to apps/wiki/next.config.ts index 3428686..6e39365 100644 --- a/next.config.ts +++ b/apps/wiki/next.config.ts @@ -10,7 +10,7 @@ const nextConfig: NextConfig = { {source:"/agent/index.md",destination:"/api/agent-index"}, {source:"/skills/:skill/:doc.md",destination:"/api/skill-docs/:skill/:doc"}, ]}, - output: "standalone", + output: "standalone", outputFileTracingRoot: process.cwd(), outputFileTracingIncludes: {"/*":["./node_modules/playwright-core/**/*"]}, poweredByHeader: false, }; diff --git a/apps/wiki/package.json b/apps/wiki/package.json new file mode 100644 index 0000000..484a438 --- /dev/null +++ b/apps/wiki/package.json @@ -0,0 +1,45 @@ +{ + "name": "@prompt/wiki", + "version": "0.1.0", + "private": true, + "engines": { + "node": ">=24 <25" + }, + "scripts": { + "dev": "next dev", + "build": "next build && esbuild src/worker.ts --bundle --platform=node --format=cjs --external:pg-native --external:playwright-core --outfile=dist/worker.cjs && esbuild scripts/bootstrap.ts --bundle --platform=node --format=cjs --external:pg-native --external:playwright-core --outfile=dist/bootstrap.cjs && esbuild scripts/publish-learning-series.ts --bundle --platform=node --format=cjs --external:pg-native --external:playwright-core --outfile=dist/publish-learning-series.cjs && node scripts/prepare-standalone.mjs", + "start": "next start", + "typecheck": "next typegen && tsc --noEmit", + "test": "tsx --test tests/health.test.ts tests/model.test.ts tests/learning-series.test.ts tests/skill-docs.test.ts tests/wiki.test.ts", + "test:smoke": "node scripts/smoke.mjs", + "storage:prepare": "tsx scripts/bootstrap.ts", + "content:publish-learning": "tsx scripts/publish-learning-series.ts", + "worker": "tsx src/worker.ts", + "test:integration": "tsx --test tests/integration.test.ts" + }, + "dependencies": { + "@aws-sdk/client-s3": "3.1155.0", + "formidable": "3.5.4", + "lucide-react": "1.61.0", + "next": "16.4.2", + "pg": "8.23.1", + "playwright-core": "1.56.1", + "react": "19.3.1", + "react-dom": "19.3.1", + "sharp": "0.35.5", + "zod": "4.6.7" + }, + "devDependencies": { + "@tailwindcss/postcss": "4.3.3", + "@types/formidable": "3.5.1", + "@types/node": "24.19.2", + "@types/pg": "8.23.1", + "@types/react": "19.3.0", + "@types/react-dom": "19.3.0", + "esbuild": "0.28.2", + "tailwindcss": "4.3.3", + "tsx": "4.23.15", + "typescript": "5.9.3" + }, + "packageManager": "pnpm@11.25.0" +} diff --git a/apps/wiki/pnpm-lock.yaml b/apps/wiki/pnpm-lock.yaml new file mode 100644 index 0000000..15057e1 --- /dev/null +++ b/apps/wiki/pnpm-lock.yaml @@ -0,0 +1,1826 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@aws-sdk/client-s3': + specifier: 3.1155.0 + version: 3.1155.0 + formidable: + specifier: 3.5.4 + version: 3.5.4 + lucide-react: + specifier: 1.61.0 + version: 1.61.0(@types/react@19.3.0)(react@19.3.1) + next: + specifier: 16.4.2 + version: 16.4.2(@types/node@24.19.2)(react-dom@19.3.1(react@19.3.1))(react@19.3.1) + pg: + specifier: 8.23.1 + version: 8.23.1 + playwright-core: + specifier: 1.56.1 + version: 1.56.1 + react: + specifier: 19.3.1 + version: 19.3.1 + react-dom: + specifier: 19.3.1 + version: 19.3.1(react@19.3.1) + sharp: + specifier: 0.35.5 + version: 0.35.5(@types/node@24.19.2) + zod: + specifier: 4.6.7 + version: 4.6.7 + devDependencies: + '@tailwindcss/postcss': + specifier: 4.3.3 + version: 4.3.3 + '@types/formidable': + specifier: 3.5.1 + version: 3.5.1 + '@types/node': + specifier: 24.19.2 + version: 24.19.2 + '@types/pg': + specifier: 8.23.1 + version: 8.23.1 + '@types/react': + specifier: 19.3.0 + version: 19.3.0 + '@types/react-dom': + specifier: 19.3.0 + version: 19.3.0(@types/react@19.3.0) + esbuild: + specifier: 0.28.2 + version: 0.28.2 + tailwindcss: + specifier: 4.3.3 + version: 4.3.3 + tsx: + specifier: 4.23.15 + version: 4.23.15 + typescript: + specifier: 5.9.3 + version: 5.9.3 + +packages: + + '@alloc/quick-lru@5.3.0': + resolution: {integrity: sha512-U4+70Pc5ZS9osnCBCE5Jha/ciHM+Yp+CNMNC/7HvYbNRk1Ldd+f7qO65W5qfhu/TCv+/ozljlXXe9Nj8419DMA==} + engines: {node: '>=10'} + + '@aws-sdk/checksums@3.1001.5': + resolution: {integrity: sha512-6erto9nK2OZO/woEgmFIaPh5gChgdNd7nL6jgAf8TAXz3/QHC8Pan2TFe9GYp3IxOIKCCGWPylSjtOHKfNzQlw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/client-s3@3.1155.0': + resolution: {integrity: sha512-l3uMeIlzWVgj/RTJTh5sKYKtQz1la3cvWLUPn1cwFH4UZpcqTH66SgJHCeB2FOE9bEAjOdbmCyPKt9aw867Fng==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/core@3.978.5': + resolution: {integrity: sha512-ruI0AWqcrfL20XDS6SwZIJFPOBZ6N0ADa9nLzWlBhxk1aoUjbUX3JkTR9vEmk7o35XpAHi68ahZ4T6RE2U9XyA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-env@3.972.76': + resolution: {integrity: sha512-YxmL1Ar7bV9ZkJvtv+lj+MF6le76NnZnbmgySyZuxpZaCv0/1lZ3KxKy6RIj1h9ui2hWnVjZxbmTMeO0y/NrQA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-http@3.972.78': + resolution: {integrity: sha512-3VHknDRngoebsaqyT1iR75b5cBT2zfEtODK6yYmYltljkK1HEAQLs2FEd1IpWqAeOYdMGaG9wikngWLTufY7RA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-ini@3.973.21': + resolution: {integrity: sha512-aLx9hbCX6mGAyv4ZZd8UagJ4RASHVJw6BFDSIyuKmLkqNL6H47EjBPK6qaJ4B5TDV6mc+vMa0SJFYyo4mkvVQg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-login@3.972.83': + resolution: {integrity: sha512-9bJU6FjRacF4FK/QHf8Dyxhur7B1grRj8C1Yh4IkpoFW2exQflPdCv0VrbemLW9ZctLNle+AE7TETs9KNvuLYg==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-node@3.972.88': + resolution: {integrity: sha512-AG0KID5qhQPzrFkh5b0Cws1Amytvzo0L0Xj6hMgJXEwD6ZXAqninDhSNAWJiN5zU4YVVZnuidnqwPwYJ04IamA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-process@3.972.76': + resolution: {integrity: sha512-pdhKFTXv1zPYhh92MTlp0jVbLWvUEV9v+rziuEkoskGGQ2iJskxHTO38nA8UAbT/N4IM3n8OZJ9rIY5IBO15/A==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-sso@3.973.20': + resolution: {integrity: sha512-DlxrAB3MnjNLx/da7b89W+3DyJQYso/q7Ns15MsST2IV2nkAYQOYTUCaffNSjgrpMP99Dm2mV2jxzcbyF94ZfA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/credential-provider-web-identity@3.972.82': + resolution: {integrity: sha512-LUo46IqPTJ4xKBsrLuoaxiv/D2GTBCcFDMD1y3jKIqPR/p7Rw14RJFZ0iRWftqZtyLPQX9JMGnSi3mBu4y/pNA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/middleware-sdk-s3@3.972.81': + resolution: {integrity: sha512-jfanv1pV0sJFZw6/DPiNjvK7B478god0zOum5yIWo+/+1Gy+CSXWpGBWx+3nBJyDvjcu/2kUMr4ADUp9BHH34Q==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/nested-clients@3.997.50': + resolution: {integrity: sha512-nKb8qu4QsnpZTq/6JIXc72mzuzfh7BK4sUQkpQznPec2z4W7Ob2xYkcM4i5e1yGTBnbJVeFv/0sf3jcz85hclA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/signature-v4-multi-region@3.996.49': + resolution: {integrity: sha512-nvuAZNRrRRVCiARRKsYlQ0VnXiEQiq7vXPH+UA+LSo+kN3Djl9eo/V2r0udkw85PnsNshmv2Em1clld5M3j67w==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/token-providers@3.1155.0': + resolution: {integrity: sha512-iIcQnYLhWuq9qOLQbIWFrxF3PF0svVeZvHnUS4DUnO4zUFmFHIyGyjqrntXG+e/5PUgfavV0pYfDIKHxTzN2LA==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/types@3.975.0': + resolution: {integrity: sha512-WQlhs6juByzWOzj5fwxOx0mPJaEqMcG/sDpl3Id61B3XhKE63xY+0QWcnG+sWR/sCfprmreyUo1lM7IKZmHMzw==} + engines: {node: '>=20.0.0'} + + '@aws-sdk/xml-builder@3.972.41': + resolution: {integrity: sha512-ctjVSyCMegrWfXlx6VqzSBFI6UqmQ5ZlnfMhdLIiWmhoH8UAQxSCP5N3OpG7X3k4LnS7ou74C4mt20+bfTW2aQ==} + engines: {node: '>=20.0.0'} + + '@aws/lambda-invoke-store@0.3.0': + resolution: {integrity: sha512-sl4Bm6yiMNYrZKkqqDFWN0UfnWhlS8ivKxrYl+6t0gCLrqr8y3B2IqZZbFRkfaVVp7C/baApyh71P+LeE1A2sQ==} + engines: {node: '>=18.0.0'} + + '@emnapi/runtime@1.11.3': + resolution: {integrity: sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==} + + '@esbuild/aix-ppc64@0.28.2': + resolution: {integrity: sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.28.2': + resolution: {integrity: sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.28.2': + resolution: {integrity: sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.28.2': + resolution: {integrity: sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.28.2': + resolution: {integrity: sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.28.2': + resolution: {integrity: sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.28.2': + resolution: {integrity: sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.28.2': + resolution: {integrity: sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.28.2': + resolution: {integrity: sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.28.2': + resolution: {integrity: sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.28.2': + resolution: {integrity: sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.28.2': + resolution: {integrity: sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.28.2': + resolution: {integrity: sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.28.2': + resolution: {integrity: sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.28.2': + resolution: {integrity: sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.28.2': + resolution: {integrity: sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.28.2': + resolution: {integrity: sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.28.2': + resolution: {integrity: sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.28.2': + resolution: {integrity: sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.28.2': + resolution: {integrity: sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.28.2': + resolution: {integrity: sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.28.2': + resolution: {integrity: sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.28.2': + resolution: {integrity: sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.28.2': + resolution: {integrity: sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.28.2': + resolution: {integrity: sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.28.2': + resolution: {integrity: sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@img/colour@1.1.0': + resolution: {integrity: sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==} + engines: {node: '>=18'} + + '@img/sharp-darwin-arm64@0.35.5': + resolution: {integrity: sha512-QRUlFQ0WxvdWyqqG/WtI3iupfD5rBzmCHXSdPsY91sAtVtTo7Q4cb6zOccZ3gqEqkr0f1As1ehLqmEpDsRf+lg==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.35.5': + resolution: {integrity: sha512-+BR255RhDlpygUpOc/Jdt1nT6DQ3XG/ERo5wbcdOf5Q320dKtPCKPLR1LJs9VGXRaMa8l1uUa0tkCNOXiAxZUw==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [darwin] + + '@img/sharp-freebsd-wasm32@0.35.5': + resolution: {integrity: sha512-Y/z91nEZ4uIBX5X3nfTovjU9lHNKFYbL2lpHCLVNmXQK03VIZvXBBt0KxbPGp2SdGSF+2mQU4e+hQaWOt86iAw==} + engines: {node: '>=20.9.0'} + os: [freebsd] + + '@img/sharp-libvips-darwin-arm64@1.3.4': + resolution: {integrity: sha512-5R89nBYiRdUlSWJxPhO+GVtaXzXSxKnRu/xqMn3KTA3L9EB9Oy/P+Nn2f2vlhPuUdy/Zusb2DarbyTpGCfEDuw==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.3.4': + resolution: {integrity: sha512-iR2OKH80yi0U+dUplyh3/xdpFvps6YkCwsXenIJxqxR1v9o+xtKTGbS9H7cps+2Vxjc8B1j96p75NmTGjIhtpQ==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.3.4': + resolution: {integrity: sha512-Y3dgX/6lE2QhQb+Gxy0WZxfg9MEm/JBjamZpS2IklP7xIQoKN4hzAm7KcMVGtaVDt3neE9OKBC7vAfonA/Lr1A==} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-arm@1.3.4': + resolution: {integrity: sha512-LmRtTsOHuvM2+wlO2Db37dx5MiZhB0FvSunciw48YjdOkZz9KAiRbm8ujeMOA1INqmei5NapFxYEK1D1ZSidmw==} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-ppc64@1.3.4': + resolution: {integrity: sha512-Le6boB8Tai0Nis+gIxIpKx68UDVVIqdR8Tin5Yf1z2LJJQLDJvCDRqRu+jC2qCoD+eIomonmOwB4smBRxfVpYQ==} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-riscv64@1.3.4': + resolution: {integrity: sha512-aHkkIEHPRdQEegJN20MLmGtxYD9R2wQr3Cwpddnu5+YKMt6Uzax7S9h5gpZTo8wyrGuZSlfQ63OevL5mTyOC7Q==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-s390x@1.3.4': + resolution: {integrity: sha512-ra/mB6MikESDUO7Yg+Mi95bFBb9GsObURuhnOv3OqknjGe9sZrG8tCe9q0xSIGrtLgvgw0gKnFWcK4blSgQOuQ==} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linux-x64@1.3.4': + resolution: {integrity: sha512-GJ//SSXbnwSDes02umB3nDJLFcQzw8a18V8fyhqr6tV515tOEMdImjjxj1AoafMRz56F3PHgftnj1QEKSU1zkw==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@img/sharp-libvips-linuxmusl-arm64@1.3.4': + resolution: {integrity: sha512-hvulFwtjUcagsis6BBxHwGFwWoNZjgYmULGVrZcyfNbjA8hKILbRxGg15/7w5HDyXHXUos/j6baAWqnCyQ2DWA==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@img/sharp-libvips-linuxmusl-x64@1.3.4': + resolution: {integrity: sha512-6zXKeE/p39I1AmA3cJG35eyBGNqNddLnUXjhwBnsGjFPWqf5VKkDBEqaEkPDoTEtkxwi2vv8Tcr2mDyP4So7Fg==} + cpu: [x64] + os: [linux] + libc: [musl] + + '@img/sharp-linux-arm64@0.35.5': + resolution: {integrity: sha512-LYVx5JTsOM2CBzmxreh+nl64/3H6Xb09iSLknqH47z2T2DFFxDeFLP5y4dJwe6H7uGQlHPyEEtIqyo3DYsRwdQ==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-arm@0.35.5': + resolution: {integrity: sha512-LEaXK2WdXVK5ykcw0buWyPMsmLLL2vpHLD6yrNSW+JGEL3BZPA4tpKN6iaMc4AxTTAoaX/sU1rOL51lcIz48ZQ==} + engines: {node: '>=20.9.0'} + cpu: [arm] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-ppc64@0.35.5': + resolution: {integrity: sha512-QVxAAq8evVRI9ia2vqgwrmWucn5Dfv+JdWzj75pD8omHLPSP7f8p20O8jxzjCcuCEQEOtYOZUmX1hkiZ0kdevA==} + engines: {node: '>=20.9.0'} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-riscv64@0.35.5': + resolution: {integrity: sha512-LtdreXguaavKODPIfzJ4kffx7UNt1omwtK0rch4EBbbSTXPnxWmYSayXdLJw0fJzQ97kHt1gL/yh4tvU+nCyRQ==} + engines: {node: '>=20.9.0'} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-s390x@0.35.5': + resolution: {integrity: sha512-UZasTOFiYzotTsGOCu42BfUzP6Tu6Do/947iRm1RsLKvlllxwGcn4RN27LibGWceix4Y+Pmw3jsnTcCQIgWjqA==} + engines: {node: '>=20.9.0'} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@img/sharp-linux-x64@0.35.5': + resolution: {integrity: sha512-SxFtLTeJInhAA9Q836kux2vZNeOBQEx658qvbboZScr0wIARym3IcGmW7KpVD5sbVg0Ojy+udFQdayYIZyoNog==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@img/sharp-linuxmusl-arm64@0.35.5': + resolution: {integrity: sha512-9HbMclmI1zlNkFRs3z9/eBtDjfD0sGlrX1z6b1qwmiFY5ElDLh4BC0LPBdVp7z1DXFiKlIcznf+ZlsuZzLxQqg==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@img/sharp-linuxmusl-x64@0.35.5': + resolution: {integrity: sha512-4KOphqB035HrVdqLZfCgMzzERrQkkzOwRhl4OAkRO1YCldbaFjySXMaK534Mo0V+LndnlJk+sbUyLeU0ULyD1A==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@img/sharp-wasm32@0.35.5': + resolution: {integrity: sha512-Ptsga1su4tQx+LLF1ECS9U6nz5kmrXKo6XVbtR48Ke3ZRxxgaWBu7IDtEe1quo8hiupwm6WFqxVlXaSf7IINGQ==} + engines: {node: '>=20.9.0'} + + '@img/sharp-webcontainers-wasm32@0.35.5': + resolution: {integrity: sha512-hfhF/FmoQyTUkA0bIKFOtw536BQSeBMe6BF6QyWlrPxT754+TFLaZ7sKKTfvvM0yJgKgaYTwnFCIZ/GuDw5SUA==} + engines: {node: '>=20.9.0'} + cpu: [wasm32] + + '@img/sharp-win32-arm64@0.35.5': + resolution: {integrity: sha512-X4t7g+7ZA5DKblCBEXGjUqqemj4vczING/5viFwAL8h4N3qYeyjwdCvRLHi4EdOUI+2Z7UFlp1VM+p/AuEtm6Q==} + engines: {node: '>=20.9.0'} + cpu: [arm64] + os: [win32] + + '@img/sharp-win32-ia32@0.35.5': + resolution: {integrity: sha512-5Zm82LoBc43nhwNybZlG7Y1KO//Zhsn306fQl29ZOuStHLGTo3BWL83q3cznX0poxSAMuYL1On/BHBxkBeKr6A==} + engines: {node: ^20.9.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.35.5': + resolution: {integrity: sha512-x76eH0vEiHlcMQu8Y8IenntaACtddpT6W0wmXtWrnKcnKI7ME5DdgqhAD6SEWOEl1v2zDvkZDhFA9KnURwpfqg==} + engines: {node: '>=20.9.0'} + cpu: [x64] + os: [win32] + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.6.0': + resolution: {integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@next/env@16.4.2': + resolution: {integrity: sha512-nTUTFH7G5/J/fmpkjVLegOkqyKOP0CEsJcMsyO4UCYeN1su+YMW/MfaSErnJskL7XM+UDK6aTvslxsRCyya/sA==} + + '@next/swc-darwin-arm64@16.4.2': + resolution: {integrity: sha512-ONkhFvZNFWlsEHOM/81AtxdyuJP2KRYKYR0JxPwvcu1AuPMMMgcL+wW2luldJvMtZwKtUxoSkCychW5wIeoYSw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + '@next/swc-darwin-x64@16.4.2': + resolution: {integrity: sha512-luPCMbOsCoaF+kXJEUjmjmOZg1lC3BflhmUu+ZmW4tBu2vW/4AXak8JBFvePizGkxVmNiAw/r9ra+6UviCWtWQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + '@next/swc-linux-arm64-gnu@16.4.2': + resolution: {integrity: sha512-xhwFTAncJyaCNy5KqKKuKaIIdCy1/1ZV1s5S1G0hhT7wGMkDTlfJ6aQbfRFnIG/s3/kDrxQ8aycVe+c5QnP8ow==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@next/swc-linux-arm64-musl@16.4.2': + resolution: {integrity: sha512-T1PNmfbPcxr5ndtWUL/3wQtLXsz808lq6sc2GrNT5k2oquF7UyqZddHSuAewHVsWsGXe6nsl9HoN1YNriVjuSg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@next/swc-linux-x64-gnu@16.4.2': + resolution: {integrity: sha512-N9cDUOCGtkJG5PNKDFZUF3xXndrJJcpLp121uAGjIGvO/U2p9tfdNOM9htj7+5f72l0m8rMw/cvYacUJBQoudg==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@next/swc-linux-x64-musl@16.4.2': + resolution: {integrity: sha512-yY2uh1YhX6ufuYy2FCbw1dqblbhI57GLYAJfCkqD9auTv6pLrH67Uccjc3QMKBeCYAG6lkgu08ExmX1bbjejjQ==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@next/swc-win32-arm64-msvc@16.4.2': + resolution: {integrity: sha512-j/ArWRIHpMMB6wYLMhr2puTguBt70lNU/Cmjl9p6dTDE8DGknYJMP9PdwPk2dqpCNL/KIX9yfngDvIesxJPmsg==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [win32] + + '@next/swc-win32-x64-msvc@16.4.2': + resolution: {integrity: sha512-AA4edyWHDko3NCSo0x6GomsdgFb0oR1J3MXU1b5xt6FRFg4AucrMPW3S0hCe/9onU0O1BbpGQBsqo1r0Gneu1g==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + '@noble/hashes@1.8.0': + resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} + engines: {node: ^14.21.3 || >=16} + + '@paralleldrive/cuid2@2.3.1': + resolution: {integrity: sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==} + + '@smithy/core@3.36.2': + resolution: {integrity: sha512-oRw0rB9QSUiCZfEs23G5F4Af+b2rQt1lItIICWu5IejFNd+uPM8SWqiKLMpQ6bX1Q7slsLbjuoE2niErFtkVPQ==} + engines: {node: '>=18.0.0'} + + '@smithy/credential-provider-imds@4.5.2': + resolution: {integrity: sha512-A9uSdn72ozbRUSit0eib0TW7nXuNPlaeM0zcGkJ+nE6tFcSDbnmtwoxbTCFBukVQcszDAyvsd7+rTduPTXpygg==} + engines: {node: '>=18.0.0'} + + '@smithy/fetch-http-handler@5.8.0': + resolution: {integrity: sha512-ycSJu3tFAQ4v04CBB0agqFMVsSQ1iG3yw+SpgxRqKfaURpQD4CZ8Wn0zPMmSnOuTpTh65Vz+EA0rMrw089wvkA==} + engines: {node: '>=18.0.0'} + + '@smithy/node-http-handler@4.12.1': + resolution: {integrity: sha512-ThMkboGeONWXAelq9FvGsuJC4rOi+qyC4/zhUF58xYpxUg5sQKx2VXZYJmtNjr4dSuBJ1HeJXETQILCz3wOHvw==} + engines: {node: '>=18.0.0'} + + '@smithy/signature-v4@5.7.4': + resolution: {integrity: sha512-tHy0K0VtqNd5Y7Y41h0a0Lhh0L1GzC08dTWg0F7vRJWFtTENg7IZikf3wQkanYIRdb7ngoIPMTmqgUi401fEeQ==} + engines: {node: '>=18.0.0'} + + '@smithy/types@4.19.0': + resolution: {integrity: sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==} + engines: {node: '>=18.0.0'} + + '@swc/helpers@0.5.23': + resolution: {integrity: sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==} + + '@tailwindcss/node@4.3.3': + resolution: {integrity: sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==} + + '@tailwindcss/oxide-android-arm64@4.3.3': + resolution: {integrity: sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.3.3': + resolution: {integrity: sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.3.3': + resolution: {integrity: sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.3.3': + resolution: {integrity: sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3': + resolution: {integrity: sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==} + engines: {node: '>= 20'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.3.3': + resolution: {integrity: sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@tailwindcss/oxide-linux-arm64-musl@4.3.3': + resolution: {integrity: sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@tailwindcss/oxide-linux-x64-gnu@4.3.3': + resolution: {integrity: sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@tailwindcss/oxide-linux-x64-musl@4.3.3': + resolution: {integrity: sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@tailwindcss/oxide-wasm32-wasi@4.3.3': + resolution: {integrity: sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + bundledDependencies: + - '@napi-rs/wasm-runtime' + - '@emnapi/core' + - '@emnapi/runtime' + - '@tybys/wasm-util' + - '@emnapi/wasi-threads' + - tslib + + '@tailwindcss/oxide-win32-arm64-msvc@4.3.3': + resolution: {integrity: sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [win32] + + '@tailwindcss/oxide-win32-x64-msvc@4.3.3': + resolution: {integrity: sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [win32] + + '@tailwindcss/oxide@4.3.3': + resolution: {integrity: sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==} + engines: {node: '>= 20'} + + '@tailwindcss/postcss@4.3.3': + resolution: {integrity: sha512-JTSZZGQi1AyKirbLN3azmjVzef92tcX7h+iSqPdaeStyFpGpDlKvvpxeOE8njhbUanbRwr3z8DyzhICWnMtQeg==} + + '@types/formidable@3.5.1': + resolution: {integrity: sha512-aFQijSGbD8JCeEST2LEbwR7faHynbt43lojLIcTM/QhB2U06h41ZVRFVEql+Z1xdL+aKGIzm69V/P/uSW9N6XA==} + + '@types/node@24.19.2': + resolution: {integrity: sha512-93d49wCWJkCyN87MxLpNN6KXPCwFw7bVUg79mGUV1OS40JGWwVCr8n61DXCSqz7CV6/VfPkb7xec7uP2M+QHWQ==} + + '@types/pg@8.23.1': + resolution: {integrity: sha512-fKVHpikPdg4GKks3JuLEhvwSyvwzF23hnabPy6DD8ljVbC7+6J5dQzdv4arV6jqq57djnMgs1HKBxX4P8aBI3A==} + + '@types/react-dom@19.3.0': + resolution: {integrity: sha512-ZI7bU42mZXXKHn/qNLEw2IrbiINU7X5+vfgdixBHkCNpYWXjKgfQ/P+uyGb5CjOLB9UcnTeg3rylQtV2hym44Q==} + peerDependencies: + '@types/react': ^19.3.0 + + '@types/react@19.3.0': + resolution: {integrity: sha512-N0rFCuH9YoxG9/m61l9MfpJKfmLOVU0em7ipIz6TRgSSkvReLB9vL85GB+yr8Bs5leqpvg96JSwF4ZS1s4viQg==} + + asap@2.0.6: + resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + + baseline-browser-mapping@2.11.32: + resolution: {integrity: sha512-UvuxFU9P3hM29LrQdwu0cD6w6/+SFr+UlB9s/knI7+O2rK9xFxKUwSDWxGdbbqQ9/V7BJ5s0NI5nQAE4uJp3gQ==} + engines: {node: '>=6.0.0'} + hasBin: true + + bowser@2.14.1: + resolution: {integrity: sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==} + + caniuse-lite@1.0.30001819: + resolution: {integrity: sha512-LFUqIIAwpzsIuevnKnsR9qnStBcgzPShTX61lBwN9uFkkf8o8zLiebEjbW8AYtZiF+1YKDWfdt/pWDtMuG8Xwg==} + + client-only@0.0.1: + resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + dezalgo@1.0.4: + resolution: {integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==} + + enhanced-resolve@5.26.0: + resolution: {integrity: sha512-9vhedylFonb2YGogzUKX6+Ja72gOJbN1QHAqdrvqLwhdl/QWbKopzoUC9EbQNVsAns/bx/4uyqalrQAoy1IByw==} + engines: {node: '>=10.13.0'} + + esbuild@0.28.2: + resolution: {integrity: sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==} + engines: {node: '>=18'} + hasBin: true + + formidable@3.5.4: + resolution: {integrity: sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==} + engines: {node: '>=14.0.0'} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + jiti@2.7.0: + resolution: {integrity: sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==} + hasBin: true + + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + + lucide-react@1.61.0: + resolution: {integrity: sha512-v2SQPPPNjnr+BlhL9Spuzmo5yR+hLkftfuE4E3jaxdNPgSH0hJKPcLJBP7yAta87jQNPsSERS59PJjCJ/CorBA==} + peerDependencies: + '@types/react': '*' + react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + nanoid@3.3.20: + resolution: {integrity: sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + next@16.4.2: + resolution: {integrity: sha512-r+oBJojfefUjOiWkBhXgLS+igxX/7BWyK59uHnyOyplMSLtBZ+QLP3okrdYTbrfrbrmNTVWLBPaHDX9KRaIt3w==} + engines: {node: '>=20.9.0'} + hasBin: true + peerDependencies: + '@opentelemetry/api': ^1.1.0 + '@playwright/test': ^1.51.1 + babel-plugin-react-compiler: '*' + react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 + react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 + sass: ^1.3.0 + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + '@playwright/test': + optional: true + babel-plugin-react-compiler: + optional: true + sass: + optional: true + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + pg-cloudflare@1.4.1: + resolution: {integrity: sha512-6PQbsFWZcp9EmJEwy5cGQ2La+AMWpP46lgbb8X+U/XsHIUweYDNCpeuKck5RxL2MdVFi7krbbEi5nX4Zh7JhrQ==} + + pg-connection-string@2.14.1: + resolution: {integrity: sha512-qR3kGNPBLpCNtz0evbKA0Y/MRFXwSSdT+pTJvYp/bXTcReZbvX1kzF0IyTc1QnxqF7AZbOeBhNL8R5mYQZV/MA==} + + pg-int8@1.0.1: + resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==} + engines: {node: '>=4.0.0'} + + pg-pool@3.14.0: + resolution: {integrity: sha512-gKtPkFdQPU3DksooVLi9LsjZxrsBUZIpa+7aVx+LV5pNh0KzP4Zleud2po+ConrxbuXGBJ6Hfer6hdgpIBpBaw==} + peerDependencies: + pg: '>=8.0' + + pg-protocol@1.16.1: + resolution: {integrity: sha512-p9VOFMiHB/ZbJATetbg+99PxssTVSQRnyuPSQ67mN1+1KBOjZaZ83ZQzltnxPhJwSsC3nwVjJ10DVJlerbFzLg==} + + pg-types@2.2.0: + resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==} + engines: {node: '>=4'} + + pg@8.23.1: + resolution: {integrity: sha512-aL96AHANtWjPLDOLqnhx+ngp9+UK7ETEU8VJrDCGvsSSi/mGLcWYsS6Herg7lmaBJe4uwrfqsa7gTEFaSizDoQ==} + engines: {node: '>= 16.0.0'} + peerDependencies: + pg-native: '>=3.0.1' + peerDependenciesMeta: + pg-native: + optional: true + + pgpass@1.0.5: + resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + playwright-core@1.56.1: + resolution: {integrity: sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==} + engines: {node: '>=18'} + hasBin: true + + postcss@8.5.23: + resolution: {integrity: sha512-g50586zr4bZmwFiTlflMu8E0bDTb5I5gertgwAKmsdUlTQIhZtunzUlD1WSzwcVWPoAVpsrA6vlfCD7oXvRwgg==} + engines: {node: ^10 || ^12 || >=14} + + postcss@8.5.31: + resolution: {integrity: sha512-YUbWYCgErwnMAVkjUnYa+KlMBzGpHwiIt/DE7f0G33AuX2LH9UcTk6KgWxd3zRU+pN3u/C+Xl3EnMLM4Hea7Sg==} + engines: {node: ^10 || ^12 || >=14} + + postgres-array@2.0.0: + resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} + engines: {node: '>=4'} + + postgres-bytea@1.0.1: + resolution: {integrity: sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==} + engines: {node: '>=0.10.0'} + + postgres-date@1.0.7: + resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==} + engines: {node: '>=0.10.0'} + + postgres-interval@1.2.0: + resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==} + engines: {node: '>=0.10.0'} + + react-dom@19.3.1: + resolution: {integrity: sha512-Y0bARz53lhEC1NMCASs0/j+faB/zqt3R8hpvg1e8+61ZVJ4UL0UdC4cBbXfZMcIuhrfgeILTLe+ZeBCavQPtKQ==} + peerDependencies: + react: ^19.3.1 + + react@19.3.1: + resolution: {integrity: sha512-QNhWdt7nrgVWWQG58QuGsAR3jv3Hbe4mb4vz7w2csnHavciZJgda1CPNaldF6eVxv90ud3jUXpKlHL69gO38yw==} + engines: {node: '>=0.10.0'} + + scheduler@0.28.0: + resolution: {integrity: sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw==} + + semver@7.8.5: + resolution: {integrity: sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==} + engines: {node: '>=10'} + hasBin: true + + sharp@0.35.5: + resolution: {integrity: sha512-Ywn4OnzGukp7CDMrp08RQ50YKmuwG47brZgIVPTvBaaAfQlRlygrRqSrxdCiL9M+LlzLBiJ68IR1QqvzHyjC7g==} + engines: {node: '>=20.9.0'} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + + source-map-js@1.2.2: + resolution: {integrity: sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==} + engines: {node: '>=0.10.0'} + + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + + styled-jsx@5.1.6: + resolution: {integrity: sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==} + engines: {node: '>= 12.0.0'} + peerDependencies: + '@babel/core': '*' + babel-plugin-macros: '*' + react: '>= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0' + peerDependenciesMeta: + '@babel/core': + optional: true + babel-plugin-macros: + optional: true + + tailwindcss@4.3.3: + resolution: {integrity: sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==} + + tapable@2.3.3: + resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} + engines: {node: '>=6'} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tsx@4.23.15: + resolution: {integrity: sha512-Yiex1Ovn8z2xPpOWckIiysV1SSyRMY9BkLF++q0yKiDxCqRhosKfMg3janKkiLBwZ5c/YryloKwGZcrEmtwxKw==} + engines: {node: '>=18.0.0'} + hasBin: true + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@7.24.6: + resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + + zod@4.6.7: + resolution: {integrity: sha512-g8W2D2kU6a8untc053fX1uVBKzM7yqAxW/3zwk83+6RyF2+SKOuV+c0wBDhUwzV1PaGapmZH+rmcUzPf+3CGwg==} + +snapshots: + + '@alloc/quick-lru@5.3.0': {} + + '@aws-sdk/checksums@3.1001.5': + dependencies: + '@aws-sdk/core': 3.978.5 + '@aws-sdk/types': 3.975.0 + '@smithy/core': 3.36.2 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/client-s3@3.1155.0': + dependencies: + '@aws-sdk/checksums': 3.1001.5 + '@aws-sdk/core': 3.978.5 + '@aws-sdk/credential-provider-node': 3.972.88 + '@aws-sdk/middleware-sdk-s3': 3.972.81 + '@aws-sdk/signature-v4-multi-region': 3.996.49 + '@aws-sdk/types': 3.975.0 + '@smithy/core': 3.36.2 + '@smithy/fetch-http-handler': 5.8.0 + '@smithy/node-http-handler': 4.12.1 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/core@3.978.5': + dependencies: + '@aws-sdk/types': 3.975.0 + '@aws-sdk/xml-builder': 3.972.41 + '@aws/lambda-invoke-store': 0.3.0 + '@smithy/core': 3.36.2 + '@smithy/signature-v4': 5.7.4 + '@smithy/types': 4.19.0 + bowser: 2.14.1 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-env@3.972.76': + dependencies: + '@aws-sdk/core': 3.978.5 + '@aws-sdk/types': 3.975.0 + '@smithy/core': 3.36.2 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-http@3.972.78': + dependencies: + '@aws-sdk/core': 3.978.5 + '@aws-sdk/types': 3.975.0 + '@smithy/core': 3.36.2 + '@smithy/fetch-http-handler': 5.8.0 + '@smithy/node-http-handler': 4.12.1 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-ini@3.973.21': + dependencies: + '@aws-sdk/core': 3.978.5 + '@aws-sdk/credential-provider-env': 3.972.76 + '@aws-sdk/credential-provider-http': 3.972.78 + '@aws-sdk/credential-provider-login': 3.972.83 + '@aws-sdk/credential-provider-process': 3.972.76 + '@aws-sdk/credential-provider-sso': 3.973.20 + '@aws-sdk/credential-provider-web-identity': 3.972.82 + '@aws-sdk/nested-clients': 3.997.50 + '@aws-sdk/types': 3.975.0 + '@smithy/core': 3.36.2 + '@smithy/credential-provider-imds': 4.5.2 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-login@3.972.83': + dependencies: + '@aws-sdk/core': 3.978.5 + '@aws-sdk/nested-clients': 3.997.50 + '@aws-sdk/types': 3.975.0 + '@smithy/core': 3.36.2 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-node@3.972.88': + dependencies: + '@aws-sdk/credential-provider-env': 3.972.76 + '@aws-sdk/credential-provider-http': 3.972.78 + '@aws-sdk/credential-provider-ini': 3.973.21 + '@aws-sdk/credential-provider-process': 3.972.76 + '@aws-sdk/credential-provider-sso': 3.973.20 + '@aws-sdk/credential-provider-web-identity': 3.972.82 + '@aws-sdk/types': 3.975.0 + '@smithy/core': 3.36.2 + '@smithy/credential-provider-imds': 4.5.2 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-process@3.972.76': + dependencies: + '@aws-sdk/core': 3.978.5 + '@aws-sdk/types': 3.975.0 + '@smithy/core': 3.36.2 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-sso@3.973.20': + dependencies: + '@aws-sdk/core': 3.978.5 + '@aws-sdk/nested-clients': 3.997.50 + '@aws-sdk/token-providers': 3.1155.0 + '@aws-sdk/types': 3.975.0 + '@smithy/core': 3.36.2 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-web-identity@3.972.82': + dependencies: + '@aws-sdk/core': 3.978.5 + '@aws-sdk/nested-clients': 3.997.50 + '@aws-sdk/types': 3.975.0 + '@smithy/core': 3.36.2 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-sdk-s3@3.972.81': + dependencies: + '@aws-sdk/core': 3.978.5 + '@aws-sdk/signature-v4-multi-region': 3.996.49 + '@aws-sdk/types': 3.975.0 + '@smithy/core': 3.36.2 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/nested-clients@3.997.50': + dependencies: + '@aws-sdk/core': 3.978.5 + '@aws-sdk/signature-v4-multi-region': 3.996.49 + '@aws-sdk/types': 3.975.0 + '@smithy/core': 3.36.2 + '@smithy/fetch-http-handler': 5.8.0 + '@smithy/node-http-handler': 4.12.1 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/signature-v4-multi-region@3.996.49': + dependencies: + '@aws-sdk/types': 3.975.0 + '@smithy/signature-v4': 5.7.4 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/token-providers@3.1155.0': + dependencies: + '@aws-sdk/core': 3.978.5 + '@aws-sdk/nested-clients': 3.997.50 + '@aws-sdk/types': 3.975.0 + '@smithy/core': 3.36.2 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/types@3.975.0': + dependencies: + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws-sdk/xml-builder@3.972.41': + dependencies: + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@aws/lambda-invoke-store@0.3.0': {} + + '@emnapi/runtime@1.11.3': + dependencies: + tslib: 2.8.1 + optional: true + + '@esbuild/aix-ppc64@0.28.2': + optional: true + + '@esbuild/android-arm64@0.28.2': + optional: true + + '@esbuild/android-arm@0.28.2': + optional: true + + '@esbuild/android-x64@0.28.2': + optional: true + + '@esbuild/darwin-arm64@0.28.2': + optional: true + + '@esbuild/darwin-x64@0.28.2': + optional: true + + '@esbuild/freebsd-arm64@0.28.2': + optional: true + + '@esbuild/freebsd-x64@0.28.2': + optional: true + + '@esbuild/linux-arm64@0.28.2': + optional: true + + '@esbuild/linux-arm@0.28.2': + optional: true + + '@esbuild/linux-ia32@0.28.2': + optional: true + + '@esbuild/linux-loong64@0.28.2': + optional: true + + '@esbuild/linux-mips64el@0.28.2': + optional: true + + '@esbuild/linux-ppc64@0.28.2': + optional: true + + '@esbuild/linux-riscv64@0.28.2': + optional: true + + '@esbuild/linux-s390x@0.28.2': + optional: true + + '@esbuild/linux-x64@0.28.2': + optional: true + + '@esbuild/netbsd-arm64@0.28.2': + optional: true + + '@esbuild/netbsd-x64@0.28.2': + optional: true + + '@esbuild/openbsd-arm64@0.28.2': + optional: true + + '@esbuild/openbsd-x64@0.28.2': + optional: true + + '@esbuild/openharmony-arm64@0.28.2': + optional: true + + '@esbuild/sunos-x64@0.28.2': + optional: true + + '@esbuild/win32-arm64@0.28.2': + optional: true + + '@esbuild/win32-ia32@0.28.2': + optional: true + + '@esbuild/win32-x64@0.28.2': + optional: true + + '@img/colour@1.1.0': {} + + '@img/sharp-darwin-arm64@0.35.5': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.3.4 + optional: true + + '@img/sharp-darwin-x64@0.35.5': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.3.4 + optional: true + + '@img/sharp-freebsd-wasm32@0.35.5': + dependencies: + '@img/sharp-wasm32': 0.35.5 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.3.4': + optional: true + + '@img/sharp-libvips-darwin-x64@1.3.4': + optional: true + + '@img/sharp-libvips-linux-arm64@1.3.4': + optional: true + + '@img/sharp-libvips-linux-arm@1.3.4': + optional: true + + '@img/sharp-libvips-linux-ppc64@1.3.4': + optional: true + + '@img/sharp-libvips-linux-riscv64@1.3.4': + optional: true + + '@img/sharp-libvips-linux-s390x@1.3.4': + optional: true + + '@img/sharp-libvips-linux-x64@1.3.4': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.3.4': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.3.4': + optional: true + + '@img/sharp-linux-arm64@0.35.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.3.4 + optional: true + + '@img/sharp-linux-arm@0.35.5': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.3.4 + optional: true + + '@img/sharp-linux-ppc64@0.35.5': + optionalDependencies: + '@img/sharp-libvips-linux-ppc64': 1.3.4 + optional: true + + '@img/sharp-linux-riscv64@0.35.5': + optionalDependencies: + '@img/sharp-libvips-linux-riscv64': 1.3.4 + optional: true + + '@img/sharp-linux-s390x@0.35.5': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.3.4 + optional: true + + '@img/sharp-linux-x64@0.35.5': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.3.4 + optional: true + + '@img/sharp-linuxmusl-arm64@0.35.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.3.4 + optional: true + + '@img/sharp-linuxmusl-x64@0.35.5': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.3.4 + optional: true + + '@img/sharp-wasm32@0.35.5': + dependencies: + '@emnapi/runtime': 1.11.3 + optional: true + + '@img/sharp-webcontainers-wasm32@0.35.5': + dependencies: + '@img/sharp-wasm32': 0.35.5 + optional: true + + '@img/sharp-win32-arm64@0.35.5': + optional: true + + '@img/sharp-win32-ia32@0.35.5': + optional: true + + '@img/sharp-win32-x64@0.35.5': + optional: true + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.6.0 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.6.0': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.6.0 + + '@next/env@16.4.2': {} + + '@next/swc-darwin-arm64@16.4.2': + optional: true + + '@next/swc-darwin-x64@16.4.2': + optional: true + + '@next/swc-linux-arm64-gnu@16.4.2': + optional: true + + '@next/swc-linux-arm64-musl@16.4.2': + optional: true + + '@next/swc-linux-x64-gnu@16.4.2': + optional: true + + '@next/swc-linux-x64-musl@16.4.2': + optional: true + + '@next/swc-win32-arm64-msvc@16.4.2': + optional: true + + '@next/swc-win32-x64-msvc@16.4.2': + optional: true + + '@noble/hashes@1.8.0': {} + + '@paralleldrive/cuid2@2.3.1': + dependencies: + '@noble/hashes': 1.8.0 + + '@smithy/core@3.36.2': + dependencies: + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@smithy/credential-provider-imds@4.5.2': + dependencies: + '@smithy/core': 3.36.2 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@smithy/fetch-http-handler@5.8.0': + dependencies: + '@smithy/core': 3.36.2 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@smithy/node-http-handler@4.12.1': + dependencies: + '@smithy/core': 3.36.2 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@smithy/signature-v4@5.7.4': + dependencies: + '@smithy/core': 3.36.2 + '@smithy/types': 4.19.0 + tslib: 2.8.1 + + '@smithy/types@4.19.0': + dependencies: + tslib: 2.8.1 + + '@swc/helpers@0.5.23': + dependencies: + tslib: 2.8.1 + + '@tailwindcss/node@4.3.3': + dependencies: + '@jridgewell/remapping': 2.3.5 + enhanced-resolve: 5.26.0 + jiti: 2.7.0 + lightningcss: 1.32.0 + magic-string: 0.30.21 + source-map-js: 1.2.2 + tailwindcss: 4.3.3 + + '@tailwindcss/oxide-android-arm64@4.3.3': + optional: true + + '@tailwindcss/oxide-darwin-arm64@4.3.3': + optional: true + + '@tailwindcss/oxide-darwin-x64@4.3.3': + optional: true + + '@tailwindcss/oxide-freebsd-x64@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-arm64-gnu@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-arm64-musl@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-x64-gnu@4.3.3': + optional: true + + '@tailwindcss/oxide-linux-x64-musl@4.3.3': + optional: true + + '@tailwindcss/oxide-wasm32-wasi@4.3.3': + optional: true + + '@tailwindcss/oxide-win32-arm64-msvc@4.3.3': + optional: true + + '@tailwindcss/oxide-win32-x64-msvc@4.3.3': + optional: true + + '@tailwindcss/oxide@4.3.3': + optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.3.3 + '@tailwindcss/oxide-darwin-arm64': 4.3.3 + '@tailwindcss/oxide-darwin-x64': 4.3.3 + '@tailwindcss/oxide-freebsd-x64': 4.3.3 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.3.3 + '@tailwindcss/oxide-linux-arm64-gnu': 4.3.3 + '@tailwindcss/oxide-linux-arm64-musl': 4.3.3 + '@tailwindcss/oxide-linux-x64-gnu': 4.3.3 + '@tailwindcss/oxide-linux-x64-musl': 4.3.3 + '@tailwindcss/oxide-wasm32-wasi': 4.3.3 + '@tailwindcss/oxide-win32-arm64-msvc': 4.3.3 + '@tailwindcss/oxide-win32-x64-msvc': 4.3.3 + + '@tailwindcss/postcss@4.3.3': + dependencies: + '@alloc/quick-lru': 5.3.0 + '@tailwindcss/node': 4.3.3 + '@tailwindcss/oxide': 4.3.3 + postcss: 8.5.31 + tailwindcss: 4.3.3 + + '@types/formidable@3.5.1': + dependencies: + '@types/node': 24.19.2 + + '@types/node@24.19.2': + dependencies: + undici-types: 7.24.6 + + '@types/pg@8.23.1': + dependencies: + '@types/node': 24.19.2 + pg-protocol: 1.16.1 + pg-types: 2.2.0 + + '@types/react-dom@19.3.0(@types/react@19.3.0)': + dependencies: + '@types/react': 19.3.0 + + '@types/react@19.3.0': + dependencies: + csstype: 3.2.3 + + asap@2.0.6: {} + + baseline-browser-mapping@2.11.32: {} + + bowser@2.14.1: {} + + caniuse-lite@1.0.30001819: {} + + client-only@0.0.1: {} + + csstype@3.2.3: {} + + detect-libc@2.1.2: {} + + dezalgo@1.0.4: + dependencies: + asap: 2.0.6 + wrappy: 1.0.2 + + enhanced-resolve@5.26.0: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.3 + + esbuild@0.28.2: + optionalDependencies: + '@esbuild/aix-ppc64': 0.28.2 + '@esbuild/android-arm': 0.28.2 + '@esbuild/android-arm64': 0.28.2 + '@esbuild/android-x64': 0.28.2 + '@esbuild/darwin-arm64': 0.28.2 + '@esbuild/darwin-x64': 0.28.2 + '@esbuild/freebsd-arm64': 0.28.2 + '@esbuild/freebsd-x64': 0.28.2 + '@esbuild/linux-arm': 0.28.2 + '@esbuild/linux-arm64': 0.28.2 + '@esbuild/linux-ia32': 0.28.2 + '@esbuild/linux-loong64': 0.28.2 + '@esbuild/linux-mips64el': 0.28.2 + '@esbuild/linux-ppc64': 0.28.2 + '@esbuild/linux-riscv64': 0.28.2 + '@esbuild/linux-s390x': 0.28.2 + '@esbuild/linux-x64': 0.28.2 + '@esbuild/netbsd-arm64': 0.28.2 + '@esbuild/netbsd-x64': 0.28.2 + '@esbuild/openbsd-arm64': 0.28.2 + '@esbuild/openbsd-x64': 0.28.2 + '@esbuild/openharmony-arm64': 0.28.2 + '@esbuild/sunos-x64': 0.28.2 + '@esbuild/win32-arm64': 0.28.2 + '@esbuild/win32-ia32': 0.28.2 + '@esbuild/win32-x64': 0.28.2 + + formidable@3.5.4: + dependencies: + '@paralleldrive/cuid2': 2.3.1 + dezalgo: 1.0.4 + once: 1.4.0 + + fsevents@2.3.3: + optional: true + + graceful-fs@4.2.11: {} + + jiti@2.7.0: {} + + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + + lucide-react@1.61.0(@types/react@19.3.0)(react@19.3.1): + dependencies: + react: 19.3.1 + optionalDependencies: + '@types/react': 19.3.0 + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.6.0 + + nanoid@3.3.20: {} + + next@16.4.2(@types/node@24.19.2)(react-dom@19.3.1(react@19.3.1))(react@19.3.1): + dependencies: + '@next/env': 16.4.2 + '@swc/helpers': 0.5.23 + baseline-browser-mapping: 2.11.32 + caniuse-lite: 1.0.30001819 + postcss: 8.5.23 + react: 19.3.1 + react-dom: 19.3.1(react@19.3.1) + styled-jsx: 5.1.6(react@19.3.1) + optionalDependencies: + '@next/swc-darwin-arm64': 16.4.2 + '@next/swc-darwin-x64': 16.4.2 + '@next/swc-linux-arm64-gnu': 16.4.2 + '@next/swc-linux-arm64-musl': 16.4.2 + '@next/swc-linux-x64-gnu': 16.4.2 + '@next/swc-linux-x64-musl': 16.4.2 + '@next/swc-win32-arm64-msvc': 16.4.2 + '@next/swc-win32-x64-msvc': 16.4.2 + sharp: 0.35.5(@types/node@24.19.2) + transitivePeerDependencies: + - '@babel/core' + - '@types/node' + - babel-plugin-macros + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + pg-cloudflare@1.4.1: + optional: true + + pg-connection-string@2.14.1: {} + + pg-int8@1.0.1: {} + + pg-pool@3.14.0(pg@8.23.1): + dependencies: + pg: 8.23.1 + + pg-protocol@1.16.1: {} + + pg-types@2.2.0: + dependencies: + pg-int8: 1.0.1 + postgres-array: 2.0.0 + postgres-bytea: 1.0.1 + postgres-date: 1.0.7 + postgres-interval: 1.2.0 + + pg@8.23.1: + dependencies: + pg-connection-string: 2.14.1 + pg-pool: 3.14.0(pg@8.23.1) + pg-protocol: 1.16.1 + pg-types: 2.2.0 + pgpass: 1.0.5 + optionalDependencies: + pg-cloudflare: 1.4.1 + + pgpass@1.0.5: + dependencies: + split2: 4.2.0 + + picocolors@1.1.1: {} + + playwright-core@1.56.1: {} + + postcss@8.5.23: + dependencies: + nanoid: 3.3.20 + picocolors: 1.1.1 + source-map-js: 1.2.2 + + postcss@8.5.31: + dependencies: + nanoid: 3.3.20 + picocolors: 1.1.1 + source-map-js: 1.2.2 + + postgres-array@2.0.0: {} + + postgres-bytea@1.0.1: {} + + postgres-date@1.0.7: {} + + postgres-interval@1.2.0: + dependencies: + xtend: 4.0.2 + + react-dom@19.3.1(react@19.3.1): + dependencies: + react: 19.3.1 + scheduler: 0.28.0 + + react@19.3.1: {} + + scheduler@0.28.0: {} + + semver@7.8.5: {} + + sharp@0.35.5(@types/node@24.19.2): + dependencies: + '@img/colour': 1.1.0 + detect-libc: 2.1.2 + semver: 7.8.5 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.35.5 + '@img/sharp-darwin-x64': 0.35.5 + '@img/sharp-freebsd-wasm32': 0.35.5 + '@img/sharp-libvips-darwin-arm64': 1.3.4 + '@img/sharp-libvips-darwin-x64': 1.3.4 + '@img/sharp-libvips-linux-arm': 1.3.4 + '@img/sharp-libvips-linux-arm64': 1.3.4 + '@img/sharp-libvips-linux-ppc64': 1.3.4 + '@img/sharp-libvips-linux-riscv64': 1.3.4 + '@img/sharp-libvips-linux-s390x': 1.3.4 + '@img/sharp-libvips-linux-x64': 1.3.4 + '@img/sharp-libvips-linuxmusl-arm64': 1.3.4 + '@img/sharp-libvips-linuxmusl-x64': 1.3.4 + '@img/sharp-linux-arm': 0.35.5 + '@img/sharp-linux-arm64': 0.35.5 + '@img/sharp-linux-ppc64': 0.35.5 + '@img/sharp-linux-riscv64': 0.35.5 + '@img/sharp-linux-s390x': 0.35.5 + '@img/sharp-linux-x64': 0.35.5 + '@img/sharp-linuxmusl-arm64': 0.35.5 + '@img/sharp-linuxmusl-x64': 0.35.5 + '@img/sharp-webcontainers-wasm32': 0.35.5 + '@img/sharp-win32-arm64': 0.35.5 + '@img/sharp-win32-ia32': 0.35.5 + '@img/sharp-win32-x64': 0.35.5 + '@types/node': 24.19.2 + + source-map-js@1.2.2: {} + + split2@4.2.0: {} + + styled-jsx@5.1.6(react@19.3.1): + dependencies: + client-only: 0.0.1 + react: 19.3.1 + + tailwindcss@4.3.3: {} + + tapable@2.3.3: {} + + tslib@2.8.1: {} + + tsx@4.23.15: + dependencies: + esbuild: 0.28.2 + optionalDependencies: + fsevents: 2.3.3 + + typescript@5.9.3: {} + + undici-types@7.24.6: {} + + wrappy@1.0.2: {} + + xtend@4.0.2: {} + + zod@4.6.7: {} diff --git a/apps/wiki/postcss.config.mjs b/apps/wiki/postcss.config.mjs new file mode 100644 index 0000000..a2dc18a --- /dev/null +++ b/apps/wiki/postcss.config.mjs @@ -0,0 +1,3 @@ +export default { + plugins: { "@tailwindcss/postcss": {} }, +}; diff --git a/public/brand-mark.svg b/apps/wiki/public/brand-mark.svg similarity index 100% rename from public/brand-mark.svg rename to apps/wiki/public/brand-mark.svg diff --git a/public/learning-skills/cover.png b/apps/wiki/public/learning-skills/cover.png similarity index 100% rename from public/learning-skills/cover.png rename to apps/wiki/public/learning-skills/cover.png diff --git a/public/learning-skills/cover.svg b/apps/wiki/public/learning-skills/cover.svg similarity index 100% rename from public/learning-skills/cover.svg rename to apps/wiki/public/learning-skills/cover.svg diff --git a/public/llms.txt b/apps/wiki/public/llms.txt similarity index 100% rename from public/llms.txt rename to apps/wiki/public/llms.txt diff --git a/public/skills/shadow-puppet/dancer-example.png b/apps/wiki/public/skills/shadow-puppet/dancer-example.png similarity index 100% rename from public/skills/shadow-puppet/dancer-example.png rename to apps/wiki/public/skills/shadow-puppet/dancer-example.png diff --git a/public/skills/shadow-puppet/egret-example.png b/apps/wiki/public/skills/shadow-puppet/egret-example.png similarity index 100% rename from public/skills/shadow-puppet/egret-example.png rename to apps/wiki/public/skills/shadow-puppet/egret-example.png diff --git a/public/skills/street-people/reference.png b/apps/wiki/public/skills/street-people/reference.png similarity index 100% rename from public/skills/street-people/reference.png rename to apps/wiki/public/skills/street-people/reference.png diff --git a/public/skills/street-people/sample.png b/apps/wiki/public/skills/street-people/sample.png similarity index 100% rename from public/skills/street-people/sample.png rename to apps/wiki/public/skills/street-people/sample.png diff --git a/scripts/bootstrap.ts b/apps/wiki/scripts/bootstrap.ts similarity index 100% rename from scripts/bootstrap.ts rename to apps/wiki/scripts/bootstrap.ts diff --git a/scripts/container-health.mjs b/apps/wiki/scripts/container-health.mjs similarity index 100% rename from scripts/container-health.mjs rename to apps/wiki/scripts/container-health.mjs diff --git a/scripts/import-character-packs.mjs b/apps/wiki/scripts/import-character-packs.mjs similarity index 100% rename from scripts/import-character-packs.mjs rename to apps/wiki/scripts/import-character-packs.mjs diff --git a/scripts/prepare-standalone.mjs b/apps/wiki/scripts/prepare-standalone.mjs similarity index 100% rename from scripts/prepare-standalone.mjs rename to apps/wiki/scripts/prepare-standalone.mjs diff --git a/scripts/publish-learning-series.ts b/apps/wiki/scripts/publish-learning-series.ts similarity index 100% rename from scripts/publish-learning-series.ts rename to apps/wiki/scripts/publish-learning-series.ts diff --git a/scripts/smoke.mjs b/apps/wiki/scripts/smoke.mjs similarity index 100% rename from scripts/smoke.mjs rename to apps/wiki/scripts/smoke.mjs diff --git a/scripts/wait-snapshots.mjs b/apps/wiki/scripts/wait-snapshots.mjs similarity index 100% rename from scripts/wait-snapshots.mjs rename to apps/wiki/scripts/wait-snapshots.mjs diff --git a/seed/characters/extraction.json b/apps/wiki/seed/characters/extraction.json similarity index 100% rename from seed/characters/extraction.json rename to apps/wiki/seed/characters/extraction.json diff --git a/seed/characters/original/01-florist.png b/apps/wiki/seed/characters/original/01-florist.png similarity index 100% rename from seed/characters/original/01-florist.png rename to apps/wiki/seed/characters/original/01-florist.png diff --git a/seed/characters/original/02-reader.png b/apps/wiki/seed/characters/original/02-reader.png similarity index 100% rename from seed/characters/original/02-reader.png rename to apps/wiki/seed/characters/original/02-reader.png diff --git a/seed/characters/original/03-cyclist.png b/apps/wiki/seed/characters/original/03-cyclist.png similarity index 100% rename from seed/characters/original/03-cyclist.png rename to apps/wiki/seed/characters/original/03-cyclist.png diff --git a/seed/characters/original/04-coffee.png b/apps/wiki/seed/characters/original/04-coffee.png similarity index 100% rename from seed/characters/original/04-coffee.png rename to apps/wiki/seed/characters/original/04-coffee.png diff --git a/seed/characters/packs.json b/apps/wiki/seed/characters/packs.json similarity index 100% rename from seed/characters/packs.json rename to apps/wiki/seed/characters/packs.json diff --git a/seed/characters/prompts.json b/apps/wiki/seed/characters/prompts.json similarity index 100% rename from seed/characters/prompts.json rename to apps/wiki/seed/characters/prompts.json diff --git a/seed/characters/reference/01-basket.png b/apps/wiki/seed/characters/reference/01-basket.png similarity index 100% rename from seed/characters/reference/01-basket.png rename to apps/wiki/seed/characters/reference/01-basket.png diff --git a/seed/characters/reference/02-phone.png b/apps/wiki/seed/characters/reference/02-phone.png similarity index 100% rename from seed/characters/reference/02-phone.png rename to apps/wiki/seed/characters/reference/02-phone.png diff --git a/seed/characters/reference/03-coffee.png b/apps/wiki/seed/characters/reference/03-coffee.png similarity index 100% rename from seed/characters/reference/03-coffee.png rename to apps/wiki/seed/characters/reference/03-coffee.png diff --git a/seed/characters/reference/04-red-coat.png b/apps/wiki/seed/characters/reference/04-red-coat.png similarity index 100% rename from seed/characters/reference/04-red-coat.png rename to apps/wiki/seed/characters/reference/04-red-coat.png diff --git a/seed/characters/reference/05-blue-dogs.png b/apps/wiki/seed/characters/reference/05-blue-dogs.png similarity index 100% rename from seed/characters/reference/05-blue-dogs.png rename to apps/wiki/seed/characters/reference/05-blue-dogs.png diff --git a/seed/characters/reference/06-dark-dog.png b/apps/wiki/seed/characters/reference/06-dark-dog.png similarity index 100% rename from seed/characters/reference/06-dark-dog.png rename to apps/wiki/seed/characters/reference/06-dark-dog.png diff --git a/seed/characters/reference/07-pockets.png b/apps/wiki/seed/characters/reference/07-pockets.png similarity index 100% rename from seed/characters/reference/07-pockets.png rename to apps/wiki/seed/characters/reference/07-pockets.png diff --git a/seed/characters/reference/08-blue-board.png b/apps/wiki/seed/characters/reference/08-blue-board.png similarity index 100% rename from seed/characters/reference/08-blue-board.png rename to apps/wiki/seed/characters/reference/08-blue-board.png diff --git a/seed/characters/reference/09-scarf-dog.png b/apps/wiki/seed/characters/reference/09-scarf-dog.png similarity index 100% rename from seed/characters/reference/09-scarf-dog.png rename to apps/wiki/seed/characters/reference/09-scarf-dog.png diff --git a/seed/characters/reference/10-elder.png b/apps/wiki/seed/characters/reference/10-elder.png similarity index 100% rename from seed/characters/reference/10-elder.png rename to apps/wiki/seed/characters/reference/10-elder.png diff --git a/seed/characters/reference/11-long-coat.png b/apps/wiki/seed/characters/reference/11-long-coat.png similarity index 100% rename from seed/characters/reference/11-long-coat.png rename to apps/wiki/seed/characters/reference/11-long-coat.png diff --git a/seed/characters/reference/12-trolley.png b/apps/wiki/seed/characters/reference/12-trolley.png similarity index 100% rename from seed/characters/reference/12-trolley.png rename to apps/wiki/seed/characters/reference/12-trolley.png diff --git a/seed/characters/reference/13-bucket.png b/apps/wiki/seed/characters/reference/13-bucket.png similarity index 100% rename from seed/characters/reference/13-bucket.png rename to apps/wiki/seed/characters/reference/13-bucket.png diff --git a/seed/characters/reference/14-curly.png b/apps/wiki/seed/characters/reference/14-curly.png similarity index 100% rename from seed/characters/reference/14-curly.png rename to apps/wiki/seed/characters/reference/14-curly.png diff --git a/seed/characters/reference/15-red-walk.png b/apps/wiki/seed/characters/reference/15-red-walk.png similarity index 100% rename from seed/characters/reference/15-red-walk.png rename to apps/wiki/seed/characters/reference/15-red-walk.png diff --git a/src/components/ArticleGallery.tsx b/apps/wiki/src/components/ArticleGallery.tsx similarity index 100% rename from src/components/ArticleGallery.tsx rename to apps/wiki/src/components/ArticleGallery.tsx diff --git a/src/components/Feed.tsx b/apps/wiki/src/components/Feed.tsx similarity index 100% rename from src/components/Feed.tsx rename to apps/wiki/src/components/Feed.tsx diff --git a/src/components/GuidanceIndex.tsx b/apps/wiki/src/components/GuidanceIndex.tsx similarity index 100% rename from src/components/GuidanceIndex.tsx rename to apps/wiki/src/components/GuidanceIndex.tsx diff --git a/src/components/Shell.tsx b/apps/wiki/src/components/Shell.tsx similarity index 95% rename from src/components/Shell.tsx rename to apps/wiki/src/components/Shell.tsx index 887ebc9..ad1a015 100644 --- a/src/components/Shell.tsx +++ b/apps/wiki/src/components/Shell.tsx @@ -3,7 +3,7 @@ import { useRouter } from "next/router"; import { Grid2X2,Image,Film,AudioLines,BookOpen,Clapperboard,Sparkles,ArrowUpRight,Layers,Tags,Upload,Menu,X,Search } from "lucide-react"; import { useEffect,useState,type ReactNode } from "react"; const groups=[ - {label:'',items:[{href:'/',label:'首页',icon:Grid2X2}]}, + {label:'',items:[{href:'/',label:'发现',icon:Grid2X2}]}, {label:'素材',items:[{href:'/images',label:'图片',icon:Image},{href:'/videos',label:'视频',icon:Film},{href:'/audio',label:'声音',icon:AudioLines}]}, {label:'作品',items:[{href:'/articles',label:'图文',icon:BookOpen},{href:'/motion',label:'动态',icon:Clapperboard}]}, {label:'工具',items:[{href:'/skills',label:'指导文档',icon:BookOpen},{href:'/tools/doodle',label:'线条工具',icon:Sparkles}]}, @@ -15,6 +15,6 @@ export function Shell({children}:{children:ReactNode}){
{e.preventDefault();const path=router.asPath.split('?')[0];const destination=/^\/(images|videos|audio|articles|motion)(\/|$)/.test(path)?path:'/';void router.push({pathname:destination,query:query?{q:query}:{}});}}>setQuery(e.target.value)}/>{query&&}
{children}
{open&&}{children}{open&&