Getting started

Install

Two packages on npm, released from the repository's main branch without a manual step. Everything below assumes pnpm and a Next.js app, but the tokens are plain CSS and the components are plain React.

1. Add the packages

Both packages are on npm under one shared version, so no registry token is needed. Pin the version this site documents:

pnpm add @mishrashardendu22/observatory-tokens@0.3.0 @mishrashardendu22/observatory-ui@0.3.0

The tokens package is a peer of @mishrashardendu22/observatory-ui; keep the two on the same version.

2. Load the styles

Tokens first, then the components' stylesheet, then your own. With Tailwind v4, also import theme.css so utilities such as bg-bg-100, text-ink-muted and rounded-lg resolve to the tokens.

/* app/globals.css */
@import "tailwindcss";
@import "@mishrashardendu22/observatory-tokens/tokens.css";
@import "@mishrashardendu22/observatory-tokens/theme.css";
@import "@mishrashardendu22/observatory-ui/styles.css";

3. Transpile the components

The ui package ships TypeScript source rather than a build, so Next.js compiles it with the app. Nothing to configure for Vite.

// next.config.ts
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  transpilePackages: ["@mishrashardendu22/observatory-ui"],
};

export default nextConfig;

4. Use a component

import Link from "next/link";
import { ButtonLink, PageHeader, StatCard, StatusBadge } from "@mishrashardendu22/observatory-ui";

export default function Page() {
  return (
    <div className="page">
      <PageHeader
        kicker="Backup operations"
        title={<>System <em>Status</em></>}
        subtitle="Runs, repository health and storage, as the worker reports them."
        actions={<StatusBadge status="completed" />}
      />
      <div className="metric-grid metric-grid--four">
        <StatCard label="Repositories" value={42} delta={{ direction: "up", label: "+3 this month" }} />
        <StatCard label="Success rate" value="99.9%" tone="success" />
      </div>
      <ButtonLink component={Link} href="/backups" variant="outline">View history</ButtonLink>
    </div>
  );
}

5. Fonts

The tokens name Instrument Serif, Inter and IBM Plex Mono, all hosted on Google Fonts. An app that self-hosts them with next/font points the three stacks at its own variables after the import:

:root {
  --font-serif: var(--font-heading), "Instrument Serif", Georgia, serif;
  --font-sans: var(--font-body), Inter, system-ui, sans-serif;
  --font-mono: var(--font-mono-var), "IBM Plex Mono", Menlo, monospace;
}

6. Theme

Dark is the default. When the device prefers light and the page sets no data-theme, the light values apply. There is no toggle, no provider and no stored preference. To pin a page:

<html data-theme="dark">
Every colour has both values
A new token is added with a dark and a light value, each checked at 4.5:1 on the grounds its usage note names.

7. Tokens outside CSS

Charts, canvases and a React Native app read the same values from the typed object. Chart libraries take the CSS variable references so the series follow the theme.

import { chart, tokens } from "@mishrashardendu22/observatory-tokens";
import { chartAxisProps, chartColors, chartTooltipStyle } from "@mishrashardendu22/observatory-ui";

tokens.color["bg-000"].dark;   // "#0e0c0a"
tokens.radius["radius-md"];    // "10px"
chart.primary;                 // "var(--chart-primary)"

<Bar fill={chartColors.primary} />
<XAxis {...chartAxisProps} />
<Tooltip contentStyle={chartTooltipStyle} />

8. Upgrading

Every merge to main of the repository that touches a package is versioned from its commits (a changeset decides the bump when one is written), published to npm with provenance and released on GitHub, all by the release workflow. The dashboard repository is told about each release and opens its own upgrade pull request. Any other app upgrades with pnpm update on the two packages.