Skip to main content
TaskForge Studio uses a modern styling stack with Tailwind CSS, shadcn/ui components, and CSS variables for theming. This guide shows you how to customize the look and feel of your application.

Styling Architecture

The styling system consists of:
  1. Tailwind CSS - Utility-first CSS framework
  2. shadcn/ui - Re-usable component library
  3. CSS Variables - Dynamic theming with HSL colors
  4. Dark Mode - Built-in dark mode support

Tailwind Configuration

1

Understanding the Tailwind config

The Tailwind configuration is located in tailwind.config.ts:
tailwind.config.ts
import type { Config } from "tailwindcss"

const config = {
  darkMode: ["class"],
  content: [
    './pages/**/*.{ts,tsx}',
    './components/**/*.{ts,tsx}',
    './app/**/*.{ts,tsx}',
    './src/**/*.{ts,tsx}',
  ],
  prefix: "",
  theme: {
    container: {
      center: true,
      padding: "2rem",
      screens: {
        "2xl": "1400px",
      },
    },
    extend: {
      colors: {
        border: "hsl(var(--border))",
        input: "hsl(var(--input))",
        ring: "hsl(var(--ring))",
        background: "hsl(var(--background))",
        foreground: "hsl(var(--foreground))",
        primary: {
          DEFAULT: "hsl(var(--primary))",
          foreground: "hsl(var(--primary-foreground))",
        },
        secondary: {
          DEFAULT: "hsl(var(--secondary))",
          foreground: "hsl(var(--secondary-foreground))",
        },
        destructive: {
          DEFAULT: "hsl(var(--destructive))",
          foreground: "hsl(var(--destructive-foreground))",
        },
        muted: {
          DEFAULT: "hsl(var(--muted))",
          foreground: "hsl(var(--muted-foreground))",
        },
        accent: {
          DEFAULT: "hsl(var(--accent))",
          foreground: "hsl(var(--accent-foreground))",
        },
        popover: {
          DEFAULT: "hsl(var(--popover))",
          foreground: "hsl(var(--popover-foreground))",
        },
        card: {
          DEFAULT: "hsl(var(--card))",
          foreground: "hsl(var(--card-foreground))",
        },
      },
      borderRadius: {
        lg: "var(--radius)",
        md: "calc(var(--radius) - 2px)",
        sm: "calc(var(--radius) - 4px)",
      },
      keyframes: {
        "accordion-down": {
          from: { height: "0" },
          to: { height: "var(--radix-accordion-content-height)" },
        },
        "accordion-up": {
          from: { height: "var(--radix-accordion-content-height)" },
          to: { height: "0" },
        },
      },
      animation: {
        "accordion-down": "accordion-down 0.2s ease-out",
        "accordion-up": "accordion-up 0.2s ease-out",
      },
    },
  },
  plugins: [require("tailwindcss-animate")],
} satisfies Config

export default config
All colors reference CSS variables, making theme customization simple and consistent.
2

Modify CSS variables for theming

Customize your theme by editing the CSS variables in app/globals.css:
app/globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  :root {
    --background: 0 0% 100%;
    --foreground: 0 0% 3.9%;
    --card: 0 0% 100%;
    --card-foreground: 0 0% 3.9%;
    --popover: 0 0% 100%;
    --popover-foreground: 0 0% 3.9%;
    --primary: 0 0% 9%;
    --primary-foreground: 0 0% 98%;
    --secondary: 0 0% 96.1%;
    --secondary-foreground: 0 0% 9%;
    --muted: 0 0% 96.1%;
    --muted-foreground: 0 0% 45.1%;
    --accent: 0 0% 96.1%;
    --accent-foreground: 0 0% 9%;
    --destructive: 0 84.2% 60.2%;
    --destructive-foreground: 0 0% 98%;
    --border: 0 0% 89.8%;
    --input: 0 0% 89.8%;
    --ring: 0 0% 3.9%;
    --radius: 0.5rem;
  }

  .dark {
    --background: 0 0% 3.9%;
    --foreground: 0 0% 98%;
    --card: 0 0% 3.9%;
    --card-foreground: 0 0% 98%;
    --popover: 0 0% 3.9%;
    --popover-foreground: 0 0% 98%;
    --primary: 0 0% 98%;
    --primary-foreground: 0 0% 9%;
    --secondary: 0 0% 14.9%;
    --secondary-foreground: 0 0% 98%;
    --muted: 0 0% 14.9%;
    --muted-foreground: 0 0% 63.9%;
    --accent: 0 0% 14.9%;
    --accent-foreground: 0 0% 98%;
    --destructive: 0 62.8% 30.6%;
    --destructive-foreground: 0 0% 98%;
    --border: 0 0% 14.9%;
    --input: 0 0% 14.9%;
    --ring: 0 0% 83.1%;
  }
}
CSS variables use HSL format (Hue, Saturation, Lightness). Adjust these values to create your custom theme.

Color Customization

Creating a Custom Theme

To create a custom brand theme, modify the HSL values:
:root {
  --primary: 221 83% 53%;        /* Blue */
  --primary-foreground: 0 0% 100%;
  --accent: 221 83% 90%;          /* Light blue */
  --accent-foreground: 221 83% 20%;
}

Using Colors in Components

Reference the color variables using Tailwind classes:
<div className="bg-primary text-primary-foreground">
  Primary Button
</div>

<div className="bg-secondary text-secondary-foreground">
  Secondary Button
</div>

<div className="border-border bg-card text-card-foreground">
  Card Content
</div>

shadcn/ui Configuration

TaskForge Studio uses shadcn/ui components configured in components.json:
components.json
{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "new-york",
  "rsc": true,
  "tsx": true,
  "tailwind": {
    "config": "tailwind.config.ts",
    "css": "app/globals.css",
    "baseColor": "neutral",
    "cssVariables": true,
    "prefix": ""
  },
  "aliases": {
    "components": "@/components",
    "utils": "@/lib/utils"
  }
}

Change Component Style

You can switch between “default” and “new-york” styles:
{
  "style": "default"  // or "new-york"
}

Change Base Color

Available base colors: slate, gray, zinc, neutral, stone
{
  "tailwind": {
    "baseColor": "slate"  // Changes the neutral color palette
  }
}

Border Radius Customization

Adjust the global border radius:
app/globals.css
:root {
  --radius: 0.5rem;  /* Default */
}

/* For more rounded corners */
:root {
  --radius: 0.75rem;
}

/* For sharp corners */
:root {
  --radius: 0rem;
}
The radius automatically scales:
  • rounded-lg = var(--radius)
  • rounded-md = calc(var(--radius) - 2px)
  • rounded-sm = calc(var(--radius) - 4px)

Dark Mode Implementation

1

Enable dark mode class

Dark mode is controlled via the class strategy in tailwind.config.ts:
const config = {
  darkMode: ["class"],
  // ...
}
2

Toggle dark mode

Add a dark mode toggle using the next-themes package:
npm install next-themes
Create a theme provider:
providers/theme-provider.tsx
'use client';

import { ThemeProvider as NextThemesProvider } from 'next-themes';

export function ThemeProvider({ children }: { children: React.ReactNode }) {
  return (
    <NextThemesProvider
      attribute="class"
      defaultTheme="system"
      enableSystem
    >
      {children}
    </NextThemesProvider>
  );
}
Add the toggle button:
import { useTheme } from 'next-themes';

function ThemeToggle() {
  const { theme, setTheme } = useTheme();

  return (
    <button onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
      Toggle Theme
    </button>
  );
}

Custom Animations

The Tailwind config includes custom animations for accordions. Add your own:
tailwind.config.ts
keyframes: {
  "fade-in": {
    from: { opacity: "0" },
    to: { opacity: "1" },
  },
  "slide-up": {
    from: { transform: "translateY(10px)", opacity: "0" },
    to: { transform: "translateY(0)", opacity: "1" },
  },
},
animation: {
  "fade-in": "fade-in 0.3s ease-out",
  "slide-up": "slide-up 0.3s ease-out",
},
Use in components:
<div className="animate-fade-in">
  Fades in
</div>

<div className="animate-slide-up">
  Slides up
</div>

Utility Class: cn()

TaskForge Studio uses a cn() utility for conditional classes in lib/utils.ts:
lib/utils.ts
import { type ClassValue, clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}
Usage:
import { cn } from '@/lib/utils';

function Button({ className, variant }) {
  return (
    <button
      className={cn(
        "px-4 py-2 rounded",
        variant === "primary" && "bg-primary text-primary-foreground",
        variant === "secondary" && "bg-secondary text-secondary-foreground",
        className
      )}
    >
      Click me
    </button>
  );
}

Font Customization

TaskForge Studio uses Inter font from Google Fonts. To change the font:
app/layout.tsx
import { Inter, Roboto } from 'next/font/google';

// Change to your preferred font
const roboto = Roboto({ 
  subsets: ['latin'],
  weight: ['400', '500', '700'],
});

export default function RootLayout({ children }) {
  return (
    <html lang='en'>
      <body className={roboto.className}>
        {children}
      </body>
    </html>
  );
}

Best Practices

Consistent theming: Always use CSS variables instead of hardcoded colors to ensure your theme is consistent and easy to change.
HSL format: When modifying CSS variables, use HSL format without the hsl() wrapper. The wrapper is added by Tailwind.
Component variants: Create component variants using the cn() utility to keep your styling logic clean and maintainable.

Responsive Design

Tailwind provides responsive utilities. The container is already configured:
tailwind.config.ts
container: {
  center: true,
  padding: "2rem",
  screens: {
    "2xl": "1400px",
  },
},
Use responsive classes:
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3">
  {/* Responsive grid */}
</div>

Next Steps

Build docs developers (and LLMs) love