@neuctra/ui-mcp 0.4.8 → 0.4.9

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.
@@ -123,7 +123,7 @@
123
123
  {
124
124
  "number": 57,
125
125
  "title": "Focal Point & Visual Interest",
126
- "content": "Eye-catching does not mean effects. Gradients, shadows and blur stay banned.\n\nVisual interest comes from:\n\n* **Scale contrast:** a very large headline next to small, quiet metadata.\n* **One bold element per viewport:** a single `bg-primary` block, button or highlight that the eye lands on first.\n* **Surface layering:** alternate sections between `bg-background`, `bg-card` and `bg-accent` bands to create depth without shadows.\n* **Big numbers:** metrics in large type with `tabular-nums`.\n* **Real imagery:** product screenshots and photos, not decorative filler.\n* **Whitespace:** give the most important element more space than anything around it.\n\nColor ratio: roughly 60% neutral surfaces, 30% text and borders, 10% primary."
126
+ "content": "Eye-catching does not mean piling on effects. Shadows on content surfaces stay banned. Gradients, glows and blur are allowed only as brand effects: theme tokens only, one effect per element.\n\nVisual interest comes from:\n\n* **Scale contrast:** a very large headline next to small, quiet metadata.\n* **One bold element per viewport:** a single `bg-primary` block, button or highlight that the eye lands on first.\n* **Surface layering:** alternate sections between `bg-background`, `bg-card` and `bg-accent` bands to create depth without shadows.\n* **Big numbers:** metrics in large type with `tabular-nums`.\n* **Real imagery:** product screenshots and photos, not decorative filler.\n* **One brand accent:** gradient headline words, a soft primary glow or a theme-colored animated background, never all of them on one screen.\n* **Whitespace:** give the most important element more space than anything around it.\n\nColor ratio: roughly 60% neutral surfaces, 30% text and borders, 10% primary."
127
127
  },
128
128
  {
129
129
  "number": 58,
@@ -328,8 +328,8 @@
328
328
  },
329
329
  {
330
330
  "number": 62,
331
- "title": "Motion Timing",
332
- "content": "Motion explains a change. It is never decoration.\n\n```text\nHover / press transition-colors duration-150\nOpen / close 200 to 300ms, ease-out\nPage load no entrance animations\n```\n\n* Respect reduced motion with `motion-reduce:` variants.\n* Animate color and opacity. Do not animate layout or add hover-scale."
331
+ "title": "Motion (Framer Motion)",
332
+ "content": "Motion explains a change and adds a light brand feel. Aim for a medium level: noticeable, never busy.\n\nUse Framer Motion for page and section motion. It already ships as a dependency of `@neuctra/ui`:\n\n```tsx\nimport { motion, MotionConfig } from \"framer-motion\";\n```\n\n```text\nHover / press transition-colors duration-150, lift y -2 to -4px, press scale 0.97\nOpen / close 200 to 300ms, ease-out\nSection reveal opacity 0 to 1, y 16 to 0, 0.4 to 0.6s, ease-out, once\nGrid / list stagger 0.06 to 0.1s between items, at most about 6 items\nHero on load one short reveal (under 0.6s), nothing else animates on load\nBackground loops slow (8s or more), low opacity, one per viewport\n```\n\n* Wrap the page in `<MotionConfig reducedMotion=\"user\">`.\n* Reveal with `whileInView` and `viewport={{ once: true, amount: 0.2 }}`. Never re-animate on every scroll.\n* Animate only opacity and transform (x, y, scale). Never animate width, height, top, left or the layout of text being read.\n* Use `ease-out` tweens or soft springs (`stiffness` about 200 to 300, `damping` 25 or more). No bounce, wobble, scale-105 zooms, parallax on text, or infinite loops on content.\n* Animate sections and grid items, not every element. Wrap `@neuctra/ui` components in a `motion.div`; do not restyle their internal animation.\n* Marketing and public pages: section reveals, stagger and an optional animated background. App and dashboard pages: hover/press, open/close and list item enter/exit only."
333
333
  },
334
334
  {
335
335
  "number": 63,
@@ -341,12 +341,29 @@
341
341
  {
342
342
  "number": 43,
343
343
  "title": "Avoid AI-Generated UI Patterns",
344
- "content": "Never automatically generate:\n\n* Hero section + three cards + gradient\n* Excessive rounded containers\n* Random decorative icons\n* Unnecessary badges\n* Excessive centered text\n* Every section inside a Card\n* Multiple primary buttons\n* Huge empty spaces\n* Excessive shadows\n* Random gradients\n* Generic dashboard cards\n* Repeated identical layouts\n* Decorative statistics without meaning\n\nAvoid the recognizable \"AI-generated SaaS template\" appearance."
344
+ "content": "Never generate:\n\n* Multicolor or rainbow gradients, or any color outside the theme\n* Shadows on buttons or cards, or large stacked shadows (shadow-xl, shadow-2xl)\n* A gradient on every heading, or gradient buttons\n* More than one animated background per viewport\n* Glow on buttons or text\n* Excessive rounded containers, every section inside a Card\n* Random decorative icons, unnecessary badges, emoji as icons\n* Multiple primary buttons, huge empty spaces, decorative statistics without meaning\n* Repeated identical layouts\n\nAllowed when on brand: theme-colored gradient headline words, soft primary glows, frosted sticky bars, and a theme-colored animated background that respects reduced motion."
345
345
  }
346
346
  ]
347
347
  },
348
348
  "goldenRule": {
349
349
  "title": "Golden Rule",
350
350
  "content": "Do not ask:\n\n> \"Which components can I put on this page?\"\n\nAsk:\n\n> \"What does the user need to understand and do, and which Neuctra UI component communicates that most naturally?\"\n\nThe best Neuctra UI interface is not the one that uses the most components.\n\nIt is the one where **every component has a purpose.**"
351
+ },
352
+ "motion": {
353
+ "library": "framer-motion",
354
+ "import": "import { motion, MotionConfig } from \"framer-motion\";",
355
+ "install": "framer-motion ships as a dependency of @neuctra/ui. If the project does not resolve it, run: npm install framer-motion",
356
+ "level": "medium: visible section reveals and small interaction feedback, never busy",
357
+ "presets": {
358
+ "pageWrapper": "<MotionConfig reducedMotion=\"user\">{children}</MotionConfig>",
359
+ "sectionReveal": "<motion.section initial={{ opacity: 0, y: 16 }} whileInView={{ opacity: 1, y: 0 }} viewport={{ once: true, amount: 0.2 }} transition={{ duration: 0.5, ease: \"easeOut\" }}>",
360
+ "staggerContainer": "const container = { hidden: {}, show: { transition: { staggerChildren: 0.08 } } };\nconst item = { hidden: { opacity: 0, y: 12 }, show: { opacity: 1, y: 0, transition: { duration: 0.4, ease: \"easeOut\" } } };\n<motion.ul variants={container} initial=\"hidden\" whileInView=\"show\" viewport={{ once: true, amount: 0.2 }}>{items.map((i) => <motion.li key={i.id} variants={item}>...</motion.li>)}</motion.ul>",
361
+ "hoverLift": "<motion.div whileHover={{ y: -3 }} whileTap={{ scale: 0.97 }} transition={{ type: \"spring\", stiffness: 260, damping: 26 }}>",
362
+ "animatedBackground": "<motion.div aria-hidden className=\"pointer-events-none absolute -z-10 left-1/2 top-0 size-96 -translate-x-1/2 rounded-full bg-primary/20 blur-[120px]\" animate={{ opacity: [0.5, 0.8, 0.5], scale: [1, 1.1, 1] }} transition={{ duration: 10, repeat: Infinity, ease: \"easeInOut\" }} />"
363
+ },
364
+ "byPageKind": {
365
+ "marketing": "Hero reveal on load, section reveals on scroll, staggered feature and pricing grids, at most one animated background per viewport.",
366
+ "app": "Hover/press feedback, open/close and list item enter/exit (AnimatePresence) only. No scroll reveals or animated backgrounds on dashboards, settings or data pages."
367
+ }
351
368
  }
352
- }
369
+ }
package/data/theme.json CHANGED
@@ -14,25 +14,28 @@
14
14
  ],
15
15
  "antiAiLookRules": [
16
16
  "This section exists because AI-generated UI has recognizable tells. Read it before generating anything visual — the goal is UI indistinguishable from a deliberate human design pass, not a demo that screams 'built by an LLM'.",
17
- "No gradients, compulsory: never use gradients on backgrounds, buttons, or text (bg-gradient-to-r, from-purple-500 to-pink-500, bg-clip-text text-transparent, etc.). Use a flat bg-primary (or the relevant status token) instead. This is the single most common AI-UI tell — do not use it even 'just for one hero section'.",
18
- "No shadows, compulsory: never add box-shadow/drop-shadow utilities (shadow-sm through shadow-2xl, glowing hover rings, colored blur halos) to any element YOU style directly — buttons, badges, cards, inputs, hand-built panels/overlays, or any other static surface you write classNames for. A flat surface with border-border is correct. Scope note (applies to every rule in this list, not just this one): this governs classNames/markup you author yourself. It does not mean stripping or fighting any pre-built @neuctra/ui component's own internal default styling, no matter which component or what that default is (several components ship their own shadow — e.g. Modal, Drawer, Popover, Dropdown, Tooltip, Table, DatePicker's calendar panel, Avatar's status dot, Kbd, and the Toast/ToastProvider notification — this is not an exhaustive list and isn't meant to be maintained as one). Per the 'don't overwrite built-in component design' rule: leave every component's shipped defaults exactly as they ship. Never add a decorative shadow yourself, and never override one away with `!important` either — both are the same mistake in opposite directions.",
19
- "No blur effects, compulsory: never use backdrop-blur or any glassmorphism treatment (frosted-glass cards, translucent bg-white/10 panels) on any element YOU style directly, including a hand-built modal/drawer backdrop — use an opaque or semi-opaque solid backdrop (e.g. bg-background/80) instead of a blurred one. Surfaces you author are opaque (bg-card, bg-popover, bg-background), not translucent. Same scope note as the shadow rule above: this is about classNames/markup you write, not about a pre-built @neuctra/ui component's own internal backdrop-blur (e.g. Modal/Drawer's backdrop, Dropdown's menu panel, Carousel's nav buttons ship with backdrop-blur baked in, among others) — leave every component's shipped defaults exactly as they ship, whichever component it is.",
17
+ "Brand effects are allowed, inside the theme, compulsory: gradients, glows, blur and animated backgrounds may be used to make a page feel branded, but every color in them must come from the theme tokens (var(--primary), var(--foreground), var(--background), var(--card), var(--border) and their /opacity variants, or color-mix() of them). Never introduce a color outside the theme for an effect: no from-purple-500 to-pink-500, no rainbow or multicolor gradients, no neon colors. Switching the theme must change every effect with it.",
18
+ "Gradients, restrained: use at most two theme colors per gradient (e.g. from-primary to-foreground, or primary fading to transparent). Allowed on: a few highlighted words in a heading (bg-clip-text), section and hero backgrounds, card edges, and thin divider lines. Not allowed on: buttons, body text, inputs, badges, or every heading on the page. At most one gradient heading per viewport.",
19
+ "No shadows on buttons and cards, compulsory: never add shadow-sm through shadow-2xl, drop-shadow, or any box-shadow to buttons, cards, panels, inputs, modals you build yourself, or any surface that holds content. Separate surfaces with border-border, a background change (bg-card vs bg-background) and spacing instead. Leave the built-in shadows of @neuctra/ui components (Modal, Drawer, Popover, Dropdown, Tooltip, Toast) exactly as they ship.",
20
+ "Glows are not shadows: a soft colored glow made from the primary token is allowed on small accents (a status dot, a step number, a progress bar, a timeline marker) and as a pointer-following light inside a card on hover. Keep it subtle (theme color at 10 to 30 percent opacity) and never use it on buttons, text or inputs.",
21
+ "Blur, in its place: backdrop-blur is allowed on sticky or fixed bars (navbar, tab bar, top bar) and on modal overlays, always with a mostly opaque token background (bg-background/75 or more). Large blurred blobs of the primary token (blur-[100px] or more, low opacity, pointer-events-none, aria-hidden) are allowed behind hero and section content. Never blur content the user reads, and never make a card see-through.",
20
22
  "No blanket border-radius escalation — don't reach for rounded-2xl/rounded-3xl/rounded-full on every card, input, and button by default. Match the radius already used by the surrounding neuctra-ui components (rounded-md/rounded-lg/rounded-xl per component, see each component's own classes) instead of picking a bigger one because it 'looks more modern'.",
21
- "No decorative hover/focus glow rings. ring-* and focus-visible:ring-ring exist for accessibility (keyboard focus indication) only — never add a colored ring or glow as a pointer-hover decoration on cards, buttons, or images.",
22
- "No animate-pulse / bounce / scale-105-on-hover / floating-icon motion sprinkled across static content as decoration. Motion should communicate state (loading, a toast entering, a modal opening) — components already handle that internally. Don't add extra hover-scale or idle animation to elements that aren't interactive or aren't mid-transition.",
23
+ "Focus rings are for accessibility only: ring-* and focus-visible:ring-ring indicate keyboard focus. Never add a colored ring as a pointer-hover decoration on cards, buttons, or images. The only hover glow allowed is the soft pointer-following primary light inside a card described in the glow rule.",
24
+ "Animated backgrounds are allowed, compulsory conditions: they use only theme tokens, sit behind content (absolute, -z-10 or under a readable overlay, pointer-events-none, aria-hidden), stay low contrast so text keeps its contrast, run at most one per viewport, and stop when the user prefers reduced motion (MotionConfig reducedMotion=\"user\" or a prefers-reduced-motion check). Never animate content itself, and never use flashing or fast loops.",
25
+ "Motion on interactive elements stays small: a hover lift of 1 to 4px or a press scale of about 0.97 is allowed on buttons, links and clickable cards. No scale-105 zooms, bouncing, floating icons or wobble. Idle animation is only for decorative backgrounds and live-status dots.",
23
26
  "No emoji used as icons or bullet markers in generated UI (✨, 🚀, 💡, ✅ as list bullets, feature markers, or button icons). Use lucide-react icons — the same icon set every neuctra-ui component already uses — passed via each component's icon props (iconBefore, iconAfter, icon, etc.).",
24
27
  "No 'icon in a colored circle badge' repeated on every single feature/stat/card by default (a bg-primary/10 rounded-full p-3 wrapper around every icon). Use it sparingly, only where the component's own design already calls for it — repeating the same decorative wrapper on every card in a grid is a generic-template tell.",
25
28
  "No arbitrary one-off spacing/sizing values (p-[13px], gap-[7px], w-[327px]) — use the Tailwind spacing scale (p-3, gap-2, w-80, etc.) so spacing stays consistent with the rest of the design system.",
26
29
  "Prefer information density and restraint over generic centered-hero-with-huge-padding layouts. Not every section needs max-w-7xl mx-auto text-center py-24 — match the density and layout the consumer's existing UI already uses.",
27
30
  "Make every layout fully responsive by default — mobile, tablet, and desktop (sm:/md:/lg:/xl: breakpoints), stacking to a single column and adjusting spacing/type-scale at small widths. Never ship a fixed-width or desktop-only layout and call it done.",
28
31
  "No em dashes (—), compulsory: never use an em dash in generated copy or UI text (headings, body copy, button labels, placeholder text). It's a recognizable AI-writing tell. Use a period, comma, colon, or restructure the sentence instead.",
29
- "No over-effects: don't stack multiple decorative treatments on one element (e.g. a gradient plus a shadow plus a hover-scale plus a glow, all on the same button). Every visual effect that does appear should communicate a real state or interaction (hover, focus, loading, an entering toast) — never decoration for its own sake.",
32
+ "No over-effects: one decorative effect per element at most (a gradient OR a glow OR a hover lift), and the effects on one screen must share one color (the primary token). If an effect makes text harder to read or competes with the primary action, remove it.",
30
33
  "Don't layer a separate leading-* utility (leading-relaxed, leading-normal, leading-tight, ...) on top of a text-size class (text-sm, text-base, text-lg, text-xl, ...) — Tailwind's text-size utilities already ship a paired line-height, so adding leading-* alongside one is redundant and can fight the intended rhythm. Only reach for leading-* when no text-size class is already setting one, and even then never leading-none/leading-tight on paragraph-length text. Letter-spacing: use tracking-tight on headings text-3xl and larger; leave everything smaller at the default (tracking-normal); only use tracking-wide for short uppercase labels (badges, eyebrow text, nav labels), and never tracking-wide on paragraph-length text.",
31
34
  "Responsive, compulsory: every page must pass the Breakpoint Checklist in the design guide (360, 768, 1024, 1280, 1536px) with no horizontal scroll and touch targets of at least 44px.",
32
35
  "One focal point per viewport: a single dominant element (usually the primary CTA or one bg-primary block) that the eye lands on first. Never several competing bg-primary blocks on one screen.",
33
36
  "Use the fixed type scale from the design guide (Type Scale section). Never more than 4 text sizes on one screen, and keep paragraphs to max-w-prose or max-w-2xl.",
34
- "The bar is modern, visually appealing UI achieved through typography hierarchy, whitespace, correct token usage, and responsive layout, not through gradients, shadows, blur, or glow effects standing in for actual design decisions.",
35
- "Decent, restrained design, compulsory: build UI that is decent and intentional, never over-designed. When unsure whether an effect (shadow, gradient, blur, glow, animation, an extra color) is warranted on something you're authoring yourself: leave it out. A flat, token-colored, appropriately-radiused, unshadowed, responsive surface using only the semantic color tokens is the correct default for the overwhelming majority of neuctra-ui components — restraint is the default, not the exception."
37
+ "The bar is branded and restrained: a page may have a signature look (gradient headline words, a glow, an animated background in the brand color), but it must still read well with every effect removed. Hierarchy, spacing and typography carry the design; effects only add the brand.",
38
+ "Decent, restrained design, compulsory: build UI that is decent and intentional, never over-designed. When unsure whether an effect (gradient, glow, blur, animation) is warranted on something you're authoring yourself, leave it out; shadows on content surfaces and colors outside the theme are never warranted. A flat, token-colored, appropriately-radiused, unshadowed, responsive surface is the correct default for most neuctra-ui components. Brand effects are added on purpose, only where the effect rules above allow them."
36
39
  ],
37
40
  "tokens": [
38
41
  { "token": "primary", "className": "bg-primary / text-primary / border-primary", "pairsWith": "primary-foreground", "light": "#00c214", "dark": "#00c214", "usage": "Brand color: primary buttons, active states, links, focus accents." },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neuctra/ui-mcp",
3
- "version": "0.4.8",
3
+ "version": "0.4.9",
4
4
  "description": "MCP server exposing the @neuctra/ui component registry (props, defaults, examples, theme tokens) so AI coding tools generate accurate Neuctra UI code, plus SEO/AEO/GEO tools (per-page meta, woven JSON-LD, audits).",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -58,6 +58,16 @@ function resolveLayout(request, requestedType, layoutData) {
58
58
  };
59
59
  }
60
60
 
61
+ const APP_MOTION_CATEGORIES = new Set(["saas-app", "forms", "tools"]);
62
+ const APP_MOTION_LAYOUTS = new Set(["checkout", "shopping-cart", "order-confirmation", "documentation"]);
63
+
64
+ function getMotionGuidance(motion, layout) {
65
+ if (!motion) return null;
66
+ const { byPageKind, ...guide } = motion;
67
+ const pageKind = APP_MOTION_CATEGORIES.has(layout.category) || APP_MOTION_LAYOUTS.has(layout.id) ? "app" : "marketing";
68
+ return { ...guide, pageKind, forThisPage: byPageKind?.[pageKind] };
69
+ }
70
+
61
71
  function detectTaskSignals(request) {
62
72
  return [
63
73
  ["create", /\b(create|build|make|new|design)\b/i],
@@ -90,7 +100,7 @@ export function registerNeuctraUiPageBuilderTool(server, data) {
90
100
  {
91
101
  title: "Analyze and plan a Neuctra UI page",
92
102
  description:
93
- "Analyze a page request and choose from every layout in the grouped real-world catalog in data/layouts.json, including marketing, SaaS dashboards, commerce, publishing, support, portfolios, communities, events, and system pages. Use pageType=auto to select the closest specific layout from the request, or choose an explicit pageType. Returns the selected recipe, context-matched design variants (navigation shell, page header, stat cards, dashboard grid), matching @neuctra/ui component specs, relevant design rules, and SEO guidance.",
103
+ "Analyze a page request and choose from every layout in the grouped real-world catalog in data/layouts.json, including marketing, SaaS dashboards, commerce, publishing, support, portfolios, communities, events, and system pages. Use pageType=auto to select the closest specific layout from the request, or choose an explicit pageType. Returns the selected recipe, context-matched design variants (navigation shell, page header, stat cards, dashboard grid), matching @neuctra/ui component specs, relevant design rules, Framer Motion animation presets, and SEO guidance.",
94
104
  inputSchema: {
95
105
  request: z.string().min(8).describe("Describe the page to create and the main user task."),
96
106
  pageType: z.enum(pageTypeOptions).default("auto").describe(`Layout ID from the full catalog (${layouts.map((layout) => layout.id).join(", ")}) or auto to infer the best match from the request.`),
@@ -117,7 +127,9 @@ export function registerNeuctraUiPageBuilderTool(server, data) {
117
127
  }
118
128
 
119
129
  const components = getComponentGuidance(data.registry, request, layout);
120
- const design = getDesignRulesContext(data.theme, data.aiDesignRules, layout.designRuleNumbers);
130
+ const designRuleNumbers = layout.designRuleNumbers ? [...new Set([...layout.designRuleNumbers, 57, 62])] : undefined;
131
+ const design = getDesignRulesContext(data.theme, data.aiDesignRules, designRuleNumbers);
132
+ const motion = getMotionGuidance(data.aiDesignRules.motion, layout);
121
133
  const seo = buildSeoGuideContext(data.seoGuide, {
122
134
  framework,
123
135
  ruleIds: layout.seoRuleIds,
@@ -156,6 +168,7 @@ export function registerNeuctraUiPageBuilderTool(server, data) {
156
168
  },
157
169
  ...(designVariants && { designVariants }),
158
170
  designRules: design,
171
+ ...(motion && { motion }),
159
172
  seoGuidance: seo ? {
160
173
  framework: seo.framework,
161
174
  relevantRules: seo.seoRules,
@@ -167,6 +180,7 @@ export function registerNeuctraUiPageBuilderTool(server, data) {
167
180
  "Keep the primary task visually clear; do not add sections that do not serve the request.",
168
181
  ...(designVariants ? ["Build the navigation shell, page header, stat cards and dashboard grid from designVariants.selections. Use the recommended variant unless an alternative clearly fits the brief better; if the project already has an app shell, keep that instead."] : []),
169
182
  "Use Neuctra UI components with the exact props and semantic theme tokens from the supplied context.",
183
+ ...(motion ? [`Add medium-level motion with Framer Motion using the motion presets: ${motion.forThisPage} Respect reduced motion and keep brand effects (gradients, glows, blur, animated backgrounds) to theme tokens only.`] : []),
170
184
  "Apply the SEO steps only when the page is public and indexable; protect private application pages.",
171
185
  "When framework is auto, inspect the project files and choose metadata and rendering APIs for the installed framework and router.",
172
186
  ],