A Next.js plugin that automatically adds IDE buttons to React components for seamless IDE integration. Supports Cursor, VS Code, WebStorm, and Atom.
npm install nextjs-ide-helperA Next.js plugin that automatically adds IDE buttons to React components in development mode, enabling seamless IDE integration and faster development workflow. Supports Cursor, VS Code, WebStorm, and Atom.
- š Automatic Integration: Automatically wraps React components with IDE buttons
- šÆ Smart Detection: Only processes components in specified directories
- š§ Zero Configuration: Works out of the box with sensible defaults (Cursor as default IDE)
- šļø Development Only: Only active in development mode, no production overhead
- šØ Non-intrusive: Minimal blue dot indicators that don't disrupt your layout
- šļø Toggle Visibility: Floating button to show/hide all IDE dots instantly
- ā” Hydration Safe: No SSR/client hydration mismatches
- š± TypeScript Support: Full TypeScript definitions included
- š Multi-IDE Support: Supports Cursor, VS Code, WebStorm, and Atom
- š Multiple Component Patterns: Supports all React component export patterns
- š AST-Based Processing: Uses robust Abstract Syntax Tree parsing for accurate code transformation
``bash`
npm install nextjs-ide-helper
Add the plugin to your next.config.js:
`javascript
const withIdeHelper = require('nextjs-ide-helper');
/* @type {import('next').NextConfig} /
const nextConfig = {
// your existing config
};
module.exports = withIdeHelper()(nextConfig);
`
All React components in your src/components directory will automatically get IDE buttons in development mode (defaults to Cursor IDE).
Each wrapped component displays a small blue dot (10x10px) in the top-right corner:
- Click the dot to open the component's source file in your IDE
- Hover to see the file path tooltip
- The dots are subtle (60% opacity) and brighten on hover
A floating toggle button appears in the bottom-right corner of your page:
- Blue = IDE dots are visible
- Gray = IDE dots are hidden
- Click to toggle all dots on/off instantly
This lets you quickly hide the dots when you want an unobstructed view of your app, then bring them back when needed.
You can customize the plugin behavior:
`javascript
const withIdeHelper = require('nextjs-ide-helper');
const nextConfig = {
// your existing config
};
module.exports = withIdeHelper({
componentPaths: ['src/components', 'components', 'src/ui'], // directories to scan (supports glob patterns)
projectRoot: process.cwd(), // project root directory
importPath: 'nextjs-ide-helper/withIdeButton', // import path for the HOC
enabled: process.env.NODE_ENV === 'development', // enable/disable
ideType: 'cursor' // IDE to use: 'cursor', 'vscode', 'webstorm', 'atom'
})(nextConfig);
`
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| componentPaths | string[] | ['src/components'] | Directories to scan for React components (supports glob patterns) |projectRoot
| | string | process.cwd() | Root directory of your project |importPath
| | string | 'nextjs-ide-helper/withIdeButton' | Import path for the withIdeButton HOC |enabled
| | boolean | process.env.NODE_ENV === 'development' | Enable/disable the plugin |ideType
| | 'cursor' \| 'vscode' \| 'webstorm' \| 'atom' | 'cursor' | IDE to open files in |
The componentPaths option supports glob patterns for matching nested directory structures:
`javascript`
module.exports = withIdeHelper({
componentPaths: [
'src/components/**', // matches all nested directories under src/components
'/components/', // matches components directories anywhere in the project
'app//ui/', // matches ui directories nested anywhere under app
'modules//components/*' // matches components in any module subdirectory
]
})(nextConfig);
Glob Pattern Examples:
- * - matches any characters within a single directory level**
- - matches any number of directories and subdirectories recursivelysrc/components/*
- - matches src/components/Button.tsx but not src/components/ui/Button.tsxsrc/components/**
- - matches both src/components/Button.tsx and src/components/ui/forms/Button.tsx/components/
- - matches app/components/Button.tsx, modules/feature/components/deep/Widget.tsx, etc.
You can also manually wrap components:
`tsx
import { withIdeButton } from 'nextjs-ide-helper';
const MyComponent = () => {
return
// Default (Cursor)
export default withIdeButton(MyComponent, 'src/components/MyComponent.tsx');
// With specific IDE
export default withIdeButton(MyComponent, 'src/components/MyComponent.tsx', {
ideType: 'vscode'
});
`
The plugin automatically detects and wraps all types of React component export patterns:
tsx
// Named arrow function exports
export const Button = () => ;
export const Modal = () => Modal content;// Named function exports
export function MyButton() {
return ;
}
export function MyModal() {
return
Function Modal;
}// Mixed named and default exports
export const HeaderButton = () => ;
const MainComponent = () =>
Main;
export default MainComponent;// TypeScript named exports
interface ButtonProps {
onClick: () => void;
}
export const TypedButton = ({ onClick }: ButtonProps) => (
);
`$3
#### Named Components
`tsx
// Standard pattern
const MyComponent = () => Hello;
export default MyComponent;// Variable declaration
const MyComponent = function() {
return
Hello;
};
export default MyComponent;
`#### Direct Export Function Components
`tsx
// Named function
export default function MyComponent() {
return Hello;
}// Anonymous function
export default function() {
return
Hello;
}
`#### Arrow Function Components
`tsx
// Anonymous arrow function
export default () => {
return Hello;
};// Arrow function with parameters
export default (props) => {
return
Hello {props.name};
};
`#### Class Components
`tsx
// Named class
export default class MyComponent extends React.Component {
render() {
return Hello;
}
}// TypeScript class
export default class MyComponent extends Component {
render() {
return Hello;
}
}
`#### TypeScript Components
`tsx
// Function with TypeScript
interface Props {
title: string;
}export default function MyComponent(props: Props) {
return
{props.title};
}// Arrow function with TypeScript
export default (props: Props) => {
return
{props.title};
};
`How It Works
1. AST-Based Processing: Uses Babel's Abstract Syntax Tree parser for robust code analysis
2. Webpack Loader: The plugin uses a custom webpack loader to transform your React components at build time
3. Automatic Detection: It scans specified directories for
.tsx and .jsx files
4. Smart Wrapping: Only wraps components that export a default React component (PascalCase names)
5. Development Only: The IDE buttons only appear in development mode
6. Hydration Safe: Uses client-side state to prevent SSR/hydration mismatchesExamples
$3
Before (your original component):
`tsx
// src/components/Button.tsx
import React from 'react';const Button = ({ children, onClick }) => {
return (
);
};
export default Button;
`After (automatically transformed):
`tsx
// src/components/Button.tsx (transformed by the plugin)
import React from 'react';
import { withIdeButton } from 'nextjs-ide-helper/withIdeButton';const Button = ({ children, onClick }) => {
return (
);
};
export default withIdeButton(Button, 'src/components/Button.tsx', {
projectRoot: '/path/to/project',
ideType: 'cursor'
});
`$3
Before (your original named exports):
`tsx
// src/components/Buttons.tsx
export const PrimaryButton = ({ children, onClick }) => {
return (
);
};export const SecondaryButton = ({ children, onClick }) => {
return (
);
};
`After (automatically transformed):
`tsx
// src/components/Buttons.tsx (transformed by the plugin)
import { withIdeButton } from 'nextjs-ide-helper/withIdeButton';export const PrimaryButton = withIdeButton(({ children, onClick }) => {
return (
);
}, 'src/components/Buttons.tsx', {
projectRoot: '/path/to/project',
ideType: 'cursor'
});
export const SecondaryButton = withIdeButton(({ children, onClick }) => {
return (
);
}, 'src/components/Buttons.tsx', {
projectRoot: '/path/to/project',
ideType: 'cursor'
});
`$3
Before (mixed exports):
`tsx
// src/components/Layout.tsx
export const Header = () => My App Header ;
export const Footer = () => ;const Layout = ({ children }) => (
{children}
);export default Layout;
`After (automatically transformed):
`tsx
// src/components/Layout.tsx (transformed by the plugin)
import { withIdeButton } from 'nextjs-ide-helper/withIdeButton';export const Header = withIdeButton(() => My App Header , 'src/components/Layout.tsx', {
projectRoot: '/path/to/project',
ideType: 'cursor'
});
export const Footer = withIdeButton(() => , 'src/components/Layout.tsx', {
projectRoot: '/path/to/project',
ideType: 'cursor'
});
const Layout = ({ children }) => (
{children}
);export default withIdeButton(Layout, 'src/components/Layout.tsx', {
projectRoot: '/path/to/project',
ideType: 'cursor'
});
`$3
Before:
`tsx
// src/components/Header.tsx
export default function Header() {
return My App Header ;
}
`After (automatically transformed):
`tsx
// src/components/Header.tsx (transformed by the plugin)
import { withIdeButton } from 'nextjs-ide-helper/withIdeButton';function Header() {
return My App Header ;
}
export default withIdeButton(Header, 'src/components/Header.tsx', {
projectRoot: '/path/to/project',
ideType: 'cursor'
});
`$3
Before:
`tsx
// src/components/Footer.tsx
export default () => {
return ;
};
`After (automatically transformed):
`tsx
// src/components/Footer.tsx (transformed by the plugin)
import { withIdeButton } from 'nextjs-ide-helper/withIdeButton';export default withIdeButton(() => {
return ;
}, 'src/components/Footer.tsx', {
projectRoot: '/path/to/project',
ideType: 'cursor'
});
`Troubleshooting
$3
1. Check that your components are in the specified
componentPaths
2. Ensure your components export a default export with a capitalized name
3. Verify you're in development mode (NODE_ENV=development)$3
The plugin is designed to prevent hydration errors, but if you encounter any:
1. Make sure you're using the latest version
2. Check that the 'use client' directive is present in the withIdeButton module
3. File an issue with details about your setup
$3
1. Ensure you have your IDE installed and properly configured
- Cursor: Make sure Cursor IDE is installed
- VS Code: Make sure VS Code is installed and set up to handle
vscode:// links
- WebStorm: Ensure WebStorm is installed and configured
- Atom: Make sure Atom is installed (note: Atom is deprecated)
2. Check that the file paths are correct
3. Verify your browser allows protocol links for your IDE
4. Try setting the ideType option explicitly in your configurationContributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT
Changelog
See CHANGELOG.md for detailed release notes.
$3
$3
- Added floating toggle button to show/hide all IDE dots
- Toggle button appears in bottom-right corner
- Blue when dots visible, gray when hidden
- State synchronized across all components via custom events$3
- Changed IDE buttons from text+emoji to minimal 10x10px blue dots
- Reduced visual footprint for less intrusive development experience
- Removed console.log statements from plugin$3
- Added comprehensive support for ES6 named exports in React components
- Support for export const Component = () => {} and export function Component() {} patterns
- Mixed export support - files with both named and default exports
- Enhanced component detection to distinguish React components from utility exports
- Expanded test suite with 8 new comprehensive test cases$3
- Added support for glob patterns in componentPaths configuration
- Support for nested directory matching with **` patterns