From 95346c5c82a5b74f3b66f603f867cd87cbaa3e35 Mon Sep 17 00:00:00 2001 From: Dave Date: Wed, 16 Sep 2026 10:32:26 +0200 Subject: [PATCH] docs: Coolify-only setup, and mark pb_migrations as non-executing There is one PocketBase instance and it is hosted. Removes the `npm run pb` script, which started a local server nothing used. The schema had two apparent sources of truth. scripts/setup-remote.ts is the one that actually runs; pb_migrations/ only executes on PocketBase server start, which never happens here. Both now say so, so nobody edits a migration and believes the schema changed. Co-Authored-By: Claude Opus 5 --- README.md | 97 ++++++++++++++++++++++++++++++ package.json | 1 - pocketbase/pb_migrations/README.md | 18 ++++++ 3 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 README.md create mode 100644 pocketbase/pb_migrations/README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..209e849 --- /dev/null +++ b/README.md @@ -0,0 +1,97 @@ +# 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. | +| `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 +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. + +## Specs and plans + +- `docs/superpowers/specs/` — design documents +- `docs/superpowers/plans/` — implementation plans diff --git a/package.json b/package.json index da316d7..8a0c7db 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,6 @@ "dev": "next dev", "build": "next build", "start": "next start", - "pb": "cd pocketbase && ./pocketbase serve --http=127.0.0.1:8090", "test": "vitest run --project unit", "test:integration": "vitest run --project integration", "test:all": "vitest run", diff --git a/pocketbase/pb_migrations/README.md b/pocketbase/pb_migrations/README.md new file mode 100644 index 0000000..e0bac25 --- /dev/null +++ b/pocketbase/pb_migrations/README.md @@ -0,0 +1,18 @@ +# These migrations never run + +PocketBase applies files in `pb_migrations/` when **its own server starts**. +This project does not start a PocketBase server — it uses one hosted instance +on Coolify, and the schema is applied to it over the admin API by +`scripts/setup-remote.ts`. + +So every file in this directory is **reference only**. Editing one changes +nothing, anywhere. + +**To change the schema, edit `scripts/setup-remote.ts` and run +`npm run setup-remote`.** + +These files are kept because they are the most readable statement of the +schema and its reasoning, and because they are what you would mount into the +container if this project ever moves to PocketBase's native migration flow. If +you update `setup-remote.ts`, update these too — but understand that doing so +is documentation, not deployment.