Skip to content
Protocore Design Systemv1.6.9

/// getting-started

Installation

PDS is a single package. Install it, import the stylesheet once, provide the two fonts, and mount the provider — five minutes to a rendered button.

1. Install the package

Add @protocore/pds with your package manager of choice. React 18 or 19 is a peer dependency; install it too if your app does not already have it.

terminal
pnpm add @protocore/pds

2. Import the stylesheet

The token layer and every component’s CSS ship in one stylesheet. Import it once, as high in your app as possible — in a Next.js App Router project that is the root layout.tsx; in Vite or CRA it is your entry module.

app/layout.tsx
import "@protocore/pds/styles.css";
Import order
Import @protocore/pds/styles.css before your own global CSS so your overrides win the cascade. The stylesheet only defines --pds-* variables and .pds-* classes, so it will not collide with your app styles.

3. Provide the fonts

PDS is typeset in Roboto and Roboto Mono. The token layer reads them from the CSS variables --font-roboto and --font-roboto-mono, with web-safe fallbacks if you skip this step. In Next.js, self-host both with next/font so no request leaves your origin, and expose them as those two variables on <html>:

app/layout.tsx
import { Roboto, Roboto_Mono } from "next/font/google";

const roboto = Roboto({
  subsets: ["latin"],
  weight: ["400", "500", "700"],
  variable: "--font-roboto",
  display: "swap",
});

const robotoMono = Roboto_Mono({
  subsets: ["latin"],
  weight: ["400", "500"],
  variable: "--font-roboto-mono",
  display: "swap",
});

export default function RootLayout({ children }) {
  return (
    <html
      lang="en"
      className={`${roboto.variable} ${robotoMono.variable}`}
    >
      <body>{children}</body>
    </html>
  );
}

Not on Next.js? Load the two families however you like (a self-hosted @font-face, a font service) and set --font-roboto / --font-roboto-mono on :root. The system never imports fonts itself.

4. Mount the provider

PdsProvider supplies the theme/accent/density context that hooks like useTheme read, and stamps the matching data-* attributes. You can either wrap your tree in it, or — the leaner option — set the attributes directly on <html> and mount the provider only where you need the context.

app/layout.tsx
<html
  lang="en"
  data-theme="dark"       // "dark" | "light"
  data-accent="green"     // green | blue | red | amber | violet
  data-density="default"  // "default" | "compact"
>

The attributes on <html> are enough to theme the entire tree — every token responds to them. Reach for PdsProvider when you want to read or flip the theme at runtime from React.

Runtime theming with the provider
import { PdsProvider } from "@protocore/pds";

<PdsProvider defaultTheme="dark" defaultAccent="green">
  <App />
</PdsProvider>

For persisting the choice without a flash of the wrong theme, see the no-flash snippet on the Theming page.

5. Verify

Render a Button. If it comes up as a sharp, uppercase-mono control that inverts on hover, your stylesheet, fonts, and tokens are all wired correctly.

app/page.tsx
import { Button } from "@protocore/pds";

export default function Page() {
  return <Button onClick={() => alert("PDS is live")}>Deploy service</Button>;
}
  1. [ 01 ]
    Install @protocore/pds
    and React 18 or 19
  2. [ 02 ]
    Import styles.css
    once, at the app root
  3. [ 03 ]
    Provide the two fonts
    Roboto + Roboto Mono
  4. [ 04 ]
    Set data-attrs or mount PdsProvider
  5. [ 05 ]
    Render a Button
    you're building

React support

ReactStatusNotes
19.xSupportedRecommended. Built and tested against 19.
18.xSupportedFully supported; the peer range starts at 18.2.
≤ 17Not supportedRelies on the modern JSX transform and hooks.

Server components: static, render-only components (Text, Badge, Tag, Card, Table…) are server-safe. Interactive ones carry "use client" where needed and work inside client boundaries out of the box.

Mobile (React Native)

@protocore/pds-mobile is the React Native sibling of the web library — 24 core components (Button, Text, Card, Input, Field, Switch, Badge, Callout, and more) built on Pressable, View, and StyleSheet.

Preview
@protocore/pds-mobile is an early preview. The API is stable-shaped and mirrors the web components, but it has had no device-level QA yet — pin the version and expect small changes.

Install the package. React and React Native are peer dependencies; an Expo or bare React Native app already has them.

terminal
npm install @protocore/pds-mobile

There is no stylesheet to import — React Native has no CSS. Instead of data-* attributes on <html>, every value comes from the theme object, so mount PdsProvider once at the root of your app and read tokens through usePdsTokens() / useTheme().

App.tsx
import { PdsProvider } from "@protocore/pds-mobile";

export default function App() {
  return (
    <PdsProvider defaultTheme="dark" defaultAccent="green">
      <RootNavigator />
    </PdsProvider>
  );
}

Components accept a style prop (a ViewStyle / TextStyle, merged after the component styles) in place of the web className, and use React Native handlers — onPress instead of onClick, onChangeText instead of onChange.

A screen
import { Card, Button, Text } from "@protocore/pds-mobile";

function DeployCard() {
  return (
    <Card title="Payments API" subtitle="v2.4.0">
      <Text color="secondary">Handles checkout and refunds.</Text>
      <Button onPress={() => deploy()}>Deploy service</Button>
    </Card>
  );
}
Fonts on React Native
The system is typeset in Roboto and Roboto Mono. React Native has no next/font, so bundle the two families with your app (in Expo, useFonts from expo-font; in bare RN, link the .ttf files) under the family names the theme expects. Until they load, RN falls back to the platform system font.

Per-component mobile guidance lives on each component page — use the Mobile switch in the right rail. Components without a mobile sibling show a “coming soon” note under that switch.

Charts subpath

Chart components live behind an optional subpath so that apps which never draw a chart do not pull in recharts. Install the peer and import from @protocore/pds/charts:

terminal
pnpm add recharts
usage
import { LineChart, ChartContainer } from "@protocore/pds/charts";
Optional peer
recharts is a peer dependency of the charts subpath only. The core @protocore/pds entry has no chart dependency — you pay for it only if you import it.