5.4 KiB
5.4 KiB
Copilot Instructions — Fiddy (External DB)
Source of truth
- Always consult PROJECT_INSTRUCTIONS.md at the repo root.
- If any guidance conflicts, PROJECT_INSTRUCTIONS.md takes precedence.
- Keep this file focused on architecture/stack; keep checklists and project workflow rules in PROJECT_INSTRUCTIONS.md.
- When asked to fix bugs, follow DEBUGGING_INSTRUCTIONS.md at the repo root.
Stack
- Monorepo (npm workspaces)
- Next.js (App Router) + TypeScript + Tailwind
- External Postgres (on-prem server) via node-postgres (pg). No ORM.
- Docker Compose dev/prod
- Gitea + act-runner CI/CD
Environment
- Dev and Prod must use the same schema/migrations (
packages/db/migrations). DATABASE_URLpoints to the external DB server (NOT a container).
Auth
- Custom email/password auth.
- Use HttpOnly session cookies backed by DB table
sessions. - NEVER trust client-side RBAC checks.
Receipts
- Store receipt images in Postgres
byteatablereceipts. - Entries list endpoints must not return image bytes.
- Image bytes only fetched by separate endpoint when inspecting a single item.
UI
- Dark mode, minimal, mobile-first.
- Dodger Blue accent (#1E90FF).
- Top navbar: left nav dropdown, middle group selector, right user menu.
Code Rules
- Small files, minimal comments.
- Prefer single-line
ifwithout braces when only one line follows. - Heavy logic lives in components/hooks/services, not page files.
- Prefer API calls via exported hooks/services for reusability and cleanliness (avoid raw fetch in components when possible).
- Add/update unit tests with changes (TDD).
- Heavy focus on code readability and maintainability; prioritize clean code over clever code.
- ie. Separating different concerns into different files, and adding helper functions to avoid nested logic and improve readability, is preferred over clever one-liners or consolidating logic into fewer files.
- ie. Separate groups of related codes by adding 3 line breaks between them
Data Model
- Users (system_role USER|SYS_ADMIN)
- Groups + membership (group_role MEMBER|GROUP_ADMIN)
- Entries (group-scoped) + optional receipt_id
- User settings (jsonb)
- Reports for system admins
Architecture Contract (Backend ↔ Client ↔ Hooks ↔ UI)
No-Assumptions Rule (Required)
- Before making structural changes, first scan the repo and identify:
- the web app root (where
app/,components/,hooks/,lib/live) - existing API routes and helpers
- existing patterns already in use
- the web app root (where
- Do not invent files, endpoints, or conventions. If something is missing, add it minimally and consistently.
Layering (Hard Boundaries)
For every domain (auth, groups, entries, receipts, etc.), keep a consistent 4-layer flow:
- API Route Handlers (
app/api/.../route.ts)
- Thin: parse input, call a server service, return JSON.
- No direct DB queries inside route files unless there is no existing server service.
- Must enforce auth & membership checks on server.
- Server Services (DB + authorization) (
lib/server/*)
- Own all DB access and authorization helpers (sessions, requireGroupMember, etc.).
- Server-only modules must include
import "server-only"; - Prefer small domain modules:
lib/server/auth.ts,lib/server/groups.ts,lib/server/entries.ts,lib/server/session.ts.
- Client API Wrappers (
lib/client/*)
- Typed fetch helpers only (no React state).
- Centralize
fetchJson()/ error normalization. - Always send credentials (cookies) and never trust client-side RBAC.
- Hooks (UI-facing API layer) (
hooks/use-*.ts)
- Hooks are the primary interface for components/pages to call APIs.
- Components should not call
fetch()directly unless there’s a strong reason.
Domain Blueprint (Consistency Rule)
For any new feature/domain, prefer:
app/api/<domain>/...lib/server/<domain>.tslib/client/<domain>.tshooks/use-<domain>.tscomponents/<domain>/*__tests__/<domain>.test.ts
API Conventions
- Prefer consistent JSON response shape for errors:
{ error: { code: string, message: string } }
- Validate inputs at the route boundary (basic shape/type), and validate authorization in server services.
- When adding endpoints, mirror existing REST style used in the project.
Non-Regression Contracts (Do Not Break)
- Entries list endpoints must never include receipt image bytes; image bytes are fetched via a separate endpoint only.
- Auth is DB-backed HttpOnly sessions; all auth checks are server-side.
- Groups require server-side membership checks; active group persists per user.
- Group invite codes:
- shown once immediately after group creation
- modal renders outside navbar/header so it overlays the viewport correctly
- avoid re-exposing invite code elsewhere without explicit “group settings” work
UI Structure
- Page files stay thin; heavy logic stays in hooks/services/components.
- Dark mode, minimal, mobile-first.
- Dodger Blue accent (#1E90FF).
- Navbar: left nav dropdown, middle group selector, right user menu.
Environment
- Dev and Prod must use the same schema/migrations (
packages/db/migrations). DATABASE_URLpoints to external Postgres (NOT a container).DATABASE_URLformat must be a full connection string; URL-encode special chars in passwords.
Tests (Required)
- Add/update tests for API behavior changes:
- auth
- groups
- entries (group scoping)
- Tests must include negative cases: unauthorized, not-a-member, invalid inputs.