Agent-almanac setup-tailwind-typescript

install
source · Clone the upstream repo
git clone https://github.com/pjt222/agent-almanac
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/pjt222/agent-almanac "$T" && mkdir -p ~/.claude/skills && cp -r "$T/i18n/wenyan-ultra/skills/setup-tailwind-typescript" ~/.claude/skills/pjt222-agent-almanac-setup-tailwind-typescript-4c214a && rm -rf "$T"
manifest: i18n/wenyan-ultra/skills/setup-tailwind-typescript/SKILL.md
source content

Set Up Tailwind CSS with TypeScript

Configure Tailwind CSS in a TypeScript project with custom theme, utilities, and type-safe patterns.

When to Use

  • Adding Tailwind CSS to an existing TypeScript project
  • Customizing Tailwind theme for a project's design system
  • Setting up type-safe component styling patterns
  • Configuring Tailwind plugins and extensions

Inputs

  • Required: TypeScript project (Next.js, Vite, or standalone React)
  • Optional: Design system tokens (colors, spacing, fonts)
  • Optional: Tailwind plugins to include

Procedure

Step 1: Install Tailwind CSS

npm install -D tailwindcss @tailwindcss/postcss postcss

For Next.js (if not already included):

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

Expected:

tailwindcss
,
postcss
, and
autoprefixer
are installed as dev dependencies. For Next.js,
tailwind.config.ts
and
postcss.config.js
are generated by
npx tailwindcss init -p
.

On failure: If

npx tailwindcss init
fails, install Tailwind first with
npm install -D tailwindcss
and retry. If using a monorepo, run the command from the app's root directory, not the workspace root.

Step 2: Configure tailwind.config.ts

import type { Config } from "tailwindcss";

const config: Config = {
  content: [
    "./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
    "./src/components/**/*.{js,ts,jsx,tsx,mdx}",
    "./src/app/**/*.{js,ts,jsx,tsx,mdx}",
  ],
  theme: {
    extend: {
      colors: {
        primary: {
          50: "#eff6ff",
          100: "#dbeafe",
          500: "#3b82f6",
          600: "#2563eb",
          700: "#1d4ed8",
          900: "#1e3a5f",
        },
        secondary: {
          500: "#6366f1",
          600: "#4f46e5",
        },
      },
      fontFamily: {
        sans: ["Inter", "system-ui", "sans-serif"],
        mono: ["JetBrains Mono", "monospace"],
      },
      spacing: {
        "18": "4.5rem",
        "88": "22rem",
      },
    },
  },
  plugins: [],
};

export default config;

Expected:

tailwind.config.ts
has a
content
array matching the project's file locations, custom colors and fonts under
theme.extend
, and proper TypeScript typing with the
Config
import.

On failure: If custom classes do not render, verify the

content
paths match your actual directory structure. Paths are glob patterns relative to the project root. Missing paths mean Tailwind will not scan those files for class usage.

Step 3: Set Up Global Styles

Edit

src/app/globals.css
:

@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
  html {
    @apply antialiased;
  }

  body {
    @apply bg-white text-gray-900 dark:bg-gray-950 dark:text-gray-100;
  }
}

@layer components {
  .btn-primary {
    @apply bg-primary-600 text-white px-4 py-2 rounded-lg
           hover:bg-primary-700 focus:outline-none focus:ring-2
           focus:ring-primary-500 focus:ring-offset-2
           transition-colors duration-200;
  }
}

Expected:

globals.css
contains the three Tailwind directives (
@tailwind base
,
@tailwind components
,
@tailwind utilities
) plus any custom base and component layer styles. The file is imported in the root layout.

On failure: If styles are not applied, verify

globals.css
is imported in
layout.tsx
(or
_app.tsx
for Pages Router). Check that the Tailwind directives are present and not commented out.

Step 4: Create Type-Safe Utility Helpers

Create

src/lib/cn.ts
:

import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}

Install dependencies:

npm install clsx tailwind-merge

Usage in components:

import { cn } from "@/lib/cn";

interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
  variant?: "primary" | "secondary" | "outline";
}

export function Button({ className, variant = "primary", ...props }: ButtonProps) {
  return (
    <button
      className={cn(
        "px-4 py-2 rounded-lg font-medium transition-colors",
        variant === "primary" && "bg-primary-600 text-white hover:bg-primary-700",
        variant === "secondary" && "bg-secondary-500 text-white hover:bg-secondary-600",
        variant === "outline" && "border border-gray-300 hover:bg-gray-50",
        className
      )}
      {...props}
    />
  );
}

Expected:

src/lib/cn.ts
exports a
cn()
function.
clsx
and
tailwind-merge
are installed as dependencies. Components use
cn()
to merge class names without conflicts.

On failure: If

clsx
or
tailwind-merge
are not found, run
npm install clsx tailwind-merge
. If TypeScript reports type errors in
cn.ts
, verify the
ClassValue
type is imported from
clsx
.

Step 5: Add Dark Mode Support

Update

tailwind.config.ts
:

const config: Config = {
  darkMode: "class", // or "media" for system preference
  // ... rest of config
};

Toggle implementation:

"use client";
import { useEffect, useState } from "react";

export function ThemeToggle() {
  const [dark, setDark] = useState(false);

  useEffect(() => {
    document.documentElement.classList.toggle("dark", dark);
  }, [dark]);

  return (
    <button onClick={() => setDark(!dark)}>
      {dark ? "Light" : "Dark"} Mode
    </button>
  );
}

Expected: Dark mode toggles correctly between light and dark themes. The

dark
class is applied to the
<html>
element, and
dark:
prefixed utility classes respond accordingly.

On failure: If dark mode does not toggle, verify

darkMode: "class"
is set in
tailwind.config.ts
. Ensure the
dark
class is toggled on the
<html>
element (not
<body>
). For system-preference mode, use
darkMode: "media"
instead.

Step 6: Add Plugins (Optional)

npm install -D @tailwindcss/typography @tailwindcss/forms
// tailwind.config.ts
import typography from "@tailwindcss/typography";
import forms from "@tailwindcss/forms";

const config: Config = {
  // ...
  plugins: [typography, forms],
};

Expected: Plugins are installed as dev dependencies and registered in the

plugins
array of
tailwind.config.ts
. Plugin-provided classes (e.g.,
prose
from typography, styled form elements from forms) are available in components.

On failure: If plugin classes do not render, verify the plugin is both installed (

npm ls @tailwindcss/typography
) and added to the
plugins
array. Restart the dev server after config changes.

Validation

  • Tailwind classes render correctly in the browser
  • Custom theme values (colors, fonts, spacing) work
  • cn()
    utility merges classes without conflicts
  • Dark mode toggles correctly
  • TypeScript shows no errors in config or components
  • Production build purges unused styles

Common Pitfalls

  • Content paths missing: If classes don't render, check
    content
    array in config matches your file locations
  • Class conflicts: Use
    tailwind-merge
    (via
    cn()
    ) to prevent conflicting utility classes
  • Custom values not working: Ensure custom values are under
    extend
    (to add) not at theme root (which replaces defaults)
  • Dark mode not toggling: Check
    darkMode
    setting and that the
    dark
    class is on
    <html>
    not
    <body>

Related Skills

  • scaffold-nextjs-app
    - project setup before Tailwind configuration
  • deploy-to-vercel
    - deploy the styled application