Files
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

206 lines
5.4 KiB
Markdown

# 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](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
```bash
git clone <repo-url>
cd xBid
npm install
```
### 2. Configure environment
```bash
cp .env.example .env
```
Edit `.env`:
```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):**
```bash
docker compose up -d postgres
```
**Option B — local PostgreSQL:**
```sql
CREATE DATABASE xbid;
```
### 4. Run database migrations
```bash
npm run db:generate # generate Prisma client
npm run db:migrate # run migrations (enter "init" as migration name)
```
### 5. Seed sample data
```bash
npm run db:seed
```
This creates 15 rate cards, 2 sample clients, 2 jobs with shots, assets, and line items.
### 6. Start development server
```bash
npm run dev
```
Open http://localhost:3000
---
## Production (Docker)
```bash
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):
```bash
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):
```bash
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](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
```bash
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)
```