Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 30 additions & 3 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
> **Now:** `component-sidebar` — finish `.5`/`.6`, then ship `@vllnt/ui@0.4.0`.
> **Next:** `agent-ui-cli` (MVP) · `ai-elements-parity`.
> **Horizon (gated):** `native-parity` (needs an RN consumer) · the front-studio line (`studio` → `studio-hub` — after the CLI ships + a real need).
> **Visibility track:** SEO/GEO phases — `search-consolidation` → `ai-toolchain-registration` → `visibility-measurement` → `seo-content-engine` → `backlink-authority`. Diagnosis: infra is DONE (`agent-surface`) but GSC shows indexed-yet-buried (141 pages, 2 clicks/90d, 0 AI-query visibility) + a dead `.com` twin outranking the live `.ai`. Full plan: [strategy dossier](https://claude.ai/code/artifact/6e2359db-a626-4226-aa54-a9e53ecfd766).
> **Last updated:** 2026-07-02
> **Visibility track:** SEO/GEO phases — `search-consolidation` → `ai-toolchain-registration` → `visibility-measurement` → `mdx-content-system` → `seo-content-engine` → `backlink-authority`. Diagnosis: infra is DONE (`agent-surface`) but GSC shows indexed-yet-buried (141 pages, 2 clicks/90d, 0 AI-query visibility) + a dead `.com` twin outranking the live `.ai`. Full plan: [strategy dossier](https://claude.ai/code/artifact/6e2359db-a626-4226-aa54-a9e53ecfd766).
> **Last updated:** 2026-07-13
> **Channels:** `@latest` = `0.3.0` · `@canary` = `0.4.0-canary.<sha>` (auto-publishes on every merge to main). Tracking: [milestone 0.3.0](https://github.com/vllnt/ui/milestone/1)

Convention: phases are kebab-case outcome slugs, ordered DONE → ACTIVE → PLANNED. Tasks carry stable `<slug>.<n>` IDs; functional tasks pair with a `Validate`/`E2E` task. History is never deleted. Shipped 0.3.0 detail lives in `CHANGELOG.md` and the 197 closed issues; phases below summarize it.
Expand Down Expand Up @@ -247,11 +247,29 @@ Falls out of API-first (`studio.11`) — registration is just another API — pl
- [ ] visibility-measurement.3 Add server-log crawler monitoring for GPTBot/ClaudeBot/Claude-Code/PerplexityBot/OAI-SearchBot — proves llms.txt consumption (cmd: `grep -Ec 'GPTBot|ClaudeBot|Claude-Code' access.log`)
- [ ] visibility-measurement.4 Script a recurring GSC position/impressions review via `gsc.py` (cmd: `python3 gsc.py query --site sc-domain:ui.vllnt.com --dimensions query --days 28`)

## mdx-content-system [PLANNED]

**Goal:** Make every content page one `.mdx` file — shared component map, frontmatter-driven JSON-LD, generic shells — so a new page is a file drop, not a route.
**Exit criteria:** A new page ships by adding one `content/pages/<ns>/<slug>/en.mdx` — no TSX, no `staticRoutes()` edit; the body may embed `<ComponentGrid/>` / `<Faq/>` from a shared map; JSON-LD (FAQPage/TechArticle) is emitted by the shell from frontmatter, never the body; the page is sitemapped automatically; adding `fr.mdx` localizes it with zero code change.
**Verify:** a maintainer drops `content/pages/guides/foo/en.mdx` carrying a `<ComponentGrid/>` + `faq:` frontmatter → `/guides/foo` renders the grid, Rich Results shows FAQPage, `/sitemap.xml` lists it, and adding `fr.mdx` makes `/fr/guides/foo` French. Personas: maintainer authoring content (no TSX); AI answer engine extracting the FAQ; translator adding a locale. (needs: search-consolidation.4 for the LD helpers)

Infra already exists and is under-used: `MDXContent` (`packages/ui/src/components/mdx-content/mdx-content.tsx`) accepts a `components` map, defaults `enableMDX = true`, auto-detects JSX via `/<[A-Z]/` after stripping fenced blocks, falls back to `ReactMarkdown` + `remarkGfm` (GFM tables), and `removeImportStatements` drops import lines. `getPageContent` already resolves `<slug>/<locale>.mdx` → default locale → flat file, so i18n is opt-in per page. Today every caller passes the **empty** default map — that is the gap this phase closes.

- [ ] mdx-content-system.1 Shared MDX component map `apps/registry/lib/mdx-components.tsx` (`ComponentGrid`, `CompareTable`, `Faq`, `InstallCommand`, `Preview`), passed as `<MDXContent components={…}>` from every content shell (cmd: `grep -rc 'components={mdxComponents}' apps/registry/app/\[locale\]` → ≥4)
- [ ] mdx-content-system.2 Extend `pageFrontmatterSchema` (`apps/registry/lib/schemas.ts`) with `faq[]`, `componentSlugs[]`, `updated`, `type: +guide|vs|react`; shells emit FAQPage/TechArticle LD from frontmatter via `lib/jsonld.ts` (test: `pnpm test lib/schemas.test.ts`)
- [ ] mdx-content-system.3 Generic MDX shells `/guides/[slug]`, `/vs/[slug]`, `/react/[slug]` reading `getPageContent()` — a new page is one `.mdx`, zero TSX → docs/specs/mdx-content-system.md
- [ ] mdx-content-system.4 Sitemap enumerates MDX slugs by globbing `content/pages/**` instead of hand-listed `staticRoutes()` entries (cmd: `curl -s https://ui.vllnt.com/sitemap.xml | grep -c /guides/`)
- [ ] mdx-content-system.5 Author guard for the `evaluate()` hazard — a page containing JSX must not use inline `` `<X>` `` code-spans (MDX 3 parses them as JSX; only fenced blocks are stripped before detection) (test: `pnpm test content-mdx-brackets.test.ts`)
- [ ] mdx-content-system.6 Migrate the 3 shipped TSX `/vs` pages (shadcn, vercel-ai-sdk, assistant-ui) onto the `/vs/[slug]` MDX shell, URLs unchanged (needs: mdx-content-system.3) (cmd: `curl -s https://ui.vllnt.com/vs/shadcn | grep -c '<table'`)
- [ ] mdx-content-system.7 Validate mdx-content-system.1–6: E2E — a dropped `guides/<slug>/en.mdx` with `<ComponentGrid/>` + `faq:` renders the grid, emits FAQPage LD, and appears in the sitemap; `fr.mdx` serves `/fr/guides/<slug>`; the 3 migrated `/vs` pages still render tables at unchanged URLs (E2E: `pnpm test:e2e mdx-content`)

## seo-content-engine [PLANNED]

**Goal:** Build the content flywheel — an MDX blog plus programmatic integration / alternative / comparison pages that capture long-tail install intent and definitional AI-wedge queries.
**Exit criteria:** `/blog` + `/blog/[slug]` render MDX posts with BlogPosting JSON-LD, Shiki highlighting, per-post OG + RSS; `/integrations/{tool}` + `/alternatives/{competitor}` pages ship and are in the sitemap; 3 flagship guides live; each `/components/[slug]` has unique copy + live demo + install command.
**Verify:** a dev searching "how to build a chat ui with the vercel ai sdk" finds a VLLNT guide; `/alternatives/assistant-ui` renders a comparison table; a blog post shows correct BlogPosting rich data. Personas: dev in organic search; dev comparing libraries; AI answer engine extracting a table. (needs: search-consolidation done first)
**Verify:** a dev searching "how to build a chat ui with the vercel ai sdk" finds a VLLNT guide; `/alternatives/assistant-ui` renders a comparison table; a blog post shows correct BlogPosting rich data. Personas: dev in organic search; dev comparing libraries; AI answer engine extracting a table. (needs: search-consolidation done first · mdx-content-system for the MDX shells)

**SYNC 2026-07-13 — GSC evidence + namespace split** (90d, `sc-domain:ui.vllnt.ai`). **Evidence:** demand is entirely component-level and framework-qualified (`react callout` ~60 impr @pos 80+, `react floating action button` ~40 impr @58–95, `radix {dialog,slider,popover,scroll-area,button}` ~20 impr) — components that mostly *exist* but rank buried, so `.6`'s uniqueness pass outranks new paths for `callout` + `floating-action-button`. The **"AI UI development" head term has zero demand**: the pillar (`.13`) is a recall/GEO bet (compounding, not near-term impressions), justified because AI *component* pages already rank pos 5–7 (`ai-chat-input`, `ai-source-citation`) and the pillar funnels to them + `/families/ai`. **Namespace decision (2026-07-13):** `/vs` = tools + libs (shadcn, radix, mui, vercel-ai-sdk) · `/alternatives` (`.5`) = direct competitors (assistant-ui, copilotkit, ai-elements) — the shipped `/vs/assistant-ui` migrates in `.11` · `/integrations` (`.4`) stays distinct (how-to-use intent, not comparison) · `/guides` = evergreen reference (new namespace, `.13`/`.14`) while `/blog` (`.1`–`.3`, `.7`) stays dated articles. All new content pages are **MDX** on the `mdx-content-system` shells.

- [ ] seo-content-engine.1 Add the MDX blog: `content/blog/{slug}/{locale}.mdx` + `lib/blog.ts` (Content Collections `@content-collections/mdx`, Zod frontmatter — NOT Contentlayer; Velite fallback) mirroring `lib/content.ts` (needs: search-consolidation.4) → docs/specs/blog-system.md
- [ ] seo-content-engine.2 Routes `/blog` + `/blog/[slug]` with `generateMetadata` + BlogPosting/Breadcrumb JSON-LD + Shiki build-time highlighting + per-post OG via `ImageResponse` (cmd: `curl -s https://ui.vllnt.com/blog/<post> | grep -c '"@type":"BlogPosting"'`)
Expand All @@ -261,6 +279,13 @@ Falls out of API-first (`studio.11`) — registration is just another API — pl
- [ ] seo-content-engine.6 Per-component uniqueness pass: unique copy + live demo + install command on each `/components/[slug]` → docs/specs/component-page-uniqueness.md
- [ ] seo-content-engine.7 Publish 3 flagship guides (best react components for AI agents; assistant-ui vs ai-elements vs vllnt; render tool calls in react) — answer-first, stats + tables, TechArticle LD (cmd: `curl -s https://ui.vllnt.com/blog/best-react-components-for-ai-agents | grep -c '<table'`)
- [ ] seo-content-engine.8 Validate seo-content-engine.1–7: E2E — blog post renders with BlogPosting rich data; integration + alternative pages return 200 with tables; component page shows demo + install; RSS/sitemap include blog (E2E: `pnpm test:e2e content-engine`)
- [ ] seo-content-engine.9 `/vs/radix` MDX comparison — GSC's largest uncovered cluster (~20 impr: "radix dialog/slider/popover/scroll-area/button", no page today); GFM table, no JSX needed (needs: mdx-content-system.3) (cmd: `curl -s https://ui.vllnt.com/vs/radix | grep -c '<table'`)
- [ ] seo-content-engine.10 `/vs/mui` MDX comparison — cross-framework intent ("material design multi select", "angular floating action button") (needs: mdx-content-system.3) (cmd: `curl -s https://ui.vllnt.com/vs/mui | grep -c '<table'`)
- [ ] seo-content-engine.11 Migrate `/vs/assistant-ui` → `/alternatives/assistant-ui` + 301, per the `/vs` = tools-and-libs vs `/alternatives` = competitors split (needs: seo-content-engine.5) (cmd: `curl -sI https://ui.vllnt.com/vs/assistant-ui | grep -c 301`)
- [ ] seo-content-engine.12 `/react/{component}` framework-qualified MDX landings, hand-written unique copy (thin templates get filtered) — seed `callout`, `floating-action-button`, `code-block` from GSC's ~100 impr of `react <component>` queries (needs: mdx-content-system.3) (cmd: `curl -sI https://ui.vllnt.com/react/callout | grep -c 200`)
- [ ] seo-content-engine.13 `/guides/ai-ui` pillar MDX — AI-UI-development reference: `<ComponentGrid family="ai"/>` + `faq:` frontmatter, funnels to `/families/ai` + `/build/*` + `/vs/*`, with a Mobile/React-Native coming-soon section (needs: mdx-content-system.3) → docs/specs/ai-ui-pillar.md
- [ ] seo-content-engine.14 `/guides/streaming-ui` + `/guides/design-tokens` evergreen MDX reference pages (needs: mdx-content-system.3) (cmd: `curl -sI https://ui.vllnt.com/guides/design-tokens | grep -c 200`)
- [ ] seo-content-engine.15 Validate seo-content-engine.9–14: E2E — `/vs/radix` + `/vs/mui` render comparison tables; `/vs/assistant-ui` 301s to `/alternatives/assistant-ui`; `/react/callout` returns 200 with unique copy; `/guides/ai-ui` emits FAQPage LD + renders the AI grid + the mobile coming-soon section; all appear in `/sitemap.xml` (E2E: `pnpm test:e2e content-paths`)

## backlink-authority [PLANNED]

Expand Down Expand Up @@ -290,6 +315,8 @@ Unscheduled — pull into a phase when prioritized.
- **agent-ui-cli-v1** — config bundle, `doctor` wrapper, `add`, `ci` reusable workflow (+ `act` for local==CI), `list`/`info`/`why`/`search`, `vllnt.config`, `upgrade`; **drift gates** — `api-extractor` (public-API `.api.md` diff), `dependency-cruiser` (import boundaries across 309 components), `sherif` (dep-version drift); **test** — wrap Storybook 10 `addon-vitest` (interaction + a11y + coverage via Vitest browser mode), don't rebuild; **dual-primitive** — `context`/`check` handle `--base radix|base-ui` (Base UI ascendant, Radix at plateau).
- **agent-ui-cli-v2** — `audit` (knip + size-limit + dependency-cruiser graph), baseline gating, i18n lint, client security, `new`/scaffold, `theme new`/`edit`, `remove`/`diff`, `watch`/`report`. (Whole-site `audit --browser` + visual regression are now the **`studio`** phase; the human↔agent review loop is **`review-loop`**. Chrome DevTools MCP + Playwright MCP feed both.)
- **docs + search** — `/docs` expansion (#248), Pagefind full-text (#257), Sandpack playground (#256), `/vs` pages (#258), `/templates` (#259), i18n via next-intl (#281).
- **multiselect** — multi-select / token-input component. GSC surfaces demand with **no component today**: "multiselect" / "multiselect ui" / "multiselect 2" / "material design multi select" (~12 impr/90d, pos 73–92, `sc-domain:ui.vllnt.ai`). New registry item (component + story + test + `registry:build`); pull into a `demand-driven-components` phase when prioritized.
- **filter-bar** — faceted filter bar. GSC surfaces demand with **no component today**: "filter bar" / "filter bars" (~5 impr/90d, pos 78–87). New registry item; pairs with the `multiselect` gap above.

---

Expand Down
Loading