{"id":33126018,"url":"https://github.com/magooney-loon/pb-ext","last_synced_at":"2026-03-03T21:00:57.864Z","repository":{"id":291098564,"uuid":"972868650","full_name":"magooney-loon/pb-ext","owner":"magooney-loon","description":"pocketbase boilerplate","archived":false,"fork":false,"pushed_at":"2026-02-25T14:40:29.000Z","size":1631,"stargazers_count":98,"open_issues_count":0,"forks_count":6,"subscribers_count":4,"default_branch":"main","last_synced_at":"2026-02-25T18:27:05.666Z","etag":null,"topics":["analytics","openapi","pocketbase","sqlite","web-server"],"latest_commit_sha":null,"homepage":"https://pkg.go.dev/github.com/magooney-loon/pb-ext","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/magooney-loon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-04-25T19:58:14.000Z","updated_at":"2026-02-25T14:40:12.000Z","dependencies_parsed_at":"2026-02-20T19:00:33.909Z","dependency_job_id":null,"html_url":"https://github.com/magooney-loon/pb-ext","commit_stats":null,"previous_names":["magooney-loon/pb-ext"],"tags_count":20,"template":false,"template_full_name":null,"purl":"pkg:github/magooney-loon/pb-ext","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magooney-loon%2Fpb-ext","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magooney-loon%2Fpb-ext/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magooney-loon%2Fpb-ext/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magooney-loon%2Fpb-ext/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/magooney-loon","download_url":"https://codeload.github.com/magooney-loon/pb-ext/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/magooney-loon%2Fpb-ext/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30060602,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-03T18:21:05.932Z","status":"ssl_error","status_checked_at":"2026-03-03T18:20:59.341Z","response_time":61,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["analytics","openapi","pocketbase","sqlite","web-server"],"created_at":"2025-11-15T07:00:23.181Z","updated_at":"2026-03-03T21:00:57.846Z","avatar_url":"https://github.com/magooney-loon.png","language":"Go","funding_links":[],"categories":["Go Plugins"],"sub_categories":[],"readme":"# pb-ext\n\nEnhanced PocketBase server with monitoring, logging \u0026 API docs.\n\n\u003cimg width=\"3840\" height=\"2160\" alt=\"pb-ext\" src=\"https://github.com/user-attachments/assets/af360704-c3d6-4d1f-9b49-80229d6570d2\" /\u003e\n\u003cimg width=\"1920\" height=\"2153\" alt=\"Screenshot_2026-02-10_14-42-37\" src=\"https://github.com/user-attachments/assets/d74cf16e-7b5a-4bd0-9f73-1ea81b8c175c\" /\u003e\n\u003cimg width=\"1656\" height=\"1645\" alt=\"Screenshot_2026-02-20_18-19-39\" src=\"https://github.com/user-attachments/assets/ee4062e3-f9f1-4868-8f17-002c4f1c9f11\" /\u003e\n\n\n\n[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/magooney-loon/pb-ext)\n\n## Core Features\n\n- **API Schema**: Auto-generates OpenAPI docs UI for your endpoints\n- **Cron Tracking**: Logs and monitors scheduled cron jobs\n- **System Monitoring**: Real-time CPU, memory, disk, network, and runtime metrics\n- **Structured Logging**: Complete logging with error tracking and request tracing\n- **Visitor Analytics**: Track GDPR compliant visitors, page views, device types, and browsers\n- **PocketBase Integration**: Uses PocketBase's auth system and styling\n\n## Access\n\n- Admin panel:\n```bash\n127.0.0.1:8090/_\n```\n- pb-ext dashboard:\n```bash\n127.0.0.1:8090/_/_\n```\n## Quick Start\n\n\u003e 🆕 New to Golang and/or PocketBase? [Read this beginner tutorial](TUTORIAL.md).\n\n```go\npackage main\n\nimport (\n\t\"flag\"\n\t\"log\"\n\n\tapp \"github.com/magooney-loon/pb-ext/core\"\n\t\"github.com/pocketbase/pocketbase/core\"\n)\n\nfunc main() {\n\tdevMode := flag.Bool(\"dev\", false, \"Run in developer mode\")\n\tgenerateSpecsDir := flag.String(\"generate-specs-dir\", \"\", \"Generate OpenAPI specs into the provided directory and exit\")\n\tgenerateSpecVersion := flag.String(\"generate-spec-version\", \"\", \"Optional API version to generate (requires --generate-specs-dir)\")\n\tvalidateSpecsDir := flag.String(\"validate-specs-dir\", \"\", \"Validate OpenAPI specs from the provided directory and exit\")\n\tflag.Parse()\n\n\tif *generateSpecsDir != \"\" {\n\t\tgen := app.NewSpecGeneratorWithInitializer(func() (*app.APIVersionManager, error) {\n\t\t\treturn initVersionedSystem(), nil\n\t\t})\n\t\tif err := gen.Generate(*generateSpecsDir, *generateSpecVersion); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\treturn\n\t}\n\n\tif *validateSpecsDir != \"\" {\n\t\tgen := app.NewSpecGeneratorWithInitializer(func() (*app.APIVersionManager, error) {\n\t\t\treturn initVersionedSystem(), nil\n\t\t})\n\t\tif err := gen.Validate(*validateSpecsDir); err != nil {\n\t\t\tlog.Fatal(err)\n\t\t}\n\t\treturn\n\t}\n\n\tinitApp(*devMode)\n}\n\nfunc initApp(devMode bool) {\n\tvar opts []app.Option\n\n\tif devMode {\n\t\topts = append(opts, app.InDeveloperMode())\n\t} else {\n\t\topts = append(opts, app.InNormalMode())\n\t}\n\n\t// Option 1: Use a custom PocketBase config\n\t// pbConfig := \u0026pocketbase.Config{\n\t// \tDefaultDev:     true,\n\t// \tDefaultDataDir: \"./custom_pb_data\",\n\t// }\n\t// opts = append(opts, app.WithConfig(pbConfig))\n\n\t// Option 2: Use an existing PocketBase instance\n\t// pb := pocketbase.New()\n\t// opts = append(opts, app.WithPocketbase(pb))\n\n\t// Set custom port programmatically\n\t// os.Args = []string{\"app\", \"serve\", \"--http=127.0.0.1:9090\"}\n\n\t// Note: WithConfig and WithPocketbase cannot be used together\n\n\tsrv := app.New(opts...)\n\n\tapp.SetupLogging(srv)\n\n\tregisterCollections(srv.App())\n\tregisterRoutes(srv.App())\n\tregisterJobs(srv.App())\n\n\tsrv.App().OnServe().BindFunc(func(e *core.ServeEvent) error {\n\t\tapp.SetupRecovery(srv.App(), e)\n\t\treturn e.Next()\n\t})\n\n\tif err := srv.Start(); err != nil {\n\t\tsrv.App().Logger().Error(\"Fatal application error\",\n\t\t\t\"error\", err,\n\t\t\t\"uptime\", srv.Stats().StartTime,\n\t\t\t\"total_requests\", srv.Stats().TotalRequests.Load(),\n\t\t\t\"active_connections\", srv.Stats().ActiveConnections.Load(),\n\t\t\t\"last_request_time\", srv.Stats().LastRequestTime.Load(),\n\t\t)\n\t\tlog.Fatal(err)\n\t}\n}\n\n// Example models in cmd/server/collections.go\n// Example routes in cmd/server/routes.go\n// Example handlers in cmd/server/handlers.go\n// Example cron jobs in cmd/server/jobs.go\n//\n// You can restructure Your project as You wish,\n// just keep this main.go in cmd/server/main.go\n//\n// Build toolchain (pb-cli):\n// go install github.com/magooney-loon/pb-ext/cmd/pb-cli@latest\n//\n// Need a pre-built Svelte5Kit starter template?\n// https://github.com/magooney-loon/svelte-gui\n//\n// Ready for a production build deployment?\n// https://github.com/magooney-loon/pb-deployer\n```\n\n```bash\ngo mod tidy\ngo install github.com/magooney-loon/pb-ext/cmd/pb-cli@latest\npb-cli --run-only\n```\n\n\nSee `**/*/README.md` for detailed docs.\n\n## OpenAPI Spec Generation \u0026 Embedding\n\n### Build pipeline integration\n\nThe pb-cli toolchain runs OpenAPI generation + validation automatically before server compilation. First install it globally:\n\n```bash\ngo install github.com/magooney-loon/pb-ext/cmd/pb-cli@latest\n```\n\nThen use it in your project:\n\n```bash\npb-cli              # Development mode\npb-cli --build-only # Build frontend only\npb-cli --production # Production build\n```\n\nFor programmatic usage, see `pkg/scripts/README.md`.\n\n\nHaving issues with Your API Docs?\n```bash\n127.0.0.1:8090/api/docs/debug/ast\n```\n\n## Reserved Collections\n\npb-ext creates the following PocketBase system collections automatically on startup. **Do not create collections with these names in your own code.**\n\n| Collection | Purpose |\n|---|---|\n| `_analytics` | Daily aggregated page view counters (one row per path/date/device/browser). Retention: 90 days. |\n| `_analytics_sessions` | Ring buffer of the 50 most recent visits for the Recent Activity display. No PII stored. |\n| `_job_logs` | Cron job execution logs (start time, end time, duration, status, output). Retention: 72 hours. |\n\n**Schema notes:**\n- All three collections are system collections (hidden from the PocketBase Collections UI).\n- `_analytics` and `_analytics_sessions` store no personal data — no IP, no user agent, no visitor ID. GDPR-compliant by design.\n- On upgrade from an old pb-ext version, incompatible schemas are automatically migrated at startup with no manual steps required.\n\n## Reserved Routes\n\npb-ext registers the following routes. **Do not register your own routes at these paths.**\n\n### Dashboard\n| Method | Path | Auth | Description |\n|---|---|---|---|\n| `GET` | `/_/_` | Superuser | pb-ext health, analytics \u0026 jobs dashboard |\n\n### Cron Job API\nAll routes require superuser authentication.\n\n| Method | Path | Description |\n|---|---|---|\n| `GET` | `/api/cron/jobs` | List registered cron jobs |\n| `POST` | `/api/cron/jobs/{id}/run` | Trigger a job manually |\n| `DELETE` | `/api/cron/jobs/{id}` | Remove a job from the scheduler |\n| `GET` | `/api/cron/status` | Cron scheduler status |\n| `POST` | `/api/cron/config/timezone` | Update scheduler timezone |\n| `GET` | `/api/cron/logs` | Paginated job execution logs |\n| `GET` | `/api/cron/logs/{job_id}` | Logs for a specific job |\n| `GET` | `/api/cron/logs/analytics` | Aggregated job log statistics |\n\n### API Docs\n| Method | Path | Description |\n|---|---|---|\n| `GET` | `/api/docs/versions` | List registered API versions |\n| `GET` | `/api/docs/debug/ast` | AST parsing debug info |\n| `GET` | `/api/docs/v{n}` | Version metadata |\n| `GET` | `/api/docs/v{n}/openapi.json` | OpenAPI 3.0 spec |\n| `GET` | `/api/docs/v{n}/swagger` | Swagger UI |\n\n### Internal System Jobs\n\npb-ext registers these cron jobs automatically. They appear in the dashboard with the \"System\" badge.\n\n| Job ID | Schedule | Description |\n|---|---|---|\n| `__pbExtLogClean__` | `0 0 * * *` (daily midnight) | Purge `_job_logs` records older than 72 hours |\n| `__pbExtAnalyticsClean__` | `0 3 * * *` (daily 3 AM) | Purge `_analytics` rows older than 90 days |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmagooney-loon%2Fpb-ext","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmagooney-loon%2Fpb-ext","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmagooney-loon%2Fpb-ext/lists"}