🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@typestyles/next

Package Overview
Dependencies
Maintainers
1
Versions
50
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@typestyles/next

Next.js integration for typestyles SSR

latest
Source
npmnpm
Version
0.3.0
Version published
Maintainers
1
Created
Source

@typestyles/next

Next.js integration for typestyles with full support for App Router, Pages Router, and React Server Components.

Installation

npm install @typestyles/next typestyles
# or
pnpm add @typestyles/next typestyles
# or
yarn add @typestyles/next typestyles

Requirements

  • Next.js >= 13.0.0
  • React >= 18.0.0
  • typestyles >= 0.1.0

Quick Start

Import getRegisteredCss in your root layout to inject styles during SSR:

// app/layout.tsx
import { getRegisteredCss } from '@typestyles/next';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  const css = getRegisteredCss();

  return (
    <html lang="en">
      <head>{css && <style dangerouslySetInnerHTML={{ __html: css }} />}</head>
      <body>{children}</body>
    </html>
  );
}

Pages Router

Wrap your pages with the stylesheet component:

// pages/_app.tsx
import { TypestylesStylesheet } from '@typestyles/next';
import type { AppProps } from 'next/app';

export default function App({ Component, pageProps }: AppProps) {
  return (
    <TypestylesStylesheet>
      <Component {...pageProps} />
    </TypestylesStylesheet>
  );
}

React Server Components (RSC)

The package provides multiple approaches for RSC support:

Option 1: Layout SSR (Simplest)

Import getRegisteredCss in your root layout - this works in both Server and Client Components:

// app/layout.tsx
import { getRegisteredCss } from '@typestyles/next';

export default function RootLayout({ children }) {
  const css = getRegisteredCss();

  return (
    <html>
      <head>{css && <style dangerouslySetInnerHTML={{ __html: css }} />}</head>
      <body>{children}</body>
    </html>
  );
}

Option 2: Client Component Provider

For complex cases with dynamic styles, create a client component wrapper:

// components/TypestylesProvider.tsx
'use client';

import { getRegisteredCss } from 'typestyles/server';
import { useEffect, useState } from 'react';

export function TypestylesProvider({ children }) {
  const [css, setCss] = useState('');
  const [mounted, setMounted] = useState(false);

  useEffect(() => {
    setMounted(true);
    setCss(getRegisteredCss());
  }, []);

  return (
    <>
      {children}
      {mounted && css && <style id="typestyles" dangerouslySetInnerHTML={{ __html: css }} />}
    </>
  );
}

Then use it in your layout:

// app/layout.tsx
import { TypestylesProvider } from '@/components/TypestylesProvider';

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <TypestylesProvider>{children}</TypestylesProvider>
      </body>
    </html>
  );
}

Option 3: Collecting from a specific component tree

getTypestylesMetadata (alias of collectStylesFromComponent) renders a React element on the server and returns the CSS registered during that render. Use it when you need CSS scoped to a subtree rather than the whole app. For App Router pages, injecting the result still belongs in layout.tsx / <head> (Next.js Metadata does not provide a supported hook for arbitrary <style> payloads).

import { getTypestylesMetadata } from '@typestyles/next/server';
import { Home } from './Home';

const css = await getTypestylesMetadata(<Home />);
// Pass `css` into your layout <style> or streaming head pipeline.

Build-time CSS + Turbopack

To ship a static typestyles.css and avoid client-side <style> injection (uses typestyles/build under the hood):

  • Run buildTypestylesForNext before next build to emit CSS (and optional manifest).
  • Import that CSS from your root layout (e.g. import './typestyles.css').
  • Wrap config with withTypestylesExtract from @typestyles/next/build.

withTypestylesExtract sets NEXT_PUBLIC_TYPESTYLES_RUNTIME_DISABLED via next.config env (works with webpack and Turbopack) and adds webpack DefinePlugin for __TYPESTYLES_RUNTIME_DISABLED__ on client bundles when webpack runs. Example app: examples/next-app.

Runtime in development, zero-runtime in production

During next dev, keeping the client runtime enabled avoids tying every style tweak to a pre-build extraction step. In production, disable injection so the browser loads one cacheable stylesheet.

// next.config.mjs
import { withTypestylesExtract } from '@typestyles/next/build';

const base = {
  /* your config */
};

export default process.env.NODE_ENV === 'production' ? withTypestylesExtract(base) : base;

You still typically generate typestyles.css before production builds (CI or prebuild). The example app uses this pattern.

API Reference

getRegisteredCss

Returns all currently registered CSS as a string. This is the simplest way to get styles for SSR.

import { getRegisteredCss } from '@typestyles/next';

const css = getRegisteredCss();

collectStylesFromComponent

Collect styles from a React component tree. Useful when you need explicit control over style collection.

import { collectStylesFromComponent } from '@typestyles/next/server';
import { YourComponent } from './YourComponent';

const css = await collectStylesFromComponent(<YourComponent />);

getTypestylesMetadata

Same as collectStylesFromComponent — renders the given element on the server and returns registered CSS. Use when you want a dedicated name for “CSS for this subtree.”

import { getTypestylesMetadata } from '@typestyles/next/server';
import { Home } from './Home';

const css = await getTypestylesMetadata(<Home />);

TypestylesStylesheet (Pages Router)

A React component that renders typestyles CSS. Works with Pages Router.

import { TypestylesStylesheet } from '@typestyles/next';

<TypestylesStylesheet>
  <YourApp />
</TypestylesStylesheet>;

Examples

Basic Usage with App Router

// app/page.tsx
import { styles } from 'typestyles';

const button = styles.component('button', {
  base: {
    padding: '12px 24px',
    backgroundColor: '#0066ff',
    color: 'white',
    border: 'none',
    borderRadius: '6px',
    cursor: 'pointer',
  },
});

export default function Home() {
  return (
    <main>
      <button className={button()}>Click me</button>
    </main>
  );
}

With Design Tokens

// app/tokens.ts
import { tokens } from 'typestyles';

export const colors = tokens.create('color', {
  primary: '#0066ff',
  secondary: '#64748b',
});

export const spacing = tokens.create('space', {
  sm: '8px',
  md: '16px',
  lg: '24px',
});

// app/page.tsx
import { styles } from 'typestyles';
import { colors, spacing } from './tokens';

const card = styles.component('card', {
  base: {
    padding: spacing.md,
    backgroundColor: colors.primary,
    borderRadius: '8px',
  },
});

export default function Page() {
  return <div className={card()}>Hello World</div>;
}

With Dark Mode

// app/layout.tsx
import { tokens } from 'typestyles';
import { getRegisteredCss } from '@typestyles/next';

const darkTheme = tokens.createTheme('dark', {
  base: {
    color: {
      background: '#1a1a1a',
      text: '#ffffff',
    },
  },
});

export default function RootLayout({ children }) {
  const css = getRegisteredCss();

  return (
    <html className={darkTheme.className}>
      <head>{css && <style dangerouslySetInnerHTML={{ __html: css }} />}</head>
      <body>{children}</body>
    </html>
  );
}

Fonts and local files

global.fontFace() registers @font-face like any other TypeStyles global. For Next’s pre-build extraction (buildTypestylesForNext), prefer fonts under public/fonts/ and a root-relative url('/fonts/…') in src so Node does not need to resolve binary imports.

For Vite, you can use import file from './font.woff2?url' and url(\${file}`) format('woff2')` so production CSS points at hashed assets.

See the Fonts guide in the TypeStyles docs (docs/content/docs/fonts.md, route /docs/fonts on the docs site).

Troubleshooting

Flash of Unstyled Content (FOUC)

If you see a flash of unstyled content, ensure getRegisteredCss() is called in the layout and styles are injected before the body renders.

Styles not appearing

Make sure typestyles is installed in your project:

npm install typestyles

TypeScript errors

Ensure you have "moduleResolution": "bundler" or "node" in your tsconfig.json.

License

MIT

Keywords

next

FAQs

Package last updated on 17 Apr 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts