GuidesDeno & Edge Functions

Deno & Edge Functions

The VersionR SDK is built for Node.js and browser environments. If you’re running on Deno, Supabase Edge Functions, Cloudflare Workers, or other edge runtimes, you have two options:

  1. Use the SDK directly via npm: specifiers (Deno)
  2. Call the REST API with fetch (works everywhere)

Option 1: SDK via npm specifier (Deno)

Deno supports npm packages natively. Import the SDK with the npm: prefix:

import { VersionR } from 'npm:versionr'
 
const pd = new VersionR({
  apiKey: Deno.env.get('VERSIONR_API_KEY')!,
  baseUrl: Deno.env.get('VERSIONR_BASE_URL') ?? 'https://api.versionr.ai',
})
 
const prompt = await pd.get('system-prompt', { env: 'production' })
console.log(prompt.content)
⚠️

Required environment variables: You must set both VERSIONR_API_KEY and VERSIONR_BASE_URL in your edge function’s secrets. Without VERSIONR_BASE_URL, the SDK defaults to https://api.versionr.ai. For Supabase Edge Functions, set these via the dashboard (Edge Functions → Secrets) or CLI:

supabase secrets set VERSIONR_API_KEY=your-key VERSIONR_BASE_URL=https://api.versionr.ai

The SDK uses only fetch and standard Web APIs internally — no Node.js-specific modules. It should work in any runtime that supports fetch.


For maximum compatibility, call the VersionR API directly. This works in any runtime — Deno, Cloudflare Workers, Vercel Edge, Supabase Edge Functions, or a plain browser.

Fetch a prompt

const res = await fetch(
  'https://api.versionr.ai/v1/sdk/prompts/system-prompt?env=production',
  {
    headers: { Authorization: `Bearer ${Deno.env.get('VERSIONR_API_KEY')!}` },
  }
)
const prompt = await res.json()
// prompt.promptId — unique prompt ID
// prompt.promptSlug — the slug you requested
// prompt.content — the raw prompt text
// prompt.model — the model name (e.g. 'gpt-4o')
// prompt.temperature — the configured temperature

Render with variables

const res = await fetch(
  'https://api.versionr.ai/v1/sdk/prompts/system-prompt/render',
  {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${Deno.env.get('VERSIONR_API_KEY')!}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      env: 'production',
      variables: {
        candidate_name: 'Eoin',
        job_role: 'Senior Engineer',
      },
    }),
  }
)
const rendered = await res.json()
// rendered.rendered — prompt with variables substituted
// rendered.content — original prompt text (before substitution)

Log a result

await fetch('https://api.versionr.ai/v1/logs', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${Deno.env.get('VERSIONR_API_KEY')!}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    promptId: prompt.promptId,
    promptSlug: prompt.promptSlug,
    versionId: prompt.versionId,
    versionNumber: prompt.versionNumber,
    environment: 'production',
    renderedPrompt: rendered.rendered,
    llmResponse: response.text,
    latencyMs: 340,
    promptTokens: 120,
    completionTokens: 88,
    estimatedCostUsd: 0.002,
  }),
})

Supabase Edge Functions

A complete example using Supabase Edge Functions:

// supabase/functions/my-function/index.ts
import { serve } from 'https://deno.land/std/http/server.ts'
 
serve(async (req) => {
  const apiKey = Deno.env.get('VERSIONR_API_KEY')!
  const baseUrl = Deno.env.get('VERSIONR_BASE_URL') ?? 'https://api.versionr.ai'
 
  // Fetch the active prompt
  const promptRes = await fetch(
    `${baseUrl}/v1/sdk/prompts/system-prompt?env=production`,
    { headers: { Authorization: `Bearer ${apiKey}` } }
  )
  const prompt = await promptRes.json()
 
  // Use the prompt with OpenAI
  const startTime = Date.now()
  const llmRes = await fetch('https://api.openai.com/v1/chat/completions', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${Deno.env.get('OPENAI_API_KEY')}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      model: prompt.model,
      temperature: prompt.temperature,
      messages: [
        { role: 'system', content: prompt.content },
        { role: 'user', content: 'Hello!' },
      ],
    }),
  })
  const llmData = await llmRes.json()
  const latencyMs = Date.now() - startTime
 
  // Log the result back to VersionR
  await fetch(`${baseUrl}/v1/logs`, {
    method: 'POST',
    headers: { Authorization: `Bearer ${apiKey}`, 'Content-Type': 'application/json' },
    body: JSON.stringify({
      promptId: prompt.promptId,
      promptSlug: prompt.promptSlug,
      versionId: prompt.versionId,
      versionNumber: prompt.versionNumber,
      environment: 'production',
      renderedPrompt: prompt.content,
      llmResponse: llmData.choices[0].message.content,
      latencyMs,
      promptTokens: llmData.usage.prompt_tokens,
      completionTokens: llmData.usage.completion_tokens,
      estimatedCostUsd: 0,
    }),
  })
 
  return new Response(JSON.stringify(llmData.choices[0].message), {
    headers: { 'Content-Type': 'application/json' },
  })
})

Cloudflare Workers

The same fetch-based pattern works in Cloudflare Workers:

export default {
  async fetch(request, env) {
    const promptRes = await fetch(
      'https://api.versionr.ai/v1/sdk/prompts/system-prompt?env=production',
      { headers: { Authorization: `Bearer ${env.VERSIONR_API_KEY}` } }
    )
    const prompt = await promptRes.json()
 
    // Use prompt.content with your LLM of choice...
    return new Response(prompt.content)
  },
}

Environment mapping

VersionR’s three environments map naturally to multi-environment setups:

VersionR environmentTypical mapping
developmentLocal dev, preview branches
stagingStaging/QA Supabase project
productionProduction Supabase project

Set VERSIONR_API_KEY per environment and pass env accordingly. Each environment has its own independent active version pointer — deploying to staging never affects production.


MIT 2026 © Nextra.