# headsta.sh > headsta.sh is a shop and community for VJ / visual-artist tools: shader > plugins for Resolume (FFGL), Synesthesia, and Wire, plus a free in-browser > ISF shader editor and a public library of ISF shaders. Note for AI agents: welcome. The read API below is open, no auth, no key. Writing (publishing shaders, posting) requires an account. Sign-in is a magic-link email, so bootstrap with your human operator's help; once signed in, mint yourself a personal API key with POST /api/auth/keys ({ "name": "my key" } → returns the key once) and send it on requests as `Authorization: Bearer hs_…` — it works everywhere a signed-in session does, and you can list (GET /api/auth/keys) and revoke (DELETE /api/auth/keys/{id}) your keys yourself. Your human operator can do the same from https://www.headsta.sh/account/keys. Publishing a shader means saving it as a plugin (POST /api/product/add), which additionally needs write access on the account — if yours doesn't have it, or you can't complete the email flow, a human can paste your shader at https://www.headsta.sh/plugin/new and save it from their account, or ask on the forum. Once authenticated, interactive OpenAPI docs covering every endpoint available to you are at https://www.headsta.sh/api/docs (anonymous visitors get a 404). ## Site map - Shop / plugins: https://www.headsta.sh/shop - Shader editor (ISF, runs in browser): https://www.headsta.sh/plugin/new - Docs: https://www.headsta.sh/docs - Community forum: https://www.headsta.sh/community - Guides: https://www.headsta.sh/guide - Changelog: https://www.headsta.sh/changelog - Sign in / sign up: https://www.headsta.sh/account/sign-in - API keys (signed in): https://www.headsta.sh/account/keys ## Contact / reaching us There is no contact form. To reach us (or the community), sign up and post on the forum at https://www.headsta.sh/community/forum. Accounts are created with a magic link, so signing up requires a working email address — if you are an agent without one, ask your human operator to sign up and post on your behalf. ## Open read API (no auth) Base URL: https://www.headsta.sh/api ### ISF shader library - POST /api/isf/search JSON body (all fields optional): { "query": "text", "shaderType": "", "categories": "a,b", "user": "username", "featured": true, "sort": "newest|updated|title|stars", "sortField": "", "sortDir": "asc|desc", "from": 0, "num": 25 } # num max 100 Returns { totalResults, results[], page, pageSize, totalPages }. - GET /api/isf/{id} — one shader, full ISF fragment source - GET /api/isf/random — a random public shader - GET /api/isf/types — valid shaderType values - GET /api/isf/categories — all category tags in use ### Products - GET /api/product — list products (params: s=skip, l=limit, sort) - GET /api/product/{id} — one product Rate limits apply (roughly 50 req/min per IP). Be polite; paginate instead of scraping in a tight loop. ## Shader format: ISF (Interactive Shader Format) Everything in the library is ISF: a GLSL fragment shader carrying a structured JSON metadata block embedded in a leading comment. The JSON comment block must be the first thing in the file; opening is /*{ and closing is }*/ — the braces are part of the JSON object. Everything after }*/ is standard GLSL. All user-controllable inputs are declared in the "INPUTS" array, and uniform declarations for all inputs are automatically injected — do NOT declare them in GLSL yourself. Example — abridged from "Equirectangular", one of our own plugin shaders: /*{ "TITLE": "Equirectangular", "CREDIT": "Shady Headstash", "DESCRIPTION": "Smoothly switch between 3D and 2D perspective using Equirectangular projection.", "INPUTS": [ { "NAME": "perspective", "TYPE": "float", "MIN": 0, "MAX": 1, "DEFAULT": 1 }, { "NAME": "zoom", "TYPE": "float", "MIN": 0, "MAX": 1, "DEFAULT": 0.5 }, { "NAME": "look_X", "TYPE": "float", "MIN": 0, "MAX": 2, "DEFAULT": 1 }, { "NAME": "look_Y", "TYPE": "float", "MIN": 0, "MAX": 2, "DEFAULT": 1 }, { "NAME": "inputImage", "TYPE": "image" } ] }*/ const float PI = 3.14159265359; #define TWPI 6.283185307179586 vec2 _rotate(vec2 v, float t) { mat2 T = mat2(cos(t), -sin(t), sin(t), cos(t)); return T*v; } void main() { vec2 _uv = isf_FragNormCoord.xy; vec2 _xy = _uv * RENDERSIZE.xy; vec2 _uvc = _xy / RENDERSIZE.y - vec2(RENDERSIZE.x/RENDERSIZE.y/2., 0.5); vec2 v = (_uv + RENDERSIZE.y) - 0.5; float th = v.y * PI, ph = v.x * TWPI; vec3 sp = vec3(sin(ph) * cos(th), sin(th), cos(ph) * cos(th)); vec3 pos = vec3(PI, 0, 0); pos *= mix(0.25+(1.0-zoom)*4., 0.25+(1.0-zoom)*2., perspective) * 0.1; sp = mix(sp, normalize(vec3(_uvc, 1.0)), 1.0-perspective); sp.yz = _rotate(sp.yz, look_Y*PI); sp.xy = _rotate(sp.xy, look_X*PI); vec2 nUv = vec2(dot(pos, sp.zxy), dot(pos.yzx, sp.zxy)) - 0.5; gl_FragColor = IMG_NORM_PIXEL(inputImage, mod(nUv, 1.0)); } Note how each name in the INPUTS header ("perspective", "zoom", "look_X", "inputImage", …) is read directly in the code as a uniform of the matching type, and image inputs are sampled with IMG_NORM_PIXEL rather than texture2D. Implement void main() and assign your final colour to gl_FragColor. The varying isf_FragNormCoord gives the normalized fragment coordinate [0,1]² with (0,0) at bottom-left — equivalent to gl_FragCoord.xy / RENDERSIZE. Uniforms automatically provided by the host (do not declare these yourself): TIME (float — elapsed seconds since render start), TIMEDELTA (float — time since the previous frame), FRAMEINDEX (int — frame counter starting at 0), RENDERSIZE (vec2 — output dimensions in pixels), DATE (vec4 — year, month, day, secondsSinceMidnight), and PASSINDEX (int — 0-based pass index in multi-pass shaders). Each "INPUTS" entry needs at minimum NAME (the GLSL uniform variable name) and TYPE. Types map to uniforms as: "float" → float, "bool" → bool, "event" → bool (momentary), "long" → int, "point2D" → vec2, "color" → vec4, "image" → sampler2D. Always use the IMG_* macros to sample image inputs — IMG_NORM_PIXEL(image, normCoord) for normalized [0,1] coords, IMG_PIXEL(image, pixelCoord) for pixel coords, IMG_THIS_NORM_PIXEL(image) for the current fragment — do not call texture2D directly. Full spec: https://github.com/mrRay/vvisf-gl/blob/master/ISF_Docs/ISF_Spec_v2.md ## License / usage Shaders in the library belong to their authors — check each shader's page before redistributing. These endpoints exist for exploration, remixing in the editor, and building integrations. For anything commercial or bulk, ask first — post on the forum: https://www.headsta.sh/community/forum