Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Collection and schema design for PocketBase. Use when creating collections, designing schemas, adding fields, setting up relations, or choosing between base/auth/view collection types. Prevents wrong field types, documents zero-default behavior, and covers relation cascading.
.claude/skills/davila7-pocketbase-collections/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-16 | ✗→✓ | ▲ Improved | 18% | 0% |
| case-01 | ✗→✓ | ▲ Improved | 8% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 4% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 29% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 50% | 0% |
Standard data collection. System fields: id, created, updated.
Extends base with authentication. Additional system fields: email, emailVisibility, verified, password, tokenKey.
Cannot delete system fields. Can disable email/password auth in collection options.
Read-only, backed by a SQL SELECT query. No create/update/delete. Fields are auto-detected from the query. Useful for aggregations, joins, and computed views.
sql-- Example: view collection query SELECT p.id, p.title, COUNT(c.id) as comments_count FROM posts p LEFT JOIN comments c ON c.post = p.id GROUP BY p.id
View collections support API rules (list/view only) and can be used in relations.
| Type | Go type | Zero default | Notes | |------|---------|-------------|-------| | text | string | "" | min/max length, regex pattern | | editor | string | "" | Rich text (sanitized HTML) | | number | float64 | 0 | min/max, noDecimal option | | bool | bool | false | | | email | string | "" | Auto-validated format | | url | string | "" | Auto-validated format | | date | string | "" | ISO 8601 (2024-01-01 00:00:00.000Z) | | select | string/[]string | ""/[] | values list, maxSelect | | file | string/[]string | ""/[] | maxSelect, maxSize, mimeTypes | | relation | string/[]string | ""/[] | collectionId, cascadeDelete, maxSelect | | json | any | null | Only type that can be null! maxSize | | autodate | string | auto | onCreate/onUpdate modifiers | | password | string | "" | Stored hashed, never returned in API |
Critical: all types default to their zero value, NOT null. Only json fields can be null.
Use in collection schema definitions:
required — field cannot be empty/zerounique — unique constraint (composite via unique indexes)presentable — included in relation displayhidden — excluded from API responses unless explicitly requested:autogenerate — for text fields: auto-generate value (e.g., slug from other field)posts.author -> users (maxSelect: 1)Each post has one author. Query posts by author: author = "USER_ID".
posts.tags -> tags (maxSelect: 0, meaning unlimited)Multi-select relation. Filter: tags ?= "TAG_ID" (contains).
No explicit back-relation field needed. Use @collection.posts.author in API rules or expand from either side:
GET /api/collections/users/records/USER_ID?expand=posts_via_authorSet cascadeDelete: true on the relation field. When the referenced record is deleted, all records pointing to it are also deleted. Default is false (sets to empty string).
A collection can reference itself:
categories.parent -> categories (maxSelect: 1)CREATE [UNIQUE] INDEX idx_name ON collection (field1, field2)CREATE INDEX ... WHERE conditionEnable per-provider in collection settings. Each provider needs client ID + secret. PocketBase handles the full OAuth2 flow.
Enable in auth collection settings. Sends code via email. Configure otp.enabled, otp.duration, otp.length.
Enable in auth collection settings. Requires a second factor after primary auth. mfa.enabled, mfa.duration, mfa.rule (filter to determine which users need MFA).
Enabled by default. Can customize minPasswordLength. Can disable entirely if using only OAuth2/OTP.
authToken.duration — token lifetime (seconds)passwordAuth.enabled — toggle email/passwordpasswordAuth.identityFields — fields used for login (default: email; can add username)oauth2.enabled — toggle OAuth2otp.enabled — toggle OTPselect over bool when there might be more than 2 states in the futurerelation not text for foreign keys — you get cascade, expand, and type safetyjson fields are schemaless — use sparingly, prefer typed fieldsblog_posts, user_profiles)maxSelect: 1 on relations returns a string ID; maxSelect: >1 or 0 returns an array| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-16 | fail→pass | 14,551 | 7,787 | -46% | 1 | 1 | 0% | 2,375 | 2,805 | +18% | 0 | 0 | — |
case-01 | fail→pass | 18,300 | 12,079 | -34% | 1 | 1 | 0% | 3,352 | 3,625 | +8% | 0 | 0 | — |
case-02 | fail→pass | 19,192 | 12,090 | -37% | 1 | 1 | 0% | 3,533 | 3,674 | +4% | 0 | 0 | — |
case-03 | pass→pass | 9,172 | 8,987 | -2% | 1 | 1 | 0% | 1,608 | 2,949 | +83% | 0 | 0 | — |
case-04 | pass→pass | 10,454 | 9,592 | -8% | 1 | 1 | 0% | 1,829 | 3,009 | +65% | 0 | 0 | — |
case-05 | pass→pass | 12,996 | 7,232 | -44% | 1 | 1 | 0% | 2,537 | 2,676 | +5% | 0 | 0 | — |
case-06 | fail→pass | 13,291 | 8,465 | -36% | 1 | 1 | 0% | 2,146 | 2,776 | +29% | 0 | 0 | — |
case-07 | pass→pass | 6,152 | 2,706 | -56% | 1 | 1 | 0% | 1,210 | 1,867 | +54% | 0 | 0 | — |
case-08 | pass→pass | 13,281 | 9,926 | -25% | 1 | 1 | 0% | 2,084 | 3,051 | +46% | 0 | 0 | — |
case-09 | fail→pass | 8,928 | 5,904 | -34% | 1 | 1 | 0% | 1,683 | 2,518 | +50% | 0 | 0 | — |
case-10 | pass→pass | 12,457 | 7,948 | -36% | 1 | 1 | 0% | 2,157 | 2,710 | +26% | 0 | 0 | — |
case-11 | pass→pass | 10,638 | 6,444 | -39% | 1 | 1 | 0% | 1,910 | 2,474 | +30% | 0 | 0 | — |
case-12 | fail→pass | 12,446 | 9,337 | -25% | 1 | 1 | 0% | 2,286 | 3,177 | +39% | 0 | 0 | — |
case-13 | pass→pass | 13,315 | 10,151 | -24% | 1 | 1 | 0% | 2,233 | 3,012 | +35% | 0 | 0 | — |
case-14 | pass→pass | 14,217 | 8,261 | -42% | 1 | 1 | 0% | 2,371 | 2,824 | +19% | 0 | 0 | — |
case-15 | pass→pass | 9,154 | 7,018 | -23% | 1 | 1 | 0% | 1,599 | 2,589 | +62% | 0 | 0 | — |
case-17 | pass→pass | 14,202 | 4,181 | -71% | 1 | 1 | 0% | 2,290 | 1,913 | -16% | 0 | 0 | — |
case-18 | pass→pass | 5,043 | 3,373 | -33% | 1 | 1 | 0% | 848 | 1,958 | +131% | 0 | 0 | — |
case-19 | pass→pass | 6,771 | 2,700 | -60% | 1 | 1 | 0% | 1,040 | 1,763 | +70% | 0 | 0 | — |
case-20 | pass→pass | 11,314 | 9,643 | -15% | 1 | 1 | 0% | 1,892 | 2,977 | +57% | 0 | 0 | — |
case-21 | pass→pass | 6,945 | 7,906 | +14% | 1 | 1 | 0% | 1,256 | 2,879 | +129% | 0 | 0 | — |
case-22 | pass→pass | 13,575 | 10,351 | -24% | 1 | 1 | 0% | 2,593 | 3,397 | +31% | 0 | 0 | — |
case-23 | pass→pass | 4,052 | 2,976 | -27% | 1 | 1 | 0% | 744 | 1,967 | +164% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of +26 percentage points is the difference between those two pass rates over the 23 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.