VDK Docs
Integrations

GitHub Copilot Integration

VDK integration with GitHub's AI-powered coding assistant through VS Code workspace configuration

GitHub Copilot Integration

GitHub Copilot is GitHub's AI-powered coding assistant that provides intelligent code suggestions. VDK CLI integrates with GitHub Copilot through VS Code workspace configuration and JSON-based guideline files to enhance its project awareness.

Overview

GitHub Copilot integration creates:

  • JSON Guidelines: .github/copilot/ directory with structured configuration files
  • VS Code Workspace: Enhanced workspace settings for Copilot
  • Custom Instructions: Project-specific coding guidelines and patterns
  • Context Enhancement: Rich project context for better suggestions

Setup

Prerequisites

  • VS Code with GitHub Copilot extension
  • GitHub Copilot subscription
  • VDK CLI installed and configured

Automatic Setup

# Initialize VDK with GitHub Copilot integration
vdk init --ide-integration

# Or setup GitHub Copilot specifically
vdk integrations --setup github-copilot

Manual Setup

# Check if GitHub Copilot is detected
vdk integrations --scan

# Setup GitHub Copilot integration
vdk integrations --setup github-copilot

# Verify setup
vdk integrations --list

Generated Files

.github/copilot/ Directory Structure

.github/
└── copilot/
    ├── instructions.json       # Main Copilot instructions
    ├── guidelines.json         # Coding guidelines
    ├── patterns.json          # Code patterns and examples
    ├── technologies.json      # Technology-specific rules
    └── workspace.json         # Workspace configuration

Instructions File (.github/copilot/instructions.json)

{
  "version": "2.0.1",
  "name": "Next.js Project Instructions",
  "description": "GitHub Copilot instructions for Next.js TypeScript project",
  "created": "2024-01-15T10:30:00Z",
  "updated": "2024-01-15T10:30:00Z",
  "project": {
    "name": "my-nextjs-app",
    "type": "web-application",
    "framework": "nextjs",
    "language": "typescript",
    "description": "Next.js 15 application with TypeScript, Tailwind CSS, and Prisma"
  },
  "context": {
    "overview": "This is a Next.js 15 application using the App Router architecture with TypeScript for type safety, Tailwind CSS for styling, and Prisma as the ORM for PostgreSQL database operations.",
    "architecture": "App Router with server components by default, client components only when needed for interactivity",
    "patterns": [
      "Server-first architecture",
      "Component-based design",
      "Feature-based organization",
      "Type-safe API development"
    ]
  },
  "technologies": {
    "frontend": {
      "framework": "Next.js 15",
      "language": "TypeScript 5.0+",
      "styling": "Tailwind CSS",
      "stateManagement": "Zustand",
      "testing": "Jest + React Testing Library"
    },
    "backend": {
      "runtime": "Node.js 18+",
      "database": "PostgreSQL",
      "orm": "Prisma",
      "authentication": "NextAuth.js"
    },
    "tooling": {
      "packageManager": "pnpm",
      "linting": "ESLint + Prettier",
      "typeChecking": "TypeScript strict mode",
      "deployment": "Vercel"
    }
  },
  "instructions": [
    "Always use TypeScript with proper type definitions",
    "Prefer server components over client components",
    "Use Tailwind CSS utility classes for styling",
    "Follow the established file naming conventions",
    "Implement proper error handling and loading states",
    "Use absolute imports with @/ prefix",
    "Include proper JSDoc comments for complex functions",
    "Follow the repository pattern for data access"
  ]
}

Guidelines File (.github/copilot/guidelines.json)

{
  "version": "2.0.1",
  "name": "Coding Guidelines",
  "description": "Project-specific coding standards and conventions",
  "guidelines": {
    "typescript": {
      "strictMode": true,
      "noImplicitAny": true,
      "preferInterfaces": true,
      "naming": {
        "interfaces": "PascalCase",
        "types": "PascalCase", 
        "functions": "camelCase",
        "constants": "UPPER_CASE"
      },
      "examples": {
        "interface": {
          "description": "Define component props with proper TypeScript interfaces",
          "code": "interface UserCardProps {\n  user: {\n    id: string;\n    name: string;\n    email: string;\n  };\n  onEdit?: (user: User) => void;\n}"
        },
        "component": {
          "description": "React component with TypeScript",
          "code": "export default function UserCard({ user, onEdit }: UserCardProps) {\n  return (\n    <div className=\"p-4 border rounded-lg\">\n      <h3 className=\"text-lg font-semibold\">{user.name}</h3>\n      <p className=\"text-gray-600\">{user.email}</p>\n    </div>\n  );\n}"
        }
      }
    },
    "react": {
      "preferServerComponents": true,
      "useClientDirective": "Only when necessary for interactivity",
      "componentStructure": {
        "interfaces": "Define props interface first",
        "hooks": "Hooks at the top of component",
        "handlers": "Event handlers after hooks",
        "earlyReturns": "Handle loading/error states early",
        "mainRender": "Main JSX at the bottom"
      },
      "examples": {
        "serverComponent": {
          "description": "Next.js server component with data fetching",
          "code": "import { getUsers } from '@/lib/api/users';\n\nexport default async function UsersPage() {\n  const users = await getUsers();\n  \n  return (\n    <div>\n      <h1>Users</h1>\n      {users.map(user => (\n        <UserCard key={user.id} user={user} />\n      ))}\n    </div>\n  );\n}"
        },
        "clientComponent": {
          "description": "Client component with state and interactivity",
          "code": "'use client'\n\nimport { useState } from 'react';\n\ninterface CounterProps {\n  initialCount?: number;\n}\n\nexport default function Counter({ initialCount = 0 }: CounterProps) {\n  const [count, setCount] = useState(initialCount);\n  \n  return (\n    <button\n      onClick={() => setCount(c => c + 1)}\n      className=\"px-4 py-2 bg-blue-500 text-white rounded\"\n    >\n      Count: {count}\n    </button>\n  );\n}"
        }
      }
    },
    "nextjs": {
      "appRouter": true,
      "fileConventions": {
        "pages": "page.tsx",
        "layouts": "layout.tsx",
        "loading": "loading.tsx",
        "error": "error.tsx",
        "notFound": "not-found.tsx"
      },
      "routing": {
        "dynamicRoutes": "[id]",
        "routeGroups": "(auth)",
        "catchAll": "[...slug]"
      },
      "examples": {
        "apiRoute": {
          "description": "API route with proper error handling",
          "code": "import { NextRequest, NextResponse } from 'next/server';\nimport { z } from 'zod';\n\nconst schema = z.object({\n  name: z.string().min(1),\n  email: z.string().email()\n});\n\nexport async function POST(request: NextRequest) {\n  try {\n    const body = await request.json();\n    const data = schema.parse(body);\n    \n    const user = await createUser(data);\n    return NextResponse.json(user, { status: 201 });\n  } catch (error) {\n    if (error instanceof z.ZodError) {\n      return NextResponse.json(\n        { error: 'Validation failed' },\n        { status: 400 }\n      );\n    }\n    return NextResponse.json(\n      { error: 'Internal server error' },\n      { status: 500 }\n    );\n  }\n}"
        }
      }
    },
    "styling": {
      "framework": "Tailwind CSS",
      "approach": "Utility-first",
      "responsive": "Mobile-first design",
      "conventions": {
        "spacing": "Use Tailwind spacing scale",
        "colors": "Use design system colors",
        "typography": "Use Tailwind typography utilities"
      },
      "examples": {
        "card": {
          "description": "Card component with Tailwind styling",
          "code": "<div className=\"p-6 bg-white rounded-lg border border-gray-200 shadow-sm hover:shadow-md transition-shadow\">\n  <h3 className=\"text-lg font-semibold text-gray-900 mb-2\">{title}</h3>\n  <p className=\"text-gray-600\">{description}</p>\n</div>"
        }
      }
    }
  }
}

Patterns File (.github/copilot/patterns.json)

{
  "version": "2.0.1",
  "name": "Code Patterns",
  "description": "Common code patterns and architectural decisions",
  "patterns": {
    "dataFetching": {
      "name": "Data Fetching Patterns",
      "description": "How to fetch and handle data in different contexts",
      "examples": [
        {
          "name": "Server Component Data Fetching",
          "context": "Server components in app/ directory",
          "pattern": "async function with direct database/API calls",
          "code": "export default async function UserPage({ params }: { params: { id: string } }) {\n  const user = await prisma.user.findUnique({\n    where: { id: params.id }\n  });\n  \n  if (!user) {\n    notFound();\n  }\n  \n  return <UserProfile user={user} />;\n}"
        },
        {
          "name": "Client Component Data Fetching",
          "context": "Client components needing reactive data",
          "pattern": "React Query with custom hooks",
          "code": "function useUser(id: string) {\n  return useQuery({\n    queryKey: ['user', id],\n    queryFn: () => fetchUser(id),\n    enabled: !!id\n  });\n}\n\nexport default function UserProfile({ id }: { id: string }) {\n  const { data: user, isLoading, error } = useUser(id);\n  \n  if (isLoading) return <LoadingSpinner />;\n  if (error) return <ErrorMessage error={error} />;\n  \n  return <div>{user?.name}</div>;\n}"
        }
      ]
    },
    "formHandling": {
      "name": "Form Handling Patterns",
      "description": "Server actions and client-side form handling",
      "examples": [
        {
          "name": "Server Action Form",
          "context": "Forms with server-side processing",
          "pattern": "Server actions with revalidation",
          "code": "// app/actions/user.ts\n'use server'\n\nimport { revalidatePath } from 'next/cache';\nimport { redirect } from 'next/navigation';\n\nexport async function createUser(formData: FormData) {\n  const name = formData.get('name') as string;\n  const email = formData.get('email') as string;\n  \n  const user = await prisma.user.create({\n    data: { name, email }\n  });\n  \n  revalidatePath('/users');\n  redirect(`/users/${user.id}`);\n}\n\n// Component\nexport default function CreateUserForm() {\n  return (\n    <form action={createUser}>\n      <input name=\"name\" placeholder=\"Name\" required />\n      <input name=\"email\" type=\"email\" placeholder=\"Email\" required />\n      <button type=\"submit\">Create User</button>\n    </form>\n  );\n}"
        }
      ]
    },
    "errorHandling": {
      "name": "Error Handling Patterns",
      "description": "Consistent error handling across the application",
      "examples": [
        {
          "name": "Error Boundary",
          "context": "React error boundaries for component errors",
          "pattern": "Error boundary with fallback UI",
          "code": "'use client'\n\nimport { Component, ErrorInfo, ReactNode } from 'react';\n\ninterface Props {\n  children: ReactNode;\n  fallback?: ReactNode;\n}\n\ninterface State {\n  hasError: boolean;\n}\n\nexport class ErrorBoundary extends Component<Props, State> {\n  constructor(props: Props) {\n    super(props);\n    this.state = { hasError: false };\n  }\n  \n  static getDerivedStateFromError(): State {\n    return { hasError: true };\n  }\n  \n  componentDidCatch(error: Error, errorInfo: ErrorInfo) {\n    console.error('Error caught by boundary:', error, errorInfo);\n  }\n  \n  render() {\n    if (this.state.hasError) {\n      return this.props.fallback || <div>Something went wrong.</div>;\n    }\n    \n    return this.props.children;\n  }\n}"
        }
      ]
    }
  }
}

VS Code Workspace Configuration

Enhanced Settings (.vscode/settings.json)

{
  "github.copilot.enable": {
    "*": true,
    "plaintext": false,
    "markdown": true,
    "scminput": false
  },
  "github.copilot.advanced": {
    "debug.overrideEngine": "copilot-codex",
    "debug.testOverrideProxyUrl": "",
    "debug.overrideProxyUrl": "",
    "length": 500,
    "temperature": "",
    "top_p": "",
    "inlineSuggestEnable": true,
    "listCount": 10,
    "indentationMode": {
      "python": "tab",
      "javascript": "space",
      "typescript": "space"
    }
  },
  "files.associations": {
    "*.json": "jsonc"
  },
  "typescript.preferences.includePackageJsonAutoImports": "auto",
  "typescript.suggest.autoImports": true,
  "editor.inlineSuggest.enabled": true,
  "editor.suggest.preview": true,
  "workbench.editor.enablePreview": false
}

Tasks Configuration (.vscode/tasks.json)

{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "Update VDK Rules",
      "type": "shell",
      "command": "vdk",
      "args": ["init", "--overwrite"],
      "group": "build",
      "presentation": {
        "echo": true,
        "reveal": "always",
        "focus": false,
        "panel": "shared"
      },
      "problemMatcher": []
    },
    {
      "label": "Sync Copilot Configuration",
      "type": "shell", 
      "command": "vdk",
      "args": ["integrations", "--sync", "github-copilot"],
      "group": "build",
      "presentation": {
        "echo": true,
        "reveal": "always",
        "focus": false,
        "panel": "shared"
      }
    }
  ]
}

GitHub Copilot Features

Context-Aware Suggestions

With VDK integration, Copilot provides better suggestions:

Before VDK:

// User types: "create user component"
function UserComponent() {
  return <div>User</div>;
}

After VDK:

// User types: "create user component"
interface UserComponentProps {
  user: {
    id: string;
    name: string;
    email: string;
  };
  onEdit?: (user: User) => void;
}

export default function UserComponent({ user, onEdit }: UserComponentProps) {
  return (
    <div className="p-4 border rounded-lg hover:shadow-md transition-shadow">
      <h3 className="text-lg font-semibold text-gray-900">{user.name}</h3>
      <p className="text-gray-600">{user.email}</p>
      {onEdit && (
        <button 
          onClick={() => onEdit(user)}
          className="mt-2 px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600"
        >
          Edit
        </button>
      )}
    </div>
  );
}

Pattern Recognition

Copilot learns your project patterns:

// When creating API routes, Copilot suggests the established pattern:
import { NextRequest, NextResponse } from 'next/server';
import { z } from 'zod';
import { prisma } from '@/lib/db';

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 prisma.user.create({ 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 }
      );
    }
    return NextResponse.json(
      { error: 'Internal server error' },
      { status: 500 }
    );
  }
}

Configuration Options

Project-Level Configuration

{
  "copilot": {
    "enabled": true,
    "contextFiles": [
      ".github/copilot/instructions.json",
      ".github/copilot/guidelines.json"
    ],
    "fileTypes": {
      "typescript": {
        "enabled": true,
        "strictMode": true
      },
      "javascript": {
        "enabled": true,
        "preferTypeScript": true
      },
      "json": {
        "enabled": true,
        "validateSchema": true
      }
    },
    "suggestions": {
      "length": 500,
      "count": 10,
      "temperature": 0.2
    }
  }
}

Global User Settings

{
  "github.copilot.advanced": {
    "inlineSuggestEnable": true,
    "listCount": 10,
    "length": 500
  },
  "vdk": {
    "copilot": {
      "autoUpdate": true,
      "contextDepth": "comprehensive",
      "patternLearning": true
    }
  }
}

Advanced Usage

Custom Instructions

Create project-specific instructions:

{
  "customInstructions": {
    "api": {
      "pattern": "Always use Zod for validation, Prisma for database operations, and proper error handling",
      "example": "// See patterns.json for API route examples"
    },
    "components": {
      "pattern": "Use TypeScript interfaces, Tailwind CSS, and proper accessibility attributes",
      "example": "// See guidelines.json for component examples"
    },
    "testing": {
      "pattern": "Use Jest and React Testing Library with comprehensive test coverage",
      "example": "// Write tests for all public APIs and components"
    }
  }
}

File-Specific Context

Provide context based on file location:

{
  "fileContext": {
    "app/**/page.tsx": {
      "type": "Next.js Page Component",
      "preferServerComponent": true,
      "includeMetadata": true,
      "pattern": "async function with data fetching"
    },
    "app/api/**/route.ts": {
      "type": "Next.js API Route",
      "includeValidation": true,
      "includeErrorHandling": true,
      "pattern": "RESTful endpoint with proper status codes"
    },
    "components/**/*.tsx": {
      "type": "React Component",
      "includeProps": true,
      "includeAccessibility": true,
      "pattern": "Reusable component with TypeScript"
    }
  }
}

Team Synchronization

Share Copilot configuration with team:

# Include Copilot configuration in git
git add .github/copilot/ .vscode/

# Deploy to VDK Hub for team sharing
vdk deploy --team frontend-team

# Team members sync with:
vdk update
vdk integrations --sync github-copilot

Troubleshooting

Common Issues

Copilot not using project context:

# Verify configuration files exist
ls -la .github/copilot/

# Check VS Code settings
code .vscode/settings.json

# Restart VS Code and Copilot extension
# Command Palette: "Developer: Reload Window"

Suggestions not matching project patterns:

# Update VDK rules
vdk init --overwrite

# Regenerate Copilot configuration
vdk integrations --setup github-copilot --force

# Check if files are being read
# VS Code: Check Copilot logs in Output panel

Configuration not loading:

# Validate JSON syntax
jq . .github/copilot/instructions.json

# Check file permissions
ls -la .github/copilot/

# Reset configuration
vdk integrations --reset github-copilot

Debug Mode

Enable detailed logging:

# Debug VDK Copilot integration
VDK_DEBUG_COPILOT=true vdk integrations --setup github-copilot

# VS Code: Enable Copilot logging
# Command Palette: "GitHub Copilot: Collect Diagnostics"

Best Practices

1. Organize Configuration by Domain

.github/copilot/
├── instructions.json       # Main instructions
├── frontend.json          # Frontend-specific rules
├── backend.json           # Backend-specific rules  
├── testing.json           # Testing guidelines
└── deployment.json        # Deployment patterns

2. Use Specific Examples

Include concrete code examples in guidelines:

{
  "examples": {
    "good": {
      "description": "Proper TypeScript component",
      "code": "interface Props { user: User; }\nexport default function UserCard({ user }: Props) { ... }"
    },
    "avoid": {
      "description": "Avoid any types",
      "code": "function UserCard(props: any) { ... }"
    }
  }
}

3. Keep Instructions Updated

# Regular update workflow
vdk init --overwrite                    # Update project analysis
vdk integrations --sync github-copilot  # Sync Copilot config
git add .github/copilot/                # Version control changes

4. Use File-Specific Context

Tailor instructions to specific file types and locations:

{
  "context": {
    "app/api/": "Focus on server-side logic, validation, and error handling",
    "components/ui/": "Focus on reusable, accessible UI components",
    "app/": "Focus on Next.js App Router patterns and server components"
  }
}

Next Steps