JavaScript Authoring Skill
Write modern vanilla JavaScript following functional core with imperative shell architecture.
Core Principles
| Principle |
Description |
| Functional Core |
Pure functions, getters, computed values - no side effects |
| Imperative Shell |
DOM manipulation, event handlers, side effects in lifecycle hooks |
| Dependency Injection |
Import templates, styles, i18n from separate files |
| Named Exports Only |
No default exports - explicit named exports |
| JSDoc Documentation |
Document classes, public methods, and events |
File Structure Pattern
components/
└── my-component/
├── my-component.js # Main component class
├── my-component-template.js # Template function
├── my-component-styles.js # CSS-in-JS styles
└── my-component-i18n.js # Translations object
Web Component Template
import { template } from './my-component-template.js';
import { styles } from './my-component-styles.js';
import { translations } from './my-component-i18n.js';
/**
* my-component: Brief description of component purpose
*
* @attr {string} lang - Language code
* @attr {string} value - Current value
* @fires my-component:update - Fired when state changes
*/
import { VBElement } from '../../lib/vb-element.js';
import { registerComponent } from '../../lib/bundle-registry.js';
class MyComponent extends VBElement {
static get observedAttributes() {
return ['lang', 'value'];
}
// FUNCTIONAL CORE - Pure getters
get lang() {
return this.getAttribute('lang') ||
this.closest('[lang]')?.getAttribute('lang') ||
document.documentElement.lang ||
'en';
}
// IMPERATIVE SHELL - Side effects
setup() {
// Initialize component, query children, bind listeners
// Use this.listen(target, event, handler) for auto-cleanup
// Return false to abort upgrade
}
teardown() {
// Component-specific cleanup (clear timers, disconnect observers)
// Event listeners registered via this.listen() are auto-cleaned
}
attributeChangedCallback(name, oldValue, newValue) {
if (oldValue !== newValue) {
// React to attribute changes
}
}
}
customElements.define('my-component', MyComponent);
export { MyComponent };
Quick Reference
ESLint Rules Enforced
| Rule |
Requirement |
no-var |
Use const or let only |
prefer-const |
Use const when variable is never reassigned |
prefer-template |
Use template literals for string concatenation |
eqeqeq |
Use === and !== only |
camelcase |
Use camelCase for variables and functions |
object-shorthand |
Use { foo } not { foo: foo } |
| Named exports |
No default exports |
Naming Conventions
| Context |
Convention |
Example |
| Variables/Functions |
camelCase |
handleClick, userName |
| Classes |
PascalCase |
MyComponent, UserService |
| Custom Elements |
kebab-case |
<my-component>, <user-card> |
| Events |
kebab-case |
'user-updated', 'form-submit' |
| CSS Classes |
kebab-case |
.card-header, .nav-item |
Related Documentation
- WEB-COMPONENTS.md - Lifecycle and Shadow DOM
- JSDOC.md - Documentation patterns
- I18N.md - Internationalization
- EVENTS.md - Event handling
- ACCESSIBILITY.md - a11y in JavaScript
- DEFENSIVE.md - Type guards, error handling, feature detection
Skills to Consider Before Writing
When authoring JavaScript, consider invoking these related skills:
| Code Pattern |
Invoke Skill |
Why |
class X extends VBElement |
custom-elements |
Full Web Component lifecycle, VBElement base class |
fetch() or API calls |
api-client |
Retry logic, error handling, caching patterns |
| Component state, reactivity |
state-management |
Observable patterns, undo/redo, sync strategies |
localStorage, IndexedDB |
data-storage |
Persistence patterns, offline-first |
| Error handling |
error-handling |
Error boundaries, global handlers, reporting |
When Creating Web Components
If your JavaScript file defines a custom element (extends VBElement), also invoke:
- custom-elements - For registration patterns, slots, attribute handling
- state-management - If component manages internal state
- accessibility-checker - For keyboard navigation, ARIA
When Making API Calls
If your code uses fetch() or makes network requests:
- api-client - Retry logic, timeout handling, typed responses
- error-handling - Network error recovery, user feedback
Related Skills
- custom-elements - Define and use custom HTML elements
- state-management - Client-side state patterns for Web Components
- api-client - Fetch API patterns with error handling and caching
- data-storage - localStorage, IndexedDB, SQLite WASM patterns
- error-handling - Consistent error handling across frontend and backend
- unit-testing - Write unit tests with Node.js native test runner
- typescript-author - TypeScript for Web Components and Node.js
1---2name: javascript-author3description: Write vanilla JavaScript for Web Components with functional core, imperative shell. Use when creating JavaScript files, building interactive components, or writing any client-side code.4---56# JavaScript Authoring Skill78Write modern vanilla JavaScript following functional core with imperative shell architecture.910## Core Principles1112| Principle | Description |13|-----------|-------------|14| Functional Core | Pure functions, getters, computed values - no side effects |15| Imperative Shell | DOM manipulation, event handlers, side effects in lifecycle hooks |16| Dependency Injection | Import templates, styles, i18n from separate files |17| Named Exports Only | No default exports - explicit named exports |18| JSDoc Documentation | Document classes, public methods, and events |1920## File Structure Pattern2122```23components/24└── my-component/25 ├── my-component.js # Main component class26 ├── my-component-template.js # Template function27 ├── my-component-styles.js # CSS-in-JS styles28 └── my-component-i18n.js # Translations object29```3031## Web Component Template3233```javascript34import { template } from './my-component-template.js';35import { styles } from './my-component-styles.js';36import { translations } from './my-component-i18n.js';3738/**39 * my-component: Brief description of component purpose40 *41 * @attr {string} lang - Language code42 * @attr {string} value - Current value43 * @fires my-component:update - Fired when state changes44 */45import { VBElement } from '../../lib/vb-element.js';46import { registerComponent } from '../../lib/bundle-registry.js';4748class MyComponent extends VBElement {49 static get observedAttributes() {50 return ['lang', 'value'];51 }5253 // FUNCTIONAL CORE - Pure getters54 get lang() {55 return this.getAttribute('lang') ||56 this.closest('[lang]')?.getAttribute('lang') ||57 document.documentElement.lang ||58 'en';59 }6061 // IMPERATIVE SHELL - Side effects62 setup() {63 // Initialize component, query children, bind listeners64 // Use this.listen(target, event, handler) for auto-cleanup65 // Return false to abort upgrade66 }6768 teardown() {69 // Component-specific cleanup (clear timers, disconnect observers)70 // Event listeners registered via this.listen() are auto-cleaned71 }7273 attributeChangedCallback(name, oldValue, newValue) {74 if (oldValue !== newValue) {75 // React to attribute changes76 }77 }78}7980customElements.define('my-component', MyComponent);8182export { MyComponent };83```8485## Quick Reference8687### ESLint Rules Enforced8889| Rule | Requirement |90|------|-------------|91| `no-var` | Use `const` or `let` only |92| `prefer-const` | Use `const` when variable is never reassigned |93| `prefer-template` | Use template literals for string concatenation |94| `eqeqeq` | Use `===` and `!==` only |95| `camelcase` | Use camelCase for variables and functions |96| `object-shorthand` | Use `{ foo }` not `{ foo: foo }` |97| Named exports | No default exports |9899### Naming Conventions100101| Context | Convention | Example |102|---------|------------|---------|103| Variables/Functions | camelCase | `handleClick`, `userName` |104| Classes | PascalCase | `MyComponent`, `UserService` |105| Custom Elements | kebab-case | `<my-component>`, `<user-card>` |106| Events | kebab-case | `'user-updated'`, `'form-submit'` |107| CSS Classes | kebab-case | `.card-header`, `.nav-item` |108109## Related Documentation110111- [WEB-COMPONENTS.md](WEB-COMPONENTS.md) - Lifecycle and Shadow DOM112- [JSDOC.md](JSDOC.md) - Documentation patterns113- [I18N.md](I18N.md) - Internationalization114- [EVENTS.md](EVENTS.md) - Event handling115- [ACCESSIBILITY.md](ACCESSIBILITY.md) - a11y in JavaScript116- [DEFENSIVE.md](DEFENSIVE.md) - Type guards, error handling, feature detection117118## Skills to Consider Before Writing119120When authoring JavaScript, consider invoking these related skills:121122| Code Pattern | Invoke Skill | Why |123|--------------|--------------|-----|124| `class X extends VBElement` | **custom-elements** | Full Web Component lifecycle, VBElement base class |125| `fetch()` or API calls | **api-client** | Retry logic, error handling, caching patterns |126| Component state, reactivity | **state-management** | Observable patterns, undo/redo, sync strategies |127| `localStorage`, `IndexedDB` | **data-storage** | Persistence patterns, offline-first |128| Error handling | **error-handling** | Error boundaries, global handlers, reporting |129130### When Creating Web Components131132If your JavaScript file defines a custom element (`extends VBElement`), also invoke:133- **custom-elements** - For registration patterns, slots, attribute handling134- **state-management** - If component manages internal state135- **accessibility-checker** - For keyboard navigation, ARIA136137### When Making API Calls138139If your code uses `fetch()` or makes network requests:140- **api-client** - Retry logic, timeout handling, typed responses141- **error-handling** - Network error recovery, user feedback142143## Related Skills144145- **custom-elements** - Define and use custom HTML elements146- **state-management** - Client-side state patterns for Web Components147- **api-client** - Fetch API patterns with error handling and caching148- **data-storage** - localStorage, IndexedDB, SQLite WASM patterns149- **error-handling** - Consistent error handling across frontend and backend150- **unit-testing** - Write unit tests with Node.js native test runner151- **typescript-author** - TypeScript for Web Components and Node.js