🚀 Live Examples & Demo are available!
zusound is a lightweight Zustand middleware that transforms state changes into sound. It provides real-time, sonic feedback for your app's state transitions, making debugging and development more intuitive and fun.
# Using npm
npm install zusound
# Using yarn
yarn add zusound
# Using pnpm
pnpm add zusound
# Using bun
bun add zusound
You can also install it directly from the repository:
# Using npm
npm install github:behoney/zusound
# Using yarn
yarn add github:behoney/zusound
# Using pnpm
pnpm add github:behoney/zusound
For development setup instructions, please see our Contributing Guidelines.
import { create } from 'zustand'
import { zusound } from 'zusound'
const useStore = create<{ count: number; inc: () => void }>()(
zusound(set => ({
count: 0,
inc: () => set(state => ({ count: state.count + 1 })),
}), { enabled: true })
)
Best Practice:
- Use
zusound
as the outermost middleware when composing with others (likepersist
,devtools
,immer
). - This ensures type safety and avoids TypeScript mutator errors.
import { create } from 'zustand'
import { devtools, persist } from 'zustand/middleware'
import { zusound } from 'zusound'
interface TodoStoreType {
todos: { id: number; title: string; completed: boolean }[]
addTodo: (todo: { id: number; title: string; completed: boolean }) => void
removeTodo: (todoId: number) => void
todoStatus: (todoId: number) => void
}
const useTodoStore = create<TodoStoreType>()(
zusound(
devtools(
persist(
set => ({
todos: [],
addTodo: todo => set(state => ({ todos: [todo, ...state.todos] })),
removeTodo: todoId => set(state => ({ todos: state.todos.filter(t => t.id !== todoId) })),
todoStatus: todoId => set(state => ({
todos: state.todos.map(t => t.id === todoId ? { ...t, completed: !t.completed } : t)
})),
}),
{ name: 'todos' }
),
{ name: 'TodoStoreDevtools' }
),
{ enabled: true }
)
)
- initializer: Your Zustand state creator function (with or without other middlewares).
- options:
{ enabled?: boolean }
(default:false
). Set totrue
to enable sound in production.
Returns: A Zustand-compatible middleware. Use as the outermost middleware for best TypeScript compatibility.
- Type Safety: zusound is designed to be type-safe and compatible with all Zustand middleware patterns.
- Middleware Order: Always use zusound as the outermost middleware. This avoids TypeScript errors like:
Argument of type 'StateCreator<...>' is not assignable to parameter of type 'StateCreator<...>'
- No
any
Leaks: zusound does not useany
in its public API. If you see type errors, check your middleware order. - Custom Middleware: zusound works with custom and third-party middlewares as long as it is the outermost wrapper.
- Intercepting: Listens to state changes via Zustand middleware
- Diffing: Calculates the difference between previous and next state
- Sonifying: Translates that difference into sound using the Web Audio API
- Intercepts state changes with Zustand middleware
- Performs shallow diffing on state changes
- Basic sonification (sound generation) based on state changes
Contributions are welcome! See CONTRIBUTING.md for details.
This project is licensed under the MIT License.
zusound is inspired by the excellent Zustand.