Next.js Server Components
Render static Boreal UI directly in Next.js App Router server files. Dedicated server entries avoid client directives, React hooks, browser APIs, and callback props while preserving Boreal styling and accessible markup.
Render on the server
Import static UI from @boreal-ui/next/server without adding a client boundary to the page.
Keep interaction explicit
Use standard @boreal-ui/next entries when a component needs hooks, browser APIs, callbacks, or client state.
Resolve themes before paint
Server-safe theme helpers apply the saved scheme to <html> before the client provider hydrates.
Import Server Entries
Use the server barrel for convenient grouped imports or a standalone path for a single component.
import {
BreadCrumbPageHeader,
Card,
Container,
MetricBox,
Timeline,
} from "@boreal-ui/next/server";import MetricBox from "@boreal-ui/next/server/MetricBox";
import { Grid, Stack } from "@boreal-ui/next/server/Layout";
import "@boreal-ui/next/globals.css";Available Server Entries
These entries accept serializable render-time values and produce static markup.
| Content and status | Alert, Avatar, Badge, Card, Divider, EmptyState, MetricBox, Skeleton, Typography, and ValidationSummary |
|---|---|
| Charts and data display | BarChart, Legend, LineChart, ProgressBar, and Sparkline |
| Navigation and page structure | BreadCrumbPageHeader, Breadcrumbs, Footer, PageHeader, Timeline, and Toolbar |
| Static actions and form controls | Button, CheckBox, RadioButton, RadioGroup, Select, TextArea, and TextInput |
| Layout | Container, Grid, Inline, Section, and Stack from the Layout entry |
| Theme helpers | getThemeAttributes, getThemeStyle, readSavedSchemeCookie, resolveThemeScheme, and THEME_COOKIE_NAME from ThemeProvider |
Static and Stripped Behavior
Normally interactive components deliberately expose a smaller server-safe API.
- Button renders static button or link markup without event callbacks.
- TextInput and TextArea render read-only values or native initial state.
- Select, CheckBox, RadioButton, and RadioGroup render native initial form state without change callbacks.
- EmptyState uses actionHref for a static action link and omits onActionClick.
- Footer renders links and static social actions, and omits the theme selector.
- Toolbar renders a static avatar and omits the avatar click handler.
- ValidationSummary renders linked or plain items without focus-on-mount and item-click behavior.
SSR Theme Setup
Read the Boreal theme cookie in the root layout, apply its attributes to the html element, then wrap the body with the normal client ThemeProvider for interactive theme changes.
import { cookies } from "next/headers";
import { ThemeProvider } from "@boreal-ui/next/ThemeProvider";
import {
getThemeAttributes,
resolveThemeScheme,
THEME_COOKIE_NAME,
} from "@boreal-ui/next/server/ThemeProvider";
import "@boreal-ui/next/globals.css";
export default async function RootLayout({ children }) {
const cookieStore = await cookies();
const savedThemeName = cookieStore.get(THEME_COOKIE_NAME)?.value;
const scheme = resolveThemeScheme(savedThemeName);
return (
<html lang="en" {...getThemeAttributes(scheme)}>
<body>
<ThemeProvider initialSchemeName={scheme.name}>
{children}
</ThemeProvider>
</body>
</html>
);
}The Next ThemeProvider synchronizes changes to local storage and the boreal-theme cookie by default. For custom schemes, pass the same customSchemes and useOnlyCustomSchemes options to both resolveThemeScheme and the client provider.
Server-Rendered Dashboard
This page remains a Server Component because every Boreal import comes from the server barrel.
import {
BreadCrumbPageHeader,
Button,
Card,
Grid,
MetricBox,
Stack,
ValidationSummary,
} from "@boreal-ui/next/server";
export default function ReportsPage() {
return (
<Stack gap="lg">
<BreadCrumbPageHeader
breadcrumbs={[{ label: "Dashboard", href: "/" }, { label: "Reports" }]}
title="Reports"
actions={<Button href="/reports/archive">View archive</Button>}
/>
<Grid minColumnWidth="14rem">
<MetricBox title="Requests" value="12.4" units="k" />
<MetricBox title="Availability" value="99.99" units="%" />
</Grid>
<Card title="Validation status">
<ValidationSummary
items={[{ message: "Name is required", fieldId: "name" }]}
/>
</Card>
</Stack>
);
}Use server entries when
- Values and markup are known during server render.
- The component only needs static links, content, or initial form state.
- You want to avoid adding a client boundary to a route.
Use standard Next entries when
- The component needs event handlers or client-managed state.
- The component uses browser APIs, hooks, or context.
- The UI must react immediately to user interaction.