- library/components/WARNING.md, library/dashboards/README.md and documentation/contributing/README.md taught "graduate into the library at the second consumer". They now teach the plugin-designer skill's rule (section 3): a component that could serve more than one map is built once in library/, driven by props, and landed through the build owner; one-off or experimental pieces stay in a map's folder; a new pattern is a pilot, then approved, then rolled out. The contributing guide's "full reasoning" link pointed to an index without it; it now points to the skill. - The app shell doxa-maps-spa is labelled Deep Research. Ten docs still called it the Research Gallery (15 mentions): DEPLOY.md, the desktop how-to, embeddability, develop-a-plugin, reference-universal-props, reference.md, the shell's EMBED.md, and the plugin-designer skill with two of its references. Identifiers (doxa-maps-spa, branch and route names) are unchanged; README.md is not touched.
4.2 KiB
Backends, data, and users
Most plugins need no backend. A map that draws its own data files, fetches a public API, or reads
data/ inside its bundle is complete without one. Reach for this page only when your plugin needs
a service or stored data.
What exists today
backend/ holds exactly two things:
| Folder | What it is |
|---|---|
backend/pocketbase/ |
the database: migrations, and the local instance bun run dev starts |
backend/rudder-engine/ |
the local speech engine for the Rudder voice plugin |
A plugin that needs one names it in its <profile>.meta.json "backend" key, as
plugin-designs/rudder-voice/rudder-voice.meta.json does with "backend": "backend/rudder-engine".
A plugin that needs a local backend almost certainly also needs "targets" without web, which
keeps it out of Deep Research — see targets.md. Rudder declares both.
The database rule: schema is a commit, never a click
You never publish a database. What travels between people is the shape — tables and fields —
as migration files committed to backend/pocketbase/pb_migrations/. Adding a field is a normal
change: edit, commit the migration, push it like any other file.
This is deliberate. A rule that opens data to the public arrives as a commit someone can read
rather than as a setting somebody clicked. documentation/HOWTO-join-the-table.md is the full
explanation.
New collections start locked. Your plugin's data is not readable until a migration opens it, so nothing is public by accident.
Which database your laptop talks to
By default, your own. bun run dev starts a local instance, keeps its data in .pb/, and gives
you an admin screen at /api/pb/_/. A fresh clone plus bun run dev is the whole setup.
Pointing at the team's shared test data is opt-in, one line in .env.local:
DX_PB_URL=https://<your team's dev server>/pb
DX_PB_PORT is the only other one, and only if the log says port 8090 is in use. The full set of
environment names is in .env.example: VITE_MAPBOX_TOKEN, VITE_API_BASE_URL, DX_SYNC_REMOTE,
DX_SYNC_BRANCH, DX_SYNC_INTERVAL, DX_PB_URL, DX_PB_PORT. Every line is optional; empty means
the all-local default.
User tiers — DESIGN INTENT, NOT BUILT
Read this heading literally. What follows is a planned model recorded in the project's architecture notes as an open, unproven assumption. None of it is implemented in this repo. Do not design your plugin around it, do not write code that assumes a tier exists, and do not tell anyone a plugin "supports" these. It is here so you recognise the vocabulary when it comes up, and so you do not invent a competing scheme.
The intended tiers, which parallel the five plugin capabilities:
| Tier | Intended meaning |
|---|---|
| anonymous | reaches the plugin by URL, no sign-in |
| access-code | temporary access without an account |
| plugin user | authenticated against the database |
| base OIDC member | signed in through the platform's identity provider |
| plugin admin | administers one plugin |
| PB plugin owner | owns a plugin's data |
| PB plugin writer | writes a plugin's data, with no access to other plugins' data |
Quantum Forms is named as the reference plugin that would exercise every tier.
Source. This is recorded in ARCHITECTURE-EQUATION.md §6, which lives in the project's QA
cycle outside this code repository (_qa-cycle/03-deployment-cycle/). It is quoted here rather
than linked because a reader who clones this repo will not have that file. If you need the
authoritative text, ask whoever maintains the QA cycle — do not reconstruct it from this summary.
What to do in the meantime
If your plugin needs any notion of "who is this" today, use what is actually built: PocketBase auth plus a migration that opens exactly the collection you need, and nothing wider. Do not hand-roll a permission model to bridge the gap — the last tier above ("no access to other plugins' data") is the property a hand-rolled scheme tends to break, and breaking it crosses plugins.
Related
targets.md— thetargetsandbackendmeta keysworkflow.md— landing a migration on main like any other filedocumentation/HOWTO-join-the-table.md— the three databases, in full