vTilt
Why vTiltHow It WorksFeaturesFAQDocs
Docs / Hono
Quick startEvent forwarding
MCP server
Guides
OverviewAuthenticationOAuthAgent skills (prompts)AI intelligenceGoogle Ads
Client setup
CursorClaude DesktopVS CodeCodex
Realtime
Debug ViewRealtime Dashboard
Integration guides
Frontend frameworks
Next.jsNuxt.jsVue.jsReactReact RouterRemixGatsbySvelte / SvelteKitAstroAngularTanStack StartDocusaurus
Backend frameworks
NestJSHonoCloudflare WorkersDjangoFlaskLaravelPhoenixRuby on Rails
Backend languages
PythonPHPRubyElixirGoJava.NET / C#Rust
Stack guides
Vue + PHP
SDK
Browser SDK
InstallScript bundlesEvent trackingAutocaptureIdentify & aliasWeb VitalsSession recordingChat widgetFeature readinessRemote configurationReverse proxyDebug logging
Node SDK
Install & setupCapture, identify & aliasContext & shutdown

Documentation

vTilt
Quick startEvent forwarding

MCP server

Realtime

Debug ViewRealtime Dashboard

Integration guides

NestJSHonoCloudflare WorkersDjangoFlaskLaravelPhoenixRuby on Rails

SDK

DocsIntegration guidesHono

Hono

Integrate vTilt with Hono — Node SDK in a request-scoped middleware, identify, capture, and shutdown across runtimes (Node, Bun, Cloudflare Workers).

Hono runs on Node, Bun, Deno, and Cloudflare Workers. The @v-tilt/node SDK works in all four — it's a thin HTTP client with no Node-only APIs. The pattern below uses Hono middleware to expose a c.get('vtilt') helper to every handler.

Tip

Tip: On Cloudflare Workers the same code applies, but you must call await ctx.executionContext.waitUntil(client.shutdown()) so events flush before the worker is frozen — see Cloudflare Workers for a worker-specific example.

#1. Install

npm install hono @v-tilt/node
bash

#2. Middleware

// src/middleware/vtilt.ts
import { createMiddleware } from 'hono/factory'
import { VTiltNode } from '@v-tilt/node'

type Env = {
  Variables: { vtilt: VTiltNode }
  Bindings: { VTILT_TRACKER_TOKEN: string; VTILT_HOST: string }
}

let _client: VTiltNode | null = null

export const vtilt = createMiddleware<Env>(async (c, next) => {
  if (!_client) {
    _client = new VTiltNode(c.env.VTILT_TRACKER_TOKEN, {
      host: c.env.VTILT_HOST,
    })
  }
  c.set('vtilt', _client)
  await next()
  // On serverless: ctx.executionContext.waitUntil(_client.shutdown())
})
typescript

#3. Mount and use

// src/index.ts
import { Hono } from 'hono'
import { vtilt } from './middleware/vtilt'

const app = new Hono<typeof vtilt extends infer M ? M : never>()
app.use('*', vtilt)

app.post('/checkout', async c => {
  const { userId, amount } = await c.req.json<{
    userId: string
    amount: number
  }>()

  c.var.vtilt.capture({
    distinctId: userId,
    event: 'purchase_completed',
    properties: { amount },
  })

  return c.json({ ok: true })
})

export default app
typescript
# .env (Node / Bun)
VTILT_TRACKER_TOKEN=YOUR_PROJECT_TOKEN
VTILT_HOST=https://www.vtilt.com
text

#4. Identify users on every request

If your auth middleware sets c.var.user, identify on every request so the server-side person record stays in sync with browser activity.

import { createMiddleware } from 'hono/factory'

export const vtiltIdentify = createMiddleware(async (c, next) => {
  await next()
  const user = c.get('user')
  if (user) {
    c.var.vtilt.identify({
      distinctId: user.id,
      anonymousId: c.req.header('cookie')?.match(/vt_anon=([^;]+)/)?.[1],
      properties: { email: user.email },
    })
  }
})

app.use('*', vtilt, vtiltIdentify)
typescript

#5. Graceful shutdown (long-running runtimes)

For Node/Bun servers, flush on SIGINT/SIGTERM:

import { serve } from '@hono/node-server'

const server = serve({ fetch: app.fetch, port: 3000 })

const shutdown = async () => {
  await _client?.shutdown()
  server.close()
  process.exit(0)
}

process.on('SIGINT', shutdown)
process.on('SIGTERM', shutdown)
typescript

#Next steps

  • Cloudflare Workers — workers-specific waitUntil pattern.
  • Node SDK / Context & shutdown — request-scoped identity.
  • Node SDK / Capture, identify & alias — full event shapes.
PreviousNestJSIntegration guidesNextCloudflare WorkersIntegration guides

On this page

  • 1. Install
  • 2. Middleware
  • 3. Mount and use
  • 4. Identify users on every request
  • 5. Graceful shutdown (long-running runtimes)
  • Next steps