Official agent skill

Migrate Styled Components To Vanilla Extract

by sanity-io in sanity-io/sanity

Step-by-step procedure for migrating components in the Sanity monorepo off styled-components to vanilla-extract (zero-runtime CSS).

OfficialMITAuto-check passedFrontend & Design

Install Migrate Styled Components To Vanilla Extract

skills CLI
$ npx skills add sanity-io/sanity --skill migrate-styled-components-to-vanilla-extract -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install sanity-io/sanity migrate-styled-components-to-vanilla-extract --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/sanity-io/sanity.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/migrate-styled-components-to-vanilla-extract .claude/skills/migrate-styled-components-to-vanilla-extract && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
migrate-styled-components-to-vanilla-extract
GitHub stars
6.4k
Token cost
~5.8k tokens
SKILL.md length
1,785 words
Files
1
Skills in repo
34
Repo updated
First seen
Licence
MIT

At a glance

Step-by-step procedure for migrating components in the Sanity monorepo off styled-components to vanilla-extract (zero-runtime CSS).

  • Works in 3 steps: Inventory → Migrate the code → Verify
  • Converting styled() components to .css.ts files
  • SKILL.md covers Ground rules, Step 1: Inventory, Step 2: Migrate the code and Step 3: Verify, plus 2 more sections
  • Calls pnpm and rg

What it does

Migrate Styled Components To Vanilla Extract is an agent skill from sanity-io/sanity, published by the product's own GitHub organization. Step-by-step procedure for migrating components in the Sanity monorepo off styled-components to vanilla-extract (zero-runtime CSS). Use when converting styled() components to .css.ts files, creating .css.ts files, handling CSS specificity against @sanity/ui, styling child elements with vanilla-extract, or when asked to migrate styling to vanilla-extract.

Its SKILL.md is about 5.8k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Frontend & Design, covering CSS and styling and Monorepo tooling. The repository describes itself as: Sanity Studio – Rapidly configure content workspaces powered by structured content. The licence is MIT.

When your agent uses it

  • Converting styled() components to .css.ts files
  • Creating .css.ts files
  • Handling CSS specificity against @sanity/ui
  • Styling child elements with vanilla-extract

Example prompts

  • “/migrate-styled-components-to-vanilla-extract”

Workflow steps

3 steps, taken from the step headings in SKILL.md.

  1. Inventory
  2. Migrate the code
  3. Verify

What it can do on your machine

Read from SKILL.md and the folder at commit efa15fb. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • pnpm
    • rg

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Links to these hosts (documentation or services it may open):

    • vanilla-extract.style

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Migrate Styled Components To Vanilla Extract loads about 5.8k tokens when it runs. Until then it costs about 100 tokens; SKILL.md has 1,785 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~100
When it runs · the whole SKILL.md, loaded when a task matches
~5.8k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from sanity-io/sanity at commit efa15fb, republished under its MIT licence (© sanity-io). 1,785 words, ~5,755 tokens.

Download SKILL.mdSave it as .claude/skills/migrate-styled-components-to-vanilla-extract/SKILL.md (or your agent's skills folder).
name
migrate-styled-components-to-vanilla-extract
description
Step-by-step procedure for migrating components in the Sanity monorepo off styled-components to vanilla-extract (zero-runtime CSS). Use when converting styled() components to .css.ts files, creating .css.ts files, handling CSS specificity against @sanity/ui, styling child elements with vanilla-extract, or when asked to migrate styling to vanilla-extract.

Migrate styled-components to vanilla-extract

The repeatable procedure for converting this monorepo's styling from styled-components (the Studio's legacy styling library) to vanilla-extract. Adapted from the sanity-io/plugins skill of the same name for this repo's setup.

The infrastructure is already wired — never touch it during a component migration. packages/sanity and packages/@sanity/vision build .css.ts files into lib/bundle.css via vanillaExtract: true in their tsdown.config.ts, expose the ./bundle.css export, register vanillaExtractPlugin() in their vitest.config.mts, and the dev studios register it in sanity.cli.ts. A migration PR only converts component styles.

Ground rules

  • Identical visual output is the goal. This is a refactor, not a redesign — every rule and specificity outcome must be preserved. Copy CSS values verbatim; do not "improve" them.
  • Small PRs. Migrate one component (or one tightly-coupled cluster) per PR, conventional-commit titled, e.g. refactor(structure): migrate Scroller to vanilla-extract.
  • Reference implementations: packages/@sanity/vision, packages/sanity/src/core/changeIndicators/ElementWithChangeBar.*, packages/sanity/src/structure/panes/document/document-layout/DocumentLayout.*, and for the dynamic shapes packages/sanity/src/core/components/popoverDialog/PopoverContainer.* (responsive widths through per-breakpoint variables) and packages/sanity/src/core/form/inputs/PortableText/text/TextBlock.styles.* (per-level styleVariants, private custom properties, theme-driven colors).

Step 1: Inventory

Classify each usage before touching code:

bash
rg "from 'styled-components'" packages/sanity/src <target-dir>
UsageMigration target
Static styled.div / styled(Primitive)style() in a colocated .css.ts + thin wrapper component (or plain className)
Overrides of @sanity/ui primitives' own stylesstyle() with the && specificity trick (see below)
Theme reads (({theme}) => ..., getTheme_v2)--card-* CSS custom properties if one exists, else createVar() + assignInlineVars() + useTheme_v2()
Prop-driven variants ($isInvalid, css branches)one style() per state + conditional clsx() composition (or styleVariants())
keyframes animationsvanilla-extract keyframes()
Descendant selectors (& img, third-party classes)class on the child directly, ${parent} &, or scoped globalStyle()
createGlobalStyleglobalStyle() (scope it — never leak outside the component)
*.styled.tsx modules.css.ts + thin wrappers; keep the .styled.tsx file when call sites need it
Computed inline style={{}} objectsstatic parts into style(), changing values via createVar() (Shape C below)

Step 2: Migrate the code

Create a ComponentName.css.ts next to the component. Files calling vanilla-extract APIs (style, styleVariants, createVar, globalStyle, keyframes) must use the .css.ts extension — a plain .ts file throws "Styles were unable to be assigned to a file" at runtime.

Shape A — keep the component layer. When the styled element is used like a component, replace it with a style() rule plus a thin wrapper keeping the same name and API, so call sites don't change. Type with ComponentProps<typeof Primitive> (or ComponentProps<'div'>) — never forwardRef; ref is a regular prop on React 19 and flows through the spread. Merge, don't clobber: a fixed className={...} after {...props} silently drops a caller's className — merge with clsx (already a dependency):

tsx
import {Card} from '@sanity/ui'
import {clsx} from 'clsx'
import {type ComponentProps} from 'react'

import {floatingCard} from './FloatingCard.css'

export function FloatingCard(props: ComponentProps<typeof Card>) {
  const {className, ...rest} = props
  return <Card {...rest} className={clsx(floatingCard, className)} />
}

Renaming a Component.styled.ts to .tsx (or .ts → .tsx) keeps extension-less import paths at call sites unchanged.

Shape B — flatten single-use wrappers. When the styled element was an internal, single-use styled.div with no meaningful API, delete it and put the class directly on the element: <div className={paragraph}>{children}</div>.

Shape C — dynamic values through CSS variables. First check whether @sanity/ui already exposes the value as a CSS custom property — prefer e.g. var(--card-bg-color) over JS theme reads (see ElementWithChangeBar.css.ts). Otherwise keep static parts in style() and bridge only changing values with createVar() + assignInlineVars() (from @vanilla-extract/dynamic, not @vanilla-extract/css), reading the theme with useTheme_v2() (alias it useTheme_v2 as useThemeV2 to satisfy the camelCase lint):

ts
// Wrapper.css.ts
import {createVar, style} from '@vanilla-extract/css'

export const paddingVar = createVar()
export const wrapper = style({paddingBottom: paddingVar})
tsx
<div className={wrapper} style={assignInlineVars({[paddingVar]: `${space[4]}px`})} />

assignInlineVars omits undefined values, so one class serves every instance.

Specificity against @sanity/ui: the && trick

@sanity/ui still uses styled-components, which injects its styles at runtime — usually after the extracted vanilla-extract stylesheet, so an equal-specificity class loses. When overriding a primitive's own styles (e.g. styled(Card) overriding Card's background), double the class:

ts
export const transparentCard = style({
  selectors: {
    '&&': {background: 'none'},
  },
})

Where styled-components silently won specificity battles via CSSOM insertion order, reach for && rather than !important. Plain-element styles (styled.div) need no trick.

The cascade model (why order is not yours to rely on)

Three stylesheets meet on a migrated element, and their order differs between sanity dev and sanity build:

Sheetsanity buildsanity dev
vanilla-extract (bundle.css)one static file, loaded firstone <style> per .css.ts module, injected when the module evaluates — lazy chunks land after styled-components' tag
@sanity/ui (styled-components, runtime)<style data-styled> appended on first rendersame
ui5 (styles.css)static filestatic file

Consequences:

  • Never rely on order against @sanity/ui. On an equal-specificity tie the winner flips between dev and prod. Beat the primitive's own rule by specificity: && (0,2,0) beats a plain component class (0,1,0). If the primitive rule you override already has two classes or a pseudo-class chain (e.g. Card's &[data-as='button']:not(:disabled)[data-selected]), count its specificity and exceed it — &&&, or &&[data-as='button']. Read the rule in node_modules/@sanity/ui/dist/*.js when unsure. !important stays banned.
  • styled-components gave you order for free; vanilla-extract does not. A styled(X) wrapper was always injected after X, so its equal-specificity declarations won. After migration, both classes live in bundle.css in module evaluation order: within one .css.ts file, definition order; across files, the importing file comes after the imported one. So for a styled(LocalStyledThing) chain, define the override below the base in the same .css.ts (or compose it with style([base, {...}])). For an override whose base lives in another .css.ts, import that class into the overriding file — the import is what guarantees the ordering — or use &&.
  • Two classes on one element from unrelated files (e.g. a styled.div root class plus a parent-state selector ${parent}:hover & defined elsewhere) are ordered by the same rule. When a declaration must win regardless of file order, raise its specificity rather than betting on order.
  • @media blocks are hoisted. vanilla-extract emits a file's media queries after that file's base rules, which is what styled-components effectively did too. Media conditions cannot read custom properties, so theme breakpoints are written as literals from the default theme (table below) with a comment naming the theme key they mirror.
What each @sanity/ui primitive sets on itself

Use && when the migrated rule overrides one of these; plain style() otherwise.

PrimitiveOwn declarations (via its props or defaults)
Boxdisplay (block, or the display prop), box-sizing, flex/flex-shrink/flex-grow props, margin*, padding*, height, overflow, column/row grid props, list-style: none for as="ul"/"ol"
FlexBox + display: flex, flex-direction, flex-wrap, align-items, justify-content, gap
StackBox + display: grid, grid-template-columns, grid-auto-rows, gap
Grid, InlineBox + display, gap, grid-*, align-items
CardBox + background-color, color, color-scheme, every --card-* variable, border/border-color (border prop), border-radius (radius), box-shadow (shadow, focus ring), button/link hover/pressed/selected/disabled variants, outline, font, text-align, appearance, width (button)
ContainerBox + max-width, margin: 0 auto
Text, Label, Heading, Codefont-family, font-size, font-weight, line-height, letter-spacing, color (--card-fg-color / muted / accent), text-align; descendant rules for & code, & a (color --card-link-color, focus ring), & strong, & svg; the inner span handles text-overflow
ButtonCard-like colors per mode/tone, padding, border-radius, font, box-shadow, cursor, &:disabled, &:not(:disabled):hover, & [data-ui='Text']
TextInput, TextArea, Selectwrapper position: relative; the inner input/textarea/select gets font, color, padding, border via presentation span; --input-* variables
Skeleton, TextSkeleton, LabelSkeletonbackground-color, border-radius, animation, width, height
Popover, Tooltip, Layer, Dialogposition, z-index, pointer-events, max-width; Popover/Tooltip content Card colors
Badge, KBD, Spinner, Switch, Checkbox, Radio, Avatar, Tab, TreeItem, MenuItemfully self-styled — treat every declaration as an override (&&)
Show full SKILL.md (676 more words)Show less
Theme reads → CSS variables

getTheme_v2(theme) inside a styled template and useTheme_v2() inside the wrapper read the same context, including the nearest Card's tone and scheme. Prefer a variable @sanity/ui already publishes on the nearest Card (they follow tone and scheme for free):

Theme readCSS variable
color.bg, color.fg, color.border, color.icon--card-bg-color, --card-fg-color, --card-border-color, --card-icon-color
color.muted.bg, color.muted.fg, color.accent.fg--card-muted-bg-color, --card-muted-fg-color, --card-accent-fg-color
color.focusRing, color.backdrop--card-focus-ring-color, --card-backdrop-color
color.badge.<tone>.{bg,fg,dot,icon}--card-badge-<tone>-{bg,fg,dot,icon}-color
color.avatar.<hue>.{bg,fg}--card-avatar-<hue>-{bg,fg}-color
color.link.fg, color.code.{bg,fg}, color.kbd.{bg,fg,border}--card-link-fg-color, --card-code-{bg,fg}-color, --card-kbd-{bg,fg,border}-color
color.shadow.{outline,umbra,penumbra,ambient}--card-shadow-{outline,umbra,penumbra,ambient}-color
color.skeleton.{from,to}--card-skeleton-color-{from,to}
color.hairline.{soft,hard}--card-hairline-{soft,hard}-color
card focus ring box-shadow (focusRingStyle(...))--card-focus-ring-box-shadow (set by Card/Button on :focus-visible)

Everything else — color.selectable.*, color.solid.*, color.input.*, color.button.*, color.syntax.*, color._dark, space[n], radius[n], font.*, container[n], avatar.sizes[n], input.*, shadow[n] — goes through Shape C: createVar() in the .css.ts, useTheme_v2() + assignInlineVars() in the wrapper. Keep the same theme key names in the var names (space3Var, radius2Var) so the intent survives. Do not hardcode scale values: a studio may build its own theme with different space, radius, or font scales.

Only @media conditions get literals, mirrored from the default theme:

KeyDefault values
media[360, 600, 900, 1200, 1800, 2400] px
container[320, 640, 960, 1280, 1600, 1920] px

Write them as '@media': {'screen and (min-width: 600px)': {...}} with a comment such as // media[1].

Wrapper contract

A wrapper that replaces an exported styled component must keep call sites working without edits:

  • Same export name, same prop names — including transient $props, which become regular props the wrapper consumes (do not rename them; callers in other directories still pass them).
  • className and style merge (clsx, spread) — never clobber.
  • ref flows through props (React 19). No forwardRef, no displayName.
  • .attrs({...}) values become JSX props on the primitive inside the wrapper; forwardedAs becomes as.
  • A prop-driven css branch becomes one style() per branch plus clsx(cond && cls); a prop-driven value becomes a createVar() set with assignInlineVars. Prefer styleVariants() for a closed set of values.
  • Shared css mixins (an export const focusRingStyles = css tagged template) become an exported StyleRule object or style() class in a .css.ts; importers compose it with style([mixin, {...}]).
  • A test that asserted a computed style of a migrated component (toHaveStyle) cannot pass in jsdom anymore (runtime styles are disabled). Assert the state through a data-* attribute the wrapper sets instead; add the attribute if none exists.
Child and descendant selectors

style() selectors must target the current element: & must be the subject. '& img' or `& ${child}` are invalid (vanilla-extract throws at build time), but `${parent} &` is valid (self, scoped under parent — define parent first). In order of preference:

  1. Put a class directly on the child if you render it yourself.
  2. selectors: {[`${parent}:hover &`]: {...}} on the child style for parent-state-dependent rules.
  3. globalStyle(${root} img, {...}) when you don't control the child (library-rendered DOM) — always scoped under a local class.

Step 3: Verify

bash
pnpm lint:fix                                  # oxfmt + oxlint (includes type checking)
pnpm build && pnpm vitest run --project=sanity <affected test paths>

Check packages/sanity/lib/bundle.css after the build: every migrated rule must appear there.

Verify visual fidelity in the dev studio (pnpm dev, see AGENTS.md for cloud-agent auth): exercise the migrated component and compare against the pre-migration rendering — theme tones, spacing, hover/focus states, stacking. Jsdom tests must not assert on vanilla-extract class names or computed styles (runtime styles are disabled there — see AGENTS.md); assert on data-testid. For high-traffic components, add a Chromatic story per the sanity-visual-regression skill so the migration is sentinel-protected.

End state

The monorepo's own code no longer imports styled-components; eslint/no-restricted-imports in .oxlintrc.json bans the module everywhere (the global rule and every override that repeats it). The dependency itself stays declared because @sanity/ui@4 requires it as a peer and still injects its own styles at runtime — which is exactly why the cascade rules above still matter for every new .css.ts. Use this skill for new components and for plugin or example code that still carries styled-components.

Checklist

  • styled-components import removed from the migrated component; emptied .styled.tsx modules deleted
  • .css.ts colocated; CSS values copied verbatim; component layer preserved where call sites need it; className merged, not clobbered
  • && used where the original relied on styled-components injection order to beat @sanity/ui
  • No build config, package.json, or exports changes (infra is already wired)
  • pnpm lint:fix, pnpm build, and affected tests pass; rules present in lib/bundle.css
  • Visual fidelity verified against the pre-migration rendering

© sanity-io, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .agents/skills/migrate-styled-components-to-vanilla-extract of sanity-io/sanity.

Open the folder on GitHubat commit efa15fb

Compare with similar skills

Migrate Styled Components To Vanilla Extract next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Migrate Styled Components To Vanilla Extract compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Migrate Styled Components To Vanilla Extract this skillsanity-io/sanity6.4k—~5.8kAutomated safety check: PassMIT
Vuetify Skilldlogue/vite-vuetify-ts-starter1811 repos~1.9kAutomated safety check: PassMIT
Port Upstreamgjtorikian/tailwind_merge148—~1.9kAutomated safety check: PassMIT
Oxlint Tailwindcsssergioazoc/oxlint-tailwindcss101—~1.9kAutomated safety check: PassMIT
Manage Componentstelerik/kendo-themes158—~2.3kAutomated safety check: PassNone
Update Web Assetsgarfiec/Librechat-Mobile111—~1.8kAutomated safety check: NotesMIT

Similar skills

  • Vuetify Skilld

    logue/vite-vuetify-ts-starter

    Vue Material Component Framework. An agent skill from logue/vite-vuetify-ts-starter.

    181 GitHub starsUsed in 1 repo~1.9k tokens
    Frontend & DesignAuto-check passed
  • Port Upstream

    gjtorikian/tailwind_merge

    Check GitHub notifications for upstream dcastil/tailwind-merge pull requests and port merged ones into this Ruby gem (branch, translated code, tests, commit, PR).

    148 GitHub stars~1.9k tokensUpdated 28 days ago
    Frontend & DesignAuto-check passed
  • Oxlint Tailwindcss

    sergioazoc/oxlint-tailwindcss

    Set up oxlint-tailwindcss — Tailwind CSS v4 lint rules for oxlint — in a project, and act on its diagnostics.

    101 GitHub stars~1.9k tokensUpdated yesterday
    Frontend & DesignAuto-check passed
  • Manage Components

    telerik/kendo-themes

    Create or update a Kendo UI component across kendo-themes packages.

    158 GitHub stars~2.3k tokensUpdated yesterday
    Frontend & DesignAuto-check passed
  • Update Web Assets

    garfiec/Librechat-Mobile

    Update the third-party JavaScript vendored into the app for the artifact, diagram, and math WebViews (KaTeX, mermaid, marked, highlight.js, Tailwind, Babel, React).

    111 GitHub stars~1.8k tokensUpdated yesterday
    Frontend & DesignAuto-check: notes
  • Frontend Code Review

    ProgrammerAnthony/Expert-Coding-Harness

    A skill your agent uses when 用户需要审查前端代码(React/Vue/Next.js/TypeScript/Tailwind等)、检查代码质量、性能问题、可维护性、安全漏洞、最佳实践落地时。触发场景:前端代码评审、前端代码优化、React/Vue代码检查、TypeScript代码审查、前端性能优化、前端安全审计、前端代码规范检查。

    235 GitHub stars~614 tokensUpdated 5 mo ago
    Frontend & DesignAuto-check passed

More from sanity-io/sanity

All 34 skills in this repo
  • Playwright CLI

    sanity-io/sanity

    Official

    Automates browser interactions for web testing, form filling, screenshots, and data extraction.

    6.4k GitHub starsUsed in 18 repos~1.9k tokens
    Auto-check passed
  • Find Skills

    sanity-io/sanity

    Official

    Helps users discover and install agent skills when they ask questions like "how do I do X", "find a skill for X", "is there a skill that can...", or express interest in extending capabilities.

    6.4k GitHub starsUsed in 67 repos~1.2k tokens
    Auto-check passed
  • Official

    React and Next.js performance optimization guidelines from Vercel Engineering.

    6.4k GitHub starsUsed in 129 repos~1.6k tokens
    Auto-check passed
  • Before And After

    sanity-io/sanity

    Official

    Add existing screenshots or screen recordings to a GitHub pull request as a before/after or preview block.

    6.4k GitHub starsUsed in 1 repo~2.1k tokens
    Auto-check passed
  • React Devtools

    sanity-io/sanity

    Official

    React DevTools CLI for AI agents. An agent skill from sanity-io/sanity.

    6.4k GitHub starsUsed in 3 repos~2.1k tokens
    Auto-check passed
  • TDD

    sanity-io/sanity

    Official

    Test-driven development with red-green-refactor loop. An agent skill from sanity-io/sanity.

    6.4k GitHub starsUsed in 20 repos~1k tokens
    Auto-check passed

Questions about Migrate Styled Components To Vanilla Extract

What does Migrate Styled Components To Vanilla Extract do?

Step-by-step procedure for migrating components in the Sanity monorepo off styled-components to vanilla-extract (zero-runtime CSS). Migrate Styled Components To Vanilla Extract is an agent skill from sanity-io/sanity, published by the product's own GitHub organization. Step-by-step procedure for migrating components in the Sanity monorepo off styled-components to vanilla-extract (zero-runtime CSS).

When should I use Migrate Styled Components To Vanilla Extract?

Migrate Styled Components To Vanilla Extract fits situations like: converting styled() components to .css.ts files; creating .css.ts files; handling CSS specificity against @sanity/ui; styling child elements with vanilla-extract.

How do I install Migrate Styled Components To Vanilla Extract in Claude Code?

Run `npx skills add sanity-io/sanity --skill migrate-styled-components-to-vanilla-extract -a claude-code`. Or copy the skill folder (.agents/skills/migrate-styled-components-to-vanilla-extract in sanity-io/sanity) into .claude/skills/migrate-styled-components-to-vanilla-extract in your project. Claude Code loads it when a task matches its description.

How do I install Migrate Styled Components To Vanilla Extract in Codex?

Run `npx skills add sanity-io/sanity --skill migrate-styled-components-to-vanilla-extract -a codex`. Or copy the skill folder (.agents/skills/migrate-styled-components-to-vanilla-extract in sanity-io/sanity) into .agents/skills/migrate-styled-components-to-vanilla-extract in your project. Codex loads it when a task matches its description.

Can I use Migrate Styled Components To Vanilla Extract in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add sanity-io/sanity --skill migrate-styled-components-to-vanilla-extract -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/migrate-styled-components-to-vanilla-extract, .gemini/skills/migrate-styled-components-to-vanilla-extract, .github/skills/migrate-styled-components-to-vanilla-extract and .opencode/skills/migrate-styled-components-to-vanilla-extract in your project.

What does Migrate Styled Components To Vanilla Extract need to run?

Going by SKILL.md and its folder, Migrate Styled Components To Vanilla Extract needs the command-line tools its instructions call (pnpm and rg).

Does Migrate Styled Components To Vanilla Extract access the network?

SKILL.md names 1 domain. As links in the text: vanilla-extract.style. This is read from the text; nothing was executed.

Is Migrate Styled Components To Vanilla Extract safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Migrate Styled Components To Vanilla Extract use?

Migrate Styled Components To Vanilla Extract is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Migrate Styled Components To Vanilla Extract use?

About 5.8k tokens (SKILL.md is roughly 23k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Migrate Styled Components To Vanilla Extract?

Skills that share tags, products or a category with Migrate Styled Components To Vanilla Extract: Vuetify Skilld (logue/vite-vuetify-ts-starter, 181 stars), Port Upstream (gjtorikian/tailwind_merge, 148 stars), Oxlint Tailwindcss (sergioazoc/oxlint-tailwindcss, 101 stars) and Manage Components (telerik/kendo-themes, 158 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Migrate Styled Components To Vanilla Extract?

sanity-io (a GitHub organization, an official publisher) maintains it in sanity-io/sanity, which has 6,352 GitHub stars. The repository holds 34 skills in this directory. The repository was last updated on October 9, 2026.

Source: sanity-io/sanity on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.