PocketBase Extending

SkillDev tools

Extend PocketBase with custom hooks and routes in JS or Go. Use when user wants to add custom API routes, modify PocketBase behavior, or add server-side logic.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the PocketBase Extending skill

What this skill tells your AI

The instructions your AI receives, as published by spinspire/pocketbase-sveltekit-starter in .agents/skills/pb-extend/SKILL.md and read by ahel’s review.

Reference: https://pocketbase.io/docs/js-overview/ | https://pocketbase.io/docs/go-overview/

Extend PocketBase with custom hooks and routes in JS or Go.

JS Hooks (pb_hooks/)

Drop *.pb.js files in pb_hooks/:

// pb_hooks/myhook.pb.js
/// <reference path="../pb_data/types.d.ts" />

router.api.post('/custom-route', async (e) => {
  const body = e.request.body
  // ... process
  return e.json({ result: 'ok' })
})

// On record create
onRecordCreateRequest((e) => {
  if (!e.record.get('email').endsWith('@company.com')) {
    return e.badRequest('Use company email')
  }
  return e.next()
})

Rules:

  • Always call e.next() / e.Next() in hooks
  • Variables outside handlers are undefined at runtime
  • Use require() for shared config (CJS only, no ESM)

Go Hooks (migrations/)

Versioned migrations in migrations/:

package migrations

import (
  "github.com/pocketbase/pocketbase/migrations"
  "github.com/pocketbase/pocketbase/tools/types"
)

func init() {
  migrations.Register(func(app *pocketbase.App) error {
    // Custom logic
    return nil
  }, func(app *pocketbase.App) error {
    // Rollback logic
    return nil
  })
}

Custom Routes

// Add to pb_hooks
router.api.post('/api/myapp/send-email', async (e) => {
  const data = await e.request.json()
  await sendEmail(data.to, data.subject)
  return e.json({ sent: true })
}, middleware.RequireAuth())

Key Hook Events

EventPurpose
onRecordCreateRequestBefore record creation
onRecordUpdateRequestBefore record update
onRecordDeleteRequestBefore record deletion
OnRecordEnrichShape response (incl. realtime)
OnRecordRequestHTTP-only response shaping
OnBeforeServeModify router before serving

Migrations

System fields: Collections created via migration files must include created and updated system fields.

Auto-migrate: Collections changed via Admin UI auto-generate migrations in pb_migrations/

Manual JS migration:

// pb_migrations/1700000000_seed_data.js
migrate((up, down) => {
  up((db) => {
    db.createCollection('categories', { /* ... */ })
  })
  down((db) => {
    db.dropCollection('categories')
  })
})

Useful Settings

// Read at runtime
const settings = require('../pb_settings/config.js')

// Access app in hooks
router.use(async (e) => {
  const app = e.app
  // ...
})

Signals

GitHub stars
507
Forks
76
Last commit
Aug 2026
Advanced
Catalog kind
skill
Gateway key
pb-extend
Source
github.com/spinspire/pocketbase-sveltekit-starter