Entrance cards
What this solves
A list of links tells you where you can go; it does not tell you why you would. An entrance card gives each destination its own icon, its name, and one sentence of purpose, so a reader who has never seen the place can pick a door by what they came to do. Grouped under a kicker that names the group and says what it is for, the runs read as a map rather than a menu.
Use it when
- A home or index page that hands out several documents or sections by intentthe docs home's repo-docs band: Start here, Working here, Canon, Reference, each a kicker with a phrase and three to six cards
- A group of destinations that differ in purpose more than in kinda README, an install page and a docs map are all markdown; the sentence is what tells them apart
- Never for a long homogeneous listthirty-four contract docs are a list card with rows, not thirty-four entrance cards
Rendered
Fixture data; check both themes.Start here
The front door: what this is, how to install the kit, and the map of everything written.
README
The repo's front door. What each layer is, who reads what, and how work happens here.
Install the kit
Prerequisites, the registry line and token, install and pin, the theme import, the bundler contract.
Docs map
What the docs can do, where truth lives for a component, what is on disk where.
patterns/entrance-cards/example.tsxCopy this into a fresh route and it renders as above.
"use client";import { Button, Card, Kicker, RenderIcon, type IconKeys } from "@versable-git/ui";// One entrance per destination: a compact card with the destination's icon// and name, one sentence on why a reader would go there, and the navigation// in the toolbar with its arrow trailing. A kicker with the group's own icon// and a phrase saying what the group is for sits above each run of cards.interface Entrance { Icon: IconKeys; title: string; card: string;}const GROUP = { Icon: "Home" as IconKeys, label: "Start here", phrase: "The front door: what this is, how to install the kit, and the map of everything written", items: [ { Icon: "Document", title: "README", card: "The repo's front door. What each layer is, who reads what, and how work happens here." }, { Icon: "Download", title: "Install the kit", card: "Prerequisites, the registry line and token, install and pin, the theme import, the bundler contract." }, { Icon: "Globe", title: "Docs map", card: "What the docs can do, where truth lives for a component, what is on disk where." }, ] satisfies Entrance[],};export function EntranceCards() { return ( <section className="flex flex-col gap-3"> <div className="flex flex-col gap-1"> <Kicker as="h2" className="flex items-center gap-1.5"> <RenderIcon Icon={GROUP.Icon} size={13} className="shrink-0" /> {GROUP.label} </Kicker> <p className="text-base-content/70 text-sm">{GROUP.phrase}.</p> </div> <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3"> {GROUP.items.map((item) => ( <Card key={item.title} compact noAnimate className="hover:border-primary/50 transition-colors" bodyClassName="gap-2" title={ <span className="flex items-center gap-2"> <RenderIcon Icon={item.Icon} size={16} className="text-primary shrink-0" /> <span className="truncate">{item.title}</span> </span> } toolbar={ <Button href="#" variant="text" size="sm" Icon="Right" iconRight onClick={(e) => e.preventDefault()}> Open </Button> } > <p className="text-base-content/70 text-xs">{item.card}</p> </Card> ))} </div> </section> );}Where it ships
apps/playground/src/app/docs/repo-docs-band.tsxthe docs home's entrance band: grouped by the rail's sections, the Reference group carrying a calloutapps/playground/src/app/landing-sections.tsxthe landing's section cards, the same card-plus-toolbar-arrow shape at a larger size
App-specific: The sentence on each card is written once, beside the destination's registry entry, and read by every surface that shows the card, so the docs home and the rail never describe a document two ways. The card's icon is the destination's own, the one its page title and its sidebar row wear.