Customizing Tailwind CSS Theme (Colors, Radius, and Variants) in prompts.chat
You customize the Tailwind CSS theme in prompts.chat by editing prompts.config.ts or setting PCHAT_ environment variables; src/app/layout.tsx converts these values into CSS custom properties like --radius and --primary that components consume via Tailwind's arbitrary value syntax such as rounded-[var(--radius)] and bg-primary.
The prompts.chat codebase implements a runtime theme system that bridges TypeScript configuration with Tailwind CSS utility classes. Instead of modifying tailwind.config.ts and rebuilding your bundle, you control colors, border radius, and UI variants through a centralized configuration object that gets injected into the DOM as CSS variables at runtime.
Theme Configuration Architecture
The theming system centers on a TypeScript configuration object that defines your brand identity, corner roundness, and interface density preferences.
The prompts.config.ts Entry Point
All visual customization starts in prompts.config.ts at the project root. This file exports a configuration object via defineConfig() from src/lib/config/index.ts, which provides full type safety through the ThemeConfig interface.
// prompts.config.ts
import { defineConfig } from "@/lib/config";
export default defineConfig({
branding: {
name: "My Prompt Hub",
logo: "/logo.svg",
},
theme: {
radius: "lg", // none | sm | md | lg
variant: "brutal", // flat | default | brutal
density: "comfortable", // compact | default | comfortable
colors: {
primary: "#ff4500", // Hex value converted to OKLCH at runtime
},
},
});
The configuration supports three distinct ui variants (flat, default, brutal) and three density modes (compact, default, comfortable), allowing you to adjust visual weight and spacing without writing custom CSS.
Type Definitions and Validation
The ThemeConfig interface and runtime logic reside in src/lib/config/index.ts. This file exports applyEnvOverrides(), which checks for environment variables at runtime and merges them over your static configuration.
Supported environment variables include:
PCHAT_THEME_RADIUS– overrides theradiusenumPCHAT_THEME_VARIANT– overrides thevariantsettingPCHAT_THEME_DENSITY– overrides thedensitysettingPCHAT_COLOR– overrides thecolors.primaryvalue
Runtime CSS Variable Injection
The conversion from configuration to rendered styles happens server-side in src/app/layout.tsx (lines 116-176), where the layout component transforms your config values into CSS custom properties on the <html> element.
Color Space Conversion with hexToOklch
Inside layout.tsx, the hexToOklch() function converts your configured hex color (e.g., #ff4500) into the OKLCH color space. This conversion ensures perceptual uniformity when the system generates contrast colors and opacity variants. The result is injected as --primary, while a calculated accessible contrast color becomes --primary-foreground.
Radius Mapping via radiusValues
The file defines a lookup table called radiusValues that maps configuration enums to concrete CSS lengths:
const radiusValues = {
none: "0",
sm: "0.25rem",
md: "0.5rem",
lg: "0.75rem",
};
Your selected radius is written to the --radius CSS variable, which components reference for consistent corner rounding throughout the application.
Variant and Density Classes
Beyond CSS variables, layout.tsx constructs themeClasses by mapping your config to class names like theme-brutal and density-comfortable. These classes are applied directly to the <html> tag, enabling scoped CSS rules that adjust shadows, borders, and internal spacing without requiring Tailwind configuration changes.
Consuming Theme Variables in Components
UI components reference these runtime variables using Tailwind's arbitrary value syntax. In src/components/ui/button.tsx, you will see patterns like:
// src/components/ui/button.tsx
<button
className="inline-flex items-center rounded-[var(--radius)] bg-primary text-primary-foreground hover:bg-primary/90 px-4 py-2"
>
Click me
</button>
rounded-[var(--radius)]dynamically applies your configured border radius.bg-primarymaps to the--primaryvariable injected by the layout.text-primary-foregroundensures WCAG-compliant contrast against your primary color.
Because these values are standard CSS custom properties, changes to prompts.config.ts reflect immediately across all components after a page refresh without requiring a Tailwind CSS rebuild.
Environment Variable Overrides
For deployment flexibility—such as running different brands on the same codebase—use the environment override system. Create a .env file in your project root:
PCHAT_THEME_RADIUS=md
PCHAT_THEME_VARIANT=default
PCHAT_THEME_DENSITY=compact
PCHAT_COLOR=#4f46e5
The applyEnvOverrides function in src/lib/config/index.ts (lines 94-100) reads these variables and deep-merges them into the configuration object before layout.tsx processes it. This approach is ideal for Docker deployments or Vercel preview environments where you need environment-specific branding.
Extending the Design System with Custom Radius Values
If the default four radius options are insufficient for your design language, you can extend the system by modifying the lookup table in src/app/layout.tsx:
const radiusValues = {
none: "0",
sm: "0.25rem",
md: "0.5rem",
lg: "0.75rem",
xl: "1.25rem", // Custom addition
"2xl": "2rem", // Another custom option
};
Then reference your new value in prompts.config.ts:
theme: {
radius: "xl",
variant: "default",
density: "default",
colors: { primary: "#3b82f6" }
}
All components using rounded-[var(--radius)] will automatically adopt the new 1.25rem value, ensuring global consistency without hunting through individual component files.
Summary
- Configuration centralization: Edit
prompts.config.tsto setradius,variant,density, andcolors.primaryusing theThemeConfigtype fromsrc/lib/config/index.ts. - Runtime conversion:
src/app/layout.tsxuseshexToOklch()and theradiusValueslookup to generate--radius,--primary, and--primary-foregroundCSS variables. - Component consumption: UI elements reference these variables via Tailwind arbitrary values like
rounded-[var(--radius)]and utility classes likebg-primary. - Environment flexibility: Use
PCHAT_THEME_*andPCHAT_COLORvariables to override settings without touching code, handled byapplyEnvOverrides. - No rebuild required: The system uses a bundled Tailwind plugin and CSS custom properties, eliminating the need to modify
tailwind.config.tsor recompile stylesheets when theming changes.
Frequently Asked Questions
Where is the tailwind.config.ts file in prompts.chat?
The project does not expose a user-editable tailwind.config.ts. Instead, it relies on a bundled Tailwind plugin that maps utility classes (like bg-primary) to CSS variables. These variables are generated at runtime by src/app/layout.tsx based on your prompts.config.ts settings, allowing dynamic theming without CSS rebuilds.
Can I add multiple custom colors beyond the primary color?
The current ThemeConfig interface in src/lib/config/index.ts is optimized for a single primary color. To add secondary or semantic colors (success, warning, danger), extend the ThemeConfig type definition, add the new properties to your prompts.config.ts, and update src/app/layout.tsx (around lines 116-176) to inject additional CSS variables (e.g., --secondary) alongside the existing --primary logic.
How do I change the border radius for only specific components?
Since the global theme sets --radius on the <html> element, all components using rounded-[var(--radius)] share that value. For component-specific overrides, use static Tailwind utility classes (e.g., rounded-md or rounded-none) directly in that component's JSX, or define a new CSS variable in layout.tsx and reference it selectively.
Why does prompts.chat use OKLCH instead of HSL or RGB?
The hexToOklch() function in src/app/layout.tsx converts hex colors to the OKLCH color space because it provides perceptual uniformity—meaning equal changes in lightness values produce visually consistent results regardless of hue. This ensures that generated accessibility colors and opacity variations (like bg-primary/90) remain harmonious and predictable across different brand palettes.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →