A single meme asset (still image, animated image, or short video clip) in a user's library.
tid
Timestamp-based ID
Properties
alt
string
Required
Accessibility alt text. Required, same convention as app.bsky.embed.images.
maxLength: 2000 bytesmaxGraphemes: 1000 graphemescreatedAt
string
datetime
Required
An RFC 3339 formatted timestamp.
duration
integer
Optional
Video memes only: clip length in milliseconds, read client-side at upload time. Omitted when the browser couldn't decode metadata for the picked file.
minimum: 1height
integer
Optional
No description available.
minimum: 1image
blob
Optional
The asset, when this meme is an image. Exactly one of image/video is set -- a constraint Lexicon can't express, so it's enforced client-side. Neither is required here so that adding video didn't have to break records written before it existed.
maxSize: 8.0 MBisAnimated
boolean
Optional
Image memes only: set client-side from frame-count inspection at upload time, since it isn't reliably inferable from mimetype alone. Not written for video, where it would be trivially true.
source
ref
#source
Optional
No description available.
tags
array
of
string
Optional
No description available.
maxLength: 25 itemstitle
string
Optional
Short human label for the meme, distinct from alt text (e.g. "distracted boyfriend").
maxLength: 300 bytesmaxGraphemes: 100 graphemesvideo
blob
Optional
The asset, when this meme is a video clip. Always mp4 regardless of what the user picked: the blob is the one Bluesky's video service transcodes and writes back to the PDS, and app.bsky.embed.video accepts nothing else.
maxSize: 100.0 MBvisibility
string
Optional
Soft signal only, not access control -- see docs/data-model.md.
maxLength: 64 bytespublic, unlistedpublicwidth
integer
Optional
No description available.
minimum: 1View raw schema
{
"key": "tid",
"type": "record",
"record": {
"type": "object",
"required": [
"alt",
"createdAt"
],
"properties": {
"alt": {
"type": "string",
"maxLength": 2000,
"description": "Accessibility alt text. Required, same convention as app.bsky.embed.images.",
"maxGraphemes": 1000
},
"tags": {
"type": "array",
"items": {
"type": "string",
"maxLength": 64
},
"maxLength": 25
},
"image": {
"type": "blob",
"accept": [
"image/png",
"image/jpeg",
"image/webp",
"image/gif"
],
"maxSize": 8000000,
"description": "The asset, when this meme is an image. Exactly one of image/video is set -- a constraint Lexicon can't express, so it's enforced client-side. Neither is required here so that adding video didn't have to break records written before it existed."
},
"title": {
"type": "string",
"maxLength": 300,
"description": "Short human label for the meme, distinct from alt text (e.g. \"distracted boyfriend\").",
"maxGraphemes": 100
},
"video": {
"type": "blob",
"accept": [
"video/mp4"
],
"maxSize": 100000000,
"description": "The asset, when this meme is a video clip. Always mp4 regardless of what the user picked: the blob is the one Bluesky's video service transcodes and writes back to the PDS, and app.bsky.embed.video accepts nothing else."
},
"width": {
"type": "integer",
"minimum": 1
},
"height": {
"type": "integer",
"minimum": 1
},
"source": {
"ref": "#source",
"type": "ref"
},
"duration": {
"type": "integer",
"minimum": 1,
"description": "Video memes only: clip length in milliseconds, read client-side at upload time. Omitted when the browser couldn't decode metadata for the picked file."
},
"createdAt": {
"type": "string",
"format": "datetime"
},
"isAnimated": {
"type": "boolean",
"description": "Image memes only: set client-side from frame-count inspection at upload time, since it isn't reliably inferable from mimetype alone. Not written for video, where it would be trivially true."
},
"visibility": {
"type": "string",
"default": "public",
"maxLength": 64,
"description": "Soft signal only, not access control -- see docs/data-model.md.",
"knownValues": [
"public",
"unlisted"
]
}
}
},
"description": "A single meme asset (still image, animated image, or short video clip) in a user's library."
}