# at.meme-museum.meme

> Published by [meme-museum.at](https://lexicon.garden/identity/did:plc:rerdjlp4sbpnw6m3t35m27zb)

✓ This is the authoritative definition for this NSID.

## Links

- [View on Lexicon Garden](https://lexicon.garden/lexicon/did:plc:rerdjlp4sbpnw6m3t35m27zb/at.meme-museum.meme)
- [Documentation](https://lexicon.garden/lexicon/did:plc:rerdjlp4sbpnw6m3t35m27zb/at.meme-museum.meme/docs)
- [Examples](https://lexicon.garden/lexicon/did:plc:rerdjlp4sbpnw6m3t35m27zb/at.meme-museum.meme/examples)

## Definitions

### `at.meme-museum.meme`

**Type**: `record`

A single meme asset (still image, animated image, or short video clip) in a user's library.

**Key**: `tid`

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `alt` | `string` | Yes | Accessibility alt text. Required, same convention as app.bsky.embed.images. |
| `tags` | `array` | No |  |
| `image` | `blob` | No | 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` | `string` | No | Short human label for the meme, distinct from alt text (e.g. "distracted boyfriend"). |
| `video` | `blob` | No | 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` | `integer` | No |  |
| `height` | `integer` | No |  |
| `source` | `ref` → `#source` | No |  |
| `duration` | `integer` | No | 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` | `string` (datetime) | Yes |  |
| `isAnimated` | `boolean` | No | 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` | `string` | No | Soft signal only, not access control -- see docs/data-model.md. |

### `at.meme-museum.meme#source`

**Type**: `object`

Provenance/attribution for a meme, if known.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `url` | `string` (uri) | No | A webpage the image came from, if relevant. |
| `note` | `string` | No | Free-text credit, e.g. "via @someone.bsky.social". |
| `importedFrom` | `string` (at-uri) | No | If copied in from another ATProto app's or user's collection, the original record's at-uri. |

## Raw Schema

```json
{
  "id": "at.meme-museum.meme",
  "defs": {
    "main": {
      "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."
    },
    "source": {
      "type": "object",
      "properties": {
        "url": {
          "type": "string",
          "format": "uri",
          "description": "A webpage the image came from, if relevant."
        },
        "note": {
          "type": "string",
          "maxLength": 500,
          "description": "Free-text credit, e.g. \"via @someone.bsky.social\"."
        },
        "importedFrom": {
          "type": "string",
          "format": "at-uri",
          "description": "If copied in from another ATProto app's or user's collection, the original record's at-uri."
        }
      },
      "description": "Provenance/attribution for a meme, if known."
    }
  },
  "$type": "com.atproto.lexicon.schema",
  "lexicon": 1
}
```
