A documentation site is four components and some prose: a sidebar that mirrors the file tree, a table of contents that tracks where you are, a code block that can be copied, and a search box. Everything else is writing.
The catalogue shows where the effort goes. 37 public components named sidebar, 47 named code, and exactly two tables of contents. The part that does the most for a reader is the part almost nobody builds.
The parts
Sidebar by Manu Arora expands on hover and collapses on mobile, and shadcn's Sidebar is the primitive version with the state handling already done. The sidebar guide covers the collapse behaviour that decides whether a docs nav is usable on a phone.
Table of Contents by hirael tracks the active heading as you scroll, and Table of Contents is the auto-scrolling variant that keeps the active item in view when the list is long.
Code Block and Code block are the two most-taken code components, and the code block guide covers the highlighting decision, which is the one with real bundle consequences.
What makes docs different from an app shell
The URL is the state. Every heading needs an anchor, the sidebar has to reflect the current path, and a deep link to a section has to land on that section. An app shell can keep its state in memory; docs cannot, because the whole point is that a link to one paragraph works.
Content is the product, so it renders on the server. A docs page whose body arrives via client-side fetch is invisible to search engines and answer engines. The server components guide has the rule: interactive parts are client components, prose is not.
The sidebar mirrors a file tree, which is why a file tree component and a docs nav share most of their logic: nesting, an expanded state, and one active item.
The table of contents detail
Scroll-spy is where these go wrong. Use an IntersectionObserver rather than a scroll handler, because a scroll handler runs on every frame and fights the browser's own scrolling.
Three rules follow. Each entry is a real link, so it works without JavaScript and a right-click can copy it. When several headings are visible at once, highlight the topmost rather than flickering between them. And when the reader clicks an entry, respect prefers-reduced-motion before smooth-scrolling, per the scroll animation guide.
Search is an index, not a box
Command Palette and Command give you the interface. The command palette guide makes the point that matters here: the component is an afternoon and the index is the project. For docs specifically, search over headings and paragraphs beats search over page titles by a wide margin, and that means building the index at build time.
The smaller parts are worth naming: Pagination for previous and next page links at the foot of an article, Callout for the highlighted notes, and a breadcrumb when the tree is more than two levels deep.
Where else to look
The honest list, because the answer is not always us:
| Source | Best for | Trade-off |
|---|---|---|
| Fumadocs / Nextra | A whole docs site from markdown, search included | You adopt its layout and its conventions |
| Docusaurus | Versioned docs at scale | A framework rather than components |
| A hosted docs product | Never maintaining any of this | Your docs live somewhere else |
| 21st | The individual parts, when the docs live inside your app | You assemble them |
Taking one
Every component page has a live preview and the code. Installing goes through the shadcn CLI against our registry:
That key comes from your 21st account, and installs require a membership. Set API_KEY_21ST once in your shell and the command works for anything in the catalogue.
Frequently asked
- What does a documentation site actually need?
- Four components and prose: a sidebar mirroring the file tree, a table of contents that tracks the active heading, a code block that can be copied, and search. The catalogue shows where effort goes: 37 public components named sidebar, 47 named code, and two tables of contents.
- How should a table of contents track the active heading?
- With an IntersectionObserver rather than a scroll handler, which runs every frame and fights the browser's own scrolling. Each entry stays a real link so it works without JavaScript, and when several headings are visible the topmost wins rather than flickering.
- Why must docs pages render on the server?
- Because content is the product. A page whose body arrives by client-side fetch is invisible to search engines and answer engines, so prose stays a server component and only the interactive parts, the sidebar toggle and the search dialog, become client components.
- Is a command palette enough for docs search?
- The palette is an afternoon and the index is the project. For documentation specifically, searching over headings and paragraphs beats searching page titles by a wide margin, and that means building the index at build time rather than querying at runtime.







