Documentation
Node.js
Nuxt

Nuxt is the Vue full-stack framework — SSR, SSG, and API routes in one. Tunnel your Nuxt dev server to test webhooks, share previews, or demo to clients.

Quick Start

npm install -g mekong-cli
mekong auth YOUR_TOKEN
# Terminal 1
npm run dev        # Nuxt starts on http://localhost:3000
 
# Terminal 2
mekong 3000
# → https://happy-tiger-a1b2c3d4.mekongtunnel.dev

Or together:

npx concurrently "nuxi dev" "mekong 3000"

package.json Scripts

{
  "scripts": {
    "dev": "nuxi dev",
    "tunnel": "mekong 3000",
    "dev:share": "concurrently \"nuxi dev\" \"mekong 3000\""
  }
}

Custom Port

nuxi dev --port 3001
mekong 3001

Or in nuxt.config.ts:

// nuxt.config.ts
export default defineNuxtConfig({
  devServer: {
    port: 3001,
  },
})

Nuxt Module (Auto-Tunnel)

Create a local Nuxt module to auto-start the tunnel when the dev server starts:

// modules/mekong-tunnel.ts
import { defineNuxtModule } from '@nuxt/kit'
import { createTunnel } from 'mekong-cli'
 
export default defineNuxtModule({
  meta: { name: 'mekong-tunnel' },
  async setup(_options, nuxt) {
    if (!nuxt.options.dev) return
    nuxt.hook('listen', async (server) => {
      const port = nuxt.options.devServer.port ?? 3000
      const tunnel = await createTunnel({ port })
      console.log(`\n  ➜  Tunnel:  ${tunnel.url}\n`)
    })
  },
})
// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['~/modules/mekong-tunnel'],
})

Environment Variables

# .env
NUXT_PUBLIC_APP_URL=https://happy-tiger-a1b2c3d4.mekongtunnel.dev
NUXT_PUBLIC_API_BASE=https://happy-tiger-a1b2c3d4.mekongtunnel.dev/api
// nuxt.config.ts
export default defineNuxtConfig({
  runtimeConfig: {
    public: {
      appUrl: process.env.NUXT_PUBLIC_APP_URL,
      apiBase: process.env.NUXT_PUBLIC_API_BASE,
    },
  },
})

Access in components:

<script setup lang="ts">
const config = useRuntimeConfig()
const apiBase = config.public.apiBase
</script>

API Routes / Server Handlers

Nuxt API routes (server/api/) are fully reachable through the tunnel:

// server/api/webhook.post.ts
export default defineEventHandler(async (event) => {
  const body = await readBody(event)
  console.log('Webhook received:', body)
  return { status: 'ok' }
})
mekong 3000
# POST https://happy-tiger-a1b2c3d4.mekongtunnel.dev/api/webhook

OAuth with nuxt-auth or sidebase/nuxt-auth

AUTH_ORIGIN=https://happy-tiger-a1b2c3d4.mekongtunnel.dev
AUTH_SECRET=your-secret
GITHUB_CLIENT_ID=...
GITHUB_CLIENT_SECRET=...

Add the callback URL in your OAuth app:

https://happy-tiger-a1b2c3d4.mekongtunnel.dev/api/auth/callback/github

Nitro / h3 Webhooks

// server/api/stripe.post.ts
import Stripe from 'stripe'
 
export default defineEventHandler(async (event) => {
  const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!)
  const body = await readRawBody(event)
  const sig = getHeader(event, 'stripe-signature')!
 
  const stripeEvent = stripe.webhooks.constructEvent(
    body!, sig, process.env.STRIPE_WEBHOOK_SECRET!
  )
 
  if (stripeEvent.type === 'checkout.session.completed') {
    // handle
  }
 
  return { received: true }
})

CORS

// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    '/api/**': {
      cors: true,
      headers: { 'Access-Control-Allow-Origin': '*' },
    },
  },
})

Nuxt 3 vs Nuxt 2

Both versions work with the tunnel. Nuxt 3 uses nuxi dev (port 3000), Nuxt 2 uses nuxt dev (port 3000). The tunnel command is identical: mekong 3000.