Skip to content
Security
Skill

/design-patterns

Agents should invoke this skill when choosing patterns, designing traits/interfaces/components, deciding abstraction boundaries, evaluating dependency injection/callbacks, or comparing implementation approaches in Rust, TypeScript/React, or Django/Python.

BOOST
From plugin
opencode-power-pack
53955 skills
Install
$ npx -y skills add waybarrios/opencode-power-pack --skill design-patterns --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/design-patterns

Context preview

The summary Claude sees to decide when to auto-load this skill.

Agents should invoke this skill when choosing patterns, designing traits/interfaces/components, deciding abstraction boundaries, evaluating dependency injection/callbacks, or comparing implementation approaches in Rust, TypeScript/React, or Django/Python.

SKILL.md

design-patterns.SKILL.md
name: design-patterns
description: Agents should invoke this skill when choosing patterns, designing traits/interfaces/components, deciding abstraction boundaries, evaluating dependency injection/callbacks, or comparing implementation approaches in Rust, TypeScript/React, or Django/Python.
license: MIT (modified; see UPSTREAMS.json)

Design Patterns

Pattern recommendations tailored to common tech stacks. Every pattern recommendation includes when to use it, when to avoid it, and the trade-offs.

Quick Start

Choose a Pattern

1. **Identify the problem:** What design challenge are you solving? 2. **Consider the context:** What language? What scale? How often will this change? 3. **Evaluate options:** 2-3 candidate patterns with trade-offs 4. **Recommend:** The best fit for *this specific context* (not the "best pattern in general")

**The golden rule:** Patterns are tools, not goals. Use the simplest pattern that solves the problem. If no pattern fits, a plain function or struct is fine.

---

Rust Patterns

Newtype Pattern

Wrap a primitive to add type safety and domain meaning.

struct UserId(u64);
struct OrderId(u64);

// Now the compiler prevents mixing up UserId and OrderId
fn get_order(user: UserId, order: OrderId) -> Order { ... }

**When to use:** When two values have the same underlying type but different meanings. **When to skip:** One-off uses where a type alias suffices.

Builder Pattern

Construct complex objects step by step.

let config = ServerConfig::builder()
    .host("localhost")
    .port(8080)
    .max_connections(100)
    .build()?;

**When to use:** Structs with many optional fields, complex construction logic. **When to skip:** Structs with 1-3 required fields — just use `new()`.

Typestate Pattern

Encode state transitions in the type system so invalid states are unrepresentable.

struct Connection<S: State> { /* ... */ state: PhantomData<S> }
struct Disconnected;
struct Connected;
struct Authenticated;

impl Connection<Disconnected> {
    fn connect(self) -> Result<Connection<Connected>> { ... }
}
impl Connection<Connected> {
    fn authenticate(self, creds: &Credentials) -> Result<Connection<Authenticated>> { ... }
}
impl Connection<Authenticated> {
    fn query(&self, sql: &str) -> Result<Rows> { ... }
}
// Can't call query() on a Disconnected connection — compile error

**When to use:** Protocols with clear state transitions (connections, workflows, parsing stages). **When to skip:** Simple on/off states — a boolean or enum is clearer.

Trait Objects vs Generics

| Approach | Dispatch | Binary Size | Flexibility | |---|---|---|---| | `impl Trait` (generics) | Static (monomorphized) | Larger (one copy per type) | Known at compile time | | `dyn Trait` (trait objects) | Dynamic (vtable) | Smaller (one copy) | Extensible at runtime |

**Use generics when:** Performance matters, types are known at compile time, you want zero-cost abstraction. **Use trait objects when:** You need heterogeneous collections, plugin systems, or the set of types is open-ended.

Error Handling Patterns

| Pattern | When | Crate | |---|---|---| | `thiserror` | Library errors — structured, specific variants | `thiserror` | | `anyhow` | Application errors — context-rich, propagate quickly | `anyhow` | | Custom enum | When you need exhaustive matching by callers | std only |

**Rule of thumb:** Libraries use `thiserror` (callers need to match). Applications use `anyhow` (callers need context).

---

TypeScript / React Patterns

Compound Components

Components that work together implicitly via shared context.

<Select>
  <Select.Trigger>Choose a fruit</Select.Trigger>
  <Select.Options>
    <Select.Option value="apple">Apple</Select.Option>
    <Select.Option value="banana">Banana</Select.Option>
  </Select.Options>
</Select>

**When to use:** Complex UI components with multiple related parts (menus, accordions, tabs). **When to skip:** Simple components with 1-2 elements.

Custom Hook Composition

Extract and compose behavior into reusable hooks.

function useDebounce<T>(value: T, delay: number): T { ... }
function usePagination(items: Item[], pageSize: number) { ... }
function useLocalStorage<T>(key: string, initial: T) { ... }

**When to use:** Shared stateful logic across components, complex state management within a component. **When to skip:** One-off logic that doesn't repeat.

Discriminated Unions

Type-safe state modeling using TypeScript's union types.

type AsyncState<T> =
  | { status: "idle" }
  | { status: "loading" }
  | { status: "success"; data: T }
  | { status: "error"; error: Error };

// Exhaustive switch — TypeScript ensures all cases handled
function render(state: AsyncState<User>) {
  switch (state.status) {
    case "idle": return <Placeholder />;
    case "loading": return <Spinner />;
    case "success": return <UserCard user={state.data} />;
    case "error": return <ErrorBanner error={state.error} />;
  }
}

**When to use:** State machines, API response states, form states, anything with distinct modes. **When to skip:** Boolean flags are fine for simple on/off states.

State Management Decision Tree

1. **UI-local state?** -> `useState` / `useReducer` 2. **Shared between siblings?** -> Lift state to common parent 3. **Shared across distant components?** -> React Context 4. **Complex state logic?** -> `useReducer` + Context 5. **Server state (API data)?** -> TanStack Query / SWR 6. **Global app state?** -> Zustand / Jotai (prefer over Redux for new projects)

---

Django / Python Patterns

Service Layer

Separate business logic from views and models.

# services/order_service.py
class OrderService:
    @staticmethod
    def create_order(user: User, items: list[CartItem]) -> Order:
        """Business logic lives here, not in the view."""
        order = Order.objects.create(user=user, total=calculate_total(items)
Read more
Ships withopencode-power-pack

54 rigorous skills for Codex, OpenCode, and Pi: code review, security audit, feature development, frontend design, MCP tools, Hugging Face ML/training, and more.

Get the whole plugin

Other skills on opencode-power-pack.