Initial commit
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
---
|
||||
title: Set Up a Go-Extended PocketBase Application
|
||||
impact: HIGH
|
||||
impactDescription: Foundation for all custom Go business logic, hooks, and routing
|
||||
tags: go, extending, setup, main, bootstrap
|
||||
---
|
||||
|
||||
## Set Up a Go-Extended PocketBase Application
|
||||
|
||||
When extending PocketBase as a Go framework (v0.36+), the entry point is a small `main.go` that creates the app, registers hooks on `OnServe()`, and calls `app.Start()`. Avoid reaching for a global `app` variable inside hook handlers - use `e.App` instead so code works inside transactions.
|
||||
|
||||
**Incorrect (global app reuse, no OnServe hook, bare http.Handler):**
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/pocketbase/pocketbase"
|
||||
)
|
||||
|
||||
var app = pocketbase.New() // global reference used inside handlers
|
||||
|
||||
func main() {
|
||||
// Routes registered directly via net/http - bypasses PocketBase's router,
|
||||
// middleware chain, auth, rate limiter and body limit
|
||||
http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte("hello"))
|
||||
})
|
||||
|
||||
if err := app.Start(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Correct (register routes inside `OnServe`, use `e.App` in handlers):**
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/pocketbase/pocketbase"
|
||||
"github.com/pocketbase/pocketbase/apis"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := pocketbase.New()
|
||||
|
||||
app.OnServe().BindFunc(func(se *core.ServeEvent) error {
|
||||
// Serve static assets from ./pb_public (if present)
|
||||
se.Router.GET("/{path...}", apis.Static(os.DirFS("./pb_public"), false))
|
||||
|
||||
// Custom API route - namespaced under /api/{yourapp}/ to avoid
|
||||
// colliding with built-in /api/collections, /api/realtime, etc.
|
||||
se.Router.GET("/api/myapp/hello/{name}", func(e *core.RequestEvent) error {
|
||||
return e.JSON(http.StatusOK, map[string]string{
|
||||
"message": "hello " + e.Request.PathValue("name"),
|
||||
})
|
||||
}).Bind(apis.RequireAuth())
|
||||
|
||||
return se.Next()
|
||||
})
|
||||
|
||||
if err := app.Start(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Project bootstrap:**
|
||||
|
||||
```bash
|
||||
go mod init myapp
|
||||
go mod tidy
|
||||
go run . serve # development
|
||||
go build && ./myapp serve # production (statically linked binary)
|
||||
```
|
||||
|
||||
**Key details:**
|
||||
- Requires **Go 1.25.0+** (PocketBase v0.36.7+ bumped the minimum to Go 1.25.0).
|
||||
- PocketBase ships with the pure-Go `modernc.org/sqlite` driver - **no CGO required** by default.
|
||||
- If you need FTS5, ICU, or a custom SQLite build, pass `core.DBConnect` in `pocketbase.NewWithConfig(...)` - it is called twice (once for `pb_data/data.db`, once for `pb_data/auxiliary.db`).
|
||||
- Inside hooks, prefer `e.App` over a captured parent-scope `app` - the hook may run inside a transaction and the parent `app` would deadlock.
|
||||
|
||||
Reference: [Extend with Go - Overview](https://pocketbase.io/docs/go-overview/)
|
||||
Reference in New Issue
Block a user