Farther ShoreDocs
Go to Farther Shore
Frontend SDK
Root & data components
Auth & sessions
Access-aware UI
Permission gates
Custom components
Variables
Public: FSPUBLIC values ship to every visitorSecret: everything else stays privateEnvironment resolutionRebuild behaviorRotate, revoke, and deleteChoosing the name
@farthershore/farthershore-js
Share with another member
Shared and private in one portal
@farthershore/farthershore-js exports
@farthershore/farthershore-js/react exports
@farthershore/farthershore-js/test-utils exports
@farthershore/farthershore-js/errors exports
@farthershore/farthershore-js/components exports
@farthershore/farthershore-js/components/docs-chrome exports
frontend-sdk HTTP contracts
Status
Docs/Build the customer UI/Variables

Variables

Every variable is a write-only secret unless its name starts with FS_PUBLIC_.

Variables are platform-owned, environment-resolved values stored outside the repository. There is nothing to configure about how a value is delivered: the name is the class.

NameClassBrowser readable?Where it goesRebuild after a change?
FS_PUBLIC_*publicYes — every visitorthe frontend build environment, then the shipped bundleYes
anything elsesecretNo — write-onlythe frontend build environment (leak-scanned), and the edge when an integration references itNo

A secret is never returned by the API, CLI, or dashboard after you set it; you can rotate it, not read it back. A public value is returned by variable listing because anyone can already read it from the shipped bundle.

Farther Shore Variables do not set environment variables in your backend application process. Put FS_RUNTIME_TOKEN, database URLs, and other backend process secrets in that deployment provider's secret manager.

Public: FS_PUBLIC_ values ship to every visitor

Use the FS_PUBLIC_ prefix only for values the provider explicitly documents as safe for every visitor: a PostHog project key, a Stripe publishable key, a Sentry DSN, a Supabase anonymous key.

bash
printf '%s' "$POSTHOG_PROJECT_KEY" | \
  farthershore variables set my-business FS_PUBLIC_POSTHOG_KEY --idempotency-key <persisted-variables-set-attempt-key>

The value enters the frontend build and is inlined into the bundle. Read it in the managed frontend as import.meta.env.FS_PUBLIC_POSTHOG_KEY. It is deliberately excluded from secret leak scanning, because appearing in the bundle is its purpose.

The dashboard asks for one confirmation before creating a public variable. Never put a secret key behind the prefix, regardless of what the value is called elsewhere.

The retired bundler prefixes (PUBLIC_, NEXT_PUBLIC_, VITE_PUBLIC_) are rejected as names, so a public-looking name can never be a secret by accident.

Secret: everything else stays private

A variable without the prefix is a secret. It is available to the isolated frontend build (the runner exposes it to the build command, removes the temporary assignment, and fails the build if the value survives into the output in any supported encoding), and it is injected at the edge for any compiled fs.frontendIntegration() that references it by name.

bash
printf '%s' "$SENTRY_AUTH_TOKEN" | \
  farthershore variables set my-business SENTRY_AUTH_TOKEN --idempotency-key <persisted-variables-set-attempt-key>

printf '%s' "$PROVIDER_SECRET" | \
  farthershore variables set my-business PROVIDER_SECRET --idempotency-key <persisted-variables-set-attempt-key>
ts
const response = await fs.integration("provider").fetch("/v1/messages", {
  method: "POST",
  body: { kind: "json", value: { message } },
});

You do not declare where a secret is used. When a compiled integration names it in secretRef, the platform publishes it to the edge; when no active integration references it any more, it is retired from the edge. Browser code never receives the secret or chooses the upstream URL. Referencing an FS_PUBLIC_ name from secretRef is a compile error.

A secret is not a runtime server environment. Hosted frontends are static artifacts; if browser behavior needs a private credential at request time, use a backend route or a compiled integration.

Environment resolution

Variables are resolved by name for the selected business environment:

  • a branch environment value overrides Main;
  • when the branch has no row for that name, it inherits Main;
  • changing a branch value does not modify Main;
  • deleting/revoking the branch override reveals the inherited effective state only after the lifecycle operation completes.

Use --env with a preview environment name or id:

bash
printf '%s' "$STAGING_KEY" | \
  farthershore variables set my-business FS_PUBLIC_POSTHOG_KEY --env staging --idempotency-key <persisted-variables-set-attempt-key>

farthershore variables list my-business --env staging --format json

The frontend build and the edge path resolve the same environment selection. Environment routing is platform-owned; frontend code should not switch values by hostname itself.

Rebuild behavior

A public value is part of the bundle, so creating, rotating, revoking, or deleting one enqueues a rebuild for that environment once the new generation is effective.

A secret does not rebuild the frontend. It never enters the bundle; the edge uses the new generation as soon as it is published, and the next build picks it up on its own.

Monitor the mutation and any resulting build:

bash
farthershore variables status my-business <operation-id> --format json
farthershore frontend status my-business --wait

Because a variable mutation has no Git commit identity, this unpinned wait is advisory only. Add --env <environment-id> to frontend status for a preview build. For a Git-triggered build, use --ref "$(git rev-parse HEAD)" --wait instead.

Rotate, revoke, and delete

Values are read from stdin, never from a CLI argument:

bash
printf '%s' "$NEW_VALUE" | \
  farthershore variables rotate my-business PROVIDER_SECRET --idempotency-key <persisted-variables-rotate-attempt-key>

farthershore variables revoke my-business PROVIDER_SECRET --yes --idempotency-key <persisted-variables-revoke-attempt-key>
farthershore variables rm my-business PROVIDER_SECRET --yes --idempotency-key <persisted-variables-rm-attempt-key>

Names are immutable. Because the name is the class, turning a secret into a public value (or back) means revoking, deleting, and creating it under the new name — a value can never silently cross that boundary.

revoke removes a value from future builds and, for a secret an integration references, from the edge once the platform acknowledges it. rm permanently destroys ciphertext and requires the variable to be revoked first. Use variables status when a mutation reports publication pending.

Choosing the name

  • If every browser user may inspect the value, start the name with FS_PUBLIC_.
  • Otherwise it is a secret — the build can use it, a compiled integration can inject it, and no one can read it back.
  • If your own server process needs it, use the server host's secret manager, not a frontend Variable.
PreviousCustom componentsNext@farthershore/farthershore-js

On this page

Public: FSPUBLIC values ship to every visitorSecret: everything else stays privateEnvironment resolutionRebuild behaviorRotate, revoke, and deleteChoosing the name