How HookTray Works
HookTray uses a stateless relay backend, Server-Sent Events for live streaming, and IndexedDB for browser-local history. No database. No retained payloads.
Architecture overview
Webhook provider or curl
|
| ANY /hooks/{token}
v
.NET Minimal API relay
|
| build bounded request snapshot
| broadcast to active SSE subscribers
v
SSE stream /api/stream/{token}
|
v
Browser UI
|
| render safely (no dangerouslySetInnerHTML)
| store locally
v
IndexedDBStep by step
1. Token creation
When you open HookTray, the browser calls POST /api/hooks. The backend generates a cryptographically secure random token and registers a session. The token is used as both the webhook receive path and the SSE channel identifier.
2. Webhook receive
Your webhook provider sends a request to /hooks/{token}. The backend accepts GET, POST, PUT, PATCH, and DELETE. It builds a bounded snapshot — method, path, query string, headers, and a size-limited body preview — and broadcasts it to all active SSE subscribers for that token.
3. SSE stream
The browser opens a persistent connection to /api/stream/{token}. The backend keeps this connection alive and pushes each request snapshot as a JSON SSE event. There is no polling — events arrive within milliseconds of the webhook landing.
4. Local storage
Each incoming snapshot is written to IndexedDB in the browser. History is scoped to the token and persists across page reloads. When you reopen HookTray with the same token in the URL (?t=TOKEN), your previous requests are hydrated from IndexedDB.
5. Backend cleanup
Sessions that have been inactive beyond the configured TTL are removed by a background cleanup task. The backend holds no payload data — only the active session registry and subscriber list.
Privacy model
The backend is intentionally a relay, not a history service. When a webhook arrives, HookTray builds a bounded snapshot, delivers it to your browser, and discards the payload server-side. Operational logs use hashed token and IP identifiers — raw values are never written. See the privacy page for the full model.
Tech stack
- Backend: .NET 10 Minimal API, in-memory session store,
Channel<T>for SSE broadcast - Frontend: Next.js 16 App Router, React 19, Zustand, Dexie (IndexedDB), Tailwind CSS v4
- Transport: Server-Sent Events (
text/event-stream) — no WebSocket, no polling - Deployment: Docker, nginx reverse proxy, static export for the frontend