# _cn Full Context
> A TanStack Start template for publishing a shadcn-compatible registry.
This file expands the Markdown pages listed in https://underscore-cn.vercel.app/llms.txt. Use https://underscore-cn.vercel.app/registry.json for the machine-readable shadcn registry index.
---
URL: https://underscore-cn.vercel.app/docs.md
Publish installable components with public docs from the same registry workspace.
# Introduction
Publish installable components with public docs from the same registry workspace.
This registry publishes copy-and-paste components, blocks, hooks, and utilities that can be installed with the shadcn CLI.
Use the docs in this section to set up the registry, customize the site, and publish your own items.
Registry docs live in `registry/docs`. Installable source lives in `registry/items`. You can
update any of these files freely (or completely delete them!)
---
URL: https://underscore-cn.vercel.app/docs/installation.md
Install and run the registry template locally.
# Installation
Install and run the registry template locally.
Install dependencies with [Vite+](https://viteplus.dev/guide/).
```sh
vp install
```
Start the development server.
```sh
vp dev
```
Open the local URL from Vite+ and browse the docs, components, blocks, and utilities sections.
---
URL: https://underscore-cn.vercel.app/docs/registry.md
Scaffold and author installable registry items under registry/items.
# Registry
Scaffold and author installable registry items under registry/items.
Registry items live under `registry/items/**` and can be installed by shadcn-compatible CLIs. Start new items with the scaffold command so the folder, `_registry.mdx`, source file, metadata, and install paths follow the template conventions.
```sh
bun --bun ./scripts/new.ts --type registry:ui --name example-card --description "A compact card component."
```
Or, run the command without flags if you want an interactive prompt (recommended).
```sh
bun --bun ./scripts/new.ts
```
[Make sure Bun is installed before running these scripts.](https://bun.com/)
## Item Types
Choose the registry type from what the item installs:
| Type | Use For | Folder |
| -------------------- | ----------------------------------------- | ------------------------------ |
| `registry:ui` | Shadcn-style UI components | `registry/items/components/**` |
| `registry:component` | Components outside `components/ui` | `registry/items/components/**` |
| `registry:block` | Larger composed UI patterns | `registry/items/blocks/**` |
| `registry:hook` | React hooks | `registry/items/hooks/**` |
| `registry:lib` | Utility or helper modules | `registry/items/lib/**` |
| `registry:page` | App page files with explicit targets | `registry/items/pages/**` |
| `registry:file` | Other files with explicit install targets | `registry/items/files/**` |
The scaffold creates each item in its own folder:
```text
registry/items/components/example-card/
_registry.mdx
example-card.tsx
```
## CLI Flags
Use flags for agent-friendly and CI-friendly scaffolding:
```sh
bun --bun ./scripts/new.ts --type registry:block --name stats-panel --description "A metrics panel with reusable sample data."
bun --bun ./scripts/new.ts --type registry:page --name dashboard-page --description "A starter dashboard page." --target app/dashboard/page.tsx
bun --bun ./scripts/new.ts --type registry:file --name chart-theme --description "Shared chart theme tokens." --target styles/chart-theme.css --file-extension css
```
Supported flags:
- `--type`: registry item type. Defaults to `registry:ui`.
- `--name`: required kebab-case item name.
- `--title`: optional public title. Defaults from the name.
- `--description`: required public description.
- `--target`: required for `registry:page` and `registry:file`.
- `--file-extension`: only for `registry:file`; defaults to `ts`.
Use `bun --bun ./scripts/new.ts --help` to print the full usage.
## Authoring
Use `_registry.mdx` for public metadata, usage docs, and the named `Preview` export. Keep `_registry.mdx` private to authoring; never list it in `files`.
For one-file `registry:ui` items, the catalog infers `.tsx`. Hooks, libs, blocks, pages, target paths, and multi-file items should list `files` explicitly.
Use `localRegistryDependencies` for dependencies on other local registry items.
After editing an item, run `vp check --fix` on touched files and `bun --bun ./scripts/doctor.ts`. Run `vp build` when registry docs, routes, JSON output, catalog loading, or source loading changed.
---
URL: https://underscore-cn.vercel.app/docs/agents.md
Give AI coding tools the right context for using and authoring this registry.
# Agents
Give AI coding tools the right context for using and authoring this registry.
This template is designed to work well with coding agents and LLM-powered tools. It exposes Markdown-first routes for reading context, and it ships an installable Agent Skill for authoring registry items correctly.
## Install The Registry Skill
Install the `_cn` registry authoring skill from the upstream template:
```sh
npx skills add jakejarvis/_cn --skill shadcn-registry
```
Forks can install the same skill from their own repository:
```sh
npx skills add / --skill shadcn-registry
```
After installing the skill, ask for registry work directly:
- "add a button component to the registry"
- "adapt this modal from my app into a reusable registry component"
- "add a reusable hook to the registry"
- "turn this dashboard section into a registry block"
The skill covers components, blocks, hooks, libs, pages, files, previews, usage docs, dependency metadata, and the scaffold command for creating new items non-interactively.
## Point Agents At Markdown
The generated [`/llms.txt`](/llms.txt) route gives AI tools a compact map of the docs, registry sections, and item pages.
Use [`/llms-full.txt`](/llms-full.txt) when a tool needs expanded context with generated Markdown content inlined.
Every docs page, registry section, and registry item also has a Markdown route:
- [`/docs.md`](/docs.md)
- [`/docs/agents.md`](/docs/agents.md)
- [`/components.md`](/components.md)
- [`/components/example-card.md`](/components/example-card.md)
Inspired by [Fumadocs](https://www.fumadocs.dev/docs/headless/utils/negotiation), "human" permalinks support Markdown content negotiation too. AI clients can request `text/markdown`, `text/x-markdown`, or `text/plain` in the `Accept` header on pages like [`/docs`](/docs) or [`/components/example-card`](/components/example-card) and receive Markdown without changing URLs.
## Recommended Agent Workflow
For registry authoring tasks, agents should:
1. Read `AGENTS.md`, this docs section, and `/llms.txt` or `/llms-full.txt` for project context.
2. Use the `shadcn-registry` skill when available.
3. Scaffold new items with `bun --bun ./scripts/new.ts --type --name --description ""`.
4. Add `--target` for `registry:page` and `registry:file`, and `--file-extension` for non-`ts` file items.
5. Edit the generated source and `_registry.mdx` with previews, usage docs, and dependency metadata.
6. Run focused checks and `bun --bun ./scripts/doctor.ts` before handoff.
---
URL: https://underscore-cn.vercel.app/docs/cli.md
Install items from this registry with the shadcn CLI.
# CLI
Install items from this registry with the shadcn CLI.
Install a registry item with the command shown on its docs page.
```sh
npx shadcn@latest add https://underscore-cn.vercel.app/r/example-card.json
```
The command that's displayed uses the `homepage` value from `registry/config.ts` for the base URL.
Use the package manager selector on item pages to switch between npm, pnpm, yarn, and bun commands.
---
URL: https://underscore-cn.vercel.app/docs/theming.md
Customize the docs shell and published components with your own design tokens.
# Theming
Customize the docs shell and published components with your own design tokens.
The docs app uses the local shadcn configuration in `components.json` and the global theme in `src/styles.css`.
Published registry items are independent from the docs shell. Put installable component source in `registry/items/**`, and include any required CSS, dependencies, or registry dependencies in the item frontmatter.
Use semantic tokens such as `background`, `foreground`, `primary`, `muted`, and `border` so installed components remain easy to customize.
---
URL: https://underscore-cn.vercel.app/docs/changelog.md
Track user-facing changes to this registry.
# Changelog
Track user-facing changes to this registry.
Use this page to publish notable registry updates, new items, breaking changes, and migration notes.
## v1.0.1: April 21, 2026
- Fixed the pointer cursor when hovering `Button` components.
---
URL: https://underscore-cn.vercel.app/components.md
Reusable UI components you can install into your project.
# Components
Reusable UI components you can install into your project.
- [Example Card](https://underscore-cn.vercel.app/components/example-card): A compact card component that demonstrates shadcn registry dependencies.
---
URL: https://underscore-cn.vercel.app/components/example-card.md
A compact card component that demonstrates shadcn registry dependencies.
# Example Card
A compact card component that demonstrates shadcn registry dependencies.
## Installation
```bash
npx shadcn@latest add https://underscore-cn.vercel.app/r/example-card.json
```
[Registry JSON](https://underscore-cn.vercel.app/r/example-card.json)
## Preview
```tsx
import { ExampleCard } from "@/components/ui/example-card";
export function Preview() {
return ;
}
```
## Source
### registry/items/components/example-card/example-card.tsx
```tsx
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card";
type ExampleCardProps = {
title?: string;
description?: string;
status?: string;
};
function ExampleCard({
title = "Ready to publish",
description = "Use this component as a small, installable starter item.",
status = "Template",
}: ExampleCardProps) {
return (
{title}{status}
{description}
Replace this example with a component from your own registry.
);
}
export { ExampleCard, type ExampleCardProps };
```
## Usage
Use the card anywhere you need a compact content summary with a title, description, status badge,
and action.
```tsx
```
---
URL: https://underscore-cn.vercel.app/blocks.md
Larger composed UI patterns you can install into your project.
# Blocks
Larger composed UI patterns you can install into your project.
- [Stats Panel](https://underscore-cn.vercel.app/blocks/stats-panel): A simple multi-file block with a component and local data helper.
---
URL: https://underscore-cn.vercel.app/blocks/stats-panel.md
A simple multi-file block with a component and local data helper.
# Stats Panel
A simple multi-file block with a component and local data helper.
## Installation
```bash
npx shadcn@latest add https://underscore-cn.vercel.app/r/stats-panel.json
```
[Registry JSON](https://underscore-cn.vercel.app/r/stats-panel.json)
## Preview
```tsx
import { StatsPanel } from "./stats-panel";
export function Preview() {
return ;
}
```
## Source
### registry/items/blocks/stats-panel/stats-panel.tsx
```tsx
import { Badge } from "@/components/ui/badge";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { ExampleCard } from "@/components/ui/example-card";
import { stats } from "@/lib/stats-data";
function StatsPanel() {
return (
Registry health
{stats.map((stat) => (
{stat.label}{stat.detail}
{stat.value}
))}
);
}
export { StatsPanel };
```
### registry/items/blocks/stats-panel/stats-data.ts
```ts
type Stat = {
label: string;
value: string;
detail: string;
};
const stats: Stat[] = [
{
label: "Components",
value: "12",
detail: "Ready to publish",
},
{
label: "Blocks",
value: "3",
detail: "Documented examples",
},
{
label: "Schema",
value: "100%",
detail: "Validated output",
},
];
export { stats, type Stat };
```
## Usage
Use the panel as a dashboard summary block. It installs the component and the local data helper
together, plus its local `example-card` dependency.
---
URL: https://underscore-cn.vercel.app/utilities.md
Hooks and helpers you can install into your project.
# Utilities
Hooks and helpers you can install into your project.
- [useCopyToClipboard](https://underscore-cn.vercel.app/utilities/use-copy-to-clipboard): A small hook that copies text and tracks the latest copy result.
---
URL: https://underscore-cn.vercel.app/utilities/use-copy-to-clipboard.md
A small hook that copies text and tracks the latest copy result.
# useCopyToClipboard
A small hook that copies text and tracks the latest copy result.
## Installation
```bash
npx shadcn@latest add https://underscore-cn.vercel.app/r/use-copy-to-clipboard.json
```
[Registry JSON](https://underscore-cn.vercel.app/r/use-copy-to-clipboard.json)
## Preview
```tsx
import { Button } from "@/components/ui/button";
import { useCopyToClipboard } from "@/hooks/use-copy-to-clipboard";
export function Preview() {
const copyState = useCopyToClipboard();
const copyValue = "npx shadcn@latest add https://example.com/r/example-card.json";
return (
{copyState.status === "copied" ? "Copied to clipboard." : "Ready to copy."}
);
}
```
## Source
### registry/items/hooks/use-copy-to-clipboard/use-copy-to-clipboard.ts
```ts
"use client";
import * as React from "react";
type CopyState =
| {
status: "idle";
value: null;
error: null;
}
| {
status: "copied";
value: string;
error: null;
}
| {
status: "error";
value: null;
error: Error;
};
function useCopyToClipboard() {
const [state, setState] = React.useState({
status: "idle",
value: null,
error: null,
});
const copy = React.useCallback(async (value: string) => {
try {
await navigator.clipboard.writeText(value);
setState({ status: "copied", value, error: null });
return true;
} catch (error) {
const copyError = error instanceof Error ? error : new Error("Copy failed.");
setState({ status: "error", value: null, error: copyError });
return false;
}
}, []);
const reset = React.useCallback(() => {
setState({ status: "idle", value: null, error: null });
}, []);
return { ...state, copy, reset };
}
export { useCopyToClipboard, type CopyState };
```
## Usage
Call `copy` with the text you want to place on the clipboard. The hook exposes the latest copy
status so your UI can respond after the operation completes.
```tsx
import { useCopyToClipboard } from "@/hooks/use-copy-to-clipboard";
export function CopyButton() {
const copyState = useCopyToClipboard();
return (
);
}
```