town.walls.photo

walls.town

{
  "id": "town.walls.photo",
  "defs": {
    "main": {
      "key": "tid",
      "type": "record",
      "record": {
        "type": "object",
        "required": [
          "createdAt"
        ],
        "properties": {
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxLength": 40,
            "description": "Faceted tags. Conventions (parsed/enforced in app code, not the lexicon): kind:<piece|throwup|tag|mural|sticker|roller|wheatpaste|other> (exactly one expected), crew:<name>, surface:<wall|truck|pole|shutter|...>. Plus freeform tags (e.g. \"trackside\", \"two-color\")."
          },
          "image": {
            "type": "blob",
            "accept": [
              "image/*"
            ],
            "maxSize": 4000000,
            "description": "The displayed photo. Optional in schema; exactly one of image or grainPost is required (enforced in app code)."
          },
          "notes": {
            "type": "string",
            "maxLength": 10000,
            "maxGraphemes": 1000
          },
          "camera": {
            "ref": "#camera",
            "type": "ref"
          },
          "artists": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxLength": 20,
            "description": "Artist names. Free strings; a piece may have several."
          },
          "caption": {
            "type": "string",
            "maxLength": 3000,
            "maxGraphemes": 300
          },
          "bskyPost": {
            "ref": "com.atproto.repo.strongRef",
            "type": "ref",
            "description": "strongRef to an app.bsky.feed.post cross-posting this sighting."
          },
          "location": {
            "ref": "#location",
            "type": "ref"
          },
          "longform": {
            "ref": "com.atproto.repo.strongRef",
            "type": "ref",
            "description": "strongRef to a site.standard.document for pieces with an essay. Reserved; not wired yet."
          },
          "createdAt": {
            "type": "string",
            "format": "datetime",
            "description": "Record creation time."
          },
          "grainPost": {
            "ref": "com.atproto.repo.strongRef",
            "type": "ref",
            "description": "strongRef to a grain post serving as the photo. Alternative to image (exactly one of image/grainPost required, app-enforced)."
          },
          "capturedAt": {
            "type": "string",
            "format": "datetime",
            "description": "When the photo was taken (EXIF DateTimeOriginal), if known."
          },
          "siteRecord": {
            "ref": "com.atproto.repo.strongRef",
            "type": "ref",
            "description": "strongRef to the site.standard.* record the website publishes per photo for discoverability."
          },
          "aspectRatio": {
            "ref": "#aspectRatio",
            "type": "ref",
            "description": "Pixel dimensions of the image, used for justified layout / to avoid reflow. Best-effort."
          },
          "grainCrosspost": {
            "ref": "com.atproto.repo.strongRef",
            "type": "ref",
            "description": "strongRef to a social.grain.gallery this admin created to syndicate the sighting onto grain (gallery == grain post). Distinct from grainPost, which is an external grain post used AS the photo source. Set by the syndication step; absence means the grain leg hasn't run."
          }
        }
      },
      "description": "A documented photo of a graffiti piece."
    },
    "camera": {
      "type": "object",
      "properties": {
        "iso": {
          "type": "integer"
        },
        "lens": {
          "type": "string"
        },
        "make": {
          "type": "string"
        },
        "model": {
          "type": "string"
        },
        "shutter": {
          "type": "string"
        },
        "aperture": {
          "type": "string"
        },
        "focalLength": {
          "type": "string"
        }
      },
      "description": "Best-effort capture metadata from EXIF or a grain record."
    },
    "location": {
      "type": "object",
      "properties": {
        "lat": {
          "type": "string",
          "description": "Decimal degrees, full precision. e.g. \"37.77531\"."
        },
        "lng": {
          "type": "string",
          "description": "Decimal degrees, full precision. e.g. \"-122.22417\"."
        },
        "name": {
          "type": "string",
          "description": "Optional human label, e.g. \"E 12th St underpass\"."
        }
      },
      "description": "Capture location. lat/lng are decimal-degree STRINGS: ATProto lexicons have no float type (only integer). NOTE: coordinates are stored at full precision here. The PUBLIC website coarsens them at render time via geo.coarsen, but the record itself is public via listRecords — exact coords are readable by anyone reading the repo directly."
    },
    "aspectRatio": {
      "type": "object",
      "required": [
        "width",
        "height"
      ],
      "properties": {
        "width": {
          "type": "integer",
          "minimum": 1
        },
        "height": {
          "type": "integer",
          "minimum": 1
        }
      },
      "description": "Image pixel dimensions. width/height are integers (e.g. for a 6000x4000 photo)."
    }
  },
  "$type": "com.atproto.lexicon.schema",
  "lexicon": 1
}

Validate Record

Validate a record against town.walls.photo

Validation Options
Treat any remaining unresolved references as valid

Metadata

DID
did:plc:geruez2v64zoge3l4sztt4kz
CID
bafyreibsrhj6ht5p7xptkjltyarsuuapkbcuzqvhwtif2wytoftqpfyi3m
Indexed At
2026-06-19 04:52 UTC
AT-URI
at://did:plc:geruez2v64zoge3l4sztt4kz/com.atproto.lexicon.schema/town.walls.photo

Lexicon Garden

@