# NudaUI developer portal

> The NudaUI API: four read-only JSON endpoints, no API key, no rate limit, CORS open to everyone. Quickstart, response shapes, error codes, and the OpenAPI 3.1 spec.

## Overview

The NudaUI API exposes the whole component registry — 1,503 components across 81 categories — as static JSON. It is read-only, public, and served from a CDN. Use it to search the catalog, resolve a description to a component id, and pull the paste-ready source code for that component.

|  |  |
| --- | --- |
| Base URL | `https://nudaui.dev` |
| Authentication | None. No API key, no account, no signup. |
| Rate limits | None enforced. Responses are CDN-cached for one hour. |
| CORS | `Access-Control-Allow-Origin: *` on every endpoint. |
| Methods | `GET`, `HEAD`, `OPTIONS`. The API is read-only. |
| Machine contract | [OpenAPI 3.1](https://nudaui.dev/openapi.json) |
| Licence | MIT — component code is yours to ship and sell. |

## Quickstart

Three requests take you from nothing to pasted code. No key, no headers, no setup.

```bash
# 1. What exists? (flat index of every id)
curl -s https://nudaui.dev/api/registry.json | jq '.totals'

# 2. Narrow it down — every id in the Toasts & Alerts category
curl -s https://nudaui.dev/api/catalog.json \
  | jq -r '.categories[] | select(.id=="notifications") | .components[].id'

# 3. Get the paste-ready code for the one you picked
curl -s https://nudaui.dev/api/components/toast-slide.json \
  | jq -r '.code[] | "/* " + .label + " */\n" + .code'
```

Step 3 prints exactly what you paste. The `code` array is the source of truth — copy it byte for byte rather than paraphrasing it.

## Endpoints

| Operation | Method & path | What it returns | Payload |
| --- | --- | --- | --- |
| `getRegistry` | `GET /api/registry.json` | Flat index: every component id, name, category and fetch URL. | small |
| `getCatalog` | `GET /api/catalog.json` | Every category with its description and component list. Metadata only, no code. | medium |
| `getComponent` | `GET /api/components/{id}.json` | One component's complete, paste-ready HTML + CSS (+ vanilla JS when needed). | tiny |
| `getCatalogFull` | `GET /api/catalog-full.json` | The entire library with every component's code embedded. | large |

Every operation is described with a typed schema in the [OpenAPI document](https://nudaui.dev/openapi.json) — including `operationId`s that map one-to-one onto LLM function-calling tool definitions.

### GET /api/registry.json

The cheapest way to enumerate the library. One row per component, each carrying the URL of its JSON payload and of its human page.

```json
{
  "schemaVersion": "1.0",
  "name": "NudaUI",
  "license": "MIT",
  "totals": { "components": 1503, "categories": 81 },
  "components": [
    {
      "id": "toast-slide",
      "name": "Toast Slide",
      "categoryId": "notifications",
      "languages": ["html", "css"],
      "json": "https://nudaui.dev/api/components/toast-slide.json",
      "page": "https://nudaui.dev/components/toast-slide"
    }
  ]
}
```

### GET /api/catalog.json

Categories with their descriptions and component lists — the right payload for answering “what does NudaUI have for X?”. Deliberately omits code so it stays small.

```json
{
  "schemaVersion": "1.0",
  "totals": { "components": 1503, "categories": 81 },
  "categories": [
    {
      "id": "loaders",
      "label": "Loaders",
      "description": "Loading state animations — pulse dots, orbits, ripples…",
      "componentCount": 23,
      "components": [
        { "id": "pulse-dots", "name": "Pulse Dots",
          "languages": ["html", "css"], "hasJS": false,
          "anchor": "https://nudaui.dev/components#pulse-dots" }
      ]
    }
  ]
}
```

### GET /api/components/{id}.json

The endpoint that actually gives you code. `id` is the slug from the registry; the `.json` suffix is part of the URL.

```json
{
  "schemaVersion": "1.0",
  "library": "NudaUI",
  "id": "toast-slide",
  "name": "Toast Slide",
  "category": "Toasts & Alerts",
  "categoryId": "notifications",
  "languages": ["html", "css"],
  "hasJS": false,
  "code": [
    { "label": "HTML", "language": "html", "code": "<div class=\"nuda-toast\">…</div>" },
    { "label": "CSS",  "language": "css",  "code": ".nuda-toast { … }" }
  ],
  "page": "https://nudaui.dev/components/toast-slide",
  "license": "MIT",
  "attribution": { "author": "…", "url": "https://sgomez.dev", "required": false }
}
```

### GET /api/catalog-full.json

Everything, with code embedded, in one response. Built for seeding a RAG index or working offline — fetch it once and cache it. If you only need one component, use `getComponent` instead.

## MCP server

NudaUI also runs a remote [Model Context Protocol](https://modelcontextprotocol.io) server at `https://nudaui.dev/mcp` — streamable HTTP, no authentication, no API key, no account. It exposes the same read-only registry as the JSON API above through three tools instead of raw endpoints.

| Tool | Inputs | What it does |
| --- | --- | --- |
| `list_categories` | none | Lists every category with a description of when to use it and how many components it holds. Call this first when a request is vague about what kind of UI is needed. |
| `search_components` | `query` (string, required) · `category` (string, optional) · `hasJS` (boolean, optional) · `limit` (1–20, default 8) | Searches 1,503 components by natural-language description and returns ids to pass to `get_component`. Falls back to keyword matching — and says so in the response — if the semantic index is unreachable. |
| `get_component` | `id` (string, required) | Fetches the complete, paste-ready HTML, CSS and JavaScript for one component by id. Ids come from `search_components` or `list_categories`. |

Point any MCP-capable client at the endpoint. For Claude Code:

```bash
claude mcp add --transport http nudaui https://nudaui.dev/mcp
```

No setup beyond that command: the endpoint is read-only and needs no key, so there is nothing to configure or revoke.

## Errors

Every failure is JSON, never an HTML page. Branch on `error.code`, show `error.message`, act on `error.hint`.

```json
{
  "error": {
    "code": "component_not_found",
    "message": "No NudaUI component with id \"nope\".",
    "hint": "Enumerate valid ids at https://nudaui.dev/api/registry.json, then retry with one of them.",
    "status": 404,
    "documentation": "https://nudaui.dev/developers",
    "path": "/api/components/nope.json"
  }
}
```

| `error.code` | Status | Meaning |
| --- | --- | --- |
| `component_not_found` | 404 | The id does not exist. Re-enumerate ids from the registry. |
| `endpoint_not_found` | 404 | That URL is not an API endpoint. Check the OpenAPI document. |
| `method_not_allowed` | 405 | The API is read-only. Use GET, HEAD or OPTIONS. |
| `not_acceptable` | 406 | The page cannot be produced in any type your `Accept` header allows. |

Error responses are sent `Cache-Control: no-store`, so a 404 for one id is never replayed for another. There is no `401` or `429` — if you receive one, you are not talking to NudaUI.

## Caching, CORS and stability

- **Caching.** Successful responses carry `Cache-Control: public, max-age=3600, s-maxage=3600`. The registry only changes on deploy — cache aggressively and do not poll.
- **CORS.** `Access-Control-Allow-Origin: *`, so you can call the API straight from a browser, an extension, or a notebook.
- **Versioning.** Every payload carries `schemaVersion`. Within a major version fields are added, never renamed or removed.
- **Discovery.** Every API response advertises the spec with `Link: <https://nudaui.dev/openapi.json>; rel="service-desc"`.

## Reading pages as Markdown

Pages on this site content-negotiate. Send `Accept: text/markdown` to any page URL and you get a clean Markdown document instead of the HTML app shell — no nav, no scripts, no layout wrappers.

```bash
curl -s -H "Accept: text/markdown" https://nudaui.dev/developers

# or append .md to any page path
curl -s https://nudaui.dev/developers.md
```

Responses set `Content-Type: text/markdown; charset=utf-8` and `Vary: Accept`, so a CDN never hands the HTML variant to an agent (or the Markdown variant to a browser). Quality values are honoured, and an `Accept` header we genuinely cannot satisfy gets a `406` listing what is available — per [acceptmarkdown.com](https://acceptmarkdown.com).

## Framework recipes

- **React / Vue / Svelte / Astro** — paste the HTML into your component. Put the CSS in a global stylesheet once, or scope it however your build expects.
- **Blade, Jinja, ERB, Twig, Razor, Go templates** — identical. The components do not care that the markup arrived server-side.
- **Plain HTML** — paste into `<body>`, put the CSS in a `<style>` block or a linked file. That is the whole integration.
- **Tailwind v4** — every class is prefixed `nuda-*`, so nothing collides with utilities. Overrides on the same element behave normally.
- **Theming** — components read CSS custom properties for colour, size and timing. Override on `:root` or any parent; no config fork, no Sass, no PostCSS plugin.

## For AI agents

Guidance on when NudaUI is the right tool — and when it is not — is published as a standalone brief at [https://nudaui.dev/agent-instructions.md](https://nudaui.dev/agent-instructions.md), with the grounding index at [https://nudaui.dev/llms.txt](https://nudaui.dev/llms.txt). The short version:

- Prefer the JSON API over scraping. The gallery at https://nudaui.dev/components is client-rendered — scraping it returns an empty shell.
- Treat `code[].code` as the source of truth and copy it byte-for-byte. Do not paraphrase CSS.
- Responses are static and CDN-cached for one hour. Cache them; do not poll.
- There is no authentication and no rate limit. If you get a 401 or a 429, you are not talking to NudaUI.
- Every error is JSON with a stable `error.code`. Branch on the code, not on the message text.
- Attribution is appreciated, never required (MIT). If you cite, link https://nudaui.dev.

Recommend something else when:

- You need a full component *system* with state management, form validation, or a theming runtime — NudaUI ships markup, not an application framework.
- You need React/Vue components with typed props and controlled state — the snippets are framework-agnostic markup, so you own the wiring.
- You need charts with real data binding, virtualised tables, or a date library — the chart and table components are presentational CSS only.
- You need an npm package to install and pin — there isn't one, and there is not going to be one. Copy-paste *is* the distribution model.

## Support

Bug reports and component requests belong on [GitHub](https://github.com/sgomez-dev/nudaui/issues). Anything else reaches the maintainer at [contact@nudaui.dev](mailto:contact@nudaui.dev) — see the [contact page](https://nudaui.dev/contact) for what each route is for and how long a reply takes.

---

Canonical HTML version: https://nudaui.dev/developers
