A grow — one documented cultivation run (a tent, a garden, a season's cycle). The grow is a lightweight container: it groups one or more `org.cannadb.plant` records and carries the shared setup and a publisher-chosen listing preference. Per-plant lifecycle, activities, notes, and measurements live in `org.cannadb.growEntry` records that reference a plant; photos live in `org.cannadb.growPhoto` records. Publishing this record IS the claim — every field is contextualized by the publisher DID at display time. NOTE on visibility: all atproto records are public regardless of `listed`; `listed` controls only whether the AppView includes this grow (and its plants/entries/photos) in public listing, search, and per-strain aggregation. Unlisted is not private.
tid
Timestamp-based ID
Properties
coverImage
blob
Optional
One representative image for the grow's listing card and header. Richer photo galleries belong in `org.cannadb.growPhoto` records. Capped at 2 MB to keep PDS storage burden modest; SVG is excluded for XSS safety.
maxSize: 2.0 MBcreatedAt
string
datetime
Required
Client-declared timestamp when this grow record was originally created.
description
string
Optional
Markdown-formatted overview of the grow — setup, intent, lighting/nutrient regimen, room notes. Per-plant and per-event detail belongs in `org.cannadb.growEntry` records; this is the grow-wide writeup.
maxLength: 100000 bytesmaxGraphemes: 10000 graphemesendedAt
string
datetime
Optional
When the grow run ended (final harvest, or the run was abandoned/archived). Optional.
environment
string
Optional
Static setup descriptor for where the grow runs. Live sensor/environment/controller telemetry is out of scope for CannaDB (it remains the domain of self-hosted tools like Isley). Open vocabulary.
indoor, outdoor, greenhouse, mixedlisted
boolean
Optional
Publisher's index preference. Absent or true means the AppView MAY include this grow — and its plants, entries, and photos — in public listing, search, and per-strain grow aggregation. False means the AppView SHOULD exclude the whole grow subtree from those public surfaces. This controls indexing only: the records remain public on the PDS and resolvable by direct AT-URI regardless. It is independent of AppView moderation (a listed grow may still be editorially hidden).
medium
string
Optional
Static setup descriptor for the growing medium. Open vocabulary.
soil, living_soil, coco, hydro, rockwool, aeroponic, othername
string
Required
Display name for this grow, e.g., "Wedding Cake — Spring '26 Tent". Capped to keep listing cards tidy.
maxLength: 2000 bytesmaxGraphemes: 200 graphemesstartedAt
string
datetime
Optional
When the grow run began (typically the first germination/plant date). Optional.
status
string
Optional
Coarse grow-level status. Distinct from per-plant lifecycle stage (which is event-sourced via `org.cannadb.growEntry`). Open vocabulary — clients should accept unknown values and fall back to generic display.
active, harvested, archived, abandonedView raw schema
{
"key": "tid",
"type": "record",
"record": {
"type": "object",
"required": [
"name",
"createdAt"
],
"properties": {
"name": {
"type": "string",
"maxLength": 2000,
"description": "Display name for this grow, e.g., \"Wedding Cake — Spring '26 Tent\". Capped to keep listing cards tidy.",
"maxGraphemes": 200
},
"listed": {
"type": "boolean",
"description": "Publisher's index preference. Absent or true means the AppView MAY include this grow — and its plants, entries, and photos — in public listing, search, and per-strain grow aggregation. False means the AppView SHOULD exclude the whole grow subtree from those public surfaces. This controls indexing only: the records remain public on the PDS and resolvable by direct AT-URI regardless. It is independent of AppView moderation (a listed grow may still be editorially hidden)."
},
"medium": {
"type": "string",
"description": "Static setup descriptor for the growing medium. Open vocabulary.",
"knownValues": [
"soil",
"living_soil",
"coco",
"hydro",
"rockwool",
"aeroponic",
"other"
]
},
"status": {
"type": "string",
"description": "Coarse grow-level status. Distinct from per-plant lifecycle stage (which is event-sourced via `org.cannadb.growEntry`). Open vocabulary — clients should accept unknown values and fall back to generic display.",
"knownValues": [
"active",
"harvested",
"archived",
"abandoned"
]
},
"endedAt": {
"type": "string",
"format": "datetime",
"description": "When the grow run ended (final harvest, or the run was abandoned/archived). Optional."
},
"createdAt": {
"type": "string",
"format": "datetime",
"description": "Client-declared timestamp when this grow record was originally created."
},
"startedAt": {
"type": "string",
"format": "datetime",
"description": "When the grow run began (typically the first germination/plant date). Optional."
},
"coverImage": {
"type": "blob",
"accept": [
"image/png",
"image/jpeg",
"image/webp"
],
"maxSize": 2000000,
"description": "One representative image for the grow's listing card and header. Richer photo galleries belong in `org.cannadb.growPhoto` records. Capped at 2 MB to keep PDS storage burden modest; SVG is excluded for XSS safety."
},
"description": {
"type": "string",
"maxLength": 100000,
"description": "Markdown-formatted overview of the grow — setup, intent, lighting/nutrient regimen, room notes. Per-plant and per-event detail belongs in `org.cannadb.growEntry` records; this is the grow-wide writeup.",
"maxGraphemes": 10000
},
"environment": {
"type": "string",
"description": "Static setup descriptor for where the grow runs. Live sensor/environment/controller telemetry is out of scope for CannaDB (it remains the domain of self-hosted tools like Isley). Open vocabulary.",
"knownValues": [
"indoor",
"outdoor",
"greenhouse",
"mixed"
]
}
}
},
"description": "A grow — one documented cultivation run (a tent, a garden, a season's cycle). The grow is a lightweight container: it groups one or more `org.cannadb.plant` records and carries the shared setup and a publisher-chosen listing preference. Per-plant lifecycle, activities, notes, and measurements live in `org.cannadb.growEntry` records that reference a plant; photos live in `org.cannadb.growPhoto` records. Publishing this record IS the claim — every field is contextualized by the publisher DID at display time. NOTE on visibility: all atproto records are public regardless of `listed`; `listed` controls only whether the AppView includes this grow (and its plants/entries/photos) in public listing, search, and per-strain aggregation. Unlisted is not private."
}