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:
- Use the SDK directly via
npm:specifiers (Deno) - 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.aiThe SDK uses only fetch and standard Web APIs internally — no Node.js-specific modules. It should work in any runtime that supports fetch.
Option 2: REST API with fetch (recommended for edge)
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 temperatureRender 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 environment | Typical mapping |
|---|---|
development | Local dev, preview branches |
staging | Staging/QA Supabase project |
production | Production 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.