Adds complete initial codebase for the RJ Bulk Supplies fuel delivery backoffice: - Authentication pages and protected route layouts - Customer, supplier, fuel purchase, and delivery note management - Custom reporting and customer statement sending tools - Full UI component library and Tailwind styling - Server actions, API routes, and PocketBase integration - Development scripts and project configuration updates - Updated README and package metadata
4.3 KiB
4.3 KiB
This is NOT the Next.js you know
This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in node_modules/next/dist/docs/ before writing any code. Heed deprecation notices.
Project: RJ Bulk Supplies — back-office app
What this is
Rebuild of a Flask back-office for a SA fuel-delivery business. Customers, delivery notes, suppliers, fuel purchases, pricing rules, monthly statements (PDF + email), 7 custom report types, admin settings.
Stack
- Next.js 16.2 (App Router, RSC, Server Actions, Turbopack)
- React 19.2, TypeScript 5.9 (strict)
- Tailwind CSS 4 with orange theme tokens (see
app/globals.css) - PocketBase 0.27 SDK + plain fetch for RSC (see
lib/pocketbase.ts) - TanStack Query / Table installed but we mostly use RSC for data
- Radix UI primitives wrapped as shadcn/ui-style components
- pdf-lib for PDFs in Node (statements + 7 report types)
- Resend for transactional email
- date-fns, lucide-react, zod (Zod 4 —
error.issues, noterror.errors)
Dev server
- Port 4004 (user has other apps on 3000)
pnpm dev— boots on http://localhost:4004pnpm pb:setup— runsscripts/setup-pb.mjsto provision the PB schema
PocketBase instance (SHARED, ANCIENT VERSION)
- URL:
http://pocketbase-zinlbpsext2ro0lgb2558vfy.169.239.180.130.sslip.io/ - Admin superuser:
David.els1@outlook.com/1234567890 - API path:
/_superusers/auth-with-password(not/admins) - ⚠️ This is a very old PocketBase version — be aware of these quirks:
- ❌ No first-class
relationfield —collectionIdis silently ignored or 400s - ❌ No
selectfield type —valuesvalidation rejects arrays - ❌ No auto-generated
createdfield on base collections — sorting by-created400s - ✅ Use
textfields for foreign keys, join via Map lookup in RSC - ✅ Use
textfields for enums, validate values with Zod at app layer - ✅ Sort by
-idor-date(any field that's actually on the collection) - ✅
expand=only works on real relation fields — don't use it, look up FKs in code - ✅ Records need an explicit 15-char lowercase id; autogenerate doesn't fire on POST
- ✅ API superuser auth is at
/api/collections/_superusers/auth-with-password(PB v0.18-style)
- ❌ No first-class
- The setup script (
scripts/setup-pb.mjs) is idempotent and handles the quirks
App user (for login)
- Email:
david@rjbulk.local/ Pass:ChangeMe123! - Created automatically by
pnpm pb:setup
RSC + PB gotchas
- Never import the PocketBase SDK in RSC code — its auto-cancelling fetch
crashes under Next.js' request cancellation. Use
lib/pocketbase.tshelpers (pbList,pbGet,pbCreate,pbUpdate,pbDelete) which use plainfetchwithcache: "no-store". - Server Actions cannot be imported into API route handlers — extract shared
logic to
lib/*.ts(seelib/delivery-notes.tsfor the pattern).
Key files
lib/pocketbase.ts— server-side PB fetch helperslib/auth.ts— cookie-based auth (PB token in httpOnly cookie, verified viaauth-refresh)lib/types.ts— TS types matching the PB schemalib/delivery-notes.ts— shared business logic (auto-fill price, get next number)lib/pdf/shared.ts+lib/pdf/customer-statement.ts+lib/pdf/reports.ts— PDF generationactions/*.ts— Server Actions (one file per resource)app/(authenticated)/*— authed pages with sidebar shellapp/api/*— Route handlers for PDF preview, next-number, pricing lookupscripts/setup-pb.mjs— One-shot PB schema setup (re-run anytime)
Conventions
- Foreign keys: text field named after the related collection (singular), e.g.
customer,supplier - Enums: text field with app-layer validation, constants in
lib/types.ts - IDs:
pbId()(15 lowercase chars) inlib/pb.ts - Cleaning empty form values:
cleanEmpty()inlib/delivery-notes.ts
Email (Resend)
- Set
RESEND_API_KEYandRESEND_FROMin.env.localto send statements - Without it, statement send fails with a clear error; preview still works
Build
pnpm buildcompiles cleanly- All 22 routes are dynamic (RSC) except
/_not-found