API
The public API
Basics
| Base | https://hoverlab5.netlify.app/api/v1 |
| Auth | None. Do not send credentials. |
| CORS | Open (*) — callable from a browser |
| Methods | GET and OPTIONS |
Endpoints
Each tier has the same pair — a list endpoint that searches, and a detail endpoint that returns source. The five below them do not follow that shape, because none of them is a tier: they answer across the catalog rather than within one rung of it.
| Endpoint | Returns |
|---|---|
GET /api/v1/effects | Search effects — metadata only |
GET /api/v1/effects/{id} | One effect, with HTML + CSS |
GET /api/v1/blocks | Search blocks |
GET /api/v1/blocks/{id} | One block, with its source files |
GET /api/v1/pages | Search pages |
GET /api/v1/pages/{id} | One page, with its files |
GET /api/v1/templates | Search templates |
GET /api/v1/templates/{id} | One template, with every file |
GET /api/v1/artifacts/{id} | Resolves an id against all four tiers — use this when you do not know the tier |
GET /api/v1/dna/{id} | Design DNA — the tokens and rules as a document for an AI tool. Takes any id, or "catalog" |
GET /api/v1/skills | The agent skills this catalog publishes |
GET /api/v1/skills/{id} | One skill; add ?format=raw for the markdown itself |
GET /api/v1/kits | The curated cross-tier sets; add ?slug= for one kit’s full contents and its install line |
GET /api/v1/trending | What has actually been copied and installed this week. Empty is a normal answer |
GET /api/v1/revisions | What changed and when, per artifact — the update ledger behind the changelog |
Searching
| Param | Meaning |
|---|---|
q | Free-text query over name, category, description and tags |
category | Restrict to one category |
featured=true | Only curated, hand-written entries |
limit | Page size |
offset | Page offset |
curl "https://hoverlab5.netlify.app/api/v1/blocks?q=pricing&limit=5"
curl "https://hoverlab5.netlify.app/api/v1/effects?category=Buttons&featured=true"Fetching source
Detail responses carry the files at the paths they should be written to, so a client can write them out without knowing anything about the tier it asked for.
curl "https://hoverlab5.netlify.app/api/v1/artifacts/pricing-tiers"{
"version": "v1",
"level": "block",
"artifact": { "id": "pricing-tiers", "name": "…", "fileCount": 1, … },
"files": [
{ "path": "components/pricing-tiers.tsx", "lang": "tsx", "source": "…" }
],
"deps": ["lucide-react"],
"notes": ["…"],
"included": []
}Add deep=true to a page or template to pull in everything it is composed of — the ids that came along appear in included.
curl "https://hoverlab5.netlify.app/api/v1/pages/checkout-page?deep=true"Effects in other frameworks
An effect is markup plus a stylesheet, so it can be handed to any framework without losing anything. Pass framework to the effect detail endpoint.
curl "https://hoverlab5.netlify.app/api/v1/effects/btn-gradient?framework=vue"Valid values: html, css, react, vue, svelte, styled-components, tailwind. The customization knobs work here too — hue, sat, scale, speed.
Motion-safety profile
Every effect response carries a motion object: four checks on the effect's shipped CSS, computed for the whole catalog and re-verified at build. It is the same data as the panel on the effect page.
curl "https://hoverlab5.netlify.app/api/v1/effects/btn-gradient" | jq .motion{
"applicable": true,
"animates": true,
"reducedMotion": "brief",
"propertyClass": "paint",
"offending": ["background-position", "box-shadow"],
"flash": { "verdict": "pass", "hz": null },
"layoutShift": "none"
}| Field | Values |
|---|---|
reducedMotion | guarded ships a prefers-reduced-motion block; brief animates but does not loop, so no guard ships; unguarded loops with no guard; none does not animate. The same predicate the catalog's motion audit uses. |
propertyClass | Worst wins: compositor (transform, opacity, filter), paint (colour, background, shadow, clip-path), layout (width, height, top/left, margin, padding), none. offending lists the non-compositor properties, layout ones first. |
flash | verdict is pass, caution or fail against WCAG 2.3.1 (three flashes a second). hz is the highest estimated rate, or null when nothing alternates brightness. fail needs a repeating change above 3 Hz that is both strong and plainly large. |
layoutShift | shifts when propertyClass is layout, otherwise none. A category, not a number. |
measured | Present only on the effects that were run in Chromium: cls, entries and the windowSeconds it covers. The only numeric layout-shift figure in the response. |
measured is a static estimate read from the CSS text, not a rendering test. The flash rate is an upper bound from duration, iterations and keyframe alternation, and it does not know what is behind the effect. The profile describes the effect as published; the speed knob retimes it, so recheck a customized copy. Canvas and WebGL effects return { "applicable": false, "reason": "…" }, and effects that are not in the catalog return null.Blocks outside React
There is no framework param for blocks, and that is deliberate. A block is hundreds of lines of React with hooks and event handlers; a machine translation of it would be a worse block claiming to be the same one.
What you can have is the block rendered to HTML. Tailwind classes are framework-agnostic, so the design transfers intact even though the component does not.
curl "https://hoverlab5.netlify.app/api/v1/blocks/pricing-tiers?format=html"notes array says so on every response.Caching
An effect id always resolves to the same CSS, so those responses are cacheable indefinitely. Block, page and template source is hand-written and gets fixed, so it carries a shorter edge cache — an accessibility fix should reach the next install, not a year later.
Something wrong or missing here? Browse the catalog — every page in it links back to the source it documents.