Generic IDE Integration
VDK support for any code editor or IDE without specific integration
Generic IDE Integration
The Generic IDE integration provides VDK support for any code editor or IDE that doesn't have a specific integration. It generates standard Markdown rules that can be used across a wide range of development environments.
Overview
Generic IDE integration creates:
- Standard Markdown Rules:
.ai/rules/
directory with universal format - Plain Text Guidelines: Human-readable documentation
- Universal Compatibility: Works with any text editor or IDE
- Copy-Paste Friendly: Easy to share and distribute
When to Use Generic IDE
Use the Generic IDE integration when:
- Your IDE doesn't have a specific VDK integration
- You need rules that work across multiple editors
- You want to create documentation for team members using different tools
- You're building custom tooling that needs VDK rules
Supported Editors
The generic format works with:
- Vim/Neovim (with appropriate plugins)
- Emacs (with markdown support)
- Sublime Text (with markdown preview)
- Atom (with community packages)
- JetBrains IDEs (IntelliJ, WebStorm, PyCharm)
- Any text editor with Markdown support
- Custom tools and CI/CD systems
Setup
Automatic Setup
# Initialize VDK with generic integration
vdk init
# The generic integration is always available as fallback
vdk integrations --setup generic
Manual Setup
# Check available integrations
vdk integrations --list
# Setup generic integration explicitly
vdk integrations --setup generic
# Verify setup
ls -la .ai/rules/
Generated Files
.ai/rules/
Directory Structure
.ai/
├── rules/
│ ├── project-overview.md # Main project context
│ ├── technology-stack.md # Tech stack details
│ ├── coding-conventions.md # Code style guide
│ ├── architecture-patterns.md # Architectural guidance
│ ├── development-workflow.md # Development processes
│ └── examples/ # Code examples
│ ├── components.md # Component examples
│ ├── api-routes.md # API examples
│ └── utilities.md # Utility examples
└── vdk-metadata.json # VDK configuration
Project Overview (project-overview.md)
# Project Overview
## Project Information
- **Name**: my-nextjs-app
- **Type**: Web Application
- **Framework**: Next.js 15
- **Language**: TypeScript
- **Description**: Modern Next.js application with TypeScript, Tailwind CSS, and Prisma
## Technology Stack
### Frontend
- **Framework**: Next.js 15 (App Router)
- **Language**: TypeScript 5.0+
- **Styling**: Tailwind CSS v3
- **State Management**: Zustand
- **UI Components**: Custom + Headless UI
### Backend
- **Runtime**: Node.js 18+
- **Database**: PostgreSQL
- **ORM**: Prisma
- **Authentication**: NextAuth.js
- **API**: Next.js API Routes
### Development Tools
- **Package Manager**: pnpm
- **Build Tool**: Next.js (Webpack)
- **Testing**: Jest + React Testing Library
- **Linting**: ESLint + Prettier
- **Type Checking**: TypeScript strict mode
## Project Structure
project-root/ ├── app/ # Next.js App Router │ ├── (auth)/ # Route groups │ ├── api/ # API routes │ ├── globals.css # Global styles │ └── layout.tsx # Root layout ├── components/ # React components │ ├── ui/ # Base UI components │ ├── forms/ # Form components │ └── layout/ # Layout components ├── lib/ # Utilities and config │ ├── auth/ # Auth configuration │ ├── db/ # Database utilities │ └── utils/ # General utilities ├── types/ # TypeScript definitions ├── styles/ # Additional styles └── prisma/ # Database schema
## Key Conventions
### File Naming
- **Components**: PascalCase (`UserProfile.tsx`)
- **Pages**: lowercase with hyphens (`user-profile/page.tsx`)
- **Utilities**: camelCase (`formatDate.ts`)
- **Types**: PascalCase (`User.ts`)
### Import Organization
1. React and Next.js imports
2. Third-party library imports
3. Internal component imports
4. Utility and type imports
5. Relative imports
### Code Style
- Use TypeScript for all files
- Prefer functional components
- Use interfaces for object types
- Follow ESLint + Prettier configuration
- Include JSDoc for complex functions
## Getting Started
1. Install dependencies: `pnpm install`
2. Set up environment: Copy `.env.example` to `.env.local`
3. Run development server: `pnpm dev`
4. Open http://localhost:3000
## Important Notes
- Server components are preferred over client components
- Use `'use client'` directive only when necessary
- Database operations should use Prisma
- All API routes should include proper error handling
- Components should be accessible (WCAG 2.1)
Technology Stack (technology-stack.md)
# Technology Stack Guide
## Framework: Next.js 15
### App Router Architecture
Next.js 15 uses the App Router for file-based routing:
- **Pages**: `app/page.tsx` → `/`
- **Nested Routes**: `app/users/page.tsx` → `/users`
- **Dynamic Routes**: `app/users/[id]/page.tsx` → `/users/123`
- **Route Groups**: `app/(auth)/login/page.tsx` → `/login`
### Server vs Client Components
**Server Components (Default)**:
```typescript
// app/users/page.tsx
export default async function UsersPage() {
const users = await getUsers(); // Server-side data fetching
return <UsersList users={users} />;
}
Client Components (When Needed):
'use client'
import { useState } from 'react';
export default function InteractiveButton() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(c => c + 1)}>Count: {count}</button>;
}
Language: TypeScript
Configuration
- Strict mode enabled
- Path mapping with
@/
forsrc/
- ESNext target for modern JavaScript features
Type Definitions
// types/user.ts
export interface User {
id: string;
name: string;
email: string;
createdAt: Date;
updatedAt: Date;
}
export type CreateUserInput = Omit<User, 'id' | 'createdAt' | 'updatedAt'>;
export type UpdateUserInput = Partial<CreateUserInput>;
Styling: Tailwind CSS
Configuration
- Utility-first approach
- Custom design system colors
- Responsive design with mobile-first breakpoints
- Dark mode support
Usage Patterns
// Component with Tailwind classes
export default function Button({ children, variant = 'primary' }) {
const baseClasses = 'px-4 py-2 rounded-md font-medium transition-colors';
const variants = {
primary: 'bg-blue-500 text-white hover:bg-blue-600',
secondary: 'bg-gray-200 text-gray-900 hover:bg-gray-300'
};
return (
<button className={`${baseClasses} ${variants[variant]}`}>
{children}
</button>
);
}
Database: PostgreSQL + Prisma
Schema Definition
// prisma/schema.prisma
model User {
id String @id @default(cuid())
name String
email String @unique
posts Post[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Post {
id String @id @default(cuid())
title String
content String
author User @relation(fields: [authorId], references: [id])
authorId String
}
Database Operations
// lib/db/users.ts
import { prisma } from '@/lib/db';
export async function createUser(data: CreateUserInput): Promise<User> {
return prisma.user.create({ data });
}
export async function getUserById(id: string): Promise<User | null> {
return prisma.user.findUnique({
where: { id },
include: { posts: true }
});
}
State Management: Zustand
Store Setup
// lib/stores/user-store.ts
import { create } from 'zustand';
interface UserState {
users: User[];
loading: boolean;
addUser: (user: User) => void;
setUsers: (users: User[]) => void;
setLoading: (loading: boolean) => void;
}
export const useUserStore = create<UserState>((set) => ({
users: [],
loading: false,
addUser: (user) => set((state) => ({ users: [...state.users, user] })),
setUsers: (users) => set({ users }),
setLoading: (loading) => set({ loading }),
}));
Testing: Jest + React Testing Library
Component Testing
// __tests__/components/Button.test.tsx
import { render, screen, fireEvent } from '@testing-library/react';
import Button from '@/components/ui/Button';
describe('Button', () => {
it('renders with correct text', () => {
render(<Button>Click me</Button>);
expect(screen.getByRole('button', { name: 'Click me' })).toBeInTheDocument();
});
it('handles click events', () => {
const handleClick = jest.fn();
render(<Button onClick={handleClick}>Click me</Button>);
fireEvent.click(screen.getByRole('button'));
expect(handleClick).toHaveBeenCalledTimes(1);
});
});
Development Tools
Package Manager: pnpm
- Faster installation and less disk space
- Strict dependency resolution
- Workspace support for monorepos
Linting: ESLint + Prettier
{
"extends": ["next/core-web-vitals", "@typescript-eslint/recommended"],
"rules": {
"@typescript-eslint/no-unused-vars": "error",
"prefer-const": "error"
}
}
Type Checking
- Run
pnpm type-check
before commits - Use TypeScript strict mode
- Include proper JSDoc for complex functions
### Coding Conventions (coding-conventions.md)
```markdown
# Coding Conventions
## TypeScript Guidelines
### Interface vs Type
```typescript
// ✅ Use interfaces for object shapes
interface UserProps {
user: User;
onEdit?: (user: User) => void;
}
// ✅ Use type aliases for unions and computed types
type Status = 'pending' | 'approved' | 'rejected';
type UserWithStatus = User & { status: Status };
Naming Conventions
- Interfaces: PascalCase (
UserProps
,ApiResponse
) - Types: PascalCase (
Status
,EventHandler
) - Functions: camelCase (
getUserData
,formatCurrency
) - Constants: UPPER_CASE (
API_BASE_URL
,MAX_RETRY_COUNT
) - Components: PascalCase (
UserProfile
,NavigationMenu
)
Generic Types
// ✅ Use descriptive generic names
interface Repository<TEntity, TKey = string> {
findById(id: TKey): Promise<TEntity | null>;
create(entity: Omit<TEntity, 'id'>): Promise<TEntity>;
}
// ✅ Use constraints when appropriate
function processItems<T extends { id: string }>(items: T[]): T[] {
return items.filter(item => item.id);
}
React Component Guidelines
Component Structure
// 1. Imports (grouped)
import React from 'react';
import { NextPage } from 'next';
import { Button } from '@/components/ui/Button';
import { formatDate } from '@/lib/utils';
import type { User } from '@/types/user';
// 2. Props interface
interface UserProfileProps {
user: User;
editable?: boolean;
}
// 3. Component function
export default function UserProfile({ user, editable = false }: UserProfileProps) {
// 4. Hooks at the top
const [isEditing, setIsEditing] = useState(false);
// 5. Event handlers
const handleEdit = () => setIsEditing(true);
// 6. Early returns
if (!user) return <div>User not found</div>;
// 7. Main render
return (
<div className="user-profile">
<h1>{user.name}</h1>
{editable && <Button onClick={handleEdit}>Edit</Button>}
</div>
);
}
Component Patterns
Server Components (Preferred):
// app/users/page.tsx
export default async function UsersPage() {
const users = await getUsers();
return (
<div>
<h1>Users</h1>
{users.map(user => (
<UserCard key={user.id} user={user} />
))}
</div>
);
}
Client Components (When Needed):
'use client'
export default function SearchForm() {
const [query, setQuery] = useState('');
return (
<form>
<input
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Search users..."
/>
</form>
);
}
API Route Conventions
Structure
// app/api/users/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { z } from 'zod';
// Validation schema
const createUserSchema = z.object({
name: z.string().min(1),
email: z.string().email()
});
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const data = createUserSchema.parse(body);
const user = await createUser(data);
return NextResponse.json(user, { status: 201 });
} catch (error) {
if (error instanceof z.ZodError) {
return NextResponse.json(
{ error: 'Validation failed', details: error.errors },
{ status: 400 }
);
}
console.error('API Error:', error);
return NextResponse.json(
{ error: 'Internal server error' },
{ status: 500 }
);
}
}
Error Handling
- Always include try-catch blocks
- Use appropriate HTTP status codes
- Validate input with Zod or similar
- Log errors for debugging
- Return consistent error format
Import Organization
// 1. React and Next.js
import React from 'react';
import { NextPage } from 'next';
import Link from 'next/link';
// 2. Third-party libraries
import { z } from 'zod';
import { format } from 'date-fns';
// 3. Internal components (absolute imports)
import { Button } from '@/components/ui/Button';
import { UserCard } from '@/components/UserCard';
// 4. Utilities and types
import { formatCurrency } from '@/lib/utils';
import type { User } from '@/types/user';
// 5. Relative imports (if any)
import './styles.css';
File Organization
Directory Structure
src/
├── app/ # Next.js App Router
├── components/ # Reusable components
│ ├── ui/ # Base UI components
│ ├── forms/ # Form components
│ └── layout/ # Layout components
├── lib/ # Utilities and config
│ ├── api/ # API utilities
│ ├── auth/ # Auth configuration
│ ├── db/ # Database utilities
│ └── utils/ # General utilities
├── types/ # TypeScript definitions
└── styles/ # Styles and themes
File Naming
- Components: PascalCase (
UserProfile.tsx
) - Pages: kebab-case (
user-profile/page.tsx
) - Utilities: camelCase (
formatDate.ts
) - Types: PascalCase (
User.ts
) - Constants: UPPER_CASE (
constants.ts
with UPPER_CASE exports)
Error Handling
Component Error Boundaries
'use client'
import { Component, ErrorInfo, ReactNode } from 'react';
interface Props {
children: ReactNode;
}
interface State {
hasError: boolean;
}
export class ErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(): State {
return { hasError: true };
}
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
console.error('Error caught by boundary:', error, errorInfo);
}
render() {
if (this.state.hasError) {
return <div>Something went wrong.</div>;
}
return this.props.children;
}
}
Async Error Handling
async function fetchUserSafely(id: string): Promise<User | null> {
try {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) {
throw new Error(`Failed to fetch user: ${response.statusText}`);
}
return await response.json();
} catch (error) {
console.error('Error fetching user:', error);
return null;
}
}
Performance Guidelines
Component Optimization
import { memo, useMemo, useCallback } from 'react';
// Memoize expensive components
const ExpensiveComponent = memo(function ExpensiveComponent({ data }) {
const processedData = useMemo(() => {
return data.map(item => ({ ...item, processed: true }));
}, [data]);
return <div>{/* Render processed data */}</div>;
});
// Memoize callbacks
function ParentComponent() {
const handleClick = useCallback((id: string) => {
// Handle click
}, []);
return <ExpensiveComponent onClick={handleClick} />;
}
Image Optimization
import Image from 'next/image';
// ✅ Use Next.js Image component
<Image
src="/profile.jpg"
alt="User profile"
width={200}
height={200}
priority // For above-the-fold images
/>
// ✅ For dynamic images
<Image
src={user.avatar}
alt={`${user.name}'s avatar`}
width={200}
height={200}
placeholder="blur"
blurDataURL="data:image/jpeg;base64,..."
/>
## Usage in Different Editors
### Vim/Neovim
```vim
" Add to your .vimrc or init.vim
" Open project rules quickly
nnoremap <leader>vr :edit .ai/rules/project-overview.md<CR>
" Set markdown filetype for .ai/rules files
autocmd BufRead,BufNewFile .ai/rules/*.md set filetype=markdown
" Enable markdown preview
Plug 'iamcco/markdown-preview.nvim'
Emacs
;; Add to your .emacs or init.el
;; Quick access to VDK rules
(defun open-vdk-rules ()
"Open VDK rules directory"
(interactive)
(find-file ".ai/rules/"))
(global-set-key (kbd "C-c v r") 'open-vdk-rules)
;; Enable markdown mode for rules
(add-to-list 'auto-mode-alist '("\\.ai/rules/.*\\.md\\'" . markdown-mode))
JetBrains IDEs
<!-- Add to your IDE settings -->
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<option value="VDK Rule Template" />
</option>
</component>
Sublime Text
// Add to your project settings
{
"folders": [
{
"path": ".",
"file_exclude_patterns": ["node_modules/*"],
"folder_exclude_patterns": ["node_modules", ".git"]
}
],
"settings": {
"vdk_rules_path": ".ai/rules/"
}
}
Automation and CI/CD
GitHub Actions
# .github/workflows/update-vdk-rules.yml
name: Update VDK Rules
on:
push:
branches: [main]
paths: ['package.json', 'src/**']
jobs:
update-rules:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
- name: Install VDK CLI
run: npm install -g @vibe-dev-kit/cli
- name: Update rules
run: vdk init --overwrite
- name: Commit changes
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add .ai/rules/
git diff --staged --quiet || git commit -m "Update VDK rules"
git push
Pre-commit Hook
#!/bin/sh
# .git/hooks/pre-commit
# Update VDK rules before commit
echo "Updating VDK rules..."
vdk init --overwrite
# Add updated rules to commit
git add .ai/rules/
echo "VDK rules updated successfully"
Best Practices
1. Keep Rules Updated
# Regular maintenance
vdk init --overwrite
git add .ai/rules/
git commit -m "Update VDK rules"
2. Document Custom Patterns
# custom-patterns.md
## Project-Specific Patterns
### Error Handling
All async operations should use our custom error wrapper:
```typescript
import { withErrorHandling } from '@/lib/error-handling';
export const getUserData = withErrorHandling(async (id: string) => {
return await prisma.user.findUnique({ where: { id } });
});
### 3. Share with Team
```bash
# Include in version control
git add .ai/
echo ".ai/cache/" >> .gitignore
# Document in README
echo "## VDK Rules" >> README.md
echo "This project uses VDK CLI for AI assistant integration." >> README.md
echo "Rules are located in `.ai/rules/` directory." >> README.md
4. Create Editor-Specific Configurations
Document how team members can use the rules in their preferred editors in your project README.
Next Steps
- Custom Templates - Create custom rule templates
- Integration Manager - Build custom integrations
- Team Collaboration - Share rules with your team
- Automation - Automate rule updates