Four steps

Getting started

From `pnpm install` to a working component reading the canonical tokens. Run the steps below in order; each one is a copy-paste away from the next.

01 · Install

Add the package

@flatpay-dk/ui and @flatpay-dk/tailwind-preset ship as private packages on GitHub Packages under the FLATPAY-DK org. That means two pieces of one-time setup before pnpm add resolves: a registry pointer in the project’s .npmrc and a token in your home folder. Once both are in place, every Flatpay project on this machine installs without further ceremony.

First-time setup (once, ever)

1. Get a token. At github.com/settings/tokens/new generate a classic personal access token with the single scope read:packages. After it’s generated, click Configure SSO and authorize FLATPAY-DK. Classic tokens at FLATPAY-DK don’t need admin approval — the whole thing takes ~2 minutes.

2. Save it to your home folder. In a terminal:

npm login --scope=@flatpay-dk --registry=https://npm.pkg.github.com

Username: your GitHub login. Password: the token. Email: whatever. The token is written to ~/.npmrc — never to a project file, never to a repo. Every future Flatpay project just works.

With auth in place, each project also needs a one-line registry pointer so pnpm knows where to look for the @flatpay-dk scope. Drop this at the project root:

.npmrc

@flatpay-dk:registry=https://npm.pkg.github.com

Then install:

bash

pnpm add @flatpay-dk/ui @flatpay-dk/tailwind-preset

Prerequisites

The package targets react@^18 || ^19, react-dom@^18 || ^19, and either next@^15 or next@^16 (Next is an optional peer — only needed if you use useFlatpayFonts). Tailwind v4 + an @import "tailwindcss" entry in your CSS is the canonical setup. Vite / CRA / Remix consumers running React 18 + Tailwind v3 are also supported via the dedicated entries in Other stacks.

02 · Wire styles & fonts

Two imports and a className

The preset imports the canonical token CSS, maps the system’s semantic vars onto the Tailwind @theme namespace, and ships the .eyebrow utility. Add it after Tailwind. The @source line below points Tailwind v4 at the compiled component bundle in node_modules/@flatpay-dk/ui/dist/ so utilities used inside the package show up in your build. Adjust the relative path if your global stylesheet lives somewhere other than app/globals.css.

app/globals.css

@import "tailwindcss";
@import "@flatpay-dk/tailwind-preset";

@source "../node_modules/@flatpay-dk/ui/dist/**/*.js";

Then mount the brand fonts on <html>. useFlatpayFonts() wraps Inter Tight and Martian Mono in next/font/local and returns a className that wires --font-sans and --font-mono in one line.

app/layout.tsx

import { useFlatpayFonts } from "@flatpay-dk/ui/fonts";

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  const { className } = useFlatpayFonts();
  return (
    <html lang="en" className={className}>
      <body>{children}</body>
    </html>
  );
}

Founders Grotesk is licensed; not in the package

The canonical Flatpay display face — Founders Grotesk X Condensed by Klim Type Foundry — is commercial and is notincluded in the published tarball. Headings fall back to Inter Tight via the preset’s --font-display: var(--font-display, var(--font-sans)) fallback. Internal Flatpay surfaces with a Klim license wire Founders locally on top of useFlatpayFonts — see apps/portal/app/fonts.ts in the Flatpay monorepo for the reference shape.

03 · Render a component

Import, render, done

Components are tree-shakeable named imports. There’s no provider, no theme wrapper — every component reads from token CSS variables, so dark mode is one [data-theme="dark"] attribute on <html>.

tsx

import { Button } from "@flatpay-dk/ui";

export function CaptureAction() {
  return <Button>Capture payment</Button>;
}

Browse the full set under Components. Every page lists props, variants, and the component’s place in the system.

04 · Reach for a token

Tokens are CSS variables

Every color, surface, and stroke is a CSS custom property. The preset re-exposes them as Tailwind utilities for backgrounds and borders; for text colors and one-off styles, reach for the variable directly. Both idioms produce the same swatch and re-theme automatically under [data-theme="dark"].

As a Tailwind utility
PAID
<span className="bg-accent-yellow-subtlest" />
As a CSS variable
PAID
background: var(--background-accent-yellow-subtlest);

The full token reference — every color step, every surface, the layering rule — lives at Foundations · Tokens.

05 · Other stacks

Vite, React 18, Tailwind v3

The package ships compiled JavaScript and reads the same token CSS variables on every stack — nothing about the components is Next-specific. Consumers on Vite + React 18 + Tailwind v3 (Lovable, CRA, Remix, plain Vite) wire two different entries: a CommonJS Tailwind v3 preset at @flatpay-dk/ui/tailwind-v3 and a CSS-only @font-face entry at @flatpay-dk/ui/fonts/css. The component bundle, the token CSS at /styles, and dark-mode behavior are identical to the Next path.

Skip @flatpay-dk/tailwind-preset — it’s Tailwind v4 only. The v3 preset below is its equivalent and reads the exact same CSS variables, so swatches don’t drift between stacks.

bash

pnpm add @flatpay-dk/ui

tailwind.config.ts

import flatpay from "@flatpay-dk/ui/tailwind-v3";

export default {
  presets: [flatpay],
  content: [
    "./src/**/*.{ts,tsx}",
    "./node_modules/@flatpay-dk/ui/dist/**/*.js",
  ],
};

src/index.css

@tailwind base;
@tailwind components;
@tailwind utilities;

@import "@flatpay-dk/ui/styles";       /* token CSS variables */
@import "@flatpay-dk/ui/fonts/css";    /* @font-face + --font-* */

That’s the whole setup. No provider, no className on <html> — the CSS entry sets --font-sans and --font-mono on :root globally. Toggle dark mode with [data-theme="dark"] on <html> the same way the Next path does.

Display face fallback

Founders Grotesk X Condensed isn’t in the published tarball (Klim license). On every stack, headings using font-display fall back to Inter Tight via --font-display: var(--font-display, var(--font-sans)). Layer your own @font-face for Founders after the imports above if you hold the license.

What’s next

Beyond the install