An intentionally minimal TanStack Start + Vite+ starter template for publishing a shadcn-compatible registry without writing the documentation site and registry plumbing from scratch.
The scaffold contains a typed registry authoring layer, authored docs, live preview pages, syntax-highlighted source snippets, schema validation, package-manager install commands, and TanStack Start server routes. See a demo here.
Tip
_cn is pronounced "underscore-cn".
You can either create a new repository based on this template directly in your GitHub account/organization, or use a tool like degit to scaffold a fresh repo locally with the latest _cn code.
npx degit jakejarvis/_cn
# or use the "Use this template" button and then clone:
git clone https://github.com/your-username/my-cn.gitOnce cloned, ensure you have Vite+ (vp) installed on your system; this will ensure all other requirements are taken care of for you.
# Install Vite+
curl -fsSL https://vite.plus | bash
# Setup and start local server
vp install
vp devOpen the localhost URL from the Vite+ output and browse the starter docs, component, block, and utility pages. A good place to start customizing is the config.ts file.
This repository includes an installable Agent Skill for authoring _cn registry items. Install it into your harness from the upstream template using the Skills CLI:
npx skills add jakejarvis/_cn --skill shadcn-registryAfter installing the skill, ask your agent for registry authoring work directly:
- "add a button component to the registry"
- "adapt this modal from my app to make it reusable via this shadcn registry"
- "add a reusable hook to the registry"
- "turn this dashboard section into a registry block"
Above is a one-click button to fork the template and deploy it to Vercel as a platform-agnostic Nitro server.
You can just as easily use any other platform (Cloudflare Workers, Netlify, etc.) by following the TanStack Start docs to make a few adjustments to your vite.config.ts file (agents are usually pretty good at this too).
Edit registry/config.ts.
export const registryConfig = {
name: "_cn",
registryName: "_cn",
namespace: "@_cn",
description: "Installable components for your project.",
homepage: "https://underscore-cn.vercel.app",
repositoryUrl: "https://github.com/jakejarvis/_cn",
} as const;Set homepage before deploying. Install commands and local registry dependency URLs are built from this value.
Create public documentation pages under registry/docs/.
registry/docs/
index.mdx
installation.mdx
registry.mdx
Docs render under /docs: registry/docs/index.mdx becomes /docs, and registry/docs/installation.mdx becomes /docs/installation. Keep docs files directly under registry/docs for now; nested docs pages are not supported yet.
---
title: Installation
description: Install and run this registry.
order: 1
group: Getting Started
---
# Installation
Use Markdown or MDX with the built-in docs components.Run bun --bun ./scripts/new.ts to interactively scaffold new registry items under registry/items/**.
It's always a good idea to also run bun --bun ./scripts/doctor.ts after making changes in the registry directory; this validates registry metadata and reports ignored or suspicious files within the directory.
Create a folder under registry/items/<section>/<item-name>/.
registry/items/components/example-card/
_registry.mdx
_preview.tsx
example-card.tsx
Write metadata and usage docs in _registry.mdx.
---
name: example-card
type: registry:ui
title: Example Card
description: A compact card component.
registryDependencies:
- card
localRegistryDependencies:
- other-local-item
---
Use the component anywhere you need a compact content summary.
```tsx
import { ExampleCard } from "@/components/ui/example-card";
export function Example() {
return <ExampleCard />;
}
```Put the interactive preview in _preview.tsx.
"use client";
import { ExampleCard } from "./example-card";
export function Preview() {
return <ExampleCard />;
}For a one-file component, the catalog infers the source file from the item root and name, then emits a shadcn target placeholder such as @ui/example-card.tsx. List files explicitly in frontmatter for hooks, libs, blocks, pages, custom target paths, or any item with multiple published files; file paths are relative to the item _registry.mdx file. Metadata-only styles, themes, fonts, bases, and universal items can omit files. Do not publish _registry.mdx, _preview.tsx, or other authoring-only files.
The MDX body renders as the optional Usage section on the docs page. Fenced code blocks are syntax highlighted and keep the docs site's copy button. _preview.tsx is authoring-only and can use local state or events behind its "use client" boundary, but server-only logic should stay out of previews. Use localRegistryDependencies for dependencies on other local registry items; they are converted into canonical registry URLs in the public JSON.
The public registry index is available at both the root and /r paths, while installable item JSON lives under /r:
/registry.jsonserves the registry index./r/registry.jsonserves the same registry index./r/<name>.jsonserves an item JSON file./llms.txtand/llms-full.txtare generated from the same Markdown docs and registry item pages used by the site.
Tip
_cn validates authored registry metadata against schemas directly from shadcn/schema to ensure compatibility.
Human-facing registry URLs support the shadcn CLI's request headers. CLI requests with Accept: application/vnd.shadcn.v1+json or User-Agent: shadcn receive the shadcn-compliant JSON from the same URL as the human-readable docs page:
/registryreturns the registry index JSON./registry/<name>and section item pages like/components/<name>return item JSON.
All pages also support Markdown content negotiation (inspired by Fumadocs). AI clients that request text/markdown, text/x-markdown, or text/plain in the Accept header receive the Markdown version of the current page directly, while normal browser requests still receive HTML.
- Choose a registry name, namespace, domain, and repository URL in
registry/config.ts. - Update or replace the starter docs under
registry/docs. - Update or replace the starter registry items in
registry/items; usebun --bun ./scripts/new.tsto generate new stubs. - Run
bun --bun ./scripts/doctor.tsto verify changes. - Run
vp checkandvp build. - Deploy!
- Test the install commands with npm, pnpm, yarn, bun, vite+, and deno.
- Optionally submit your registry to shadcn's official directory.
Warning
The docs site uses the local shadcn UI configuration in components.json; that styling is for this app shell and does not affect the published registry items in any way.