Adds the visible front-end and the worker back-end for the agent
task system. The PocketBase schema, API routes, and ToastProvider
were already in the previous commit; this commit completes the
picture.
UI
- app/tasks/{page,KanbanBoard,TaskCard,CardModal,TaskDetail,api,columns}
Full Kanban with six columns (Backlog, Ready, In Progress,
Blocked, Done, Failed), drag-and-drop between columns, quick-add
chips, type/priority filters, task detail panel with retry/cancel/
delete, 5s polling, transition toasts.
- components/NavBar.tsx: 'Tasks' link in primary nav.
- app/bizportal-2/BizPortal2Explorer.tsx: 'Send to Kanban' button
on the result view — dispatches the current search to the agent
queue as a 'ready' task.
Back-end
- scripts/task_worker.py: PocketBase polling worker with two
lanes. Deterministic handles bizportal_search/reserve, pdf_generate,
email_send. Custom lane writes to /tmp/agent_inbox/ for the
LLM agent to pick up. Atomic claim via PB filter, auto-retry up
to 3x, structured log on each task.
- scripts/bizportal_service.py: bugfix — _is_logged_in was using
a non-CSS selector so session-recovery was a no-op. Also made
the login flow re-runnable mid-session (handles BizPortal's
~20-minute session timeout transparently).
- scripts/init_pb_schema.py: duration_ms no longer capped at 0.
Verified end-to-end:
- CK search via worker: 1 company, 3 directors, ~10s
- ID search via worker: 4 companies, 7 total directors, ~34s
- Auto-retry + status transitions + toast fires
|
||
|---|---|---|
| .od-skills/creative-director-d03e82b79d | ||
| app | ||
| components | ||
| lib | ||
| scripts | ||
| .dockerignore | ||
| .env.example | ||
| .env.local.example | ||
| .gitignore | ||
| docker-compose.yml | ||
| Dockerfile | ||
| favicon.png | ||
| image-1.png | ||
| image-2.png | ||
| image.png | ||
| logo.png | ||
| next.config.mjs | ||
| package-lock.json | ||
| package.json | ||
| postcss.config.mjs | ||
| README.md | ||
| sqlite_mcp_server.db | ||
| tailwind.config.ts | ||
| tsconfig.json | ||
| tsconfig.tsbuildinfo | ||
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.