Architecture
A single Next.js 16 application (App Router, Server Components and Server Actions) talking directly to PostgreSQL 16, packaged with Docker. Sign-in is delegated to a shared authentication service.
Why PostgreSQL: the schema needs JSONB, timestamptz, EXCLUDE USING gist constraints, triggers that block ledger edits, generated columns, pg_trgm and unaccent.
Code layers
| Layer | Role |
|---|---|
| Screens (routes) | Server Components read data and check permissions; Server Actions handle every write |
| Business core | Inventory ledger posting, order lifecycle, reports, authentication and permissions, with no UI code |
| Reusable UI | Tables, forms, SVG icons, following the Tân Doanh design system, no emoji |
| Migrations | One numbered file per feature; building an empty database runs them all in order |
Conventions
Folders, routes and business functions use Vietnamese names without diacritics; technical terms stay in English. There is an 8-step recipe for adding a feature: migration, business logic, action, screen, menu and permissions, labels, tests, build.
Search and speed
The catalogue of more than 5,000 products downloads a slimmed-down copy to the browser so search is instant without asking the server; a trigram index handles fuzzy, accent-insensitive matching; navigation caching makes tab clicks appear almost immediately.