Zachary Lowden c78f85dd5a fix(deps): Next 16.3.0 → 16.3.1, and make the compiled-branch gate hard (#3983) (#4075)
* fix(deps): Next 16.3.0 -> 16.3.1, and make the compiled-branch gate hard (#3983)

This is the fix for #3983. The defect was in the bundler, not in our source.

Turbopack's value analyzer in 16.3.0 models a bare `return someAsyncFn()` tail
call as `Promise<Promise<T>>`. That is always truthy, so a caller that `await`s
it is analysed as always-true and every statement after the resulting
conditional is eliminated as dead code. `isAppListingsEnabled` ends in exactly
that shape, which is why `resolveStoreVisibilityScopeUninstrumented` lost two of
its three returns, fell off the end, and produced `undefined` for every
non-privileged caller — served as the whole catalog on one read path
(`?? 'full'`) and as an empty store on the other (`?? 'none'`).

Upstream: vercel/next.js#96601 "[turbopack] Collapse nested promises in the
analyzer", backported as #96675, shipped in 16.3.1.

MEASURED, not inferred. Two production builds of THIS commit on one machine,
same Node 24.19.0, differing only in the pinned Next:

  16.3.0  async function S(e){if(await p(e))return"full"}
  16.3.1  async function w(e){return await c(e)?"full":await y(e)?"public-external":"none"}

Both read out of the emitted `.next/server` chunks by source-map attribution and
identified by their source neighbour `STORE_SCOPE_FLAGS`, never by minified
name. Note the fixed form is a TERNARY — `grep 'return"public-external"'`
returns zero on the FIXED build too, which is why the gate reads source maps.

`package.json` already allowed 16.3.1 (`^16.3.0`); only the lockfile pinned
16.3.0, so the substance here is the lockfile. The floor is raised to `^16.3.1`
so a fresh resolution cannot land back on the broken compiler. `patches/next@…`
is renamed and its `patchedDependencies` key updated — that patch is the
unrelated libvips/SVG one-liner (vercel/next.js#96681), it still applies
cleanly, and 16.3.1 still does not carry the loader entry upstream, so it stays.

`--warn-only` is removed from `scripts/assert-compiled-branches.mjs` in the same
commit. It existed only because the 16.3.0 build genuinely violated the gate,
and a permanently-red gate trains everyone to click through. Keeping the bump
and the strictness atomic means the gate's strictness always matches the
toolchain: a revert of the bump turns it red instead of silently passing.

Verified on this commit:
  - gate exit 0 (hard, no --warn-only) against the 16.3.1 build
  - gate exit 1 against a 16.3.0 build of the same tree — watched red
  - `scripts/ci/assert-next-svg-patch-applied.mjs` OK on both installed copies
  - unit suite 1149 files / 18,123 tests passed, 0 failed

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

* fix(build): ship @swc/helpers' module-sync branch into the standalone image (#3983)

The bump built clean, passed every source-level gate — unit suites, typecheck,
ESLint + Prettier, schema drift, the event-engine pin, and the now-hard
compiled-branch gate — and the container could not boot:

  Error: Cannot find module '.../@swc/helpers/esm/_interop_require_default.js'
      at ... next/dist/server/require-hook.js
    code: 'MODULE_NOT_FOUND'

Same shape as the defect this PR exists to fix: a correct source tree producing
a broken artefact, invisible to everything that reads source.

ROOT CAUSE, measured on the published artefact rather than inferred.
`output: 'standalone'` does not ship node_modules; it ships the subset
@vercel/nft traced. nft resolves a bare specifier under the `require`/`default`
conditions. Node (>= 22.10) additionally honours `module-sync` for a CJS
`require`. When a package's `exports` map points those two at different files,
the build traces one and the running process asks for the other.

next/dist/shared/lib/constants.js does
`require('@swc/helpers/_/_interop_require_default')`, reached from the generated
server.js via `next` -> config.js -> constants.js, i.e. before any application
code. The relevant delta is not next itself but next's own dependency:

                                 next 16.3.0        next 16.3.1
  @swc/helpers                   0.5.15             0.5.23
  ./_/_interop_require_default   {import,default}   {module-sync,webpack,import,default}
  require.resolve() under CJS    cjs/...cjs         esm/...js

Both resolutions were RUN, not reasoned about. nft still traced the cjs file, so
the published image carried that package as exactly cjs/_interop_require_default.cjs,
cjs/_interop_require_wildcard.cjs and package.json — no esm/ directory at all.
Adding only the missing esm/ directory to that exact image, nothing else changed,
boots it: "Next.js 16.3.1 ... Ready".

FIX. `outputFileTracingIncludes` force-includes BOTH condition branches of EVERY
installed @swc/helpers copy — not the one file missing today, because which
helper Next requires and which branch each resolver picks are upstream details
that move. Globs are version- and hash-agnostic (`@swc+helpers@*`), plus a flat
form for a hoisted layout. ~950 KB per copy. Verified on a local production
build of this commit: both copies land in .next/standalone with complete esm/
(108 and 105 files) and cjs/, and next's virtual store links the 0.5.23 copy.

Attached to three existing API-route keys rather than a `'**'` key.
copyTracedFiles unions every entry's traced set into the single
.next/standalone node_modules, so one entry carrying it is enough, while `'**'`
would make all 572 entries read/parse/rewrite their .nft.json concurrently —
826 MB of JSON in one Promise.all — on a build already tuned against OOM.

GATE, because a glob is a silent no-op once it stops matching.
scripts/ci/assert-standalone-boot-graph.mjs runs in the Dockerfile's RUNNER
stage: the first gate in that file to run against the runtime filesystem rather
than the build tree, and the only one that can see this class of defect. It
reads the GENERATED server.js for the specifiers that process requires at module
scope and loads them in a child rooted at the shipped tree — no package, version,
virtual-store path or patch hash hardcoded, so it keeps covering this after the
next bump. Exit 2, never 0, when it cannot observe its input. It must run in the
runner and not the builder: /app there is byte-for-byte what ships, whereas the
builder's complete node_modules sits above .next/standalone on the resolution
path and can satisfy a require the image cannot.

Watched red and green on real artefacts, not only fixtures:
  - exit 1 with this exact MODULE_NOT_FOUND against the published broken image;
  - exit 0 against the same image with only the esm/ directory added;
  - exit 0 against the local production build of this commit, isolated from any
    parent node_modules;
  - exit 1 again after deleting exactly esm/_interop_require_default.js from
    that same local build.
src/tests/build/standalone-boot-graph.test.ts pins the MECHANISM (a
module-sync/default split with only the default branch present) rather than the
package, and all 5 of its cases were watched to fail against a neutered gate.

NOT VERIFIED. Nothing about production: this is only true of production once it
merges, is promoted main -> release, is built and is serving. The gate covers the
ENTRYPOINT's require graph; route chunks load lazily, so a condition mismatch
reachable only from a route would still surface at request time.

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

* chore: retrigger preview

The previous preview run (pr-preview-4075-b2wnw) never scheduled: its
build-image and typecheck pods sat Pending with ExceededNodeResources for
82 minutes and the run hit the 1h30m PipelineRunTimeout. No verdict was
produced — this was build-pool capacity contention, not a code failure.

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

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 15:07:05 -05:00
2024-12-16 16:24:45 -05:00
2024-05-16 16:46:10 -06:00
2025-08-12 13:20:21 -04:00
2025-06-07 17:36:07 -04:00
2023-04-12 20:34:56 +01:00
2026-07-30 13:19:05 -05:00

Contributors Forks Stargazers Issues Apache License 2.0 Discord


Table of Contents

About the Project

Our goal with this project is to create a platform where people can share their stable diffusion models (textual inversions, hypernetworks, aesthetic gradients, VAEs, and any other crazy stuff people do to customize their AI generations), collaborate with others to improve them, and learn from each other's work. The platform allows users to create an account, upload their models, and browse models that have been shared by others. Users can also leave comments and feedback on each other's models to facilitate collaboration and knowledge sharing.

Tech Stack

We've built this project using a combination of modern web technologies, including Next.js for the frontend, TRPC for the API, and Prisma + Postgres for the database. By leveraging these tools, we've been able to create a scalable and maintainable platform that is both user-friendly and powerful.

  • DB: Prisma + Postgres
  • API: tRPC
  • Front-end + Back-end: NextJS
  • UI Kit: Mantine
  • Storage: Cloudflare

Getting Started

To get a local copy up and running, follow these steps.

Prerequisites

First, make sure that you have the following installed on your machine:

  • Docker (for running the database and services)
  • If using devcontainers
    • An IDE that supports them (VS Code with devcontainers extension, Jetbrains, etc.)
  • If running directly
    • Node.js (version 20 or later)
      • We recommend you have installed nvm in order to set the right node version to run this project
        curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
        
    • Make (optional, for easier initial setup)

Installation

  1. Follow the Prerequisites steps above
  2. Clone the repository to your local machine
  3. Choose one method:
    • a) Use devcontainers

      ⚠️ Important Warning for Windows Users: Either clone this repo onto a WSL volume, or use the "clone repository in named container volume" command. Otherwise, you will see performance issues.

      • Open the directory up in your IDE of choice
        • VS Code should prompt you to "Open in container"
          • If not, you may need to manually run Dev Containers: Open Folder in Container
        • For other IDEs, you may need to open the .devcontainer/devcontainer.json file, and click "Create devcontainer and mount sources"
        • Note: this may take some time to run initially
      • Run make run or npm run dev
    • b) Run make init
      • This command will do a few things:
        • Creates a starter env file
        • Installs npm packages
        • Spins up docker containers
        • Runs any additional database migrations
        • Creates some dummy seed data
        • Populates metrics and meilisearch
        • Initializes prisma
        • Runs the server
      • If you see an error about an app not being found, make sure node_modules/.bin is added to your path:
        • export PATH="$PATH:$(realpath node_modules/.bin)"
      • If you are an internal member, you can use the buzz and signals service
        • Set this up once by creating a personal access token in github (with read package permissions)
        • Set that to CR_PAT env
        • Run echo $CR_PAT | docker login ghcr.io -u USERNAME --password-stdin
    • Please report any issues with these commands to us on discord
  4. Edit the .env.development file
    • Most default values are configured to work out of the box, except the S3 upload key and secret. To generate those, navigate to the minio web interface at http://localhost:9000 with the default username and password minioadmin, and then navigate to the "Access Keys" tab. Click "Create Access Key" and copy the generated key and secret into the .env file (S3_UPLOAD_KEY and S3_UPLOAD_SECRET, S3_IMAGE_UPLOAD_KEY and S3_IMAGE_UPLOAD_SECRET).
    • Set WEBHOOK_TOKEN to a random string of your choice. This will be used to authenticate requests to the webhook endpoint.
    • Add a random string of your choice to the email properties to allow user registration
      • EMAIL_USER
      • EMAIL_PASS
      • EMAIL_FROM (Valid email format needed)
  5. Run git submodule update --recursive
  6. Finally, visit http://localhost:3000 to see the website.

* Note that account creation will run emails through maildev, which can be accessed at http://localhost:1080.

Altering your user

  • First, create an account for yourself as you normally would through the UI.
  • You may wish to set yourself up as a moderator. To do so:
    • Use a database editor (like DataGrip) or connect directly to the DB (PGPASSWORD=postgres psql -h localhost -p 15432 -U postgres civitai)
    • Find your user (by email or username), and change isModerator to true

Known limitations

Services that require external input will currently not work locally. These include:

  • Orchestration (Generation, Training)
  • Signals (Chat, Notifications, other real-time updates)
  • Buzz

Contributing

Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork the repository to your own GitHub account.
  2. Create a new branch for your changes.
  3. Make your changes to the code.
  4. Commit your changes and push the branch to your forked repository.
  5. Open a pull request on our repository.

If you would like to be more involved, consider joining the Community Development Team! For more information on the team as well as how to join, see Calling All Developers: Join Civitai's Community Development Team.

Data Migrations

Over the course of development, you may need to change the structure of the database. To do this:

  1. Make your changes to the packages/civitai-db-schema/prisma/schema.prisma file
  2. Run pnpm run db:migrate:empty "brief description here". This creates packages/civitai-db-schema/prisma/migrations/YYYYMMDDHHmmss_brief_description_here/migration.sql for you, in the one directory Prisma reads. To create it by hand instead, use that same path — not the prisma/migrations directory at the repo root, which predates the monorepo layout and is no longer read.
  3. Put your sql changes in the generated migration.sql
    • These are usually simple sql commands like ALTER TABLE ...
  4. Run make run-migrations and make gen-prisma
  5. If you are adding/changing a column or table, please try to keep the gen_seed.ts file up to date with these changes.

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website.

License

Apache License 2.0 - Please have a look at the LICENSE for more details.

S
Description
clickup: Interact with ClickUp tasks and documents - get task details, view comments, create and manage tasks, create and edit docs. Use when working with ClickUp…; quick-mockups: Create multiple UI design mockups in parallel. Use when asked to create mockups, wireframes, or design variations for a feature. Creates HTML files using…
Readme 362 MiB
Languages
TypeScript 93.3%
JavaScript 2.6%
Svelte 2.5%
PLpgSQL 0.5%
SCSS 0.4%
Other 0.6%