---
name: stencil
description: >
Use this skill when the user says 'Stencil', 'Stencil.js', 'Stencil component', 'Stencil web component', 'Stencil setup', 'Stencil compiler', 'Stencil design system', 'web component compiler', or when building reusable web components with Stencil. This skill enforces: Stencil decorators (@Component, @Prop, @State, @Event), JSX-based component compilation, lazy-loading for performance, framework-agnostic output. Requires Stencil CLI (@stencil/core). Do NOT use for: non-web-component projects, React/Vue components that don't need framework-agnostic output, or vanilla custom elements.
version: "1.0.0"
author: "j4flmao"
license: "MIT"
compatibility:
claude-code: true
cursor: true
codex: true
windsurf: true
tags: [frontend, stencil, phase-2]
---
# Stencil
## Purpose
Build reusable, framework-agnostic web components using Stencil's TypeScript-first compiler — optimized for design systems, component libraries, and performance-critical UIs.
## Agent Protocol
### Trigger
Exact user phrases: "Stencil setup", "Stencil component", "Stencil web component", "Stencil compiler", "Stencil design system", "Stencil project", "stencil component library".
### Input Context
Before activating, verify:
- @stencil/core is in devDependencies.
- Whether building a standalone component library, a design system, or embedded in an app.
- Target framework consumers (React, Vue, Angular, or vanilla).
### Output Artifact
No file output. Produces code snippets and config examples as text.
### Response Format
Component definition:
```tsx
@Component({ tag: 'my-button', styleUrl: 'my-button.css' })
export class MyButton { ... }
```
No preamble. No postamble. No explanations. Compress output — why use many token when few do trick.
### Completion Criteria
- [ ] Components follow Stencil API: @Component, @Prop, @State, @Event, @Method.
- [ ] Styles scoped with Shadow DOM or scoped CSS.
- [ ] Reactive props with @Prop decorator (mutable or reflect).
- [ ] Events emitted with @Event and EventEmitter.
- [ ] Components tested with @stencil/jest or @stencil/playwright.
- [ ] Library can be consumed as framework-agnostic or via framework bindings.
- [ ] Build output includes lazy-loaded bundles.
### Max Response Length
~4096 tokens.
## Workflow
### Step 1: New Project
```bash
npm init stencil
# Select component (library) or app
cd my-components
npm install
npm start
```
### Step 2: Basic Component
```tsx
// src/components/my-button/my-button.tsx
import { Component, Prop, h } from '@stencil/core'
@Component({
tag: 'my-button',
styleUrl: 'my-button.css',
shadow: true,
})
export class MyButton {
@Prop() variant: 'primary' | 'secondary' = 'primary'
@Prop() disabled = false
render() {
return (
)
}
}
```
### Step 3: State & Events
```tsx
import { Component, State, Event, EventEmitter, Prop, h } from '@stencil/core'
@Component({
tag: 'my-counter',
styleUrl: 'my-counter.css',
shadow: true,
})
export class MyCounter {
@Prop() initialValue = 0
@State() count = 0
@Event() countChanged: EventEmitter
componentWillLoad() {
this.count = this.initialValue
}
private increment() {
this.count++
this.countChanged.emit(this.count)
}
render() {
return (
Count: {this.count}
)
}
}
```
### Step 4: Methods
```tsx
import { Component, Method, h } from '@stencil/core'
@Component({ tag: 'my-dialog', shadow: true })
export class MyDialog {
private dialogEl!: HTMLDialogElement
@Method()
async open() {
this.dialogEl.showModal()
}
@Method()
async close() {
this.dialogEl.close()
}
render() {
return (
)
}
}
```
### Step 5: Consuming Components
```html
```
### Step 6: Build
```bash
npm run build
# Output: dist/ with lazy-loaded bundles
```
## Rules
- Use `shadow: true` for style encapsulation (Shadow DOM).
- Props are `camelCase` in JSX, `kebab-case` in HTML.
- Events are dispatched as CustomEvent with `@Event`.
- Use `@Method` sparingly — prefer props and events for public API.
- Render function returns JSX (not template strings).
- Style per component, not global (unless design tokens).
- Use `@stencil/core/testing` for unit tests, Playwright for e2e.
- Mark props as `mutable: true` only when the component itself mutates them.
## References
- references/stencil-advanced.md — Stencil Advanced Topics
- references/stencil-architecture.md — Stencil Architecture Patterns
- references/stencil-components.md — Stencil Components & Patterns
- references/stencil-deployment.md — Stencil Deployment
- references/stencil-fundamentals.md — Stencil Fundamentals
- references/stencil-setup.md — Stencil Setup Guide
## Handoff
No artifact produced.
Next skill: stencil-design-system (if building a design system) or frontend-testing.
Carry forward: @Component/@Prop/@Event pattern, shadow DOM, framework-agnostic output.