Core JavaScript language conventions, idioms, and modern practices. Invoke whenever task involves any interaction with JavaScript code — writing, reviewing, refactoring, debugging, or understanding .js/.jsx files and JavaScript projects.
Applies modern JavaScript best practices for writing, reviewing, and refactoring .js/.jsx code.
npx claudepluginhub xobotyi/cc-foundryThis skill inherits all available tools. When active, it can use any tool Claude has access to.
references/async.mdreferences/functions.mdreferences/idioms.mdreferences/jsdoc.mdreferences/modules.mdreferences/objects-and-arrays.mdClarity is the highest JavaScript virtue. If your code requires a comment to explain its control flow, rewrite it.
JavaScript rewards explicit, readable code. Prefer boring patterns that are easy to understand over clever tricks that save characters.
| Topic | Reference | Contents |
|---|---|---|
| Functions, closures, composition | references/functions.md | Arrow function examples, closure patterns, early return, parameter destructuring |
| Async patterns, error handling, concurrency | references/async.md | Promise.all/race/any examples, cancellation, custom error classes, for-await |
| Objects, arrays, iteration, Map/Set | references/objects-and-arrays.md | Iteration decision table, destructuring patterns, immutable updates, generators |
| ES modules, imports, barrel files | references/modules.md | Import ordering, barrel file rationale, directory import pitfalls, dynamic imports |
| JSDoc typing, full tag catalog | references/jsdoc.md | Full tag reference (@callback, @template, @enum), type assertions, class modifiers |
| General JS idioms and edge cases | references/idioms.md | Variable/naming examples, equality coercion table, modern syntax patterns |
const by default. Use let only when reassignment is required. Never var.const prevents reassignment, not mutation. Objects and arrays declared with const
can still be mutated.let/const are block-scoped; var is function-scoped and
hoists — this causes bugs in loops and conditionals.const a = 1, b = 2.const first, then let.| Entity | Style | Examples |
|---|---|---|
| Variables, functions | camelCase | userName, fetchData |
| Classes, constructors | PascalCase | UserService, HttpClient |
| True compile-time constants | SCREAMING_SNAKE_CASE | MAX_RETRIES, API_BASE_URL |
| Private fields/methods | # prefix (class) | #count, #validate() |
| Booleans | is/has/can/should prefix | isValid, hasAccess |
| File names | kebab-case or camelCase | user-service.js, userService.js |
userCount not n. Short names (i, x) only in tiny scopes
(loop indices, simple arrow callbacks).url, id, err, ctx, req, res — universally
understood. Avoid all others.car.make not car.carMake.getUser() everywhere, not getUserInfo() / getClientData() / getCustomerRecord().=== and !==. Never == except for value == null (checks both null
and undefined).?? over || for defaults — || treats 0, "", false as falsy.?. for optional access. Don't overuse — missing data you expect should throw, not
silently return undefined.false, 0, -0, 0n, "", null, undefined, NaN.
Everything else is truthy, including [], {}, and "0".// OK — fits on one line
const label = isActive ? 'Active' : 'Inactive';
// OK — each branch on its own line
const label = isActive
? buildActiveLabel(user)
: buildInactiveLabel(user);
Any ternary that doesn't fit one of these two patterns must be rewritten as
if/else or early return.if/else, early returns,
or a lookup object.`Hello, ${name}`. Don't use
template literals for strings without interpolation — use plain quotes.{ ...obj } and [...arr]. Never Object.assign.const { id, ...rest } = user.{ name, age } not { name: name, age: age }. Group
shorthand properties at the top of object literals.{ [key]: value, [${key}Date]: new Date() }.opts.timeout ??= 5000 (assign if nullish),
opts.name ||= "default" (assign if falsy), opts.handler &&= wrap(opts.handler)
(assign if truthy).this binding is needed.this — they do NOT have their own this. Never
use arrow functions as object methods or on prototypes.|| or manual checks. Defaults are evaluated left-to-right
and can reference earlier params.arguments object. arguments is array-like, not a real Array.async/await over .then() chains for sequential operations.await promises. Missing await = floating promise = silent failures.return await only inside try blocks where you need to catch the awaited error.
Otherwise just return promise — no need for async wrapper.Promise.all for independent parallel work. Rejects on first rejection.Promise.allSettled when all results matter regardless of individual failures.Promise.race for timeouts. Promise.any for fallbacks (rejects only when
ALL reject).Promise.all(items.map(...)) for parallel.
Use a concurrency limiter (e.g. p-map) for large arrays.Error objects, never strings or plain objects — strings lose stack traces.Error, set
this.name, add context properties.catch must handle, rethrow, or report. Empty catch
blocks hide bugs. console.log(err) alone is not handling.await
in try/catch — only where you need to handle at that level..catch() to non-awaited promise chains. Unhandled rejections crash Node.js.
Fire-and-forget: fetchData().catch(reportError).new Promise() to wrap callback-based APIs. Most async code should compose
existing promises with async/await.AbortController for cancellable async operations: pass { signal } to fetch
and other APIs.for await...of for async iterables (streams, async generators).import/export for all new code. CommonJS (require) is
legacy — use only when runtime requires it.let bindings. Export accessor functions instead:
export function getCount() not export let count.node:fs), external
(express), internal (./utils)."./user.js", not "./user".
Extensionless imports vary across runtimes.index.js.index.js re-exports create indirection and hurt
tree-shaking. Acceptable only as a standalone package entry point where the runtime can
enforce the boundary via package.json exports.import * as dateFns) for large modules (5+ items). Prefer named
imports when importing fewer than ~5 items.import()) for code splitting and lazy loading: routes loaded on
navigation, large conditional dependencies, feature flags.import "./polyfill.js") should be rare. Document why.{} and [], never new Object() / new Array().greet() { } not greet: function() { }.{ ...obj } and [...arr]. Prefer over Object.assign.user.name vs
user[dynamicKey].Object.hasOwn(obj, key) instead of obj.hasOwnProperty(key).map, filter, find, some, every, flatMap,
reduce) over imperative loops for data transformation.map, filter, reduce callbacks.Array.from(arrayLike) for array-like objects (not spread).
Array.from(iterable, mapFn) instead of [...iterable].map(mapFn) — avoids
intermediate array.[...arr, item], remove arr.filter(...), update arr.map(...).for...of for side-effect loops. Never for...in on arrays.Array.prototype, Object.prototype). Use
utility functions or subclasses.Prefer for...of for side-effect loops, Array.prototype methods (.map, .filter,
.reduce, .find, .some, .every) for data transforms, for for index-needed loops.
See references/objects-and-arrays.md for the full iteration decision table.
Use Map when keys aren't strings or are user-provided (avoids prototype pollution).
Use Set for dedup ([...new Set(items)]). Use generators (function*) for lazy
sequences and deferred computation.
class syntax only. No function constructors or prototype manipulation.#private fields for encapsulation. Not _ convention.extends only for true "is-a" relationships.super(), omit it.this for fluent/chainable APIs.For pure JavaScript projects that don't use TypeScript, use JSDoc annotations to provide
type safety through editor tooling. Enable // @ts-check at file top or checkJs in
jsconfig.json.
Core tags: @type, @param, @returns, @typedef (with @property), @template.
See references/jsdoc.md for the full tag catalog including @callback, @enum,
class modifiers, and type import syntax.
{string | number} over
{(string|number)}.@typedef for shared shapes — define once near file top or in types.js.const x = 5 is clearly a number, skip @type.When writing JavaScript code:
When reviewing JavaScript code:
Bad review comment:
"According to best practices, you should use const instead of let
when the variable is never reassigned."
Good review comment:
"`let` -> `const` — `config` is never reassigned."
A typescript-language-server LSP server is configured for all JS/TS file types (.js, .jsx,
.ts, .tsx, .mjs, .cjs, .mts, .cts). Always use LSP tools for code navigation
instead of Grep or Glob. LSP understands module resolution, type inference, scope rules, and
project boundaries — text search does not.
| Task | LSP Operation | Why LSP over text search |
|---|---|---|
| Find where a function/class/variable is defined | goToDefinition | Resolves imports, re-exports, aliases |
| Find all usages of a symbol | findReferences | Scope-aware, no false positives from string matches |
| Get type signature, docs, or return types | hover | Instant type info without reading source files |
| List all exports/symbols in a file | documentSymbol | Structured output vs grepping for function/class/export |
| Find a symbol by name across the project | workspaceSymbol | Searches all modules |
| Find implementations of an interface | goToImplementation | Knows the type system |
| Find what calls a function | incomingCalls | Precise call graph across module boundaries |
| Find what a function calls | outgoingCalls | Structured dependency map |
Grep/Glob remain appropriate for: text in comments, string literals, log messages, TODO markers, config values, env vars, CSS classes, file name patterns, URLs, error message text.
When spawning subagents for JS/TS codebase exploration, instruct them to use LSP tools. Subagents have access to the same LSP server.
The coding skill governs workflow; this skill governs JavaScript implementation choices. For TypeScript projects, the typescript skill extends this one.
Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.
Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.