PocketBase — database, auth & files
Managed SQLite-backed backend
Use PocketBase when your app needs shared records, user accounts, uploads, or data that follows people across devices. Percher runs a separate database for your app and manages its backups. You define the collections, access rules, and app integration.
A static site or browser-only tool may not need a database. Already using another provider? Keep your external database. Enabling PocketBase does not automatically move existing data or replace localStorage.
Set up PocketBase
Ask your assistant
From the app's project, ask your connected assistant:
Add Percher PocketBase to this app. Create the collections and per-user access rules it needs, connect the app through the PocketBase SDK, publish, and verify that one user cannot read another user's private data.
Review its proposed fields and rules before publishing. The checks below also apply to an AI-built app.
Start a new app with a template
bunx percher create my-app --template capsule cd my-app bunx percher publish
The Capsule template includes sign-in, a database client, and a schema applied during publish. Use a new directory; this does not add a database to an existing app.
Add it to an existing app
In your project's percher.toml, add or update the data section. Keep the existing app name and runtime:
[data] mode = "pocketbase"
bunx percher publish bunx percher data
Open the app's Data tab to find the database and admin link. To sign in, use its reset-password control or run this from the project directory:
bunx percher data reset-superuser --reveal
Use the returned email and password in the admin UI. The password is shown once; keep it private. Redeploy if your running server uses the rotated superuser password. Next, create the collections your app needs and connect its code.
Create collections and access rules
In the PocketBase admin UI, create a Base collection named tasks. Add title (Text), done (Bool), and user (a required single Relation to users). Auth collections hold user accounts; File fields hold uploads.
Rules for private tasks
Locked rules allow only superusers; empty rules allow anyone. For records that belong to one signed-in user, set these rules on tasks:
List, View, and Delete:
@request.auth.id != "" && user = @request.auth.id
Create:
@request.auth.id != "" && @request.body.user = @request.auth.id
Update:
@request.auth.id != "" && user = @request.auth.id && @request.body.user:changed = false
Set user to the signed-in user's ID when creating each task. These rules prevent another user reading it or taking ownership. See the PocketBase rule reference.
Keep the schema in your project
Use pb/schema.json as described in the Capsule guideto apply supported additive collection and field changes during publish. This makes setup repeatable. Breaking changes are rejected; simply changing data.modedoes not create collections or rules.
Using PocketBase from your app
Install the SDK with your project's package manager:
npm install pocketbase
Connect with the SDK
Three env vars are injected automatically:
POCKETBASE_URLInternal Docker URL (server-side calls)POCKETBASE_PUBLIC_URLPublic URL with SSLVITE_POCKETBASE_URLPublic URL (Vite convention)// Server-side import PocketBase from 'pocketbase'; const pb = new PocketBase(process.env.POCKETBASE_URL);
// Browser (Vite) import PocketBase from 'pocketbase'; const pb = new PocketBase(import.meta.env.VITE_POCKETBASE_URL);
For server-side user sessions, create a separate SDK client for each request so users do not share mutable authentication state. Never expose POCKETBASE_ADMIN_PASSWORD to the browser. Custom Dockerfiles need an ARG VITE_POCKETBASE_URL for the frontend build.
Next.js: a NEXT_PUBLIC_* variant isn't injected — only the three vars above are. To reach PocketBase from browser code in Next.js, set one yourself with the same value as POCKETBASE_PUBLIC_URL (bunx percher env set NEXT_PUBLIC_POCKETBASE_URL=https://pb-yourapp.percher.run) before publishing. Public-prefixed variables are forwarded to the build — see the environment variables guide. Server-side Next.js code can use process.env.POCKETBASE_URL as-is.
Create, read, update & delete records
// Create a record
const task = await pb.collection('tasks').create({
title: 'Buy groceries',
done: false,
user: pb.authStore.record?.id,
});
// List with filters
const tasks = await pb.collection('tasks').getList(1, 20, {
filter: 'done = false',
sort: '-created',
});
// Update
await pb.collection('tasks').update(task.id, { done: true });
// Delete
await pb.collection('tasks').delete(task.id);Sign users up and log them in
// Sign up
await pb.collection('users').create({
email: 'user@example.com',
password: 'securepassword',
passwordConfirm: 'securepassword',
});
// Log in
const auth = await pb.collection('users').authWithPassword(
'user@example.com',
'securepassword',
);
// auth.token is now set in pb.authStore
// Check auth state
if (pb.authStore.isValid) {
console.log('Logged in as', pb.authStore.record?.email);
}Upload files and get their URLs
// Upload a file
const formData = new FormData();
formData.append('title', 'My photo');
formData.append('image', fileInput.files[0]);
const record = await pb.collection('posts').create(formData);
// Get file URL
const url = pb.files.getURL(record, record.image);Subscribe to live changes (realtime)
// Subscribe to changes
pb.collection('messages').subscribe('*', (e) => {
console.log(e.action, e.record);
// action: 'create' | 'update' | 'delete'
});
// Unsubscribe
pb.collection('messages').unsubscribe();Verify the deployed app
- Sign up and sign in through your app, then create and read a record.
- Sign out and test with a second user. Neither should see the first user's private records.
- Reload and publish again. Confirm the record remains.
- If the app sends verification or reset emails, configure SMTP below and test delivery.
See backup and restore for recovery, and export data for a downloadable copy.
Managing your PocketBase
Open the admin UI (collections, rules, data)
Your PocketBase admin panel is available at pb-yourapp.percher.run/_/. Use it to create collections, set API rules, and manage data. The superuser password is generated at first deploy and stored encrypted — it is never shown, and percher env list shows it masked. Run bunx percher data reset-superuser <app> --reveal to mint one you can sign in with.
Get or rotate the superuser password
bunx percher data reset-superuser <app> generates a new password, re-injects it asPOCKETBASE_ADMIN_PASSWORD (encrypted at rest), and updates the deployment's stored credential so percher data keeps working. Default output confirms the rotation but doesn't print the plaintext — pass --reveal to also see the password once if you need to log into the admin UI directly. Redeploy to pick up the new credential in the running container.
Don't use PocketBase's built-in "forgot password" flow for superuser recovery — it depends on SMTP (see below), and the platform doesn't configure SMTP by default. reset-superuser is the supported recovery path.
Email (SMTP) — bring your own
Percher does not provide SMTP for your PocketBase sidecar. Every PB feature that sends mail (end-user signup verification, end-user password reset, OAuth notifications) is a silent no-op until you wire up your own provider — the password-reset endpoint even returns HTTP 204 while no email actually leaves the box.
Configure an SMTP provider
Sender reputation, deliverability, and cost are app-specific, so email delivery is your responsibility, not the platform's — sidecars ship without any SMTP relay configured.
Configure it in the PB admin UI: Settings → Mail settings. Pick any provider you already use — Resend, Postmark, Amazon SES, Mailgun, SendGrid, or your own SMTP server — paste the credentials, then verify with Send test email on that same page before you trust user-facing flows.
Heads-up: until SMTP is configured, PocketBase's password-reset endpoint still returns HTTP 204 on the wire even though no email actually leaves the box — that's the PocketBase API contract, not a Percher quirk.