Server and SSR

Evaluate public and private flags from your server with @coframe/sdk/server, or call the Edge endpoint from any language

Guide~3 min read

Copy this guide and your current settings as a prompt for your AI agent.

Preview agent promptSee the guide, code and settings included when you copy.

Server code sends a server API key and gets public and private flags. Every call is async and carries apiKey and projectId; the key stays in an environment variable and never reaches a browser bundle.

On this page
  1. 01Node and server-side rendering
  2. 02Any language: the HTTP endpoint

01Node and server-side rendering

TS
import {
  evaluateFlags,
  isFeatureEnabled,
  getFeatureFlag,
  getRemoteConfig,
} from '@coframe/sdk/server'

const options = {
  projectId: 'your-project-id',
  apiKey: process.env.COFRAME_FEATURE_FLAGS_SERVER_KEY!,
  userToken: user.id,
  currentUrl: request.url,
  userContext: { plan: user.plan },
}

const cart = await evaluateFlags({ ...options, selector: { groups: ['cart_checkout'] } })
const enabled = await isFeatureEnabled('checkout-redesign', { ...options, defaultValue: false })
const variant = await getFeatureFlag('checkout-layout', options)
const nav = await getRemoteConfig('navigation-config', options)
Function Behaviour
evaluateFlags(options) One request for several flags; returns the full response (flags, errorsWhileComputingFlags, requestId, snapshotVersion)
getFeatureFlagResult, getFeatureFlag, isFeatureEnabled(key, { defaultValue }), getFeatureFlagPayload / getRemoteConfig Each sends its own request for one flag

Options: apiKey, projectId, userToken, selector, requestTimeoutMs (default 3000), edgeUrl, and the context fields currentUrl, languages, browserPlatform, country, device, userVisitCount, userContext.

On a timeout, a network error or a non-2xx response the helpers return undefined. Pass a defaultValue so your code always has a safe answer.

Identity on the server

Only what you pass counts. Use userToken: user.id, or read the coframe.user.token cookie yourself to share identity with the browser SDK. Pass nothing and any partial rollout or weighted split answers missing_user_token. Never make up a fresh id per request: every request would land in a different bucket.

Rendering a page

Evaluate with the key on the server, then pass only the public flags into the HTML the browser receives. Keep an allow-list of the public keys your page needs and drop everything else from the server’s answer. A private flag’s answer can still shape the page, for example a trusted checkout mode, as long as only the outcome reaches the browser.

02Any language: the HTTP endpoint

HTTP
POST https://edge.cofra.me/api/v1/flags
Content-Type: application/json
Authorization: Bearer cffs_v1_…        (only for private flags; never from a browser)

{
  "projectId": "your-project-id",
  "userToken": "customer-123",
  "selector": { "groups": ["cart_checkout"] },
  "currentUrl": "https://shop.example.com/checkout",
  "languages": ["en-US", "en"],
  "userContext": { "plan": "pro" }
}
JSON
{
  "flags": {
    "checkout_experience_v1": {
      "key": "checkout_experience_v1", "enabled": true, "reason": "condition_match",
      "variant": "standard", "payload": { "layout": "standard", "cta": "Place order" },
      "metadata": { "version": 1 }
    },
    "checkout_v2": { "key": "checkout_v2", "enabled": false, "reason": "no_matching_condition", "metadata": { "version": 1 } },
    "navigation-config": {
      "key": "navigation-config", "enabled": true, "reason": "remote_config",
      "payload": { "theme": "ocean", "navigation": "compact" }, "metadata": { "version": 1 }
    }
  },
  "errorsWhileComputingFlags": false,
  "requestId": "…uuid…",
  "snapshotVersion": 4
}
Field Notes
projectId Required
userToken Up to 512 characters. Needed for partial rollouts and weighted variants
selector names and/or groups, up to 100 each; the union is evaluated, unknown keys are skipped. Omit it for every flag
currentUrl Absolute URL, up to 4,096 characters
languages, browserPlatform, country, device (desktop or mobile), userVisitCount Optional context. Country defaults to the request’s cf-ipcountry; device is detected from the user agent when omitted
userContext Your own properties, up to 4 KB of JSON, matched by User property conditions

Every response is Cache-Control: private, no-store, so no CDN or browser shares one visitor’s answer with another. The snapshot is read from the Edge store on every request, so a publish is visible on the next request.

See Reference for the status codes and the reason values.

Related reading

Content and video lessons from Coframe documentation. Code examples are not executed on this page.

BACK TOFeature Flags

Documentation

Open Coframe App

Search documentation

Search all guides and references↑ ↓ Navigate · Esc Close