Docs
Customization

Theming

Learn how to style your application.

shadcn/ui

The starter kit uses shadcn/ui, which is essentially a set of Tailwind CSS-styled components based on Radix UI and enhanced with Embla Carousel, Vaul, Sonner and custom implementations.

Tailwind

In the tooling/tailwind/index.js file you can configure the Tailwind CSS theme. It's used across the monorepo, ensuring a consistent theme. This includes colors, spacing, border radius and animations.

import animate from 'tailwindcss-animate';
import { fontFamily } from 'tailwindcss/defaultTheme';
 
/** @type {import("tailwindcss").Config} */
const config = {
  darkMode: ['class'],
  content: [
    '../../apps/dashboard/**/*.{ts,tsx}',
    '../../apps/marketing/**/*.{ts,tsx}',
    '../../packages/ui/**/*.{ts,tsx}',
    '!**/.next',
    '!**/.cache',
    '!**/.content-collections',
    '!**/.turbo',
    '!**/node_modules',
    '!**/build',
    '!**/dist'
  ],
  theme: {
    container: {
      center: true,
      padding: '2rem',
      screens: {
        '2xl': '1400px'
      }
    },
    extend: {
      fontFamily: {
        sans: ['var(--font-sans)', ...fontFamily.sans],
        mono: ['var(--font-mono)', ...fontFamily.mono]
      },
      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))'
        },
        sidebar: {
          DEFAULT: 'hsl(var(--sidebar-background))',
          foreground: 'hsl(var(--sidebar-foreground))',
          primary: 'hsl(var(--sidebar-primary))',
          'primary-foreground': 'hsl(var(--sidebar-primary-foreground))',
          accent: 'hsl(var(--sidebar-accent))',
          'accent-foreground': 'hsl(var(--sidebar-accent-foreground))',
          border: 'hsl(var(--sidebar-border))',
          ring: 'hsl(var(--sidebar-ring))'
        }
      },
      backgroundImage: {
        'diagonal-lines':
          'repeating-linear-gradient(-45deg, hsl(var(--background)), hsl(var(--border)) 1px, hsl(var(--background)) 1px, hsl(var(--background)) 8px)'
      },
      borderRadius: {
        lg: 'var(--radius)',
        md: 'calc(var(--radius) - 2px)',
        sm: 'calc(var(--radius) - 4px)'
      },
      keyframes: {
        // ...
      },
      animation: {
        // ...
      }
    }
  },
  plugins: [animate]
};
 
export default config;

Font

You change the font individually for each app. Open

  • Dashboard: apps/dashboard/app/layout.tsx
  • Marketing: apps/marketing/app/layout.tsx

and change the current font

import { Inter } from 'next/font/google';
 
const inter = Inter({ subsets: ['latin'] });

to some other font, e.g. Geist font.

Global styles

If you need to modify the global css style, have a look at packages/ui/src/styles/globals.css. We configured a few global styles like disabled the chrome number input spinner in favor of our own number input component.

/* Chrome, Safari, Edge, Opera */
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
 
/* Firefox */
input[type='number'] {
  -moz-appearance: textfield;
}