React Server Components
Five components in tekivex-ui are RSC-safe: they call no hook, use no browser
API, and attach no event handler, so they render on the server in Next.js App
Router (or any RSC framework) without "use client" and ship no JavaScript
to the browser.
The five server-safe components
Section titled “The five server-safe components”| Component | Notes |
|---|---|
TkxBadge | Status pill |
TkxDivider | Horizontal / vertical separator |
TkxEmpty | Empty-state placeholder |
TkxIcon | Icon set |
TkxSparkline | Inline trend chart (pure SVG) |
Why the rest are Client Components
Section titled “Why the rest are Client Components”Every other component calls useTheme(), which reads React context, or else
uses state, refs, or event handlers. Context is not available in Server
Components, so those have to stay client-side.
The five above escape it because of the CSS-variable change in 4.1.0:
components paint with var(--tkx-token, fallback) rather than a resolved hex
value, and ThemeProvider defines those variables on the DOM. A purely
presentational component can therefore emit the variable reference directly —
through the React-free cssTokens module — and let CSS resolve it. Theming,
including live theme switching, keeps working with no JavaScript at all,
because the resolution happens in CSS rather than in JS.
That is also the recipe for widening this list: remove a component’s dependency on context, rather than just removing its directive.
Usage in Next.js App Router
Section titled “Usage in Next.js App Router”// app/dashboard/page.tsx — Server Componentimport { TkxBadge, TkxDivider, TkxSparkline } from 'tekivex-ui';
export default async function Dashboard() { const data = await fetch('https://api.example.com/metrics', { cache: 'no-store', }).then(r => r.json());
return ( <section> <TkxBadge variant="success">{data.status}</TkxBadge> <TkxDivider /> <TkxSparkline data={data.trend} /> </section> );}No "use client", and no JavaScript shipped for those three. The HTML arrives
fully rendered on first byte.
When you need a client component
Section titled “When you need a client component”Anything interactive — buttons with onClick, forms with onChange, modals,
the image editor, the captcha — must sit in a client boundary, as must any
component that reads the theme through context (which today is everything not
in the table above). The convention is to keep your 'use client' boundaries
small and leaf-level:
// app/page.tsx — Serverimport { TkxBadge } from 'tekivex-ui';import { LoginForm } from './login-form';
export default function Page() { return ( <section> <TkxBadge variant="info">Beta</TkxBadge> <LoginForm /> </section> );}
// app/login-form.tsx — Client island'use client';import { TkxInput, TkxButton } from 'tekivex-ui';// …The Server Component still ships the surrounding structure on first byte; only the form hydrates.