React components for Next.js and Server Components
Where the client boundary goes, the error you get if you miss it, and what the CSS costs.
The short answer
oks-ui works in the Next.js App Router and with static export. Since oks-ui 1.3.1 each component's own entry (oks-ui/button, oks-ui/modal, and so on) is marked as a client component, so you can import it straight into a Server Component and Next prerenders its HTML. The exceptions are oks-ui/text-editor and oks-ui/pagination, which also export plain functions a server can call, and the main oks-ui entry: render their components only from a file that starts with "use client". Import each component's stylesheet next to it, or oks-ui/styles.css once in your root layout.
Tested, not assumed
The client-boundary results come from a new Next.js app built on with Next.js 16.3.7, React 19.3.0 and oks-ui 1.3.1, and compared with oks-ui 1.2.2 on the same page. The CSS and static-export results come from an earlier app built on with Next.js 16.3.0 (Turbopack), React 19.2.8 and oks-ui 1.2.1. Only the App Router was tested.
1. Import a component’s own entry, even in a Server Component
Since oks-ui 1.3.1, oks-ui/button, oks-ui/modal and the other per-component entries (plus oks-ui/motion) start with "use client" themselves. A Server Component can import them directly, and Next still prerenders their HTML: the built page contained the <button> markup. Props that are functions, such as onPress, cannot be passed from a Server Component, so keep those in a file that starts with "use client".
// app/page.tsx (a Server Component, no "use client")
import { Button } from "oks-ui/button";
import "oks-ui/button.css";
const Page = () => {
return (
<main>
<h1>Welcome</h1>
<Button color="primary">Get started</Button>
</main>
);
};
export default Page;// SaveButton.tsx (interactive, so it is a client file)
"use client";
import { Button } from "oks-ui/button";
import "oks-ui/button.css";
export const SaveButton = ({ id }: { id: string }) => {
return (
<Button color="primary" onPress={() => console.log("save", id)}>
Save
</Button>
);
};What still fails
Two entries are deliberately not marked, because they also export plain functions that a server can call: oks-ui/text-editor (blocksToHtml, blocksToMarkdown) and oks-ui/pagination (paginationRange). The main oks-ui entry is unmarked for the same reason (it exports helpers such as oksVar). Importing a component from any of these into a Server Component fails the build, and so does importing any component on oks-ui 1.2.x. This is the real message from the test app, the same on both:
// app/page.tsx (a Server Component)
import { Button } from "oks-ui"; // <- the main entry is not a client entry
const Page = () => {
return <Button color="primary">Direct</Button>;
};
export default Page;
// next build:
// Error occurred prerendering page "/".
// TypeError: (0 , c.useState) is not a function or its return value is not iterableThe fix is the pattern above: import from the component’s own entry, or move the import into a file that starts with "use client".
2. Load the CSS, or nothing is styled
With Turbopack, the stylesheet import inside a component’s JavaScript is not followed. In the test app, a client component that imported a Modal without adding any CSS shipped no stylesheet at all. You have two options, and they differ in size:
- Everything, once. Import
oks-ui/styles.cssin the root layout. In the test app that was about 45 KB gzipped (352 KB raw), containing every component’s styles and the design tokens, on every page. - Only what you use. Import each component’s own stylesheet next to it. The Button stylesheet was about 2.7 KB gzipped in the same build.
// app/layout.tsx
import "oks-ui/styles.css";
const RootLayout = ({ children }: { children: React.ReactNode }) => {
return (
<html lang="en">
<body>{children}</body>
</html>
);
};
export default RootLayout;3. Static export
The same app built with output: "export" and prerendered every page. oks-ui needs no configuration of its own; these are Next’s own settings for a static host:
// next.config.mjs, for static export
export default {
output: "export",
images: { unoptimized: true },
trailingSlash: true, // if you host on S3 and CloudFront
};Go further
- Next.js in the docs, including the no-flash theme script.
- Dark mode without a flash.
- Measured sizes for every component.
Questions
Does oks-ui work with the Next.js App Router?
Yes. The client boundary was tested on 30 September 2026 in a new Next.js 16.3.7 app with React 19.3.0 and oks-ui 1.3.1. The CSS and static-export results are from a test on 24 September 2026 with Next.js 16.3.0, React 19.2.8 and oks-ui 1.2.1. Only the App Router was tested.
Do I need "use client" to use oks-ui in Next.js?
Not for a component's own entry from oks-ui 1.3.1: import oks-ui/button straight into a Server Component and Next prerenders its HTML. You still need "use client" for components from oks-ui/text-editor, oks-ui/pagination or the main oks-ui entry, if you pass function props such as onPress from a Server Component, or if you are on oks-ui 1.2.x, where no entry is marked.
Why do I get "useState is not a function" with oks-ui in Next.js?
You imported a component into a Server Component from the main oks-ui entry, from oks-ui/text-editor or oks-ui/pagination, or you are on oks-ui 1.2.x. The component uses React state, which does not exist on the server, so the build fails with TypeError: (0, c.useState) is not a function or its return value is not iterable. Import from the component's own entry (for example oks-ui/button, on 1.3.1 or later), or move the import into a file that starts with "use client".
Why are my oks-ui components unstyled in Next.js?
Under Next.js with Turbopack the stylesheet import inside a component's JavaScript is not followed, so nothing loads unless you add the CSS yourself. Import oks-ui/styles.css once in your root layout, or add each component's own CSS, for example import "oks-ui/button.css".
Does oks-ui work with Next.js static export?
Yes. A test app with output: "export" built and prerendered an oks-ui Button into the static HTML. Set images.unoptimized to true, and trailingSlash to true if you host on S3 and CloudFront. oks-ui itself needs no special configuration.
Keep exploring
- React component library with zero dependencies
- Theme React components with CSS variables
- Accessible React components
- React charts without a charting library
- Strict TypeScript React components
- Build React interfaces with ChatGPT and Claude
- All 45 components
- Install oks-ui
Figures and claims on this page were last checked on 2026-10-03.