Installation
Follow the Tailwind documentation to create a new Next.js project using Tailwind.
Currently, Soul supports Tailwind v4. If you're using Tailwind v3, refer to our previous Tailwind v3 documentation.
Install dependencies
npm install -D @tailwindcss/typography tailwindcss-animate
Update globals.css
Copy and paste the following styles into your globals.css file below the @import 'tailwindcss'
statement.
@plugin 'tailwindcss-animate';@plugin '@tailwindcss/typography';@theme inline { --color-primary: var(--primary); --color-primary-highlight: var(--primary-highlight); --color-primary-shadow: var(--primary-shadow); --color-accent: var(--accent); --color-accent-highlight: var(--accent-highlight); --color-accent-shadow: var(--accent-shadow); --color-success: var(--success); --color-success-highlight: var(--success-highlight); --color-success-shadow: var(--success-shadow); --color-error: var(--error); --color-error-highlight: var(--error-highlight); --color-error-shadow: var(--error-shadow); --color-warning: var(--warning); --color-warning-highlight: var(--warning-highlight); --color-warning-shadow: var(--warning-shadow); --color-info: var(--info); --color-info-highlight: var(--info-highlight); --color-info-shadow: var(--info-shadow); --color-foreground: var(--foreground); --color-background: var(--background); --color-contrast-100: var(--contrast-100); --color-contrast-200: var(--contrast-200); --color-contrast-300: var(--contrast-300); --color-contrast-400: var(--contrast-400); --color-contrast-500: var(--contrast-500); --text-xs: var(--font-size-xs); --text-xs--line-height: var(--font-size-xs-line-height); --text-xs--letter-spacing: var(--font-size-xs-letter-spacing); --text-sm: var(--font-size-sm); --text-sm-line-height: var(--font-size-sm-line-height); --text-sm-letter-spacing: var(--font-size-sm-letter-spacing); --text-base: var(--font-size-base); --text-base--line-height: var(--font-size-base-line-height); --text-base--letter-spacing: var(--font-size-base-letter-spacing); --text-lg: var(--font-size-lg); --text-lg--line-height: var(--font-size-lg-line-height); --text-lg--letter-spacing: var(--font-size-lg-letter-spacing); --text-xl: var(--font-size-xl); --text-xl--line-height: var(--font-size-xl-line-height); --text-xl--letter-spacing: var(--font-size-xl-letter-spacing); --text-2xl: var(--font-size-2xl); --text-2xl--line-height: var(--font-size-2xl-line-height); --text-2xl--letter-spacing: var(--font-size-2xl-letter-spacing); --text-3xl: var(--font-size-3xl); --text-3xl--line-height: var(--font-size-3xl-line-height); --text-3xl--letter-spacing: var(--font-size-3xl-letter-spacing); --text-4xl: var(--font-size-4xl); --text-4xl--line-height: var(--font-size-4xl-line-height); --text-4xl--letter-spacing: var(--font-size-4xl-letter-spacing); --text-5xl: var(--font-size-5xl); --text-5xl--line-height: var(--font-size-5xl-line-height); --text-5xl--letter-spacing: var(--font-size-5xl-letter-spacing); --text-6xl: var(--font-size-6xl); --text-6xl--line-height: var(--font-size-6xl-line-height); --text-6xl--letter-spacing: var(--font-size-6xl-letter-spacing); --text-7xl: var(--font-size-7xl); --text-7xl--line-height: var(--font-size-7xl-line-height); --text-7xl--letter-spacing: var(--font-size-7xl-letter-spacing); --text-8xl: var(--font-size-8xl); --text-8xl--line-height: var(--font-size-8xl-line-height); --text-8xl--letter-spacing: var(--font-size-8xl-letter-spacing); --text-9xl: var(--font-size-9xl); --text-9xl--line-height: var(--font-size-9xl-line-height); --text-9xl--letter-spacing: var(--font-size-9xl-letter-spacing); --shadow-xs: var(--shadow-xs); --shadow-sm: var(--shadow-sm); --shadow-md: var(--shadow-md); --shadow-lg: var(--shadow-lg); --shadow-xl: var(--shadow-xl); --font-heading: var(--font-family-heading); --font-heading--font-feature-settings: var(--font-feature-settings-heading); --font-heading--font-variation-settings: var(--font-variation-settings-heading); --font-body: var(--font-family-body); --font-body--font-feature-settings: var(--font-feature-settings-body); --font-body--font-variation-settings: var(--font-variation-settings-body); --font-mono: var(--font-family-mono); --font-mono--font-feature-settings: var(--font-feature-settings-mono); --font-mono--font-variation-settings: var(--font-variation-settings-mono); --animate-collapse: collapse 400ms cubic-bezier(1, 0, 0.25, 1); --animate-expand: expand 400ms cubic-bezier(1, 0, 0.25, 1); --animate-marching: marching-ants 10s linear infinite; --animate-rotate: rotate 2000ms linear infinite; --animate-scroll: scroll 200ms infinite linear both; --animate-scrollLeft: scrollLeft var(--marquee-duration) linear infinite; --animate-shake: shake 0.5s cubic-bezier(0.36, 0.07, 0.19, 0.97) both; --animate-slideIn: slideIn 800ms cubic-bezier(0.25, 1, 0, 1); @keyframes collapse { from { height: var(--radix-accordion-content-height); } to { height: 0; } } @keyframes expand { from { height: 0; } to { height: var(--radix-accordion-content-height); } } @keyframes marching-ants { to { background-position: 0 0, 0 -1px, calc(100% + 1px) 0, 100% calc(100% + 1px), -1px 100%; } } @keyframes rotateFade { from { opacity: 1; transform: rotateZ(0deg) translate3d(-50%, -50%, 0); } 35% { opacity: 0; } 70% { opacity: 0; } to { opacity: 1; transform: rotateZ(360deg) translate3d(-50%, -50%, 0); } } @keyframes rotate { from { transform: rotateZ(0deg) translate3d(-50%, -50%, 0); } to { transform: rotateZ(360deg) translate3d(-50%, -50%, 0); } } @keyframes scroll { to { background-position: 5px 0; } } @keyframes dotScrollSmall: { to: { background-position: -6px -6px, -12px -12px; } } @keyframes dotScrollLarge: { to { background-position: -8px -8px, -16px -16px; } } @keyframes scrollLeft { 0% { transform: translateX(0); } 100% { transform: translateX(-100%); } } @keyframes shake { 10%, 90% { transform: translate3d(-1px, 0, 0); } 20%, 80% { transform: translate3d(1px, 0, 0); } 30%, 50%, 70% { transform: translate3d(-2px, 0, 0); } 40%, 60% { transform: translate3d(2px, 0, 0); } } @keyframes slideIn: { 0% { transform: translateX(-100%); } 100% { transform: translateX(0%); } }}@layer utilities { .prose { :where(h1):not(:where([class~='not-prose'], [class~='not-prose'] *)) { color: var(--foreground); font-family: var(--font-family-heading); } :where(h2):not(:where([class~='not-prose'], [class~='not-prose'] *)) { color: var(--foreground); font-family: var(--font-family-heading); } :where(h3):not(:where([class~='not-prose'], [class~='not-prose'] *)) { color: var(--foreground); font-family: var(--font-family-heading); } :where(h4):not(:where([class~='not-prose'], [class~='not-prose'] *)) { color: var(--foreground); font-family: var(--font-family-heading); } :where(h5):not(:where([class~='not-prose'], [class~='not-prose'] *)) { color: var(--foreground); font-family: var(--font-family-heading); } :where(h6):not(:where([class~='not-prose'], [class~='not-prose'] *)) { color: var(--foreground); font-family: var(--font-family-heading); } :where(p):not(:where([class~='not-prose'], [class~='not-prose'] *)) { color: var(--foreground); font-family: var(--font-family-body); } :where(a):not(:where([class~='not-prose'], [class~='not-prose'] *)) { color: color-mix(in oklab, var(--primary), black 15%); text-decoration: none; &:hover { text-decoration: underline; } } :where(ul):not(:where([class~='not-prose'], [class~='not-prose'] *)) { color: var(--contrast-500); font-family: var(--font-family-body); } :where(ol):not(:where([class~='not-prose'], [class~='not-prose'] *)) { color: var(--contrast-500); font-family: var(--font-family-body); } :where(strong):not(:where([class~='not-prose'], [class~='not-prose'] *)) { font-weight: 600; } :where(blockquote):not(:where([class~='not-prose'], [class~='not-prose'] *)) { border-left-color: var(--contrast-300); p { color: var(--contrast-500); font-style: normal; font-weight: 400; } } :where(code):not(:where([class~='not-prose'], [class~='not-prose'] *)) { color: var(--contrast-500); font-family: var(--font-family-mono); } :where(pre):not(:where([class~='not-prose'], [class~='not-prose'] *)) { color: var(--background); background-color: var(--foreground); font-family: var(--font-family-mono); } }}
Optional: Configure image domains
Add the following configuration in your next.config.ts
file to display images in the code examples. Remember to update this configuration with your production image domain when deploying.
import type { NextConfig } from 'next';const nextConfig: NextConfig = { images: { remotePatterns: [ { protocol: 'https', hostname: 'storage.googleapis.com', pathname: '/s.mkswft.com/**', port: '', }, ], },};export default nextConfig;