diff --git a/app/components/[category]/[slug]/page.tsx b/app/components/[category]/[slug]/page.tsx
index 315bd1b..81c279a 100644
--- a/app/components/[category]/[slug]/page.tsx
+++ b/app/components/[category]/[slug]/page.tsx
@@ -8,17 +8,17 @@ import {
registry,
type ComponentExample,
} from "@/lib/registry";
-import { CodeBlock } from "@/components/app/code-block";
-import { InstallBlock } from "@/components/app/install-block";
+import { CodeBlock } from "@/components/app/docs/code-block";
+import { InstallBlock } from "@/components/app/docs/install-block";
import {
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from "@/components/motion/tabs";
-import { NewBadge } from "@/components/app/new-badge";
-import { ComponentCard } from "@/components/app/component-card";
-import { JsonLd } from "@/components/app/json-ld";
+import { NewBadge } from "@/components/app/docs/new-badge";
+import { ComponentCard } from "@/components/app/docs/component-card";
+import { JsonLd } from "@/components/app/analytics/json-ld";
import { getPreview, previews } from "@/components/previews";
import { pageUrlFor, withSignature } from "@/lib/signature";
import { readSourceFile } from "@/lib/source-files";
diff --git a/app/components/[category]/page.tsx b/app/components/[category]/page.tsx
index 4cf03da..3b4965b 100644
--- a/app/components/[category]/page.tsx
+++ b/app/components/[category]/page.tsx
@@ -1,8 +1,8 @@
import type { Metadata } from "next";
import { notFound } from "next/navigation";
import { findCategory, registry } from "@/lib/registry";
-import { ComponentCard } from "@/components/app/component-card";
-import { JsonLd } from "@/components/app/json-ld";
+import { ComponentCard } from "@/components/app/docs/component-card";
+import { JsonLd } from "@/components/app/analytics/json-ld";
import { breadcrumbJsonLd, categoryJsonLd } from "@/lib/seo";
export function generateStaticParams() {
diff --git a/app/docs/ai-agents/page.tsx b/app/docs/ai-agents/page.tsx
index 0dd2a01..3e0e187 100644
--- a/app/docs/ai-agents/page.tsx
+++ b/app/docs/ai-agents/page.tsx
@@ -1,7 +1,7 @@
import type { Metadata } from "next";
import Link from "next/link";
import { ArrowUpRight } from "lucide-react";
-import { CodeBlock } from "@/components/app/code-block";
+import { CodeBlock } from "@/components/app/docs/code-block";
export const metadata: Metadata = {
title: "AI Agents",
@@ -25,12 +25,36 @@ export const metadata: Metadata = {
};
const ENDPOINTS: { label: string; url: string; desc: string }[] = [
- { label: "llms.txt", url: "/llms.txt", desc: "Markdown index in llmstxt.org format." },
- { label: "Registry index", url: "/r", desc: "JSON catalogue of every component." },
- { label: "Component detail", url: "/r/{slug}", desc: "JSON with files, deps, source." },
- { label: "shadcn catalog", url: "/registry.json", desc: "Directory-compatible registry catalog." },
- { label: "shadcn item", url: "/r/{slug}.json", desc: "Install item with inline file content and shadcn semantic color classes." },
- { label: "Raw source", url: "/r/{slug}/raw", desc: "Plain text .tsx ready to drop in." },
+ {
+ label: "llms.txt",
+ url: "/llms.txt",
+ desc: "Markdown index in llmstxt.org format.",
+ },
+ {
+ label: "Registry index",
+ url: "/r",
+ desc: "JSON catalogue of every component.",
+ },
+ {
+ label: "Component detail",
+ url: "/r/{slug}",
+ desc: "JSON with files, deps, source.",
+ },
+ {
+ label: "shadcn catalog",
+ url: "/registry.json",
+ desc: "Directory-compatible registry catalog.",
+ },
+ {
+ label: "shadcn item",
+ url: "/r/{slug}.json",
+ desc: "Install item with inline file content and shadcn semantic color classes.",
+ },
+ {
+ label: "Raw source",
+ url: "/r/{slug}/raw",
+ desc: "Plain text .tsx ready to drop in.",
+ },
];
const MCP_URL = "https://mcp.beui.dev/mcp";
@@ -92,17 +116,30 @@ const ENTRY_SHAPE = `{
export default function AIAgentsPage() {
return (
-
-
Intro
-
For AI agents
+ <>
+
+ Intro
+
+
+ For AI agents
+
- beUI exposes a static, agent-friendly surface. Connect the MCP server below, or hit the raw endpoints directly. Coding agents (Claude, Codex, Cursor, Amp) can list components, fetch source with all deps, and drop files into the user's project.
+ beUI exposes a static, agent-friendly surface. Connect the MCP server
+ below, or hit the raw endpoints directly. Coding agents (Claude, Codex,
+ Cursor, Amp) can list components, fetch source with all deps, and drop
+ files into the user's project.
-
MCP server
+
+ MCP server
+
- The fastest path: connect the beUI MCP server and your agent can list, search and install components directly. Hosted at{" "}
- {MCP_URL}.
+ The fastest path: connect the beUI MCP server and your agent can list,
+ search and install components directly. Hosted at{" "}
+
+ {MCP_URL}
+
+ .
@@ -114,17 +151,42 @@ export default function AIAgentsPage() {
@@ -143,28 +205,46 @@ export default function AIAgentsPage() {
))}
-
Agent flow
-
Four calls, then install. Components are self-contained and own their files.
+
+ Agent flow
+
+
+ Four calls, then install. Components are self-contained and own their
+ files.
+
-
shadcn flow
+
+ shadcn flow
+
- The shadcn item installs source files and package dependencies. Components use shadcn semantic color utilities directly, so they inherit the target app's theme without beUI-specific color variables.
+ The shadcn item installs source files and package dependencies.
+ Components use shadcn semantic color utilities directly, so they inherit
+ the target app's theme without beUI-specific color variables.
-
Entry shape
+
+ Entry shape
+
- Internal helpers (e.g. @/lib/utils) ship inline as type: util so the agent does not have to chase imports.
+ Internal helpers (e.g.{" "}
+
+ @/lib/utils
+
+ ) ship inline as{" "}
+
+ type: util
+ {" "}
+ so the agent does not have to chase imports.
-
-
+ >
);
}
diff --git a/app/docs/theme/page.tsx b/app/docs/theme/page.tsx
index cf3dd0d..0c70d9b 100644
--- a/app/docs/theme/page.tsx
+++ b/app/docs/theme/page.tsx
@@ -1,7 +1,7 @@
import type { Metadata } from "next";
import Link from "next/link";
import { ArrowUpRight } from "lucide-react";
-import { CodeBlock } from "@/components/app/code-block";
+import { CodeBlock } from "@/components/app/docs/code-block";
import { THEME_CSS } from "@/lib/theme-css";
export const metadata: Metadata = {
diff --git a/app/layout.tsx b/app/layout.tsx
index 5bbeed5..c88ec6c 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -4,15 +4,15 @@ import { SpeedInsights } from "@vercel/speed-insights/next";
import { Inter, JetBrains_Mono } from "next/font/google";
import { GeistPixelSquare } from "geist/font/pixel";
import "./globals.css";
-import { GoogleAnalytics } from "@/components/app/google-analytics";
-import { ThemeProvider } from "@/components/app/theme-provider";
-import { PreferencesProvider } from "@/components/app/preferences-provider";
-import { PreferencesPanel } from "@/components/app/preferences-panel";
-import { SiteHeader } from "@/components/app/site-header";
-import { SiteDock } from "@/components/app/site-dock";
-import { SiteFrame } from "@/components/app/site-frame";
-import { KeyboardShortcuts } from "@/components/app/keyboard-shortcuts";
-import { JsonLd } from "@/components/app/json-ld";
+import { GoogleAnalytics } from "@/components/app/analytics/google-analytics";
+import { ThemeProvider } from "@/components/app/chrome/theme-provider";
+import { PreferencesProvider } from "@/components/app/preferences/preferences-provider";
+import { PreferencesPanel } from "@/components/app/preferences/preferences-panel";
+import { SiteHeader } from "@/components/app/chrome/site-header";
+import { SiteDock } from "@/components/app/chrome/site-dock";
+import { SiteFrame } from "@/components/app/chrome/site-frame";
+import { KeyboardShortcuts } from "@/components/app/chrome/keyboard-shortcuts";
+import { JsonLd } from "@/components/app/analytics/json-ld";
import { getGithubStarCount } from "@/lib/github";
import { AUTHOR, SITE_DESCRIPTION, SITE_NAME, siteJsonLd } from "@/lib/seo";
import { SITE_URL } from "@/lib/site";
diff --git a/app/page.tsx b/app/page.tsx
index fbf81f0..18724dd 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -1,11 +1,11 @@
import Link from "next/link";
import { ArrowRight } from "lucide-react";
import { registry } from "@/lib/registry";
-import { Hero } from "@/components/app/hero";
-import { InstallCommand } from "@/components/app/install-command";
-import { LandingComponentCard } from "@/components/app/landing-component-card";
-import { SiteFooter } from "@/components/app/site-footer";
-import { WorkCta } from "@/components/app/work-cta";
+import { Hero } from "@/components/app/landing/hero";
+import { InstallCommand } from "@/components/app/docs/install-command";
+import { LandingComponentCard } from "@/components/app/landing/landing-component-card";
+import { SiteFooter } from "@/components/app/chrome/site-footer";
+import { WorkCta } from "@/components/app/landing/work-cta";
const CURATED: { category: string; slug: string }[] = [
{ category: "motion", slug: "button" },
diff --git a/app/sponsors/page.tsx b/app/sponsors/page.tsx
index dfb706a..fb4d66c 100644
--- a/app/sponsors/page.tsx
+++ b/app/sponsors/page.tsx
@@ -1,6 +1,6 @@
import type { Metadata } from "next";
import { ArrowUpRight } from "lucide-react";
-import { CopyButton } from "@/components/app/copy-button";
+import { CopyButton } from "@/components/app/docs/copy-button";
import { PressLink } from "@/components/app/press-link";
export const metadata: Metadata = {
diff --git a/components/app/google-analytics.tsx b/components/app/analytics/google-analytics.tsx
similarity index 100%
rename from components/app/google-analytics.tsx
rename to components/app/analytics/google-analytics.tsx
diff --git a/components/app/json-ld.tsx b/components/app/analytics/json-ld.tsx
similarity index 100%
rename from components/app/json-ld.tsx
rename to components/app/analytics/json-ld.tsx
diff --git a/components/app/header-tabs.tsx b/components/app/chrome/header-tabs.tsx
similarity index 100%
rename from components/app/header-tabs.tsx
rename to components/app/chrome/header-tabs.tsx
diff --git a/components/app/keyboard-shortcuts.tsx b/components/app/chrome/keyboard-shortcuts.tsx
similarity index 100%
rename from components/app/keyboard-shortcuts.tsx
rename to components/app/chrome/keyboard-shortcuts.tsx
diff --git a/components/app/mobile-nav.tsx b/components/app/chrome/mobile-nav.tsx
similarity index 97%
rename from components/app/mobile-nav.tsx
rename to components/app/chrome/mobile-nav.tsx
index 1b41f8f..33a224a 100644
--- a/components/app/mobile-nav.tsx
+++ b/components/app/chrome/mobile-nav.tsx
@@ -4,7 +4,7 @@ import { Menu } from "lucide-react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { useEffect, useState } from "react";
-import { SidebarNav } from "@/components/app/site-sidebar";
+import { SidebarNav } from "@/components/app/chrome/site-sidebar";
import { BottomSheet } from "@/components/motion/bottom-sheet";
import { Button } from "@/components/motion/button";
import { cn } from "@/lib/utils";
diff --git a/components/app/page-transition.tsx b/components/app/chrome/page-transition.tsx
similarity index 100%
rename from components/app/page-transition.tsx
rename to components/app/chrome/page-transition.tsx
diff --git a/components/app/site-dock.tsx b/components/app/chrome/site-dock.tsx
similarity index 100%
rename from components/app/site-dock.tsx
rename to components/app/chrome/site-dock.tsx
diff --git a/components/app/site-footer.tsx b/components/app/chrome/site-footer.tsx
similarity index 84%
rename from components/app/site-footer.tsx
rename to components/app/chrome/site-footer.tsx
index 558e424..ca64342 100644
--- a/components/app/site-footer.tsx
+++ b/components/app/chrome/site-footer.tsx
@@ -2,8 +2,13 @@ import Link from "next/link";
import { GithubIcon } from "@/components/app/icons";
import { registry } from "@/lib/registry";
-const motionComponents = registry.find((c) => c.slug === "motion")?.components ?? [];
-const blockComponents = registry.find((c) => c.slug === "blocks")?.components ?? [];
+// The catalog keeps growing — the footer shows only the newest few per column.
+const FOOTER_LIMIT = 8;
+
+const allMotion = registry.find((c) => c.slug === "motion")?.components ?? [];
+const allBlocks = registry.find((c) => c.slug === "blocks")?.components ?? [];
+const motionComponents = allMotion.slice(-FOOTER_LIMIT).reverse();
+const blockComponents = allBlocks.slice(-FOOTER_LIMIT).reverse();
export function SiteFooter() {
return (
@@ -68,6 +73,14 @@ export function SiteFooter() {
))}
+
+
+ View all ({allMotion.length})
+
+
@@ -87,6 +100,14 @@ export function SiteFooter() {
))}
+
+
+ View all ({allBlocks.length})
+
+
diff --git a/components/app/site-frame.tsx b/components/app/chrome/site-frame.tsx
similarity index 81%
rename from components/app/site-frame.tsx
rename to components/app/chrome/site-frame.tsx
index b9ea44f..da71e04 100644
--- a/components/app/site-frame.tsx
+++ b/components/app/chrome/site-frame.tsx
@@ -2,8 +2,8 @@
import { usePathname } from "next/navigation";
import type { ReactNode } from "react";
-import { SiteSidebar } from "@/components/app/site-sidebar";
-import { PageTransition } from "@/components/app/page-transition";
+import { SiteSidebar } from "@/components/app/chrome/site-sidebar";
+import { PageTransition } from "@/components/app/chrome/page-transition";
const SIDEBAR_PATHS = ["/components", "/docs"];
diff --git a/components/app/site-header.tsx b/components/app/chrome/site-header.tsx
similarity index 96%
rename from components/app/site-header.tsx
rename to components/app/chrome/site-header.tsx
index 8ed598e..220145e 100644
--- a/components/app/site-header.tsx
+++ b/components/app/chrome/site-header.tsx
@@ -7,10 +7,10 @@ import Link from "next/link";
import { usePathname } from "next/navigation";
import { useState } from "react";
import { GithubIcon } from "@/components/app/icons";
-import { MobileNav } from "@/components/app/mobile-nav";
-import { usePreferences } from "@/components/app/preferences-provider";
+import { MobileNav } from "@/components/app/chrome/mobile-nav";
+import { usePreferences } from "@/components/app/preferences/preferences-provider";
import { PressLink } from "@/components/app/press-link";
-import { SiteSearch } from "@/components/app/site-search";
+import { SiteSearch } from "@/components/app/chrome/site-search";
import { Tooltip } from "@/components/motion/tooltip";
import { cn } from "@/lib/utils";
diff --git a/components/app/site-search.tsx b/components/app/chrome/site-search.tsx
similarity index 97%
rename from components/app/site-search.tsx
rename to components/app/chrome/site-search.tsx
index b128106..1731dc9 100644
--- a/components/app/site-search.tsx
+++ b/components/app/chrome/site-search.tsx
@@ -8,7 +8,7 @@ import {
CommandPalette,
type CommandItem,
} from "@/components/motion/command-palette";
-import { NewBadge } from "@/components/app/new-badge";
+import { NewBadge } from "@/components/app/docs/new-badge";
import { registry } from "@/lib/registry";
const PAGES = [
diff --git a/components/app/site-sidebar.tsx b/components/app/chrome/site-sidebar.tsx
similarity index 98%
rename from components/app/site-sidebar.tsx
rename to components/app/chrome/site-sidebar.tsx
index c58cdd2..a5ccd47 100644
--- a/components/app/site-sidebar.tsx
+++ b/components/app/chrome/site-sidebar.tsx
@@ -3,7 +3,7 @@
import Link from "next/link";
import { usePathname } from "next/navigation";
import { registry } from "@/lib/registry";
-import { NewBadge } from "@/components/app/new-badge";
+import { NewBadge } from "@/components/app/docs/new-badge";
import { SharedLayoutBg } from "@/components/motion/shared-layout-bg";
import { cn } from "@/lib/utils";
diff --git a/components/app/theme-provider.tsx b/components/app/chrome/theme-provider.tsx
similarity index 100%
rename from components/app/theme-provider.tsx
rename to components/app/chrome/theme-provider.tsx
diff --git a/components/app/theme-toggle.tsx b/components/app/chrome/theme-toggle.tsx
similarity index 100%
rename from components/app/theme-toggle.tsx
rename to components/app/chrome/theme-toggle.tsx
diff --git a/components/app/code-block.tsx b/components/app/docs/code-block.tsx
similarity index 100%
rename from components/app/code-block.tsx
rename to components/app/docs/code-block.tsx
diff --git a/components/app/component-card.tsx b/components/app/docs/component-card.tsx
similarity index 95%
rename from components/app/component-card.tsx
rename to components/app/docs/component-card.tsx
index d4f7ead..f26f889 100644
--- a/components/app/component-card.tsx
+++ b/components/app/docs/component-card.tsx
@@ -1,5 +1,5 @@
import Link from "next/link";
-import { NewBadge } from "@/components/app/new-badge";
+import { NewBadge } from "@/components/app/docs/new-badge";
export function ComponentCard({
categorySlug,
diff --git a/components/app/copy-button.tsx b/components/app/docs/copy-button.tsx
similarity index 100%
rename from components/app/copy-button.tsx
rename to components/app/docs/copy-button.tsx
diff --git a/components/app/expandable-code.tsx b/components/app/docs/expandable-code.tsx
similarity index 100%
rename from components/app/expandable-code.tsx
rename to components/app/docs/expandable-code.tsx
diff --git a/components/app/install-block.tsx b/components/app/docs/install-block.tsx
similarity index 64%
rename from components/app/install-block.tsx
rename to components/app/docs/install-block.tsx
index 65a2a72..9510af4 100644
--- a/components/app/install-block.tsx
+++ b/components/app/docs/install-block.tsx
@@ -1,6 +1,6 @@
-import { InstallCommand } from "@/components/app/install-command";
-import { InstallTabs } from "@/components/app/install-tabs";
-import { ManualInstall } from "@/components/app/manual-install";
+import { InstallCommand } from "@/components/app/docs/install-command";
+import { InstallTabs } from "@/components/app/docs/install-tabs";
+import { ManualInstall } from "@/components/app/docs/manual-install";
/**
* Install UI for a component: the shadcn CLI command plus a shadcn-free
diff --git a/components/app/install-command.tsx b/components/app/docs/install-command.tsx
similarity index 98%
rename from components/app/install-command.tsx
rename to components/app/docs/install-command.tsx
index 9aa7e40..a8dd5db 100644
--- a/components/app/install-command.tsx
+++ b/components/app/docs/install-command.tsx
@@ -1,7 +1,7 @@
"use client";
import { useEffect, useState } from "react";
-import { CopyButton } from "@/components/app/copy-button";
+import { CopyButton } from "@/components/app/docs/copy-button";
import { ActionSwapCascadeText } from "@/components/motion/action-swap-cascade";
import { Tabs, TabsList, TabsTrigger } from "@/components/motion/tabs";
import { registry } from "@/lib/registry";
diff --git a/components/app/install-tabs.tsx b/components/app/docs/install-tabs.tsx
similarity index 100%
rename from components/app/install-tabs.tsx
rename to components/app/docs/install-tabs.tsx
diff --git a/components/app/manual-install.tsx b/components/app/docs/manual-install.tsx
similarity index 97%
rename from components/app/manual-install.tsx
rename to components/app/docs/manual-install.tsx
index 070f6e3..4369c92 100644
--- a/components/app/manual-install.tsx
+++ b/components/app/docs/manual-install.tsx
@@ -1,6 +1,6 @@
import Link from "next/link";
import { ArrowUpRight } from "lucide-react";
-import { CodeBlock } from "@/components/app/code-block";
+import { CodeBlock } from "@/components/app/docs/code-block";
import { buildEntry } from "@/lib/registry-server";
// Already present in any React project; not worth a copy-paste install line.
diff --git a/components/app/new-badge.tsx b/components/app/docs/new-badge.tsx
similarity index 100%
rename from components/app/new-badge.tsx
rename to components/app/docs/new-badge.tsx
diff --git a/components/app/hero-preview-dock.tsx b/components/app/landing/hero-preview-dock.tsx
similarity index 100%
rename from components/app/hero-preview-dock.tsx
rename to components/app/landing/hero-preview-dock.tsx
diff --git a/components/app/hero.tsx b/components/app/landing/hero.tsx
similarity index 100%
rename from components/app/hero.tsx
rename to components/app/landing/hero.tsx
diff --git a/components/app/landing-component-card.tsx b/components/app/landing/landing-component-card.tsx
similarity index 97%
rename from components/app/landing-component-card.tsx
rename to components/app/landing/landing-component-card.tsx
index 28c855a..60b3da1 100644
--- a/components/app/landing-component-card.tsx
+++ b/components/app/landing/landing-component-card.tsx
@@ -1,6 +1,6 @@
import Link from "next/link";
import type { ComponentEntry } from "@/lib/registry";
-import { NewBadge } from "@/components/app/new-badge";
+import { NewBadge } from "@/components/app/docs/new-badge";
import { getPreview } from "@/components/previews";
export function LandingComponentCard({
diff --git a/components/app/work-cta.tsx b/components/app/landing/work-cta.tsx
similarity index 100%
rename from components/app/work-cta.tsx
rename to components/app/landing/work-cta.tsx
diff --git a/components/app/playground/code-panel.tsx b/components/app/playground/code-panel.tsx
index 34c18fd..e1c63c2 100644
--- a/components/app/playground/code-panel.tsx
+++ b/components/app/playground/code-panel.tsx
@@ -2,7 +2,7 @@
import { useEffect, useState } from "react";
import { getSingletonHighlighter, type Highlighter } from "shiki";
-import { CopyButton } from "@/components/app/copy-button";
+import { CopyButton } from "@/components/app/docs/copy-button";
import { cn } from "@/lib/utils";
// One shared highlighter for the page, created lazily on first render.
diff --git a/components/app/preferences-panel.tsx b/components/app/preferences/preferences-panel.tsx
similarity index 98%
rename from components/app/preferences-panel.tsx
rename to components/app/preferences/preferences-panel.tsx
index 6e9b9ea..35b39ea 100644
--- a/components/app/preferences-panel.tsx
+++ b/components/app/preferences/preferences-panel.tsx
@@ -8,7 +8,7 @@ import { THEME_LIST, themeExportCss } from "@/lib/themes";
import {
type IconSet,
usePreferences,
-} from "@/components/app/preferences-provider";
+} from "@/components/app/preferences/preferences-provider";
const ICON_SETS: { id: IconSet | string; name: string; soon?: boolean }[] = [
{ id: "lucide", name: "Lucide" },
diff --git a/components/app/preferences-provider.tsx b/components/app/preferences/preferences-provider.tsx
similarity index 100%
rename from components/app/preferences-provider.tsx
rename to components/app/preferences/preferences-provider.tsx
diff --git a/lib/seo.ts b/lib/seo.ts
index 5e5cb64..c0126bc 100644
--- a/lib/seo.ts
+++ b/lib/seo.ts
@@ -1,4 +1,4 @@
-import type { JsonLdSchema } from "@/components/app/json-ld";
+import type { JsonLdSchema } from "@/components/app/analytics/json-ld";
import {
type CategoryEntry,
type ComponentEntry,