Shared design tokens, themes, and Tailwind CSS 4 integration for all Ekonavi apps.
This package provides a single source of truth for:
- Brand color palette (greens, earths, neutrals)
- Theme variants (forest + earthy, each with light/dark modes)
- Tailwind 4
@theme inlineintegration (CSS vars → utility classes) - shadcn/ui base layer (border, body, heading defaults)
- Shared utility classes (scrollbar, radio chips, product grid, etc.)
No compiled CSS is shipped. Each consuming app runs its own Tailwind 4 build, avoiding class collisions entirely.
pnpm add @ekonavi/theme@import "tailwindcss";
@import "tw-animate-css";
@import "@ekonavi/theme";
/* Tell Tailwind 4 to scan the theme package for class usage */
@source '../node_modules/@ekonavi/theme';
/* App-specific styles below */CSS @import cannot resolve Node.js package exports. Add aliases to vite.config.ts:
// vite.config.ts
resolve: {
alias: {
'@ekonavi/theme/extras.css': path.resolve(__dirname, 'node_modules/@ekonavi/theme/src/tokens/extras.css'),
'@ekonavi/theme': path.resolve(__dirname, 'node_modules/@ekonavi/theme/src/index.css'),
}
}Add one of these classes to your <html> element:
| Class | Description |
|---|---|
forest-light |
Green dominant, light mode |
forest-dark |
Green dominant, dark mode |
earthy-light |
Brown/amber dominant, light mode |
earthy-dark |
Brown/amber dominant, dark mode |
// Next.js layout.tsx example
export default function RootLayout({ children }) {
return (
<html className="forest-light">
<body>{children}</body>
</html>
);
}import { ThemeProvider } from "next-themes";
// Map next-themes values to CSS classes
const themeMap = {
"forest-light": "forest-light",
"forest-dark": "forest-dark",
"earthy-light": "earthy-light",
"earthy-dark": "earthy-dark",
};
export function Providers({ children }) {
return (
<ThemeProvider
attribute="class"
themes={Object.keys(themeMap)}
defaultTheme="forest-light"
>
{children}
</ThemeProvider>
);
}| Import Path | Contents |
|---|---|
@ekonavi/theme |
Everything (tokens + tailwind + base + utilities) |
@ekonavi/theme/tokens |
All token files only (no utilities/base) |
@ekonavi/theme/tokens/colors |
Brand color palette only |
@ekonavi/theme/tokens/forest |
Forest theme vars only |
@ekonavi/theme/tokens/earthy |
Earthy theme vars only |
@ekonavi/theme/tokens/typography |
Font definitions only |
@ekonavi/theme/tokens/spacing |
Spacing/radius/layout only |
@ekonavi/theme/extras.css |
Air, Sea, Midnight themes |
@ekonavi/theme/tailwind.css |
@theme inline block only |
@ekonavi/theme/shadcn-base.css |
Base layer only |
@ekonavi/theme/utilities.css |
Utility classes only |
In addition to semantic colors (bg-primary, text-foreground, etc.), the theme exposes brand colors directly:
<div class="bg-eko-sage text-eko-deep-green">Sage background</div>
<div class="bg-eko-amber text-white">Amber CTA</div>
<div class="border-eko-dark-teal">Teal border</div>
<div class="bg-eko-gold">Gold badge</div>Available: eko-sage, eko-deep-green, eko-dark-teal, eko-light-green, eko-dark-green-bg, eko-amber, eko-coral, eko-earth-brown, eko-cream, eko-gold, eko-warm-beige
Fonts are defined as CSS custom properties. Load them in your app:
// Next.js app/layout.tsx
import { Josefin_Sans } from "next/font/google";
const josefin = Josefin_Sans({
subsets: ["latin"],
variable: "--font-josefin",
});
export default function RootLayout({ children }) {
return (
<html className={`forest-light ${josefin.variable}`}>
<body>{children}</body>
</html>
);
}- Body: Josefin Sans (Google Fonts)
- Display/Headings: Bryndan Write (custom — load via
@font-face)
When working on the theme package alongside an app:
# Option A: pnpm link
cd ekonavi-theme && pnpm link --global
cd ../your-app && pnpm link --global @ekonavi/theme
# Option B: yalc (more reliable)
cd ekonavi-theme && yalc publish
cd ../your-app && yalc add @ekonavi/theme@ekonavi/theme/
├── src/
│ ├── tokens/
│ │ ├── colors.css ← brand palette (--eko-sage, --eko-amber, etc.)
│ │ ├── forest.css ← .forest-light, .forest-dark
│ │ ├── earthy.css ← .earthy-light, .earthy-dark
│ │ ├── extras.css ← .air-*, .sea-*, .midnight-*
│ │ ├── typography.css ← font families, sizes, weights
│ │ ├── spacing.css ← radius, sidebar, z-index
│ │ └── index.css ← imports all tokens
│ ├── tailwind.css ← @theme inline block
│ ├── shadcn-base.css ← @layer base rules
│ ├── utilities.css ← shared utility classes
│ └── index.css ← main entry point
├── package.json
└── README.md