Running "npm run dev" as a tracked agent task gets the process killed when the runtime cap is reached, which leaves the machine with no dev server on port 6001. This script starts it with Start-Process so it survives session churn, and it refuses to start a second server when the port is already taken. The older .run-dev.ps1 in the same folder is broken and is replaced by this one: it invokes the Next binary without its extension, which PowerShell cannot execute, so node.exe is called explicitly instead. |
||
|---|---|---|
| .. | ||
| app | ||
| assets | ||
| components | ||
| docs/superpowers | ||
| lib | ||
| scripts | ||
| .cipc-service-launcher.cmd | ||
| .dockerignore | ||
| .env.example | ||
| .run-dev.ps1 | ||
| .start-cipc-service.ps1 | ||
| .start-dev-detached.ps1 | ||
| docker-compose.yml | ||
| Dockerfile | ||
| favicon.png | ||
| image-1.png | ||
| image-2.png | ||
| image.png | ||
| logo.png | ||
| middleware.ts | ||
| next-env.d.ts | ||
| next.config.mjs | ||
| package-lock.json | ||
| package.json | ||
| postcss.config.mjs | ||
| README.md | ||
| Sample_ChangeInShareholders_Letter.docx | ||
| Sample_ChangeInShareholders_Letter.pdf | ||
| tailwind.config.ts | ||
| tsconfig.json | ||
Workflow PocketBase Frontend
A read-only Next.js frontend that browses two PocketBase collections:
ysterbaard_directorsysterbaard_companies
The PocketBase instance is private. The superuser JWT is held server-side only — a Next.js route handler proxies every collection request, attaches the bearer token, and forwards to PB. The browser bundle never sees PB_TOKEN.
Routes
| Path | Surface |
|---|---|
/ |
Dashboard — total counts, status rollup, legend |
/directors |
Sortable, searchable list (table on desktop, cards on mobile) |
/directors/[id] |
Director profile + linked companies |
/companies |
Sortable, searchable, status-filtered list |
/companies/[id] |
Company detail + linked director card |
Stack
- Next.js 14 (App Router) + React 18 + TypeScript
- Tailwind CSS for styling (Airbnb light theme — white canvas, Rausch coral accent)
- pocketbase JS SDK on the server only
- TanStack Query v5 for client-side pagination + search
- Inter as the webfont, via
next/font/google
Setup
1. Install
npm install
2. Pull the superuser JWT from the admin UI
PocketBase v0.39 admin auth (/api/admins/auth-with-password) is unreachable from the public REST API — the only working admin auth lives behind /_/. Pull the JWT from the UI's localStorage:
-
Open
https://pb.agent.apphub.co.za/_/and sign in with:- Username:
ysterbaard@apphub.co.za - Password:
123456789
- Username:
-
Open DevTools, go to the Console, and run:
localStorage .getItem('__pb_superusers__/_') .match(/"token":"([^"]+)"/)[1] -
Copy the JWT string (no quotes).
3. Fill in .env.local
cp .env.local.example .env.local
Edit .env.local so that:
PB_URL=https://pb.agent.apphub.co.za
PB_TOKEN=<paste the JWT here>
4. Run the dev server
npm run dev
Open http://localhost:3000.
Acceptance criteria
- All 5 routes render with real data from PocketBase
- No superuser token leaks to the browser bundle (proxy holds it in
process.env) /directorsand/companiespaginate, search, and link to detail pages- Detail pages show the relation (
director↔ companies) correctly viaexpand=director - Lighthouse mobile score ≥ 90 (verify after deploy)
- Local dev runs without errors
Out of scope
- Authentication UI for end users
- Write/edit forms (this is read-only)
- Charts / analytics dashboards (just stat cards)
- Admin panel re-skin
Architecture notes
Server / client split
- Server Components fetch the initial page directly through
lib/pb.tsso the first paint always shows real data. No client spinner on cold load. - Client Components (the two Explorers) take that first page as
initialDataand re-fetch through/api/pb/records/listfor pagination, search, and filter changes. - API route handlers sit in
app/api/pb/records/[list|...id]/route.ts. They are the only placePB_TOKENis referenced.
Filter syntax
PocketBase filter expressions used by the explorers:
- Case-insensitive search:
field :~ 'value' - Equality:
field = 'value' - Boolean:
is_active = true - Range match:
enterprise_status :~ 'deregist'
The build*Filter helpers in app/directors/DirectorExplorer.tsx and app/companies/CompanyExplorer.tsx are the canonical place to read / change the filter behaviour.
Browser safety
lib/pb.tsimports"server-only"so any accidental import from a"use client"module trips a build-time error.- Tailwind utility classes reference CSS variables (
bg-surface,text-fg,border-border— wired intailwind.config.ts). No raw hex outsideglobals.css.
Project structure
.
├── app/
│ ├── api/pb/records/
│ │ ├── list/route.ts # GET paginated list
│ │ └── [id]/route.ts # GET single record
│ ├── companies/
│ │ ├── [id]/page.tsx
│ │ ├── CompanyExplorer.tsx
│ │ └── page.tsx
│ ├── directors/
│ │ ├── [id]/page.tsx
│ │ ├── DirectorExplorer.tsx
│ │ └── page.tsx
│ ├── error.tsx
│ ├── layout.tsx
│ ├── not-found.tsx
│ ├── globals.css
│ └── page.tsx
├── components/
│ ├── NavBar.tsx
│ ├── PageHeader.tsx
│ ├── QueryProvider.tsx
│ ├── Skeleton.tsx
│ ├── StatCard.tsx
│ └── StatusBadge.tsx
├── lib/
│ ├── api.ts # Browser-safe client (calls /api/pb/...)
│ ├── format.ts # Defensive formatters
│ ├── pb.ts # Server-only PB client
│ └── types.ts # Director + Company + PBList types
├── .env.local.example
├── .gitignore
├── next.config.mjs
├── package.json
├── postcss.config.mjs
├── tailwind.config.ts
└── tsconfig.json
Deploy
Local dev only for this iteration. To wire up Vercel later:
- Add the project as a Vercel app pointing at this directory.
- Set the two env vars (
PB_URL,PB_TOKEN) in the Vercel project settings. - The 14.x Next.js App Router setup auto-builds with no extra config.