Smithery Logo
MCPsSkillsDocsPricing
Login
Smithery Logo

Accelerating the Agent Economy

Resources

DocumentationPrivacy PolicySystem Status

Company

PricingAboutBlog

Connect

© 2026 Smithery. All rights reserved.

    knowsuchagency

    pocketbase-migrations

    knowsuchagency/pocketbase-migrations
    Coding
    3

    About

    SKILL.md

    Install

    Install via Skills CLI

    or add to your agent
    • Claude Code
      Claude Code
    • Codex
      Codex
    • OpenClaw
      OpenClaw
    • Cursor
      Cursor
    • Amp
      Amp
    • GitHub Copilot
      GitHub Copilot
    • Gemini CLI
      Gemini CLI
    • Kilo Code
      Kilo Code
    • Junie
      Junie
    • Replit
      Replit
    • Windsurf
      Windsurf
    • Cline
      Cline
    • Continue
      Continue
    • OpenCode
      OpenCode
    • OpenHands
      OpenHands
    • Roo Code
      Roo Code
    • Augment
      Augment
    • Goose
      Goose
    • Trae
      Trae
    • Zencoder
      Zencoder
    • Antigravity
      Antigravity
    ├─
    ├─
    └─

    About

    Comprehensive guide for PocketBase migrations (0.20+) using Go-based migration system...

    SKILL.md

    PocketBase Migrations

    Guide for creating PocketBase migrations using the Go-based system (0.20+).

    Core Workflow

    Critical Migration Pattern

    ALWAYS follow this workflow:

    1. Write ONE migration at a time
    2. Execute immediately with mise run migrate
    3. Verify it worked with mise run show-collections
    4. Only then write the next migration
    5. Run mise run backup before destructive changes

    Never write multiple migrations without running them between each one.

    Migration Structure

    package migrations
    
    import (
        "github.com/pocketbase/pocketbase/core"
        "github.com/pocketbase/pocketbase/tools/types"
        m "github.com/pocketbase/pocketbase/migrations"
    )
    
    func init() {
        m.Register(func(app core.App) error {
            // Up migration
            return nil
        }, func(app core.App) error {
            // Down migration
            return nil
        })
    }
    

    Collection Operations

    Create Base Collection

    collection := core.NewBaseCollection("posts")
    
    // Add fields
    collection.Fields.Add(&core.TextField{
        Name: "title",
        Required: true,
        Max: 100,
    })
    
    // Set rules (use types.Pointer())
    collection.ListRule = types.Pointer("@request.auth.id != ''")
    collection.CreateRule = types.Pointer("@request.auth.id != ''")
    collection.UpdateRule = types.Pointer("@request.auth.id = author")
    collection.DeleteRule = types.Pointer("@request.auth.id = author")
    
    return app.Save(collection)
    

    Update Existing Collection

    collection, err := app.FindCollectionByNameOrId("posts")
    if err != nil {
        return err
    }
    
    // Add field
    collection.Fields.Add(&core.DateField{
        Name: "publishedAt",
    })
    
    // Remove field
    collection.Fields.RemoveByName("oldField")
    
    // Update rules
    collection.UpdateRule = types.Pointer("@request.auth.id = author")
    
    return app.Save(collection)
    

    Common Field Types

    See references/field-types.md for complete field type reference.

    Quick Reference

    // Text
    &core.TextField{Name: "title", Required: true, Max: 100}
    
    // Number
    &core.NumberField{Name: "price", Min: types.Pointer(0.0)}
    
    // Boolean
    &core.BoolField{Name: "isActive"}
    
    // Email
    &core.EmailField{Name: "email", Required: true}
    
    // Date
    &core.DateField{Name: "publishedAt"}
    
    // Auto-managed date
    &core.AutodateField{Name: "created", OnCreate: true}
    
    // Select
    &core.SelectField{
        Name: "status",
        Values: []string{"draft", "published"},
        MaxSelect: 1,
    }
    
    // File
    &core.FileField{
        Name: "avatar",
        MaxSelect: 1,
        MaxSize: 5242880, // bytes
    }
    
    // Editor (rich text)
    &core.EditorField{
        Name: "content",
        MaxSize: 1048576,
    }
    
    // JSON
    &core.JSONField{Name: "metadata", MaxSize: 65535}
    

    Working with Relations

    Best Practices

    1. Create collections in dependency order
    2. Fetch collections before creating relations
    3. Use actual collection IDs for relations
    4. Handle self-referencing relations in separate migrations

    Relation Field

    // Fetch the target collection first
    authorsCollection, err := app.FindCollectionByNameOrId("authors")
    if err != nil {
        return err
    }
    
    // Add relation field
    collection.Fields.Add(&core.RelationField{
        Name: "author",
        Required: true,
        MaxSelect: 1,  // Note: use MaxSelect, not Max
        CollectionId: authorsCollection.Id,
        CascadeDelete: true,
    })
    
    // System users collection
    collection.Fields.Add(&core.RelationField{
        Name: "creator",
        CollectionId: "_pb_users_auth_",
        MaxSelect: 1,
    })
    

    Migration Order for Relations

    Create collections in this order:

    1. Independent collections (no relations)
    2. Collections depending on system collections
    3. Collections with relations to other custom collections
    4. Self-referencing relations (separate migration)

    Example order:

    1_create_categories.go       # Independent
    2_create_authors.go          # Depends on system users
    3_create_posts.go           # Depends on authors & categories
    4_create_comments.go        # Depends on posts & users
    5_add_parent_to_comments.go # Self-referencing
    

    Collection Rules

    Rule Types

    • ListRule - List records
    • ViewRule - View individual records
    • CreateRule - Create records
    • UpdateRule - Update records
    • DeleteRule - Delete records

    Common Patterns

    // Public access
    types.Pointer("")
    
    // Authenticated only
    types.Pointer("@request.auth.id != ''")
    
    // Owner only
    types.Pointer("@request.auth.id = author")
    
    // Published or owner
    types.Pointer("status = 'published' || author = @request.auth.id")
    
    // Through relations
    types.Pointer("author.user = @request.auth.id")
    

    View Collections

    viewQuery := `
    SELECT 
        posts.id,
        posts.title,
        users.name as author_name
    FROM posts
    JOIN users ON posts.author = users.id
    `
    collection := core.NewViewCollection("posts_with_authors", viewQuery)
    return app.Save(collection)
    

    Error Handling

    Always check errors:

    collection, err := app.FindCollectionByNameOrId("posts")
    if err != nil {
        return err
    }
    
    if err := app.Save(collection); err != nil {
        return err
    }
    

    Task Commands

    • mise run makemigration <name> - Create new migration file
    • mise run migrate - Run pending migrations
    • mise run migratedown - Rollback last migration
    • mise run show-collections - Display collections
    • mise run backup - Backup database to /tmp

    Best Practices

    1. Import types package for nullable values: "github.com/pocketbase/pocketbase/tools/types"
    2. Use types.Pointer() for rule assignments and pointer values
    3. Check collection existence before creating relations
    4. Validate field names don't conflict with system fields (id, created, updated)
    5. Handle errors immediately after operations
    6. Never skip migration testing - run each one before writing the next
    7. Backup before destructive changes

    Common Gotchas

    • Use MaxSelect (not Max) for RelationField
    • Use MaxSize (not Max) for EditorField
    • System users collection ID: "_pb_users_auth_"
    • For number min/max: types.Pointer(0.0)
    • Empty rules need: types.Pointer("")
    • Self-referencing relations need separate migrations

    Additional Resources

    • Field types reference: references/field-types.md
    • Official docs: https://pocketbase.io/docs/go-collections/
    Recommended Servers
    Neon
    Neon
    Supabase
    Supabase
    Prisma
    Prisma
    Repository
    knowsuchagency/pocketbase-template
    Files