nextjs-ide-helper
v1.5.4
Published
A Next.js plugin that automatically adds IDE buttons to React components for seamless IDE integration. Supports Cursor, VS Code, WebStorm, and Atom.
Maintainers
Readme
NextJS IDE Helper
A 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.
Features
- 🚀 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
Installation
npm install nextjs-ide-helperQuick Start
1. Configure Next.js
Add the plugin to your next.config.js:
const withIdeHelper = require('nextjs-ide-helper');
/** @type {import('next').NextConfig} */
const nextConfig = {
// your existing config
};
module.exports = withIdeHelper()(nextConfig);2. That's it!
All React components in your src/components directory will automatically get IDE buttons in development mode (defaults to Cursor IDE).
User Interface
IDE Indicator Dots
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
Toggle Button
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.
Configuration
You can customize the plugin behavior:
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);Configuration Options
| 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 |
Glob Pattern Support
The componentPaths option supports glob patterns for matching nested directory structures:
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/*- matchessrc/components/Button.tsxbut notsrc/components/ui/Button.tsxsrc/components/**- matches bothsrc/components/Button.tsxandsrc/components/ui/forms/Button.tsx**/components/**- matchesapp/components/Button.tsx,modules/feature/components/deep/Widget.tsx, etc.
Manual Usage
You can also manually wrap components:
import { withIdeButton } from 'nextjs-ide-helper';
const MyComponent = () => {
return <div>Hello World</div>;
};
// Default (Cursor)
export default withIdeButton(MyComponent, 'src/components/MyComponent.tsx');
// With specific IDE
export default withIdeButton(MyComponent, 'src/components/MyComponent.tsx', {
ideType: 'vscode'
});Supported Component Patterns
The plugin automatically detects and wraps all types of React component export patterns:
Named Export Components
// Named arrow function exports
export const Button = () => <button>Click me</button>;
export const Modal = () => <div>Modal content</div>;
// Named function exports
export function MyButton() {
return <button>Function Button</button>;
}
export function MyModal() {
return <div>Function Modal</div>;
}
// Mixed named and default exports
export const HeaderButton = () => <button>Header</button>;
const MainComponent = () => <div>Main</div>;
export default MainComponent;
// TypeScript named exports
interface ButtonProps {
onClick: () => void;
}
export const TypedButton = ({ onClick }: ButtonProps) => (
<button onClick={onClick}>Typed Button</button>
);Default Export Components
Named Components
// Standard pattern
const MyComponent = () => <div>Hello</div>;
export default MyComponent;
// Variable declaration
const MyComponent = function() {
return <div>Hello</div>;
};
export default MyComponent;Direct Export Function Components
// Named function
export default function MyComponent() {
return <div>Hello</div>;
}
// Anonymous function
export default function() {
return <div>Hello</div>;
}Arrow Function Components
// Anonymous arrow function
export default () => {
return <div>Hello</div>;
};
// Arrow function with parameters
export default (props) => {
return <div>Hello {props.name}</div>;
};Class Components
// Named class
export default class MyComponent extends React.Component {
render() {
return <div>Hello</div>;
}
}
// TypeScript class
export default class MyComponent extends Component<Props> {
render() {
return <div>Hello</div>;
}
}TypeScript Components
// Function with TypeScript
interface Props {
title: string;
}
export default function MyComponent(props: Props) {
return <div>{props.title}</div>;
}
// Arrow function with TypeScript
export default (props: Props) => {
return <div>{props.title}</div>;
};How It Works
- AST-Based Processing: Uses Babel's Abstract Syntax Tree parser for robust code analysis
- Webpack Loader: The plugin uses a custom webpack loader to transform your React components at build time
- Automatic Detection: It scans specified directories for
.tsxand.jsxfiles - Smart Wrapping: Only wraps components that export a default React component (PascalCase names)
- Development Only: The IDE buttons only appear in development mode
- Hydration Safe: Uses client-side state to prevent SSR/hydration mismatches
Examples
Standard Component Pattern
Before (your original component):
// src/components/Button.tsx
import React from 'react';
const Button = ({ children, onClick }) => {
return (
<button onClick={onClick}>
{children}
</button>
);
};
export default Button;After (automatically transformed):
// src/components/Button.tsx (transformed by the plugin)
import React from 'react';
import { withIdeButton } from 'nextjs-ide-helper/withIdeButton';
const Button = ({ children, onClick }) => {
return (
<button onClick={onClick}>
{children}
</button>
);
};
export default withIdeButton(Button, 'src/components/Button.tsx', {
projectRoot: '/path/to/project',
ideType: 'cursor'
});Named Export Pattern
Before (your original named exports):
// src/components/Buttons.tsx
export const PrimaryButton = ({ children, onClick }) => {
return (
<button className="primary" onClick={onClick}>
{children}
</button>
);
};
export const SecondaryButton = ({ children, onClick }) => {
return (
<button className="secondary" onClick={onClick}>
{children}
</button>
);
};After (automatically transformed):
// src/components/Buttons.tsx (transformed by the plugin)
import { withIdeButton } from 'nextjs-ide-helper/withIdeButton';
export const PrimaryButton = withIdeButton(({ children, onClick }) => {
return (
<button className="primary" onClick={onClick}>
{children}
</button>
);
}, 'src/components/Buttons.tsx', {
projectRoot: '/path/to/project',
ideType: 'cursor'
});
export const SecondaryButton = withIdeButton(({ children, onClick }) => {
return (
<button className="secondary" onClick={onClick}>
{children}
</button>
);
}, 'src/components/Buttons.tsx', {
projectRoot: '/path/to/project',
ideType: 'cursor'
});Mixed Named and Default Exports
Before (mixed exports):
// src/components/Layout.tsx
export const Header = () => <header>My App Header</header>;
export const Footer = () => <footer>© 2025 My App</footer>;
const Layout = ({ children }) => (
<div>
<Header />
<main>{children}</main>
<Footer />
</div>
);
export default Layout;After (automatically transformed):
// src/components/Layout.tsx (transformed by the plugin)
import { withIdeButton } from 'nextjs-ide-helper/withIdeButton';
export const Header = withIdeButton(() => <header>My App Header</header>, 'src/components/Layout.tsx', {
projectRoot: '/path/to/project',
ideType: 'cursor'
});
export const Footer = withIdeButton(() => <footer>© 2025 My App</footer>, 'src/components/Layout.tsx', {
projectRoot: '/path/to/project',
ideType: 'cursor'
});
const Layout = ({ children }) => (
<div>
<Header />
<main>{children}</main>
<Footer />
</div>
);
export default withIdeButton(Layout, 'src/components/Layout.tsx', {
projectRoot: '/path/to/project',
ideType: 'cursor'
});Direct Export Function Component
Before:
// src/components/Header.tsx
export default function Header() {
return <header>My App Header</header>;
}After (automatically transformed):
// src/components/Header.tsx (transformed by the plugin)
import { withIdeButton } from 'nextjs-ide-helper/withIdeButton';
function Header() {
return <header>My App Header</header>;
}
export default withIdeButton(Header, 'src/components/Header.tsx', {
projectRoot: '/path/to/project',
ideType: 'cursor'
});Anonymous Component
Before:
// src/components/Footer.tsx
export default () => {
return <footer>© 2025 My App</footer>;
};After (automatically transformed):
// src/components/Footer.tsx (transformed by the plugin)
import { withIdeButton } from 'nextjs-ide-helper/withIdeButton';
export default withIdeButton(() => {
return <footer>© 2025 My App</footer>;
}, 'src/components/Footer.tsx', {
projectRoot: '/path/to/project',
ideType: 'cursor'
});Troubleshooting
Components not getting wrapped
- Check that your components are in the specified
componentPaths - Ensure your components export a default export with a capitalized name
- Verify you're in development mode (
NODE_ENV=development)
Hydration errors
The plugin is designed to prevent hydration errors, but if you encounter any:
- Make sure you're using the latest version
- Check that the 'use client' directive is present in the withIdeButton module
- File an issue with details about your setup
IDE not opening files
- 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)
- Check that the file paths are correct
- Verify your browser allows protocol links for your IDE
- Try setting the
ideTypeoption explicitly in your configuration
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT
Changelog
See CHANGELOG.md for detailed release notes.
Recent Releases
1.5.0 - Toggle Visibility
- 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
1.4.1 - Minimal UI
- 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
1.4.0 - Named Export Support
- Added comprehensive support for ES6 named exports in React components
- Support for
export const Component = () => {}andexport 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
1.3.0 - Glob Pattern Support
- Added support for glob patterns in
componentPathsconfiguration - Support for nested directory matching with
**patterns - Enhanced file path matching for complex project structures
- Updated tests and documentation
1.2.0 - Enhanced Component Support
- Added support for all React component export patterns
- AST-based code transformation for better reliability
- Anonymous component support
- Enhanced TypeScript compatibility
1.1.3
- Updated readme
1.1.2
- Added support for multiple IDEs (Cursor, VS Code, WebStorm, Atom)
1.0.0
- Initial release
- Automatic component wrapping
- TypeScript support
- Hydration-safe implementation
