- Added `NEXT_PUBLIC_APP_URL` to `.env.example` for app URL configuration. - Updated `README.md` to document the new `NEXT_PUBLIC_APP_URL` variable. - Improved CSS to support light and dark color schemes. - Refactored intake link actions to utilize the new app URL and handle token generation more efficiently. - Enhanced public intake route to validate work area selection. - Updated `IntakeLinksPanel` to allow copying of generated links. - Improved error handling and user experience in `BriefPreviewPublic` and `IntakePublic` components. - Refined theme synchronization and toggle components for better user preference management.
140 lines
5.6 KiB
Markdown
140 lines
5.6 KiB
Markdown
# Client Board
|
|
|
|
Project tracking for client work. A developer runs their own board across
|
|
several client companies; each client's manager signs in, sees only their own
|
|
projects, and sets the priorities and target dates that matter to them.
|
|
|
|
Next.js 16 + PocketBase.
|
|
|
|
## There is no local PocketBase
|
|
|
|
This project uses **one** PocketBase instance, hosted on Coolify. There is no
|
|
local server to start and no local database to keep in sync. Point
|
|
`NEXT_PUBLIC_PB_URL` at the hosted instance and run the app against it.
|
|
|
|
That means every developer and every test run shares one database. See
|
|
"Tests touch real data" below before running the integration suite.
|
|
|
|
## Setup
|
|
|
|
```bash
|
|
npm install
|
|
cp .env.example .env.local
|
|
```
|
|
|
|
Fill in `.env.local`:
|
|
|
|
| Variable | Notes |
|
|
| --- | --- |
|
|
| `NEXT_PUBLIC_PB_URL` | The Coolify PocketBase URL. Public by design — the browser connects to it directly. |
|
|
| `NEXT_PUBLIC_APP_URL` | Public HTTPS address of the app, used if a link request has no Origin header. Set it to the deployed domain, for example `https://planner.apphub.co.za`. |
|
|
| `PB_SUPERUSER_EMAIL` | Server-side only. Never exposed to the browser. |
|
|
| `PB_SUPERUSER_PASSWORD` | Server-side only. Never commit this. |
|
|
|
|
`.env.local` is gitignored. **`.env.example` is not** — it is tracked, so
|
|
anything written there is published to every clone and stays in history. Put
|
|
placeholders in it, never real credentials.
|
|
|
|
## Running
|
|
|
|
```bash
|
|
npm run dev
|
|
```
|
|
|
|
## Applying the schema
|
|
|
|
```bash
|
|
set -a
|
|
source .env.local
|
|
set +a
|
|
npm run setup-remote
|
|
```
|
|
|
|
`scripts/setup-remote.ts` is the **single source of truth for the schema.** It
|
|
creates every collection and applies the API rules against the hosted instance
|
|
through the admin API. It is idempotent and non-destructive: re-running reuses
|
|
existing collections and never deletes anything.
|
|
|
|
`pocketbase/pb_migrations/` holds the same schema as PocketBase migration
|
|
files. **They are reference only and never execute** — migrations run on
|
|
server start, and this project does not start a PocketBase server. If you
|
|
change the schema, change `scripts/setup-remote.ts`. Editing a migration file
|
|
does nothing at all.
|
|
|
|
## Seeding demo data
|
|
|
|
```bash
|
|
npm run seed
|
|
```
|
|
|
|
Creates one client, one project with its default columns, an owner account, a
|
|
client-manager account, and a few cards.
|
|
|
|
## Tests
|
|
|
|
```bash
|
|
npm test # unit — pure logic, no network
|
|
npm run test:integration # requires npm run dev to be running
|
|
npm run test:all
|
|
```
|
|
|
|
**Tests touch real data.** The integration suite signs in against the hosted
|
|
PocketBase, creates and deletes a throwaway client and project, and changes
|
|
priorities on seeded cards. That is fine while the database holds demo data
|
|
only. Before a real client's board lives there, stand up a second PocketBase
|
|
instance for tests — otherwise a test run edits their project.
|
|
|
|
## Permissions, in one paragraph
|
|
|
|
PocketBase API rules are record-level and cannot express "this user may update
|
|
`priority` but not `column`". So client managers are denied **all** writes at
|
|
the database, and their edits go through `/api/client/*` route handlers that
|
|
authenticate as a superuser and copy across only whitelisted fields. The owner
|
|
writes through `/api/owner/*` using their own token, because the auth cookie is
|
|
httpOnly and the browser SDK therefore has no credentials. If you find yourself
|
|
relaxing a write rule to make a form work, that form should be posting to a
|
|
route handler instead.
|
|
|
|
## Collaborative planning
|
|
|
|
`/plan` reads live cards in Inbox, Backlog, To Do, and other working columns.
|
|
Review, Done, archived cards, and inactive projects are omitted. Undated cards
|
|
stay visible with a **Set dates** action. The week view is for precise ranges;
|
|
the year view shows the wider schedule.
|
|
|
|
Clients may edit draft ranges for their own projects and submit a project plan.
|
|
The owner may approve it or request changes, optionally pointing to a card.
|
|
An approved copy remains visible while another draft is prepared. Ranges live
|
|
in `projects.plan_data`, separate from `cards.start_date` (which also controls
|
|
commit linking). Client plan writes verify the signed-in account and project
|
|
ownership before updating the project through the admin connection.
|
|
|
|
Before using the new planner on the hosted instance, load `.env.local` as shown
|
|
above and run `npm run setup-plan-schema`. This targeted command only adds the
|
|
optional `projects.plan_data` JSON field; it does not run the full setup script
|
|
or rewrite existing records. Existing projects start with an empty draft, and
|
|
no existing card dates are overwritten.
|
|
|
|
## Work areas
|
|
|
|
Each project has its own named work areas. A card can link to one area while
|
|
keeping its independent Kanban column, priority, and plan dates. The board
|
|
shows an area-colored edge and label on linked cards; the area legend filters
|
|
the visible cards. The Plan page shows the same area labels alongside its
|
|
existing priority-colored schedule bars. Existing cards remain uncategorised
|
|
until assigned on their card page.
|
|
|
|
The quick-add and intake forms ask for an existing area or a new name. New
|
|
areas receive the next unused color from a fixed palette; the color is saved
|
|
on the area record. `work_areas` is related to `projects`, and client reads
|
|
follow the project's client access rule. Client writes are validated by the
|
|
app before using the admin connection.
|
|
|
|
Run `npm run setup-work-area-schema` with `.env.local` loaded to add only the
|
|
`work_areas` collection and optional `cards.work_area` relation. The same
|
|
schema addition is included in `npm run setup-remote` for new environments.
|
|
|
|
## Specs and plans
|
|
|
|
- `docs/superpowers/specs/` — design documents
|
|
- `docs/superpowers/plans/` — implementation plans
|