v0.3.0 · MIT
Connect state across tabs instantly. No server, no WebSockets, no extra configuration.
pnpm add tabus-js925 B
Min + gzip
0
Dependencies
0
Servers
Shared cart
Tabus Sneakers
Tab A → B
Event in ~0ms
Shared cart
Tabus Sneakers
Shared cart
Tabus Sneakers
No heavy runtime, no new concepts. One class, two methods, and the browser does the rest.
Sync state across tabs with the browser's native API. No WebSockets, no polling, no server in between.
No BroadcastChannel in your environment? It automatically falls back to an in-memory bus, same API.
Define your event map with generics. emit and on get real autocomplete and type checking.
Limit high-frequency events with a single option — ideal for shared scroll or resize handling.
Nothing to audit, nothing to update. It doesn't drag a dependency tree into your bundle.
925 B min+gzip, CJS + ESM, and types included. Install it and forget about it.
import { Tabus } from 'tabus-js'
type Events = {
'cart:add': { id: string }
'cart:reset': void
}
const bus = new Tabus<Events>('shop')
// listen on the other tabs
bus.on('cart:add', ({ id }) => {
addToCart(id)
})
// emit from this one
bus.emit('cart:add', { id: 'sku_42' })▍// the full API
You create a typed channel, listen on the other tabs, and emit from yours. There's no step four.
// works wherever you already do
It's a JS class built on a standard API. Wrap it in a hook, a composable, or use it directly.
import { useEffect } from 'react'
import { Tabus } from 'tabus-js'
export const useTabSync = (onAdd: (id: string) => void) => {
useEffect(() => {
const bus = new Tabus<{ 'cart:add': { id: string } }>('shop')
bus.on('cart:add', ({ id }) => onAdd(id))
return () => bus.destroy()
}, [])
}Sync your tabs in about as long as it takes to read the docs.