noslopui 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/SKILL.md +304 -299
- package/dist/index.js +1 -1
- package/dist/lib/version.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -61,7 +61,7 @@ Anything else that speaks MCP over HTTP can be connected by hand — add `https:
|
|
|
61
61
|
|---|---|
|
|
62
62
|
| `npx noslopui search <query>` | Search UI blocks and Motion Lab effects (`--section ui-blocks\|motion-lab`, `--tag style:editorial`, `--limit`) |
|
|
63
63
|
| `npx noslopui get <id>` | Print a component's code, or `--write src/Hero.tsx` (`--format tsx\|html\|vue`) |
|
|
64
|
-
| `npx noslopui prompt <id>` | Print a component's
|
|
64
|
+
| `npx noslopui prompt <id>` | Print a ready-to-paste prompt with a component's code |
|
|
65
65
|
| `npx noslopui design-systems [query]` | Search design systems (`--tag theme:dark`) |
|
|
66
66
|
| `npx noslopui design-system <id>` | Print a DESIGN.md, or `--write DESIGN.md` |
|
|
67
67
|
| `npx noslopui collections` | Your saved collections |
|
package/SKILL.md
CHANGED
|
@@ -3,11 +3,11 @@ name: noslopui
|
|
|
3
3
|
description: Build a stunning, non-generic UI using noslopUI's hand-crafted catalog over MCP — either from a collection the user curated themselves, or by choosing one Design System and applying it consistently across every component. Use when asked to build a landing page, dashboard, marketing site, or any new page/section from scratch, when the user mentions a noslopUI collection, or when a UI you're building looks like "AI slop" (gradient text, purple-on-purple, bounce easing, everything centered) and needs a real design system instead.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# noslopUI
|
|
7
|
-
|
|
8
|
-
You have access to the **noslopUI MCP server** — a catalog of hand-crafted (not
|
|
9
|
-
AI-generated) UI components, full page examples, and portable Design Systems.
|
|
10
|
-
|
|
6
|
+
# noslopUI
|
|
7
|
+
|
|
8
|
+
You have access to the **noslopUI MCP server** — a catalog of hand-crafted (not
|
|
9
|
+
AI-generated) UI components, full page examples, and portable Design Systems.
|
|
10
|
+
|
|
11
11
|
## The rules
|
|
12
12
|
|
|
13
13
|
1. **Choose one design system before fetching any component, then restyle every component to it** — colours, type scale, spacing, radius, motion. One system applied everywhere is what stops a multi-page build reading as a collage.
|
|
@@ -17,298 +17,303 @@ AI-generated) UI components, full page examples, and portable Design Systems.
|
|
|
17
17
|
5. **A collection existing is not the same as the user asking for it.** `list_collections` is free to call, but only build from what it returns when the user asked for their saved items by name or in substance, or confirmed it when you asked. The default "Favorites" list is just where the save button drops a single item with zero setup — a lone design system sitting in it is not a decision to build the whole thing around. One collection with content and no explicit ask → surface it as a question, don't assume either answer. Nothing confirmed → shortlist two or three design systems with `search_design_systems` and let the user pick.
|
|
18
18
|
6. **If a gated tool says the trial has ended or the fair-use limit is reached, tell the user and stop** — don't retry, and don't swap in something generated from scratch.
|
|
19
19
|
7. **A Motion Lab effect is a signature moment, not a section.** Reach for one (`search_components` with `section: "motion_lab"`) when the user asks for an effect, motion, 3D or a showpiece, or the brief clearly calls for one — then use one per page unless they ask for more. Recolour it through its `colorVars` to the design system's tokens, follow its `usage`, and keep its reduced-motion fallback.
|
|
20
|
-
|
|
21
|
-
Setup, if the noslopUI tools aren't available: the user runs
|
|
22
|
-
`npx noslopui@latest init`, or adds `https://noslopui.com/api/mcp` in their
|
|
23
|
-
agent and signs in when it asks (steps for each agent: `noslopui.com/mcp`).
|
|
24
|
-
Every call runs as the user's account. Search, metadata and collections are
|
|
25
|
-
free on every account. Code, prompts and DESIGN.md files need a paid plan or
|
|
26
|
-
the account's free 3-day trial, which the first such call starts.
|
|
27
|
-
|
|
28
|
-
---
|
|
29
|
-
|
|
30
|
-
## Step 0 — Which path?
|
|
31
|
-
|
|
32
|
-
**Call `list_collections` first.** It's free on every account. But a
|
|
33
|
-
collection existing is not the same as the user asking you to build from it —
|
|
34
|
-
the default "Favorites" list is just where the save button puts a single item
|
|
35
|
-
with zero setup, so a design system sitting there alone is very often a saved
|
|
36
|
-
reference, not a decision. Don't let its mere presence override what the user
|
|
37
|
-
actually asked for.
|
|
38
|
-
|
|
39
|
-
- The user already said to use their saved items ("build from my collection",
|
|
40
|
-
"use what I've saved", names a list by name) → **Path A**, no need to ask.
|
|
41
|
-
- Nothing was said either way, but exactly one collection has content that
|
|
42
|
-
looks relevant → **ask**: name what's in it and let them choose Path A or
|
|
43
|
-
Path B. Don't assume silently in either direction.
|
|
44
|
-
- No collection, or nothing in any of them fits → **Path B**.
|
|
45
|
-
- Several collections and no obvious match → ask which one. Don't guess
|
|
46
|
-
between two curated sets.
|
|
47
|
-
|
|
48
|
-
---
|
|
49
|
-
|
|
50
|
-
## Step 1 — Requirements, including brand
|
|
51
|
-
|
|
52
|
-
Do this on both paths, before choosing a system. Two groups of things.
|
|
53
|
-
|
|
54
|
-
**The build:**
|
|
55
|
-
|
|
56
|
-
1. **Purpose** — what is this for? (SaaS product, local service business,
|
|
57
|
-
portfolio, storefront, internal dashboard, docs site, …)
|
|
58
|
-
2. **Audience** — who is it for?
|
|
59
|
-
3. **Tone** — 2-3 words ("calm and minimal", "bold and playful", "editorial and
|
|
60
|
-
serif-driven", "warm and local"). This is what Step 2 matches against.
|
|
61
|
-
4. **Required sections** — the concrete list of what must exist.
|
|
62
|
-
|
|
63
|
-
**Their brand** — skip this and you ship a beautiful page that isn't theirs:
|
|
64
|
-
|
|
65
|
-
5. **Logo or wordmark** — do they have one, and in what format?
|
|
66
|
-
6. **Brand colours** — hex values if they have them, and whether they are fixed
|
|
67
|
-
(a franchise or a rebrand-in-progress changes the answer).
|
|
68
|
-
7. **Existing typeface** — anything already in use they need to stay with?
|
|
69
|
-
8. **Photography or illustration** — real assets to work from, or
|
|
70
|
-
placeholder-and-replace-later?
|
|
71
|
-
9. **An existing site or profile** to stay consistent with.
|
|
72
|
-
|
|
73
|
-
No brand at all → say so plainly and use the design system's own palette. Don't
|
|
74
|
-
invent a logo.
|
|
75
|
-
|
|
76
|
-
No real photography → don't ship a grey box. Use a seeded placeholder from
|
|
77
|
-
[Picsum](https://picsum.photos) — `https://picsum.photos/seed/<brand-slug>-<slot-name>/<w>/<h>`
|
|
78
|
-
— so the same build gets the same photo on every regenerate instead of a new
|
|
79
|
-
random one. Mark every one with `<!-- TODO: Replace with real photo, target
|
|
80
|
-
size <w>x<h> -->` immediately above it, and write alt text for the *intended*
|
|
81
|
-
subject ("Hand-poured ceramic mug, studio lighting"), not the placeholder
|
|
82
|
-
("Picsum image"), so it's already correct once they swap it in. Skip
|
|
83
|
-
photography altogether where the chosen design system's own register is
|
|
84
|
-
photo-free (type-led, editorial, most SaaS) rather than forcing a stock photo
|
|
85
|
-
in where the system doesn't call for one.
|
|
86
|
-
|
|
87
|
-
If the user already stated all this, don't re-ask — restate it in one line and
|
|
88
|
-
move on.
|
|
89
|
-
|
|
90
|
-
---
|
|
91
|
-
|
|
92
|
-
## Path A — the user curated a collection
|
|
93
|
-
|
|
94
|
-
`get_collection({ listId })` (or `name`). Every item carries a `kind` —
|
|
95
|
-
`design_systems`, `ui_blocks` or `motion_lab` (an effect) — plus a top-level
|
|
96
|
-
`designSystems` array and a `guidance` line. A saved effect is a pick like any
|
|
97
|
-
other: use it where it fits, restyled as in Step 3.
|
|
98
|
-
|
|
99
|
-
1. **The collection's design system wins.** One in it → that is the system, no
|
|
100
|
-
searching; `get_design_system_file` for its DESIGN.md. More than one → ask
|
|
101
|
-
which; they saved both deliberately. None → say so, choose one as in Path B,
|
|
102
|
-
and tell them which and why.
|
|
103
|
-
2. **Cover each required section from the collection first.** If the user saved
|
|
104
|
-
something that covers a section, use it. Always. **Never substitute a
|
|
105
|
-
catalog component for one they explicitly saved**, even if you found
|
|
106
|
-
something you think is better — that was their call, not an oversight.
|
|
107
|
-
3. **Fill the gaps with `search_components`, checked before you hand-build
|
|
108
|
-
anything.** Search the whole catalog on fit, and restyle what you find to
|
|
109
|
-
the collection's design system. Only build a gap section yourself if
|
|
110
|
-
nothing in the catalog fits it, and say so in step 4's report.
|
|
111
|
-
4. **Report what you filled in.** "Hero, pricing and footer from your
|
|
112
|
-
collection; you had no testimonial section saved, so I pulled one from the
|
|
113
|
-
catalog and restyled it." They should never have to diff the result to find
|
|
114
|
-
out what they didn't choose.
|
|
115
|
-
|
|
116
|
-
Continue to Step 3.
|
|
117
|
-
|
|
118
|
-
---
|
|
119
|
-
|
|
120
|
-
## Path B — you choose
|
|
121
|
-
|
|
122
|
-
### B1. Shortlist design systems, then ask
|
|
123
|
-
|
|
124
|
-
Design systems are classified by **tag**, not by category — there is no tree to
|
|
125
|
-
walk. Call `search_design_systems` with no arguments first if you don't know
|
|
126
|
-
what exists: it returns every system plus `availableTags`, the full filterable
|
|
127
|
-
vocabulary (`theme:`, `style:`, `industry:` and so on).
|
|
128
|
-
|
|
129
|
-
Then filter with `tags` (ANDed) and/or a free-text `query` built from the tone
|
|
130
|
-
words plus purpose:
|
|
131
|
-
|
|
132
|
-
```
|
|
133
|
-
search_design_systems({ tags: ["industry:hair-beauty"] })
|
|
134
|
-
search_design_systems({ tags: ["industry:dentist", "theme:light"] })
|
|
135
|
-
search_design_systems({ query: "calm minimal", tags: ["industry:saas"] })
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
`industry:` is a two-level tree, shaped like a template marketplace's: a
|
|
139
|
-
**field** (`food-drink`, `medical`, `home-services`, `technology`…) and, under
|
|
140
|
-
it, **niches** (`restaurant`, `dentist`, `roofing`, `saas`…). Every system
|
|
141
|
-
tagged with a niche is also tagged with its field, so start with the niche if
|
|
142
|
-
the brief names one and widen to the field when that returns fewer than three.
|
|
143
|
-
|
|
144
|
-
**"Local business" is not an industry — name the trade.** A plumber is
|
|
145
|
-
`home-services`, a barber `hair-beauty`, a café `food-drink`, a physio
|
|
146
|
-
`medical`, a yoga studio `wellness`, an accountant `professional-services`.
|
|
147
|
-
Each of those looks and reads differently, and filtering on the specific field
|
|
148
|
-
is what keeps two local businesses from getting the same site.
|
|
149
|
-
|
|
150
|
-
A system can carry several fields — a warm serif system serves a restaurant, a
|
|
151
|
-
wedding planner and a spa alike — so don't treat one tag as excluding the
|
|
152
|
-
others, and don't pick the same system for every brief in a field: read the
|
|
153
|
-
descriptions and match the tone the user described.
|
|
154
|
-
|
|
155
|
-
Every result comes back with its tags, its token summary (colours, fonts,
|
|
156
|
-
radius) and a `previewUrl`. **Present the 2-3 best matches to the user with
|
|
157
|
-
their names, one-line descriptions, palettes and preview URLs, and ask which
|
|
158
|
-
they want.** Don't pick silently. This single choice shapes every screen, it
|
|
159
|
-
costs one question, and the user has taste you cannot infer from "a roofing
|
|
160
|
-
business".
|
|
161
|
-
|
|
162
|
-
Then `get_design_system` on their pick for the ungated token summary, and
|
|
163
|
-
`get_design_system_file` for the full DESIGN.md.
|
|
164
|
-
|
|
165
|
-
If nothing matches well, say so and ask whether to go with the closest or with
|
|
166
|
-
a system they describe by hand — don't quietly fall back to stock Tailwind
|
|
167
|
-
defaults, which is the "AI slop" this workflow exists to avoid.
|
|
168
|
-
|
|
169
|
-
**Read the whole DESIGN.md before fetching any component.** It's short by
|
|
170
|
-
design — tokens plus a page or two of intent prose, meant to be held in context
|
|
171
|
-
for the entire build. Its **Do's and Don'ts** section is the part doing the real
|
|
172
|
-
work.
|
|
173
|
-
|
|
174
|
-
### B2. Find components on fit
|
|
175
|
-
|
|
176
|
-
**Never write a section's markup from scratch before checking the catalog.**
|
|
177
|
-
Having the DESIGN.md in hand is not the same as being done searching — for
|
|
178
|
-
*every* required section, call `search_components` first — `section` and
|
|
179
|
-
`tags` filters as needed, with `tags` ANDed the same way (`["style:editorial"]`,
|
|
180
|
-
`["animation:carousel"]`). Pick the best **structural** match: the thing that
|
|
181
|
-
actually does what the section needs. Largely ignore how it currently looks;
|
|
182
|
-
you are restyling it regardless. Only once nothing in the catalog fits a
|
|
183
|
-
section is hand-building it acceptable — and say so, don't pass it off as a
|
|
184
|
-
catalog pick.
|
|
185
|
-
|
|
186
|
-
Every result is published as React/TSX with Tailwind classes, whatever stack
|
|
187
|
-
the build target is. That's not a limitation — the markup and styling aren't
|
|
188
|
-
React-specific, so converting a result to plain HTML, Vue, or anything else is
|
|
189
|
-
a mechanical step (`className` to `class`, drop event-handler props, etc.),
|
|
190
|
-
not a rebuild. Never skip a structurally-right component, or conclude the
|
|
191
|
-
catalog has nothing for a non-React project, over its source format.
|
|
192
|
-
|
|
193
|
-
**Effects are a separate kind.** `section: "motion_lab"` searches Motion Lab:
|
|
194
|
-
shader backgrounds, 3D, liquid glass, text, cursor and scroll effects. An
|
|
195
|
-
effect isn't a section of the page — it's the one moment people remember the
|
|
196
|
-
page for. Use one where the brief asks for it (an effect, motion, 3D, "make it
|
|
197
|
-
pop") or clearly calls for a showpiece, and one per page unless the user asks
|
|
198
|
-
for more. `get_component` tells you how: `usage` says where it earns its
|
|
199
|
-
place, `props` are its knobs, `colorVars` are the CSS custom properties its
|
|
200
|
-
colours come from, and `libraries` are the exact npm packages and versions to
|
|
201
|
-
install.
|
|
202
|
-
|
|
203
|
-
Then `get_component_code` for the ones you'll use.
|
|
204
|
-
|
|
205
|
-
---
|
|
206
|
-
|
|
207
|
-
## Step 3 — Apply the system, and fit the brand into it
|
|
208
|
-
|
|
209
|
-
Two moves, in this order.
|
|
210
|
-
|
|
211
|
-
**A. Restyle everything to the design system.** Same colour variables, same type
|
|
212
|
-
scale, same radius, same spacing scale, same motion durations and easing, across
|
|
213
|
-
every component. Where a fetched component's own defaults conflict with the
|
|
214
|
-
system, the system wins — adapt the component, and never leave both looks in
|
|
215
|
-
play at once.
|
|
216
|
-
|
|
217
|
-
**B. Substitute the brand into the system's tokens.** This is what makes the
|
|
218
|
-
result *theirs* rather than a nice demo:
|
|
219
|
-
|
|
220
|
-
- Their primary colour replaces the system's `accent` token. A secondary, if
|
|
221
|
-
they have one, replaces a supporting token — not a second accent.
|
|
222
|
-
- Their wordmark typeface replaces the `display` face if it suits headlines.
|
|
223
|
-
Body text stays the system's text face unless they insist.
|
|
224
|
-
- Their photography replaces placeholder imagery at the same crops and ratios.
|
|
225
|
-
|
|
226
|
-
**C. Effects take the system's colours through their variables.** A Motion
|
|
227
|
-
Lab effect exposes each colour as a CSS custom property (`colorVars`, e.g.
|
|
228
|
-
`--ml-accent`) and as a prop. Set those from the system's tokens — the brand
|
|
229
|
-
accent, the darkest surface — and tune its `props` toward the system's motion
|
|
230
|
-
rules (slower if the system is calm). Never recolour inside a shader or
|
|
231
|
-
script, and never remove its reduced-motion fallback.
|
|
232
|
-
|
|
233
|
-
**Substitute values, keep the rules.** The system's spacing scale, radius
|
|
234
|
-
discipline, contrast requirements and "one accent moment per screen" all still
|
|
235
|
-
apply after the swap — that is the point of a system: it survives a brand
|
|
236
|
-
change. A roofing company's green goes where the indigo was, and the restraint
|
|
237
|
-
around it is unchanged.
|
|
238
|
-
|
|
239
|
-
**Check contrast after substituting.** A brand colour that fails the system's
|
|
240
|
-
stated contrast pairs is a real problem: tell the user, propose a darker or
|
|
241
|
-
lighter variant of their colour for text, and keep the original for large
|
|
242
|
-
fills. Don't silently ship unreadable text because it was their hex.
|
|
243
|
-
|
|
244
|
-
DESIGN.md files follow the open [DESIGN.md
|
|
245
|
-
format](https://github.com/google-labs-code/design.md): YAML front matter with
|
|
246
|
-
machine-readable tokens (`colors`, `typography`, `rounded`, `spacing`,
|
|
247
|
-
`components`, with `{colors.accent}` references already resolved), then prose
|
|
248
|
-
sections. Take concrete values from the front matter and the rules from the
|
|
249
|
-
prose.
|
|
250
|
-
|
|
251
|
-
## Step 4 — Polish pass (before calling anything done)
|
|
252
|
-
|
|
253
|
-
Run this against the assembled result. These are the "AI slop" tells noslopUI
|
|
254
|
-
exists to avoid — catch them here rather than shipping them:
|
|
255
|
-
|
|
256
|
-
- **Typography** — one display face used sparingly (headlines only, not buttons
|
|
257
|
-
or body), one text face for everything else. Nothing outside the DESIGN.md's
|
|
258
|
-
stated scale.
|
|
259
|
-
- **Color/contrast** — one accent moment per screen, not accent bleeding into
|
|
260
|
-
every icon, border and badge. Real contrast on text over any background,
|
|
261
|
-
checked against the DESIGN.md's own stated pairs.
|
|
262
|
-
- **Spacing** — compose from the DESIGN.md's spacing scale; don't invent
|
|
263
|
-
in-between values. Prefer more whitespace over a denser grid.
|
|
264
|
-
- **Motion** — only where it communicates a real state change; the DESIGN.md's
|
|
265
|
-
durations and easing, never a default bounce or spring. The one exception is
|
|
266
|
-
a Motion Lab effect placed where its `usage` says it earns its place — one
|
|
267
|
-
per page, recoloured to the system.
|
|
268
|
-
- **Named slop-tells to actively reject**: gradient text, purple-on-purple
|
|
269
|
-
palettes, bounce/spring easing on everything, every layout centered with no
|
|
270
|
-
asymmetry, decorative-only animation.
|
|
271
|
-
|
|
272
|
-
## Step 5 — Point back to the catalog for variations
|
|
273
|
-
|
|
274
|
-
If the result doesn't land, don't re-prompt the same component blind. Point the
|
|
275
|
-
user at `noslopui.com/explore` (every UI block in one grid, with Motion Lab and
|
|
276
|
-
design-system shelves) to browse real alternatives, and at the
|
|
277
|
-
Collections tab on `noslopui.com/account` to save the ones they like — which
|
|
278
|
-
turns the next build into Path A. Then repeat from Step 3 with whatever they
|
|
279
|
-
pick.
|
|
280
|
-
|
|
281
|
-
---
|
|
282
|
-
|
|
283
|
-
## Quick reference — tool call shape
|
|
284
|
-
|
|
285
|
-
```
|
|
286
|
-
list_collections({}) -> { collections: [{ id, name, itemCount }] }
|
|
287
|
-
get_collection({ listId?, name? }) -> { collection, designSystems: [{id,name}], items: [{ id, name, kind, ... }], guidance }
|
|
288
|
-
|
|
289
|
-
search_design_systems({ query?, tags?, tag?, limit? }) -> { results: [{ id, name, description, tags, tokens, previewUrl, url }], availableTags, industryTree }
|
|
290
|
-
get_design_system({ id }) -> { id, name, tokens, previewUrl, detailUrl }
|
|
291
|
-
get_design_system_file({ id }) -> { id, name, designMd } [gated: paid or trial]
|
|
292
|
-
|
|
293
|
-
search_components({ query?, section?, tags?, tag?, limit? }) -> { results: [{ id, name, kind, tags, url }] }
|
|
294
|
-
get_component({ id }) -> { id, name, dependencies, builtWithDesignSystem, previewUrl, detailUrl }
|
|
295
|
-
motion_lab items add { usage, props, colorVars, libraries }
|
|
296
|
-
get_component_code({ id }) -> { id, name, snippets: [{ language, code }] } [gated: paid or trial]
|
|
297
|
-
get_component_prompt({ id }) -> { id, name, promptText } [gated: paid or trial]
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
- If a gated call
|
|
312
|
-
|
|
313
|
-
|
|
20
|
+
|
|
21
|
+
Setup, if the noslopUI tools aren't available: the user runs
|
|
22
|
+
`npx noslopui@latest init`, or adds `https://noslopui.com/api/mcp` in their
|
|
23
|
+
agent and signs in when it asks (steps for each agent: `noslopui.com/mcp`).
|
|
24
|
+
Every call runs as the user's account. Search, metadata and collections are
|
|
25
|
+
free on every account. Code, prompts and DESIGN.md files need a paid plan or
|
|
26
|
+
the account's free 3-day trial, which the first such call starts.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Step 0 — Which path?
|
|
31
|
+
|
|
32
|
+
**Call `list_collections` first.** It's free on every account. But a
|
|
33
|
+
collection existing is not the same as the user asking you to build from it —
|
|
34
|
+
the default "Favorites" list is just where the save button puts a single item
|
|
35
|
+
with zero setup, so a design system sitting there alone is very often a saved
|
|
36
|
+
reference, not a decision. Don't let its mere presence override what the user
|
|
37
|
+
actually asked for.
|
|
38
|
+
|
|
39
|
+
- The user already said to use their saved items ("build from my collection",
|
|
40
|
+
"use what I've saved", names a list by name) → **Path A**, no need to ask.
|
|
41
|
+
- Nothing was said either way, but exactly one collection has content that
|
|
42
|
+
looks relevant → **ask**: name what's in it and let them choose Path A or
|
|
43
|
+
Path B. Don't assume silently in either direction.
|
|
44
|
+
- No collection, or nothing in any of them fits → **Path B**.
|
|
45
|
+
- Several collections and no obvious match → ask which one. Don't guess
|
|
46
|
+
between two curated sets.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Step 1 — Requirements, including brand
|
|
51
|
+
|
|
52
|
+
Do this on both paths, before choosing a system. Two groups of things.
|
|
53
|
+
|
|
54
|
+
**The build:**
|
|
55
|
+
|
|
56
|
+
1. **Purpose** — what is this for? (SaaS product, local service business,
|
|
57
|
+
portfolio, storefront, internal dashboard, docs site, …)
|
|
58
|
+
2. **Audience** — who is it for?
|
|
59
|
+
3. **Tone** — 2-3 words ("calm and minimal", "bold and playful", "editorial and
|
|
60
|
+
serif-driven", "warm and local"). This is what Step 2 matches against.
|
|
61
|
+
4. **Required sections** — the concrete list of what must exist.
|
|
62
|
+
|
|
63
|
+
**Their brand** — skip this and you ship a beautiful page that isn't theirs:
|
|
64
|
+
|
|
65
|
+
5. **Logo or wordmark** — do they have one, and in what format?
|
|
66
|
+
6. **Brand colours** — hex values if they have them, and whether they are fixed
|
|
67
|
+
(a franchise or a rebrand-in-progress changes the answer).
|
|
68
|
+
7. **Existing typeface** — anything already in use they need to stay with?
|
|
69
|
+
8. **Photography or illustration** — real assets to work from, or
|
|
70
|
+
placeholder-and-replace-later?
|
|
71
|
+
9. **An existing site or profile** to stay consistent with.
|
|
72
|
+
|
|
73
|
+
No brand at all → say so plainly and use the design system's own palette. Don't
|
|
74
|
+
invent a logo.
|
|
75
|
+
|
|
76
|
+
No real photography → don't ship a grey box. Use a seeded placeholder from
|
|
77
|
+
[Picsum](https://picsum.photos) — `https://picsum.photos/seed/<brand-slug>-<slot-name>/<w>/<h>`
|
|
78
|
+
— so the same build gets the same photo on every regenerate instead of a new
|
|
79
|
+
random one. Mark every one with `<!-- TODO: Replace with real photo, target
|
|
80
|
+
size <w>x<h> -->` immediately above it, and write alt text for the *intended*
|
|
81
|
+
subject ("Hand-poured ceramic mug, studio lighting"), not the placeholder
|
|
82
|
+
("Picsum image"), so it's already correct once they swap it in. Skip
|
|
83
|
+
photography altogether where the chosen design system's own register is
|
|
84
|
+
photo-free (type-led, editorial, most SaaS) rather than forcing a stock photo
|
|
85
|
+
in where the system doesn't call for one.
|
|
86
|
+
|
|
87
|
+
If the user already stated all this, don't re-ask — restate it in one line and
|
|
88
|
+
move on.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Path A — the user curated a collection
|
|
93
|
+
|
|
94
|
+
`get_collection({ listId })` (or `name`). Every item carries a `kind` —
|
|
95
|
+
`design_systems`, `ui_blocks` or `motion_lab` (an effect) — plus a top-level
|
|
96
|
+
`designSystems` array and a `guidance` line. A saved effect is a pick like any
|
|
97
|
+
other: use it where it fits, restyled as in Step 3.
|
|
98
|
+
|
|
99
|
+
1. **The collection's design system wins.** One in it → that is the system, no
|
|
100
|
+
searching; `get_design_system_file` for its DESIGN.md. More than one → ask
|
|
101
|
+
which; they saved both deliberately. None → say so, choose one as in Path B,
|
|
102
|
+
and tell them which and why.
|
|
103
|
+
2. **Cover each required section from the collection first.** If the user saved
|
|
104
|
+
something that covers a section, use it. Always. **Never substitute a
|
|
105
|
+
catalog component for one they explicitly saved**, even if you found
|
|
106
|
+
something you think is better — that was their call, not an oversight.
|
|
107
|
+
3. **Fill the gaps with `search_components`, checked before you hand-build
|
|
108
|
+
anything.** Search the whole catalog on fit, and restyle what you find to
|
|
109
|
+
the collection's design system. Only build a gap section yourself if
|
|
110
|
+
nothing in the catalog fits it, and say so in step 4's report.
|
|
111
|
+
4. **Report what you filled in.** "Hero, pricing and footer from your
|
|
112
|
+
collection; you had no testimonial section saved, so I pulled one from the
|
|
113
|
+
catalog and restyled it." They should never have to diff the result to find
|
|
114
|
+
out what they didn't choose.
|
|
115
|
+
|
|
116
|
+
Continue to Step 3.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Path B — you choose
|
|
121
|
+
|
|
122
|
+
### B1. Shortlist design systems, then ask
|
|
123
|
+
|
|
124
|
+
Design systems are classified by **tag**, not by category — there is no tree to
|
|
125
|
+
walk. Call `search_design_systems` with no arguments first if you don't know
|
|
126
|
+
what exists: it returns every system plus `availableTags`, the full filterable
|
|
127
|
+
vocabulary (`theme:`, `style:`, `industry:` and so on).
|
|
128
|
+
|
|
129
|
+
Then filter with `tags` (ANDed) and/or a free-text `query` built from the tone
|
|
130
|
+
words plus purpose:
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
search_design_systems({ tags: ["industry:hair-beauty"] })
|
|
134
|
+
search_design_systems({ tags: ["industry:dentist", "theme:light"] })
|
|
135
|
+
search_design_systems({ query: "calm minimal", tags: ["industry:saas"] })
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`industry:` is a two-level tree, shaped like a template marketplace's: a
|
|
139
|
+
**field** (`food-drink`, `medical`, `home-services`, `technology`…) and, under
|
|
140
|
+
it, **niches** (`restaurant`, `dentist`, `roofing`, `saas`…). Every system
|
|
141
|
+
tagged with a niche is also tagged with its field, so start with the niche if
|
|
142
|
+
the brief names one and widen to the field when that returns fewer than three.
|
|
143
|
+
|
|
144
|
+
**"Local business" is not an industry — name the trade.** A plumber is
|
|
145
|
+
`home-services`, a barber `hair-beauty`, a café `food-drink`, a physio
|
|
146
|
+
`medical`, a yoga studio `wellness`, an accountant `professional-services`.
|
|
147
|
+
Each of those looks and reads differently, and filtering on the specific field
|
|
148
|
+
is what keeps two local businesses from getting the same site.
|
|
149
|
+
|
|
150
|
+
A system can carry several fields — a warm serif system serves a restaurant, a
|
|
151
|
+
wedding planner and a spa alike — so don't treat one tag as excluding the
|
|
152
|
+
others, and don't pick the same system for every brief in a field: read the
|
|
153
|
+
descriptions and match the tone the user described.
|
|
154
|
+
|
|
155
|
+
Every result comes back with its tags, its token summary (colours, fonts,
|
|
156
|
+
radius) and a `previewUrl`. **Present the 2-3 best matches to the user with
|
|
157
|
+
their names, one-line descriptions, palettes and preview URLs, and ask which
|
|
158
|
+
they want.** Don't pick silently. This single choice shapes every screen, it
|
|
159
|
+
costs one question, and the user has taste you cannot infer from "a roofing
|
|
160
|
+
business".
|
|
161
|
+
|
|
162
|
+
Then `get_design_system` on their pick for the ungated token summary, and
|
|
163
|
+
`get_design_system_file` for the full DESIGN.md.
|
|
164
|
+
|
|
165
|
+
If nothing matches well, say so and ask whether to go with the closest or with
|
|
166
|
+
a system they describe by hand — don't quietly fall back to stock Tailwind
|
|
167
|
+
defaults, which is the "AI slop" this workflow exists to avoid.
|
|
168
|
+
|
|
169
|
+
**Read the whole DESIGN.md before fetching any component.** It's short by
|
|
170
|
+
design — tokens plus a page or two of intent prose, meant to be held in context
|
|
171
|
+
for the entire build. Its **Do's and Don'ts** section is the part doing the real
|
|
172
|
+
work.
|
|
173
|
+
|
|
174
|
+
### B2. Find components on fit
|
|
175
|
+
|
|
176
|
+
**Never write a section's markup from scratch before checking the catalog.**
|
|
177
|
+
Having the DESIGN.md in hand is not the same as being done searching — for
|
|
178
|
+
*every* required section, call `search_components` first — `section` and
|
|
179
|
+
`tags` filters as needed, with `tags` ANDed the same way (`["style:editorial"]`,
|
|
180
|
+
`["animation:carousel"]`). Pick the best **structural** match: the thing that
|
|
181
|
+
actually does what the section needs. Largely ignore how it currently looks;
|
|
182
|
+
you are restyling it regardless. Only once nothing in the catalog fits a
|
|
183
|
+
section is hand-building it acceptable — and say so, don't pass it off as a
|
|
184
|
+
catalog pick.
|
|
185
|
+
|
|
186
|
+
Every result is published as React/TSX with Tailwind classes, whatever stack
|
|
187
|
+
the build target is. That's not a limitation — the markup and styling aren't
|
|
188
|
+
React-specific, so converting a result to plain HTML, Vue, or anything else is
|
|
189
|
+
a mechanical step (`className` to `class`, drop event-handler props, etc.),
|
|
190
|
+
not a rebuild. Never skip a structurally-right component, or conclude the
|
|
191
|
+
catalog has nothing for a non-React project, over its source format.
|
|
192
|
+
|
|
193
|
+
**Effects are a separate kind.** `section: "motion_lab"` searches Motion Lab:
|
|
194
|
+
shader backgrounds, 3D, liquid glass, text, cursor and scroll effects. An
|
|
195
|
+
effect isn't a section of the page — it's the one moment people remember the
|
|
196
|
+
page for. Use one where the brief asks for it (an effect, motion, 3D, "make it
|
|
197
|
+
pop") or clearly calls for a showpiece, and one per page unless the user asks
|
|
198
|
+
for more. `get_component` tells you how: `usage` says where it earns its
|
|
199
|
+
place, `props` are its knobs, `colorVars` are the CSS custom properties its
|
|
200
|
+
colours come from, and `libraries` are the exact npm packages and versions to
|
|
201
|
+
install.
|
|
202
|
+
|
|
203
|
+
Then `get_component_code` for the ones you'll use.
|
|
204
|
+
|
|
205
|
+
---
|
|
206
|
+
|
|
207
|
+
## Step 3 — Apply the system, and fit the brand into it
|
|
208
|
+
|
|
209
|
+
Two moves, in this order.
|
|
210
|
+
|
|
211
|
+
**A. Restyle everything to the design system.** Same colour variables, same type
|
|
212
|
+
scale, same radius, same spacing scale, same motion durations and easing, across
|
|
213
|
+
every component. Where a fetched component's own defaults conflict with the
|
|
214
|
+
system, the system wins — adapt the component, and never leave both looks in
|
|
215
|
+
play at once.
|
|
216
|
+
|
|
217
|
+
**B. Substitute the brand into the system's tokens.** This is what makes the
|
|
218
|
+
result *theirs* rather than a nice demo:
|
|
219
|
+
|
|
220
|
+
- Their primary colour replaces the system's `accent` token. A secondary, if
|
|
221
|
+
they have one, replaces a supporting token — not a second accent.
|
|
222
|
+
- Their wordmark typeface replaces the `display` face if it suits headlines.
|
|
223
|
+
Body text stays the system's text face unless they insist.
|
|
224
|
+
- Their photography replaces placeholder imagery at the same crops and ratios.
|
|
225
|
+
|
|
226
|
+
**C. Effects take the system's colours through their variables.** A Motion
|
|
227
|
+
Lab effect exposes each colour as a CSS custom property (`colorVars`, e.g.
|
|
228
|
+
`--ml-accent`) and as a prop. Set those from the system's tokens — the brand
|
|
229
|
+
accent, the darkest surface — and tune its `props` toward the system's motion
|
|
230
|
+
rules (slower if the system is calm). Never recolour inside a shader or
|
|
231
|
+
script, and never remove its reduced-motion fallback.
|
|
232
|
+
|
|
233
|
+
**Substitute values, keep the rules.** The system's spacing scale, radius
|
|
234
|
+
discipline, contrast requirements and "one accent moment per screen" all still
|
|
235
|
+
apply after the swap — that is the point of a system: it survives a brand
|
|
236
|
+
change. A roofing company's green goes where the indigo was, and the restraint
|
|
237
|
+
around it is unchanged.
|
|
238
|
+
|
|
239
|
+
**Check contrast after substituting.** A brand colour that fails the system's
|
|
240
|
+
stated contrast pairs is a real problem: tell the user, propose a darker or
|
|
241
|
+
lighter variant of their colour for text, and keep the original for large
|
|
242
|
+
fills. Don't silently ship unreadable text because it was their hex.
|
|
243
|
+
|
|
244
|
+
DESIGN.md files follow the open [DESIGN.md
|
|
245
|
+
format](https://github.com/google-labs-code/design.md): YAML front matter with
|
|
246
|
+
machine-readable tokens (`colors`, `typography`, `rounded`, `spacing`,
|
|
247
|
+
`components`, with `{colors.accent}` references already resolved), then prose
|
|
248
|
+
sections. Take concrete values from the front matter and the rules from the
|
|
249
|
+
prose.
|
|
250
|
+
|
|
251
|
+
## Step 4 — Polish pass (before calling anything done)
|
|
252
|
+
|
|
253
|
+
Run this against the assembled result. These are the "AI slop" tells noslopUI
|
|
254
|
+
exists to avoid — catch them here rather than shipping them:
|
|
255
|
+
|
|
256
|
+
- **Typography** — one display face used sparingly (headlines only, not buttons
|
|
257
|
+
or body), one text face for everything else. Nothing outside the DESIGN.md's
|
|
258
|
+
stated scale.
|
|
259
|
+
- **Color/contrast** — one accent moment per screen, not accent bleeding into
|
|
260
|
+
every icon, border and badge. Real contrast on text over any background,
|
|
261
|
+
checked against the DESIGN.md's own stated pairs.
|
|
262
|
+
- **Spacing** — compose from the DESIGN.md's spacing scale; don't invent
|
|
263
|
+
in-between values. Prefer more whitespace over a denser grid.
|
|
264
|
+
- **Motion** — only where it communicates a real state change; the DESIGN.md's
|
|
265
|
+
durations and easing, never a default bounce or spring. The one exception is
|
|
266
|
+
a Motion Lab effect placed where its `usage` says it earns its place — one
|
|
267
|
+
per page, recoloured to the system.
|
|
268
|
+
- **Named slop-tells to actively reject**: gradient text, purple-on-purple
|
|
269
|
+
palettes, bounce/spring easing on everything, every layout centered with no
|
|
270
|
+
asymmetry, decorative-only animation.
|
|
271
|
+
|
|
272
|
+
## Step 5 — Point back to the catalog for variations
|
|
273
|
+
|
|
274
|
+
If the result doesn't land, don't re-prompt the same component blind. Point the
|
|
275
|
+
user at `noslopui.com/explore` (every UI block in one grid, with Motion Lab and
|
|
276
|
+
design-system shelves) to browse real alternatives, and at the
|
|
277
|
+
Collections tab on `noslopui.com/account` to save the ones they like — which
|
|
278
|
+
turns the next build into Path A. Then repeat from Step 3 with whatever they
|
|
279
|
+
pick.
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
## Quick reference — tool call shape
|
|
284
|
+
|
|
285
|
+
```
|
|
286
|
+
list_collections({}) -> { collections: [{ id, name, itemCount }] }
|
|
287
|
+
get_collection({ listId?, name? }) -> { collection, designSystems: [{id,name}], items: [{ id, name, kind, ... }], guidance }
|
|
288
|
+
|
|
289
|
+
search_design_systems({ query?, tags?, tag?, limit? }) -> { results: [{ id, name, description, tags, tokens, previewUrl, url }], availableTags, industryTree }
|
|
290
|
+
get_design_system({ id }) -> { id, name, tokens, previewUrl, detailUrl }
|
|
291
|
+
get_design_system_file({ id }) -> { id, name, designMd } [gated: paid or trial]
|
|
292
|
+
|
|
293
|
+
search_components({ query?, section?, tags?, tag?, limit? }) -> { results: [{ id, name, kind, tags, url }] }
|
|
294
|
+
get_component({ id }) -> { id, name, dependencies, builtWithDesignSystem, previewUrl, detailUrl }
|
|
295
|
+
motion_lab items add { usage, props, colorVars, libraries }
|
|
296
|
+
get_component_code({ id }) -> { id, name, snippets: [{ language, code }] } [gated: paid or trial]
|
|
297
|
+
get_component_prompt({ id }) -> { id, name, promptText } [gated: paid or trial]
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
`promptText` is the component's full code wrapped in integration
|
|
301
|
+
instructions (stack, file path, pinned dependencies, fonts, the design system it
|
|
302
|
+
was built with). You don't need it to build — `get_component_code` is enough.
|
|
303
|
+
It's for handing one component to a different agent or tool.
|
|
304
|
+
|
|
305
|
+
The account rides on the connection (a key or a sign-in, sent as the
|
|
306
|
+
`Authorization` header), so no tool takes a credential argument. Every search, metadata and collection tool is free on
|
|
307
|
+
every account; `get_design_system_file`, `get_component_code` and
|
|
308
|
+
`get_component_prompt` need the account on a paid plan or inside its free
|
|
309
|
+
3-day trial.
|
|
310
|
+
|
|
311
|
+
- If a gated call's result carries a `trial` field, that call just started the
|
|
312
|
+
user's trial — tell them, with the end date it gives.
|
|
313
|
+
- A trial covers up to 30 different items per 24 hours, far more than one site
|
|
314
|
+
needs. Fetch what the build uses, not the catalog speculatively; re-fetching
|
|
315
|
+
an item you already opened never counts again.
|
|
316
|
+
- If a gated call says the trial has ended (or the fair-use limit is reached),
|
|
317
|
+
stop and tell the user plainly — don't retry, and don't quietly swap in
|
|
318
|
+
something generated from scratch in its place. Search and collections keep
|
|
314
319
|
working, so the plan itself can still be finished.
|
package/dist/index.js
CHANGED
|
@@ -39,7 +39,7 @@ ${color.bold('Account')}
|
|
|
39
39
|
${color.bold('Catalog')}
|
|
40
40
|
search <query> Search blocks and effects --section ui-blocks|motion-lab, --tag <facet:value>, --limit
|
|
41
41
|
get <id> Print a component's code --format tsx|html|vue, --write <file>
|
|
42
|
-
prompt <id> Print a component's
|
|
42
|
+
prompt <id> Print a ready-to-paste prompt with a component's code
|
|
43
43
|
design-systems [query] Search design systems --tag theme:dark …
|
|
44
44
|
design-system <id> Print a design system's DESIGN.md --write DESIGN.md
|
|
45
45
|
collections List your saved collections
|
package/dist/lib/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "noslopui",
|
|
3
|
-
"version": "0.3.
|
|
4
|
-
"description": "Connect your coding agent to noslopUI
|
|
3
|
+
"version": "0.3.1",
|
|
4
|
+
"description": "Connect your coding agent to noslopUI — hand-crafted UI components and portable design systems, over MCP.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|
|
7
7
|
"claude-code",
|