pocketbase-best-practices

PocketBase development best practices covering collection design, API rules, authentication, SDK usage, query optimization, realtime subscriptions, file handling, deployment, and server-side extending (Go + JSVM). Current as of PocketBase v0.40 and JS SDK v0.28. Use when building PocketBase backends

By greendesertsnow · 714 installs

npx skills add greendesertsnow/pocketbase-skills --skill pocketbase-best-practices

Source repository · Upstream listing

PocketBase Best Practices PocketBase is a single binary backend (SQLite + REST + realtime + auth) that is easy to start with and easy to misuse at scale. This skill gives AI agents the guardrails: 64 rules across 9 categories , each with an incorrect vs. correct code example, covering the mistakes agents actually make — insecure API rules, unindexed queries, broken auth flows, N+1 expands, leaked server side handles. Updated for PocketBase v0.40 and JS SDK v0.28 (August 2026). Works with v0.36+. How rules are prioritized Every rule carries an impact level: Critical = security holes or broken data models, High = performance and correctness problems, Medium/Low = operational polish. When rules conflict, higher impact wins. What's covered Category Impact What it protects you from Collection Design Critical Wrong field types, missing indexes, manual ID strings instead of relations API Rules & Security Critical Data leaks from empty/incorrect access rules, filter injection Authentication Critical Broken password/OAuth2/OTP/MFA flows, token mishandling SDK Usage High Bad client setup, swallowed errors, cancelled request bugs Query Performance High N+1 queries, over fetching, missing pagination Realtime Medium Dropped subscriptions, unauthenticated realtime access File Handling Medium Unvalidated uploads, wrong file URLs, missing thumbnails Production & Deployment Medium No backups, no rate limits, exposed superuser access Server Side Extending High Go/JSVM hook mistakes, transaction misuse, unsafe filter binding Quick Reference Collection Design (CRITICAL) coll field types : Use appropriate field types (json for objects, select for enums) coll auth vs base : Extend auth collection for users, base for non auth data coll relations : Use relation fields, not manual ID strings coll indexes : Create indexes on frequently filtered/sorted fields coll view collections : Use views for complex aggregations coll geopoint : Store coordinates as json field with lat/lng API Rules (CRITICAL) rules basics : Always set API rules; empty = public access rules filter syntax : Use @request.auth, @collection, @now in rules rules request context : Access request data via @request.body, @request.query; @request.context values: default / oauth2 / otp / password / realtime / protectedFile rules cross collection : Use @collection.name.field for cross collection checks rules locked vs open : Start locked, open selectively rules strftime : Use strftime('%Y %m %d', created) for date arithmetic (v0.36+) Authentication (CRITICAL) auth password : Use authWithPassword for email/password login auth oauth2 : Configure OAuth2 providers via Admin UI; run ≥v0.38.2 (pre linking hijack fix); provider logos come inline from listAuthMethods() (v0.37+) auth otp : Two step requestOTP → authWithOTP ; rate limit requestOTP and never leak email existence auth token management : Store tokens securely, refresh before expiry auth mfa : Enable MFA for sensitive applications auth impersonation : Use impersonation for admin actions on behalf of users SDK Usage (HIGH) sdk initialization : Initialize client once, reuse instance sdk auth store : Use AsyncAuthStore for React Native/SSR sdk error handling : Catch ClientResponseError, check status codes sdk auto cancellation : Disable auto cancel for concurrent requests sdk filter binding : Use filter binding to prevent injection Query Performance (HIGH) query expand : Expand relations to avoid N+1 queries query field selection : Select only needed fields query pagination : Use cursor pagination for large datasets query batch operations : Batch creates/updates when possible Realtime (MEDIUM) realtime subscribe : Subscribe to specific records or collections realtime events : Handle create, update, delete events separately realtime auth : Realtime respects API rules automatically; auth unsets on password change; ~30min absolute connection cap (v0.38+) realtime reconnection : Implement reconnection logic — periodic reconnects are by design, re sync state instead of fighting them File Handling (MEDIUM) file upload : Use FormData for uploads, set proper content types file serving : Use pb.files.getURL() for file URLs file validation : Validate file types and sizes server side Deployment (MEDIUM) deploy backup : Schedule regular backups of pb data deploy configuration : Use environment variables for config; mind v0.40 log caps ( Log.Data ~16KB) and treat the SQL console (v0.39+) as debug only deploy reverse proxy : Put behind nginx/caddy in production deploy sqlite considerations : Optimize SQLite for production workloads deploy rate limiting : Enable the built in rate limiter (fixed window as of v0.36.7); front with Nginx/Caddy for defense in depth deploy scaling : Raise ulimit n for realtime, set GOMEMLIMIT , enable settings encryption deploy superuser ips : Whitelist superuser access by IP/CIDR in production (v0.38+); recovery via the superuser ips console command Server Side Extending (HIGH) ext go setup : Use app.OnServe() to register routes; use e.App inside hooks, not the parent scope app; v0.40 needs Go 1.27 ( encoding/json/v2 — test before shipping) ext js setup : Drop .pb.js in pb hooks/ ; add /// <reference path="../pb data/types.d.ts" / ext hooks chain : Always call e.Next() / e.next() ; use Bind with an Id for later Unbind ext hooks record vs request : Use OnRecordEnrich to shape responses (incl. realtime); OnRecordRequest for HTTP only ext routing custom : Namespace routes under /api/{yourapp}/ ; attach RequireAuth() middleware ext transactions : Use the scoped txApp inside RunInTransaction ; never capture the outer app ext filter binding server : Bind user input with {:name} + dbx.Params in FindFirstRecordByFilter / FindRecordsByFilter ext filesystem : defer fs.Close() on every NewFilesystem() / NewBackupsFilesystem() handle ext cron jobs : Register with app.Cron().MustAdd(id, expr, fn) / cronAdd() ; stable ids, no pb prefix ext go migrations : Versioned .go files under migrations/ ; Automigrate: osutils.IsProbablyGoRun() ext js migrations : pb migrations/<unix .js with migrate(upFn, downFn) ; auto discovered by filename ext mailer : Resolve sender from app.Settings().Meta at send time; never ship no reply@example.com ; create the mail client per send ext settings : Read via app.Settings() at call time; set PB ENCRYPTION (32 chars) to encrypt params at rest ext testing : tests.NewTestApp(testDataDir) + tests.ApiScenario ; defer app.Cleanup() , assert ExpectedEvents ext compose request flow : Composite walkthrough showing which app instance is active at each layer (route → tx → hook → enrich) ext go custom sqlite : Only use DBConnect when you need FTS5/ICU; DBConnect is called twice (data.db + auxiliary.db) ext jsvm scope : Variables outside handlers are undefined at runtime — load shared config via require() inside the handler ext jsvm modules : Only CJS ( require() ) works in goja; bundle ESM first; avoid mutable module state Example Prompts Try these with your AI agent to see the skill in action: Building a new feature: "Design a PocketBase schema for an e commerce app with products, orders, and reviews" "Implement OAuth2 login with Google and GitHub for my app" "Build a real time notification system with PocketBase subscriptions" "Create a file upload form with image validation and thumbnail previews" Fixing issues: "My list query is slow on 100k records optimize it" "I'm getting 403 errors on my batch operations" "Fix the N+1 query problem in my posts list that loads author data in a loop" "My realtime subscriptions stop working after a few minutes" Security review: "Review my API rules users should only access their own data" "Set up proper access control: admins manage all content, users edit only their own" "Are my authentication cookies configured securely for SSR?" "Audit my collection rules for IDOR vulnerabilities" Going to production: "Configure Nginx with HTTPS, rate limiting, and security headers for PocketBase" "Set up automated backups for my PocketBase database" "Optimize SQLite settings for a production workload with ~500 concurrent users" "Deploy PocketBase with Docker Compose and Caddy" Extending PocketBase: "Add a custom Go route that sends a Slack notification after a record is created" "Write a pb hooks script that validates an email domain before user signup" "Set up FTS5 full text search with a custom SQLite driver in my Go app" "Share a config object across multiple pb hooks files without race conditions" Detailed Rules Load the relevant category for complete rule documentation with code examples: [Collection Design](references/collection design.md) Schema patterns, field types, relations, indexes [API Rules & Security](references/api rules security.md) Access control, filter expressions, security patterns [Authentication](references/authentication.md) Password auth, OAuth2, MFA, token management [SDK Usage](references/sdk usage.md) Client initialization, auth stores, error handling, hooks [Query Performance](references/query performance.md) Pagination, expansion, batch operations, N+1 prevention [Realtime](references/realtime.md) SSE subscriptions, event handling, reconnection [File Handling](references/file handling.md) Uploads, serving, validation [Production & Deployment](references/production deployment.md) Backup, configuration, reverse proxy, SQLite optimization [Server Side Extending](references/server side extending.md) Go/JSVM setup, event hooks, custom routes, modules, custom SQLite