Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/outray-tunnel/outray/llms.txt

Use this file to discover all available pages before exploring further.

The @outray/vite plugin integrates with Vite’s configureServer hook to start an OutRay tunnel as soon as the dev server begins listening. The tunnel URL appears in the terminal alongside Vite’s local and network URLs.
The plugin uses apply: "serve" and only runs during vite dev. It is completely inactive during builds.

Setup

1

Install the package

npm install @outray/vite
2

Add the plugin to your Vite config

Import outray and add it to the plugins array in vite.config.ts:
vite.config.ts
import { defineConfig } from 'vite'
import outray from '@outray/vite'

export default defineConfig({
  plugins: [outray()]
})
3

Start the dev server

Run vite or npm run dev. The tunnel URL appears alongside the local address:
  Local:   http://localhost:5173/
  Tunnel:  https://abc123.outray.dev

Configuration

Pass an options object to outray():
vite.config.ts
import { defineConfig } from 'vite'
import outray from '@outray/vite'

export default defineConfig({
  plugins: [
    outray({
      subdomain: 'my-app',
      apiKey: process.env.OUTRAY_API_KEY,
    })
  ]
})

Options

OptionTypeDefaultDescription
subdomainstringRequest a specific subdomain. Requires authentication.
customDomainstringUse a custom domain configured in the OutRay dashboard.
apiKeystringprocess.env.OUTRAY_API_KEYAPI key for authentication.
serverUrlstringwss://api.outray.dev/OutRay server WebSocket URL. Change this only for self-hosted instances.
enabledbooleanprocess.env.OUTRAY_ENABLED !== "false"Enable or disable the tunnel.
silentbooleanfalseSuppress all tunnel status logs.
localbooleanfalseEnable LAN access via mDNS (.local domain) for devices on the same network.
onTunnelReady(url: string) => voidCalled when the tunnel is established.
onLocalReady(info: LocalInfo) => voidCalled when LAN access is available.
onError(error: Error) => voidCalled when the tunnel encounters an error.
onClose() => voidCalled when the tunnel connection closes.
onReconnecting() => voidCalled when the tunnel is attempting to reconnect.

Environment variables

VariableDescription
OUTRAY_API_KEYAPI key for authentication — fallback for the apiKey option.
OUTRAY_SUBDOMAINSubdomain to request — fallback for the subdomain option.
OUTRAY_SERVER_URLServer WebSocket URL — fallback for the serverUrl option.
OUTRAY_ENABLEDSet to "false" to disable the tunnel without removing the plugin.

Examples

Custom subdomain

Reserve a consistent URL for your project:
vite.config.ts
import { defineConfig } from 'vite'
import outray from '@outray/vite'

export default defineConfig({
  plugins: [
    outray({
      subdomain: 'my-app',
      apiKey: process.env.OUTRAY_API_KEY,
    })
  ]
})

Custom domain

Use a domain you’ve configured in the OutRay dashboard:
vite.config.ts
import { defineConfig } from 'vite'
import outray from '@outray/vite'

export default defineConfig({
  plugins: [
    outray({
      customDomain: 'dev.example.com',
      apiKey: process.env.OUTRAY_API_KEY,
    })
  ]
})

Callbacks

React to tunnel lifecycle events:
vite.config.ts
import { defineConfig } from 'vite'
import outray from '@outray/vite'

export default defineConfig({
  plugins: [
    outray({
      onTunnelReady: (url) => {
        console.log(`Share this URL: ${url}`)
      },
      onError: (error) => {
        console.error('Tunnel error:', error.message)
      },
      onReconnecting: () => {
        console.log('Connection lost, reconnecting...')
      },
    })
  ]
})

Silent mode

Suppress all console output and handle the URL yourself:
vite.config.ts
import { defineConfig } from 'vite'
import outray from '@outray/vite'

export default defineConfig({
  plugins: [
    outray({
      silent: true,
      onTunnelReady: (url) => {
        // store or forward url as needed
      },
    })
  ]
})

Framework integration

The plugin works with any Vite-based framework. Add it alongside your existing framework plugin:
vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import outray from '@outray/vite'

export default defineConfig({
  plugins: [react(), outray()]
})

TypeScript

The package exports OutrayPluginOptions for typed configuration:
vite.config.ts
import { defineConfig } from 'vite'
import outray from '@outray/vite'
import type { OutrayPluginOptions } from '@outray/vite'

const outrayOptions: OutrayPluginOptions = {
  subdomain: 'my-app',
  apiKey: process.env.OUTRAY_API_KEY,
  onTunnelReady: (url: string) => {
    console.log(`Tunnel ready: ${url}`)
  },
}

export default defineConfig({
  plugins: [outray(outrayOptions)]
})
The full OutrayPluginOptions interface:
interface OutrayPluginOptions {
  subdomain?: string
  customDomain?: string
  apiKey?: string
  serverUrl?: string
  enabled?: boolean
  silent?: boolean
  local?: boolean
  onTunnelReady?: (url: string) => void
  onLocalReady?: (info: {
    hostname: string
    ip: string
    httpUrl?: string
    httpsUrl?: string
  }) => void
  onError?: (error: Error) => void
  onClose?: () => void
  onReconnecting?: () => void
}

Compatibility

  • Vite: 4.x, 5.x, 6.x, 7.x
  • Servers: TCP ports only — Unix domain sockets are not supported.

Troubleshooting

Tunnel not starting
  • Confirm your Vite dev server is listening on a TCP port.
  • Check that OUTRAY_ENABLED is not set to "false".
  • Verify your API key is valid if using a reserved subdomain.
Authentication errors
  • Run outray login to authenticate, or set OUTRAY_API_KEY.
Connection issues
  • The plugin reconnects automatically on connection loss.
  • Confirm the server URL is correct (default: wss://api.outray.dev/).

Build docs developers (and LLMs) love