Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
practicalswan avatar

Javascript Development

  • 14 installs
  • 7 repo stars
  • Updated August 2, 2026
  • practicalswan/agent-skills

javascript-development is a Claude Code skill for ai & agent building.

About

javascript-development is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.

  • javascript-development
  • AI & Agent Building
  • AI-coding skill

Javascript Development by the numbers

  • 14 all-time installs (skills.sh)
  • Ranked #11,275 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
  • Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/practicalswan/agent-skills --skill javascript-development

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs14
repo stars7
Last updatedAugust 2, 2026
Repositorypracticalswan/agent-skills

How do I helps with ai & agent building tasks.?

Helps with ai & agent building tasks.

Who is it for?

Best when you're working on ai & agent building and need structured help with javascript development.

Skip if: Teams with no ai & agent building needs, or anyone wanting a generic chat assistant without this specific workflow.

When should I use this skill?

When you need to helps with ai & agent building tasks., or when javascript-development is a claude code skill for ai & agent building.

What you get

Structured output aligned to javascript-development: javascript-development, AI & Agent Building.

Files

SKILL.mdMarkdownGitHub ↗

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":

1. Pass/fail: The Javascript Development implementation names the target runtime, framework version, and affected files. 2. Pass/fail: Build, lint, test, or equivalent local validation is run for the changed surface. 3. Pass/fail: Edge cases for errors, dependency drift, and environment differences are addressed or explicitly out of scope. 4. Pressure-test scenario: Apply the workflow to a change that passes happy-path tests but fails one boundary condition. 5. Success metric: Zero untested success claims; every implementation claim maps to a command or artifact.

Before and After Example

// Before
async function loadProfile() {
  const response = await fetch('/api/profile');
  return response.json();
}

// After
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

// Logical Assignment Operators (ES2021)
const obj = { a: 1 };
obj.a ??= 10;  // Only assign if obj.a is null/undefined
console.log(obj.a); // 1 (no change)

obj.b ??= 20;  // Assign if missing
console.log(obj.b); // 20

// Numeric Separators (ES2021)
const billion = 1_000_000_000;
const bytes = 0xff_13_ff; // Hex

// String methods (ES2022)
const str = "Hello World";
console.log(str.replaceAll('l', 'L')); // "HeLLo WorLd"
console.log(str.at(-1)); // "d" (last character)

// Array methods (ES2023)
const array = [1, 2, 3, 4, 5];
console.log(array.toReversed()); // [5, 4, 3, 2, 1]
console.log(array.toSorted()); // [1, 2, 3, 4, 5]
console.log(array.with(2, 99)); // [1, 2, 99, 4, 5] (non-mutating)

// Hashbang (for scripts)
#!/usr/bin/env node
console.log("Executable script!");

// Object.groupBy (ES2024)
const people = [
    { name: "Alice", age: 25, role: "admin" },
    { name: "Bob", age: 30, role: "user" },
    { name: "Charlie", age: 25, role: "user" },
];

const groupedByAge = Object.groupBy(people, ({ age }) => age);
console.log(groupedByAge);
// { 25: [{name: "Alice", age: 25, role: "admin"}, ...], 30: [...] }

const groupedByRole = Map.groupBy(people, ({ role }) => role);
console.log(groupedByRole);
// Map { "admin" => [...], "user" => [...] }

Template Literals & Tagged Templates

// Template literals with expressions
const firstName = "John";
const lastName = "Doe";
const greeting = `Hello, ${firstName} ${lastName}!`;

// Tagged template for custom formatting
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.`;
// "User <strong>John</strong> is online."

Destructuring & Spread

// Object destructuring
const user = { id: 1, name: "Alice", email: "alice@example.com", role: "admin" };
const { name, email, role: userRole } = user;
console.log(name, email, userRole); // "Alice", "alice@example.com", "admin"

// Array destructuring
const numbers = [1, 2, 3, 4, 5];
const [first, second, ...rest] = numbers;
console.log(first, second, rest); // 1, 2, [3, 4, 5]

// Destructuring in function parameters
function processRecipe({ title, difficulty, ingredients = [] }) {
    return `${title} (${difficulty}) - ${ingredients.length} ingredients`;
}

const recipe = { title: "Pasta", difficulty: "Medium", ingredients: ["Pasta", "Sauce"] };
processRecipe(recipe); // "Pasta (Medium) - 2 ingredients"

---

Part 2: Async Programming

Async/Await Patterns

// Basic async/await
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;
    }
}

// Parallel async operations with Promise.all
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.json()),
            fetch(`/api/recipes/${recipeId}/ingredients`).then(r => r.json()),
        ]);

        return { recipe, reviews, ingredients };
    } catch (error) {
        console.error("Failed to fetch recipe data:", error);
        throw error;
    }
}

// Race with Promise.any (ES2021)
async function fetchFromMultipleEndpoints() {
    const endpoints = [
        '/api/v1/users',
        '/api/v2/users',
        '/api/v3/users',
    ];

    try {
        const response = await Promise.any(
            endpoints.map(url => fetch(url).then(r => r.json()))
        );
        return response;
    } catch (error) {
        // All promises rejected
        console.error("All endpoints failed:", error);
        throw error;
    }
}

// All Settled (ES2020)
async function fetchWithStatus() {
    const requests = [
        fetch('/api/users'),
        fetch('/api/recipes'),
        fetch('/api/stats'),
    ];

    const results = await Promise.allSettled(requests);

    results.forEach((result, index) => {
        if (result.status === 'fulfilled') {
            console.log(`Request ${index} successful`);
        } else {
            console.error(`Request ${index} failed:`, result.reason);
        }
    });
}

Async Iterator (ES2018)

// Async generator function
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;

        // Add delay to avoid rate limiting
        await new Promise(resolve => setTimeout(resolve, 500));
    }
}

// Using async iterator
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)

// In ES modules, you can use await at top level
const config = await fetch('/api/config').then(r => r.json());
console.log('App config loaded:', config);

// This is useful for modules that need to load data before export
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

// Basic GET request
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();
}

// POST request with JSON body
async function createRecipe(recipeData) {
    const response = await fetch('/api/recipes', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Accept': 'application/json',
        },
        body: JSON.stringify(recipeData),
    });

    if (!response.ok) {
        const error = await response.json();
        throw new Error(error.message || 'Failed to create recipe');
    }

    return await response.json();
}

// PUT request with authentication
async function updateRecipe(recipeId, recipeData, token) {
    const response = await fetch(`/api/recipes/${recipeId}`, {
        method: 'PUT',
        headers: {
            'Content-Type': 'application/json',
            'Accept': 'application/json',
            'Authorization': `Bearer ${token}`,
        },
        body: JSON.stringify(recipeData),
    });

    if (!response.status === 200 && response.status !== 204) {
        throw new Error(`Update failed: ${response.status}`);
    }

    return await response.json();
}

// DELETE request
async function deleteRecipe(recipeId, token) {
    const response = await fetch(`/api/recipes/${recipeId}`, {
        method: 'DELETE',
        headers: {
            'Authorization': `Bearer ${token}`,
        },
    });

    if (!response.ok) {
        throw new Error(`Delete failed: ${response.status}`);
    }

    return true;
}

Axios Integration

import axios from 'axios';

// Create axios instance with default config
const api = axios.create({
    baseURL: '/api',
    timeout: 10000,
    headers: {
        'Content-Type': 'application/json',
    },
});

// Request interceptor for adding authentication
api.interceptors.request.use(
    (config) => {
        const token = localStorage.getItem('token');
        if (token) {
            config.headers.Authorization = `Bearer ${token}`;
        }
        return config;
    },
    (error) => Promise.reject(error)
);

// Response interceptor for error handling
api.interceptors.response.use(
    (response) => response,
    (error) => {
        if (error.response?.status === 401) {
            // Unauthorized - redirect to login
            localStorage.removeItem('token');
            window.location.href = '/login';
        }
        return Promise.reject(error);
    }
);

// API methods
export const recipesApi = {
    async getAll(filters = {}) {
        const response = await api.get('/recipes', { params: filters });
        return response.data;
    },

    async getById(recipeId) {
        const response = await api.get(`/recipes/${recipeId}`);
        return response.data;
    },

    async create(recipeData) {
        const response = await api.post('/recipes', recipeData);
        return response.data;
    },

    async update(recipeId, recipeData) {
        const response = await api.put(`/recipes/${recipeId}`, recipeData);
        return response.data;
    },

    async delete(recipeId) {
        const response = await api.delete(`/recipes/${recipeId}`);
        return response.data;
    },
};

Error Handling & Retry

// Retry utility with exponential backoff
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...`);

            // Exponential backoff: 1s, 2s, 4s
            const delay = Math.pow(2, attempt) * 1000;
            await new Promise(resolve => setTimeout(resolve, delay));
        }
    }

    throw new Error(`Failed after ${maxRetries} attempts: ${lastError.message}`);
}

// Usage with error handling
async function getRecipeWithRetry(recipeId) {
    try {
        const recipe = await fetchWithRetry(`/api/recipes/${recipeId}`);
        console.log('Recipe loaded:', recipe);
        return recipe;
    } catch (error) {
        console.error('Failed to load recipe:', error);
        // Show user-friendly error message
        return { error: true, message: 'Failed to load recipe. Please try again.' };
    }
}

---

Part 4: DOM Manipulation & Events

Element Selection & Manipulation

// Modern element selection
const button = document.querySelector('#submit-btn');
const items = document.querySelectorAll('.list-item');
const container = document.getElementById('container');
const firstChild = document.querySelector('.item:first-child');

// Using closest for event delegation
document.addEventListener('click', (event) => {
    const button = event.target.closest('.action-button');
    if (button) {
        console.log('Button clicked:', button.dataset.id);
    }
});

// Element creation and manipulation
function addRecipeToList(recipe) {
    const li = document.createElement('li');
    li.className = 'recipe-item';
    li.dataset.recipeId = recipe.id;

    li.innerHTML = `
        <h3>${recipe.title}</h3>
        <p>${recipe.description}</p>
        <button class="delete-btn">Delete</button>
    `;

    // Add event listener to delete button
    const deleteBtn = li.querySelector('.delete-btn');
    deleteBtn.addEventListener('click', () => deleteRecipe(recipe.id));

    // Append to container
    document.getElementById('recipe-list').appendChild(li);
}

// Element removal
function removeRecipeElement(recipeId) {
    const element = document.querySelector(`[data-recipe-id="${recipeId}"]`);
    if (element) {
        element.remove();
    }
}

Event Handling

// Form submission with validation
const form = document.getElementById('recipe-form');

form.addEventListener('submit', async (event) => {
    event.preventDefault(); // Prevent default form submission

    const formData = new FormData(form);
    const recipeData = {
        title: formData.get('title'),
        description: formData.get('description'),
        category: formData.get('category'),
        difficulty: formData.get('difficulty'),
    };

    // Validation
    if (!recipeData.title || recipeData.title.length < 3) {
        showError('Title is required and must be at least 3 characters');
        return;
    }

    try {
        // Submit to API
        const response = await fetch('/api/recipes', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(recipeData),
        });

        if (response.ok) {
            showSuccess('Recipe created successfully!');
            form.reset();
        }
    } catch (error) {
        showError('Failed to create recipe: ' + error.message);
    }
});

// Debounce for search input
let searchTimeout;
const searchInput = document.getElementById('search');

searchInput.addEventListener('input', (event) => {
    clearTimeout(searchTimeout);

    searchTimeout = setTimeout(() => {
        const query = event.target.value;
        if (query.length >= 2) {
            performSearch(query);
        }
    }, 300); // Wait 300ms after user stops typing
});

// Intersection Observer for infinite scroll
const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
        if (entry.isIntersecting) {
            loadMoreRecipes();
        }
    });
}, {
    root: null,
    threshold: 0.1,
});

// Observe sentinel element
const sentinel = document.getElementById('load-more-sentinel');
observer.observe(sentinel);

---

Part 5: Data Structures & Algorithms

Array Methods

// map - Transform array
const recipes = [
    { title: 'Pasta', difficulty: 'Medium' },
    { title: 'Salad', difficulty: 'Easy' },
];

const titles = recipes.map(recipe => recipe.title);
// ['Pasta', 'Salad']

// filter - Select elements
const easyRecipes = recipes.filter(recipe => recipe.difficulty === 'Easy');
// [{ title: 'Salad', difficulty: 'Easy' }]

// reduce - Aggregate array
const wordCount = recipes.reduce((count, recipe) => {
    return count + recipe.title.split(' ').length;
}, 0);

// find - Find first matching element
const pasta = recipes.find(recipe => recipe.title.includes('Pasta'));

// some - Check if any matches
const hasMediumDifficulty = recipes.some(recipe => recipe.difficulty === 'Medium'); // true

// every - Check if all match
const allHaveTitles = recipes.every(recipe => recipe.title.length > 0); // true

// sort - Sort array
const sortedRecipes = [...recipes].sort((a, b) =>
    a.title.localeCompare(b.title)
);

// flatMap - Map and flatten
const nested = [[1, 2], [3, 4]];
const flattened = nested.flatMap(arr => arr); // [1, 2, 3, 4]

Object Methods

// Object.keys, Object.values, Object.entries
const user = {
    id: 1,
    name: 'Alice',
    email: 'alice@example.com',
    role: 'admin',
};

const keys = Object.keys(user); // ['id', 'name', 'email', 'role']
const values = Object.values(user); // [1, 'Alice', 'alice@example.com', 'admin']
const entries = Object.entries(user);
// [['id', 1], ['name', 'Alice'], ['email', 'alice@example.com'], ['role', 'admin']]

// Object.fromEntries - Convert back to object
const filtered = Object.fromEntries(
    Object.entries(user).filter(([key]) => key !== 'role')
);
// { id: 1, name: 'Alice', email: 'alice@example.com' }

// Object.freeze - Make immutable
const config = Object.freeze({ apiUrl: '/api/v1' });
config.apiUrl = '/api/v2'; // Error in strict mode

Set and Map

// Set - Unique values
const tags = new Set(['Easy', 'Medium', 'Medium', 'Hard']);
console.log(tags.size); // 3

tags.add('Easy');
 console.log(tags.has('Medium')); // true

tags.delete('Hard');

const uniqueTags = Array.from(tags); // ['Easy', 'Medium']

// Map - Key-value pairs with any type
const userRoles = new Map();
userRoles.set(1, 'admin');
userRoles.set(2, 'user');
userRoles.set('alice', 'editor');

console.log(userRoles.get(1)); // 'admin'
console.log(userRoles.has('alice')); // true

const roles = Array.from(userRoles.entries());
// [[1, 'admin'], [2, 'user'], ['alice', 'editor']]

---

Part 6: Date & Time

Date Operations

// Creating dates
const now = new Date();
const specificDate = new Date('2024-02-01');
const fromTimestamp = new Date(17068896000000);

// Date formatting
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);
}
// "February 1, 2024 at 12:00 PM"

// Relative time (e.g., "2 hours ago")
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 = Math.floor(minutes / 60);
    const days = Math.floor(hours / 24);

    if (seconds < 60) return 'just now';
    if (minutes < 60) return `${minutes} minute${minutes > 1 ? 's' : ''} ago`;
    if (hours < 24) return `${hours} hour${hours > 1 ? 's' : ''} ago`;
    return `${days} day${days > 1 ? 's' : ''} ago`;
}

// Date manipulation
function addDays(date, days) {
    const result = new Date(date);
    result.setDate(result.getDate() + days);
    return result;
}

function isSameDay(date1, date2) {
    return date1.toDateString() === date2.toDateString();
}

---

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();
        } catch (error) {
            console.error('Failed to clear localStorage:', error);
        }
    }

    static has(key) {
        return localStorage.getItem(key) !== null;
    }
}

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));
    }
}

// Usage
const stateManager = new StateManager({
    user: null,
    recipes: [],
    loading: false,
});

stateManager.subscribe((state) => {
    console.log('State updated:', state);
    // Update UI
});

stateManager.setState({ recipes: [...] });

---

Part 8: Utility Functions

Common Utilities

// Debounce
function debounce(func, wait) {
    let timeout;
    return function executedFunction(...args) {
        const later = () => {
            clearTimeout(timeout);
            func(...args);
        };
        clearTimeout(timeout);
        timeout = setTimeout(later, wait);
    };
}

// Throttle
function throttle(func, limit) {
    let inThrottle;
    return function(...args) {
        if (!inThrottle) {
            func.apply(this, args);
            inThrottle = true;
            setTimeout(() => inThrottle = false, limit);
        }
    };
}

// Random ID
function generateId() {
    return Math.random().toString(36).substr(2, 9);
}

// Slugify text
function slugify(text) {
    return text
        .toString()
        .toLowerCase()
        .trim()
        .replace(/\s+/g, '-')
        .replace(/[^\w\-]+/g, '');
}

// Format number with commas
function formatNumber(num) {
    return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}

// Truncate text
function truncate(text, maxLength) {
    return text.length > maxLength
        ? text.substring(0, maxLength - 3) + '...'
        : text;
}

---

JavaScript Development Best Practices

Code Quality

  • [ ] Use const and let instead of var
  • [ ] Use strict mode ('use strict')
  • [ ] Add JSDoc comments for functions
  • [ ] Use modern ES2024+ features
  • [ ] Avoid global variables
  • [ ] Use meaningful variable and function names

Asynchronous Code

  • [ ] Prefer async/await over .then() chains
  • [ ] Handle errors with try-catch
  • [ ] Use Promise.all for parallel operations
  • [ ] Implement retry logic for network requests
  • [ ] Provide loading states for async operations

DOM & Events

  • [ ] Use event delegation for dynamic content
  • [ ] Clean up event listeners to prevent memory leaks
  • [ ] Use dataset for custom data attributes
  • [ ] Validate form input before submission
  • [ ] Use debouncing/throttling for rapid events

Performance

  • [ ] Minimize DOM manipulation
  • [ ] Use document fragments for bulk inserts
  • [ ] Implement lazy loading for images/lists
  • [ ] Cache expensive computations
  • [ ] Use requestAnimationFrame for animations

Security

  • [ ] Sanitize user input to prevent XSS
  • [ ] Use HTTPS for API calls
  • [ ] Store tokens securely (HttpOnly cookies)
  • [ ] Validate data from localStorage
  • [ ] Implement CSRF protection

---

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

---

<!-- PORTABILITY:START -->

Cross-Client Portability

This skill is written to stay usable across GitHub Copilot, Claude Code, Codex, and Gemini CLI.

  • GitHub Copilot: keep the folder in a Copilot-visible skill or plugin path, or wrap the workflow as project instructions if the host does not support portable skill folders directly.
  • Claude Code: keep the folder in a local skills directory or a compatible plugin or marketplace source.
  • Codex: install or sync the folder into $CODEX_HOME/skills/<skill-name> and restart Codex after major changes.
  • Gemini CLI: this repository generates a project command named /skills:javascript-development from this skill. Rebuild commands with python scripts/export-gemini-skill.py javascript-development and then run /commands reload inside Gemini CLI.

<!-- PORTABILITY:END -->

<!-- MCP:START -->

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.

<!-- MCP:END -->

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.

Related skills

FAQ

What does javascript-development do?

javascript-development is a Claude Code skill for ai & agent building.

When should I use javascript-development?

When you need to helps with ai & agent building tasks., or when javascript-development is a claude code skill for ai & agent building.

What are the main capabilities?

javascript-development; AI & Agent Building; AI-coding skill.

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.