Aller au contenu

PocketBase Cheat Sheet

Overview

PocketBase is an open-source backend that packages a SQLite database, realtime subscriptions, built-in authentication, file storage, and an admin dashboard into a single portable binary. It is written in Go and requires zero external dependencies, making it ideal for prototyping, small to medium applications, and self-hosted projects.

PocketBase provides a REST API automatically for all your collections (database tables), supports OAuth2 authentication with multiple providers, offers realtime events via Server-Sent Events, and includes an extensible Go and JavaScript SDK. The admin UI lets you manage collections, records, users, and settings through a browser-based interface.

Installation

# Download the latest release (Linux AMD64)
curl -Lo pocketbase.zip https://github.com/pocketbase/pocketbase/releases/latest/download/pocketbase_0.25.0_linux_amd64.zip
unzip pocketbase.zip
chmod +x pocketbase

# macOS (ARM64)
curl -Lo pocketbase.zip https://github.com/pocketbase/pocketbase/releases/latest/download/pocketbase_0.25.0_darwin_arm64.zip
unzip pocketbase.zip

# Start the server
./pocketbase serve

# Start on a specific address and port
./pocketbase serve --http="0.0.0.0:8090"

# Admin UI: http://127.0.0.1:8090/_/
# API:      http://127.0.0.1:8090/api/

Docker

FROM alpine:latest
ARG PB_VERSION=0.25.0
RUN apk add --no-cache unzip ca-certificates
ADD https://github.com/pocketbase/pocketbase/releases/download/v${PB_VERSION}/pocketbase_${PB_VERSION}_linux_amd64.zip /tmp/pb.zip
RUN unzip /tmp/pb.zip -d /pb/
EXPOSE 8090
CMD ["/pb/pocketbase", "serve", "--http=0.0.0.0:8090"]
docker build -t pocketbase .
docker run -p 8090:8090 -v $(pwd)/pb_data:/pb/pb_data pocketbase

Core API

Collections (CRUD)

MethodEndpointDescription
GET/api/collections/{collection}/recordsList records
GET/api/collections/{collection}/records/{id}Get one record
POST/api/collections/{collection}/recordsCreate a record
PATCH/api/collections/{collection}/records/{id}Update a record
DELETE/api/collections/{collection}/records/{id}Delete a record

Example API Calls

# List records with filtering
curl "http://127.0.0.1:8090/api/collections/posts/records?filter=(status='published')&sort=-created&perPage=20" \
  -H "Authorization: Bearer USER_TOKEN"

# Create a record
curl -X POST "http://127.0.0.1:8090/api/collections/posts/records" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer USER_TOKEN" \
  -d '{"title":"Hello","content":"World","status":"draft"}'

# Update a record
curl -X PATCH "http://127.0.0.1:8090/api/collections/posts/records/RECORD_ID" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer USER_TOKEN" \
  -d '{"status":"published"}'

# Delete a record
curl -X DELETE "http://127.0.0.1:8090/api/collections/posts/records/RECORD_ID" \
  -H "Authorization: Bearer USER_TOKEN"

# Upload a file
curl -X POST "http://127.0.0.1:8090/api/collections/posts/records" \
  -H "Authorization: Bearer USER_TOKEN" \
  -F "title=My Post" \
  -F "image=@photo.jpg"

Authentication

# Register a new user
curl -X POST "http://127.0.0.1:8090/api/collections/users/records" \
  -H "Content-Type: application/json" \
  -d '{"email":"user@example.com","password":"securepass123","passwordConfirm":"securepass123","name":"Alice"}'

# Authenticate (get token)
curl -X POST "http://127.0.0.1:8090/api/collections/users/auth-with-password" \
  -H "Content-Type: application/json" \
  -d '{"identity":"user@example.com","password":"securepass123"}'

# OAuth2 authentication
curl -X POST "http://127.0.0.1:8090/api/collections/users/auth-with-oauth2" \
  -H "Content-Type: application/json" \
  -d '{"provider":"google","code":"AUTH_CODE","redirectURL":"http://localhost:3000/auth/callback"}'

Filtering and Sorting

# Filter syntax
filter=(status='published' && created>'2025-01-01')
filter=(title~'hello' || tags?~'news')
filter=(author.name='Alice')

# Sort (prefix with - for descending)
sort=-created,title

# Field selection
fields=id,title,created

# Expand relations
expand=author,comments

JavaScript SDK

import PocketBase from "pocketbase"

const pb = new PocketBase("http://127.0.0.1:8090")

// Authenticate
const authData = await pb.collection("users").authWithPassword("user@example.com", "securepass123")

// List records
const posts = await pb.collection("posts").getList(1, 20, {
  filter: 'status = "published"',
  sort: "-created",
  expand: "author",
})

// Get one record
const post = await pb.collection("posts").getOne("RECORD_ID", {
  expand: "author,comments",
})

// Create a record
const newPost = await pb.collection("posts").create({
  title: "New Post",
  content: "Hello World",
  author: pb.authStore.record.id,
})

// Update a record
await pb.collection("posts").update("RECORD_ID", { status: "published" })

// Delete a record
await pb.collection("posts").delete("RECORD_ID")

// Realtime subscriptions
pb.collection("posts").subscribe("*", function (e) {
  console.log(e.action) // create, update, delete
  console.log(e.record)
})

// Unsubscribe
pb.collection("posts").unsubscribe()

Configuration

Collection Schema (via Admin UI or API)

{
  "name": "posts",
  "type": "base",
  "schema": [
    { "name": "title", "type": "text", "required": true, "options": { "min": 1, "max": 200 } },
    { "name": "content", "type": "editor", "required": false },
    { "name": "status", "type": "select", "options": { "values": ["draft", "published", "archived"] } },
    { "name": "image", "type": "file", "options": { "maxSelect": 1, "maxSize": 5242880, "mimeTypes": ["image/png", "image/jpeg"] } },
    { "name": "author", "type": "relation", "options": { "collectionId": "users", "maxSelect": 1 } },
    { "name": "tags", "type": "json" }
  ]
}

API Rules (Access Control)

# In Admin UI > Collection > API Rules

# List rule (who can list records)
@request.auth.id != "" && status = "published"

# View rule
@request.auth.id != "" || status = "published"

# Create rule
@request.auth.id != "" && @request.data.author = @request.auth.id

# Update rule
@request.auth.id = author.id

# Delete rule
@request.auth.id = author.id

Advanced Usage

Custom Go Backend

package main

import (
    "log"
    "github.com/pocketbase/pocketbase"
    "github.com/pocketbase/pocketbase/core"
)

func main() {
    app := pocketbase.New()

    app.OnRecordCreate("posts").BindFunc(func(e *core.RecordEvent) error {
        log.Println("New post created:", e.Record.GetString("title"))
        return e.Next()
    })

    app.OnServe().BindFunc(func(se *core.ServeEvent) error {
        se.Router.GET("/api/custom/hello", func(e *core.RequestEvent) error {
            return e.JSON(200, map[string]string{"message": "Hello!"})
        })
        return se.Next()
    })

    if err := app.Start(); err != nil {
        log.Fatal(err)
    }
}

Migrations

# Create a migration
./pocketbase migrate create "add_posts_collection"

# Run migrations
./pocketbase migrate up

# Rollback
./pocketbase migrate down

Backup and Restore

# Create a backup via API
curl -X POST "http://127.0.0.1:8090/api/backups" \
  -H "Authorization: Bearer ADMIN_TOKEN"

# List backups
curl "http://127.0.0.1:8090/api/backups" \
  -H "Authorization: Bearer ADMIN_TOKEN"

# Manual backup: just copy the pb_data directory
cp -r pb_data pb_data_backup_$(date +%Y%m%d)

Troubleshooting

IssueSolution
Admin UI not loadingEnsure you are accessing /_/ path; check firewall rules
Auth token expiredTokens expire after 14 days by default; re-authenticate
File upload failsCheck maxSize in schema; verify pb_data/storage has write permissions
Realtime not connectingEnsure client uses SSE-compatible connection; check CORS settings
Database lockedSQLite allows one writer at a time; use WAL mode (default) for better concurrency
Relations not expandingUse expand=relation_field query param; verify relation field name
CORS errorsConfigure allowed origins in Admin UI > Settings > Application
Slow queriesAdd indexes via Admin UI; reduce perPage size; filter on indexed fields