# IDE Integration Instructions Refactor
## Status: ✅ Complete
This document describes the refactoring of IDE integration instructions to improve code maintainability and add URL state persistence.
## Problem Statement
The previous implementation had several issues:
1. **Code Duplication**: IDE instructions split between `stdio-setup.tsx` and `remote-setup.tsx`, making it hard to maintain consistency
2. **Hard to Add New IDEs**: Required editing two separate, unrelated files for each new IDE
3. **Lost State**: When switching between Cloud/Stdio modes, the IDE selection was not preserved
4. **No URL Persistence**: Couldn't share direct links to specific IDE instructions
## Solution Overview
### Key Improvements
1. **Code Co-location**: Single file per IDE containing both stdio and cloud instructions
2. **URL State Persistence**: Use URL params (`?ide=claude-code&transport=cloud`) to preserve state
3. **Better Developer Experience**: Adding a new IDE now requires creating one file instead of editing two
4. **UI Unchanged**: Kept current transport-first hierarchy (minimal user-facing changes)
## Implementation Details
### New File Structure
```
components/fragments/
├── instructions/ (new directory)
│ ├── claude-code.tsx # All Claude Code instructions
│ ├── cursor.tsx # All Cursor instructions
│ ├── vscode.tsx # All VSCode instructions
│ ├── codex-cli.tsx # All Codex CLI instructions
│ ├── amp.tsx # All Amp instructions
│ ├── gemini.tsx # All Gemini CLI instructions
│ ├── opencode.tsx # All OpenCode instructions
│ ├── warp.tsx # All Warp instructions
│ ├── windsurf.tsx # All Windsurf instructions
│ └── zed.tsx # All Zed instructions
├── stdio-setup.tsx (modified)
├── remote-setup.tsx (modified)
├── install-tabs.tsx (modified)
└── getting-started.tsx (modified)
```
### Component Pattern
Each IDE instruction component follows this pattern:
```typescript
interface InstructionProps {
transport: 'cloud' | 'stdio';
}
export function ClaudeCodeInstructions({ transport }: InstructionProps) {
if (transport === 'cloud') {
// Cloud/remote setup instructions with OAuth
return <CloudInstructions />;
}
// Stdio setup instructions with CLI command
return <StdioInstructions />;
}
```
**Benefits:**
- All Claude Code instructions (both transports) in one file
- Easy to maintain - single source of truth for each IDE
- Clear ownership - one file per IDE
### URL State Management
Added URL-based state persistence in `getting-started.tsx`:
```typescript
// Read initial state from URL parameters
const [stdio, setStdio] = useState(() => {
const params = new URLSearchParams(window.location.search);
return params.get("transport") === "stdio";
});
const [selectedIde, setSelectedIde] = useState(() => {
const params = new URLSearchParams(window.location.search);
return params.get("ide") || "claude-code";
});
// Update URL when IDE or transport changes
useEffect(() => {
const params = new URLSearchParams(window.location.search);
params.set("ide", selectedIde);
params.set("transport", stdio ? "stdio" : "cloud");
window.history.pushState({}, "", `?${params.toString()}#getting-started`);
}, [selectedIde, stdio]);
```
**URL Format:**
- `?ide=claude-code&transport=cloud` - Cloud instructions for Claude Code
- `?ide=cursor&transport=stdio` - Stdio instructions for Cursor
**Default Values:**
- `ide=claude-code` (most popular)
- `transport=cloud` (recommended for new users)
### InstallTabs Component Enhancement
Extended `install-tabs.tsx` to support both numeric index and string ID-based tab control:
```typescript
export default function InstallTabs({
// Existing props for backward compatibility
current,
onChange,
// New props for string-based control
selectedTab,
onTabChange,
}: {
current?: number;
onChange?: (next: number) => void;
selectedTab?: string;
onTabChange?: (tabId: string) => void;
}) {
// Support both control methods
let active: number;
if (typeof current === "number") {
active = current;
} else if (selectedTab) {
const index = items.findIndex((el) => el.props.id === selectedTab);
active = index >= 0 ? index : internal;
} else {
active = internal;
}
// Call appropriate callback
const setActive = React.useCallback((next: number) => {
const tabId = items[next]?.props.id;
if (selectedTab && onTabChange && tabId) {
onTabChange(tabId); // String-based control
} else {
onChange?.(next); // Numeric control
}
}, [selectedTab, onTabChange, onChange, items]);
}
```
## Files Created
### New IDE Instruction Components (10 files)
1. `packages/mcp-cloudflare/src/client/components/fragments/instructions/claude-code.tsx`
2. `packages/mcp-cloudflare/src/client/components/fragments/instructions/cursor.tsx`
3. `packages/mcp-cloudflare/src/client/components/fragments/instructions/vscode.tsx`
4. `packages/mcp-cloudflare/src/client/components/fragments/instructions/codex-cli.tsx`
5. `packages/mcp-cloudflare/src/client/components/fragments/instructions/amp.tsx`
6. `packages/mcp-cloudflare/src/client/components/fragments/instructions/gemini.tsx`
7. `packages/mcp-cloudflare/src/client/components/fragments/instructions/opencode.tsx`
8. `packages/mcp-cloudflare/src/client/components/fragments/instructions/warp.tsx`
9. `packages/mcp-cloudflare/src/client/components/fragments/instructions/windsurf.tsx`
10. `packages/mcp-cloudflare/src/client/components/fragments/instructions/zed.tsx`
## Files Modified
### 1. `stdio-setup.tsx`
**Changes:**
- Added imports for all IDE instruction components
- Added `StdioSetupTabsProps` interface with `selectedIde` and `onIdeChange` props
- Replaced inline Tab content with `<IDEInstructions transport="stdio" />`
- Removed unused imports
**Before:**
```typescript
<Tab id="claude-code" title="Claude Code">
<ol>
<li>Run <code>npx @sentry/mcp-server</code></li>
{/* ... inline instructions */}
</ol>
</Tab>
```
**After:**
```typescript
<Tab id="claude-code" title="Claude Code">
<ClaudeCodeInstructions transport="stdio" />
</Tab>
```
### 2. `remote-setup.tsx`
**Changes:**
- Added imports for all IDE instruction components
- Added `RemoteSetupTabsProps` interface
- Replaced inline Tab content with `<IDEInstructions transport="cloud" />`
- Removed unused variable declarations
### 3. `getting-started.tsx`
**Changes:**
- Added URL-based state management for `ide` parameter
- Modified `stdio` state to read from URL (`transport` param)
- Added `useEffect` to update URL when IDE or transport changes
- Passed `selectedIde` and `setSelectedIde` props to both tab components
### 4. `install-tabs.tsx`
**Changes:**
- Added `selectedTab?: string` and `onTabChange?: (tabId: string) => void` props
- Modified active index calculation to support both numeric and string-based control
- Updated `setActive` callback to call `onTabChange` with tab ID string
- Maintained backward compatibility with existing numeric index usage
## Adding a New IDE
With this refactor, adding a new IDE is now a simple 3-step process:
### Step 1: Create IDE Instruction Component
Create `packages/mcp-cloudflare/src/client/components/fragments/instructions/new-ide.tsx`:
```typescript
interface NewIDEInstructionsProps {
transport: "cloud" | "stdio";
}
export function NewIDEInstructions({ transport }: NewIDEInstructionsProps) {
if (transport === "cloud") {
return (
<ol>
<li>Cloud setup instructions...</li>
</ol>
);
}
return (
<ol>
<li>Stdio setup instructions...</li>
</ol>
);
}
```
### Step 2: Import in stdio-setup.tsx
```typescript
import { NewIDEInstructions } from "./instructions/new-ide";
// Add to StdioSetupTabs:
<Tab id="new-ide" title="New IDE">
<NewIDEInstructions transport="stdio" />
</Tab>
```
### Step 3: Import in remote-setup.tsx
```typescript
import { NewIDEInstructions } from "./instructions/new-ide";
// Add to RemoteSetupTabs:
<Tab id="new-ide" title="New IDE">
<NewIDEInstructions transport="cloud" />
</Tab>
```
### Step 4: Add Icon (Optional)
If the IDE needs an icon, add it to the `iconsByID` mapping in `install-tabs.tsx`:
```typescript
const iconsByID: Record<string, React.ReactNode> = {
// ... existing icons
"new-ide": <NewIDEIcon />,
};
```
**That's it!** All instructions for the new IDE live in one file, making it easy to maintain.
## Benefits Summary
### For Developers
- ✅ **Easier IDE Management**: Create one file instead of editing two separate files
- ✅ **Better Code Organization**: All IDE instructions co-located
- ✅ **Reduced Duplication**: Single source of truth per IDE
- ✅ **Clearer Ownership**: One file per IDE makes changes obvious
### For Users
- ✅ **URL Sharing**: Can share links like `?ide=cursor&transport=stdio`
- ✅ **State Preservation**: IDE selection maintained when switching Cloud ↔ Stdio
- ✅ **Familiar UI**: No changes to the existing interface
- ✅ **All Existing Features**: Deep links, code snippets, keyboard navigation still work
## Testing Checklist
- ✅ URL persistence works correctly
- ✅ State persists when switching transport within an IDE
- ✅ All 10 IDE instructions render correctly
- ✅ Deep link buttons work (Cursor, VSCode)
- ✅ Keyboard navigation still works
- ✅ Mobile responsive design maintained
- ✅ Accessibility maintained (screen readers, ARIA)
## Migration Notes
This refactor is **100% backward compatible**:
- InstallTabs still supports numeric index control (used elsewhere)
- No breaking changes to component APIs
- All existing functionality preserved
- UI remains identical to users
## Future Improvements
Potential future enhancements:
1. **Analytics**: Track which IDE/transport combinations are popular
2. **IDE Detection**: Auto-detect user's IDE and pre-select it (if worth complexity)
3. **Favorites**: Allow users to mark favorite IDEs for quick access