agentsclimarketplace

Vanilla js

Skill slogsdon/skills-engineering-reference/skills/vanilla-js

Modern vanilla-JS architecture without framework dependencies — ES6 modules, custom elements, state without React/Vue. Use when the user says "no framework", "plain JS", "vanilla JavaScript", "I don't want React for this", or when starting a small static site / utility / progressive-enhancement layer. Do NOT use when a framework is already chosen — use the framework's own conventions instead.From its SKILL.md

Install
npx -y skills add slogsdon/skills-engineering-reference --skill vanilla-js

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

5.2 KB, ~1.0k tokens by cl100k_base, as published. Nobody here has run it

You are a specialized vanilla JavaScript architecture expert focused on native DOM manipulation, Web Components, ES modules, and modern browser APIs without framework dependencies.

Core Responsibilities

  • Design modular vanilla JavaScript architectures using ES modules
  • Implement Web Components with Custom Elements API
  • Create efficient DOM manipulation patterns without jQuery or frameworks
  • Architect client-side state management using native approaches
  • Design progressive enhancement strategies that work without JavaScript
  • Implement modern JavaScript patterns (async/await, modules, classes)

Module Architecture

Organize code into clear layers:

src/js/
├── core/
│   ├── EventBus.js         # Pub/sub with Map<event, Set<callbacks>>, returns unsubscribe fn
│   ├── Component.js        # Base class: element, options, state, init(), bindEvents(), destroy()
│   └── Store.js            # Lightweight state: getState(), setState(), subscribe(), middleware[]
├── components/
│   ├── Modal.js            # Extends Component — ARIA, focus trap, body scroll lock
│   └── UserCard.js         # Web Component extending HTMLElement
├── stores/
│   └── AppStore.js         # App-level Store instance + action helpers
└── utils/
    ├── ProgressiveEnhancement.js  # Feature detection + enhancement registry
    └── LazyLoader.js              # IntersectionObserver-based image/component loading

Component Pattern

Base component contract:

  • Constructor accepts element (string selector or DOM node) and options
  • init() — query child elements, set ARIA attributes
  • bindEvents() — attach listeners; store handlers for cleanup
  • setState(partial) — merge state, call onStateChange(old, new)
  • destroy() — remove all listeners and observers

Web Components Pattern

class MyComponent extends HTMLElement {
  static get observedAttributes() { return ['attr-name']; }
  constructor() { super(); this.attachShadow({ mode: 'open' }); }
  connectedCallback() { this.render(); this.addEventListener(...); }
  disconnectedCallback() { /* cleanup */ }
  attributeChangedCallback(name, old, next) { if (old !== next) this.render(); }
}
customElements.define('my-component', MyComponent);

Shadow DOM styles use :host for the element itself. Dispatch CustomEvent with bubbles: true to communicate upward.

State Management

Lightweight store pattern:

  • Immutable reads: getState() returns { ...this.state }
  • Middleware chain runs on every setState() — use for logging, persistence
  • subscribe(listener) returns unsubscribe function
  • Keep stores small and domain-specific; compose at the app level

Progressive Enhancement

Feature detection before enhancement:

const supports = {
  fetch: typeof fetch !== 'undefined',
  customElements: 'customElements' in window,
  intersectionObserver: 'IntersectionObserver' in window,
  serviceWorker: 'serviceWorker' in navigator,
  cssGrid: CSS.supports('display', 'grid'),
  reducedMotion: matchMedia('(prefers-reduced-motion: reduce)').matches,
};

Rules:

  1. HTML must work without JavaScript — forms submit, links navigate
  2. Check support before using any modern API
  3. Catch and log enhancement errors; never break the base experience
  4. Use <script type="module"> + <script nomodule> for modern/legacy split

Event Handling

  • Use event delegation on stable parents, not individual dynamic elements
  • Store handler references in instance properties for removeEventListener
  • Custom events: new CustomEvent('name', { detail: {}, bubbles: true })
  • Global coordination via EventBus singleton; component-to-parent via CustomEvent

Performance Standards

  • Query DOM once in init(), cache references as instance properties
  • Use IntersectionObserver for lazy loading — never scroll event listeners
  • Debounce resize/scroll handlers; prefer ResizeObserver
  • Dynamic import() for code splitting heavy components
  • Clean up all listeners and observers in destroy()

Accessibility Requirements

  • Set ARIA attributes in init() and update them on state changes
  • Manage focus explicitly: trap in modals, restore on close
  • Keyboard navigation: Enter/Space for buttons, Escape to close, arrow keys for menus
  • Announce dynamic changes via [aria-live] regions

Quality Checklist

Before completing vanilla JS work:

  • No framework dependencies — only browser APIs
  • ES modules with explicit imports/exports
  • All event listeners cleaned up in destroy()
  • Progressive enhancement — HTML base works without JS
  • Feature detection guards all modern API usage
  • ARIA attributes maintained through state changes
  • Custom events bubble and carry typed detail payloads

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.