# Adding Fields to an Existing PocketBase Collection

PocketBase silently drops fields not in the collection schema — no HTTP error, no warning, just data loss. If your app writes fields that PocketBase ignores, you need to add them to the schema.

## Detection

Signs that PocketBase is dropping fields:
- Code writes a field (e.g., `recommendation`, `explanation`) via `addDoc()` or `updateDoc()`
- The record is created/updated with HTTP 200
- But re-reading the record shows the field as `undefined`/missing
- The field works fine in Firestore but not PocketBase

## Fix: PATCH the Collection Schema

Adding fields requires sending the COMPLETE fields array (existing + new) via PATCH:

```python
#!/usr/bin/env python3
"""Add fields to existing PocketBase collection"""
import json, urllib.request, ssl

ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE

BASE = "http://localhost:8091"
COLLECTION_ID = "pbc_863811952"  # from GET /api/collections

# Step 1: Auth as superuser
auth_resp = json.loads(urllib.request.urlopen(
    urllib.request.Request(f"{BASE}/api/collections/_superusers/auth-with-password",
        data=json.dumps({"identity": "admin@example.com", "password": "..."}).encode(),
        headers={"Content-Type": "application/json"},
        method="POST"), context=ctx).read())
token = auth_resp["token"]

# Step 2: Get current fields
collections = json.loads(urllib.request.urlopen(
    urllib.request.Request(f"{BASE}/api/collections",
        headers={"Authorization": f"Bearer {token}"}), context=ctx).read())
svc = next(c for c in collections["items"] if c["id"] == COLLECTION_ID)
existing_fields = svc["fields"]

# Step 3: Build new fields to add
new_fields = [
    {"autogeneratePattern":"","hidden":False,"id":"text_new_1","max":0,"min":0,
     "name":"explanation","pattern":"","presentable":False,"primaryKey":False,
     "required":False,"system":False,"type":"text"},
    {"autogeneratePattern":"","hidden":False,"id":"text_new_2","max":0,"min":0,
     "name":"recommendation","pattern":"","presentable":False,"primaryKey":False,
     "required":False,"system":False,"type":"text"},
]

# Step 4: PATCH with complete fields array (existing + new)
all_fields = existing_fields + new_fields
result = json.loads(urllib.request.urlopen(
    urllib.request.Request(f"{BASE}/api/collections/{COLLECTION_ID}",
        data=json.dumps({"fields": all_fields}).encode(),
        headers={"Authorization": f"Bearer {token}", "Content-Type": "application/json"},
        method="PATCH"), context=ctx).read())
print(f"Updated fields: {[f['name'] for f in result['fields']]}")
```

## Critical Requirements

1. **Send ALL fields, not just new ones.** PATCH replaces the entire `fields` array. Sending only the new fields will DELETE all existing fields and break the collection.

2. **Each field needs a unique `id` string.** Use descriptive strings like `text_exp_001` — they just need to be unique within the collection.

3. **Field types matter.** `text` for strings, `number` for numbers, `bool` for booleans. Use `text` for most fields to be safe.

4. **No `system:true` for custom fields.** Only the built-in `id` field should have `system:true`.

## Never Do This

- **Never edit the SQLite database directly.** Use the REST API. Direct SQLite edits can corrupt field ID tracking and break the collection irreversibly.
- **Never use POST to update an existing collection.** POST creates a new collection; PATCH updates an existing one.
- **Don't forget to include the `id` field.** The system `id` field must remain in the array.
