Imported from herloncosta/vault (
AGENTS.md). Install upstream withnpx skills add herloncosta/vault. Copyright stays with the author.
AGENTS.md
Project structure
vault/
├── api/ # Express 5 REST API (Postgres + Prisma v7)
├── client/ # Vite + React 19 + TypeScript 6 SPA
Commands
| Purpose | Directory | Command |
|---|---|---|
API dev server (--watch) |
api/ |
npm run dev |
| API production start | api/ |
npm start |
| Start Postgres | api/ |
npm run db:up |
| Stop Postgres | api/ |
npm run db:down |
| Apply schema | api/ |
npm run db:push |
| Create migration | api/ |
npm run db:migrate |
| Generate Prisma Client | api/ |
npm run db:generate |
| Open Prisma Studio | api/ |
npm run db:studio |
| Run seed | api/ |
npm run db:seed |
| Client dev server | client/ |
npm run dev |
| Build (tsc + vite) | client/ |
npm run build |
| Format via Prettier | client/ |
npm run format |
API gotchas
- Prisma v7 —
datasource.urlgoes inprisma.config.js, not inschema.prisma.new PrismaClient()without a driver adapter fails; usePrismaPgwithconnectionStringfrom env (seesrc/config/database.js). - Auth — tokens delivered via httpOnly cookies (
accessToken,refreshToken). The client sendscredentials: "include". Refresh token rotation invalidates the old token on each use. Access token also accepted asAuthorization: Bearerheader. - RBAC —
ADMINandOPERATOR(default).POST /api/usersrequiresADMIN. OPERATOR can only access own data. - Logger —
pino+pino-prettyin dev,winstonJSON in production (checked viaNODE_ENV). - Modules — routes live in
src/modules/{auth,users,transactions,recurring-expenses,installment-expenses}/. - Test requests —
api/requests.httpworks with VS Code REST Client. - Full API reference at
README.mdand Swagger UI (GET /api-docs).
Client conventions
- Styling — Tailwind CSS v4 via
@tailwindcss/viteplugin. No CSS modules. Dark mode via.darkclass on<html>, toggled byThemeContext(persisted to localStorage keytheme). - Prettier — config at
client/.prettierrc(double quotes, trailing commas, 100 print width). - Icons —
lucide-react. - Charts —
recharts. - API layer —
src/lib/api.tshandles all fetch calls, auto-refresh on 401,credentials: "include". Never use rawfetch. Session expiry handler viasetOnUnauthorized. - Auth —
AuthContextprovides{ user, loading, login, logout, updateProfile, refreshUser }. - TypeScript —
verbatimModuleSyntax(useimport type),erasableSyntaxOnly(no enums, no namespaces),noUnusedLocals/noUnusedParameters. - Routing —
react-router-domv7. Pages are lazy-loaded. Public route at/login, all other routes under/*wrapped inProtectedLayout. Admin-only route at/admin/usuarios. - Route paths are in Portuguese —
/perfil,/configuracoes,/transacoes,/despesas-fixas,/despesas-parceladas,/admin/usuarios. - Modals — use
Modalcomponent fromsrc/components/modal.tsx(usescreatePortal). Never inline overlay divs.
Utils
src/lib/currency.ts—fmt()(BRL string),parse()(BRL string → number),toInput()(number → BRL input string). Use instead ofIntl.NumberFormat.
What's already built
All screens exist in client/src/pages/: login, home (dashboard), profile, settings, transactions, recurring-expenses, installment-expenses, admin-users. Do not create new top-level page files unless adding a new feature.
No tests
No test framework or test files exist in either api/ or client/.