
Docs Sandpack
- 71 installs
- 11.8k repo stars
- Updated July 31, 2026
- reactjs/react.dev
Helps with ai & agent building tasks.
About
docs-sandpack is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- docs-sandpack
- AI & Agent Building
- AI-coding skill
Docs Sandpack by the numbers
- 71 all-time installs (skills.sh)
- +3 installs in the week ending Aug 4, 2026 (Skillselion tracking)
- Ranked #5,673 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/reactjs/react.dev --skill docs-sandpackAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 71 |
|---|---|
| repo stars | ★ 11.8k |
| Last updated | July 31, 2026 |
| Repository | reactjs/react.dev ↗ |
What it does
Helps with ai & agent building tasks.
Files
Sandpack Patterns
Quick Start Template
Most examples are single-file. Copy this and modify:
<Sandpack>
` ` `js
import { useState } from 'react';
export default function Example() {
const [value, setValue] = useState(0);
return (
<button onClick={() => setValue(value + 1)}>
Clicked {value} times
</button>
);
}
` ` `
</Sandpack>---
File Naming
| Pattern | Usage |
|---|---|
`js | Main file (no prefix) |
`js src/FileName.js | Supporting files |
`js src/File.js active | Active file (reference pages) |
`js src/data.js hidden | Hidden files |
`css | CSS styles |
`json package.json | External dependencies |
Critical: Main file must have export default.
Line Highlighting
function Example() { // Lines 2-4 // will be // highlighted return null; }
## Code References (numbered callouts)
```js [[1, 4, "age"], [2, 4, "setAge"]] // Creates numbered markers pointing to "age" and "setAge" on line 4
## Expected Errors (intentionally broken examples)
```js {expectedErrors: {'react-compiler': [7]}} // Line 7 shows as expected error
## Multi-File Example
<Sandpack>
```js src/App.js import Gallery from './Gallery.js';
export default function App() { return <Gallery />; }
export default function Gallery() { return <h1>Gallery</h1>; }
h1 { color: purple; }
</Sandpack>External Dependencies
<Sandpack>
import { useImmer } from 'use-immer'; // ...
{ "dependencies": { "immer": "1.7.3", "use-immer": "0.5.1", "react": "latest", "react-dom": "latest", "react-scripts": "latest" } }
</Sandpack>Code Style in Sandpack (Required)
Sandpack examples are held to strict code style standards:
1. Function declarations for components (not arrows) 2. `e` for event parameters 3. Single quotes in JSX 4. `const` unless reassignment needed 5. Spaces in destructuring: ({ props }) not ({props}) 6. Two-line createRoot: separate declaration and render call 7. Multiline if statements: always use braces
Don't Create Hydration Mismatches
Sandpack examples must produce the same output on server and client:
// 🚫 This will cause hydration warnings
export default function App() {
const isClient = typeof window !== 'undefined';
return <div>{isClient ? 'Client' : 'Server'}</div>;
}Use Ref for Non-Rendered State
// 🚫 Don't trigger re-renders for non-visual state
const [mounted, setMounted] = useState(false);
useEffect(() => { setMounted(true); }, []);
// ✅ Use ref instead
const mounted = useRef(false);
useEffect(() => { mounted.current = true; }, []);forwardRef and memo Patterns
forwardRef - Use Named Function
// ✅ Named function for DevTools display name
const MyInput = forwardRef(function MyInput(props, ref) {
return <input {...props} ref={ref} />;
});
// 🚫 Anonymous loses name
const MyInput = forwardRef((props, ref) => { ... });memo - Use Named Function
// ✅ Preserves component name
const Greeting = memo(function Greeting({ name }) {
return <h1>Hello, {name}</h1>;
});Line Length
- Prose: ~80 characters
- Code: ~60-70 characters
- Break long lines to avoid horizontal scrolling
Anti-Patterns
| Pattern | Problem | Fix |
|---|---|---|
const Comp = () => {} | Not standard | function Comp() {} |
onClick={(event) => ...} | Conflicts with global | onClick={(e) => ...} |
useState for non-rendered values | Re-renders | Use useRef |
Reading window during render | Hydration mismatch | Check in useEffect |
| Single-line if without braces | Harder to debug | Use multiline with braces |
Chained createRoot().render() | Less clear | Two statements |
//... without space | Inconsistent | // ... with space |
| Tabs | Inconsistent | 2 spaces |
ReactDOM.render | Deprecated | Use createRoot |
| Fake package names | Confusing | Use './your-storage-layer' |
PropsWithChildren | Outdated | children?: ReactNode |
Missing key in lists | Warnings | Always include key |
Additional Code Quality Rules
Always Include Keys in Lists
// ✅ Correct
{items.map(item => <li key={item.id}>{item.name}</li>)}
// 🚫 Wrong - missing key
{items.map(item => <li>{item.name}</li>)}Use Realistic Import Paths
// ✅ Correct - descriptive path
import { fetchData } from './your-data-layer';
// 🚫 Wrong - looks like a real npm package
import { fetchData } from 'cool-data-lib';Console.log Labels
// ✅ Correct - labeled for clarity
console.log('User:', user);
console.log('Component Stack:', errorInfo.componentStack);
// 🚫 Wrong - unlabeled
console.log(user);Keep Delays Reasonable
// ✅ Correct - 1-1.5 seconds
setTimeout(() => setLoading(false), 1000);
// 🚫 Wrong - too long, feels sluggish
setTimeout(() => setLoading(false), 3000);Updating Line Highlights
When modifying code in examples with line highlights ({2-4}), always update the highlight line numbers to match the new code. Incorrect line numbers cause rendering crashes.
File Name Conventions
- Capitalize file names for component files:
Gallery.jsnotgallery.js - After initially explaining files are in
src/, refer to files by name only:Gallery.jsnotsrc/Gallery.js
Naming Conventions in Code
Components: PascalCase
Profile,Avatar,TodoList,PackingList
State variables: Destructured pattern
const [count, setCount] = useState(0)- Booleans:
[isOnline, setIsOnline],[isPacked, setIsPacked] - Status strings:
'typing','submitting','success','error'
Event handlers:
handleClick,handleSubmit,handleAddTask
Props for callbacks:
onClick,onChange,onAddTask,onSelect
Custom Hooks:
useOnlineStatus,useChatRoom,useFormInput
Reducer actions:
- Past tense:
'added','changed','deleted' - Snake_case compounds:
'changed_selection','sent_message'
Updater functions: Single letter
setCount(n => n + 1)
Pedagogical Code Markers
Wrong vs right code:
// 🔴 Avoid: redundant state and unnecessary Effect
// ✅ Good: calculated during renderingConsole.log for lifecycle teaching:
console.log('✅ Connecting...');
console.log('❌ Disconnected.');Server/Client Labeling
// Server Component
async function Notes() {
const notes = await db.notes.getAll();
}
// Client Component
"use client"
export default function Expandable({children}) {
const [expanded, setExpanded] = useState(false);
}Bundle Size Annotations
import marked from 'marked'; // 35.9K (11.2K gzipped)
import sanitizeHtml from 'sanitize-html'; // 206K (63.3K gzipped)---
Sandpack Example Guidelines
Package.json Rules
Include package.json when:
- Using external npm packages (immer, remarkable, leaflet, toastify-js, etc.)
- Demonstrating experimental/canary React features
- Requiring specific React versions (
react: beta,react: 19.0.0-rc-*)
Omit package.json when:
- Example uses only built-in React features
- No external dependencies needed
- Teaching basic hooks, state, or components
Always mark package.json as hidden:
{ "dependencies": { "react": "latest", "react-dom": "latest", "react-scripts": "latest", "immer": "1.7.3" } }
Version conventions:
- Use
"latest"for stable features - Use exact versions only when compatibility requires it
- Include minimal dependencies (just what the example needs)
Hidden File Patterns
Always hide these file types:
| File Type | Reason |
|---|---|
package.json | Configuration not the teaching point |
sandbox.config.json | Sandbox setup is boilerplate |
public/index.html | HTML structure not the focus |
src/data.js | When it contains sample/mock data |
src/api.js | When showing API usage, not implementation |
src/styles.css | When styling is not the lesson |
src/router.js | Supporting infrastructure |
src/actions.js | Server action implementation details |
Rationale:
- Reduces cognitive load
- Keeps focus on the primary concept
- Creates cleaner, more focused examples
Example:
export const items = [ { id: 1, name: 'Item 1' }, { id: 2, name: 'Item 2' }, ];
Active File Patterns
Mark as active when:
- File contains the primary teaching concept
- Learner should focus on this code first
- Component demonstrates the hook/pattern being taught
Effect of the `active` marker:
- Sets initial editor tab focus when Sandpack loads
- Signals "this is what you should study"
- Works with hidden files to create focused examples
Most common active file: src/index.js or src/App.js
Example:
// This file will be focused when example loads export default function App() { // ... }
File Structure Guidelines
| Scenario | Structure | Reason |
|---|---|---|
| Basic hook usage | Single file | Simple, focused |
| Teaching imports | 2-3 files | Shows modularity |
| Context patterns | 4-5 files | Realistic structure |
| Complex state | 3+ files | Separation of concerns |
Single File Examples (70% of cases):
- Use for simple concepts
- 50-200 lines typical
- Best for: Counter, text inputs, basic hooks
Multi-File Examples (30% of cases):
- Use when teaching modularity/imports
- Use for context patterns (4-5 files)
- Use when component is reused
File Naming:
- Main component:
App.js(capitalized) - Component files:
Gallery.js,Button.js(capitalized) - Data files:
data.js(lowercase) - Utility files:
utils.js(lowercase) - Context files:
TasksContext.js(named after what they provide)
Code Size Limits
- Single file: <200 lines
- Multi-file total: 150-300 lines
- Main component: 100-150 lines
- Supporting files: 20-40 lines each
CSS Guidelines
Always:
- Include minimal CSS for demo interactivity
- Use semantic class names (
.panel,.button-primary,.panel-dark) - Support light/dark themes when showing UI concepts
- Keep CSS visible (never hidden)
Size Guidelines:
- Minimal (5-10 lines): Basic button styling, spacing
- Medium (15-30 lines): Panel styling, form layouts
- Complex (40+ lines): Only for layout-focused examples