Count Cachula
Local-first performance without the complexity π§
Stale-while-revalidate on steroids: instant UI updates with cache tags, invalidation, and smart preloading
Get started:
npm install @countcachula/coreβ‘ Fast
Serve cached content instantly while revalidating in the background
π Fresh
Automatic cache invalidation keeps your data up-to-date
π― Simple
Drop-in replacement for fetch with powerful caching
What is Count Cachula?
An alternative to local-first that gives you the same instant, responsive UXβbut simpler, lighter, and easier to reason about.
The Local-First Promise
Local-first architectures provide instant UI updates by keeping a local copy of your data. But they come with serious complexity: CRDTs, conflict resolution, sync protocols, offline queues, and complex state management.
The problem: You're building distributed systems whether you want to or not.
The Count Cachula Way
Get the same instant responsiveness by treating your cache as truth. Stale-while-revalidate means users see data immediately, then get updates automatically. No sync, no conflicts, no distributed systems.
The solution: Your server is still the source of truth. The cache just makes it feel instant.
Stale-While-Revalidate on Steroids
Instant Response
Serve from cache immediately while fetching fresh data in the background
Cache Tags
Tag related data and invalidate entire groups at once
Smart Invalidation
Automatically invalidate caches when mutations happen via SSE
Preloading
Warm up caches before users need them for zero-latency navigation
Why This Works
Users see data instantly
Cached data appears immediately, no loading spinners
Data stays fresh automatically
Background revalidation and SSE invalidation keep everything current
Server remains source of truth
No conflict resolution, no CRDTs, no distributed systems complexity
Drop-in replacement for fetch
Works with your existing API, no architecture overhaul needed
How It Works
Count Cachula uses server-driven invalidation and preloading to keep your client perfectly in syncβwithout any client-side complexity.
Browser Connects to SSE
When your app loads, it establishes a Server-Sent Events connection. This gives the server a direct channel to push updates to the client.
Server Sends Preload Hints
The server can immediately start warming up the cache by sending preload hints for important APIs:
event: preload-hintdata: {"url": "/api/tasks", "tags": ["tasks"]}
event: preload-hintdata: {"url": "/api/user/profile", "tags": ["user"]}The client fetches and caches this data in the background, so it's ready instantly when needed.
Code Requests Data
When your code needs data, it makes a normal request using Count Cachula's fetch:
// When your code needs dataconst request = new Request('/api/tasks');const tasks = await CountCachula.fetch(request);
// Returns cached data instantly (if available)// Then fetches fresh data in background// UI updates automatically when fresh data arrivesThe magic: Returns cached data instantly, then fetches fresh data in the background and automatically updates your UI when it arrives. No loading states needed!
Mutations Invalidate Tags
When you mutate data on the server, you invalidate related cache tags:
// After a mutation on the serverawait db.tasks.create(newTask);
// Invalidate related cache tagshub.invalidate(['tasks', 'user:stats']);// SSE automatically notifies all connected clientsThe server pushes invalidation events via SSE to all connected clients:
event: invalidatedata: {"tags": ["tasks", "task:123"]}Client Updates Automatically
When the client receives invalidation events, it automatically refetches any affected Observables and updates your UI.
π― This gives you REAL-TIME updates!
All users see changes instantly, even on pages they're not currently viewing. The cache stays warm and ready.
π Server-Driven Everything
The server controls invalidation and preloading, which means the client is never stale. Every fetch gets fresh data in the background, and SSE pushes immediate updates when things change.
π Progressive Enhancement
Start simple with just CountCachula.fetch() for automatic stale-while-revalidate. Add SSE for real-time updates. Add cache tags for smart invalidation. Add preloading for instant navigation. Build up complexity only when you need it.
π Documentation
Comprehensive guides for each package
Core Library
Learn the fundamentals of Count Cachula's cache-first architecture and stale-while-revalidate pattern.
SSE Package
Set up real-time cache invalidation and preload hints using Server-Sent Events.
React Hooks
Build React apps with Suspense integration and clean, declarative data fetching.
Ready to see Count Cachula in action?
π View Live Demo