From javascript
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.
npx claudepluginhub xobotyi/cc-foundry --plugin javascriptThis skill uses the workspace's default tool permissions.
**Clarity is the highest JavaScript virtue. If your code requires a comment to explain its control flow, rewrite it.**
Generates design tokens/docs from CSS/Tailwind/styled-components codebases, audits visual consistency across 10 dimensions, detects AI slop in UI.
Records polished WebM UI demo videos of web apps using Playwright with cursor overlay, natural pacing, and three-phase scripting. Activates for demo, walkthrough, screen recording, or tutorial requests.
Delivers idiomatic Kotlin patterns for null safety, immutability, sealed classes, coroutines, Flows, extensions, DSL builders, and Gradle DSL. Use when writing, reviewing, refactoring, or designing Kotlin code.
Clarity 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.
${CLAUDE_SKILL_DIR}/references/functions.md] — Arrow function examples,
closure patterns, early return, parameter destructuring${CLAUDE_SKILL_DIR}/references/async.md] — Promise.all/race/any
examples, cancellation, custom error classes, for-await${CLAUDE_SKILL_DIR}/references/objects-and-arrays.md] — Iteration
decision table, destructuring patterns, immutable updates, generators${CLAUDE_SKILL_DIR}/references/modules.md] — Import ordering, barrel file
rationale, directory import pitfalls, dynamic imports${CLAUDE_SKILL_DIR}/references/jsdoc.md] — Full tag reference (@callback,
@template, @enum), type assertions, class modifiers${CLAUDE_SKILL_DIR}/references/idioms.md] — Variable/naming examples,
equality coercion table, modern syntax patternsconst 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".One-liners or split-per-branch only. Ternaries are acceptable in two forms:
// 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.
Nested ternaries are banned. No exceptions. Use 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 ${CLAUDE_SKILL_DIR}/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
${CLAUDE_SKILL_DIR}/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.
goToDefinition — Resolves imports, re-exports, aliasesfindReferences — Scope-aware, no false positives from string matcheshover — Instant type info without reading source filesdocumentSymbol — Structured output vs grepping for
function/class/exportworkspaceSymbol — Searches all modulesgoToImplementation — Knows the type systemincomingCalls — Precise call graph across module boundariesoutgoingCalls — Structured dependency mapGrep/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.