# Not found 4

> Search field with quick-link chips and home CTA — catalog discovery on dead ends.

A shadcn/ui block from the [@nusaiba](https://nusaiba.dev) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/nusaiba/not-found-4).

- Page, with a live preview: https://shadcn.exchange/r/nusaiba/not-found-4
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/nusaiba/not-found-4-light-18a70e9559f0bf13.png
- Registry item: https://nusaiba.dev/r/base-nova/not-found-4.json
- Categories: not-found
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://nusaiba.dev/r/base-nova/not-found-4.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- npm packages: `motion`
- Registry items: `@nusaiba/foundation`, `button`, `input`

## Files

### `registry/blocks/not-found/not-found-data.ts`

```ts
export const notFoundCode = "404";

export const notFoundHome = {
	label: "Back to home",
	href: "/",
} as const;

export const notFoundCenteredCopy = {
	title: "Page not found",
	description:
		"The page you're looking for doesn't exist or has been moved. Check the URL or head back home.",
} as const;

export const notFoundSplitCopy = {
	title: "This route isn't in the registry",
	description:
		"The path may have been renamed after a block update — browse the catalog or open docs for install paths.",
} as const;

export const notFoundFramedCopy = {
	eyebrow: "Missing page",
	title: "Nothing installed here",
	description: "Return to the registry home or search the block catalog for what you need.",
} as const;

export const notFoundSearchCopy = {
	title: "Can't find that page",
	description: "Search the block catalog or jump to a common destination below.",
	placeholder: "Search blocks…",
} as const;

export const notFoundCycleCopy = {
	title: "Wrong status code",
	description: "You landed on a route that doesn't resolve — pick a path below to keep shipping.",
} as const;

export const notFoundGridCopy = {
	title: "Try one of these instead",
	description: "Common destinations when a deep link goes stale after a registry update.",
} as const;

export const notFoundPathCopy = {
	title: "Route not found",
	description: "The URL below didn't match any page in this preview — update the path or go back.",
	brokenPath: "/blocks/registry/unknown-block",
} as const;

export const notFoundVisualCopy = {
	title: "Lost in the grid",
	description: "The section you wanted isn't here — head home or browse blocks to keep moving.",
} as const;

export const notFoundStackCopy = {
	eyebrow: "404",
	title: "Where to next",
	description: "Pick a destination — each link opens a live registry surface.",
} as const;

export const notFoundTerminalCopy = {
	eyebrow: "stderr",
	title: "ENOENT: page not found",
	description: "Exit code 404 — rerun from home or list available routes.",
} as const;

export type NotFoundLink = {
	label: string;
	href: string;
	description?: string;
};

export const notFoundQuickLinks: NotFoundLink[] = [
	{
		label: "Browse blocks",
		href: "/blocks",
		description: "Preview every section before you install",
	},
	{
		label: "Read docs",
		href: "/docs",
		description: "CLI install paths and Copy Prompt handoff",
	},
	{
		label: "Pricing",
		href: "/pricing",
		description: "Free vs Pro blocks and licensing",
	},
	{
		label: "Motion",
		href: "/motion",
		description: "Animation patterns tied to live blocks",
	},
];

export const notFoundStatusCodes = ["401", "403", "404", "410"] as const;
```

### `registry/blocks/not-found/not-found-primitives.tsx`

```tsx
"use client";

import Link from "next/link";
import { ArrowLeftIcon, ArrowRightIcon } from "lucide-react";
import { motion, useInView, useReducedMotion } from "motion/react";
import { useRef, type ReactNode } from "react";
import { buttonVariants } from "@/components/ui/button";
import { SectionShell } from "@/components/layout-contract";
import { motionStagger, motionViewport } from "@/lib/motion-tokens";
import { cn } from "@/lib/utils";
import { notFoundCode, notFoundHome, type NotFoundLink } from "./not-found-data";

const spring = { type: "spring" as const, duration: 0.3, bounce: 0 };

export function useNotFoundItemVariants() {
	const reduceMotion = useReducedMotion();

	return reduceMotion
		? { hidden: { opacity: 1 }, visible: { opacity: 1 } }
		: {
				hidden: { opacity: 0, filter: "blur(4px)", y: 8 },
				visible: { opacity: 1, filter: "blur(0px)", y: 0, transition: spring },
			};
}

export function NotFoundStagger({
	children,
	className,
}: {
	children: ReactNode;
	className?: string;
}) {
	const ref = useRef<HTMLDivElement>(null);
	const inView = useInView(ref, motionViewport);

	return (
		<motion.div
			animate={inView ? "visible" : "hidden"}
			className={className}
			initial="hidden"
			ref={ref}
			variants={{
				hidden: {},
				visible: { transition: { staggerChildren: motionStagger.item, delayChildren: 0.04 } },
			}}
		>
			{children}
		</motion.div>
	);
}

export function NotFoundStaggerItem({
	children,
	className,
}: {
	children: ReactNode;
	className?: string;
}) {
	const itemVariants = useNotFoundItemVariants();

	return (
		<motion.div className={className} variants={itemVariants}>
			{children}
		</motion.div>
	);
}

export function NotFoundCode({
	className,
	size = "lg",
}: {
	className?: string;
	size?: "lg" | "xl";
}) {
	return (
		<p
			className={cn(
				"font-mono font-medium tracking-tighter tabular-nums",
				size === "xl" ? "text-7xl md:text-8xl" : "text-6xl md:text-7xl",
				className,
			)}
		>
			{notFoundCode}
		</p>
	);
}

export function NotFoundHomeLink({ className }: { className?: string }) {
	return (
		<Link className={cn(buttonVariants(), "active:scale-[0.96] transition-transform", className)} href={notFoundHome.href}>
			<ArrowLeftIcon data-icon="inline-start" />
			{notFoundHome.label}
		</Link>
	);
}

export function NotFoundOutlineLink({
	href,
	children,
	className,
}: {
	href: string;
	children: ReactNode;
	className?: string;
}) {
	return (
		<Link
			className={cn(
				buttonVariants({ variant: "outline", size: "sm" }),
				"active:scale-[0.96] transition-transform",
				className,
			)}
			href={href}
		>
			{children}
		</Link>
	);
}

export function NotFoundLinkCard({ link }: { link: NotFoundLink }) {
	return (
		<Link
			className="group flex flex-col gap-1 rounded-xl border border-border bg-background p-4 transition-colors hover:bg-muted/30 active:scale-[0.98]"
			href={link.href}
		>
			<span className="flex items-center justify-between gap-2 font-medium text-sm">
				{link.label}
				<ArrowRightIcon className="size-3.5 text-muted-foreground transition-transform group-hover:translate-x-0.5" />
			</span>
			{link.description ? (
				<span className="text-pretty text-muted-foreground text-xs leading-relaxed">
					{link.description}
				</span>
			) : null}
		</Link>
	);
}

export function NotFoundLinkRow({ link }: { link: NotFoundLink }) {
	return (
		<Link
			className="group flex min-h-11 items-center justify-between gap-4 border-border border-b py-3.5 last:border-b-0 transition-colors hover:bg-muted/25"
			href={link.href}
		>
			<div className="min-w-0">
				<p className="font-medium text-sm">{link.label}</p>
				{link.description ? (
					<p className="mt-0.5 truncate text-muted-foreground text-xs">{link.description}</p>
				) : null}
			</div>
			<ArrowRightIcon className="size-4 shrink-0 text-muted-foreground transition-transform group-hover:translate-x-0.5" />
		</Link>
	);
}

export function NotFoundSectionShell({
	children,
	className,
}: {
	children: ReactNode;
	className?: string;
}) {
	return (
		<SectionShell spacingMode="section" className={cn("flex min-h-[70vh] items-center", className)}>
			{children}
		</SectionShell>
	);
}
```

### `registry/blocks/not-found/4/not-found-section.tsx`

```tsx
"use client";

import Link from "next/link";
import { SearchIcon } from "lucide-react";
import { Input } from "@/components/ui/input";
import { notFoundQuickLinks, notFoundSearchCopy } from "../not-found-data";
import {
	NotFoundHomeLink,
	NotFoundSectionShell,
	NotFoundStagger,
	NotFoundStaggerItem,
} from "../not-found-primitives";

export function NotFoundSearchSection() {
	return (
		<NotFoundSectionShell className="justify-center">
			<NotFoundStagger className="mx-auto w-full max-w-md">
				<NotFoundStaggerItem className="text-center">
					<p className="font-mono text-5xl font-medium tracking-tighter tabular-nums md:text-6xl">
						404
					</p>
					<h1 className="mt-4 font-medium text-xl tracking-tight md:text-2xl">
						{notFoundSearchCopy.title}
					</h1>
					<p className="mt-3 text-pretty text-muted-foreground text-sm leading-relaxed">
						{notFoundSearchCopy.description}
					</p>
				</NotFoundStaggerItem>

				<NotFoundStaggerItem className="mt-8">
					<div className="relative">
						<SearchIcon className="pointer-events-none absolute top-1/2 left-3 size-4 -translate-y-1/2 text-muted-foreground" />
						<Input
							className="h-11 pl-9"
							placeholder={notFoundSearchCopy.placeholder}
							readOnly
						/>
					</div>
				</NotFoundStaggerItem>

				<NotFoundStaggerItem className="mt-4 flex flex-wrap justify-center gap-2">
					{notFoundQuickLinks.slice(0, 3).map((link) => (
						<Link
							className="rounded-full border border-border px-3 py-1.5 text-sm transition-colors hover:bg-muted/40 active:scale-[0.96]"
							href={link.href}
							key={link.href}
						>
							{link.label}
						</Link>
					))}
				</NotFoundStaggerItem>

				<NotFoundStaggerItem className="mt-8 flex justify-center">
					<NotFoundHomeLink />
				</NotFoundStaggerItem>
			</NotFoundStagger>
		</NotFoundSectionShell>
	);
}
```
