Installation
Add the GDOP tokens and components to a Next.js app that already uses shadcn/ui with Tailwind CSS v4.
1. Prerequisites
A Next.js app with Tailwind CSS v4 and shadcn/ui initialised (the components here are built on the Base UI base-nova style). If you are starting fresh:
pnpm dlx shadcn@latest init2. Add the design tokens
The globals item merges the GDOP colors, status tones, chart colors, radius, elevation and typography tokens into your existing stylesheet, for light and dark mode. It replaces variables with the same name (such as --primary) and leaves the rest of your CSS alone. It also adds the tw-animate-css and shadcn/tailwind.css imports the components need for their animations and variants.
pnpm dlx shadcn@latest add @gdop-ui/globals3. Load the fonts
The font stack expects Inter for Latin text and Noto Sans Ethiopic for Amharic. A registry can't ship fonts, so load them with next/font. Without this step the stack falls back to the system UI font.
app/layout.tsx// app/layout.tsx
import { Inter, Noto_Sans_Ethiopic } from "next/font/google";
const inter = Inter({ subsets: ["latin"], variable: "--font-inter" });
const notoEthiopic = Noto_Sans_Ethiopic({
subsets: ["ethiopic"],
variable: "--font-noto-ethiopic",
});
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" className={`${inter.variable} ${notoEthiopic.variable}`}>
<body>{children}</body>
</html>
);
}4. Add components
Every component page shows its install command. Full URLs work with no configuration:
pnpm dlx shadcn@latest add @gdop-ui/user-avatarTo use short names instead (shadcn add @gdop-ui/user-avatar), register the namespace in components.json:
components.json{
"registries": {
"@gdop-ui": "https://ui.gdop.gov.et/r/{name}.json"
}
}Components install to components/gdop-ui/ (inside src/ when your project uses it) and import cn from your @/lib/utils.
5. Shared lint and format rules (optional)
The base configs install as oxlint.base.ts and oxfmt.base.ts. Your own config extends them, so updating the base never overwrites your overrides.
pnpm dlx shadcn@latest add @gdop-ui/oxlint-base @gdop-ui/oxfmt-baseoxlint.config.ts// oxlint.config.ts
import { defineConfig } from "oxlint";
import base from "./oxlint.base.ts";
export default defineConfig({
extends: [base],
ignorePatterns: ["src/components/ui/"],
});