* test(preview): fix whatIfFromGraph smoke test against tRPC request batching The `whatIfFromGraph fires on /generate` preview smoke test has failed 100% of the time on every PR. It is NOT a cold pod, a DB artifact, or a product defect: driving a live preview shows the request fires ~1.3s after navigation and returns HTTP 200 with `cost.total = 8`. Two test-side defects, both introduced by `trpcBatching` (#2946) ramping on: 1. URL predicate. `httpBatchStreamLink` coalesces concurrent queries into one request whose path is the COMMA-JOINED procedure list, and whatIf is last: /api/trpc/content.get,challenge.getInfinite,...,orchestrator.whatIfFromGraph That does not contain `/api/trpc/orchestrator.whatIfFromGraph`, so `waitForResponse` never matched and timed out on a request that succeeded. Now matched by procedure name within the path list (batched or not). 2. Body shape + capture. The client sends `trpc-accept: application/jsonl`, so the response is newline-delimited chunks — `response.json()` throws, and the payload sits at a different depth than the old walk expected. Parse raw text, handling all three wire shapes, and locate the payload structurally (numeric `cost.total` + boolean `ready`, the whatIf contract) so a sibling procedure in the batch cannot produce a false pass. The app also reads the full stream and then abandons the idle reader, which Chromium reports as `net::ERR_ABORTED` and evicts — making a later `response.text()` fail with "No data found for resource" on 4 of 8 loads. The body is now buffered by a route handler, removing that race. Verified against the live preview for PR #3535: red at origin/main (45s `waitForResponse` timeout, the exact CI signature), green after, 12/12 runs (11/12 without the internal retry), ~2s to the assertion. Mutation-checked: disabling the jsonl branch fails with this guard's own error ("cost.total parsed from whatIfFromGraph response" -> null). The 45s budget is unchanged and the test still guards the pre-spend cost quote. * fix(test): narrow capturedBody honestly instead of casting through null CI Typecheck failed: tests/preview-generation.spec.ts(177,24): error TS2352: Conversion of type 'null' to type 'string' may be a mistake `capturedBody` is declared `string | null`, but it is assigned from inside the `page.route` closure, which TS control-flow analysis cannot see. After the per-attempt reset to null, TS narrows it to `null` at the return, making `as string` an illegal null->string conversion. Replaced the `expect(...).not.toBeNull()` + cast with an explicit null check. That narrows the type honestly, removes the cast entirely, and fails with a message distinguishing the two halves: the response was observed, but the route handler did not capture its body. Verified: tsc error count 22 at origin/main and 22 here in the same environment (delta 0), with zero errors mentioning this spec. The 22 are pre-existing local artifacts (no prisma generate on NixOS, missing submodule). Why this was not caught before pushing: the fix was verified by RUNNING the Playwright spec 12 times, and Playwright transpiles without full type checking. `tests/` is in the tsconfig include set, so CI checks it — a green Playwright run is not a typecheck. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: audit <alexhurwitz.dev@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
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
nvmin order to set the right node version to run this projectcurl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
- We recommend you have installed
- Make (optional, for easier initial setup)
- Node.js (version 20 or later)
Installation
- Follow the Prerequisites steps above
- Clone the repository to your local machine
- 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
- If not, you may need to manually run
- For other IDEs, you may need to open the
.devcontainer/devcontainer.jsonfile, and click "Create devcontainer and mount sources" - Note: this may take some time to run initially
- VS Code should prompt you to "Open in container"
- Run
make runornpm run dev
- Open the directory up in your IDE of choice
- b) Run
make init- This command will do a few things:
- Creates a starter
envfile - 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
- Creates a starter
- If you see an error about an app not being found, make sure
node_modules/.binis 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_PATenv - Run
echo $CR_PAT | docker login ghcr.io -u USERNAME --password-stdin
- This command will do a few things:
- Please report any issues with these commands to us on discord
- a) Use devcontainers
- Edit the
.env.developmentfile- 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.envfile (S3_UPLOAD_KEYandS3_UPLOAD_SECRET,S3_IMAGE_UPLOAD_KEYandS3_IMAGE_UPLOAD_SECRET). - Set
WEBHOOK_TOKENto 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_USEREMAIL_PASSEMAIL_FROM(Valid email format needed)
- 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
- Run
git submodule update --recursive - 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
isModeratortotrue
- Use a database editor (like DataGrip) or connect directly to the
DB (
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!
- Fork the repository to your own GitHub account.
- Create a new branch for your changes.
- Make your changes to the code.
- Commit your changes and push the branch to your forked repository.
- 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:
- Make your changes to the
packages/civitai-db-schema/prisma/schema.prismafile - Run
pnpm run db:migrate:empty "brief description here". This createspackages/civitai-db-schema/prisma/migrations/YYYYMMDDHHmmss_brief_description_here/migration.sqlfor you, in the one directory Prisma reads. To create it by hand instead, use that same path — not theprisma/migrationsdirectory at the repo root, which predates the monorepo layout and is no longer read. - Put your sql changes in the generated
migration.sql- These are usually simple sql commands like
ALTER TABLE ...
- These are usually simple sql commands like
- Run
make run-migrationsandmake gen-prisma - If you are adding/changing a column or table, please try to keep the
gen_seed.tsfile 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.