design-library
README.md
# design-library-mcp
A local, free, open-source design-reference library with two faces:
- a **web gallery** at http://127.0.0.1:8000 where you browse, search, preview and curate references, and
- an **MCP server** that Claude queries, so UI work starts from references you chose on purpose
instead of generic defaults.
Everything runs on your machine. No API keys, no paid services, no cloud.
```
library/entries/*.json ──► library/index.db (SQLite + FTS5) ──► CLI · web gallery · MCP server
source of truth library/vectors.db (sqlite-vec) one shared `core` package
rebuildable caches
```
Search is **hybrid**: keyword matching (FTS5) merged with **semantic** matching, so
"spinner while waiting" finds a loader and "choose a plan" finds pricing tables even with no
shared words. The meaning model (`all-MiniLM-L6-v2`) runs locally on your CPU.
---
## 1. Install (once)
Needs Python 3.11+ and [uv](https://docs.astral.sh/uv/) (free, open source).
```powershell
python -m pip install --user uv
cd "C:\path\to\design-library-mcp"
python -m uv sync # creates .venv and installs everything (incl. semantic search)
python -m uv run python -m designlib rebuild # builds the search index + meaning vectors
python -m uv run pytest -m "not slow" # optional: tests, about 8 seconds
```
The first `rebuild` (or first search) downloads the meaning model once: about 90 MB from
Hugging Face, free, no account. After that it works offline. Semantic search pulls in PyTorch
(CPU build, a few hundred MB). To install without it: `python -m uv sync --no-group semantic`;
search then uses keywords only and everything else works the same.
> `pip install --user` puts `uv` in `%APPDATA%\Python\Python3xx\Scripts`, which usually isn't on
> your PATH, so this README writes `python -m uv`. Add that folder to PATH to type `uv` instead.
## 2. Start the gallery
Double-click **`start.cmd`**, or in PowerShell:
```powershell
cd "C:\path\to\design-library-mcp"
.\start.ps1
```
Both open http://127.0.0.1:8000 in your browser. Stop with **Ctrl+C**.
If PowerShell says running scripts is disabled, use `start.cmd`, which doesn't need PowerShell.
The gallery only listens on `127.0.0.1`, so other devices on your network cannot reach it.
**You usually don't need to start it yourself:** while Claude is open, the MCP server also
serves the gallery, so the `gallery_url` links Claude gives you always open. If the gallery is
already running (started by Claude or by you), `start.cmd` just opens it in your browser.
## 3. Connect Claude
The MCP server is started by Claude itself. You never run it by hand. Both setups below use
the project's own Python (`.venv\Scripts\python.exe`), so they don't depend on PATH.
### (a) Claude desktop app (Windows)
1. Open the config file. In the app: **Settings → Developer → Edit Config**, or open it directly:
`%APPDATA%\Claude\claude_desktop_config.json`.
2. Add a `design-library` entry inside `"mcpServers"`, next to any servers already there:
```json
{
"mcpServers": {
"design-library": {
"command": "C:\\path\\to\\design-library-mcp\\.venv\\Scripts\\python.exe",
"args": ["-m", "designlib", "mcp"]
}
}
}
```
Replace `C:\\path\\to\\design-library-mcp` with the folder you cloned the repo into.
In JSON every backslash in a path is written twice (`\\`).
3. **Quit Claude completely** (system tray icon → Quit, not just closing the window) and reopen it.
4. In a new chat, open the tools/connectors menu: **design-library** should be listed with 6 tools.
### (b) Claude Code
```powershell
claude mcp add --scope user design-library -- "C:\path\to\design-library-mcp\.venv\Scripts\python.exe" -m designlib mcp
```
- `--scope user` makes it available in every project. Leave it out to add it only to the
current project.
- Check it: `claude mcp get design-library` should say **✔ Connected**. Inside Claude Code, `/mcp` lists it.
- Remove it: `claude mcp remove design-library -s user`
### Make Claude use it every time (optional)
Claude reads the server's built-in instructions, but a line in your global
`~/.claude/CLAUDE.md` makes it a habit in Claude Code:
```markdown
Before designing or building any UI, search the `design-library` MCP server
(search_designs, then get_design) and follow its style guide (list_styles / get_style_guide).
Say which references and style guide you used.
```
### Things to ask Claude
- "Build a pricing section for my app. Check my design library first."
- "What toggles do I have saved? Show me the one I rated highest."
- "Use my *quiet-product* style guide to restyle this settings page."
- "Save https://example.com/some-landing-page to my design library as a screen, tagged hero, saas."
## 4. The MCP tools
| Tool | Use |
|---|---|
| `search_designs(query, type?, tags?, framework?, platform?, category?, limit=10, mode="hybrid")` | Ranked matches (no code) with `gallery_url`, platform and categories for each. `mode="keyword"` = exact words only |
| `list_categories(platform?)` | The category sidebar as data: groups, categories, counts (optionally for one platform) |
| `get_design(id)` | The full entry: code (when the license allows), style notes, when to use / avoid, license, `gallery_url` |
| `list_tags()` | Tags and how many entries use each |
| `list_styles()` | Your style guides in `library/styles/` |
| `get_style_guide(style)` | One guide's rules (palette, type, spacing, do/don't) |
| `add_design(url, type, tags?, notes?)` | Save a page as a link-only reference (metadata only) |
`gallery_url` (http://127.0.0.1:8000/d/<id>) opens whenever Claude or `start.cmd` is running:
the MCP server serves the gallery in the background if port 8000 is free. With several Claude
sessions, the first one serves it; if that one closes, another takes over within 30 seconds.
To turn this off, set the environment variable `DESIGNLIB_GALLERY_WITH_MCP=0`.
### How semantic search behaves
- The gallery and the MCP server load the model **in the background** when they start
(importing PyTorch takes ~10 s). Until then, searches use keywords only, so the gallery's
live search never waits. Once ready, the result count says *matched by meaning and keywords*.
Claude's searches wait for the model, so they always include meaning.
- Each entry's title, type, tags, notes, style notes and when to use / avoid are embedded.
Code is left out on purpose (class names would drown the description).
- New or edited entries are embedded automatically before the next semantic search. Only
entries whose text changed are re-embedded; toggling a favorite costs nothing.
- Results from both methods are merged with Reciprocal Rank Fusion: an entry found by both
keywords and meaning ranks highest. Matches weaker than a cosine distance of 0.75 are dropped.
- Turn it off without uninstalling: set the environment variable `DESIGNLIB_SEMANTIC=0`.
## 5. Command line
```powershell
python -m uv run python -m designlib <command>
```
| Command | Example |
|---|---|
| `add` | `add https://godly.website --type style --tags bold,editorial --notes "big type" --rating 4` |
| `list` | `list --type component --limit 20` |
| `search` | `search pricing table --tags saas --framework tailwind` (add `--keyword` for exact words only) |
| `rebuild` | `rebuild` (recreate `index.db` from the JSON files, embed new/changed entries) |
| `dedupe` | `dedupe` (list duplicates), `dedupe --apply` (merge them: keep one, combine tags) |
| `categorize` | `categorize` (sort new entries), `categorize --force` (redo all after editing the taxonomy), `--no-meaning` (rules only) |
| `serve` | `serve --open` (`--port 8001`, `--reload` while developing) |
| `import` | `import all` (every code library), or one of: `hyperui` (`--dark`), `uiverse` (`--category buttons,cards`), `shadcn`, `magicui`, `flowbite`, `daisyui`, `tokens`, `icons`, `framework7`, `konsta`, `reactnative`, `nativeapps`, `saaslandingpage`, `designprompts`, `collectui`, `penpot`, `guidelines`. Default: everything; `--limit N` for a sample |
| `mcp` | Used by Claude; waits silently for a client |
`add` options: `--title`, `--framework`, `--rating 1-5`, `--favorite`, `--no-fetch` (don't contact the site).
## 6. Your library
About 10,000 references from 17 sources: full open-source component libraries (with code
Claude Code can use or install directly) plus link-only inspiration galleries. The full
list, licenses and how each was collected are in [`library/sources.md`](library/sources.md).
| Kind | Sources |
|---|---|
| Live-preview code (HTML/Tailwind) | HyperUI, Uiverse, Flowbite, daisyUI |
| React code + install command | shadcn/ui, Magic UI |
| Tokens and color scales | Open Props, Radix Colors |
| Icon sets (searchable by icon name) | Lucide, Heroicons |
| Link-only inspiration | SaaS Landing Page, DesignPrompts, Collect UI, plus hand-picked pages |
| Mobile apps | Framework7 (live iOS/Material phone screens), Konsta UI, React Native Paper, react-native-reusables, Android Compose samples, Flutter templates, Penpot kits |
| Official guidelines and kits | Material Design 3, Apple Human Interface Guidelines, Apple and Wear OS Figma kits |
- **Entries**: `library/entries/<id>.json`, one file per reference. Edit them in the gallery
(or by hand, then run `rebuild`). Commit them with git like any other file.
- **Screenshots**: uploaded in the gallery, stored in `library/assets/mine/`.
- **Style guides**: add `library/styles/<name>.md`. The first paragraph becomes the summary
Claude sees in `list_styles`. Start from `quiet-product.md`.
- **Sources**: `library/sources.md` lists every source, its license, and whether code may be stored.
An entry has: `id, title, source, url, license, type (style|component|screen|interaction|layout|palette|token),
tags, framework (html|tailwind|react|none), style_notes {palette, fonts, spacing, mood}, notes, code, prompt,
preview_image_url, local_image, when_to_use, avoid_when, my_rating (1-5), favorite, added_at, updated_at`.
### The rules it enforces
- **Code is only stored for MIT, Apache-2.0, ISC or your own work (`Own`).** The schema rejects anything else,
whether it comes from the CLI, the gallery or Claude.
- **Gallery and inspiration sites are link only**: URL, title, tags, your notes, and the og:image *URL*
(shown as a hotlink with no referrer). Their images and content are never downloaded.
- **Fetching is polite**: checks `robots.txt`, sends an honest User-Agent, waits 2 s between requests to
the same site, reads at most 1 MB, and only reads metadata.
- **Importers verify the repo's LICENSE file** before reading anything, and stop if it isn't open.
### No duplicates
Two entries count as the same resource when they have the same link **and** the same content
(the same code, or the same preview image). Every import and `add` skips anything already in
the library (`add` tells you which entry already has it), and `designlib dedupe` finds and
merges older duplicates. Same link alone isn't a duplicate: a library's docs page can show
several different examples, and one post can have several images.
### Categories and platforms
Every reference is sorted two ways, like Collect UI's sidebar:
- **Platform**: Web, Mobile, Desktop, or *Any platform* (icons, colors, logos, and shots that
don't say). Tabs at the top of the gallery.
- **Category**: what it is, in five groups (left sidebar):
- *Pages & sections*: landing/home page, hero, navigation, footer, call to action, features,
pricing, testimonials, FAQ, blog, about, contact, logo cloud, stats, newsletter, 404, ...
- *App screens*: dashboard, login & sign up, onboarding, settings, profile, checkout,
e-commerce, chat, inbox, calendar, tables, charts, empty states, search, AI interfaces, ...
- *Components*: buttons, cards, forms, toggles, selects, modals, tooltips, tabs, accordions,
alerts, badges, avatars, loaders, pagination, carousels, timelines, layouts, menus, ...
- *Motion & effects*: animations, hover effects, text effects, scroll animations,
backgrounds, 3D/WebGL
- *Style & brand*: design styles, branding & logos, illustrations, typography, colors,
icons, design tokens
An entry can be in up to three categories (best match first). Sorting is automatic:
each tag and title word is looked up in [`core/taxonomy.py`](src/designlib/core/taxonomy.py),
web code counts as Web, and `mobile-app` / `mac-app` style tags decide Mobile / Desktop. When
the rules can't tell, `designlib categorize` asks the local meaning model, but only accepts
answers it was measured to get right 96%+ of the time; everything else stays *Any platform*.
To change a single entry, open it, choose Edit, and tick its categories and platform: your
choice is kept from then on. To change the scheme, edit `core/taxonomy.py` and run
`python -m uv run python -m designlib categorize --force`.
## 7. Project layout
```
design-library-mcp/
start.cmd / start.ps1 / start.sh start the gallery
pyproject.toml, uv.lock dependencies
docs/testing.md tests + MCP Inspector walkthrough
library/ YOUR DATA (entries, assets, styles, sources.md)
src/designlib/
config.py paths, 127.0.0.1:8000
cli.py the command line
core/ schema, storage, index, search, semantic, fetch, library, styleguide
web/ FastAPI app, Jinja templates, CSS/JS, vendored assets
importers/ hyperui.py, uiverse.py, common.py
mcp_server.py the MCP tools
tests/ pytest suite
```
## 8. Troubleshooting
| Problem | Fix |
|---|---|
| Claude desktop doesn't show design-library | Fully quit and reopen the app. Check the JSON is valid (doubled backslashes, commas). Logs: `%APPDATA%\Claude\logs\mcp-server-design-library.log` |
| `claude mcp get` says failed | Run `"C:\path\to\design-library-mcp\.venv\Scripts\python.exe" -m designlib mcp` yourself: it should sit silently. Any error it prints is the cause |
| `.venv` missing or broken | `python -m uv sync` |
| Search misses something you just edited by hand | `python -m uv run python -m designlib rebuild` |
| Gallery never says "matched by meaning" | Check `python -m uv run python -c "from designlib.core import semantic; print(semantic.enabled())"` prints True; run `rebuild` once to download the model |
| Semantic search acting strange | Delete `library/vectors.db`; it is rebuilt on the next search |
| A `gallery_url` link doesn't open | Is Claude (or `start.cmd`) running? The gallery lives as long as one of them does. After updating this project, restart Claude (desktop: tray → Quit; Claude Code: `/mcp` → reconnect) so it runs the new code |
| Port 8000 used by another program | Set the environment variable `DESIGNLIB_PORT=8001` (for Claude too: add `"env": {"DESIGNLIB_PORT": "8001"}` to the desktop config entry), or run `serve --port 8001` |
| Test the tools interactively | See [docs/testing.md](docs/testing.md) (MCP Inspector) |
## Credits and licenses
This project: MIT (see `LICENSE`). Third-party files stored in the project (`src/designlib/web/static/vendor/`),
each with its license file: htmx 2.0.4 (0BSD), Tailwind CSS browser build 4.1.11 (MIT),
highlight.js 11.10.0 (BSD-3-Clause), Familjen Grotesk font (SIL OFL 1.1).
Semantic search uses sentence-transformers (Apache-2.0), sqlite-vec (MIT/Apache-2.0) and the
all-MiniLM-L6-v2 model (Apache-2.0), downloaded at first use rather than stored in the repo.
Imported components keep their source's license (HyperUI: MIT, Uiverse: MIT) and a link to the
original file in each entry.