home / skills / commontoolsinc / labs / pattern-implement

pattern-implement skill

/.claude/skills/pattern-implement

This skill helps you implement a minimal sub-pattern with a testable Stream-based interface and lightweight UI for data flow validation.

npx playbooks add skill commontoolsinc/labs --skill pattern-implement

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
1.7 KB
---
name: pattern-implement
description: Build sub-patterns with minimal UI
user-invocable: false
---

Use `Skill("ct")` for ct CLI documentation when running commands.

# Implement Sub-Pattern

## Core Rule
Write ONE sub-pattern with minimal stub UI. No styling, just basic inputs/buttons to verify data flow.

**Always use `pattern<Input, Output>()`** - expose actions as `Stream<T>` for testability.

## Order
1. Leaf patterns first (no dependencies on other patterns)
2. Container patterns (compose leaf patterns)
3. main.tsx last (composes everything)

## Read First
- `docs/common/patterns/` - especially `meta/` for generalizable idioms
- `docs/common/concepts/action.md` - action() for local state
- `docs/common/concepts/handler.md` - handler() for reusable logic
- `docs/common/concepts/reactivity.md` - Cell behavior, .get()/.set()
- `docs/common/concepts/identity.md` - equals() for object comparison

## Key Patterns

**action()** - Closes over local state in pattern body:
```tsx
const inputValue = Cell.of("");
const submit = action(() => {
  items.push({ text: inputValue.get() });
  inputValue.set("");
});
```

**handler()** - Reused with different bindings:
```tsx
const deleteItem = handler<void, { items: Writable<Item[]>; index: number }>(
  (_, { items, index }) => items.set(items.get().toSpliced(index, 1))
);
// In JSX: onClick={deleteItem({ items, index })}
```

**Rendering sub-patterns** - Use function calls, not JSX:
```tsx
// ✅ Correct
{items.map((item) => ItemPattern({ item, allItems: items }))}

// ❌ Wrong - JSX fails with typed Output
{items.map((item) => <ItemPattern item={item} />)}
```

## Done When
- Pattern compiles: `deno task ct check pattern.tsx --no-run`
- Minimal UI renders inputs/buttons
- Ready for testing

Overview

This skill teaches how to implement a single sub-pattern with a minimal UI using TypeScript and the provided pattern primitives. It focuses on delivering one leaf or container pattern that exposes actions as Stream<T> and renders only basic inputs and buttons to verify data flow. The goal is a compilable pattern ready for automated checks and tests.

How this skill works

Follow the prescribed order: create leaf patterns first, then container patterns, and finally compose in main.tsx. Implement patterns with pattern<Input, Output>() and expose user interactions via action() and handler() primitives. Render sub-patterns by calling them as functions so typed Outputs remain intact, and use Cells for local reactive state.

When to use it

  • Implementing a new UI behavior that must be testable via Streams
  • Creating a minimal, no-styling prototype to validate data flow
  • Building leaf components that will be composed into larger patterns
  • Preparing a pattern to pass automated compilation and basic runtime checks
  • Demonstrating handler/action idioms for reuse across patterns

Best practices

  • Always write one focused sub-pattern; keep UI minimal with basic inputs and buttons
  • Use pattern<Input, Output>() so actions can be exposed as Stream<T> for testing
  • Prefer action() for local state effects and handler() for reusable logic
  • Render children by calling pattern functions, not JSX, to preserve typed outputs
  • Follow the order: leaf patterns → container patterns → main composition
  • Keep equals(), Cell, and .get()/.set() usage consistent for identity and reactivity

Example use cases

  • A todo item leaf pattern exposing add/remove actions as streams for test harnesses
  • A list container pattern that composes item patterns and verifies event propagation
  • A form pattern that uses Cells for inputs and an action to submit structured data
  • A small demo main.tsx composing patterns to validate compile-time checks
  • Replacing a complex styled component with a minimal stub to test logic in isolation

FAQ

Do I need to include styling or complex markup?

No. Keep the UI minimal—plain inputs and buttons are sufficient to verify data flow and actions.

How should I expose interactions for tests?

Always expose actions as Stream<T> by using pattern<Input, Output>() and action()/handler() so tests can subscribe to events.