|
|
||
|---|---|---|
| .github/workflows | ||
| .w4c | ||
| app | ||
| components | ||
| docker | ||
| lib | ||
| messages | ||
| prisma | ||
| public | ||
| tests | ||
| .dockerignore | ||
| .env.example | ||
| .eslintrc.json | ||
| .gitignore | ||
| middleware.ts | ||
| next.config.ts | ||
| package-lock.json | ||
| package.json | ||
| postcss.config.mjs | ||
| README.md | ||
| tsconfig.json | ||
| vitest.config.ts | ||
Admin / CRM — Next.js (templates2)
A ready-to-run internal tool built on the v2 Next.js base: an entity registry (Customers, Deals) with CRUD, roles, CSV import/export and an audit log. Everything works on the first run — SQLite + mock providers need no keys.
Quickstart
npm ci
cp .env.example .env # SQLite + mock providers by default — no keys needed
npm run db:setup # prisma db push + seed (20 customers, 15 deals, audit trail)
npm run dev # http://localhost:3000/admin
Demo accounts (seeded)
| Role | Password | Can do | |
|---|---|---|---|
| admin | admin@example.com |
password |
read, create/edit, delete, import/export |
| editor | editor@example.com |
password |
read, create/edit, import/export |
| viewer | viewer@example.com |
password |
read only |
Roles are enforced server-side on every admin API route (lib/server/guard.ts +
lib/rbac.ts); the UI merely hides what a role cannot do.
What this case adds on top of the base
- Entity registry —
CustomerandDealwith list (search, column filter, sort, pagination), detail, create/edit and delete (delete asks for confirmation).components/admin/CustomersManagerandDealsManagerdrive the/admin/customersand/admin/dealspages. - Dashboard — counters (customers, leads, deals, won value), a deals-by-stage bar chart and
recent activity on
/admin(lib/server/crm.ts#overview). - CSV import —
/admin/importvalidates a CSV, shows a per-row error report and a preview of the first valid rows, then commits. Export is atext/csvdownload. - Audit log — every mutation writes an
AuditLogrow (lib/server/audit.ts);/admin/auditlists it and filters by action. - Loading / empty / error states on every list and the import wizard.
API
| Method | Path | Role |
|---|---|---|
| GET | /api/admin/customers?q=&status=&sort=&page= |
viewer+ |
| POST | /api/admin/customers |
editor+ |
| GET / PATCH / DELETE | /api/admin/customers/:id |
viewer+ / editor+ / admin |
| GET / POST | /api/admin/deals |
viewer+ / editor+ |
| PATCH / DELETE | /api/admin/deals/:id |
editor+ / admin |
| POST | /api/admin/import/customers ({ csv, commit }) |
editor+ |
| GET | /api/admin/export/customers |
viewer+ |
| GET | /api/admin/audit?action= |
viewer+ |
Data model
prisma/schema.prisma: the base User, Session, Subscription, AuditLog plus Customer
and Deal. SQLite in development; point DATABASE_URL at Postgres for production.
Quality
node ../templates2/qa.mjs Admin.Next # from the repo root: node templates2/qa.mjs Admin.Next
The harness runs validate → clone → install → lint → typecheck → unit → build → boot → routes →
e2e → screenshot. See ../CONTRACT.md for the Definition of Done.