Best for
- Creating new cf- prefixed components in the UI package
- Modifying existing Common UI v2 components
- Implementing theme-aware components
commontoolsinc/labs/skills/lit-component/SKILL.md
Guide for developing Lit web components in the Common UI v2 system (@commonfabric/ui). Use when creating or modifying cf- prefixed components, implementing theme integration, working with Cell abstractions, or building reactive UI components that integrate with the Common Fabric runtime.
Decision brief
This skill provides guidance for developing Lit web components within the Common UI v2 component library (packages/ui/src/v2).
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/commontoolsinc/labs --skill "skills/lit-component"Inspect the Agent Skill "lit-component" from https://github.com/commontoolsinc/labs/blob/b0ff67d2dde1812680849aa2373df1f49b6faa2f/skills/lit-component/SKILL.md at commit b0ff67d2dde1812680849aa2373df1f49b6faa2f. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
Identify which category the component falls into:
Do NOT use this skill when authoring or styling pattern UIs that consume cf- components — that's pattern-ui's job. Patterns must never touch component internals, and pattern JSX uses theme={...}, not Lit's .theme=${...}.
Common UI is inspired by SwiftUI and emphasizes:
Identify which category the component falls into:
Create the component directory structure:
Permission review
The documentation asks the agent to create, modify, or delete local files.
Create the component directory structure:The documentation asks the agent to create, modify, or delete local files.
### 4. Create Index FileEvidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 86/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 37 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
This skill provides guidance for developing Lit web components within the Common
UI v2 component library (packages/ui/src/v2).
Use this skill when:
cf- prefixed components in the UI packageDo NOT use this skill when authoring or styling pattern UIs that consume cf-
components — that's pattern-ui's job. Patterns must never touch component
internals, and pattern JSX uses theme={...}, not Lit's .theme=${...}.
Common UI is inspired by SwiftUI and emphasizes:
Identify which category the component falls into:
Complexity spectrum: Components range from pure presentation (no runtime) to deeply integrated (Cell operations, pattern execution, backlink resolution). Choose the simplest pattern that meets requirements.
See references/component-patterns.md for detailed patterns for each category
and references/advanced-patterns.md for complex integration patterns.
Create the component directory structure:
packages/ui/src/v2/components/cf-component-name/
├── cf-component-name.ts # Component implementation
├── index.ts # Export and registration
└── styles.ts # Optional: for complex components
Basic template:
import { css, html } from "lit";
import { BaseElement } from "../../core/base-element.ts";
export class CFComponentName extends BaseElement {
static override styles = [
BaseElement.baseStyles,
css`
:host {
display: block;
box-sizing: border-box;
}
*,
*::before,
*::after {
box-sizing: inherit;
}
`,
];
static override properties = {
// Define reactive properties
};
constructor() {
super();
// Set defaults
}
override render() {
return html`
<!-- component template -->
`;
}
}
globalThis.customElements.define("cf-component-name", CFComponentName);
import { CFComponentName } from "./cf-component-name.ts";
if (!customElements.get("cf-component-name")) {
customElements.define("cf-component-name", CFComponentName);
}
export { CFComponentName };
export type {}; /* exported types */
Both registrations are the codebase convention, not a contradiction: the component file registers unconditionally when it is imported, and the index file's guarded define is a safe no-op in that case — it only registers when the component module didn't (and prevents duplicate-registration errors during hot module replacement). Keep both.
Most components should use var(--cf-theme-*) CSS variables with fallbacks
(--cf-theme-* first, then --cf-* base token, then a literal). Consume
cfThemeContext (with applyThemeToElement) only when JavaScript needs the
theme object for runtime logic, derived values, or applying theme variables to
dynamically created elements.
Theme consumption code and complete reference: See
references/theme-system.md for the @consume boilerplate, all available CSS
variables, and helper functions.
For components that work with reactive runtime data, declare the cell as
@property({ attribute: false }), subscribe with
cell.sink(() => this.requestUpdate()) when the cell property changes, and
read with cell.get() in render() (guarding the no-cell case). The pitfalls
that matter:
disconnectedCallback() (memory leaks)isCell(this.cell) before subscribingSubscription boilerplate and complete Cell patterns: See
references/cell-integration.md for subscription management, nested property
access with .key(), array cell manipulation, transaction-based mutations, and
finding cells by equality.
For reusable component behaviors, use reactive controllers. Example:
InputTimingController for debouncing/throttling:
import { InputTimingController } from "../../core/input-timing-controller.ts";
export class CFInput extends BaseElement {
@property()
timingStrategy: "immediate" | "debounce" | "throttle" | "blur" = "debounce";
@property()
timingDelay: number = 500;
private inputTiming = new InputTimingController(this, {
strategy: this.timingStrategy,
delay: this.timingDelay,
});
private handleInput(event: Event) {
const value = (event.target as HTMLInputElement).value;
this.inputTiming.schedule(() => {
this.emit("cf-change", { value });
});
}
}
Use the emit() helper from BaseElement:
private handleChange(newValue: string) {
this.emit("cf-change", { value: newValue });
}
Events are automatically bubbles: true and composed: true.
Use classMap for conditional classes:
import { classMap } from "lit/directives/class-map.js";
const classes = {
button: true,
[this.variant]: true,
disabled: this.disabled,
};
return html`
<button class="${classMap(classes)}">...</button>
`;
Use repeat directive with stable keys:
import { repeat } from "lit/directives/repeat.js";
return html`
${repeat(
items,
(item) => item.id, // stable key
(item) =>
html`
<div>${item.title}</div>
`,
)}
`;
Colocate tests with components:
// cf-button.test.ts
import { describe, it } from "@std/testing/bdd";
import { expect } from "@std/expect";
import { CFButton } from "./cf-button.ts";
describe("CFButton", () => {
it("should be defined", () => {
expect(CFButton).toBeDefined();
});
it("should have default properties", () => {
const element = new CFButton();
expect(element.variant).toBe("primary");
});
});
Run with: deno task test (includes required flags)
Each component is declared in its own directory under
packages/ui/src/v2/components/. packages/ui/src/v2/index.ts re-exports every
component, and the package root re-exports that in turn, so consumers import
them from @commonfabric/ui:
// packages/ui/src/v2/index.ts
export * from "./components/cf-button/index.ts";
Load these references as needed for detailed guidance:
references/component-patterns.md - Detailed patterns for each component
category, file structure, type safety, styling conventions, event handling,
and lifecycle methodsreferences/theme-system.md - Theme philosophy, cf-theme provider,
CFTheme interface, CSS variables, and theming patternsreferences/cell-integration.md - Comprehensive Cell integration patterns
including subscriptions, mutations, array handling, and common pitfallsreferences/advanced-patterns.md - Advanced architectural patterns
revealed by complex components: context provision, third-party integration,
reactive controllers, path-based operations, diff-based rendering, and
progressive enhancementBaseElement - Provides emit() helper and base CSS
variablesattribute: false for objects/arrays/Cells - Prevents serialization
errorscf- - Namespace conventionexport type { ... }disconnectedCallback()@element, @attr, @fires, @exampledeno task test - Not plain deno testrepeat() (breaks reactivity)attribute: true for objects/arrays (serialization errors)super calls in lifecycle methods (breaks base functionality)Study these components to understand architectural patterns:
Basic patterns:
cf-separator - Minimal component, CSS parts, ARIAcf-vstack - Flexbox abstraction, utility classes with classMapcf-button - Theme consumption, event emission, variantsAdvanced patterns:
cf-theme - Ambient configuration with @provide,
display: contents, reactive Cell subscriptionscf-render - Pattern loading, UI extraction, lifecycle
managementcf-code-editor - CodeMirror lifecycle,
Compartments, bidirectional sync, CellControllerEach component reveals deeper patterns - study them not just for API but for architectural principles.
Alternatives
coreyhaines31/marketingskills
When the user wants to plan, design, or implement an A/B test or experiment, or build a growth experimentation program. Also use when the user mentions "A/B test," "split test," "experiment," "test this change," "variant copy," "multivariate test," "hypothesis," "should I test this," "which version is better," "test two versions," "statistical significance," "how long should I run this test," "growth experiments," "experiment velocity," "experiment backlog," "ICE score," "experimentation program
coreyhaines31/marketingskills
When the user wants to reduce churn, build cancellation flows, set up save offers, recover failed payments, or implement retention strategies. Also use when the user mentions 'churn,' 'cancel flow,' 'offboarding,' 'save offer,' 'dunning,' 'failed payment recovery,' 'win-back,' 'retention,' 'exit survey,' 'pause subscription,' 'involuntary churn,' 'people keep canceling,' 'churn rate is too high,' 'how do I keep users,' or 'customers are leaving.' Use this whenever someone is losing subscribers o
prowler-cloud/prowler
PostgreSQL indexing best practices for Prowler: index design, partial indexes, partitioned table indexing, EXPLAIN ANALYZE validation, concurrent operations, monitoring, and maintenance. Trigger: When creating or modifying PostgreSQL indexes, analyzing query performance with EXPLAIN, debugging slow queries, reviewing index usage statistics, reindexing, dropping indexes, or working with partitioned table indexes. Also trigger when discussing index strategies, partial indexes, or index maintenance
JasonColapietro/suede-creator-skills
Suede-owned experimentation discipline for hypotheses, sample sizing, test duration, significance, and repeatable experiment programs. Use when comparing variants, deciding whether a result is reliable, or building an experiment backlog and cadence. NOT FOR: analytics instrumentation (use suede-analytics), post-click conversion diagnosis (use suede-site-alchemy), or writing the variant copy itself (use suede-copy).