Files
civitai__civitai/package.json
T
Zachary Lowden e92cf5fe4a test(geometry): a browser tier that loads the real cascade at a phone viewport (#4601)
* test(geometry): a browser tier that loads the real cascade at a phone viewport

Adds a fourth Vitest project, `geometry`, and demonstrates it catching a defect
whose own source comment records that nothing rendered can see it.

WHAT THE GAP IS, AND WHAT IT IS NOT. The `component` project is NOT jsdom — it is
real headless Chromium via @vitest/browser-playwright, `page.viewport()` moves
`window.innerWidth`, and `getBoundingClientRect()` returns real boxes. What it is
missing is the STYLESHEET and the VIEWPORT. `test/component-setup.tsx` injects
only the `:root` custom properties parsed out of globals.css, so the document
holds 24 CSS rules: Mantine classes are styleless, Tailwind utilities are inert,
and any `getComputedStyle` assertion whose expected value is the CSS initial
value passes against a broken component. And nothing sets a viewport, so files
inherit the runner's silent 414x896.

THE SAME FIXTURE, THE SAME CORRECT SOURCE, IN BOTH TIERS (PageBlockHost in its
production shell chain):

                            `component`      `geometry`
  viewport                    414 x 896       390 x 844   (default vs set)
  CSS rules in the document          24           3,677
  box-sizing on a bare div  content-box      border-box
  `className="flex"`              block            flex
  chrome bar height                 200              31
  host frame height                 350             844
  APP COLUMN HEIGHT                 150             813

That last row is the argument. 150 is ALSO what the app column measures once the
recorded `flex: 1` defect is planted, so a threshold written in the `component`
tier would have to expect the number the DEFECT produces.

THE HARNESS. `test/geometry-setup.tsx` loads the production cascade in production
order — the `@layer tailwind-preflight, theme, mantine, modules;` statement first
(as _document.tsx emits it), then globals.css, then every `@mantine/*` layer
stylesheet _app.tsx imports. It defaults to a 390x844 phone and THROWS unless the
window reports back the size it asked for; tests assert `observed` against their
own literal on top of that. It exports measurement helpers: `box`,
`childrenUnionBox` (the union of child rects — `scrollHeight` is clamped to the
padding box and cannot see a parent taller than its content), `flexAxis`,
`flexLonghands` (longhands, because `getComputedStyle(el).flex` serialises
`1 1 220px` and `1 1 0%` identically), and `cascadeEvidence`.

WHY A PROJECT AND NOT A CHANGE TO THE SHARED SETUP. Loading the cascade in
`component-setup.tsx` moves existing numbers — measured, the same chrome bar is
200px there and 31px with the cascade, a 169px move on one element, under 212
files / 2,362 tests of which 14 read getBoundingClientRect and 20 read
getComputedStyle. The per-file import pattern (15 files do it today, 3 also take
globals.css) stays available and is not deprecated; what it cannot give is a
guarantee — those files each picked their own subset, none declares the @layer
order, none sets a viewport, and the "did my stylesheet load" guard is
re-hand-rolled per file. The `geometry` glob (`src/**/*.geometry.test.tsx`) is
disjoint from every other project's, so nothing that runs today changes project
and no file is collected twice.

DEMONSTRATED RED. `PageBlockHostFillHeight.geometry.test.tsx` asserts that the
app column reaches the bottom of the host frame at 390x844 and at 390x640.
Dropping `flex: 1` from `app-page-content` (the mutation PageBlockHost.tsx's own
comment records as invisible to every rendered tier) fails it:

  the app column ends at y=181 inside a frame that ends at y=844 — 663px of the
  phone is blank below a running App Block. The column measured 150px of the
  frame's 844px, with flex longhands {"grow":"0","shrink":"1","basis":"auto"}.

Restoring the property returns it to 10/10. A second mutant — dropping `flex: 1`
from the frame's `fit === 'fill'` branch — collapses the column to 269px and is
caught by the literal floor rather than by the frame/content comparison, which
both mutations keep satisfied.

BOTH MUTANTS ARE ALSO CAUGHT IN THE NODE TIER TODAY, by verbatim source pins in
pageBlockHostMaxWidth.test.ts and pageRunScrollContract.test.ts. Stated plainly
so this is not read as claiming otherwise. The difference is what each guard can
SEE: a source pin is a claim about the text of one file, blind to a collapse
arriving from the cascade, from an ancestor or from a viewport, and it has to be
rewritten every time the block is legitimately reformatted.

WHAT RUNS THIS TODAY: NOTHING. lint.yml selects `--project 'unit*'`,
`'@civitai/*'` and `'app:*'`; no pattern matches `component` or `geometry`,
because the Actions runners install no Chromium. `component` has the preview
pipeline's report-only status; `geometry` has no CI home at all. Wiring one is a
pipeline change and deliberately not in this PR — but a harness nothing runs
rots, so it is said out loud in the setup file rather than left to be discovered.

Verification: typecheck 0 errors · geometry 2 files / 10 tests passed · component
212 files / 2,362 tests passed (unchanged) · scripts unit tier 24 files / 521
tests passed · eslint clean on both new test files.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* ci(geometry): run the geometry tier, and refuse a green that collected nothing

Adds a `Geometry tests` job to lint.yml. Without it this harness runs in no gate
at all — the workflow selects projects by name (`unit*`, `@civitai/*`, `app:*`)
and none of those patterns matches `geometry`.

ALIGNED WITH THE `unit` JOB'S COMMENT, NOT AN OVERRIDE OF IT. That comment gives
exactly one reason for keeping browser tests out — "they need Chromium, which
this job does not install. That is the whole reason." — which is a statement
about what that job provides, not a ban on providing it. The same comment then
retracts the only other objection on the record ("Don't cite a cold-cache flake
as a reason to keep this job Chromium-free") and names vitest.config.mts's
dedupe + optimizeDeps pre-bundling as the canonical fix. A job that DOES install
Chromium satisfies the stated condition.

GEOMETRY ONLY. `component` stays ungated and that is now visible rather than
fixed. Measured on a 16-core box: `geometry` is 2 files / 10 tests in 9.07s;
`component` is 212 files / 2,362 tests in 112.92s wall, of which 334s is test
time spread across workers — so a 2-core runner (browser pool `min(12, cpus-1)`
= 1 instance) does not divide it. That is an order of magnitude more expensive,
with 212 files of pass/fail history this workflow has never seen. It belongs in
its own PR.

REPORT-ONLY, mirroring `unit` and for its stated reason: blocking a brand-new
tier from day one would red unrelated PRs and the job would be switched off
within a week. `main` has no required_status_checks, so nothing here blocks a
merge either way; `continue-on-error` only decides whether a red renders as red
or as red-but-ignored. The FLIP TO BLOCKING note says concretely what would make
that safe. The `unit` job's selectors and its `continue-on-error` are untouched.

CHROMIUM comes from `pnpm exec playwright install --with-deps chromium` — the
workspace-local playwright, so the revision follows this repo's own pin rather
than a second version written into the workflow. Desynchronising those two is
the documented failure mode (CLAUDE.md records 59 preview specs dying on a
revision mismatch with zero specs run). A local NixOS bundle mismatch is a
property of that host and is handled by PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH; the
pin is not moved to accommodate it.

A GREEN VITEST RUN IS A CLAIM, NOT EVIDENCE — the hazard the `packages` job's
ledger exists for, one project over. `--project` matching nothing exits 0, and
this tier's glob is deliberately narrow, which is exactly the kind of pattern
that can quietly stop matching. The new step asserts floors of 2 files and 10
tests from the JSON report, with `if: always()` so it also fires when the tests
fail or the runner aborts without writing a report.

Two things measured rather than assumed while writing it: the file count comes
from `testResults.length`, NOT `numTotalTestSuites` — against a real report this
run is 2 files while that field reads 4, because it counts `describe` blocks.
And the gate script was extracted back out of the parsed YAML and executed on
all three arms before commit: real report -> exit 0 (2 files, 10 tests); a
report with `testResults: []` -> exit 1; a missing report -> exit 1 with its own
message.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(ci): the geometry job must be report-only on PRs ONLY, not on pushes to main

Caught by this repo's own gate on the previous commit's run:
`scripts/__tests__/main-branch-ci-coverage.test.ts` > "has no unconditionally
report-only job on the push path" went red (Unit tests shard 2, 1 failed / 5,624
passed).

The job was written with a literal `continue-on-error: true`. That is report-only
on EVERY event, including a push to `main`, where it produces a run reporting
`success` while the step underneath failed — the stale-TRUE shape that guard
exists to forbid, and the exact hazard the `unit` job's own comment spells out:
"A green that has to be disbelieved is worse than no run at all."

Now `${{ github.event_name == 'pull_request' }}`, byte-identical to `unit`'s.
Report-only on PRs (a new tier should not red unrelated work while it settles),
honest verdict on `main` (where the merge has already happened and there is no
unrelated work to protect). The guard accepts a conditional precisely because a
conditional can differ between a PR and a push; a literal cannot.

The comment now records this so the next reader does not "simplify" it back.

Red at c2359ba847 (CI), green at HEAD: the guard file is 1 file / 6 tests passed
locally, and the whole `scripts/` unit tier is 24 files / 521 tests passed. That
tier was run BEFORE the workflow existed on the previous commit, which is why it
did not catch this locally — a suite is only evidence about the tree it ran on.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 16:40:40 -05:00

450 lines
20 KiB
JSON

{
"name": "model-share",
"version": "5.1.70",
"private": true,
"packageManager": "pnpm@10.28.1",
"engines": {
"node": ">=24.0.0 <25"
},
"scripts": {
"preinstall": "npx only-allow pnpm",
"start": "next start",
"start-debug": "NODE_OPTIONS='--inspect' next start",
"build:workers": "node scripts/build-workers.mjs",
"clean": "node -e \"fs.rmSync('.next',{recursive:true,force:true})\"",
"predev": "pnpm build:workers",
"dev": "next dev",
"dev:auth": "pnpm --filter @civitai/auth-app dev",
"dev:moderator": "pnpm --filter @civitai/moderator-app dev",
"dev:creator-studio": "pnpm --filter @civitai/creator-studio-app dev",
"dev:storage": "pnpm --filter @civitai/storage-app dev",
"dev-low": "cross-env NODE_OPTIONS=\"--max_old_space_size=6144\" next dev",
"dev-debug": "pnpm build:workers && cross-env NODE_OPTIONS=\"--max_old_space_size=8192 --inspect\" next dev",
"dev-snap": "cross-env NODE_OPTIONS=\"--max_old_space_size=8192 --heapsnapshot-near-heap-limit=3\" next dev",
"dev:daemon": "node .claude/skills/dev-server/console.mjs",
"dev:rgb": "node .claude/skills/dev-server/cli.mjs rgb start",
"dev:rgb:stop": "node .claude/skills/dev-server/cli.mjs rgb stop",
"dev:rgb:status": "node .claude/skills/dev-server/cli.mjs rgb status",
"prod": "cross-env NODE_ENV=production next dev",
"boost": "next-boost",
"release:base": "git checkout release && git pull --rebase && git rebase main && git push --force-with-lease && git checkout main",
"release:major": "git pull && npm version major && git push --follow-tags && pnpm run release:base",
"release:minor": "git pull && npm version minor && git push --follow-tags && pnpm run release:base",
"release:patch": "git pull && npm version patch && git push --follow-tags && pnpm run release:base",
"release": "pnpm run release:patch",
"release:auth": "pnpm run release:auth:patch",
"release:auth:patch": "node scripts/release-app.mjs apps/auth auth-app-v patch",
"release:auth:minor": "node scripts/release-app.mjs apps/auth auth-app-v minor",
"release:auth:major": "node scripts/release-app.mjs apps/auth auth-app-v major",
"release:notifications": "pnpm run release:notifications:patch",
"release:notifications:patch": "node scripts/release-app.mjs apps/notifications notifications-v patch",
"release:notifications:minor": "node scripts/release-app.mjs apps/notifications notifications-v minor",
"release:notifications:major": "node scripts/release-app.mjs apps/notifications notifications-v major",
"release:creator-studio": "pnpm run release:creator-studio:patch",
"release:creator-studio:patch": "node scripts/release-app.mjs apps/creator-studio creator-studio-v patch",
"release:creator-studio:minor": "node scripts/release-app.mjs apps/creator-studio creator-studio-v minor",
"release:creator-studio:major": "node scripts/release-app.mjs apps/creator-studio creator-studio-v major",
"release:storage": "pnpm run release:storage:patch",
"release:storage:patch": "node scripts/release-app.mjs apps/storage storage-v patch",
"release:storage:minor": "node scripts/release-app.mjs apps/storage storage-v minor",
"release:storage:major": "node scripts/release-app.mjs apps/storage storage-v major",
"release:event-engine": "pnpm run release:event-engine:patch",
"release:event-engine:patch": "node scripts/release-app.mjs apps/event-engine event-engine-v patch",
"release:event-engine:minor": "node scripts/release-app.mjs apps/event-engine event-engine-v minor",
"release:event-engine:major": "node scripts/release-app.mjs apps/event-engine event-engine-v major",
"release:moderator": "pnpm run release:moderator:patch",
"release:moderator:patch": "node scripts/release-app.mjs apps/moderator moderator-v patch",
"release:moderator:minor": "node scripts/release-app.mjs apps/moderator moderator-v minor",
"release:moderator:major": "node scripts/release-app.mjs apps/moderator moderator-v major",
"yolo": "pnpm run release",
"seed:scanner-policies": "tsx --env-file=.env scripts/seed-scanner-policies.ts",
"prebuild": "pnpm build:workers",
"build": "next build",
"build:dev": "pnpm build:workers && cross-env NODE_OPTIONS=\"--max_old_space_size=16384\" next build",
"build:analyze": "cross-env NODE_OPTIONS=\"--max_old_space_size=16384\" ANALYZE=true next build",
"size": "node scripts/bundle-budget.mjs",
"deploy": "pnpm run build && pnpm run db:deploy",
"postinstall": "pnpm run db:generate",
"typecheck": "node scripts/typecheck.mjs",
"lint": "eslint src/ --cache --cache-strategy metadata",
"lint:packages": "eslint packages --ext .ts",
"eslint": "cross-env TIMING=1 eslint src/ --quiet --cache --cache-strategy metadata",
"prettier:check": "node scripts/prettier-changed.mjs check",
"prettier:write": "node scripts/prettier-changed.mjs write",
"db:ui": "prisma studio",
"db:pull": "prisma db pull",
"db:push": "prisma db push",
"db:migrate": "node scripts/prisma-migrate-with-views-workaround.mjs",
"db:migrate:empty": "node scripts/create-empty-migration.mjs",
"db:applied": "node scripts/prisma-mark-migration-applied.mjs",
"db:deploy": "node scripts/prisma-migrate-with-views-workaround.mjs -p && npm run db:program",
"db:program": "node scripts/prisma-prepare-programmability.mjs",
"db:generate": "node scripts/generate-slim-schema.js && prisma generate --no-hints",
"db:check-generated": "pnpm run db:generate && git diff --exit-code -- packages/civitai-db-schema/src",
"db:seed": "prisma db seed",
"db:moderator:pull": "prisma db pull --schema apps/moderator/prisma/schema.prisma",
"db:moderator:generate": "prisma generate --no-hints --schema apps/moderator/prisma/schema.prisma",
"share": "ngrok http 3000",
"prepare": "husky",
"analyze": "cross-env ANALYZE=true next build",
"analyze:server": "cross-env BUNDLE_ANALYZE=server next build",
"analyze:browser": "cross-env BUNDLE_ANALYZE=browser next build",
"tsc:trace": "cross-env NODE_OPTIONS=\"--max_old_space_size=8192\" tsc --generateTrace ./trace --incremental false",
"tsc:analyze": "npx analyze-trace trace",
"test": "cross-env NODE_ENV=development npx playwright test",
"test:ui": "cross-env NODE_ENV=development npx playwright test --ui",
"test:gen": "cross-env NODE_ENV=development npx playwright codegen",
"test:reset": "make bootstrap-db",
"test:unit": "vitest --project 'unit*'",
"test:unit:run": "node scripts/test-unit-run.mjs",
"test:unit:coverage": "vitest run --project 'unit*' --coverage",
"test:packages": "vitest --project '@civitai/*'",
"test:packages:run": "vitest run --project '@civitai/*'",
"test:apps": "vitest --project 'app:*'",
"test:apps:run": "vitest run --project 'app:*'",
"test:lint-rules": "vitest run --project 'unit*' src/server/notifications/__tests__/notification-settings-polarity.test.ts src/server/schema/__tests__/track.addView.schema.test.ts src/server/services/__tests__/hub-filter-parity.test.ts src/server/services/__tests__/no-agent-ground-truth-write.test.ts src/server/services/__tests__/no-coerce-boolean-in-api.test.ts src/server/services/__tests__/no-direct-shared-module-mock.test.ts src/server/services/__tests__/no-doubled-free-slot-noun.test.ts src/server/services/__tests__/no-hand-typed-redis-key-constants.test.ts src/server/services/__tests__/no-io-in-transaction.test.ts src/server/services/__tests__/no-lint-rules-script-drift.test.ts src/server/services/__tests__/no-module-scope-cache.test.ts src/server/services/__tests__/no-pk-addressed-engagement-write.test.ts src/server/services/__tests__/no-server-infra-in-app-graph.test.ts src/server/services/__tests__/no-sharp-outside-native-project.test.ts src/server/services/__tests__/no-stale-moderator-route-probe.test.ts src/server/services/__tests__/no-static-html2canvas-import.test.ts src/server/services/__tests__/no-unbounded-paging-fake.test.ts src/server/services/__tests__/no-unguarded-billable-submit.test.ts src/server/services/__tests__/no-unguarded-user-text.test.ts src/server/services/__tests__/no-unloadable-image-fixture.test.ts src/server/services/__tests__/no-unmuteable-comment-processor.test.ts src/server/services/__tests__/no-unpriced-default-model.test.ts src/server/services/__tests__/no-unscoped-email-verification-exemption.test.ts src/server/services/__tests__/no-untruthy-query-gate.test.ts src/server/services/__tests__/no-unverified-provenance-write.test.ts src/server/services/__tests__/no-unwrapped-knob-rotation.test.ts src/server/services/__tests__/no-wholesale-module-mock.test.ts src/server/services/__tests__/poi-checks-strip-benign-phrases.test.ts src/server/services/__tests__/video-leaderboard-badge-staging.test.ts",
"test:component": "node scripts/test-component-run.mjs",
"test:component:watch": "vitest --project component",
"test:geometry": "vitest run --project geometry",
"test:geometry:watch": "vitest --project geometry",
"meilisearch:migrate": "NODE_ENV=development tsx scripts/oneoffs/meilisearch-migration.ts",
"tsscript": "NODE_ENV=development tsx",
"madge:orphans": "madge --orphans --image ./public/orphans-graph.svg --ts-config ./tsconfig.json --extensions ts,tsx src/",
"depcheck": "depcheck",
"generate-types": "typed-scss-modules src",
"ts-script": "NODE_ENV=development tsx",
"generate:moderator-endpoints": "node scripts/generate-moderator-endpoint-catalog.mjs"
},
"prisma": {
"schema": "packages/civitai-db-schema/prisma/schema.prisma",
"seed": "ts-node --compiler-options {\"module\":\"CommonJS\"} packages/civitai-db-schema/prisma/seed.ts"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.490.0",
"@aws-sdk/lib-storage": "^3.490.0",
"@aws-sdk/s3-request-presigner": "^3.490.0",
"@axiomhq/axiom-node": "^0.12.0",
"@civitai/app-sdk": "^0.14.0",
"@civitai/auth": "workspace:*",
"@civitai/buzz": "workspace:*",
"@civitai/client": "0.2.0-beta.98",
"@civitai/cybertipline-tools": "^0.1.0",
"@civitai/db-queries": "workspace:*",
"@civitai/db-schema": "workspace:*",
"@civitai/flipt": "workspace:*",
"@civitai/generation-metadata": "^0.1.0",
"@civitai/moderation": "workspace:*",
"@civitai/next-axiom": "^0.17.0",
"@civitai/shared": "workspace:*",
"@clavata/sdk": "^0.2.3",
"@clickhouse/client": "^0.2.2",
"@coinbase/cdp-sdk": "^1.13.0",
"@discordjs/rest": "^2.6.0",
"@dnd-kit/core": "^6.1.0",
"@dnd-kit/sortable": "^8.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@emotion/react": "^11.10.4",
"@essentials/one-key-map": "^1.2.0",
"@flipt-io/flipt-client-js": "^0.2.0",
"@floating-ui/dom": "^1.6.0",
"@google-cloud/recaptcha-enterprise": "^5.1.1",
"@grafana/faro-web-sdk": "2.8.2",
"@grafana/faro-web-tracing": "2.8.2",
"@headlessui/react": "2.2",
"@hookform/resolvers": "^5.1.1",
"@mantine/core": "^7.17.7",
"@mantine/dates": "^7.17.7",
"@mantine/dropzone": "^7.17.7",
"@mantine/hooks": "^7.17.7",
"@mantine/modals": "^7.17.7",
"@mantine/notifications": "^7.17.7",
"@mantine/nprogress": "^7.17.7",
"@mantine/tiptap": "^7.17.7",
"@marsidev/react-turnstile": "^1.0.1",
"@meilisearch/instant-meilisearch": "0.13.5",
"@microsoft/signalr": "^7.0.10",
"@next/bundle-analyzer": "^16.3.0",
"@next/third-parties": "^15.0.3",
"@node-oauth/oauth2-server": "^5.3.0",
"@number-flow/react": "^0.5.7",
"@okikio/sharedworker": "^1.1.0",
"@openrouter/sdk": "^0.5.1",
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/api-logs": "^0.219.0",
"@opentelemetry/core": "2.9.0",
"@opentelemetry/exporter-logs-otlp-proto": "^0.219.0",
"@opentelemetry/exporter-trace-otlp-proto": "^0.219.0",
"@opentelemetry/instrumentation": "0.219.0",
"@opentelemetry/instrumentation-http": "^0.213.0",
"@opentelemetry/instrumentation-redis": "^0.61.0",
"@opentelemetry/resources": "2.9.0",
"@opentelemetry/sdk-logs": "^0.219.0",
"@opentelemetry/sdk-node": "^0.219.0",
"@opentelemetry/sdk-trace-node": "^2.5.0",
"@opentelemetry/sdk-trace-web": "2.9.0",
"@opentelemetry/semantic-conventions": "^1.39.0",
"@paddle/paddle-js": "^1.2.1",
"@paddle/paddle-node-sdk": "^1.4.1",
"@paypal/react-paypal-js": "^8.1.3",
"@prisma/client": "^6.3.0",
"@prisma/instrumentation": "^7.4.2",
"@pyroscope/nodejs": "0.6.2",
"@react-hook/window-size": "^3.1.1",
"@react-pdf/renderer": "^3.3.8",
"@stripe/react-stripe-js": "^2.4.0",
"@stripe/stripe-js": "^2.2.0",
"@tabler/icons-react": "^3.7.0",
"@tanstack/react-query": "^5.101.0",
"@tanstack/react-query-devtools": "^5.101.0",
"@tanstack/react-virtual": "^3.13.12",
"@tiptap/core": "3.16.0",
"@tiptap/extension-color": "3.16.0",
"@tiptap/extension-heading": "3.16.0",
"@tiptap/extension-image": "3.16.0",
"@tiptap/extension-link": "3.16.0",
"@tiptap/extension-mention": "3.16.0",
"@tiptap/extension-placeholder": "3.16.0",
"@tiptap/extension-text": "3.16.0",
"@tiptap/extension-text-style": "3.16.0",
"@tiptap/extension-underline": "3.16.0",
"@tiptap/extension-youtube": "3.16.0",
"@tiptap/extensions": "3.16.0",
"@tiptap/html": "3.16.0",
"@tiptap/pm": "3.16.0",
"@tiptap/react": "3.16.0",
"@tiptap/starter-kit": "3.16.0",
"@tiptap/static-renderer": "3.16.0",
"@tiptap/suggestion": "3.16.0",
"@trpc/client": "^11.17.0",
"@trpc/next": "^11.17.0",
"@trpc/react-query": "^11.17.0",
"@trpc/server": "^11.17.0",
"@types/stream-to-blob": "^2.0.0",
"@typescript/analyze-trace": "^0.10.1",
"algoliasearch": "^4.23.3",
"archiver": "^6.0.1",
"blurhash": "^2.0.4",
"chalk": "^5.2.0",
"chart.js": "^4.4.0",
"chartjs-adapter-dayjs-4": "^1.0.4",
"circular-dependency-plugin": "^5.2.2",
"cloudflare": "^2.9.1",
"clsx": "^2.1.1",
"compromise": "^14.14.4",
"cookies-next": "^2.1.1",
"dayjs": "^1.11.12",
"decimal.js": "^10.5.0",
"devalue": "5.8.1",
"diff": "4.0.2",
"discord-api-types": "^0.38.37",
"discord.js": "^14.7.1",
"dotenv": "^16.4.5",
"draft-js": "^0.11.7",
"embla-carousel": "^8.6.0",
"embla-carousel-autoplay": "^8.5.2",
"embla-carousel-react": "^8.5.2",
"exceljs": "^4.4.0",
"exifreader": "^4.39.0",
"fastest-levenshtein": "^1.0.16",
"file-saver": "^2.0.5",
"google-auth-library": "^9.15.0",
"googleapis": "^144.0.0",
"gray-matter": "^4.0.3",
"happy-dom": "^20.0.2",
"he": "^1.2.0",
"html-to-text": "^9.0.5",
"html2canvas-pro": "2.3.8",
"htmlparser2": "8.0.2",
"idb-keyval": "^6.2.0",
"immer": "^9.0.15",
"instantsearch.js": "4.64.1",
"jose": "^6.0.11",
"js-yaml": "^4.1.1",
"jsonwebtoken": "^9.0.1",
"jssha": "^3.3.1",
"jszip": "^3.10.1",
"konva": "^10.0.12",
"linkify-react": "^4.1.3",
"linkifyjs": "^4.1.3",
"lodash-es": "^4.17.21",
"lottie-react": "^2.4.1",
"lru-cache": "^11.2.2",
"mantine-react-table": "^2.0.0-beta.9",
"masonic": "^3.7.0",
"meilisearch": "0.33.0",
"motion": "^11.11.17",
"msgpackr": "^1.10.2",
"next": "^16.3.1",
"nodemailer": "^6.8.0",
"obscenity": "^0.4.5",
"openai": "^4.73.0",
"p-limit": "^6.2.0",
"path-to-regexp": "^6.2.1",
"pg": "^8.11.3",
"prom-client": "^14.2.0",
"qrcode.react": "^4.2.0",
"query-string": "^7.1.1",
"rand-seed": "^1.0.2",
"randomstring": "^1.3.0",
"react": "^18.3.1",
"react-blurhash": "^0.2.0",
"react-chartjs-2": "^5.2.0",
"react-dom": "^18.3.1",
"react-easy-crop": "^5.4.1",
"react-highlight-within-textarea": "^3.2.1",
"react-hook-form": "^7.71.1",
"react-instantsearch": "7.12.0",
"react-instantsearch-router-nextjs": "7.12.0",
"react-intersection-observer": "^9.4.0",
"react-joyride": "^2.9.3",
"react-konva": "^18.2.14",
"react-markdown": "^9.0.1",
"react-social-media-embed": "^2.5.9",
"recheck": "^4.5.0",
"redis": "^5.8.3",
"rehype-raw": "^7.0.0",
"rehype-stringify": "^10.0.1",
"remark-breaks": "^4.0.0",
"remark-gfm": "^4.0.0",
"remark-parse": "^11.0.0",
"remark-rehype": "^11.1.1",
"request-ip": "^3.3.0",
"sanitize-html": "2.12.1",
"sass": "^1.82.0",
"semver": "^7.6.0",
"sharp": "^0.32.6",
"slate": "^0.94.1",
"slate-history": "^0.93.0",
"slate-react": "^0.95.0",
"slugify": "^1.6.5",
"socket.io-client": "^4.5.4",
"source-map": "^0.7.4",
"sqids": "^0.3.0",
"stacktrace-parser": "^0.1.10",
"stream-to-blob": "^2.0.1",
"stripe": "^11.6.0",
"superjson": "^2.2.6",
"three": "^0.180.0",
"trie-memoize": "^1.2.0",
"unfurl.js": "^6.4.0",
"unified": "^11.0.5",
"use-sound": "^5.0.0",
"uuid": "^9.0.0",
"viem": "^2.30.6",
"xml2js": "^0.6.2",
"yaml": "^2.8.1",
"zod": "^4.0.17",
"zustand": "^4.3.7"
},
"devDependencies": {
"@anthropic-ai/claude-agent-sdk": "^0.2.6",
"@electric-sql/pglite": "^0.4.6",
"@faker-js/faker": "^9.0.3",
"@ladle/react": "^5.1.1",
"@next/eslint-plugin-next": "^15.5.19",
"@playwright/test": "^1.57.0",
"@prisma/generator-helper": "^5.22.0",
"@types/archiver": "^6.0.2",
"@types/cloudflare": "^2.7.9",
"@types/diff": "4.0.2",
"@types/file-saver": "^2.0.7",
"@types/he": "^1.2.3",
"@types/html-to-text": "^9.0.4",
"@types/js-yaml": "^4.0.9",
"@types/jsonwebtoken": "^9.0.2",
"@types/lodash-es": "^4.17.7",
"@types/mailchimp__mailchimp_marketing": "^3.0.12",
"@types/marked": "^4.0.7",
"@types/node": "24.13.3",
"@types/node-os-utils": "^1.3.1",
"@types/nodemailer": "^6.4.7",
"@types/offscreencanvas": "^2019.7.3",
"@types/pg": "^8.11.0",
"@types/pg-format": "^1.0.5",
"@types/randomstring": "^1.1.8",
"@types/react": "18.0.14",
"@types/react-dom": "18.0.5",
"@types/request-ip": "^0.0.37",
"@types/sanitize-html": "^2.6.2",
"@types/semver": "^7.7.1",
"@types/sharp": "^0.31.0",
"@types/three": "^0.180.0",
"@types/uuid": "^9.0.0",
"@types/vimeo__player": "^2.18.3",
"@types/xml2js": "^0.4.14",
"@typescript-eslint/eslint-plugin": "^5.33.0",
"@typescript-eslint/parser": "^5.33.0",
"@vitest/browser": "^4.1.11",
"@vitest/browser-playwright": "4.1.11",
"@vitest/coverage-v8": "^4.1.11",
"autoprefixer": "^10.4.19",
"cross-env": "^7.0.3",
"cssnano": "^7.0.1",
"esbuild": "^0.25.5",
"eslint": "8.57.1",
"eslint-config-next": "^15.5.19",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-local-rules": "^3.0.2",
"eslint-plugin-tailwindcss": "^3.15.1",
"husky": "^9.1.1",
"jsdom": "^27.4.0",
"pg-format": "^1.0.4",
"playwright": "^1.57.0",
"postcss": "^8.5.3",
"postcss-assign-layer": "^0.4.0",
"postcss-preset-mantine": "^1.17.0",
"postcss-simple-vars": "^7.0.1",
"prettier": "^2.8.8",
"prisma": "^6.3.0",
"prisma-generator-typescript-interfaces": "^1.6.1",
"prisma-kysely": "^2.2.0",
"tailwindcss": "^3.4.3",
"ts-node": "^10.9.1",
"tsx": "^4.19.2",
"turbo": "^2.9.17",
"typed-scss-modules": "^8.1.1",
"typescript": "^5.9.2",
"vitest": "^4.1.11",
"vitest-browser-react": "^2.2.0",
"ws": "^8.19.0"
},
"ct3aMetadata": {
"initVersion": "6.2.1"
},
"//eslint-config-next": "Stay on major 15. v16 is flat-config-only (peer eslint >=9); extending it from .eslintrc.js makes @eslint/eslintrc reject it and then crash while formatting the error, so lint silently never runs. Pinned below so a `pnpm up` can't walk it forward.",
"pnpm": {
"overrides": {
"eslint-config-next": "15",
"vite": "6.4.3",
"protobufjs@7": "^7.5.6",
"fast-xml-parser": "^5.9.3",
"@aws-sdk/core>fast-xml-parser": "5.2.5",
"axios": "^1.16.0",
"undici@6": "^6.27.0",
"tar-fs@2": "^2.1.5",
"tar-fs@3": "^3.1.3",
"ws@7": "^7.5.11"
},
"onlyBuiltDependencies": [
"@parcel/watcher",
"@prisma/client",
"@prisma/engines",
"bigint-buffer",
"bufferutil",
"core-js",
"esbuild",
"exifreader",
"msgpackr-extract",
"prisma",
"protobufjs",
"sharp",
"unrs-resolver",
"utf-8-validate"
],
"patchedDependencies": {
"@mantine/hooks": "patches/@mantine__hooks.patch"
}
}
}