- What is Context Engineering?
- The Context Engineering Framework
- Project Documentation & Context
- Three Types of Context
- Practical Tips for JavaScript Students
- JavaScript-Specific Context Examples
- Real-World JavaScript Example
- Getting Started: Your First JavaScript Project
- Resources to Explore
- Quick Reference: JavaScript Context Checklist
Context engineering is the practice of strategically organizing your code, files, comments, and project structure to provide AI coding assistants (like GitHub Copilot) with the most relevant and useful informationβso they can generate better, more accurate suggestions.
Think of it this way: You're not just writing code for browsers and compilers anymore. You're also writing for an AI that needs to understand your intent, constraints, and the broader context of what you're building.
"Context engineering is focused less on clever phrasing and more on bringing the right information (in the right format) to the LLM."
β Braintrust CEO Ankur Goyal
Information embedded directly in your source code:
- Meaningful names - Files, folders, variables, functions that describe their purpose
- Open files - Copilot can see tabs open in your editor
- Comments as prompts - Write comments that guide the AI
- Documentation blocks - JSDoc comments, clear function signatures
- Consistent patterns - Following established conventions across your project
- Standard formatting - Consistent style that AI recognizes
Example:
/**
* Validates user registration form data
* @param {Object} formData - User input from registration form
* @param {string} formData.email - User's email address
* @param {string} formData.password - User's password
* @param {string} formData.passwordConfirm - Password confirmation
* @returns {Object} Validation result with isValid boolean and errors array
*/
function validateRegistrationForm(formData) {
const errors = [];
// Check if email is valid format
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(formData.email)) {
errors.push('Please enter a valid email address');
}
// Check password length (minimum 8 characters)
if (formData.password.length < 8) {
errors.push('Password must be at least 8 characters');
}
// Check if passwords match
if (formData.password !== formData.passwordConfirm) {
errors.push('Passwords do not match');
}
return {
isValid: errors.length === 0,
errors: errors
};
}Persistent guidance that travels with your project:
.github/copilot-instructions.md- Project-wide patterns, preferences, constraintsinstructions.mdor.cursorrules- Alternative instruction files- Acts as "memory" across sessions
What to include in .github/copilot-instructions.md:
- Project Overview - What does this app do? Who's it for?
- Tech Stack - Vanilla JS? Node? What frameworks and libraries?
- Coding Guidelines - Naming conventions, style preferences, patterns
- Project Structure - Where things live in your repo
- Testing Requirements - What testing approach do you use?
Example structure:
# Task Manager App - JavaScript Project
A browser-based task management application for organizing daily to-dos.
Built with vanilla JavaScript, no frameworks.
## Tech Stack
- Vanilla JavaScript (ES6+)
- HTML5 & CSS3
- Local Storage for data persistence
- No external libraries or frameworks
## JavaScript Coding Guidelines
- Use ES6+ syntax (const/let, arrow functions, template literals)
- Semicolons required at end of statements
- Use strict equality (===) not loose equality (==)
- Prefer const over let, never use var
- Use JSDoc comments for all functions
- Handle errors with try-catch blocks
- Validate user input before processing
- Use descriptive variable names (camelCase)
## Code Organization
- One function does one thing (Single Responsibility)
- Keep functions under 20 lines when possible
- Extract magic numbers into named constants
- Use early returns to avoid deep nesting
## Project Structure
- `/js/`
- `app.js` - Main application logic
- `dom.js` - DOM manipulation functions
- `storage.js` - LocalStorage utilities
- `validation.js` - Input validation functions
- `/css/` - Stylesheets
- `index.html` - Main HTML file
## Data Handling
- Always validate data before saving to localStorage
- Use try-catch when parsing JSON
- Provide default values for missing data
- Clear localStorage on logout
## Error Handling
- Never use alert() for errors
- Display user-friendly error messages in the UI
- Log errors to console for debugging
- Validate all user inputs before processingStructured task context and project history:
- GitHub Issues - Clear problem statements with acceptance criteria
- Pull Requests - Proposed changes with rationale and discussion
- Issue templates - Standardized context structure
- Linked issues/PRs - Show relationships between work
- Creates traceable decision history that AI can reference
Example GitHub Issue:
## Add Task Priority Feature
### Description
Users should be able to assign priority levels (High, Medium, Low) to tasks.
### Acceptance Criteria
- [ ] Add priority dropdown to task creation form
- [ ] Store priority with task in localStorage
- [ ] Display priority badge on each task
- [ ] Allow filtering tasks by priority
- [ ] Use color coding: Red (High), Yellow (Medium), Green (Low)
### Technical Notes
- Add `priority` property to task object
- Update `createTask()` function in app.js
- Modify task template in dom.js
- Add CSS classes for priority badgesWhy this matters: When you write clear issues and PRs, Copilot can understand what you're trying to accomplish and suggest code that actually solves the problem you described.
Structured ways to invoke specific AI behaviors:
- Slash commands -
/edit,/fix,/doc,/explain - Chat keywords -
#file,#editor,#codebase,@workspace - Makes intent explicit rather than implicit
Examples in JavaScript projects:
/doc- Generate JSDoc comments for a function/fix- Fix bugs in selected code/explain- Explain what code does#file:storage.js- Reference your localStorage utilities#file:app.js #file:dom.js- Include multiple files for context
Example usage:
Prompt: "Create a function to filter tasks by status"
Context: #file:app.js #file:storage.js
Copilot will know about your existing task structure and storage methods!
Pre-built best practices and workflows:
- Skills - Domain-specific knowledge AI can reference
- Prompt files - Reusable templates for common tasks
- Expert templates built into the tool
Tools and data sources AI can access:
- MCP servers - Memory-keeper, Context7, filesystem access
- Copilot Spaces - Organized collections of context (repos, docs, files)
- Transforms AI from isolated assistant to connected agent
Understanding the boundaries:
- Context window - The actual token limit you're working within
- What fits, what gets prioritized, what gets truncated
- Strategic decisions about information timing and inclusion
Your project documentation (README.md, CONTRIBUTING.md, docs/ folder) provides important context, but there's a critical distinction:
Think of documentation this way:
| File | Audience | When Copilot Sees It |
|---|---|---|
| README.md | Humans (developers, users) | Only when explicitly referenced or open in tabs |
| .github/copilot-instructions.md | AI assistants | Always - automatically included in every request |
| docs/ folder | Humans (detailed specs) | Only when explicitly referenced or open in tabs |
| CONTRIBUTING.md | Humans (team members) | Only when explicitly referenced or open in tabs |
Option 1: Distill into .github/copilot-instructions.md
Take key information from your README and reformat it for AI:
# README.md (for humans)
## Architecture
This project follows the Model-View-Controller (MVC) pattern.
The application is organized with separate concerns for data
management, user interface, and business logic...
# .github/copilot-instructions.md (for AI)
## Code Organization - MVC Pattern
When creating new features:
- Models: /js/models/ - Data structures and storage logic
- Views: /js/views/ - DOM manipulation and templates
- Controllers: /js/controllers/ - Event handlers and business logic
- Naming: UserController.js, UserModel.js, UserView.jsOption 2: Explicitly reference docs in prompts
#file:README.md #file:docs/architecture.md
Create a new feature following our MVC patterns
Option 3: Open relevant docs as tabs
- If README.md is open, Copilot can see it (calculated context)
- Works best for smaller documentation files
- Remember to close unrelated docs when switching tasks
For a JavaScript project, create:
-
README.md - Traditional documentation
- Project overview
- Setup instructions
- How to run/build
- High-level architecture
- Contribution guidelines (if team project)
-
.github/copilot-instructions.md - AI-optimized context
- Concise coding standards
- Tech stack specifics
- Project structure (where files go)
- Common patterns to follow
- Data structure definitions
- Error handling approach
-
docs/ folder (optional, for complex projects)
- Detailed API documentation
- Architecture decision records
- Deployment guides
Your README explains the "what" and "why" for humans.
Your copilot-instructions.md explains the "how" for AI.
Example Comparison:
README.md might say:
## Error Handling Philosophy
We believe in graceful degradation and user-friendly error messages.
Never expose technical details to end users, but log everything for debugging.copilot-instructions.md should say:
## Error Handling Rules
- Use try-catch for all async operations
- Display errors in .error-message div, never alert()
- Log detailed errors: console.error('Function name:', error)
- Provide fallback values: return { data: null, error: error.message }The instructions file gives actionable, specific patterns that Copilot can follow.
Understanding these helps you provide better information to Copilot:
What Copilot gets without you doing anything:
- Files open in your editor tabs
- Current file and cursor position
- Recently edited files
- Your project's package.json (if present)
- README.md IF it's open in a tab
What Copilot figures out from patterns:
- File extension (
.js,.mjs,.cjs) - Coding patterns in your project (do you use arrow functions?)
- Import/export statements
- Consistent naming conventions (camelCase for variables)
What you deliberately give Copilot:
.github/copilot-instructions.mdfile (always active)- JSDoc comments describing function purpose
- Using
#file:storage.jsto reference specific files - Using
#file:README.mdto include your documentation - Clear function names and parameter descriptions
- Open relevant files - If working on
app.jsthat uses functions fromstorage.jsanddom.js, have all three open - Write descriptive comments first - Describe what you want before writing code
- Close unrelated files - Keep only pertinent files visible
- Use meaningful names -
filterTasksByPriority()is better thanfilter()
- Be specific - "Create a function that validates email format using regex" beats "check email"
- Provide examples - Show expected input/output
// Create a function to calculate task completion percentage // Input: array of task objects with 'completed' boolean // Output: percentage as number (0-100) // Example: [{completed: true}, {completed: false}, {completed: true}] β 66.67
- Break down complex tasks - Instead of "build a todo app," ask for:
- Function to add task
- Function to delete task
- Function to toggle task completion
- Function to filter tasks
- Give context in comments - Write what you want as a comment, then let Copilot suggest
Example - Writing comment as prompt:
// Create a function that takes an array of tasks and returns
// only the tasks that are not completed, sorted by priority (High β Low)
// Then let Copilot suggest the implementation- Create a
.github/copilot-instructions.mdfile for each project - Document your JavaScript conventions - Do you use semicolons? Template literals? Arrow functions?
- Specify your data structures - What does a task object look like?
- Include common patterns - How do you handle localStorage? Form validation?
/**
* Task Object Structure
*
* @typedef {Object} Task
* @property {string} id - Unique identifier (UUID)
* @property {string} text - Task description
* @property {boolean} completed - Completion status
* @property {string} priority - Priority level: 'high', 'medium', 'low'
* @property {Date} createdAt - Timestamp when task was created
* @property {Date|null} completedAt - Timestamp when task was completed
* @property {string[]} tags - Array of tag strings
*/// In your .github/copilot-instructions.md:
## Function Patterns We Use
### Array Operations
- Use .filter() for filtering
- Use .map() for transforming
- Use .reduce() for aggregating
- Avoid .forEach() when .map() or .filter() would work
### Async Operations
- Use async/await, not .then() chains
- Always wrap in try-catch
- Handle errors with user-friendly messages
### Event Listeners
- Use addEventListener, never onclick attributes
- Name handler functions descriptively: handleFormSubmit, handleDeleteClick
- Remove listeners when components are destroyed// storage.js - Document your module pattern
/**
* LocalStorage wrapper for task data
* All functions return null on error and log to console
*/
const STORAGE_KEY = 'taskManager_tasks';
export function saveTasks(tasks) { /* ... */ }
export function loadTasks() { /* ... */ }
export function clearTasks() { /* ... */ }function x(arr) {
let y = [];
for(let i=0; i<arr.length; i++) {
if(arr[i].z == true) {
y.push(arr[i]);
}
}
return y;
}/**
* Filters task array to return only completed tasks
* @param {Task[]} tasks - Array of task objects
* @returns {Task[]} Array containing only completed tasks
*/
function getCompletedTasks(tasks) {
return tasks.filter(task => task.completed === true);
}- Create
.github/copilot-instructions.mdin your project root - Write a short project overview - What JavaScript app are you building?
- Document your JavaScript preferences - ES6+? Semicolons? Arrow functions?
- Define your data structures - What do your objects look like?
- Specify common patterns - How do you handle errors? Async code?
# Weather Dashboard - JavaScript Project
A weather dashboard that displays current weather and 5-day forecast
for user-specified cities. Built with vanilla JavaScript and OpenWeather API.
## Tech Stack
- Vanilla JavaScript (ES6+)
- Fetch API for HTTP requests
- LocalStorage for saving favorite cities
- No frameworks or bundlers
## JavaScript Coding Standards
### Syntax Preferences
- Use semicolons at end of statements
- Use const by default, let only when reassignment needed
- Never use var
- Use template literals for string interpolation
- Use arrow functions for callbacks
- Use strict equality (===) always
### Naming Conventions
- Functions: camelCase (fetchWeatherData, displayForecast)
- Constants: UPPER_SNAKE_CASE (API_KEY, BASE_URL)
- Classes: PascalCase (WeatherCard, CityManager)
- Private functions: prefix with _ (_validateApiResponse)
### Error Handling
- Always use try-catch with async/await
- Never use alert() for errors
- Display errors in designated .error-message div
- Log detailed errors to console for debugging
- Provide fallback values for missing data
### API Integration
- Store API key in separate config file (not committed)
- Always validate API responses before using data
- Handle network errors gracefully
- Show loading states during API calls
- Cache API responses when appropriate
### Data Validation
- Validate all user inputs before processing
- Check for null/undefined before accessing properties
- Use optional chaining (?.) when safe
- Provide sensible defaults for missing data
## Project Structure
- `/js/`
- `app.js` - Main application entry point
- `api.js` - Weather API integration
- `storage.js` - LocalStorage utilities
- `dom.js` - DOM manipulation functions
- `utils.js` - Helper functions
- `config.js` - API keys and constants (gitignored)
- `/css/` - Stylesheets
- `index.html` - Main HTML
## Data Structures
### City Object
```javascript
{
name: string, // "New York"
country: string, // "US"
lat: number, // 40.7128
lon: number, // -74.0060
isFavorite: boolean
}{
temp: number, // Current temperature
feelsLike: number, // Feels like temperature
humidity: number, // Humidity percentage
description: string, // "Partly cloudy"
icon: string, // OpenWeather icon code
windSpeed: number, // Wind speed
timestamp: number // Unix timestamp
}async function fetchWeatherData(cityName) {
try {
const response = await fetch(`${API_URL}?q=${cityName}`);
if (!response.ok) throw new Error('City not found');
const data = await response.json();
return data;
} catch (error) {
console.error('Weather fetch failed:', error);
displayError('Unable to fetch weather data');
return null;
}
}// Always update DOM with dedicated functions
function displayWeather(weatherData) {
const container = document.getElementById('weather-display');
container.innerHTML = `
<div class="weather-card">
<h2>${weatherData.temp}Β°F</h2>
<p>${weatherData.description}</p>
</div>
`;
}// Always try-catch localStorage operations
function saveFavoriteCities(cities) {
try {
localStorage.setItem('favoriteCities', JSON.stringify(cities));
} catch (error) {
console.error('Storage failed:', error);
displayError('Unable to save favorite cities');
}
}- Provide context to GitHub Copilot
- Adding custom instructions
- Prompt engineering for Copilot Chat
- VS Code context engineering guide
- Want better AI outputs? Try context engineering - Start here!
- 5 tips for writing better custom instructions
- Using GitHub Copilot in your IDE: Tips, tricks, and best practices
- Awesome GitHub Copilot Customizations - Community examples you can use
Before asking Copilot for help, make sure you have:
β
Relevant files open - If working with tasks, have app.js, storage.js, dom.js open
β
Clear comment describing intent - What should this function do?
β
JSDoc comments - Document parameters and return types
β
Meaningful function names - calculateTaskStats() not calc()
β
Consistent code style - Match patterns already in your project
β
Example data structures - Show what your objects look like
β
Error handling preferences - How do you want errors handled?
β
.github/copilot-instructions.md - Project-wide context file
Context engineering isn't about being perfect. It's about being intentional with the information you provide to AI tools. Start small, iterate, and build better habits over time.
The goal: Help Copilot become a thoughtful coding partner, not just a code-completion tool.
Think of it like pair programming with someone who can't read your mindβyou need to communicate clearly!
Questions? Issues? Ideas?
Open a discussion in this Gist or ask in class!
Last updated: February 2026
Created for RVCC Web Development - JavaScript Course