OpCreative
Production fulfillment platform for print-on-demand sellers — a full rebuild of a legacy system with zero-downtime cutover and nightly checksum-verified delta sync.
Summary
OpCreative is a fulfillment platform for print-on-demand sellers, live in production at opcreative.us and replacing a client's legacy system. It's a Turborepo monorepo — a Next.js 16 (App Router) dashboard plus shared libs for database, auth, and types — written in TypeScript: ~80,000 lines of TS/TSX, plus 4,200 lines of SQL and a 1,900-line Prisma 7 schema (45 models, 24 enums, 48 migrations across 9 domain files). It runs on Vercel against Neon PostgreSQL, with Auth.js v5 (Google OAuth, password, and email OTP via Resend), Vercel Blob for files, and an embedded AI assistant on Moonshot's kimi-k3 through the Vercel AI SDK. Nine feature modules cover catalog, orders, fulfillment, inventory, finance, identity, support, platform services, and the assistant, across 38 pages and 14 API routes, fully internationalized into 6 languages (1,878 keys each, enforced by CI). The legacy system's live database delta-syncs into production nightly via cron with checksum verification and email alerting. Built solo in 328 commits since July 2026; the dashboard is live, catalog v2 is mid-flight, and the public storefront and multi-tenancy are planned.
Target user
Print-on-demand fulfillment operations and the sellers they serve. Sellers get a private dashboard for orders, catalog, and billing in their own language (6 locales); the ops team gets warehouse, inventory, procurement, and finance tooling in one system instead of spreadsheets plus an aging legacy app. Unlike off-the-shelf POD platforms, it models the client's actual bill-of-materials and multi-warehouse flow.
- 01
Nine domain modules (catalog, orders/fulfillment, inventory/BOM, finance, identity, support, platform, assistant, core) behind a shared guard/scope/audit kernel — every server action passes role-permission checks and writes an audit trail
- 02
Options-as-data catalog v2 with deterministically generated SKUs (e.g. `HW-TRK-GK-LG__P-C`) so variants are data, not schema
- 03
Bulk order upload: Excel intake with fuzzy product matching, validation, and per-row error reporting
- 04
Full i18n in 6 locales (en, zh, vi, ja, ko, fr), 1,878 keys each, single-dictionary server-side loading with a CI gate that fails on untranslated or missing keys
- 05
In-app AI assistant with tool access scoped to the user's permissions, structured output forced via tool calls (the model lacks native JSON mode), and a schema digest auto-generated from the Prisma files
- 06
Database-backed search with pg_trgm indexes (627ms → 30ms) plus client-side fuzzy ranking
- 07
Warehouse operations: stations, shipping labels, tracking, barcode/QR generation, PDF label pipelines
- 08
Nightly checksum-verified delta sync from the client's live legacy database, with escalating email alerts on consecutive failures
Built a delta-sync pipeline (SQL diff scripts on a cron box, read-only access into the client's live DB via a jump host) with per-field checksums to detect drift and escalating email alerts on failed ticks. Trade-off accepted: the sync is one-way by convention and alerting catches failures, not silently-wrong data — a drift incident (82 bad rows over 11 days) led to the checksum method.
Built generateStructured() — a forced tool call with toolChoice 'required' whose input schema is the desired output schema — plus a build step that parses the Prisma schema files into a context digest so the assistant knows the data model without hand-maintained docs. Trade-off: one extra round-trip shape versus swapping to a pricier model.
Fixed with pg_trgm GIN indexes, restructured queries, cached dashboard stats, and tuning Neon's suspend timeout — search dropped 627ms → 30ms without adding a search service.
- L01
A green build proves nothing about content.
~110 translation keys rotted because copied English passed tsc, eslint, and the build; only a CI check comparing values caught it. Anything a human can fake by copy-paste needs a semantic check, not a type check.
- L02
Editing the repo is not deploying.
The sync box ran copies of the repo's scripts; 11 days of drift between them wrote 82 bad rows. Every artifact that runs off-repo needs a checksum comparison against source, or it will silently diverge.
- L03
Migrations are the only schema truth.
Banning `prisma db push` entirely — every change is a reviewed, committed migration — is what made a prod database restored-from-snapshot locally, a legacy cutover, and 48 migrations coexist without a single schema-drift incident.
- typescript loc
- 80154
- sql loc
- 4207
- prisma schema loc
- 1931
- git commits
- 328
- dev started
- 2026-07-17
- prisma models
- 45
- prisma enums
- 24
- db migrations
- 48
- feature modules
- 9
- dashboard pages
- 38
- api routes
- 14
- locales
- 6
- i18n keys per locale
- 1878
- test files
- 48
- search latency improvement
- 627ms → 30ms
- team size
- 1