An OpenCode skill for converting React components to Svelte 5 using modern runes syntax.
This skill provides comprehensive instructions for migrating React components to Svelte 5, covering:
- State Management:
useState→$state,useReducerpatterns - Derived Values:
useMemo→$derived,useCallbacksimplification - Side Effects:
useEffect→$effect,useLayoutEffect→$effect.pre - Props: Destructuring →
$props()with TypeScript support - Pure Components: Automatic purity in Svelte (no memo needed)
- Event Handling: React events → Svelte events
- Rendering: JSX → Svelte templates with
{#if}and{#each} - Context:
createContext/useContext→setContext/getContext - Refs:
useRef→bind:this - Forms: Two-way binding with
bind:value - Custom Hooks: Converting to Svelte 5 runes-based functions
- Accessibility: ARIA attributes, keyboard events, focus management, reduced motion
mkdir -p .opencode/skills/react-to-svelte
cp SKILL.md .opencode/skills/react-to-svelte/mkdir -p ~/.config/opencode/skills/react-to-svelte
cp SKILL.md ~/.config/opencode/skills/react-to-svelte/Once installed, OpenCode agents can load this skill automatically or you can invoke it:
/skill react-to-svelte
Then ask the agent to convert a React component:
Convert this React component to Svelte 5:
[paste your React code]
- All React hooks (useState, useEffect, useMemo, useCallback, useRef, useContext, useReducer)
- Pure components and optimization patterns
- Event handling and custom events
- Conditional and list rendering
- Context API migration
- Form handling with two-way binding
- Component composition (slots vs children)
- Custom hooks to Svelte 5 functions
- ARIA attribute preservation
- Keyboard event handling
- Focus management patterns
- Screen reader support
- Reduced motion preferences
- Svelte's built-in a11y warnings
- Step-by-step conversion checklist
- Common pitfalls and solutions
- Before/after code examples
- TypeScript integration
React:
function Counter({ initial = 0 }) {
const [count, setCount] = useState(initial);
return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}Svelte 5:
<script>
let { initial = 0 } = $props();
let count = $state(initial);
</script>
<button onclick={() => count++}>
{count}
</button>React:
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(`/api/users/${userId}`)
.then(r => r.json())
.then(data => {
setUser(data);
setLoading(false);
});
}, [userId]);
if (loading) return <div>Loading...</div>;
return <div>{user.name}</div>;
}Svelte 5:
<script>
let { userId } = $props();
let user = $state(null);
let loading = $state(true);
$effect(() => {
fetch(`/api/users/${userId}`)
.then(r => r.json())
.then(data => {
user = data;
loading = false;
});
});
</script>
{#if loading}
<div>Loading...</div>
{:else}
<div>{user.name}</div>
{/if}- Rename file from
.jsx/.tsxto.svelte - Remove React imports
- Convert function to Svelte structure
- Convert
useStateto$state - Convert
useEffectto$effect - Convert
useMemoto$derived - Convert props to
$props() - Convert event handlers
- Convert conditional rendering to
{#if}blocks - Convert
.map()to{#each}blocks - Convert
useContexttogetContext - Convert
useReftobind:this - Add scoped styles
- Review accessibility attributes
- Test component behavior
- OpenCode: Native support
- Svelte Version: 5.x (runes syntax)
- TypeScript: Full support with type examples
Feel free to open issues or PRs to improve this skill.
MIT