Designed for tablet+. View on a tablet or larger screen for the intended layout.
CORE_WORKSHOP_v1.0
SPEAKER NOTES MODE — press s to hide
BLOCK 4 · AI GATEWAY (PRODUCTION) 4:20 – 4:40 · 20 min · 5L / 15HO · Lab

TOPIC 4.9 / 10 · ★ LOAD-BEARING (VueConf payoff)

Nuxt integration lab

The boundary in code. Vue knows useFetch. The server route knows Bifrost. Bifrost knows everything else. Wire it. Watch a 402 fire when the budget caps out.

★ LOAD-BEARING (VueConf audience payoff)

4.9.1

The boundary

5 min Lecture 4:20 – 4:25
Slide 1 / 3 · What Vue knows

The boundary in one frame

VUE KNOWS                    │ GATEWAY KNOWS
─────────────────────────────┼─────────────────────────────
the gateway URL              │ providers
the Virtual Key (Bearer)     │ models + aliases
useFetch                     │ routing rules
                              │ budgets
                              │ semantic cache
                              │ prompt repository
                              │ guardrails (if enterprise)
                              │ audit logs (if enterprise)

Vue doesn't know about providers. Vue doesn't hold API keys.

Slide 2 / 3 · The starter app

Four files

nuxt-app/
├── nuxt.config.ts          # runtimeConfig: bifrostUrl, workshopVk
├── pages/index.vue         # chat UI — useFetch against /api/chat
├── server/api/chat.post.ts # server route → POST to Bifrost
└── .env                    # BIFROST_URL, WORKSHOP_VK
Slide 3 / 3 · Why through a server route

Don't call Bifrost from the browser

  • CORS — Bifrost doesn't ship browser-CORS by default
  • VK secrecy — if you call Bifrost from the browser, the VK is in the bundle
  • Server route is the right shape — useFetch → Nuxt server → Bifrost
  • The Nuxt server is your application's secret boundary
4.9.2

Wire Nuxt to Bifrost

10 min 10HO 4:25 – 4:35 ★ LOAD-BEARING (VueConf payoff in code)
Slide 1 / 3 · Three steps to wired

HO #7 — Wire Nuxt to Bifrost (10 min)

  1. Confirm .envBIFROST_URL=http://localhost:8080 + WORKSHOP_VK=<your VK>
  2. Run cd nuxt-app && npm run dev — Nuxt boots on localhost:3000
  3. Send a message in the UI — confirm reply renders
  4. Check the gateway — Bifrost dashboard → ObservabilityLLM Logs → request attributed to your VK
Slide 2 / 3 · Reading chat.post.ts

What the server route does

// the workshop's actual shape
export default defineEventHandler(async (event) => {
  const { prompt } = await readBody<{ prompt: string }>(event)

  const result = await callBifrost({
    model: 'anthropic/claude-sonnet-4-6',
    messages: [{ role: 'user', content: prompt }],
    max_tokens: 500,
  })

  return { reply: result.choices[0]?.message?.content ?? '' }
})
export async function callBifrost(body: ChatRequest) {
  const { bifrostUrl, workshopVk } = useRuntimeConfig()
  return await $fetch(`${bifrostUrl}/v1/chat/completions`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${workshopVk}`,
    },
    body,
  })
}

Two files. chat.post.ts shapes the request; bifrost.ts hides the gateway. Vue never sees either.

Also lives in chat.post.ts (not shown above for slide brevity): the 402 → 403 translation — when Bifrost returns 402 Payment Required for a tripped budget, the server route surfaces it as a 403 with a reason: 'Budget cap exceeded...' so the UI's policy-warning branch lights up. (Beat 4.9.3 leans on this.)

Slide 3 / 3 · What success looks like

Success criteria

  • Nuxt UI shows a chat box · message types render
  • Bifrost dashboard → ObservabilityLLM Logs → new request appears
  • Request is attributed to workshop-vk-1
4.9.3

Watch the system work

5 min 5HO 4:35 – 4:40
Slide 1 / 2 · Trip the budget

Make a 402 happen

  • Send messages rapidly until the $0.50 budget caps out
  • Bifrost returns 402 Payment Required
  • Your server route sees the 402, surfaces it as a 4xx to the UI
  • Vue UI doesn't have to know whether it's a budget cap, a guardrail, or a downstream outage
Slide 2 / 2 · Reset

Recovery

  • Wait for the 1h reset (workshop budget is small on purpose)
  • Or delete + recreate the budget in the dashboard
  • In production: alert on 402, auto-page, audit, dashboard