Files
XBid/README.md
T
twotalesanimation 396ebf9837
Deploy / deploy (push) Successful in 3m45s
Run database migrations as part of the deploy
The deploy workflow pulled, built and started the app, but never applied
migrations. Shipping a change that adds a table therefore broke the app
until someone remembered to migrate by hand -- the new api_keys table
would have done exactly that to the settings page.

The workflow now builds, applies pending migrations, and only then starts
the app. A failed migration exits non-zero, so the deploy fails instead of
starting an app whose schema is behind its code. Because `up -d` is never
reached in that case, production keeps serving the previous containers.

Migrations run through a new `migrate` compose service built from the
Dockerfile's builder stage, rather than `docker compose exec app npx
prisma migrate deploy` as the README previously suggested. The production
image copies prisma/ and node_modules/.prisma but not the Prisma CLI,
which is a devDependency and is absent from the standalone bundle, so that
command would have had npx download Prisma inside the container at runtime
as the unprivileged nextjs user. The builder stage has the CLI and its
engines already.

The service sits behind a `tools` profile so `docker compose up` never
starts it, and takes DATABASE_URL from compose rather than a .env file --
dotenv does not override variables that are already set, so the compose
value wins.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-11-11 09:30:58 +02:00

5.4 KiB

xBid — VFX Quoting & Bidding SaaS

A professional full-stack VFX quoting application built with Next.js 15, TypeScript, Tailwind CSS v4, Prisma ORM, and PostgreSQL.


Features

  • Clients — manage client companies with full contact and billing info
  • Jobs / Quotes — versioned quote documents with status workflow (Draft ? Sent ? Approved/Rejected)
  • Shots — VFX shot breakdown with complexity multipliers and drag-and-drop reordering
  • Assets — CG asset budget tracking (characters, environments, vehicles, etc.)
  • Line Items — per-task cost rows with hours/days/artists/rates, markup, discount, tax
  • Rate Cards — studio rate card library organized by department
  • PDF Export — professional quote PDF with front page + detailed appendix
  • Decimal Precision — all financials use decimal.js (no floating-point drift)
  • REST API - create and manage quotes, shots, assets and tasks programmatically (API.md)

Tech Stack

Layer Technology
Framework Next.js 15 (App Router, Server Actions)
Language TypeScript
Styling Tailwind CSS v4 + shadcn/ui
ORM Prisma 7 + PostgreSQL 16
Forms React Hook Form + Zod
Drag & Drop @dnd-kit/core + @dnd-kit/sortable
Finance Math decimal.js
Notifications sonner
PDF HTML render via /api/pdf/[id]

Prerequisites

  • Node.js 20+
  • PostgreSQL 16 (or Docker)
  • npm 10+
  • ts-node for seeding: npm install -g ts-node typescript

Quick Start

1. Clone & install

git clone <repo-url>
cd xBid
npm install

2. Configure environment

cp .env.example .env

Edit .env:

DATABASE_URL="postgresql://postgres:postgres@localhost:5432/xbid"
NEXTAUTH_SECRET="your-random-secret-here"
NEXTAUTH_URL="http://localhost:3000"

3. Start PostgreSQL

Option A — Docker (recommended):

docker compose up -d postgres

Option B — local PostgreSQL:

CREATE DATABASE xbid;

4. Run database migrations

npm run db:generate   # generate Prisma client
npm run db:migrate    # run migrations (enter "init" as migration name)

5. Seed sample data

npm run db:seed

This creates 15 rate cards, 2 sample clients, 2 jobs with shots, assets, and line items.

6. Start development server

npm run dev

Open http://localhost:3000


Production (Docker)

docker compose up --build -d

Pushing to main triggers the Gitea workflow in .gitea/workflows/deploy.yml, which pulls, builds, applies pending migrations, and only then starts the app. A failed migration fails the deploy rather than starting an app whose schema is behind its code, so there is no manual migration step.

Migrations run through the migrate service, which builds from the Dockerfile builder stage. That matters: the production image ships runtime dependencies only, and the Prisma CLI is a devDependency, so docker compose exec app npx prisma ... would try to download Prisma inside the container at runtime.

To run migrations by hand (or to seed on a first deploy):

docker compose --profile tools run --rm migrate
docker compose --profile tools run --rm migrate npx prisma db seed

PDF Export

Navigate to any job and click Download PDF. The route at /api/pdf/[id] generates HTML with:

  • Front page: client info, project details, shot/asset summary, financial totals, T&C
  • Appendix: full per-shot and per-asset line item breakdown

Print to PDF via browser (Ctrl+P ? Save as PDF).


REST API

xBid exposes a REST API at /api/v1 so another system can create and manage quotes, shots, assets and tasks without anyone opening the UI.

Requests authenticate with an API key, created under Settings -> API Keys (admins only):

curl -s http://localhost:3000/api/v1 \
  -H "Authorization: Bearer $XBID_API_KEY"

That endpoint lists every available route and confirms what the key may do. See API.md for the full reference: endpoints, pricing rules, shot code generation and error codes.

Note: GET_SHOTS.md documents the opposite direction - the review app's API that xBid pulls shots from.


Project Structure

src/
  app/                  Next.js App Router pages
    api/pdf/[id]/       PDF generation endpoint
    clients/            Client management
    jobs/               Job management
    rate-cards/         Rate card management
  actions/              Server actions (CRUD)
  components/
    assets/             Asset editor
    clients/            Client form & table
    dashboard/          Stats & recent jobs
    jobs/               Job form, table, detail, totals
    layout/             Sidebar navigation
    line-items/         Line item table & dialog
    rate-cards/         Rate card management
    shots/              Shot editor
    ui/                 shadcn/ui components
  lib/
    calculations.ts     Decimal.js financial math
    constants.ts        Domain constants & defaults
    prisma.ts           Prisma client singleton
    validations.ts      Zod schemas
prisma/
  schema.prisma         Full database schema
  seed.ts               Sample data seeder

Database Scripts

npm run db:generate   # npx prisma generate
npm run db:migrate    # npx prisma migrate dev
npm run db:seed       # ts-node prisma/seed.ts
npm run db:studio     # npx prisma studio (DB GUI at :5555)