Vuetify Skilld
logue/vite-vuetify-ts-starter
Vue Material Component Framework. An agent skill from logue/vite-vuetify-ts-starter.
Step-by-step procedure for migrating components in the Sanity monorepo off styled-components to vanilla-extract (zero-runtime CSS).
$ npx skills add sanity-io/sanity --skill migrate-styled-components-to-vanilla-extract -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install sanity-io/sanity migrate-styled-components-to-vanilla-extract --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ 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-srcUse ~/.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/
Install the "migrate-styled-components-to-vanilla-extract" agent skill from https://github.com/sanity-io/sanity/tree/main/.agents/skills/migrate-styled-components-to-vanilla-extract into .claude/skills/migrate-styled-components-to-vanilla-extract/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "migrate-styled-components-to-vanilla-extract", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/sanity-io/sanity/tree/main/.agents/skills/migrate-styled-components-to-vanilla-extractType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add sanity-io/sanity --skill migrate-styled-components-to-vanilla-extract -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install sanity-io/sanity migrate-styled-components-to-vanilla-extract --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/sanity-io/sanity.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.agents/skills/migrate-styled-components-to-vanilla-extract .agents/skills/migrate-styled-components-to-vanilla-extract && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "migrate-styled-components-to-vanilla-extract" agent skill from https://github.com/sanity-io/sanity/tree/main/.agents/skills/migrate-styled-components-to-vanilla-extract into .agents/skills/migrate-styled-components-to-vanilla-extract/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "migrate-styled-components-to-vanilla-extract", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add sanity-io/sanity --skill migrate-styled-components-to-vanilla-extract -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install sanity-io/sanity migrate-styled-components-to-vanilla-extract --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/sanity-io/sanity.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.agents/skills/migrate-styled-components-to-vanilla-extract .cursor/skills/migrate-styled-components-to-vanilla-extract && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "migrate-styled-components-to-vanilla-extract" agent skill from https://github.com/sanity-io/sanity/tree/main/.agents/skills/migrate-styled-components-to-vanilla-extract into .cursor/skills/migrate-styled-components-to-vanilla-extract/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "migrate-styled-components-to-vanilla-extract", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/sanity-io/sanity.git --path .agents/skills/migrate-styled-components-to-vanilla-extract--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add sanity-io/sanity --skill migrate-styled-components-to-vanilla-extract -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install sanity-io/sanity migrate-styled-components-to-vanilla-extract --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/sanity-io/sanity.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.agents/skills/migrate-styled-components-to-vanilla-extract .gemini/skills/migrate-styled-components-to-vanilla-extract && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "migrate-styled-components-to-vanilla-extract" agent skill from https://github.com/sanity-io/sanity/tree/main/.agents/skills/migrate-styled-components-to-vanilla-extract into .gemini/skills/migrate-styled-components-to-vanilla-extract/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "migrate-styled-components-to-vanilla-extract", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install sanity-io/sanity migrate-styled-components-to-vanilla-extractInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add sanity-io/sanity --skill migrate-styled-components-to-vanilla-extract -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/sanity-io/sanity.git skills-src && mkdir -p .github/skills && cp -r skills-src/.agents/skills/migrate-styled-components-to-vanilla-extract .github/skills/migrate-styled-components-to-vanilla-extract && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "migrate-styled-components-to-vanilla-extract" agent skill from https://github.com/sanity-io/sanity/tree/main/.agents/skills/migrate-styled-components-to-vanilla-extract into .github/skills/migrate-styled-components-to-vanilla-extract/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "migrate-styled-components-to-vanilla-extract", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add sanity-io/sanity --skill migrate-styled-components-to-vanilla-extract -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install sanity-io/sanity migrate-styled-components-to-vanilla-extract --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/sanity-io/sanity.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.agents/skills/migrate-styled-components-to-vanilla-extract .opencode/skills/migrate-styled-components-to-vanilla-extract && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "migrate-styled-components-to-vanilla-extract" agent skill from https://github.com/sanity-io/sanity/tree/main/.agents/skills/migrate-styled-components-to-vanilla-extract into .opencode/skills/migrate-styled-components-to-vanilla-extract/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "migrate-styled-components-to-vanilla-extract", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
migrate-styled-components-to-vanilla-extractStep-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). 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.
3 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit efa15fb. It shows what the files ask for, not the result of running them.
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.
Shell commands in SKILL.md call:
pnpmrgFrom the folder's file list and the shell code blocks in SKILL.md.
Links to these hosts (documentation or services it may open):
vanilla-extract.styleFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
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.
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.
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.
The full file from sanity-io/sanity at commit efa15fb, republished under its MIT licence (© sanity-io). 1,785 words, ~5,755 tokens.
.claude/skills/migrate-styled-components-to-vanilla-extract/SKILL.md (or your agent's skills folder).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.
refactor(structure): migrate Scroller to vanilla-extract.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).Classify each usage before touching code:
rg "from 'styled-components'" packages/sanity/src <target-dir>| Usage | Migration target |
|---|---|
Static styled.div / styled(Primitive) | style() in a colocated .css.ts + thin wrapper component (or plain className) |
Overrides of @sanity/ui primitives' own styles | style() 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 animations | vanilla-extract keyframes() |
Descendant selectors (& img, third-party classes) | class on the child directly, ${parent} &, or scoped globalStyle() |
createGlobalStyle | globalStyle() (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={{}} objects | static parts into style(), changing values via createVar() (Shape C below) |
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):
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):
// Wrapper.css.ts
import {createVar, style} from '@vanilla-extract/css'
export const paddingVar = createVar()
export const wrapper = style({paddingBottom: paddingVar})<div className={wrapper} style={assignInlineVars({[paddingVar]: `${space[4]}px`})} />assignInlineVars omits undefined values, so one class serves every instance.
&& 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:
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.
Three stylesheets meet on a migrated element, and their order differs between sanity dev and
sanity build:
| Sheet | sanity build | sanity dev |
|---|---|---|
vanilla-extract (bundle.css) | one static file, loaded first | one <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 render | same |
ui5 (styles.css) | static file | static file |
Consequences:
@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(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 &&.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.@sanity/ui primitive sets on itselfUse && when the migrated rule overrides one of these; plain style() otherwise.
| Primitive | Own declarations (via its props or defaults) |
|---|---|
Box | display (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" |
Flex | Box + display: flex, flex-direction, flex-wrap, align-items, justify-content, gap |
Stack | Box + display: grid, grid-template-columns, grid-auto-rows, gap |
Grid, Inline | Box + display, gap, grid-*, align-items |
Card | Box + 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) |
Container | Box + max-width, margin: 0 auto |
Text, Label, Heading, Code | font-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 |
Button | Card-like colors per mode/tone, padding, border-radius, font, box-shadow, cursor, &:disabled, &:not(:disabled):hover, & [data-ui='Text'] |
TextInput, TextArea, Select | wrapper position: relative; the inner input/textarea/select gets font, color, padding, border via presentation span; --input-* variables |
Skeleton, TextSkeleton, LabelSkeleton | background-color, border-radius, animation, width, height |
Popover, Tooltip, Layer, Dialog | position, z-index, pointer-events, max-width; Popover/Tooltip content Card colors |
Badge, KBD, Spinner, Switch, Checkbox, Radio, Avatar, Tab, TreeItem, MenuItem | fully self-styled — treat every declaration as an override (&&) |
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 read | CSS 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:
| Key | Default 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].
A wrapper that replaces an exported styled component must keep call sites working without edits:
$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.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.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, {...}]).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.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:
selectors: {[`${parent}:hover &`]: {...}} on the child style for parent-state-dependent rules.globalStyle(${root} img, {...}) when you don't control the child (library-rendered DOM) —
always scoped under a local class.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.
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.
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/uipackage.json, or exports changes (infra is already wired)pnpm lint:fix, pnpm build, and affected tests pass; rules present in lib/bundle.css© 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
Just SKILL.md in .agents/skills/migrate-styled-components-to-vanilla-extract of sanity-io/sanity.
Open the folder on GitHubat commit efa15fb
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.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Migrate Styled Components To Vanilla Extract this skillsanity-io/sanity | 6.4k | — | ~5.8k | Automated safety check: Pass | MIT | |
| Vuetify Skilldlogue/vite-vuetify-ts-starter | 181 | 1 repos | ~1.9k | Automated safety check: Pass | MIT | |
| Port Upstreamgjtorikian/tailwind_merge | 148 | — | ~1.9k | Automated safety check: Pass | MIT | |
| Oxlint Tailwindcsssergioazoc/oxlint-tailwindcss | 101 | — | ~1.9k | Automated safety check: Pass | MIT | |
| Manage Componentstelerik/kendo-themes | 158 | — | ~2.3k | Automated safety check: Pass | None | |
| Update Web Assetsgarfiec/Librechat-Mobile | 111 | — | ~1.8k | Automated safety check: Notes | MIT |
logue/vite-vuetify-ts-starter
Vue Material Component Framework. An agent skill from logue/vite-vuetify-ts-starter.
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).
sergioazoc/oxlint-tailwindcss
Set up oxlint-tailwindcss — Tailwind CSS v4 lint rules for oxlint — in a project, and act on its diagnostics.
telerik/kendo-themes
Create or update a Kendo UI component across kendo-themes packages.
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).
ProgrammerAnthony/Expert-Coding-Harness
A skill your agent uses when 用户需要审查前端代码(React/Vue/Next.js/TypeScript/Tailwind等)、检查代码质量、性能问题、可维护性、安全漏洞、最佳实践落地时。触发场景:前端代码评审、前端代码优化、React/Vue代码检查、TypeScript代码审查、前端性能优化、前端安全审计、前端代码规范检查。
sanity-io/sanity
Automates browser interactions for web testing, form filling, screenshots, and data extraction.
sanity-io/sanity
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.
sanity-io/sanity
React and Next.js performance optimization guidelines from Vercel Engineering.
sanity-io/sanity
Add existing screenshots or screen recordings to a GitHub pull request as a before/after or preview block.
sanity-io/sanity
React DevTools CLI for AI agents. An agent skill from sanity-io/sanity.
sanity-io/sanity
Test-driven development with red-green-refactor loop. An agent skill from sanity-io/sanity.
Categories
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).
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.
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.
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.
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.
Going by SKILL.md and its folder, Migrate Styled Components To Vanilla Extract needs the command-line tools its instructions call (pnpm and rg).
SKILL.md names 1 domain. As links in the text: vanilla-extract.style. This is read from the text; nothing was executed.
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.
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.
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.
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.
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.