We keep a small, deliberate site. Whatever you were reaching for either moved, or was never part of it. The full index is below.
Monochrome 404 built on oversized display type: a parenthetical eyebrow, a display headline with a muted emphasis clause, a pill call to action, and a ruled index of every section on the site.
A monochrome 404 carried entirely by type: a parenthetical eyebrow, a display headline whose emphasis clause drops to muted grey, a pill call to action, and a ruled index listing every section of the site in large bold rows.
Upgrade to Pro
Pro blocks install through the shadcn CLI with your license key and ship their full source. Docs and live previews stay open to everyone, so you can read every block's details first.
Swap YOUR_EMAIL and YOUR_KEY for the email and license key on your account. Find your license key on your account page.
Radix flavor
npx shadcn add "https://ui.beste.co/r/error19?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
npx shadcn add "https://ui.beste.co/r-base/error19?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the block to components/beste/block/error19.tsx, plus the two design-system primitives it renders through: badge7 for the parenthetical eyebrow and button12 for the pill call to action.
The installed file exports error19Demo alongside the block: the exact props behind the preview above. Spread it to get a working error page in one line.
import { Error19, error19Demo } from "@/components/beste/block/error19";
export default function NotFound() {
return <Error19 {...error19Demo} />;
}Then replace the demo with your own props. The eyebrow is an object, and the emphasis inside the heading comes from a <strong> tag:
import { Error19 } from "@/components/beste/block/error19";
export default function NotFound() {
return (
<Error19
badge={{ label: "404" }}
heading="The page you asked for <strong>never existed here</strong>."
description="Whatever you were reaching for either moved, or was never part of the site."
button={{ label: "Return to the start", href: "/" }}
labels={{ indexTitle: "Index" }}
items={[
{ title: "Selected work", description: "Twelve projects, told properly", href: "/work" },
{ title: "Enquiries", description: "Briefs, timelines and availability", href: "/contact" },
]}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
badge | { label: string } | – | Parenthetical eyebrow above the headline |
heading | string | – | Headline HTML, rendered as an h1; <strong> marks the muted clause |
description | string | – | Explanatory paragraph under the headline |
button | ActionLink | – | Pill call to action |
labels | { indexTitle?: string } | {} | Eyebrow above the index |
items | IndexItem[] | [] | Ruled index rows |
className | string | – | Extra classes for the outer <section> |
type ActionLink = {
label: string;
href: string;
};
type IndexItem = {
title: string;
description?: string;
href: string;
};heading is injected with dangerouslySetInnerHTML, so it accepts inline HTML. Text inside <strong> drops to the muted colour instead of an accent, which is what gives the headline its two-tone reading. Keep the value under your own control, never user input.group/error19 group. Nothing moves or scales.