{"id":32956927,"url":"https://github.com/I-am-abdulazeez/stunk","last_synced_at":"2025-11-16T03:01:44.100Z","repository":{"id":277679628,"uuid":"922920607","full_name":"I-am-abdulazeez/stunk","owner":"I-am-abdulazeez","description":"A framework-agnostic state management library that keeps your app’s state clean and simple. It uses a fine-grained state model, breaking state into independent, manageable chunks.","archived":false,"fork":false,"pushed_at":"2025-10-18T05:15:29.000Z","size":398,"stargazers_count":147,"open_issues_count":2,"forks_count":8,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-19T03:20:42.184Z","etag":null,"topics":["angular","client-state-management","queflow","react","solid","state-management","svelte","typescript","vue","zustand-alternative"],"latest_commit_sha":null,"homepage":"https://stunk.vercel.app/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/I-am-abdulazeez.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":"ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-01-27T10:29:15.000Z","updated_at":"2025-10-15T18:26:54.000Z","dependencies_parsed_at":null,"dependency_job_id":"6180b28c-1102-422b-a146-7d308d27b7ed","html_url":"https://github.com/I-am-abdulazeez/stunk","commit_stats":null,"previous_names":["i-am-abdulazeez/stunk"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/I-am-abdulazeez/stunk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/I-am-abdulazeez%2Fstunk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/I-am-abdulazeez%2Fstunk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/I-am-abdulazeez%2Fstunk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/I-am-abdulazeez%2Fstunk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/I-am-abdulazeez","download_url":"https://codeload.github.com/I-am-abdulazeez/stunk/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/I-am-abdulazeez%2Fstunk/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":284654194,"owners_count":27041729,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-11-16T02:00:05.974Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","client-state-management","queflow","react","solid","state-management","svelte","typescript","vue","zustand-alternative"],"created_at":"2025-11-12T23:00:21.961Z","updated_at":"2025-11-16T03:01:44.075Z","avatar_url":"https://github.com/I-am-abdulazeez.png","language":"TypeScript","funding_links":[],"categories":["Built with TypeScript","Reactive Programming"],"sub_categories":["Libraries","Runner"],"readme":"# Stunk\n\nStunk is a lightweight, framework-agnostic state management library built on atomic state principles. It simplifies state management by breaking state into manageable \"chunks\", ensuring efficient updates and reactivity.\n\n- **Pronunciation**: _Stunk_ (A playful blend of \"state\" and \"chunk\")\n\n**Stunk** is like dividing your jar into many smaller containers, each holding a single piece of state. These smaller containers are called **chunks**. Each **chunk** can be updated and accessed easily, and any part of your app can subscribe to changes in a chunk so it gets updated automatically.\n\n## Features\n\n- 🚀 **Lightweight and Fast**: No dependencies, minimal overhead\n- 🔄 **Reactive**: Automatic updates when state changes\n- 📦 **Batch Updates**: Group multiple state updates together\n- 🎯 **Atomic State Management**: Break down state into manageable chunks\n- 🎭 **State Selection**: Select and derive specific parts of the state\n- 🔄 **Async Support**: Handle async state with built-in loading and error states\n- 🔌 **Middleware Support**: Extend functionality with custom middleware\n- ⏱️ **Time Travel**: Undo/redo state changes\n- 🔍 **Type-Safe**: Written in TypeScript with full type inference\n\n## Installation\n\n```bash\nnpm install stunk\n# or\nyarn add stunk\n# or\npnpm install stunk\n```\n\nRead Docs:\n\n[Stunk](https://stunk.vercel.app/)\n\n## Creating a Chunk\n\n```typescript\nimport { chunk } from \"stunk\";\n\n// Create a chunk holding a number\nconst count = chunk(0);\n\n// Create a chunk holding a string\nconst name = chunk(\"Stunky, chunky\");\n```\n\n👉 [See full explanation in docs](https://stunk.vercel.app/chunk.html)\n\n## Interacting with a Chunk\n\n```typescript\n// Get value\nconsole.log(count.get()); // 0\n\n// Set a new value\ncount.set(10);\n\n// Update based on the previous value\ncount.set((prev) =\u003e prev + 1);\n\n// Reset to the initial value\ncount.reset();\n\n// Destroy the chunk and all its subscribers.\ncount.destroy();\n```\n\n👉 [See full explanation in docs](https://stunk.vercel.app/chunk.html)\n\n## React via useChunk\n\nThe `useChunk` hook, enables components to reactively read and update state from a Chunk. The counter example below depicts\n\n```typescript\nimport { chunk } from \"stunk\";\nimport { useChunk } from \"stunk/react\";\n\nconst count = chunk(0);\n\nconst Counter = () =\u003e {\n  const [value, set, reset] = useChunk(count);\n\n  return (\n    \u003cdiv\u003e\n      \u003cp\u003eCount: {value}\u003c/p\u003e\n      \u003cbutton onClick={() =\u003e set((prev) =\u003e prev + 1)}\u003eIncrement\u003c/button\u003e\n      \u003cbutton onClick={() =\u003e reset()}\u003eReset\u003c/button\u003e\n    \u003c/div\u003e\n  );\n};\n```\n\n👉 [See full explanation in docs](https://stunk.vercel.app/useChunk.html)\n\n## React via useDerive\n\nHook that lets you create a read-only derived state from a Chunk. It keeps the derived value reactive, automatically updating whenever the source Chunk changes.\n\n```typescript\nimport { chunk } from \"stunk\";\nimport { useDerive } from \"stunk/react\";\n\nconst count = chunk(0);\n\nconst DoubledCount = () =\u003e {\n  const double = useDerive(count, (value) =\u003e value * 2);\n\n  return \u003cp\u003eDouble: {double}\u003c/p\u003e;\n};\n```\n\n👉 [See full explanation in docs](https://stunk.vercel.app/useDerive.html)\n\n## React via useComputed\n\nHook that derives a computed value from one or more Chunks. It automatically re-evaluates whenever any of its dependencies change, ensuring efficient and reactive updates.\n\n```typescript\nimport { chunk } from \"stunk\";\nimport { useComputed } from \"stunk/react\";\n\nconst count = chunk(2);\nconst multiplier = chunk(3);\n\nconst ComputedExample = () =\u003e {\n  const product = useComputed([count, multiplier], (c, m) =\u003e c * m);\n\n  return \u003cp\u003eProduct: {product}\u003c/p\u003e;\n};\n```\n\n👉 [See full explanation in docs](https://stunk.vercel.app/useComputed.html)\n\n## React via useAsyncChunk\n\nHook that manages that manages asynchronous state. It offers built-in reactivity, handling loading, error, and data states, ensuring the UI stays in sync with asynchronous operations.\n\n```typescript\nimport { asyncChunk } from \"stunk\";\nimport { useAsyncChunk } from \"stunk/react\";\n\nconst fetchUser = asyncChunk(async () =\u003e {\n  const res = await fetch(\"https://jsonplaceholder.typicode.com/users/1\");\n  return res.json();\n});\n\nconst UserProfile = () =\u003e {\n  const { data, loading, error, reload } = useAsyncChunk(fetchUser);\n\n  if (loading) return \u003cp\u003eLoading...\u003c/p\u003e;\n  if (error) return \u003cp\u003eError: {error.message}\u003c/p\u003e;\n\n  return (\n    \u003cdiv\u003e\n      \u003ch2\u003e{data.name}\u003c/h2\u003e\n      \u003cp\u003e{data.email}\u003c/p\u003e\n      \u003cbutton onClick={reload}\u003eReload\u003c/button\u003e\n    \u003c/div\u003e\n  );\n};\n```\n\n👉 [See full explanation in docs](https://stunk.vercel.app/useAysncChunk.html)\n\n## React via useChunkValue\n\nHook that subscribes to a Chunk and returns its current value. It is useful for read-only components that don’t need to modify the state.\n\n```typescript\nimport { chunk } from \"stunk\";\nimport { useChunkValue } from \"stunk/react\";\n\nconst count = chunk(0);\n\nconst CounterDisplay = () =\u003e {\n  const value = useChunkValue(count);\n\n  return \u003cp\u003eCount: {value}\u003c/p\u003e;\n};\n```\n\n👉 [See full explanation in docs](https://stunk.vercel.app/read-only-values.html)\n\nLive Examples:\n\n👉 [Visit](https://stunk-examples.vercel.app/)\n\nCoding Examples:\n\n👉 [Visit](https://stunk.vercel.app/examples.html)\n\nFurther Examples:\n\n👉 [Visit](https://github.com/I-am-abdulazeez/stunk-examples/)\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n[Pull Request](https://github.com/I-am-abdulazeez/stunk/pulls)\n\n## License\n\nThis is licence under MIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FI-am-abdulazeez%2Fstunk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FI-am-abdulazeez%2Fstunk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FI-am-abdulazeez%2Fstunk/lists"}