Vision

Introduction

See exactly what happens inside your API. Debug in seconds, not hours.

Vision

See exactly what happens inside your API.

Vision shows you the complete journey of every request: which database queries ran, how long each step took, what data was sent and received. When something breaks, you click the failed request and see exactly where and why.

Before: Something's slow. Add console.log. Restart. Check logs. Repeat.
After:  Open Vision. Click the slow request. See the waterfall. Fix it.

30-Second Demo

1. Create your app:

import { createVision, createModule } from '@getvision/server'
import { z } from 'zod'

const usersModule = createModule({ prefix: '/users' })
  .get(
    '/:id',
    ({ params, span }) => {
      return span('db.select', { 'db.table': 'users' }, () => getUser(params.id))
    },
    { params: z.object({ id: z.string() }) }
  )

const app = createVision({ service: { name: 'My API' } }).use(usersModule)

app.listen(3000)

2. Make a request to your API

3. Open localhost:9500 and click the request:

GET /users/123 (245ms)
├── middleware.auth (5ms)
├── handler (235ms)
│   ├── db.select.users (12ms)
│   ├── db.select.orders (180ms) ← Found it! This query is slow
│   └── transform (40ms)
└── response (5ms)

You immediately see: The orders query takes 180ms. That's the problem.

No console.log. No guessing. Just click and see.


What Vision Shows You

Request Waterfall

See every operation inside your request:

  • HTTP handling - method, path, status, timing
  • Database queries - which queries ran, how long each took
  • External API calls - requests to Stripe, SendGrid, etc.
  • Custom operations - anything you wrap in a span

Request & Response Data

See exactly what was sent and received:

  • Full request headers and body
  • Full response headers and body
  • Validation errors with field-level detail
  • Error stack traces

Auto-Discovered Routes

All your endpoints appear automatically:

  • Grouped by service (/users/* → Users, /orders/* → Orders)
  • Input/output schemas extracted from Zod / Valibot / TypeBox
  • Ready to test in the API Explorer

Live Logs (Wide Events)

Your console.log calls appear in the dashboard with automatic context:

  • Request-scoped - Click a trace to see only logs from that request
  • Searchable - Search by message OR by context fields like userId=123
  • Add context once, see it everywhere - addContext() attaches to all logs in that request
// Vision Server — addContext is available in every handler
.get('/:id', ({ params, addContext }) => {
  addContext({ userId: params.id, orderId: 'abc' })
  console.log('Processing')  // Automatically has userId, orderId
  console.log('Done')        // Automatically has userId, orderId
})

Two Ways to Use Vision

A Bun-first, Elysia-based meta-framework with everything built in:

bun add @getvision/server zod
import { createVision, createModule, defineEvents } from '@getvision/server'
import { z } from 'zod'

const usersModule = createModule({ prefix: '/users' })
  .use(
    defineEvents({
      'user/created': {
        schema: z.object({ userId: z.string(), email: z.string().email() }),
        handler: async (event) => console.log('welcome →', event.email),
      },
    })
  )
  .post(
    '/',
    async ({ body, addContext, emit, span }) => {
      addContext({ 'user.email': body.email })
      const user = span('db.insert', { 'db.table': 'users' }, () => ({
        id: crypto.randomUUID(),
        ...body,
      }))
      await emit('user/created', { userId: user.id, email: user.email })
      return user
    },
    {
      body: z.object({ name: z.string().min(1), email: z.string().email() }),
    }
  )

const app = createVision({ service: { name: 'My API' } }).use(usersModule)

app.listen(3000)

export type AppType = typeof app  // ← Eden Treaty type for the client

Vision Server includes:

  • span() — built-in tracing
  • addContext() — wide-events logging
  • emit() — type-safe pub/sub events (BullMQ)
  • Cron jobs via defineCrons()
  • Rate limiting via rateLimit()
  • End-to-end type safety via Eden Treaty (treaty<AppType>)

Framework Adapters

Prefer to keep your existing Hono, Fastify, or Express app? Adapters give you the Vision dashboard and tracing without switching frameworks:

bun add @getvision/adapter-hono  # or adapter-fastify, adapter-express

Adapters and Vision Server are equally supported — pick whichever fits your stack.


Which Should I Use?

ScenarioUse This
Starting a new API projectVision Server — everything built in
Want span(), addContext(), emit() in handlersVision Server — all typed in context
Need routes + pub/sub + cron in one placeVision Server — batteries included
Want a typed RPC client on the frontendVision Server — Eden Treaty ready
Have a mature Hono / Fastify / Express app you don't want to portAdapters

Recommendation: Start with Vision Server. It's the full experience.


Why Not Just Use console.log?

You can. But:

Problemconsole.logVision
"Which query is slow?"Add timing logs around each queryClick request, see waterfall
"What was in the request body?"console.log(req.body)Already captured
"Did the cache hit?"Add log, restart, testAlready captured as span
"What happened in production staging?"Scroll through terminalOpen dashboard, click trace
"Which request caused this error?"Hope you logged enough contextError is attached to trace

Vision captures everything automatically. You look at what you need, when you need it.


Why Not DataDog / NewRelic?

Those are great for production monitoring. Vision is for development:

VisionDataDog/NewRelic
CostFree, open source$50+/month
Setup2 lines of codeSDK + config + agent
DataStays on your machineSent to cloud
FocusDebugging during devProduction monitoring
UILocal dashboardCloud dashboard

Use Vision during development. Add production APM when you need it.


Get Started

Quickest path:

git clone https://github.com/ephor/vision
cd vision/examples/vision
bun install && bun dev

# Open http://localhost:9500

Add to your app:

Learn more:


Open Source

Vision is MIT licensed. Star us on GitHub if you find it useful.