WebSocket-first data framework for SolidJS
Stop making your users wait for data they already have.
0ms revisit · 2.8KB gzipped · WebSocket-first
npm install @uikode/tide Click to copy // First visit: skeleton shimmer
// Revisit: 0ms from sessionStorage
The Problem
You're building a real-time dashboard. API calls take 1–9 seconds. Every navigation = blank page → spinner → wait → render. Your data was RIGHT THERE 2 seconds ago.
7
Endpoints optimized
<25ms
All responses after cache
1,490×
Fastest improvement
"Your data was RIGHT THERE. Why wait again?"
See the difference
How Tide Works
5 layers, 1 hook. Zero config.
Tap a layer to explore ↑
How Tide Compares
TanStack Query is great for REST. Tide is built for live data.
| Feature | TanStack Query | solid-swr | @uikode/tide |
|---|---|---|---|
| API response (server cache) | N/A | N/A | 2ms |
| Revisit render | ~80ms | ~100ms | 0ms |
| WebSocket-first | ❌ | ❌ | ✅ Built-in |
| sessionStorage persist | ❌ | ❌ | ✅ 0ms hydrate |
| Server cache convention | ❌ | ❌ | ✅ server-side (Go/Fiber) |
| Bundle size | 15.5KB | 1.33KB | 2.8KB |
| Zero deps | ❌ | ✅ | ✅ |
| SolidJS native | Adapter | ✅ | ✅ |
| Skeleton system | ❌ | ❌ | ✅ Included |
| Prefetch on hover | ❌ | ❌ | ✅ Built-in |
| Offline resilient | ❌ | ❌ | ✅ |
| Visibility pause | ❌ | ❌ | ✅ |
| Request dedup | ✅ | ✅ | ✅ |
TanStack Query
solid-swr
@uikode/tide ✨
"TanStack polls. Tide pushes. When your data changes 10x/second, you don't want to ask — you want to be told."
"Why not just add WebSocket to TanStack?" →
🔄 Already using TanStack Query?
import { createQuery } from '@tanstack/solid-query'
const q = createQuery(() => ({
queryKey: ['dashboard'],
queryFn: fetchDashboard,
})) import { createTide } from '@uikode/tide'
const d = createTide({
key: 'dashboard',
fetcher: ({ signal }) => fetchDashboard(signal),
}) 5 minutes. Zero breaking changes.
See It In Action
import { createTide } from "@uikode/tide"
// v1.1: URL shorthand — no fetcher needed!
const users = createTide<User[]>({
key: "users",
url: "/api/users", // auto-creates fetcher
transform: (raw) => raw.data, // optional transform
staleTime: 30_000,
cacheTime: 300_000,
})
// Revisit? Renders instantly from sessionStorage.Real Production Benchmarks
From ACS Dashboard — 11 pages, 12 Hermes gateways, Go backend, WS broadcast every 5s
vs TanStack Query
Revisit: ~80ms
Bundle: 15.5KB (+persist)
vs solid-swr
Revisit: ~100ms
Bundle: 1.33KB
@uikode/tide
Revisit: 0ms
Bundle: 2.8KB
API Response Times (Server Cache)
| Endpoint | Before | After | Speed |
|---|---|---|---|
| /api/dashboard | 8,941ms | 6ms | 1,490× |
| /api/agentic/tooling | 5,609ms | 16ms | 350× |
| /api/stack/status | 5,000ms | 6ms | 833× |
| /api/gateways | 1,828ms | 2ms | 914× |
| /api/agentic/summary | 200ms | 10ms | 20× |
| /api/announcements | 50ms | 8ms | 6× |
| /api/daemon/status | 10ms | 4ms | 2.5× |
All endpoints < 25ms after server-side cache warm
Test environment: Windows 11, Go binary, 12 Hermes gateways, 26 skills, 279 kanban tasks, 10 API providers, WS broadcast every 5s. Measured via CloakBrowser automated testing on localhost.
⚡ Running in 60 Seconds
npm install @uikode/tide solid-js import { TideProvider } from '@uikode/tide'
function Root() {
return (
<TideProvider ws={{ url: 'wss://your-server/ws' }}>
<App />
</TideProvider>
)
} import { createTide } from '@uikode/tide'
const todos = createTide({
key: 'todos',
fetcher: ({ signal }) =>
fetch('/api/todos', { signal }).then((r) => r.json()),
ws: (msg) => (msg.type === 'todos' ? msg.data : null),
}) That's it. WebSocket, caching, reconnection, skeleton — all handled.
12 Problems Solved in 2.8KB
WebSocket-first
Push primary, poll fallback
Instant revisit
sessionStorage hydration (0ms)
Skeleton system
Layout-matched shimmer components
Stale-while-revalidate
Show data, refresh in background
Prefetch on hover
Warm cache before navigation
Retry with backoff
Exponential 1s/2s/4s recovery
Request dedup
1 inflight request per key
Abort on re-fetch
Race-free data fetching
Visibility pause
Stop polling when tab hidden
Offline resilient
Cache serves indefinitely offline
Dev logging
Hit/miss/timing in console
< 3KB gzipped
Zero dependencies, solid-js peer
What Teams Build With Tide
Dashboards
Admin panels, monitoring, analytics
Chat/Collab
Messaging, live editing, multiplayer
Trading
Financial data, order books, price feeds
IoT/Devices
Sensor streams, fleet management
Game state
Lobby status, player state
Dev tools
Log viewers, process monitors
Frequently Asked Questions
Does Tide work with SSR / SSG?
Yes. Tide hydrates from sessionStorage on client. Server renders skeleton/fallback. Zero hydration mismatch.
Can I use Tide with React or Vue?
Tide is SolidJS-only by design. SolidJS signals enable 0-cost reactive subscriptions. We chose depth over breadth.
How does bundle size compare to TanStack Query?
Tide: 2.8KB gzipped (core+skeleton), WebSocket transport included. TanStack Query + persist plugin (parity for instant revisit): 15.5KB — Tide is ~5.4x smaller. Note: solid-swr is smaller still (1.33KB) but ships no WebSocket, persistence, or skeleton system.
Is Tide production-ready?
Tide is at v1.1.0 (published June 2026) and powers the ACS dashboard (11 pages, 12 gateways) in real use. Benchmarks on this page come from that deployment. It is young with low adoption so far — evaluate accordingly.
Why not just add a WebSocket adapter to TanStack Query?
TanStack was designed HTTP-first. Bolting WS on gives you double caching, no built-in reconnection, and loses stale-while-revalidate on transport switch. Tide is WS-first from line 1.
What happens when the WebSocket disconnects?
Automatic exponential backoff (1s/2s/4s) + HTTP fallback. UI stays interactive with stale cache, updates when connection restores.
How do I migrate from TanStack Query?
Most cases: swap createQuery for createTide, swap the provider. See the Migration Guide.
Quick Links
Resources
Community
MIT License • Built by Andy Vandaric • © 2026 UIKode