{
"id": "com.luminframe.effect",
"defs": {
"main": {
"key": "any",
"type": "record",
"record": {
"type": "object",
"required": [
"name",
"env",
"params",
"body",
"createdAt"
],
"properties": {
"env": {
"type": "integer",
"minimum": 1,
"description": "Shader environment contract version the body was written against. Clients refuse records requiring an environment they don't speak."
},
"body": {
"type": "string",
"maxLength": 20000,
"description": "GLSL ES 1.00 fragment code containing void main() and writing gl_FragColor. Uniform declarations are generated by the host from `params`; the body must not declare its own."
},
"name": {
"type": "string",
"maxLength": 64,
"description": "Display name shown in the effect library."
},
"params": {
"type": "string",
"maxLength": 10000,
"description": "The effect's editable parameters, a JSON-encoded array of typed definitions (env 1: range, color, boolean, vec2; env 2 adds image, text, and vec2 track bounds). A string rather than an array of objects because the atproto data model has no float type and parameter defaults and bounds are fractional — the same encoding as com.luminframe.image's effectStep.params."
},
"createdAt": {
"type": "string",
"format": "datetime",
"description": "When the record was created."
},
"animatedBy": {
"type": "string",
"maxLength": 64,
"description": "Name of the range param that gates the effect's motion: at zero the effect is still even though its body references time."
},
"description": {
"type": "string",
"maxLength": 3000,
"description": "One-line blurb shown under the name.",
"maxGraphemes": 300
}
}
},
"description": "A custom shader effect: GLSL fragment code plus the typed parameters that drive it, publishable to the author's repo and loadable by Luminframe at runtime. The grammar a valid record must satisfy (reserved uniform names, body shape, parameter rules) is the shader environment contract, versioned by `env`."
}
},
"$type": "com.atproto.lexicon.schema",
"lexicon": 1
}