Migrate from Stitches.js to Stitches RSC
Guide migration from the original @stitches/react or @stitches/core packages to @stitches-rsc/react or @stitches-rsc/core.
Migration Overview
Stitches RSC is a 1:1 API-compatible replacement. Most code works without changes. The key differences are:
- •Package names:
@stitches/react→@stitches-rsc/react - •Build plugin required: Add Next.js or Vite plugin for CSS extraction
- •No runtime CSS: CSS is extracted at build time, not generated at runtime
Migration Steps
Step 1: Analyze Current Usage
Search the codebase for Stitches imports and usage patterns:
# Find all Stitches imports grep -r "from '@stitches" --include="*.ts" --include="*.tsx" grep -r "from \"@stitches" --include="*.ts" --include="*.tsx" # Find stitches.config files find . -name "stitches.config.*" -type f
Step 2: Update Package Dependencies
Replace Stitches packages in package.json:
Before:
{
"dependencies": {
"@stitches/react": "^1.2.8"
}
}
After:
{
"dependencies": {
"@stitches-rsc/react": "^0.1.0"
}
}
For core-only usage:
{
"dependencies": {
"@stitches-rsc/core": "^0.1.0"
}
}
Step 3: Update Imports
Replace import paths throughout the codebase:
// Before
import { styled, css, globalCss, keyframes, createTheme } from '@stitches/react';
import { createStitches } from '@stitches/react';
// After
import { styled, css, globalCss, keyframes, createTheme } from '@stitches-rsc/react';
import { createStitches } from '@stitches-rsc/react';
Use sed for bulk replacement:
# macOS
find . -type f \( -name "*.ts" -o -name "*.tsx" \) -exec sed -i '' "s/@stitches\/react/@stitches-rsc\/react/g" {} +
find . -type f \( -name "*.ts" -o -name "*.tsx" \) -exec sed -i '' "s/@stitches\/core/@stitches-rsc\/core/g" {} +
# Linux
find . -type f \( -name "*.ts" -o -name "*.tsx" \) -exec sed -i "s/@stitches\/react/@stitches-rsc\/react/g" {} +
Step 4: Add Build Plugin
For Next.js - Install and configure:
pnpm add @stitches-rsc/next-plugin
Update next.config.js:
const withStitchesRSC = require('@stitches-rsc/next-plugin');
module.exports = withStitchesRSC({
useScope: true,
useLayers: true,
})({
// existing Next.js config
});
For Vite - Install and configure:
pnpm add @stitches-rsc/vite-plugin
Update vite.config.ts:
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import stitchesRSC from '@stitches-rsc/vite-plugin';
export default defineConfig({
plugins: [
react(),
stitchesRSC({
useScope: true,
useLayers: true,
}),
],
});
Step 5: Handle Breaking Patterns
getCssText() Usage
The getCssText() function still works but is primarily for SSR. With build plugins, CSS is extracted automatically.
Before (SSR hydration):
// _document.tsx
<style id="stitches" dangerouslySetInnerHTML={{ __html: getCssText() }} />
After: Remove this - the build plugin handles CSS injection.
Dynamic css prop with Non-Serializable Values
Functions in css prop won't work at build time:
// Won't work - function can't be extracted
<Box css={{ color: () => getColor() }} />
// Works - static value or variable
<Box css={{ color: dynamicColor }} />
The build plugin converts dynamic values to CSS variables automatically.
Step 6: Verify Migration
- •
Run the build to check for errors:
bashpnpm build
- •
Check generated CSS for proper layer structure:
bash# Look for @layer declarations in output grep -r "@layer stitches" dist/
- •
Test in browser - styles should apply without runtime JS
Common Migration Issues
Issue: Styles not applying
Cause: Build plugin not processing files Fix: Check include/exclude patterns in plugin config
Issue: TypeScript errors
Cause: Type definitions slightly different Fix: Update type imports if needed - most types are compatible
Issue: Theme tokens not resolving
Cause: Token syntax difference
Fix: Ensure $token syntax is used (same as original Stitches)
Additional Resources
See references/api-differences.md for detailed API comparison.
See examples/ for before/after migration examples.