diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ea5490c..cd93c911 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,13 @@ Release automation can regenerate this file from Conventional Commits with ### Added +- **Component family landing pages** - every component family has a standalone, + SEO-oriented landing at `/families/[category]`, plus a `/families` index. One + shared template renders a hero with CTAs, per-family SEO sub-groups with + editorial copy and live component previews, an agent-readable surface + (`/llms.txt`, `/llms-full.txt`, `/r/.json`), and a FAQ. Each page ships + `CollectionPage`/`ItemList`, `FAQPage`, and `BreadcrumbList` JSON-LD and is + listed in the sitemap. - **Typography foundation primitives** — `Text`, `Heading`, `Display`, and `Prose` in the `core` family. Font family (`--font-sans` + a new `--font-display`), heading/display weight (`--font-weight-heading`, @@ -23,6 +30,10 @@ Release automation can regenerate this file from Conventional Commits with ### Changed +- **AI family consolidated onto the shared template** - the bespoke `/ai` hub is + gone; `/ai` now permanently redirects to `/families/ai`, which renders through + the same family template. AI components are recategorized out of the + `learning` family into `ai`. - `HeadingProps` exported from `@vllnt/ui` now refers to the `Heading` primitive (adds optional `level`/`size`/`ref`); the plain heading-element alias is available as `TypographyHeadingProps`. (#465) diff --git a/ROADMAP.md b/ROADMAP.md index b6a07785..068e5ba8 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -34,6 +34,20 @@ Convention: phases are kebab-case outcome slugs, ordered DONE → ACTIVE → PLA --- +## family-pages [ACTIVE — code-complete on `feat/family-homepage`, pending merge] + +**Goal:** A per-family landing at `/families/[category]` — the SEO / agent-surface destination for the Family breadcrumb crumb (#461) and the sidebar drill-down. +**Exit criteria:** 12 family landings on one shared `/families/[category]` template (`ai` included), each hero + CTAs + count + SEO sub-groups (`family-groups.ts`) + editorial copy + FAQ + agent surface; sitemap'd; `CollectionPage`/`ItemList` + `FAQPage` JSON-LD; `/components` headings + component-page family crumb link in via `familyPath`. +**Verify:** `/families/form` renders the Form grid + FAQ; `/ai` permanently redirects to `/families/ai`; Google Rich Results clean on a family page. Moves to the DONE cluster on merge to main + canary publish. + +- [x] family-pages.1 `/families/[category]` route: hero + description + count + data-driven grid, zero nav maintenance — #463 +- [x] family-pages.2 Internal links: `/components` family headings + component-page family crumb → family page via `familyPath` — #463 +- [x] family-pages.3 sitemap `familyRoutes()` + `collectionPageLd` (CollectionPage/ItemList) + `faqPageLd` — #463 +- [x] family-pages.4 `ai` reconciled: consolidated under `/families/ai` (shared template, grouped), `/ai` → permanent redirect, `familyPath` helper — #463 +- [x] family-pages.5 Per-family SEO copy + FAQ (`family-copy.ts`) + branded titles / keywords — #463 +- [x] family-pages.6 Validate: e2e `family-homepage.spec.ts` + unit `component-categories.test.ts` (E2E) +- [x] family-pages.7 One shared landing template for every family incl. `ai` (hero + CTAs + agent surface); per-family SEO sub-groups (`family-groups.ts`); `/families` index — #463 + ## component-sidebar [ACTIVE] **Goal:** Navigate 309 components via a single-pane **drill-down** — families list ⇄ one family's components — synced to the breadcrumb, so the sidebar never shows more than one family at once. @@ -269,6 +283,7 @@ Falls out of API-first (`studio.11`) — registration is just another API — pl Unscheduled — pull into a phase when prioritized. - **react-doctor-90** — push score 71 → 90 (sweep issues closed but target not fully met; see `codebase-health` caveat). +- **typography-primitives** (#465) — foundation `Text` / `Heading` / `Display` (/`Prose`) with token-driven font-family, heading-weight, and type-scale, all theme-overridable. Feasible (~12–18 files; an existing `typography` component — H1–H4/P/Lead/… — to model or extend), **but needs 3 triage decisions before scheduling**: (1) `--font-display` is a net-new token → conflicts with "no new design tokens beyond DESIGN.md baseline" (Out of scope) — resolve by adding a display family to the DESIGN.md baseline, or drop `--font-display` and map `Display` to `--font-sans`; (2) wire `--font-sans` as the actual default — today the body font is `font-mono` (`packages/ui/src/styles.css`), not sans, so "default stays semibold sans" isn't literally true; (3) reconcile the default heading weight — existing `typography.tsx` h1 uses `font-extrabold` (800) vs DESIGN.md's 600 semibold. - **ai-elements-voice** (6) — AudioPlayer, MicSelector, Persona, SpeechInput, Transcription, VoiceSelector. - **ai-elements-ide** (9) — Commit, EnvironmentVariables, FileTree, PackageInfo, SchemaDisplay, Snippet, StackTrace, Terminal, TestResults. - **ai-elements-canvas** (5) — Canvas, Connection, Controls, Node, Panel (verify against existing `@xyflow`-based components first). @@ -508,7 +523,7 @@ Semver discipline starts hard at `1.0.0`. Until then, `0.x.0` may include breaki - React Compiler adoption. - Right-to-left language support. - Backend services for `/report` or `/request-component` (prefilled GitHub URLs — no backend). -- New design tokens beyond DESIGN.md baseline. +- New design tokens beyond DESIGN.md baseline (this is what gates `typography-primitives` #465's `--font-display` — see Later). - Versioned docs (deferred until breaking changes appear). - Component analytics (privacy-respecting telemetry — separate decision). diff --git a/apps/registry/app/[locale]/ai/page.tsx b/apps/registry/app/[locale]/ai/page.tsx index 47dafd29..124a8634 100644 --- a/apps/registry/app/[locale]/ai/page.tsx +++ b/apps/registry/app/[locale]/ai/page.tsx @@ -1,253 +1,24 @@ -import { Sidebar } from "@vllnt/ui"; -import { ArrowRight, Sparkles, Terminal } from "lucide-react"; -import type { Metadata } from "next"; -import Link from "next/link"; +import { permanentRedirect } from "next/navigation"; import { setRequestLocale } from "next-intl/server"; -import { Footer } from "@/components/footer/footer"; -import type { Locale } from "@/i18n/routing"; -import { - AI_COMPONENT_GROUPS, - getAiComponentSlugs, - resolveAiComponent, -} from "@/lib/ai-seo"; -import { breadcrumbLd, faqPageLd, jsonLdScriptAttributes } from "@/lib/jsonld"; -import { generateOGMetadata, generateTwitterMetadata } from "@/lib/og"; -import { canonical, languageAlternates, localizePathname } from "@/lib/seo"; -import { getSidebarSections } from "@/lib/sidebar-sections"; +import { type Locale, routing } from "@/i18n/routing"; +import { localizePathname } from "@/lib/seo"; type Props = { readonly params: Promise<{ locale: Locale }>; }; -const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL ?? "https://ui.vllnt.ai"; -const PATHNAME = "/ai"; - -const TITLE = "AI Agent UI Components — chat, streaming, tools, citations"; -const DESCRIPTION = - "The open-source UI design system for AI agents and AI-first apps. React components for AI chat, streaming text, tool calls, citations, agent activity, and artifacts. Install via the shadcn CLI."; - -const FAQ = [ - { - answer: - "An agent-first design system gives you the UI primitives that AI products actually need — chat input, message bubbles, streaming text, tool-call displays, source citations, agent activity timelines, and artifacts — and also ships every component as machine-readable JSON so AI coding agents can install it without scraping HTML. VLLNT UI is open source (MIT) and installs with the shadcn CLI.", - question: "What is an agent-first UI design system?", - }, - { - answer: - "At minimum: AI Chat Input for the composer, AI Message Bubble to render each turn, and AI Streaming Text for token-by-token output. Add AI Tool Call Display and Agent Activity for agentic flows, AI Source Citation for RAG, and AI Artifact for canvas-style output.", - question: "Which components do I need to build an AI chat app in React?", - }, - { - answer: - "Three surfaces: /llms.txt (a concise index per the llmstxt.org spec), /llms-full.txt (the full registry context in one fetch), and /r/.json (a machine-readable descriptor per component with props, accessibility schema, and examples). Coding agents like Claude, Cursor, Cline, and Continue read these directly.", - question: "How do AI agents consume VLLNT UI?", - }, - { - answer: - "Yes. VLLNT UI is open source under the MIT license. You own the source after install, with no backend and no tracking.", - question: "Is VLLNT UI free to use?", - }, -]; - -export async function generateMetadata({ params }: Props): Promise { - const { locale } = await params; - const ogParameters = { - description: DESCRIPTION, - title: TITLE, - type: "page" as const, - }; - - return { - alternates: { - canonical: canonical(PATHNAME, locale), - languages: languageAlternates(PATHNAME), - }, - description: DESCRIPTION, - openGraph: generateOGMetadata(ogParameters, { - locale, - pathname: PATHNAME, - }), - title: `${TITLE} | VLLNT UI`, - twitter: generateTwitterMetadata(ogParameters), - }; -} - -function ComponentCard({ locale, slug }: { locale: Locale; slug: string }) { - const resolved = resolveAiComponent(slug); - if (!resolved) { - return null; - } - return ( -
  • - -

    {resolved.title}

    -

    - {resolved.description} -

    - - View component - - - -
  • - ); +export function generateStaticParams(): { locale: Locale }[] { + return routing.locales.map((locale) => ({ locale })); } -export default async function AiHubPage({ params }: Props) { +/** + * The AI hub moved to `/families/ai` (all family landings now live under + * `/families`). Permanently redirect the old `/ai` URL to preserve its SEO + * equity and any external links. + */ +export default async function AiRedirect({ params }: Props) { const { locale } = await params; setRequestLocale(locale); - - const componentCount = getAiComponentSlugs().length; - - return ( - <> -