// project ·
Iris: Print-Shop Operations Web App
Built one place for print-shop work orders, people, and daily mess, with a React frontend backed by a Go API and SQLite.
Role: Freelance · full stack · Year: 2026 - Present · Status: in development
tldr: Iris is an operations app for a print shop. A React frontend talks to a Go REST API that owns authentication, work orders, customers, reporting, public order tracking, and SQLite persistence. What I took from it: the OpenAPI spec, the Go types, and the TypeScript models have to move together or the client drifts.
Problem
A 15-person print shop tracked work orders, customers, deadlines, and billing in spreadsheets. Staff needed fast browser workflows for all of it, and the state of an order (new, in progress, completed, invoiced) had to be clear without manual status handoffs between people.
Constraints
- Orders have a lifecycle. Every transition from new to invoiced has to look the same in forms, tables, detail pages, and dashboards.
- Contracts drift. OpenAPI, Go domain types, TypeScript models, SQLite storage, and fixtures must change together.
- Tenant isolation. Authentication and every query keep each shop’s users and data inside its tenant.
- Serbian-speaking operators. Statuses, dates, currency, and form labels are localized without pushing locale logic into the models.
- A small shop runs it. Installation and backups have to be something the owner can handle.
Decisions
- A Go API on
chiwith an OpenAPI contract covering auth, work orders, customers, locations, catalog, settings, reports, and public tracking. - HTTP-only session cookies instead of tokens in browser storage.
- Tenant-scoped SQLite with schema migrations, plus a Go CLI for seeding, CSV imports, user management, and backups.
- React Hook Form with Zod keeps dense work-order and billing forms responsive and validates against the shapes the API expects.
- Recharts dashboards for revenue, order volume, operator queues, and clients who need attention.
Outcome
Iris replaced the spreadsheets with role-based access, CRUD workflows for orders and customers, PDF work-order reports, public order tracking, and a five-chart dashboard. It saves the shop more than 10 hours of admin work a week. Two trade-offs were deliberate. Dashboard aggregation runs in the client, which kept reporting screens quick to iterate on. SQLite instead of a database server keeps install and backup practical, and tenant-scoped queries with migrations leave room to grow.
