Files
tessera/CLAUDE.md
Gjermund Høsøien Wiggen 1d4dc38d06 docs: update CLAUDE.md, redesign AGENTS.md, add design-system.md
- CLAUDE.md: updated API endpoints, dev workflow, current stack
- web/AGENTS.md: replaced auto-generated text with Tessera design rules
- docs/design-system.md: new — component patterns, typography scale,
  color tokens, anti-patterns to avoid

Ensures design consistency across all future work.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-09 23:07:32 +02:00

4.7 KiB

Tessera

Open-source ticketing system — Request Tracker's paradigm rebuilt in modern TypeScript.

Architecture

tessera/
├── src/                    # Backend: Bun + Hono + Drizzle ORM
│   ├── index.ts            # Hono server entry (port 9876)
│   ├── config.ts           # Zod-validated env config
│   ├── db/                 # Drizzle ORM schema + migrations
│   ├── routes/             # REST API endpoints
│   ├── models/             # TypeScript types + Zod schemas
│   ├── scrip/              # Scrip engine (prepare/commit two-phase)
│   └── lifecycle/          # State machine validator
├── web/                    # Frontend: Next.js 16 + shadcn/ui
│   ├── src/app/            # App Router pages
│   ├── src/components/     # Reusable components + widgets
│   └── src/lib/            # API client + types + utils
├── drizzle/                # SQL migration files
└── docs/                   # Architecture + design specs

Stack

Backend: Bun runtime, Hono web framework, Drizzle ORM, PostgreSQL 17, Zod validation, Handlebars templates, nodemailer

Frontend: Next.js 16 App Router (Turbopack), shadcn/ui (Tailwind CSS), next-themes, date-fns, lucide-react icons

Fonts: Inter (variable), JetBrains Mono

Running Locally

Prerequisites

  • Bun (nix-shell -p bun or install globally)
  • Node.js 22+ (nix-shell -p nodejs_22)
  • Docker (for PostgreSQL)
  • PostgreSQL container: docker run -d --name tessera-db -e POSTGRES_USER=tessera -e POSTGRES_PASSWORD=*** -e POSTGRES_DB=tessera -p 127.0.0.1:5433:5432 postgres:17-alpine

Start backend

cd ~/projects/tessera
cp .env.example .env
npm run dev:backend   # Starts API on port 9876

Run migrations

npm run db:migrate
npm run db:seed         # Demo data
npm run db:seed:reset   # Reset + re-seed

Start frontend

cd web
npm install             # Use npm, NOT bun
bun run dev             # Dev server on 127.0.0.1:3100 (HMR)

API Endpoints

All endpoints on port 9876. Frontend proxies /api/* via next.config.ts.

Method Path Description
GET /health Health check
GET /tickets List tickets (?queue_id=&status=&owner_id=&team_id=&q=&limit=&cf.*=)
POST /tickets Create ticket
GET /tickets/:id Get ticket with custom fields
PATCH /tickets/:id Update ticket (validates lifecycle, runs scrips, returns scrip_results)
POST /tickets/:id/preview Dry-run scrips for status change
POST /tickets/:id/comment Add comment to ticket
GET /tickets/:id/transactions List ticket transactions
GET/POST/PATCH /queues CRUD queues
GET/POST/PATCH/DELETE /scrips CRUD scrips
GET/POST/PATCH /custom-fields CRUD custom fields
GET/POST/PATCH /lifecycles CRUD lifecycles
GET/POST/PATCH/DELETE /users CRUD users
GET/POST/PATCH/DELETE /templates CRUD templates + POST /preview
GET/POST/PATCH/DELETE /views CRUD saved views
GET/POST/PATCH/DELETE /teams CRUD teams + POST/DELETE members
GET/POST/PATCH/DELETE /dashboards CRUD dashboards + widgets + widget data

Key Design Decisions

  • Ticket IDs are sequential integers (1, 2, 3...), formatted as TKT-0001 for display. No UUIDs.
  • Transaction-centric: Every state change creates a transaction record. The scrip engine runs on transactions.
  • Two-phase scrip engine: Prepare (no side effects) then Commit (execute actions). Supports dry-run mode.
  • Lifecycle state machines: Per-queue configurable status transitions with wildcard support.
  • SQL-level filtering: Ticket filters (status, queue, owner, team, custom fields) pushed to PostgreSQL via Drizzle WHERE clauses.
  • No ORM for frontend: Drizzle is only on the backend. Frontend uses a typed fetch wrapper (web/src/lib/api.ts).
  • Dev server over production: Use bun run dev (port 3100) with HMR. Build+restart only when dev server has issues.
  • Design consistency: See docs/design-system.md for the design rules applied across the app.

Git Workflow

Repo: https://git.gjermund.xyz/gjermund/tessera

git remote set-url origin https://gjermund:TOKEN@git.gjermund.xyz/gjermund/tessera.git

Common Issues

  • Frontend shows skeleton/blank page: Dev server may have HMR issues. Kill port 3100, rebuild with npm run build, restart with npm run start.
  • Backend not running on 9876: Restart with bun run src/index.ts. Check port with ss -tlnp | grep 9876.
  • Database connection refused: Docker container may be stopped. docker start tessera-db.
  • Build errors after migration: Run bun run src/db/migrate.ts to apply new migrations.