{
"id": "social.twinkl.theme.pack",
"defs": {
"main": {
"key": "literal:self",
"type": "record",
"record": {
"type": "object",
"required": [
"name",
"createdAt"
],
"properties": {
"name": {
"type": "string",
"maxLength": 640,
"description": "Display name of the theme.",
"maxGraphemes": 64
},
"active": {
"type": "string",
"description": "Which look is active: `base` renders the plain `customBase` built-in theme (the tokens/CSS/effects/background are kept but dormant); `custom` layers them on top of `customBase`. Absent on legacy records — readers then infer `custom` when any customization is present, else `base`.",
"knownValues": [
"base",
"custom"
]
},
"assets": {
"type": "array",
"items": {
"type": "blob",
"accept": [
"image/png",
"image/jpeg",
"image/webp",
"image/gif",
"font/woff2",
"font/woff"
],
"maxSize": 5000000
},
"maxLength": 16,
"description": "Blobs referenced by the pack's CSS/tokens (backgrounds, cursors, fonts). Listed here so the PDS keeps them referenced; a CID used in CSS but absent here is rejected on save."
},
"tokens": {
"type": "unknown",
"description": "Open map of theme token name (e.g. the --twinkl-* custom properties) to a string value. All values are strings; names and value grammar are validated in application code."
},
"effects": {
"type": "array",
"items": {
"ref": "social.twinkl.theme.defs#effect",
"type": "ref"
},
"maxLength": 8,
"description": "Enabled first-party page effects."
},
"gallery": {
"type": "string",
"format": "did",
"description": "Set to the Twinkl gallery DID to list this pack publicly; omit or remove to unpublish. Gallery hydration re-verifies this value."
},
"homeCss": {
"type": "string",
"maxLength": 100000,
"description": "Custom home-page CSS (sanitized + scoped before use)."
},
"postCss": {
"type": "string",
"maxLength": 50000,
"description": "Post-decoration CSS (sanitized + scoped, never executes JS)."
},
"preview": {
"type": "blob",
"accept": [
"image/png",
"image/jpeg",
"image/webp"
],
"maxSize": 1000000,
"description": "Optional preview thumbnail for the gallery."
},
"createdAt": {
"type": "string",
"format": "datetime"
},
"updatedAt": {
"type": "string",
"format": "datetime"
},
"background": {
"type": "string",
"maxLength": 2048,
"description": "Optional page background image URL (a same-origin /blob/<did>/<cid> proxy URL or an allowlisted origin); the referenced blob must appear in `assets`."
},
"customBase": {
"type": "string",
"default": "y2kringe",
"description": "Built-in base theme whose tokens this pack layers on top of.",
"knownValues": [
"y2kringe",
"gyaru"
]
},
"description": {
"type": "string",
"maxLength": 3000,
"description": "Free-form description of the vibe.",
"maxGraphemes": 300
},
"sourceTheme": {
"type": "string",
"format": "at-uri",
"description": "Provenance: the theme.pack this look was copied from. Backlink target for gallery wearer counts."
},
"priorThemeCid": {
"type": "string",
"format": "cid",
"description": "CID of the previous version of this look, for one-step rollback (best-effort)."
},
"sourceThemeCid": {
"type": "string",
"format": "cid",
"description": "CID of the pack version that was copied."
}
}
},
"description": "The user's active look AND the unit of theme sharing (one per user, key=self). Holds the base theme, tokens, custom CSS, effects, and asset blobs (backgrounds/fonts) — which are kept live by this record's structural blob references. Listed in the public gallery by setting `gallery` to the Twinkl gallery DID (the publish property); discovered via constellation backlinks on `.gallery`. \"Stealing\" copies another user's pack into the applier's own self pack (copy-on-apply) — there is no live cross-repo reference, so a theme author can never retro-push CSS onto wearers. Custom CSS is sanitized + scoped server-side before it is ever rendered."
}
},
"$type": "com.atproto.lexicon.schema",
"lexicon": 1
}