@neuctra/ui-mcp 0.4.2 → 0.4.4

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 CHANGED
@@ -64,13 +64,20 @@ Three independently-regenerable files feed the server:
64
64
  the color-token rules ("never hardcode colors"), the anti-AI-look rules ("no
65
65
  gradients/shadows/blurs/glows/emoji-icons"), the recommended `@neuctra/ui-cli init`
66
66
  setup command, and how the standalone `toast()` API works.
67
- - **`data/aiDesignRules.json`** — also hand-curated, no generator. A 51-section
67
+ - **`data/aiDesignRules.json`** — also hand-curated, no generator. A 63-section
68
68
  product/UX design guide (design philosophy, visual hierarchy, page/sidebar/navigation
69
69
  structure, per-component usage guidance, spacing/color/border/radius/shadow
70
70
  conventions, responsive design, accessibility, and a final UI quality checklist).
71
71
  `theme.json`'s `rules`/`antiAiLookRules` are the mechanical, CSS-level rules; this file
72
72
  is the higher-level product-design layer — both are served together by
73
73
  `get_design_rules`.
74
+ - **`data/seoGuide.json`** — hand-curated, no generator. A 16-topic SEO / AEO / GEO
75
+ playbook (technical SEO, Core Web Vitals, on-page, keywords and intent, E-E-A-T, answer
76
+ engine and generative engine optimisation, schema weaving, FAQs, the per-page meta
77
+ checklist, where metadata goes in each framework plus Next.js metadata gotchas, page
78
+ templates for tool/category/home pages, site-wide essentials, ads readiness, off-page
79
+ and monitoring, and a launch checklist). Served by `get_seo_guide`; the logic behind `generate_page_seo` and
80
+ `audit_page_seo` lives in `src/seo.mjs`.
74
81
 
75
82
  ---
76
83
 
@@ -100,17 +107,16 @@ the result back into its context before continuing.
100
107
  The tools are designed to be called in roughly this order when generating UI, not
101
108
  grabbed ad hoc:
102
109
 
103
- 1. **`get_design_rules`** — call this first, before picking any component. It returns
104
- the styling rules, the anti-AI-look rules, and the 51-section product/UX guide. This
105
- shapes *what* to build (hierarchy, when a group actually needs `Card`, when `Modal`
106
- vs `Drawer`, etc.) before you start reaching for components.
107
- 2. **`get_theme`** — call alongside step 1, not instead of it. Tokens without the design
108
- rules just tell you which colors exist, not how to use them well.
110
+ 1. **`neuctra-ui-builder`** — use this for routine UI generation. It infers the UI
111
+ category, returns a focused UX plan, core styling and accessibility rules, relevant
112
+ design-guide sections, component candidates, and preference questions when useful.
113
+ 2. Ask any high-impact questions returned in `uxPlan.preferenceQuestions`, then pass
114
+ answers back through `preferences` if they change the implementation.
109
115
  3. **`list_components`** (filtered by category) or **`search_components`** (keyword) —
110
116
  confirm which real components exist for what you need. This matters specifically
111
117
  because the design guide can describe a *pattern* (e.g. a sidebar nav item) without
112
118
  there being a dedicated component for it — don't assume one exists, confirm here.
113
- 4. **`get_component`** — full spec for every component before writing code against it.
119
+ 4. **`get_component`** — full spec for every unfamiliar component before writing code against it.
114
120
  Do this every time you touch a component you haven't already pulled specs for in the
115
121
  current conversation, not just once at the start. Never guess prop names from memory.
116
122
  5. **Write the UI**, applying the design rules, the tokens, and the exact props from
@@ -120,13 +126,36 @@ grabbed ad hoc:
120
126
  `antiAiLookRules` from `get_design_rules` before considering the UI
121
127
  done — reread them, don't just rely on having read them once at the start.
122
128
 
123
- Steps 1–2 only need to happen once per session/task, not once per component — refetching
124
- `get_theme`/`get_design_rules` for every single component would be wasteful. Step 4 is
125
- the one that repeats for every new component.
129
+ 7. **For public pages**, call **`get_seo_guide`** once, then **`generate_page_seo`** for
130
+ each page (meta, OpenGraph and a woven JSON-LD graph in the project's framework) and
131
+ **`audit_page_seo`** to check the finished page.
132
+
133
+ Call `get_design_rules` for broad design reviews or unresolved edge cases, and `get_theme`
134
+ when the complete token/setup reference is needed. The full guide remains the source of
135
+ truth; the builder selects relevant sections for each request.
126
136
 
127
137
  ---
128
138
 
129
- ## 5. The five tools, in detail
139
+ ## 5. The nine tools, in detail
140
+
141
+ ### `neuctra-ui-builder`
142
+
143
+ Creates a compact, category-aware brief for the host model. It infers or accepts a UI
144
+ category, selects relevant UX rules and component candidates, includes essential Neuctra
145
+ styling rules and semantic token names, and asks about visual direction, density, or the
146
+ primary action when those preferences are missing. It plans and curates context; the host
147
+ model writes the UI. Use `get_component` for exact props before implementing an unfamiliar
148
+ component.
149
+
150
+ **Input:** `{ request: string, category?: "auto" | "dashboard" | "landing-page" | "form" | "settings" | "authentication" | "data-table" | "ecommerce" | "documentation" | "custom", preferences?: { visualDirection?, density?, primaryAction?, platform?, audience? } }`
151
+
152
+ ```json
153
+ {
154
+ "request": "Build a project dashboard where a team can review activity and invite members.",
155
+ "category": "auto",
156
+ "preferences": { "density": "balanced", "platform": "responsive" }
157
+ }
158
+ ```
130
159
 
131
160
  ### `list_components`
132
161
 
@@ -230,13 +259,14 @@ requirements — e.g. `CardBody` is compulsory whenever `Card` has body content,
230
259
  `Card` itself renders no padding — and component-specific gotchas like Dropdown's
231
260
  trigger already stopping propagation internally) and **`antiAiLookRules`** (no
232
261
  gradients/shadows/blurs/glows/emoji-icons/em-dashes — the visual tells that make UI read
233
- as AI-generated), plus **`productDesignGuide`** — a 51-section product/UX design guide
262
+ as AI-generated), plus **`productDesignGuide`** — a 63-section product/UX design guide
234
263
  covering design philosophy, visual hierarchy, page/sidebar/navigation structure,
235
264
  per-component usage guidance (when to reach for `Card` vs plain whitespace, `Modal` vs
236
265
  `Drawer`, `Table` vs `List`, etc.), spacing/color/border/radius/shadow conventions,
237
266
  responsive design, accessibility, interaction design, and a final UI quality checklist.
238
267
 
239
- Call this before generating any UI — see the recommended workflow above.
268
+ Use this for full-guide reviews and edge cases. For routine generation, use
269
+ `neuctra-ui-builder` to retrieve the rules relevant to the request.
240
270
 
241
271
  **Response shape (trimmed):**
242
272
  ```jsonc
@@ -258,13 +288,59 @@ Call this before generating any UI — see the recommended workflow above.
258
288
  "sections": [
259
289
  { "number": 1, "title": "Core Design Philosophy", "content": "..." },
260
290
  { "number": 7, "title": "Cards", "content": "..." },
261
- // ...51 sections total
291
+ // ...63 sections total
262
292
  ],
263
293
  "goldenRule": { "title": "Golden Rule", "content": "..." }
264
294
  }
265
295
  }
266
296
  ```
267
297
 
298
+ ### `get_seo_guide`
299
+
300
+ Returns the SEO / AEO / GEO playbook from `data/seoGuide.json`: the whole guide, or one
301
+ topic via `topic` (`technical`, `performance`, `on-page`, `keywords-intent`, `eeat`,
302
+ `aeo`, `geo`, `schema`, `faq`, `meta-checklist`, `frameworks`, `page-templates`,
303
+ `site-wide`, `ads-readiness`, `off-page-monitoring`, `launch-checklist`).
304
+
305
+ ```json
306
+ { "topic": "geo" }
307
+ ```
308
+
309
+ ### `generate_page_seo`
310
+
311
+ Deterministic generator (no LLM, never invents facts) for everything one page needs:
312
+ a meta title (60 chars max) and description (155 max), canonical, robots, OpenGraph
313
+ and Twitter tags, and one JSON-LD `@graph` weaving Organization, WebSite, WebPage,
314
+ BreadcrumbList, the page-type node (TechArticle, BlogPosting, SoftwareApplication for
315
+ tool and product pages, Product with offers), HowTo (from the visible `steps`), ItemList
316
+ (from a category's `items`) and FAQPage together by stable `@id`s (the same scheme as
317
+ `neuctra-ui-docs-v2/lib/seo/schemas`). Returns a ready-to-paste snippet for
318
+ `nextjs-app`, `nextjs-pages`, `react-vite`, `react-router`, `astro`, `tanstack-start`,
319
+ `gatsby` or `html`, plus warnings and AEO/GEO follow-ups.
320
+
321
+ ```json
322
+ {
323
+ "framework": "nextjs-app",
324
+ "pageType": "docs",
325
+ "siteName": "Neuctra UI",
326
+ "siteUrl": "https://ui.neuctra.com",
327
+ "path": "/docs/card",
328
+ "primaryKeyword": "react card component",
329
+ "description": "Composable React card component with header, body and footer sections...",
330
+ "faqs": [{ "question": "Does Card support dark mode?", "answer": "Yes. ..." }]
331
+ }
332
+ ```
333
+
334
+ ### `audit_page_seo`
335
+
336
+ Rule-based check of one page. The easiest input is the page's built HTML (`html`, from
337
+ view-source or the `out/` / `dist/` folder): title, description, canonical, headings,
338
+ og:image, JSON-LD types, alt text and word count are extracted from it. Explicit fields
339
+ override the extracted ones, and checks without input are skipped. It catches doubled or
340
+ missing brand suffixes (with `brandName`), duplicate schema nodes, JSON-LD that doesn't
341
+ parse, and pages that render client-only (no H1 in the HTML). Returns a 0–100 score and a sorted
342
+ list of `fail` / `warn` / `pass` items, each with the exact fix.
343
+
268
344
  ---
269
345
 
270
346
  ## 6. Local development
@@ -363,13 +439,15 @@ neuctra-ui-mcp/
363
439
  ├── bin/
364
440
  │ └── cli.mjs # entry point: connects the server to a stdio transport
365
441
  ├── src/
366
- │ └── server.mjs # defines the 5 tools and their handlers
442
+ │ ├── server.mjs # defines the 9 tools and their handlers
443
+ │ └── seo.mjs # pure builders behind generate_page_seo / audit_page_seo
367
444
  ├── scripts/
368
445
  │ └── sync-registry.mjs # copies registry/components.json from neuctra-ui-package
369
446
  ├── data/
370
447
  │ ├── components.json # synced (generated) — don't edit by hand
371
448
  │ ├── theme.json # hand-curated token + styling/anti-AI-look rules
372
- │ └── aiDesignRules.json # hand-curated 51-section product/UX design guide
449
+ │ ├── aiDesignRules.json # hand-curated 63-section product/UX design guide
450
+ │ └── seoGuide.json # hand-curated SEO / AEO / GEO playbook
373
451
  └── package.json
374
452
  ```
375
453
 
@@ -50,7 +50,7 @@
50
50
  {
51
51
  "number": 10,
52
52
  "title": "Typography",
53
- "content": "Typography should create hierarchy without requiring excessive decoration.\n\nRecommended hierarchy:\n\n```text\nPage title\n↓\nSection title\n↓\nComponent title\n↓\nBody text\n↓\nMetadata\n```\n\nUse:\n\n* Strong weight for headings\n* Regular weight for descriptions\n* `text-secondary` for paragraphs and descriptions\n* Muted color for metadata\n* Comfortable line-height for reading\n\nAvoid:\n\n* Excessive bold text\n* Too many font sizes\n* All-caps body text\n* Huge headings on every page\n* Centering everything"
53
+ "content": "Typography should create hierarchy without requiring excessive decoration.\n\nRecommended hierarchy:\n\n```text\nPage title\n↓\nSection title\n↓\nComponent title\n↓\nBody text\n↓\nMetadata\n```\n\nUse:\n\n* Strong weight for headings\n* Regular weight for descriptions\n* `text-secondary` for paragraphs and descriptions\n* Muted color for metadata\n* Comfortable line-height for reading — but from the text-size class itself (text-sm, text-base, text-lg, ...), not a separate leading-* utility layered on top; the text-size class already pairs a line-height, so adding leading-* alongside it is redundant\n\nSee Type Scale (section 52) and Readable Measure (section 53) for exact classes.\n\nAvoid:\n\n* Excessive bold text\n* Too many font sizes\n* All-caps body text\n* Huge headings on every page\n* Centering everything\n* Adding leading-* on top of a text-size class that already sets line-height"
54
54
  },
55
55
  {
56
56
  "number": 11,
@@ -175,7 +175,7 @@
175
175
  {
176
176
  "number": 35,
177
177
  "title": "Responsive Design",
178
- "content": "Design mobile-first.\n\nDesktop:\n\n```text\nSidebar + Main Content\n```\n\nTablet:\n\n```text\nCollapsed Sidebar + Main Content\n```\n\nMobile:\n\n```text\nTop Bar\nContent\n```\n\nNavigation should become more compact rather than simply shrinking.\n\nForms should become single-column where necessary.\n\nCards should stack naturally.\n\nTables may require:\n\n* horizontal scrolling\n* responsive transformation\n* reduced columns\n\nNever allow the layout to become horizontally broken."
178
+ "content": "Design mobile-first.\n\nDesktop:\n\n```text\nSidebar + Main Content\n```\n\nTablet:\n\n```text\nCollapsed Sidebar + Main Content\n```\n\nMobile:\n\n```text\nTop Bar\nContent\n```\n\nNavigation should become more compact rather than simply shrinking.\n\nForms should become single-column where necessary.\n\nCards should stack naturally.\n\nTables may require:\n\n* horizontal scrolling\n* responsive transformation\n* reduced columns\n\nNever allow the layout to become horizontally broken.\n\nSee the Breakpoint Checklist (section 59) for the widths and checks every page must pass."
179
179
  },
180
180
  {
181
181
  "number": 36,
@@ -256,6 +256,66 @@
256
256
  "number": 51,
257
257
  "title": "Paragraph Text Color",
258
258
  "content": "Use `text-secondary` for all paragraph text: body copy, section descriptions, card descriptions, and supporting text under headings.\n\nDo not use `text-muted-foreground` for paragraphs. It is too low-contrast for reading text.\n\nKeep `text-muted-foreground` for small, low-priority text only:\n\n* Timestamps\n* Metadata\n* Captions\n* Placeholders\n* Helper and hint text\n* Disabled states\n\nUse `text-foreground` for headings, titles, and anything that needs full emphasis.\n\n`secondary` is a text color only. Do not use it as a background (`bg-secondary`).\n\nOrder of emphasis:\n\n```text\ntext-foreground ← headings\n↓\ntext-secondary ← paragraphs\n↓\ntext-muted-foreground ← metadata and hints\n```\n\nToken values:\n\n* Light theme: `--secondary: #3f3f46`\n* Dark theme: `--secondary: #d4d4d8`"
259
+ },
260
+ {
261
+ "number": 52,
262
+ "title": "Type Scale",
263
+ "content": "Use one fixed, responsive type scale on every page:\n\n```text\nDisplay / H1 text-4xl sm:text-5xl lg:text-6xl font-bold tracking-tight\nH2 text-3xl sm:text-4xl font-semibold tracking-tight\nH3 text-xl sm:text-2xl font-semibold\nBody text-base\nSmall text-sm\nMeta text-xs\n```\n\nRules:\n\n* Never use more than 4 text sizes on one screen.\n* Add `text-balance` to headings so lines break evenly.\n* Add `text-pretty` to paragraphs to avoid single-word last lines.\n* Step headings down one level at a time. Do not jump from H1 straight to small text.\n* `tracking-tight` only on `text-3xl` and larger. Everything smaller stays at the default tracking.\n* Line-height comes from the text-size class. Do not add `leading-*` on top of it."
264
+ },
265
+ {
266
+ "number": 53,
267
+ "title": "Readable Measure",
268
+ "content": "Long lines are hard to read.\n\n* Paragraphs: `max-w-prose` or `max-w-2xl`.\n* Headings may run wider: `max-w-3xl`.\n* Never let body text stretch the full width of a wide container.\n\nThe layout can be wide. The reading column should not be."
269
+ },
270
+ {
271
+ "number": 54,
272
+ "title": "Spacing Rhythm",
273
+ "content": "Use the 4/8 spacing scale only. Space shrinks as you go deeper into the layout.\n\n```text\nPage gutters px-4 sm:px-6 lg:px-8\nBetween sections py-16 sm:py-20 lg:py-28\nBetween blocks mt-10 / mt-12\nHeading to body mt-4\nInside a component gap-2 / gap-3\n```\n\nBig gaps separate ideas. Small gaps group them. If everything has the same gap, nothing is grouped."
274
+ },
275
+ {
276
+ "number": 55,
277
+ "title": "Grid & Layout Patterns",
278
+ "content": "Build layouts from a few reliable patterns:\n\n* **Card grid:** `grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 sm:gap-6`.\n* **Split:** text and visual side by side with `lg:grid-cols-2`, alternating sides from one section to the next.\n* **Bento:** one large tile (`lg:col-span-2`) with smaller tiles around it, instead of identical boxes.\n* **Asymmetric:** `lg:grid-cols-[2fr_1fr]` for main content plus a side column. Grid templates like this are the one allowed exception to the no-arbitrary-values rule.\n\nAdd `min-w-0` to flex and grid children that contain text, so truncation works instead of overflowing.\n\nAvoid the default \"three equal cards in a row\" on every section."
279
+ },
280
+ {
281
+ "number": 56,
282
+ "title": "Hero / Above the Fold",
283
+ "content": "The hero must answer \"what is this and why should I care\" within 5 seconds.\n\nRecommended order:\n\n```text\nBadge short eyebrow (New, Beta, v2.0)\nH1 value proposition, under 10 words\nLead text text-lg text-secondary, one or two sentences\nActions one primary Button + one secondary Button\nProof real product screenshot, stat row, or customer logos\n```\n\n* Left-align by default. Center only short, single-message heroes.\n* Use a split layout (text left, visual right) on `lg` and stack on mobile.\n* One primary action only. The second action is outline or ghost."
284
+ },
285
+ {
286
+ "number": 57,
287
+ "title": "Focal Point & Visual Interest",
288
+ "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."
289
+ },
290
+ {
291
+ "number": 58,
292
+ "title": "Section Variety",
293
+ "content": "A page should feel composed, not stamped out.\n\n* Never use the same layout for two sections in a row.\n* Mix patterns: split, card grid, bento, full-width band, stat row, testimonial, FAQ, CTA band.\n* Alternate background surfaces between neighbouring sections.\n* End every landing page with a clear call-to-action section."
294
+ },
295
+ {
296
+ "number": 59,
297
+ "title": "Breakpoint Checklist",
298
+ "content": "Design mobile-first, then check every page at:\n\n```text\n360px small phone\n768px tablet\n1024px small laptop\n1280px desktop\n1536px large desktop\n```\n\nAt every width:\n\n* No horizontal scroll.\n* Touch targets are at least 44px.\n* Navigation collapses into a Drawer below `md`.\n* Tables sit inside `overflow-x-auto`.\n* Images use an `aspect-*` class with `object-cover`, so nothing shifts while loading.\n* On mobile, stack content in order of importance (use `order-*` when the source order differs)."
299
+ },
300
+ {
301
+ "number": 60,
302
+ "title": "Imagery & Media",
303
+ "content": "* Use consistent aspect ratios: `aspect-video`, `aspect-square`, or `aspect-[4/3]` (allowed ratio).\n* Use one corner radius for all images on a page.\n* Always write real, descriptive `alt` text.\n* Lazy-load images below the fold.\n* Prefer real product screenshots over stock illustrations or abstract shapes."
304
+ },
305
+ {
306
+ "number": 61,
307
+ "title": "Iconography",
308
+ "content": "* Use lucide-react icons only.\n* Match icon size to the text beside it: 16px with `text-sm`, 20px with `text-base`, 24px next to headings.\n* Keep the same stroke width across the whole interface.\n* Icons support labels. They do not replace them, except in an IconButton with a Tooltip.\n* Do not wrap every icon in a colored circle."
309
+ },
310
+ {
311
+ "number": 62,
312
+ "title": "Motion Timing",
313
+ "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."
314
+ },
315
+ {
316
+ "number": 63,
317
+ "title": "Microcopy",
318
+ "content": "Words are part of the design.\n\n* Sentence case for headings, buttons and labels.\n* Buttons start with a verb: \"Create project\", not \"Submit\".\n* Headlines state the benefit, not the feature name.\n* One idea per sentence. Short sentences.\n* No em dashes. Use a period, comma or colon instead."
259
319
  }
260
320
  ],
261
321
  "goldenRule": {
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema#",
3
3
  "package": "@neuctra/ui",
4
- "version": "1.0.9",
5
- "generatedAt": "2026-09-27T15:08:02.263Z",
4
+ "version": "1.0.14",
5
+ "generatedAt": "2026-10-07T06:01:15.313Z",
6
6
  "componentCount": 79,
7
7
  "components": [
8
8
  {
@@ -3111,7 +3111,7 @@
3111
3111
  },
3112
3112
  {
3113
3113
  "name": "size",
3114
- "type": "\"sm\" | \"md\" | \"lg\"",
3114
+ "type": "\"xs\" | \"sm\" | \"md\" | \"lg\"",
3115
3115
  "required": false,
3116
3116
  "default": null,
3117
3117
  "description": "Size variant controlling padding, font size and icon sizing."
@@ -5315,7 +5315,7 @@
5315
5315
  },
5316
5316
  {
5317
5317
  "name": "size",
5318
- "type": "\"sm\" | \"md\" | \"lg\"",
5318
+ "type": "\"xs\" | \"sm\" | \"md\" | \"lg\"",
5319
5319
  "required": false,
5320
5320
  "default": null,
5321
5321
  "description": "Size variant controlling trigger/item padding and icon sizing."
@@ -0,0 +1,86 @@
1
+ {
2
+ "title": "Neuctra UI: SEO, AEO and GEO Guide",
3
+ "intro": "A practical playbook for making sites built with @neuctra/ui rank in search engines (SEO), get picked as the answer in featured snippets, AI Overviews and voice (AEO), and get cited by generative engines like ChatGPT, Perplexity, Claude and Gemini (GEO). It includes page templates for tool, category and home pages, site-wide essentials, and ads readiness. Pair it with the generate_page_seo tool (per-page meta, OpenGraph and a woven JSON-LD graph for your framework) and the audit_page_seo tool (pass/warn/fail checks with exact fixes).",
4
+ "topics": [
5
+ {
6
+ "id": "technical",
7
+ "title": "Technical SEO Foundations",
8
+ "content": "Search engines and AI crawlers can only rank what they can fetch, render and understand.\n\n**Render on the server.** Titles, meta tags, JSON-LD and the main body text must be in the initial HTML (SSR or SSG). Google renders JavaScript late and not always; most AI crawlers (GPTBot, ClaudeBot, PerplexityBot) do not run JavaScript at all. A client-only SPA that patches `<title>` in a `useEffect` is effectively invisible to them.\n\n**Canonical URLs.** Every indexable page declares one absolute canonical: `<link rel=\"canonical\" href=\"https://example.com/docs/button\">`. Pick one host (with or without `www`), one protocol (`https`) and one trailing-slash style, and 301-redirect every other variant to it.\n\n**URLs.** Short, lowercase, kebab-case, readable: `/docs/date-picker`, not `/Docs/DatePicker?id=12`. Never change a live URL without a 301 redirect.\n\n**robots.txt.** Lives at `/robots.txt`, points to the sitemap, and blocks only what must never be crawled (admin, API, internal search results):\n\n```text\nUser-agent: *\nAllow: /\nDisallow: /api/\nDisallow: /admin/\n\nSitemap: https://example.com/sitemap.xml\n```\n\n`robots.txt` controls crawling, not indexing. To keep a crawlable page out of results use `<meta name=\"robots\" content=\"noindex\">` (and do not also block it in robots.txt, or the noindex is never seen).\n\n**XML sitemap.** Lists every canonical, indexable URL (never redirects, 404s or noindex pages) with an accurate `<lastmod>`. Regenerate it on every build (e.g. `next-sitemap`, `@astrojs/sitemap`) and submit it in Google Search Console and Bing Webmaster Tools.\n\n**Site architecture.** Every important page is reachable within 3 clicks of the home page and has at least one internal link pointing to it (no orphan pages). Use real `<a href>` links; buttons with `onClick` navigation are not crawled.\n\n**Status codes.** 200 for real pages, 301 for permanent moves, 404/410 for removed pages. A \"not found\" screen that returns 200 (soft 404) wastes crawl budget.\n\n**noindex** thin or utility pages: login, cart, account, internal search, tag pages with one post, paginated archives beyond page 1 if they add nothing.\n\n**International sites.** Use `hreflang` alternates (`<link rel=\"alternate\" hreflang=\"de\" href=\"...\">`) plus `x-default`, and keep one language per URL.\n\n**HTTPS and security.** HTTPS everywhere, no mixed content, HSTS enabled.\n\n**Only the widget may be client-only.** Interactive tools (editors, converters, canvas, file processing) often need `dynamic(() => import(\"./Tool\"), { ssr: false })` or a client-only island. Wrap only the widget that way. The page frame around it (breadcrumb, H1, lead paragraph, article sections, FAQ and JSON-LD) must render on the server. If the whole page is client-only, the built HTML has no H1, no text and no schema, and crawlers see an empty page.\n\n**One URL registry.** Keep every route in one data file (e.g. `lib/routes.js` with categories and pages, each with an `href`). Generate navigation, the sitemap, `llms.txt`, breadcrumbs and related links from it, so a renamed URL can't leave stale links behind.\n\n**Redirect old slugs.** When a URL changes, add a permanent 301 from the old path, update the registry, and regenerate the sitemap and `llms.txt`. They must list only final URLs, never URLs that redirect.\n\n**Sitemap dates.** Set `<lastmod>` to the date the content really changed, not the build time for every URL: a lastmod that always changes is ignored. Google ignores `<priority>` and `<changefreq>`, so don't spend effort tuning them. Exclude admin, API, 404 and other noindex routes."
9
+ },
10
+ {
11
+ "id": "performance",
12
+ "title": "Performance and Core Web Vitals",
13
+ "content": "Core Web Vitals are a ranking signal and a conversion factor. Targets at the 75th percentile of real users:\n\n```text\nLCP (Largest Contentful Paint) < 2.5s\nINP (Interaction to Next Paint) < 200ms\nCLS (Cumulative Layout Shift) < 0.1\n```\n\n**LCP**\n* The hero image is the usual LCP element: serve it in AVIF/WebP, sized to the viewport, and mark it high priority (`priority` on `next/image`, `fetchpriority=\"high\"` and no `loading=\"lazy\"` on a plain `<img>`).\n* Lazy-load everything below the fold.\n* Preconnect to critical third-party origins; self-host fonts where possible.\n\n**CLS**\n* Give every image, video and embed explicit `width`/`height` or an `aspect-*` class.\n* Reserve space for banners, ads and late-loading content.\n* Load fonts with `font-display: swap` and a size-matched fallback.\n\n**INP**\n* Keep main-thread tasks under 50ms: split large bundles, defer non-critical scripts, avoid heavy work in click handlers.\n* Load analytics and chat widgets after interaction or idle.\n\n**Measure** with PageSpeed Insights (field + lab data), the Search Console Core Web Vitals report and Lighthouse. Lab scores alone are not what Google ranks on.\n\n**Avoid layout shift from theme and ads**\n* Apply the saved light/dark theme with a tiny inline script in `<head>` before first paint, so the page doesn't flash and re-layout.\n* Reserve the height of ad slots and embeds before they load, and only load them when they near the viewport."
14
+ },
15
+ {
16
+ "id": "on-page",
17
+ "title": "On-Page SEO",
18
+ "content": "**Title tag** (the single strongest on-page signal)\n* 50 to 60 characters (Google truncates around 580px).\n* Primary keyword first, then a benefit or differentiator, then the brand: `React Date Picker Component: Accessible and Themeable | Neuctra UI`, `Merge PDF Online Free: Combine Files, No Sign-Up | Brand`.\n* Long-tail modifiers people actually search belong in the title when true: \"free\", \"online\", \"no sign-up\", \"without watermark\", \"for React\".\n* **One brand-suffix rule for the whole site.** Add ` | Brand` in exactly one place (a title template or one metadata builder) and never hand-type it into individual titles. Mixing the two produces missing suffixes on some pages and doubled ones (`| Brand | Brand`) on others.\n* Unique on every page. Never \"Home\", \"Untitled\" or the same title site-wide.\n* Home page: `Brand: what it is in plain words`.\n\n**Meta description** (not a ranking factor, but it drives click-through)\n* 140 to 155 characters.\n* Formula: primary keyword + what the page or tool does + trust points + call to action. Example: \"Merge PDF files online for free. Combine documents in seconds, right in your browser. No upload, no sign-up, no watermark. Merge your PDFs now.\"\n* Trust points that are true for the page (\"no sign-up\", \"files never leave your device\", \"free forever\") lift click-through.\n* Unique per page. If missing or weak, Google writes its own from page text.\n\n**Headings**\n* Exactly one `<h1>`, matching the search intent and close to the title (not identical is fine).\n* `<h2>`/`<h3>` in order, never skipping levels. Phrase several `<h2>`s as the questions people actually search.\n\n**Body**\n* Primary keyword (or a close variant) in the first 100 words.\n* Cover the topic completely: answer the main question, the follow-up questions and the obvious objections.\n* Short paragraphs, lists and tables where they fit. Write for people; no keyword stuffing.\n\n**Links**\n* Descriptive internal anchor text (\"React table component\", never \"click here\").\n* Link down to child pages and across to related pages. Link out to authoritative sources when you cite facts.\n\n**Images**\n* Descriptive `alt` text for meaningful images, empty `alt=\"\"` for decorative ones.\n* Descriptive file names (`react-date-picker-dark-mode.webp`).\n\n**Social previews**\n* OpenGraph and Twitter tags with a 1200x630 image on every shareable page.\n\n**Social copy.** OpenGraph title and description may be a shorter, punchier variant of the SEO title and description (`og:title` does not need the brand suffix). Every page still needs its own `og:image`.\n\n**Meta keywords.** Google ignores `<meta name=\"keywords\">`. Research long-tail variants (free, online, no sign-up, without watermark, for beginners, vs competitor) and use them in the title, H2s, body and FAQ questions instead. A keywords tag is harmless, but it does nothing for ranking."
19
+ },
20
+ {
21
+ "id": "keywords-intent",
22
+ "title": "Keywords, Search Intent and Site Structure",
23
+ "content": "**One page, one primary intent.** Decide what a page should rank for before writing it:\n\n```text\nInformational \"what is a date picker\" guide, docs, blog\nCommercial \"best react ui library\" comparison, landing\nTransactional \"neuctra ui pricing\" pricing, signup\nNavigational \"neuctra ui docs\" home, docs index\n```\n\n* Pick one primary keyword and a handful of close variants per page.\n* Two pages targeting the same keyword compete with each other (cannibalisation). Merge them or differentiate the intent.\n\n**Topic clusters.** Build a pillar page for each core topic (e.g. \"React UI Components\") and cluster pages for each subtopic (Button, Modal, Date Picker). The pillar links to every cluster page and every cluster page links back to the pillar and to its siblings. This is how topical authority is earned.\n\n**Research sources.** Google Search Console queries you already rank for on page 2, \"People also ask\", autocomplete, related searches, competitor pages that rank, and your own support and sales questions.\n\n**Map it.** Keep a simple keyword map (URL, primary keyword, intent, status) so no two pages chase the same query."
24
+ },
25
+ {
26
+ "id": "eeat",
27
+ "title": "E-E-A-T and Trust Signals",
28
+ "content": "Google's quality raters look for Experience, Expertise, Authoritativeness and Trust. AI engines prefer the same sources when choosing what to cite.\n\n* **Real authorship.** Named authors with a short bio and links to their profiles for articles and guides. Use `author` in the schema.\n* **Dates.** Show \"Published\" and \"Last updated\" dates on content that ages, and mirror them in `datePublished` / `dateModified`. Only bump `dateModified` when the content really changed.\n* **Evidence.** Original data, benchmarks, screenshots, code that runs, and citations to primary sources.\n* **Transparency.** About, Contact, Privacy Policy and Terms pages; a physical or company address where relevant.\n* **Consistency.** The same brand name, logo and description everywhere (site, GitHub, npm, social profiles, directories).\n* **Reputation.** Reviews and mentions on third-party sites count for more than claims on your own site."
29
+ },
30
+ {
31
+ "id": "aeo",
32
+ "title": "AEO: Answer Engine Optimisation",
33
+ "content": "AEO targets the answer surfaces: featured snippets, \"People also ask\", Google AI Overviews, voice assistants. The goal is to be the passage an engine lifts as the answer.\n\n**Answer-first structure**\n* Phrase key `<h2>`s as questions: \"How do I add a date picker in React?\"\n* Put a direct, self-contained answer of 40 to 60 words right under the question, then expand with detail.\n* Start definitions with the term: \"A date picker is a form control that ...\"\n\n**Snippet-friendly formats**\n* Steps: an ordered list (`<ol>`) with one action per item.\n* Comparisons: a real `<table>` with clear column headers.\n* Lists of options: an unordered list with the item name first.\n\n**FAQ block on every key page**\n* 4 to 8 real questions with concise answers (see the `faq` topic), marked up with `FAQPage` schema.\n\n**Voice and conversational queries**\n* Cover long, natural questions (\"which react ui library works with tailwind v4\").\n* Keep answers short and speakable; avoid tables-only answers for questions people ask aloud.\n\n**Make the answer easy to extract**\n* Plain HTML text, not text baked into images, canvas or tabs that only render on click.\n* One idea per paragraph. No filler introduction before the answer."
34
+ },
35
+ {
36
+ "id": "geo",
37
+ "title": "GEO: Generative Engine Optimisation",
38
+ "content": "GEO targets being retrieved and cited by generative engines: ChatGPT search, Perplexity, Claude, Gemini, Copilot and Google AI Mode. They pick sources that are crawlable, clear, specific and trusted.\n\n**1. Let them crawl.** Server-render the content (they rarely run JavaScript) and make an explicit robots.txt decision per bot:\n\n```text\n# Search / answer bots: allow these if you want to be cited\nUser-agent: OAI-SearchBot\nAllow: /\nUser-agent: ChatGPT-User\nAllow: /\nUser-agent: PerplexityBot\nAllow: /\nUser-agent: Claude-SearchBot\nAllow: /\nUser-agent: Claude-User\nAllow: /\n\n# Training bots: a business decision, allow or disallow\nUser-agent: GPTBot\nAllow: /\nUser-agent: ClaudeBot\nAllow: /\nUser-agent: Google-Extended\nAllow: /\nUser-agent: CCBot\nAllow: /\n```\n\nBlocking a search bot means that engine cannot cite you. Blocking a training bot does not stop citations from its search bot.\n\n**2. Publish llms.txt.** A markdown index at `/llms.txt` (spec: llmstxt.org): an H1 with the site name, a one-paragraph summary in a blockquote, then sections of `- [Page title](url): one-line description`. Optionally `/llms-full.txt` with the full text of key docs. Generate it at build time from the same route registry as the sitemap, so it never lists old URLs that now redirect.\n\n**3. Be the clearest source.**\n* State facts plainly and specifically: numbers, versions, dates, limits, prices.\n* Keep sections self-contained so a single passage makes sense when quoted alone.\n* Add comparison tables, definitions and step lists; engines quote these heavily.\n* Cite primary sources and include original data or benchmarks worth citing.\n\n**4. Strengthen the entity.**\n* Use the same brand name and one-line description everywhere.\n* `Organization` schema with `logo` and `sameAs` links (GitHub, npm, LinkedIn, X, YouTube, Wikipedia/Wikidata if you have them).\n* Earn mentions on sites the engines already trust: docs aggregators, GitHub, Reddit, Stack Overflow, industry publications, review sites.\n\n**5. Stay fresh.** Show and maintain \"Last updated\" dates; engines favour current sources for anything version-sensitive.\n\n**6. Get indexed by Bing.** ChatGPT search and Copilot lean on Bing's index: verify the site in Bing Webmaster Tools, submit the sitemap and ping IndexNow on publish.\n\n**7. Measure.** Track referral traffic from chatgpt.com, perplexity.ai, gemini.google.com and copilot.microsoft.com, and regularly ask those engines your target questions to see who they cite."
39
+ },
40
+ {
41
+ "id": "schema",
42
+ "title": "Structured Data and Schema Weaving",
43
+ "content": "Structured data (JSON-LD) tells engines exactly what a page is. **Schema weaving** means emitting one connected `@graph` per page instead of several disconnected blobs, with nodes referencing each other by stable `@id`.\n\n**Stable @id scheme** (reuse the exact same IDs on every page):\n\n```text\nOrganization https://example.com/#organization\nWebSite https://example.com/#website\nWebPage https://example.com/docs/card#webpage\nBreadcrumbList https://example.com/docs/card#breadcrumb\nMain entity https://example.com/docs/card#article (or #product, #software)\nFAQPage https://example.com/docs/card#faq\n```\n\n**Every page** gets Organization + WebSite + a WebPage (or subtype) + BreadcrumbList, wired together:\n* `WebSite.publisher` -> Organization\n* `WebPage.isPartOf` -> WebSite, `WebPage.breadcrumb` -> BreadcrumbList\n* main entity `mainEntityOfPage` -> WebPage, `publisher` -> Organization\n\n**Type map**\n\n```text\nhome WebPage (+ Organization, WebSite as the main entities)\ndocs WebPage + TechArticle\nblog WebPage + BlogPosting (author, datePublished, dateModified, image)\nproduct WebPage + SoftwareApplication or Product\npricing WebPage + Product with Offer items (real prices only)\nlanding WebPage\nfaq FAQPage (as the page type)\nabout AboutPage\ncontact ContactPage\ncategory CollectionPage\n```\n\n**Example graph**\n\n```json\n{\n \"@context\": \"https://schema.org\",\n \"@graph\": [\n { \"@type\": \"Organization\", \"@id\": \"https://example.com/#organization\", \"name\": \"Example\", \"url\": \"https://example.com\", \"logo\": \"https://example.com/logo.png\", \"sameAs\": [\"https://github.com/example\"] },\n { \"@type\": \"WebSite\", \"@id\": \"https://example.com/#website\", \"url\": \"https://example.com\", \"name\": \"Example\", \"publisher\": { \"@id\": \"https://example.com/#organization\" } },\n { \"@type\": \"WebPage\", \"@id\": \"https://example.com/docs/card#webpage\", \"url\": \"https://example.com/docs/card\", \"name\": \"Card Component | Example\", \"isPartOf\": { \"@id\": \"https://example.com/#website\" }, \"breadcrumb\": { \"@id\": \"https://example.com/docs/card#breadcrumb\" } },\n { \"@type\": \"BreadcrumbList\", \"@id\": \"https://example.com/docs/card#breadcrumb\", \"itemListElement\": [\n { \"@type\": \"ListItem\", \"position\": 1, \"name\": \"Home\", \"item\": \"https://example.com/\" },\n { \"@type\": \"ListItem\", \"position\": 2, \"name\": \"Docs\", \"item\": \"https://example.com/docs\" },\n { \"@type\": \"ListItem\", \"position\": 3, \"name\": \"Card\", \"item\": \"https://example.com/docs/card\" }\n ] },\n { \"@type\": \"TechArticle\", \"@id\": \"https://example.com/docs/card#article\", \"headline\": \"Card Component\", \"mainEntityOfPage\": { \"@id\": \"https://example.com/docs/card#webpage\" }, \"publisher\": { \"@id\": \"https://example.com/#organization\" } }\n ]\n}\n```\n\n**Rules**\n* Structured data must describe what is visible on the page. Never mark up content users cannot see.\n* Never invent reviews, ratings, prices or authors. Fake markup risks a manual action.\n* Since 2023 Google shows FAQ rich results only for well-known government and health sites, and HowTo rich results are gone. Still add `FAQPage` where there is a visible FAQ: it helps AI Overviews and generative engines understand the Q&A.\n* Emit JSON-LD in the server-rendered HTML. Escape `<` as `\\u003c` when injecting it into a `<script>` tag.\n* Validate every template with Google's Rich Results Test and validator.schema.org before shipping.\n\nUse the `generate_page_seo` tool to build a woven graph for any page.\n\n**One node per type per page.** A page must not emit two `SoftwareApplication`, two `FAQPage` or two `BreadcrumbList` nodes. This happens when a shared page shell emits schema and the individual page adds its own `<script type=\"application/ld+json\">` too. Pick one owner (the shell), pass the data into it, and delete the page-level duplicate.\n\n**One data source for visible content and schema.** Build the visible steps list and the `HowTo` node from the same array, and the visible FAQ accordion and the `FAQPage` node from the same array. They then can't drift apart, and nothing is shown twice.\n\n**Tool and web-app pages** (free online tools, converters, calculators, generators):\n* `SoftwareApplication` with `applicationCategory` (e.g. `UtilitiesApplication`, `DeveloperApplication`, `MultimediaApplication`), `operatingSystem` (\"Web\" or \"All\"), `featureList`, `isAccessibleForFree: true` and an `Offer` with `price: \"0\"` only if the tool really is free.\n* `HowTo` with the visible usage steps. Google no longer shows HowTo rich results, but engines still use the steps for answers.\n* `BreadcrumbList` (Home > Category > Tool) and `FAQPage`.\n\n**Listing pages**\n* Category or collection pages: `CollectionPage` + an `ItemList` of the pages it links to, in visible order.\n* Home page: `ItemList`s for the main categories and popular items, next to Organization and WebSite.\n\n**Optional extras, with honest expectations**\n* `WebSite` `potentialAction` `SearchAction`: fine if the site has search, but Google retired the sitelinks search box in 2024, so it no longer changes how results look.\n* `speakable`: a beta mostly limited to news publishers; low value for other sites."
44
+ },
45
+ {
46
+ "id": "faq",
47
+ "title": "Writing FAQs That Rank and Get Cited",
48
+ "content": "**Where the questions come from:** Google \"People also ask\", autocomplete, Search Console queries, Reddit and forum threads, support tickets and sales calls. Never invent questions nobody asks.\n\n**Per page**\n* 4 to 8 questions, specific to that page. Never reuse the same FAQ block across pages.\n* Question as the user would type or say it: \"Does the date picker support keyboard navigation?\"\n* Answer in 40 to 80 words: direct answer in the first sentence, then the key detail. Plain text, no marketing fluff.\n* Include the page's primary keyword or entity name naturally in at least one question.\n\n**Markup**\n* Render the FAQ visibly on the page (an Accordion is fine, as long as the text is in the HTML).\n* Mirror the exact same questions and answers in `FAQPage` schema (`mainEntity` of `Question` items with an `acceptedAnswer` `Answer`).\n* The visible text and the schema text must match word for word.\n\n**Maintenance**\n* Update answers when the product changes, and bump `dateModified`.\n* Add new questions as support and search data reveal them."
49
+ },
50
+ {
51
+ "id": "meta-checklist",
52
+ "title": "Per-Page Meta Checklist",
53
+ "content": "Every indexable page ships these tags in the server-rendered `<head>`:\n\n```html\n<html lang=\"en\">\n<meta charset=\"utf-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n<title>Primary Keyword: Qualifier | Brand</title>\n<meta name=\"description\" content=\"140 to 155 characters, unique, with the value and a reason to click.\">\n<link rel=\"canonical\" href=\"https://example.com/path\">\n<meta name=\"robots\" content=\"index, follow, max-image-preview:large\">\n\n<meta property=\"og:type\" content=\"website\"> <!-- \"article\" for blog posts -->\n<meta property=\"og:site_name\" content=\"Brand\">\n<meta property=\"og:title\" content=\"Same as or close to the title\">\n<meta property=\"og:description\" content=\"Same as or close to the description\">\n<meta property=\"og:url\" content=\"https://example.com/path\">\n<meta property=\"og:image\" content=\"https://example.com/og/path.png\"> <!-- 1200x630 -->\n<meta property=\"og:image:alt\" content=\"What the image shows\">\n\n<meta name=\"twitter:card\" content=\"summary_large_image\">\n<meta name=\"twitter:title\" content=\"...\">\n<meta name=\"twitter:description\" content=\"...\">\n<meta name=\"twitter:image\" content=\"https://example.com/og/path.png\">\n\n<link rel=\"icon\" href=\"/favicon.svg\" type=\"image/svg+xml\">\n<link rel=\"apple-touch-icon\" href=\"/apple-touch-icon.png\">\n<meta name=\"theme-color\" content=\"#ffffff\">\n\n<script type=\"application/ld+json\">{ \"@context\": \"https://schema.org\", \"@graph\": [ ... ] }</script>\n```\n\nChecks:\n* Title and description are unique across the whole site.\n* Canonical and `og:url` are absolute and identical.\n* OG image URL is absolute, 1200x630, under about 5MB, and readable at small sizes.\n* Blog posts also get `article:published_time` and `article:modified_time`.\n* Utility pages use `<meta name=\"robots\" content=\"noindex, follow\">`."
54
+ },
55
+ {
56
+ "id": "frameworks",
57
+ "title": "Where Metadata Goes in Each Framework",
58
+ "content": "Neuctra UI runs anywhere React 18+ and Tailwind v4 run. The rule is the same everywhere: metadata and JSON-LD must be in the server-rendered HTML. The `generate_page_seo` tool outputs a ready snippet for each of these.\n\n**Next.js App Router** (`framework: \"nextjs-app\"`)\n* `export const metadata = {...}` or `export async function generateMetadata()` in `page.js` or `layout.js`. Use `alternates.canonical`, `openGraph`, `twitter`, `robots`.\n* Set `metadataBase: new URL(\"https://example.com\")` in the root layout so relative URLs resolve.\n* A `\"use client\"` page cannot export metadata: put it in the route's `layout.js` instead.\n* **Metadata merging is shallow.** A child segment's `openGraph` object replaces the parent's completely. If a page sets `openGraph` at all, it must repeat `images` (and `siteName`, `locale`), or the page ships without an `og:image`. The same applies to `twitter`.\n* **Title template.** `title: { template: \"%s | Brand\", default: \"...\" }` in the root layout adds the suffix to child titles. Child titles must then not include the brand themselves, or it doubles. When a builder already returns a full title, use `title: { absolute: \"...\" }` so the template is skipped.\n* **Robots for Googlebot** uses kebab-case keys: `robots: { index: true, follow: true, googleBot: { index: true, follow: true, \"max-image-preview\": \"large\", \"max-snippet\": -1, \"max-video-preview\": -1 } }`. camelCase keys like `maxImagePreview` are ignored.\n* **Client-only widgets:** `dynamic(() => import(\"./Widget\"), { ssr: false })` must wrap only the widget. Keep the H1, text, FAQ and JSON-LD in the server-rendered `page.js`.\n* `output: \"export\"` (static export) is fully crawlable: everything above still applies, and you can check the result in the `out/` HTML.\n* JSON-LD: render `<script type=\"application/ld+json\" dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd).replace(/</g, \"\\\\u003c\") }} />` in the page or layout.\n* `app/sitemap.js` and `app/robots.js` generate those files natively.\n\n**Next.js Pages Router** (`\"nextjs-pages\"`)\n* `import Head from \"next/head\"` and render the tags inside `<Head>`. Pages are pre-rendered, so crawlers see them.\n\n**Vite + React SPA** (`\"react-vite\"`)\n* React 19 hoists `<title>`, `<meta>` and `<link>` rendered anywhere in the tree into `<head>`. On React 18 use `react-helmet-async`.\n* Warning: a client-only SPA ships an empty HTML shell. Prerender the routes at build time or move to an SSR framework (Next.js, React Router, Astro, TanStack Start) for anything that must rank or be cited.\n\n**React Router v7 / Remix** (`\"react-router\"`)\n* Export `meta()` from the route module returning `[{ title }, { name: \"description\", content }, { tagName: \"link\", rel: \"canonical\", href }, { \"script:ld+json\": jsonLd }]`.\n\n**Astro** (`\"astro\"`)\n* Put the tags in the layout's `<head>`, passing title/description as props. JSON-LD: `<script type=\"application/ld+json\" set:html={JSON.stringify(jsonLd)} />`. Use React islands for Neuctra UI components. `@astrojs/sitemap` builds the sitemap.\n\n**TanStack Start** (`\"tanstack-start\"`)\n* Return `{ meta, links, scripts }` from the route's `head()` option; JSON-LD goes in `scripts` as `{ type: \"application/ld+json\", children: JSON.stringify(jsonLd) }`.\n\n**Gatsby** (`\"gatsby\"`)\n* `export const Head = () => (<>...tags...</>)` from the page component.\n\n**Plain HTML / other** (`\"html\"`)\n* Put the tags from the `meta-checklist` topic directly in `<head>`."
59
+ },
60
+ {
61
+ "id": "page-templates",
62
+ "title": "Page Templates for Tool, Category and Home Pages",
63
+ "content": "Consistent templates make every page crawlable, answerable and internally linked by default.\n\n**Tool / product page** (e.g. a free online tool or a single feature):\n\n```text\n<main>\n <header>\n Visible breadcrumb Home > Category > Tool (matches BreadcrumbList)\n Category Badge\n H1 primary keyword + differentiator\n Lead paragraph text-secondary, 1 to 2 sentences, keyword in it\n </header>\n The tool / product UI client-only widget is fine here\n <article>\n <section> H2 intro what it is, who it's for, keyword in first 100 words\n <section> H2 \"How to <task>\" <ol> steps (same data as the HowTo schema)\n <section> H2 benefits H3 per benefit\n <section> H2 \"Who uses <tool>\" use cases + 3 to 4 related links\n <section> H2 privacy / trust e.g. \"Your files stay on your device\"\n <section> H2 FAQ accordion, 6 to 8 questions (same data as FAQPage)\n </article>\n</main>\n```\n\n**Category page**\n* H1 + lead paragraph, then an H2 above the grid of items (never jump from H1 to H3 card titles).\n* Each card links to its page with descriptive anchor text.\n* `CollectionPage` + `ItemList` + `BreadcrumbList` schema.\n\n**Home page**\n* H1 stating what the site is, a lead paragraph, the main categories and popular items, a short FAQ.\n* `Organization`, `WebSite`, `ItemList`s of categories and popular items, `FAQPage`.\n\n**Internal linking**\n* Render related links from the route registry with a shared `RelatedLinks` component and the framework's link component (`next/link`, `<Link>`), never hand-typed `<a>` tags that go stale.\n* Link each page to its category, 3 to 4 siblings, and the category to every child."
64
+ },
65
+ {
66
+ "id": "site-wide",
67
+ "title": "Site-Wide Essentials",
68
+ "content": "Set these once in the root layout and every page inherits them.\n\n* `<html lang=\"...\">`, `<meta name=\"viewport\">`, `<meta charset=\"utf-8\">`.\n* A default `og:image` (1200x630), overridden per page or per category where you can.\n* `Organization` with `logo` and `sameAs` (GitHub, LinkedIn, X, YouTube, ...) and `WebSite` with `publisher`, both with stable `@id`s.\n* Search engine verification: `google-site-verification` and `msvalidate.01` meta tags (or DNS verification).\n* `manifest.webmanifest`, `theme-color`, favicon (SVG + ICO) and `apple-touch-icon` (180x180).\n* Privacy-friendly analytics that separates organic and AI-referral traffic.\n* Fonts with `font-display: swap`; the theme set before first paint.\n* Trust pages linked in the footer: About, Contact (with a real email address), Privacy Policy, Terms, and a Disclaimer where relevant.\n* `robots.txt` and the sitemap generated by the build, not maintained by hand."
69
+ },
70
+ {
71
+ "id": "ads-readiness",
72
+ "title": "Ads and Monetisation Without Hurting SEO",
73
+ "content": "Ad networks (Google AdSense and others) review trust and content quality, and badly loaded ads hurt Core Web Vitals.\n\n* Publish `/ads.txt` at the site root, generated at build time from your publisher ID.\n* Add the network's account verification meta tag in the root layout.\n* Load ad scripts after the page is interactive (`strategy=\"afterInteractive\"` or `lazyOnload` with `next/script`), and only when the publisher ID is configured.\n* Reserve each slot's size before it loads, and fill slots only when they come near the viewport, to avoid layout shift.\n* Never push the main content or the tool below the fold with ads, and never place ads inside the H1/lead block.\n* Have About, Contact, Privacy (with the ads and cookie disclosure), Terms and Disclaimer pages live before applying.\n* Keep substantial, original content on every monetised page. Thin pages with ads are the most common rejection reason."
74
+ },
75
+ {
76
+ "id": "off-page-monitoring",
77
+ "title": "Off-Page Authority and Monitoring",
78
+ "content": "**Authority**\n* Earn links, don't buy them: publish genuinely useful resources (templates, benchmarks, free tools, open-source code), get listed in relevant directories and \"awesome\" lists, write guest posts and answer questions where your audience asks them.\n* Digital PR: original data and strong opinions get cited by journalists and by AI engines.\n* Keep the brand consistent across GitHub, npm, social profiles and directories.\n\n**Setup on launch**\n* Google Search Console: verify the domain property, submit the sitemap, check indexing and Core Web Vitals reports.\n* Bing Webmaster Tools: verify (you can import from Search Console), submit the sitemap, enable IndexNow.\n* Analytics that separate organic search and AI referrals (chatgpt.com, perplexity.ai, gemini.google.com, copilot.microsoft.com).\n\n**Ongoing**\n* Weekly: Search Console coverage errors, new queries on page 2 worth improving.\n* Monthly: rankings for target keywords, pages losing clicks, Core Web Vitals, broken links, which sources AI engines cite for your target questions.\n* Refresh top pages every few months: new facts, new FAQs, updated `dateModified`."
79
+ },
80
+ {
81
+ "id": "launch-checklist",
82
+ "title": "SEO / AEO / GEO Launch Checklist",
83
+ "content": "Run this before any page or site goes live. Every item is pass or fail.\n\n**Check the built HTML, not the source code.** Run the production build and inspect the output (`view-source:`, or grep the static `out/` / `dist/` HTML). Bugs like client-only pages, duplicate schema and missing images only show up there.\n\n**Crawl and index**\n- [ ] Content, meta and JSON-LD are in the server-rendered HTML (view source, not DevTools)\n- [ ] One absolute canonical per page; all host/protocol/slash variants 301 to it\n- [ ] robots.txt allows the site, references the sitemap, has an explicit AI bot policy\n- [ ] sitemap.xml lists only canonical 200 pages with accurate lastmod, submitted to Google and Bing\n- [ ] Utility and thin pages are noindex; no important page is noindex by mistake\n- [ ] No orphan pages; every key page within 3 clicks of home\n- [ ] Real 404 status for missing pages\n- [ ] Every page has exactly one H1 in the built HTML (a missing H1 usually means the page renders client-only)\n- [ ] Sitemap and llms.txt list only final URLs (no 301s), generated from one route registry\n- [ ] Sitemap lastmod reflects real content changes\n\n**On-page**\n- [ ] Unique title, 50 to 60 characters, keyword first, brand last\n- [ ] Unique meta description, 140 to 155 characters\n- [ ] Exactly one H1; H2/H3 in order; several H2s phrased as questions\n- [ ] Primary keyword in the first 100 words\n- [ ] Descriptive alt text on meaningful images\n- [ ] OpenGraph + Twitter tags with a 1200x630 image on every page, including category and static pages\n- [ ] Brand suffix identical on every title, never missing and never doubled\n\n**Structured data**\n- [ ] One woven `@graph`: Organization, WebSite, WebPage, BreadcrumbList + page type node\n- [ ] FAQPage only where the FAQ is visible, text identical\n- [ ] At most one node of each type per page (no duplicate SoftwareApplication, FAQPage, BreadcrumbList)\n- [ ] Visible steps/FAQs and their schema come from the same data, and nothing is rendered twice\n- [ ] No invented reviews, ratings or prices\n- [ ] Passes Rich Results Test and validator.schema.org\n\n**AEO / GEO**\n- [ ] 40 to 60 word direct answer under each question heading\n- [ ] 4 to 8 page-specific FAQs\n- [ ] /llms.txt published and generated from the route list\n- [ ] Organization `sameAs` links and consistent brand naming\n- [ ] Visible \"Last updated\" date on content that ages\n\n**Performance**\n- [ ] LCP < 2.5s, INP < 200ms, CLS < 0.1 on mobile\n- [ ] LCP image high priority, below-fold media lazy, all media sized\n\nUse the `audit_page_seo` tool to check a page against the on-page and schema items automatically."
84
+ }
85
+ ]
86
+ }
package/data/theme.json CHANGED
@@ -27,7 +27,10 @@
27
27
  "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
28
  "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
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.",
30
- "Use correct line-height and letter-spacing for readability. Body text: leading-relaxed or leading-normal, never leading-none/leading-tight on paragraphs. Letter-spacing: leave at the default (tracking-normal) for body and headings; only use tracking-wide for short uppercase labels (badges, eyebrow text, nav labels), and never tracking-wide on paragraph-length text.",
30
+ "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
+ "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
+ "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
+ "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.",
31
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.",
32
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."
33
36
  ],
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@neuctra/ui-mcp",
3
- "version": "0.4.2",
4
- "description": "MCP server exposing the @neuctra/ui component registry (props, defaults, examples, theme tokens) so AI coding tools generate accurate Neuctra UI code.",
3
+ "version": "0.4.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",
7
7
  "author": "Your Name <tahaasifaqwe@gmail.com>",
@@ -16,7 +16,11 @@
16
16
  "neuctra",
17
17
  "ui",
18
18
  "react",
19
- "component-registry"
19
+ "component-registry",
20
+ "seo",
21
+ "aeo",
22
+ "geo",
23
+ "json-ld"
20
24
  ],
21
25
  "bin": {
22
26
  "neuctra-ui-mcp": "./bin/cli.mjs"
@@ -27,6 +31,7 @@
27
31
  "./data/components.json": "./data/components.json",
28
32
  "./data/theme.json": "./data/theme.json",
29
33
  "./data/aiDesignRules.json": "./data/aiDesignRules.json",
34
+ "./data/seoGuide.json": "./data/seoGuide.json",
30
35
  "./package.json": "./package.json"
31
36
  },
32
37
  "files": [