| name | javascript-development |
| version | 2.0 |
| last_updated | 2026-08-29T00:00:00.000Z |
| tags | ["javascript","development","testing","quality","automation"] |
| description | JavaScript/TypeScript ES2024+, async/await, DOM manipulation, Node.js, and API integration. Use when writing vanilla JS/TS code, working with REST/fetch APIs, implementing frontend logic, or configuring JS build tools. |
JavaScript Development
Optimized for ECMAScript 2024+, Node.js 22+, TypeScript 5.5+, and modern browser or server-first JavaScript runtimes.
Expert guidance for writing modern JavaScript code with ES2024+ features, async programming patterns, DOM manipulation, API integration, and best practices following official JavaScript resources at https://developer.mozilla.org/en-US/docs/Web/JavaScript.
- Leverage native parallel subagent dispatch and 200k+ context windows where available.
Anti-Patterns
- Copying outdated browser or framework patterns: Deprecated APIs and old workarounds add complexity immediately.
- Skipping abort, timeout, or response checks in async code: Network paths fail at the edges first, not on the happy path.
- Treating accessibility as a final polish pass: Markup and state shape are harder to fix after the component contract is set.
Verification Protocol
Before claiming "skill applied successfully":
- Pass/fail: The Javascript Development implementation names the target runtime, framework version, and affected files.
- Pass/fail: Build, lint, test, or equivalent local validation is run for the changed surface.
- Pass/fail: Edge cases for errors, dependency drift, and environment differences are addressed or explicitly out of scope.
- Pressure-test scenario: Apply the workflow to a change that passes happy-path tests but fails one boundary condition.
- Success metric: Zero untested success claims; every implementation claim maps to a command or artifact.
Before and After Example
async function loadProfile() {
const response = await fetch('/api/profile');
return response.json();
}
export async function loadProfile(signal) {
const response = await fetch('/api/profile', { signal });
if (!response.ok) {
throw new Error(`Profile request failed: ${response.status}`);
}
return response.json();
}
Adds cancellation and explicit response validation so network failures do not masquerade as parsing bugs.
Activation Conditions
Use symptom -> action triggers: when one matches, apply this skill and verify with the protocol below.
Core JavaScript Development:
- Writing modern JavaScript with ES2024+ features
- Creating React components and hooks
- Working with DOM manipulation and events
- Implementing forms and user interactions
- Managing state in frontend applications
Asynchronous Programming:
- Using Promises and async/await patterns
- Fetching data from APIs
- Handling loading and error states
- Implementing retry mechanisms
- Working with concurrent operations
Data Handling:
- Manipulating arrays and objects
- Using modern array methods (map, filter, reduce, find)
- Working with JSON data
- LocalStorage and session management
- Data transformation and formatting
API Integration:
- Fetch API for HTTP requests
- Axios for advanced HTTP client features
- RESTful API design and consumption
- Authentication with JWT tokens
- CORS and error handling
Part 1: Modern JavaScript (ES2024+)
New Features & Syntax
const obj = { a: 1 };
obj.a ??= 10;
console.log(obj.a);
obj.b ??= 20;
console.log(obj.b);
const billion = 1_000_000_000;
const bytes = 0xff_13_ff;
const str = "Hello World";
console.log(str.replaceAll('l', 'L'));
console.log(str.at(-1));
const array = [1, 2, 3, 4, 5];
console.log(array.toReversed());
console.log(array.());
.(array.(, ));
#!bin/env node
.();
people = [
{ : , : , : },
{ : , : , : },
{ : , : , : },
];
groupedByAge = .(people, age);
.(groupedByAge);
groupedByRole = .(people, role);
.(groupedByRole);
Template Literals & Tagged Templates
const firstName = "John";
const lastName = "Doe";
const greeting = `Hello, ${firstName} ${lastName}!`;
function highlight(strings, ...values) {
return strings.reduce((result, str, i) => {
return result + str + (values[i] ? `<strong>${values[i]}</strong>` : '');
}, '');
}
const message = highlight`User ${firstName} is online.`;
Destructuring & Spread
const user = { id: 1, name: "Alice", email: "alice@example.com", role: "admin" };
const { name, email, role: userRole } = user;
console.log(name, email, userRole);
const numbers = [1, 2, 3, 4, 5];
const [first, second, ...rest] = numbers;
console.log(first, second, rest);
function processRecipe({ title, difficulty, ingredients = [] }) {
return `${title} (${difficulty}) - ${ingredients.length} ingredients`;
}
const recipe = { title: "Pasta", difficulty: "Medium", ingredients: ["Pasta", "Sauce"] };
processRecipe(recipe);
Part 2: Async Programming
Async/Await Patterns
async function fetchUser(userId) {
try {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const user = await response.json();
return user;
} catch (error) {
console.error("Failed to fetch user:", error);
throw error;
}
}
async function fetchRecipeData(recipeId) {
try {
const [recipe, reviews, ingredients] = await Promise.all([
fetch(`/api/recipes/${recipeId}`).then(r => r.json()),
fetch(`/api/recipes/${recipeId}/reviews`).then(r => r.()),
().( r.()),
]);
{ recipe, reviews, ingredients };
} (error) {
.(, error);
error;
}
}
() {
endpoints = [
,
,
,
];
{
response = .(
endpoints.( (url).( r.()))
);
response;
} (error) {
.(, error);
error;
}
}
() {
requests = [
(),
(),
(),
];
results = .(requests);
results.( {
(result. === ) {
.();
} {
.(, result.);
}
});
}
Async Iterator (ES2018)
async function* fetchPaginatedUsers(pageSize = 10) {
let page = 1;
let hasMore = true;
while (hasMore) {
const response = await fetch(`/api/users?page=${page}&limit=${pageSize}`);
const { users, totalPages } = await response.json();
yield* users;
page++;
hasMore = page <= totalPages;
await new Promise(resolve => setTimeout(resolve, 500));
}
}
async function getAllUsers() {
const userIterator = fetchPaginatedUsers();
const allUsers = [];
for await (const user of userIterator) {
allUsers.push(user);
console.log(`Fetched: ${user.name}`);
}
return allUsers;
}
Top-level Await (ES2022)
const config = await fetch('/api/config').then(r => r.json());
console.log('App config loaded:', config);
export const recipes = await fetch('/api/recipes').then(r => r.json());
export const users = await fetch('/api/users').then(r => r.json());
Part 3: API Integration
Fetch API Patterns
async function getRecipes(filters = {}) {
const queryParams = new URLSearchParams(filters);
const url = `/api/recipes?${queryParams}`;
const response = await fetch(url, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
});
if (!response.ok) {
throw new Error(`Request failed: ${response.status}`);
}
return await response.json();
}
async function createRecipe(recipeData) {
const response = await fetch('/api/recipes', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
body: JSON.(recipeData),
});
(!response.) {
error = response.();
(error. || );
}
response.();
}
() {
response = (, {
: ,
: {
: ,
: ,
: ,
},
: .(recipeData),
});
(!response. === && response. !== ) {
();
}
response.();
}
() {
response = (, {
: ,
: {
: ,
},
});
(!response.) {
();
}
;
}
Axios Integration
import axios from 'axios';
const api = axios.create({
baseURL: '/api',
timeout: 10000,
headers: {
'Content-Type': 'application/json',
},
});
api.interceptors.request.use(
(config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => Promise.reject(error)
);
api.interceptors.response.use(
(response) => response,
(error) => {
if (error.response?.status === 401) {
localStorage.removeItem('token');
.. = ;
}
.(error);
}
);
recipesApi = {
() {
response = api.(, { : filters });
response.;
},
() {
response = api.();
response.;
},
() {
response = api.(, recipeData);
response.;
},
() {
response = api.(, recipeData);
response.;
},
() {
response = api.();
response.;
},
};
Error Handling & Retry
async function fetchWithRetry(url, options = {}, maxRetries = 3) {
let lastError;
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const response = await fetch(url, options);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return response.json();
} catch (error) {
lastError = error;
console.log(`Attempt ${attempt + 1} failed, retrying...`);
const delay = Math.pow(2, attempt) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
}
throw new Error(`Failed after ${maxRetries} attempts: ${lastError.message}`);
}
() {
{
recipe = ();
.(, recipe);
recipe;
} (error) {
.(, error);
{ : , : };
}
}
Part 4: DOM Manipulation & Events
Element Selection & Manipulation
const button = document.querySelector('#submit-btn');
const items = document.querySelectorAll('.list-item');
const container = document.getElementById('container');
const firstChild = document.querySelector('.item:first-child');
document.addEventListener('click', (event) => {
const button = event.target.closest('.action-button');
if (button) {
console.log('Button clicked:', button.dataset.id);
}
});
function addRecipeToList(recipe) {
const li = document.createElement('li');
li.className = 'recipe-item';
li.dataset.recipeId = recipe.id;
li.innerHTML = `
<h3></h3>
<p></p>
<button class="delete-btn">Delete</button>
`;
deleteBtn = li.();
deleteBtn.(, (recipe.));
.().(li);
}
() {
element = .();
(element) {
element.();
}
}
Event Handling
const form = document.getElementById('recipe-form');
form.addEventListener('submit', async (event) => {
event.preventDefault();
const formData = new FormData(form);
const recipeData = {
title: formData.get('title'),
description: formData.get('description'),
category: formData.get('category'),
difficulty: formData.get('difficulty'),
};
if (!recipeData.title || recipeData.title.length < 3) {
showError('Title is required and must be at least 3 characters');
return;
}
try {
const response = await fetch('/api/recipes', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: .(recipeData),
});
(response.) {
();
form.();
}
} (error) {
( + error.);
}
});
searchTimeout;
searchInput = .();
searchInput.(, {
(searchTimeout);
searchTimeout = ( {
query = event..;
(query. >= ) {
(query);
}
}, );
});
observer = ( {
entries.( {
(entry.) {
();
}
});
}, {
: ,
: ,
});
sentinel = .();
observer.(sentinel);
Part 5: Data Structures & Algorithms
Array Methods
const recipes = [
{ title: 'Pasta', difficulty: 'Medium' },
{ title: 'Salad', difficulty: 'Easy' },
];
const titles = recipes.map(recipe => recipe.title);
const easyRecipes = recipes.filter(recipe => recipe.difficulty === 'Easy');
const wordCount = recipes.reduce((count, recipe) => {
return count + recipe.title.split(' ').length;
}, 0);
const pasta = recipes.find(recipe => recipe.title.includes('Pasta'));
const hasMediumDifficulty = recipes.some(recipe => recipe.difficulty === 'Medium');
allHaveTitles = recipes.( recipe.. > );
sortedRecipes = [...recipes].(
a..(b.)
);
nested = [[, ], [, ]];
flattened = nested.( arr);
Object Methods
const user = {
id: 1,
name: 'Alice',
email: 'alice@example.com',
role: 'admin',
};
const keys = Object.keys(user);
const values = Object.values(user);
const entries = Object.entries(user);
const filtered = Object.fromEntries(
Object.entries(user).filter(([key]) => key !== 'role')
);
const config = Object.freeze({ apiUrl: '/api/v1' });
config.apiUrl = '/api/v2';
Set and Map
const tags = new Set(['Easy', 'Medium', 'Medium', 'Hard']);
console.log(tags.size);
tags.add('Easy');
console.log(tags.has('Medium'));
tags.delete('Hard');
const uniqueTags = Array.from(tags);
const userRoles = new Map();
userRoles.set(1, 'admin');
userRoles.set(2, 'user');
userRoles.set('alice', 'editor');
console.log(userRoles.get(1));
console.log(userRoles.has('alice'));
const roles = Array.from(userRoles.());
Part 6: Date & Time
Date Operations
const now = new Date();
const specificDate = new Date('2024-02-01');
const fromTimestamp = new Date(17068896000000);
function formatDate(date) {
const options = {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
};
return new Intl.DateTimeFormat('en-US', options).format(date);
}
function getRelativeTime(date) {
const now = new Date();
const diff = now - date;
const seconds = Math.floor(diff / 1000);
const minutes = Math.floor(seconds / 60);
const hours = .(minutes / );
days = .(hours / );
(seconds < ) ;
(minutes < ) ;
(hours < ) ;
;
}
() {
result = (date);
result.(result.() + days);
result;
}
() {
date1.() === date2.();
}
Part 7: LocalStorage & State Management
LocalStorage Wrapper
class StorageManager {
static set(key, value) {
try {
localStorage.setItem(key, JSON.stringify(value));
} catch (error) {
console.error('Failed to save to localStorage:', error);
}
}
static get(key, defaultValue = null) {
try {
const item = localStorage.getItem(key);
return item ? JSON.parse(item) : defaultValue;
} catch (error) {
console.error('Failed to read from localStorage:', error);
return defaultValue;
}
}
static remove(key) {
try {
localStorage.removeItem(key);
} catch (error) {
console.error('Failed to remove from localStorage:', error);
}
}
static clear() {
try {
localStorage.clear();
} (error) {
.(, error);
}
}
() {
.(key) !== ;
}
}
State Management (Simple)
class StateManager {
constructor(initialState = {}) {
this.state = initialState;
this.listeners = [];
}
setState(newState) {
this.state = { ...this.state, ...newState };
this.notify();
}
subscribe(listener) {
this.listeners.push(listener);
listener(this.state);
}
notify() {
this.listeners.forEach(listener => listener(this.state));
}
}
const stateManager = new StateManager({
user: null,
recipes: [],
loading: false,
});
stateManager.subscribe((state) => {
console.log('State updated:', state);
});
stateManager.({ : [...] });
Part 8: Utility Functions
Common Utilities
function debounce(func, wait) {
let timeout;
return function executedFunction(...args) {
const later = () => {
clearTimeout(timeout);
func(...args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
function throttle(func, limit) {
let inThrottle;
return function(...args) {
if (!inThrottle) {
func.apply(this, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
function generateId() {
return Math.random().toString(36).substr(2, 9);
}
function slugify(text) {
return text
.toString()
.()
.()
.(, )
.(, );
}
() {
num.().(, );
}
() {
text. > maxLength
? text.(, maxLength - ) +
: text;
}
JavaScript Development Best Practices
Code Quality
Asynchronous Code
DOM & Events
Performance
Security
Modern Component and Testing Examples
Server Components
export default async function ProfileCard({ userId }) {
const user = await getUser(userId);
return <section>{user.name}</section>;
}
Error Boundaries
import { ErrorBoundary } from 'react-error-boundary';
<ErrorBoundary fallbackRender={() => <p>Something went wrong.</p>}>
<ProfileDashboard />
</ErrorBoundary>
Accessibility Testing Tools
import { axe } from 'jest-axe';
test('search form has no obvious accessibility violations', async () => {
const { container } = render(<SearchForm />);
expect(await axe(container)).toHaveNoViolations();
});
Common Pitfalls
- Copying outdated browser or framework patterns: Deprecated APIs and unnecessary workarounds add complexity immediately.
- Skipping response and abort handling: Network code fails in edge cases first, so the happy path alone is misleading.
- Treating accessibility as post-processing: Component structure is harder to fix later if semantics were not built in from the start.
References & Resources
Official Documentation
Libraries & Tools
Learning Resources
Cross-Client Portability
This skill is written to stay usable across GitHub Copilot, Claude Code, and Codex.
- GitHub Copilot: keep the folder in a Copilot-visible skill path or wrap the
workflow in project instructions when folder discovery is unavailable.
- Claude Code: keep the folder in a local skills directory or a compatible plugin source.
- Codex: install or sync the folder into
$CODEX_HOME/skills/javascript-development and restart Codex after major changes.
MCP Availability And Fallback
Preferred MCP Server: None required
- Fallback prompt: "Use the JavaScript Development skill without MCP. Rely on the local
SKILL.md, bundled references or scripts, and manual verification. Show the exact commands, evidence, and final checks you used before concluding."
- If the current host does not expose a matching server, use the bundled references, scripts, native toolchain, and manual workflow already described in this skill.
- Treat direct local verification, rendered output, logs, tests, or screenshots as the fallback evidence path before completion.
Related Skills
- react-development: Use it when the workflow also needs React component architecture and client or server boundaries.
- nextjs-development: Use it when the workflow also needs Next.js App Router and server-first React patterns.
- vite-development: Use it when the workflow also needs Vite build and development-server configuration.
- web-testing: Use it when the workflow also needs browser and end-to-end testing evidence.