
tailwind-design-system
Build scalable design systems with Tailwind CSS v4, design tokens, component libraries, and responsive patterns. Use when creating component libraries, implementing design systems, or standardizing UI patterns.
- Installs
- 1.1K
- Last 24h
- +11
- Trending rank
- #8381
- Security
- Not audited
Install
Works with every agent the skills CLI supports.
npx skills add https://github.com/calesthio/openmontage --skill tailwind-design-system- 01
Install
Run the command in your project. The CLI asks which agents to install for.
- 02
Describe the task
Ask your agent for something this skill covers. It loads tailwind-design-system automatically when relevant.
- 03
Review the result
The agent follows the SKILL.md steps, scripts and references bundled with the skill.
SKILL.md
The instructions your agent reads when the skill is triggered.
Tailwind Design System (v4)
Build production-ready design systems with Tailwind CSS v4, including CSS-first configuration, design tokens, component variants, responsive patterns, and accessibility.
Note: This skill targets Tailwind CSS v4 (2024+). For v3 projects, refer to the upgrade guide.
When to Use This Skill
- Creating a component library with Tailwind v4
- Implementing design tokens and theming with CSS-first configuration
- Building responsive and accessible components
- Standardizing UI patterns across a codebase
- Migrating from Tailwind v3 to v4
- Setting up dark mode with native CSS features
Key v4 Changes
| v3 Pattern | v4 Pattern |
|---|---|
tailwind.config.ts | @theme in CSS |
@tailwind base/components/utilities | @import "tailwindcss" |
darkMode: "class" | @custom-variant dark (&:where(.dark, .dark *)) |
theme.extend.colors | @theme { --color-*: value } |
require("tailwindcss-animate") | CSS @keyframes in @theme + @starting-style for entry animations |
Quick Start
/* app.css - Tailwind v4 CSS-first configuration */
@import "tailwindcss";
/* Define your theme with @theme */
@theme {
/* Semantic color tokens using OKLCH for better color perception */
--color-background: oklch(100% 0 0);
--color-foreground: oklch(14.5% 0.025 264);
--color-primary: oklch(14.5% 0.025 264);
--color-primary-foreground: oklch(98% 0.01 264);
--color-secondary: oklch(96% 0.01 264);
--color-secondary-foreground: oklch(14.5% 0.025 264);
--color-muted: oklch(96% 0.01 264);
--color-muted-foreground: oklch(46% 0.02 264);
--color-accent: oklch(96% 0.01 264);
--color-accent-foreground: oklch(14.5% 0.025 264);
--color-destructive: oklch(53% 0.22 27);
--color-destructive-foreground: oklch(98% 0.01 264);
--color-border: oklch(91% 0.01 264);
--color-ring: oklch(14.5% 0.025 264);
--color-card: oklch(100% 0 0);
--color-card-foreground: oklch(14.5% 0.025 264);
/* Ring offset for focus states */
--color-ring-offset: oklch(100% 0 0);
/* Radius tokens */
--radius-sm: 0.25rem;
--radius-md: 0.375rem;
--radius-lg: 0.5rem;
--radius-xl: 0.75rem;
/* Animation tokens - keyframes inside @theme are output when referenced by --animate-* variables */
--animate-fade-in: fade-in 0.2s ease-out;
--animate-fade-out: fade-out 0.2s ease-in;
--animate-slide-in: slide-in 0.3s ease-out;
--animate-slide-out: slide-out 0.3s ease-in;
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fade-out {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
@keyframes slide-in {
from {
transform: translateY(-0.5rem);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
@keyframes slide-out {
from {
transform: translateY(0);
opacity: 1;
}
to {
transform: translateY(-0.5rem);
opacity: 0;
}
}
}
/* Dark mode variant - use @custom-variant for class-based dark mode */
@custom-variant dark (&:where(.dark, .dark *));
/* Dark mode theme overrides */
.dark {
--color-background: oklch(14.5% 0.025 264);
--color-foreground: oklch(98% 0.01 264);
--color-primary: oklch(98% 0.01 264);
--color-primary-foreground: oklch(14.5% 0.025 264);
--color-secondary: oklch(22% 0.02 264);
--color-secondary-foreground: oklch(98% 0.01 264);
--color-muted: oklch(22% 0.02 264);
--color-muted-foreground: oklch(65% 0.02 264);
--color-accent: oklch(22% 0.02 264);
--color-accent-foreground: oklch(98% 0.01 264);
--color-destructive: oklch(42% 0.15 27);
--color-destructive-foreground: oklch(98% 0.01 264);
--color-border: oklch(22% 0.02 264);
--color-ring: oklch(83% 0.02 264);
--color-card: oklch(14.5% 0.025 264);
--color-card-foreground: oklch(98% 0.01 264);
--color-ring-offset: oklch(14.5% 0.025 264);
}
/* Base styles */
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground antialiased;
}
}
Core Concepts
1. Design Token Hierarchy
Brand Tokens (abstract)
└── Semantic Tokens (purpose)
└── Component Tokens (specific)
Example:
oklch(45% 0.2 260) → --color-primary → bg-primary
2. Component Architecture
Base styles → Variants → Sizes → States → Overrides
Patterns
Pattern 1: CVA (Class Variance Authority) Components
// components/ui/button.tsx
import { Slot } from '@radix-ui/react-slot'
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/lib/utils'
const buttonVariants = cva(
// Base styles - v4 uses native CSS variables
'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
{
variants: {
variant: {
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
outline: 'border border-border bg-background hover:bg-accent hover:text-accent-foreground',
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
ghost: 'hover:bg-accent hover:text-accent-foreground',
link: 'text-primary underline-offset-4 hover:underline',
},
size: {
default: 'h-10 px-4 py-2',
sm: 'h-9 rounded-md px-3',
lg: 'h-11 rounded-md px-8',
icon: 'size-10',
},
},
defaultVariants: {
variant: 'default',
size: 'default',
},
}
)
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean
}
// React 19: No forwardRef needed
export function Button({
className,
variant,
size,
asChild = false,
ref,
...props
}: ButtonProps & { ref?: React.Ref<HTMLButtonElement> }) {
const Comp = asChild ? Slot : 'button'
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
)
}
// Usage
<Button variant="destructive" size="lg">Delete</Button>
<Button variant="outline">Cancel</Button>
<Button asChild><Link href="/home">Home</Link></Button>
Pattern 2: Compound Components (React 19)
// components/ui/card.tsx
import { cn } from '@/lib/utils'
// React 19: ref is a regular prop, no forwardRef
export function Card({
className,
ref,
...props
}: React.HTMLAttributes<HTMLDivElement> & { ref?: React.Ref<HTMLDivElement> }) {
return (
<div
ref={ref}
className={cn(
'rounded-lg border border-border bg-card text-card-foreground shadow-sm',
className
)}
{...props}
/>
)
}
export function CardHeader({
className,
ref,
...props
}: React.HTMLAttributes<HTMLDivElement> & { ref?: React.Ref<HTMLDivElement> }) {
return (
<div
ref={ref}
className={cn('flex flex-col space-y-1.5 p-6', className)}
{...props}
/>
)
}
export function CardTitle({
className,
ref,
...props
}: React.HTMLAttributes<HTMLHeadingElement> & { ref?: React.Ref<HTMLHeadingElement> }) {
return (
<h3
ref={ref}
className={cn('text-2xl font-semibold leading-none tracking-tight', className)}
{...props}
/>
)
}
export function CardDescription({
className,
ref,
...props
}: React.HTMLAttributes<HTMLParagraphElement> & { ref?: React.Ref<HTMLParagraphElement> }) {
return (
<p
ref={ref}
className={cn('text-sm text-muted-foreground', className)}
{...props}
/>
)
}
export function CardContent({
className,
ref,
...props
}: React.HTMLAttributes<HTMLDivElement> & { ref?: React.Ref<HTMLDivElement> }) {
return (
<div ref={ref} className={cn('p-6 pt-0', className)} {...props} />
)
}
export function CardFooter({
className,
ref,
...props
}: React.HTMLAttributes<HTMLDivElement> & { ref?: React.Ref<HTMLDivElement> }) {
return (
<div
ref={ref}
className={cn('flex items-center p-6 pt-0', className)}
{...props}
/>
)
}
// Usage
<Card>
<CardHeader>
<CardTitle>Account</CardTitle>
<CardDescription>Manage your account settings</CardDescription>
</CardHeader>
<CardContent>
<form>...</form>
</CardContent>
<CardFooter>
<Button>Save</Button>
</CardFooter>
</Card>
Pattern 3: Form Components
// components/ui/input.tsx
import { cn } from '@/lib/utils'
export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
error?: string
ref?: React.Ref<HTMLInputElement>
}
export function Input({ className, type, error, ref, ...props }: InputProps) {
return (
<div className="relative">
<input
type={type}
className={cn(
'flex h-10 w-full rounded-md border border-border bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
error && 'border-destructive focus-visible:ring-destructive',
className
)}
ref={ref}
aria-invalid={!!error}
aria-describedby={error ? `${props.id}-error` : undefined}
{...props}
/>
{error && (
<p
id={`${props.id}-error`}
className="mt-1 text-sm text-destructive"
role="alert"
>
{error}
</p>
)}
</div>
)
}
// components/ui/label.tsx
import { cva, type VariantProps } from 'class-variance-authority'
const labelVariants = cva(
'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70'
)
export function Label({
className,
ref,
...props
}: React.LabelHTMLAttributes<HTMLLabelElement> & { ref?: React.Ref<HTMLLabelElement> }) {
return (
<label ref={ref} className={cn(labelVariants(), className)} {...props} />
)
}
// Usage with React Hook Form + Zod
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { z } from 'zod'
const schema = z.object({
email: z.string().email('Invalid email address'),
password: z.string().min(8, 'Password must be at least 8 characters'),
})
function LoginForm() {
const { register, handleSubmit, formState: { errors } } = useForm({
resolver: zodResolver(schema),
})
return (
<form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<Input
id="email"
type="email"
{...register('email')}
error={errors.email?.message}
/>
</div>
<div className="space-y-2">
<Label htmlFor="password">Password</Label>
<Input
id="password"
type="password"
{...register('password')}
error={errors.password?.message}
/>
</div>
<Button type="submit" className="w-full">Sign In</Button>
</form>
)
}
Pattern 4: Responsive Grid System
// components/ui/grid.tsx
import { cn } from '@/lib/utils'
import { cva, type VariantProps } from 'class-variance-authority'
const gridVariants = cva('grid', {
variants: {
cols: {
1: 'grid-cols-1',
2: 'grid-cols-1 sm:grid-cols-2',
3: 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3',
4: 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-4',
5: 'grid-cols-2 sm:grid-cols-3 lg:grid-cols-5',
6: 'grid-cols-2 sm:grid-cols-3 lg:grid-cols-6',
},
gap: {
none: 'gap-0',
sm: 'gap-2',
md: 'gap-4',
lg: 'gap-6',
xl: 'gap-8',
},
},
defaultVariants: {
cols: 3,
gap: 'md',
},
})
interface GridProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof gridVariants> {}
export function Grid({ className, cols, gap, ...props }: GridProps) {
return (
<div className={cn(gridVariants({ cols, gap, className }))} {...props} />
)
}
// Container component
const containerVariants = cva('mx-auto w-full px-4 sm:px-6 lg:px-8', {
variants: {
size: {
sm: 'max-w-screen-sm',
md: 'max-w-screen-md',
lg: 'max-w-screen-lg',
xl: 'max-w-screen-xl',
'2xl': 'max-w-screen-2xl',
full: 'max-w-full',
},
},
defaultVariants: {
size: 'xl',
},
})
interface ContainerProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof containerVariants> {}
export function Container({ className, size, ...props }: ContainerProps) {
return (
<div className={cn(containerVariants({ size, className }))} {...props} />
)
}
// Usage
<Container>
<Grid cols={4} gap="lg">
{products.map((product) => (
<ProductCard key={product.id} product={product} />
))}
</Grid>
</Container>
Pattern 5: Native CSS Animations (v4)
/* In your CSS file - native @starting-style for entry animations */
@theme {
--animate-dialog-in: dialog-fade-in 0.2s ease-out;
--animate-dialog-out: dialog-fade-out 0.15s ease-in;
}
@keyframes dialog-fade-in {
from {
opacity: 0;
transform: scale(0.95) translateY(-0.5rem);
}
to {
opacity: 1;
transform: scale(1) translateY(0);
}
}
@keyframes dialog-fade-out {
from {
opacity: 1;
transform: scale(1) translateY(0);
}
to {
opacity: 0;
transform: scale(0.95) translateY(-0.5rem);
}
}
/* Native popover animations using @starting-style */
[popover] {
transition:
opacity 0.2s,
transform 0.2s,
display 0.2s allow-discrete;
opacity: 0;
transform: scale(0.95);
}
[popover]:popover-open {
opacity: 1;
transform: scale(1);
}
@starting-style {
[popover]:popover-open {
opacity: 0;
transform: scale(0.95);
}
}
// components/ui/dialog.tsx - Using native popover API
import * as DialogPrimitive from '@radix-ui/react-dialog'
import { cn } from '@/lib/utils'
const DialogPortal = DialogPrimitive.Portal
export function DialogOverlay({
className,
ref,
...props
}: React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay> & {
ref?: React.Ref<HTMLDivElement>
}) {
return (
<DialogPrimitive.Overlay
ref={ref}
className={cn(
'fixed inset-0 z-50 bg-black/80',
'data-[state=open]:animate-fade-in data-[state=closed]:animate-fade-out',
className
)}
{...props}
/>
)
}
export function DialogContent({
className,
children,
ref,
...props
}: React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> & {
ref?: React.Ref<HTMLDivElement>
}) {
return (
<DialogPortal>
<DialogOverlay />
<DialogPrimitive.Content
ref={ref}
className={cn(
'fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 border border-border bg-background p-6 shadow-lg sm:rounded-lg',
'data-[state=open]:animate-dialog-in data-[state=closed]:animate-dialog-out',
className
)}
{...props}
>
{children}
</DialogPrimitive.Content>
</DialogPortal>
)
}
Pattern 6: Dark Mode with CSS (v4)
// providers/ThemeProvider.tsx - Simplified for v4
'use client'
import { createContext, useContext, useEffect, useState } from 'react'
type Theme = 'dark' | 'light' | 'system'
interface ThemeContextType {
theme: Theme
setTheme: (theme: Theme) => void
resolvedTheme: 'dark' | 'light'
}
const ThemeContext = createContext<ThemeContextType | undefined>(undefined)
export function ThemeProvider({
children,
defaultTheme = 'system',
storageKey = 'theme',
}: {
children: React.ReactNode
defaultTheme?: Theme
storageKey?: string
}) {
const [theme, setTheme] = useState<Theme>(defaultTheme)
const [resolvedTheme, setResolvedTheme] = useState<'dark' | 'light'>('light')
useEffect(() => {
const stored = localStorage.getItem(storageKey) as Theme | null
if (stored) setTheme(stored)
}, [storageKey])
useEffect(() => {
const root = document.documentElement
root.classList.remove('light', 'dark')
const resolved = theme === 'system'
? (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')
: theme
root.classList.add(resolved)
setResolvedTheme(resolved)
// Update meta theme-color for mobile browsers
const metaThemeColor = document.querySelector('meta[name="theme-color"]')
if (metaThemeColor) {
metaThemeColor.setAttribute('content', resolved === 'dark' ? '#09090b' : '#ffffff')
}
}, [theme])
return (
<ThemeContext.Provider value={{
theme,
setTheme: (newTheme) => {
localStorage.setItem(storageKey, newTheme)
setTheme(newTheme)
},
resolvedTheme,
}}>
{children}
</ThemeContext.Provider>
)
}
export const useTheme = () => {
const context = useContext(ThemeContext)
if (!context) throw new Error('useTheme must be used within ThemeProvider')
return context
}
// components/ThemeToggle.tsx
import { Moon, Sun } from 'lucide-react'
import { useTheme } from '@/providers/ThemeProvider'
export function ThemeToggle() {
const { resolvedTheme, setTheme } = useTheme()
return (
<Button
variant="ghost"
size="icon"
onClick={() => setTheme(resolvedTheme === 'dark' ? 'light' : 'dark')}
>
<Sun className="size-5 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Moon className="absolute size-5 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
<span className="sr-only">Toggle theme</span>
</Button>
)
}
Utility Functions
// lib/utils.ts
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
// Focus ring utility
export const focusRing = cn(
"focus-visible:outline-none focus-visible:ring-2",
"focus-visible:ring-ring focus-visible:ring-offset-2",
);
// Disabled utility
export const disabled = "disabled:pointer-events-none disabled:opacity-50";
Advanced v4 Patterns
Custom Utilities with @utility
Define reusable custom utilities:
/* Custom utility for decorative lines */
@utility line-t {
@apply relative before:absolute before:top-0 before:-left-[100vw] before:h-px before:w-[200vw] before:bg-gray-950/5 dark:before:bg-white/10;
}
/* Custom utility for text gradients */
@utility text-gradient {
@apply bg-gradient-to-r from-primary to-accent bg-clip-text text-transparent;
}
Theme Modifiers
/* Use @theme inline when referencing other CSS variables */
@theme inline {
--font-sans: var(--font-inter), system-ui;
}
/* Use @theme static to always generate CSS variables (even when unused) */
@theme static {
--color-brand: oklch(65% 0.15 240);
}
/* Import with theme options */
@import "tailwindcss" theme(static);
Namespace Overrides
@theme {
/* Clear all default colors and define your own */
--color-*: initial;
--color-white: #fff;
--color-black: #000;
--color-primary: oklch(45% 0.2 260);
--color-secondary: oklch(65% 0.15 200);
/* Clear ALL defaults for a minimal setup */
/* --*: initial; */
}
Semi-transparent Color Variants
@theme {
/* Use color-mix() for alpha variants */
--color-primary-50: color-mix(in oklab, var(--color-primary) 5%, transparent);
--color-primary-100: color-mix(
in oklab,
var(--color-primary) 10%,
transparent
);
--color-primary-200: color-mix(
in oklab,
var(--color-primary) 20%,
transparent
);
}
Container Queries
@theme {
--container-xs: 20rem;
--container-sm: 24rem;
--container-md: 28rem;
--container-lg: 32rem;
}
v3 to v4 Migration Checklist
- Replace
tailwind.config.tswith CSS@themeblock - Change
@tailwind base/components/utilitiesto@import "tailwindcss" - Move color definitions to
@theme { --color-*: value } - Replace
darkMode: "class"with@custom-variant dark - Move
@keyframesinside@themeblocks (ensures keyframes output with theme) - Replace
require("tailwindcss-animate")with native CSS animations - Update
h-10 w-10tosize-10(new utility) - Remove
forwardRef(React 19 passes ref as prop) - Consider OKLCH colors for better color perception
- Replace custom plugins with
@utilitydirectives
Best Practices
Do's
- Use
@themeblocks - CSS-first configuration is v4's core pattern - Use OKLCH colors - Better perceptual uniformity than HSL
- Compose with CVA - Type-safe variants
- Use semantic tokens -
bg-primarynotbg-blue-500 - Use
size-*- New shorthand forw-* h-* - Add accessibility - ARIA attributes, focus states
Don'ts
- Don't use
tailwind.config.ts- Use CSS@themeinstead - Don't use
@tailwinddirectives - Use@import "tailwindcss" - Don't use
forwardRef- React 19 passes ref as prop - Don't use arbitrary values - Extend
@themeinstead - Don't hardcode colors - Use semantic tokens
- Don't forget dark mode - Test both themes
FAQ
What does the tailwind-design-system skill do?
Build scalable design systems with Tailwind CSS v4, design tokens, component libraries, and responsive patterns. Use when creating component libraries, implementing design systems, or standardizing UI patterns.
How do I install tailwind-design-system?
Run npx skills add https://github.com/calesthio/openmontage --skill tailwind-design-system in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/tailwind-design-system/ (personal) or .claude/skills/tailwind-design-system/ (project).
Which AI agents can use tailwind-design-system?
Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.
Is tailwind-design-system safe to install?
No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.
Who maintains tailwind-design-system?
It is published by calesthio in calesthio/openmontage. It has 1,059 recorded installs.
More from calesthio/openmontage
video-edit
calesthio/openmontage
Edit videos locally using ffmpeg. Trim, concat, resize, speed, overlay, extract audio, compress, and convert. Use when: (1) Trimming or cutting video segments, (2) Concatenating multiple clips, (3) Resizing video for social platforms, (4) Extracting or replacing audio, (5) Compressing video, (6) Converting video formats, (7) Getting video info.
video-understand
calesthio/openmontage
Understand video content locally using ffmpeg frame extraction and Whisper transcription. No API keys needed. Use when: (1) Understanding what a video contains, (2) Transcribing video audio locally, (3) Extracting key frames for visual analysis, (4) Getting video content without API keys.
svg-character-animation
calesthio/openmontage
Animate SVG character rigs with GSAP, CSS transforms, Remotion frame control, and HyperFrames-compatible browser previews.
ai-video-gen
calesthio/openmontage
Generate AI videos from text prompts using multiple provider gateways. Use when: (1) Generating videos from text descriptions, (2) Creating AI-generated video clips for content production, (3) Image-to-video generation with a reference image, (4) Choosing between video generation providers (VEO, Kling, Sora, Runway, Seedance, MiniMax, Gemini Omni). Supports gateways: HeyGen API, fal.ai API, Kling official direct API, and the Gemini API (Gemini Omni Flash).
video-download
calesthio/openmontage
Download video and audio from YouTube and 1000+ sites using yt-dlp. No API keys needed. Use when: (1) Downloading a video from YouTube or other sites, (2) Extracting audio from a video URL, (3) Downloading subtitles/captions from a video, (4) Getting video metadata without downloading.
remotion
calesthio/openmontage
Toolkit-specific Remotion patterns — custom transitions, shared components, and project conventions. For core Remotion framework knowledge (hooks, animations, rendering, etc.), see the remotion-official skill.
Popular frontend & design skills
setup-matt-pocock-skills
mattpocock/skills
Configure this repo for the engineering skills: set up its issue tracker, triage label vocabulary, and domain doc layout. Run once before first use of the other engineering skills.
frontend-design
anthropics/skills
Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one. Helps with aesthetic direction, typography, and making choices that don't read as templated defaults.
hyperframes-animation
heygen-com/hyperframes
All animation knowledge for HyperFrames — atomic motion rules, multi-phase scene blueprints, scene transitions, broader motion-design techniques, AND the seven runtime adapters (GSAP default, plus Lottie, Three.js, Anime.js, CSS keyframes, Web Animations API, TypeGPU). Use for any motion or animation task: pick 2-4 rules and compose, or load a blueprint, or look up runtime-specific API (e.g. GSAP eases / Lottie player / Three.js mixer). Also covers auditing an existing composition's choreography (animation map) and 24 named text-animation effects. HyperFrames-native: single paused timeline, seek-safe, deterministic.
prototype
mattpocock/skills
Build a throwaway prototype to answer a design question. Use when the user wants to sanity-check whether a state model or logic feels right, or explore what a UI should look like.
hyperframes-core
heygen-com/hyperframes
The HyperFrames composition contract — build one renderable project. Use for composition structure, the data- timing attributes, class="clip", tracks, sub-compositions, variables, framework-owned media playback, deterministic-render rules, and validation. Read before writing composition HTML.
vercel-react-best-practices
vercel-labs/agent-skills
React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.