signal-state-management — community signal-state-management, ree-board, community, ide skills, Claude Code, Cursor, Windsurf

v1.0.0
GitHub

About this Skill

Perfect for Frontend Agents needing efficient client-side state management and reactive UI updates. Retro board build using Turso, Next.js and Supabase Auth

DW225 DW225
[0]
[0]
Updated: 3/5/2026

Agent Capability Analysis

The signal-state-management skill by DW225 is an open-source community AI agent skill for Claude Code and other IDE workflows, helping agents execute tasks with better context, repeatability, and domain-specific guidance.

Ideal Agent Persona

Perfect for Frontend Agents needing efficient client-side state management and reactive UI updates.

Core Value

Empowers agents to manage mutable state with signals, integrate with React components, and optimize re-renders using libraries like @preact/signal and Next.js, while organizing state by domain for enhanced performance.

Capabilities Granted for signal-state-management

Implementing computed values for dynamic UI updates
Batching state updates for improved application performance
Integrating signals with React components for seamless state management
Organizing state by domain for enhanced data organization and retrieval

! Prerequisites & Limits

  • Requires knowledge of JavaScript and React
  • Limited to client-side application state management
  • Dependent on libraries like @preact/signal and Next.js
Labs Demo

Browser Sandbox Environment

⚡️ Ready to unleash?

Experience this Agent in a zero-setup browser environment powered by WebContainers. No installation required.

Boot Container Sandbox

signal-state-management

Install signal-state-management, an AI agent skill for AI agent workflows and automation. Works with Claude Code, Cursor, and Windsurf with one-command setup.

SKILL.md
Readonly

Signal State Management

When to Use This Skill

Activate this skill when working on:

  • Managing client-side application state
  • Creating reactive UI updates
  • Implementing computed values
  • Batching state updates for performance
  • Organizing state by domain (boards, posts, members)
  • Integrating signals with React components
  • Optimizing re-renders

Core Patterns

Signal vs Computed Signal

Simple Signal: Holds mutable state

typescript
1import { signal } from "@preact/signals-react"; 2 3// ✅ Simple signal for primitive values 4export const currentBoardId = signal<string | null>(null); 5 6// ✅ Simple signal for complex state 7export const postsSignal = signal<Post[]>([]);

Computed Signal: Derives value from other signals

typescript
1import { signal, computed } from "@preact/signals-react"; 2 3export const postsSignal = signal<Post[]>([]); 4export const filterSignal = signal<PostFilter>("all"); 5 6// ✅ Computed signal automatically updates 7export const filteredPosts = computed(() => { 8 const posts = postsSignal.value; 9 const filter = filterSignal.value; 10 11 if (filter === "all") return posts; 12 return posts.filter((p) => p.type === filter); 13});

State Organization by Domain

Separate Files for Each Domain:

typescript
1// lib/signal/postSignals.ts 2import { signal, computed } from "@preact/signals-react"; 3 4// State 5export const postsSignal = signal<Post[]>([]); 6export const selectedPostId = signal<string | null>(null); 7 8// Computed values 9export const selectedPost = computed(() => { 10 const id = selectedPostId.value; 11 if (!id) return null; 12 return postsSignal.value.find((p) => p.id === id); 13}); 14 15export const postsByType = computed(() => { 16 const posts = postsSignal.value; 17 return { 18 wentWell: posts.filter((p) => p.type === "went_well"), 19 toImprove: posts.filter((p) => p.type === "to_improve"), 20 actionItems: posts.filter((p) => p.type === "action_items"), 21 }; 22}); 23 24// Actions 25export const addPost = (post: Post) => { 26 postsSignal.value = [...postsSignal.value, post]; 27}; 28 29export const updatePost = (id: string, updates: Partial<Post>) => { 30 postsSignal.value = postsSignal.value.map((p) => 31 p.id === id ? { ...p, ...updates } : p 32 ); 33}; 34 35export const deletePost = (id: string) => { 36 postsSignal.value = postsSignal.value.filter((p) => p.id !== id); 37};

Action Creator Pattern

Encapsulate State Updates:

typescript
1// lib/signal/boardSignals.ts 2import { signal } from "@preact/signals-react"; 3 4export const boardsSignal = signal<Board[]>([]); 5export const loadingSignal = signal<boolean>(false); 6export const errorSignal = signal<string | null>(null); 7 8// ✅ Action creators for complex operations 9export const loadBoards = async () => { 10 loadingSignal.value = true; 11 errorSignal.value = null; 12 13 try { 14 const boards = await fetchBoards(); 15 boardsSignal.value = boards; 16 } catch (error) { 17 errorSignal.value = "Failed to load boards"; 18 console.error(error); 19 } finally { 20 loadingSignal.value = false; 21 } 22}; 23 24export const createBoard = async (name: string) => { 25 try { 26 const newBoard = await createBoardAction(name); 27 // Optimistic update 28 boardsSignal.value = [...boardsSignal.value, newBoard]; 29 return newBoard; 30 } catch (error) { 31 errorSignal.value = "Failed to create board"; 32 throw error; 33 } 34};

Batch Updates for Performance

Update Multiple Signals Together:

typescript
1import { batch } from "@preact/signals-react"; 2 3// ❌ Bad: Triggers 3 re-renders 4const updateBoard = (id: string, data: BoardUpdate) => { 5 boardsSignal.value = updateBoardList(id, data); 6 selectedBoardId.value = id; 7 lastUpdatedSignal.value = Date.now(); 8}; 9 10// ✅ Good: Triggers 1 re-render 11const updateBoard = (id: string, data: BoardUpdate) => { 12 batch(() => { 13 boardsSignal.value = updateBoardList(id, data); 14 selectedBoardId.value = id; 15 lastUpdatedSignal.value = Date.now(); 16 }); 17};

Integration with React Components

Reading Signals:

typescript
1"use client"; 2 3import { postsSignal, filteredPosts } from "@/lib/signal/postSignals"; 4 5export function PostList() { 6 // ✅ Component re-renders when signal changes 7 const posts = filteredPosts.value; 8 9 return ( 10 <div> 11 {posts.map((post) => ( 12 <PostCard key={post.id} post={post} /> 13 ))} 14 </div> 15 ); 16}

Updating Signals:

typescript
1"use client"; 2 3import { updatePost } from "@/lib/signal/postSignals"; 4 5export function EditPostForm({ postId }: { postId: string }) { 6 const handleSubmit = (content: string) => { 7 // ✅ Update signal 8 updatePost(postId, { content }); 9 10 // Persist to database 11 updatePostAction(postId, content); 12 }; 13 14 return <form onSubmit={handleSubmit}>...</form>; 15}

Combining Signals with Server Actions

Pattern: Update signal first (optimistic), then persist

typescript
1"use client"; 2 3import { addPost, deletePost } from "@/lib/signal/postSignals"; 4import { createPost as createPostAction } from "@/lib/actions/post/createPost"; 5 6export function CreatePostButton({ boardId }: { boardId: string }) { 7 const handleCreate = async () => { 8 // Create temporary post for optimistic UI 9 const tempPost: Post = { 10 id: `temp-${Date.now()}`, 11 boardId, 12 content: "", 13 type: "went_well", 14 createdAt: new Date(), 15 }; 16 17 // ✅ Optimistic update 18 addPost(tempPost); 19 20 try { 21 // Persist to database 22 const savedPost = await createPostAction(boardId, "", "went_well"); 23 24 // Replace temp with real post 25 deletePost(tempPost.id); 26 addPost(savedPost); 27 } catch (error) { 28 // Rollback on error 29 deletePost(tempPost.id); 30 showError("Failed to create post"); 31 } 32 }; 33 34 return <button onClick={handleCreate}>Create Post</button>; 35}

Signal Performance Patterns

Avoid Unnecessary Signal Subscriptions:

typescript
1// ❌ Bad: Creates new computed signal on every render 2function PostCount() { 3 const count = computed(() => postsSignal.value.length); 4 return <div>{count.value}</div>; 5} 6 7// ✅ Good: Computed signal defined once outside component 8const postCount = computed(() => postsSignal.value.length); 9 10function PostCount() { 11 return <div>{postCount.value}</div>; 12}

Use Signal Peeking for Non-Reactive Reads:

typescript
1import { postsSignal } from "@/lib/signal/postSignals"; 2 3function logCurrentPosts() { 4 // ✅ Read without subscribing (doesn't trigger re-render) 5 console.log("Current posts:", postsSignal.peek()); 6}

Anti-Patterns

❌ Mutating Signal Values Directly

Bad:

typescript
1// ❌ Never mutate signal values directly 2postsSignal.value.push(newPost);

Good:

typescript
1// ✅ Create new array 2postsSignal.value = [...postsSignal.value, newPost];

❌ Creating Signals Inside Components

Bad:

typescript
1function MyComponent() { 2 // ❌ Creates new signal on every render 3 const localSignal = signal(0); 4 return <div>{localSignal.value}</div>; 5}

Good:

typescript
1// ✅ Define signals outside components 2const counterSignal = signal(0); 3 4function MyComponent() { 5 return <div>{counterSignal.value}</div>; 6}

❌ Not Using Batch for Multiple Updates

Bad:

typescript
1// ❌ Triggers 3 re-renders 2const resetFilters = () => { 3 filterSignal.value = "all"; 4 sortSignal.value = "date"; 5 searchSignal.value = ""; 6};

Good:

typescript
1// ✅ Triggers 1 re-render 2import { batch } from "@preact/signals-react"; 3 4const resetFilters = () => { 5 batch(() => { 6 filterSignal.value = "all"; 7 sortSignal.value = "date"; 8 searchSignal.value = ""; 9 }); 10};

❌ Forgetting .value Accessor

Bad:

typescript
1// ❌ Comparing signal object, not value 2if (currentBoardId === "board-123") { 3 // This will never be true 4}

Good:

typescript
1// ✅ Access signal value 2if (currentBoardId.value === "board-123") { 3 // Correct comparison 4}

Integration with Other Skills

Project-Specific Context

Key Files

  • lib/signal/boardSignals.ts - Board listing and management
  • lib/signal/postSignals.ts - Post state within boards
  • lib/signal/memberSignals.ts - Board member management
  • components/board/PostProvider.tsx - Signal updates from real-time

Domain-Specific Signals

Board Management:

typescript
1// lib/signal/boardSignals.ts 2export const boardsSignal = signal<Board[]>([]); 3export const currentBoardId = signal<string | null>(null); 4export const currentBoard = computed(() => 5 boardsSignal.value.find((b) => b.id === currentBoardId.value) 6);

Post Management:

typescript
1// lib/signal/postSignals.ts 2export const postsSignal = signal<Post[]>([]); 3export const postFilter = signal<PostType | "all">("all"); 4export const filteredPosts = computed(() => { 5 const filter = postFilter.value; 6 if (filter === "all") return postsSignal.value; 7 return postsSignal.value.filter((p) => p.type === filter); 8});

Member Management:

typescript
1// lib/signal/memberSignals.ts 2export const membersSignal = signal<Member[]>([]); 3export const currentUserRole = computed(() => { 4 const members = membersSignal.value; 5 const userId = currentUserId.value; 6 return members.find((m) => m.userId === userId)?.role || "guest"; 7});

Real-Time Integration

Update Signals from Ably Messages:

typescript
1// components/board/PostProvider.tsx 2useChannel(`board:${boardId}`, (message) => { 3 switch (message.name) { 4 case "post:create": 5 addPost(message.data); 6 break; 7 8 case "post:update": 9 updatePost(message.data.id, message.data); 10 break; 11 12 case "post:delete": 13 deletePost(message.data.id); 14 break; 15 } 16});

Testing Signals

Reset Signals in beforeEach:

typescript
1import { postsSignal, filterSignal } from "@/lib/signal/postSignals"; 2 3beforeEach(() => { 4 postsSignal.value = []; 5 filterSignal.value = "all"; 6}); 7 8test("filters posts by type", () => { 9 postsSignal.value = [ 10 { id: "1", type: "went_well", content: "Test" }, 11 { id: "2", type: "to_improve", content: "Test" }, 12 ]; 13 14 filterSignal.value = "went_well"; 15 expect(filteredPosts.value).toHaveLength(1); 16});

Last Updated: 2026-01-10

FAQ & Installation Steps

These questions and steps mirror the structured data on this page for better search understanding.

? Frequently Asked Questions

What is signal-state-management?

Perfect for Frontend Agents needing efficient client-side state management and reactive UI updates. Retro board build using Turso, Next.js and Supabase Auth

How do I install signal-state-management?

Run the command: npx killer-skills add DW225/ree-board/signal-state-management. It works with Cursor, Windsurf, VS Code, Claude Code, and 19+ other IDEs.

What are the use cases for signal-state-management?

Key use cases include: Implementing computed values for dynamic UI updates, Batching state updates for improved application performance, Integrating signals with React components for seamless state management, Organizing state by domain for enhanced data organization and retrieval.

Which IDEs are compatible with signal-state-management?

This skill is compatible with Cursor, Windsurf, VS Code, Trae, Claude Code, OpenClaw, Aider, Codex, OpenCode, Goose, Cline, Roo Code, Kiro, Augment Code, Continue, GitHub Copilot, Sourcegraph Cody, and Amazon Q Developer. Use the Killer-Skills CLI for universal one-command installation.

Are there any limitations for signal-state-management?

Requires knowledge of JavaScript and React. Limited to client-side application state management. Dependent on libraries like @preact/signal and Next.js.

How To Install

  1. 1. Open your terminal

    Open the terminal or command line in your project directory.

  2. 2. Run the install command

    Run: npx killer-skills add DW225/ree-board/signal-state-management. The CLI will automatically detect your IDE or AI agent and configure the skill.

  3. 3. Start using the skill

    The skill is now active. Your AI agent can use signal-state-management immediately in the current project.

Related Skills

Looking for an alternative to signal-state-management or another community skill for your workflow? Explore these related open-source skills.

View All

widget-generator

Logo of f
f

f.k.a. Awesome ChatGPT Prompts. Share, discover, and collect prompts from the community. Free and open source — self-host for your organization with complete privacy.

149.6k
0
AI

flags

Logo of vercel
vercel

flags is a Next.js feature management skill that enables developers to efficiently add or modify framework feature flags, streamlining React application development.

138.4k
0
Browser

zustand

Logo of lobehub
lobehub

The ultimate space for work and life — to find, build, and collaborate with agent teammates that grow with you. We are taking agent harness to the next level — enabling multi-agent collaboration, effortless agent team design, and introducing agents as the unit of work interaction.

72.8k
0
AI

data-fetching

Logo of lobehub
lobehub

The ultimate space for work and life — to find, build, and collaborate with agent teammates that grow with you. We are taking agent harness to the next level — enabling multi-agent collaboration, effortless agent team design, and introducing agents as the unit of work interaction.

72.8k
0
AI