org.cannadb.review
A review of a cannabis strain or cut. Reviews are where subjective experience lives — the reviewer's perceived flavors and effects, multi-axis ratings, prose body, and optional images. Reviews reference exactly one strain record via `subject` and aggregate at the AppView layer into per-strain summaries (community-derived effect/flavor percentages, average ratings). Publishing this record IS the claim — every field is contextualized by the publisher DID at display time. CannaDB editorial accounts do not publish reviews.
Details · record, key tid
| Kind | record |
|---|---|
| Record key | tid |
| Authority | cannadb.org |
| Indexed |
Checks
Validlarge-stringdefs.main.record.properties.bodymaxLength is over 20 KB. Use a blob for content that large.unlimited-stringdefs.main.record.properties.effects.itemsNo maxLength, maxGraphemes or format limits this string.unlimited-stringdefs.main.record.properties.flavors.itemsNo maxLength, maxGraphemes or format limits this string.
{
"$type": "com.atproto.lexicon.schema",
"defs": {
"main": {
"description": "A review of a cannabis strain or cut. Reviews are where subjective experience lives — the reviewer's perceived flavors and effects, multi-axis ratings, prose body, and optional images. Reviews reference exactly one strain record via `subject` and aggregate at the AppView layer into per-strain summaries (community-derived effect/flavor percentages, average ratings). Publishing this record IS the claim — every field is contextualized by the publisher DID at display time. CannaDB editorial accounts do not publish reviews.",
"key": "tid",
"record": {
"properties": {
"body": {
"description": "Markdown-formatted review prose. Optional — a review can be ratings-only or tag-only. Capped at 5000 graphemes (50000 bytes) — enforced by the lexicon to keep reviews modest.",
"maxGraphemes": 5000,
"maxLength": 50000,
"type": "string"
},
"createdAt": {
"description": "Client-declared timestamp when this review was originally written.",
"format": "datetime",
"type": "string"
},
"effects": {
"description": "Effect descriptors as the reviewer experienced them. Open vocabulary — see `flavors` for rationale. The AppView aggregates across reviews into community-derived effect percentages on the strain (the canonical \"top effects\" surface visitors expect on a strain page).",
"items": {
"description": "A single effect descriptor.",
"type": "string"
},
"type": "array"
},
"flavors": {
"description": "Flavor descriptors as the reviewer experienced them. Open vocabulary — the lexicon does not enforce a closed set; the AppView normalizes near-duplicates at index time and aggregates across reviews into community-derived flavor percentages on the strain.",
"items": {
"description": "A single flavor descriptor.",
"type": "string"
},
"type": "array"
},
"growRef": {
"description": "Forward-compatible AT-URI reference to a grow record (`org.cannadb.grow`, Phase 6) backing this review. Optional and speculative — the grow record type does not exist yet and this field is a placeholder for the eventual review-grow linkage. Consumers should ignore this field until the grow lexicon ships.",
"format": "at-uri",
"type": "string"
},
"images": {
"description": "Up to three image blobs attached to this review. Each image accepts common web image formats and is capped at 1 MB. Reviews are deliberately limited to three images to keep PDS storage burden modest; richer photo galleries belong in grow records (Phase 6).",
"items": {
"accept": [
"image/png",
"image/jpeg",
"image/webp"
],
"description": "A single review image.",
"maxSize": 1000000,
"type": "blob"
},
"maxLength": 3,
"type": "array"
},
"ratings": {
"description": "Multi-axis numeric ratings on a 1–5 scale. All axes are independently optional — a reviewer may rate only `overall`, only some axes, or skip ratings entirely. The AppView averages each axis across reviews for the per-strain summary.",
"ref": "#ratings",
"type": "ref"
},
"subject": {
"description": "AT-URI reference to an `org.cannadb.strain` record (any `kind`). Required. (The lexicon spec does not enforce collection constraints on at-uri; consumers must validate the ref resolves to an `org.cannadb.strain` record and reject reviews whose subject points elsewhere.)",
"format": "at-uri",
"type": "string"
}
},
"required": [
"subject",
"createdAt"
],
"type": "object"
},
"type": "record"
},
"ratings": {
"description": "Multi-axis numeric ratings on a 1–5 scale. All axes are independently optional. Aggregations (averages, distributions) happen at the AppView layer.",
"properties": {
"bagAppeal": {
"description": "Bag appeal rating, 1–5. Reviewer's subjective sense of visual quality of the cured flower.",
"maximum": 5,
"minimum": 1,
"type": "integer"
},
"ease": {
"description": "Ease-of-grow rating, 1–5. Distinct from the strain record's `growDifficulty` claim — this is the reviewer's experienced ease.",
"maximum": 5,
"minimum": 1,
"type": "integer"
},
"flavor": {
"description": "Flavor rating, 1–5.",
"maximum": 5,
"minimum": 1,
"type": "integer"
},
"overall": {
"description": "Overall rating, 1–5.",
"maximum": 5,
"minimum": 1,
"type": "integer"
},
"potency": {
"description": "Potency rating, 1–5. Reviewer's subjective sense of strength — distinct from measured cannabinoid percentages.",
"maximum": 5,
"minimum": 1,
"type": "integer"
},
"yield": {
"description": "Yield rating, 1–5. Reviewer's subjective sense of how the strain produced — a grower-axis rating distinct from the strain record's structured `yield` claim.",
"maximum": 5,
"minimum": 1,
"type": "integer"
}
},
"type": "object"
}
},
"id": "org.cannadb.review",
"lexicon": 1
}