Farther ShoreDocs
Go to Farther Shore
What is FartherShore
Install the CLI
Quickstart
Core concepts
The @Product class
Meters & resources
Features & routes
Capabilities & entitlements
Plans & pricing
The Manifest IR
Bring your own backend
Transport modes
Metering & verification
Runtime tokens
Frontend SDK
Root & data components
Auth & sessions
Entitlement gates
Connect Stripe
Subscriptions & usage
Plan changes & grandfathering
Billing strategies
Apply & deploy
Environments
Migrations
Docs versions & archive
Operate with an agent
Operation classes
MCP server
End-to-end via CLI/MCP
CLI reference
@farthershore/product
@farthershore/backend
@farthershore/farthershore-js
ClientClient namespacesReact (/react)Components (/components)Errors and deny codesCatalog helpers
Environment variables
Response & deny codes
Add a metered capability
Gate a feature
Change a price
Prepaid credits
Meter AI tokens
Operate via an agent
Prepare for launch
Status
Docs/Reference/@farthershore/farthershore-js

@farthershore/farthershore-js

The browser client, React hooks, and managed component kit.

Previous@farthershore/backendNextEnvironment variables

@farthershore/farthershore-js is the Frontend SDK — the browser integration layer between a static frontend artifact and the platform. Your frontend code never sees Core URLs, gateway URLs, or auth endpoints; it expresses intent and the SDK decides where each request goes (Core for platform concerns, the Gateway for builder features), how it's authenticated, and the host/env scoping. Pin it in lockstep with @farthershore/product and @farthershore/backend.

pnpm add @farthershore/farthershore-js   # react is an optional peer (for /react)

Client

import { createFartherShoreClient } from "@farthershore/farthershore-js";

const fs = createFartherShoreClient({ coreUrl: "https://core.farthershore.com" });

const { product, plans } = await fs.bootstrap();          // → Core (discover this host)
await fs.auth.signIn({ apiKey: "fsk_test_…" });            // persona/preview env
const usage = await fs.usage.snapshot();                   // → Core
fs.setApiKey("fsk_live_…");
const forecast = await fs.feature("weather").json("/forecast?city=NYC"); // → Gateway

On platform-served portals, createFartherShoreClient() needs no config — the edge injects window.__FS_CONFIG__ and the SDK falls back to it. Everywhere else coreUrl is required. Constructors:

FactoryUse
createFartherShoreClient(config)The browser client. coreUrl is usually the only required field; portalHost defaults to window.location.host.
createFartherShoreClientFromEnv()Reads config from the bundler env / edge-injected window.__FS_CONFIG__.
createServerClient(config)SSR alias — pass portalHost, fetch, and a per-request getToken (no browser globals).

Config fields: coreUrl, portalHost, productId, environmentId, organizationId, gatewayUrl, apiKey, getToken, fetch.

Client namespaces

The client routes each namespace to Core or the Gateway:

NamespaceRoutes toMethods
fs.bootstrap()Core (public resolve)discover product / env / gateway / capabilities (memoized)
fs.product(bootstrap)get()
fs.authCoregetSession(), signIn({ apiKey }), signOut(), setToken()
fs.keysCorelist(), create(), revoke(), rotate()
fs.usageCoresummary(), events(), snapshot()
fs.billingCoresubscription(), openBillingPortal(), creditBalance()
fs.plansCore / (bootstrap)list(), subscribe()
fs.feature(name) / fs.invoke(path)Gatewayfetch(path), json(path)
fs.setApiKey(key)—set the consumer key for Gateway calls

Core calls use the consumer session token (Authorization: Bearer); Gateway calls use the consumer API key (fsk_…).

React (/react)

Hooks live in a subpath; react is an optional peer. Each hook returns { data, loading, error, refresh } plus its mutations.

import { createFartherShoreClient } from "@farthershore/farthershore-js";
import { FartherShoreProvider, useApiKeys } from "@farthershore/farthershore-js/react";

const fs = createFartherShoreClient({ coreUrl: import.meta.env.VITE_CORE_URL });

function App() {
  return (
    <FartherShoreProvider client={fs}>
      <Portal />
    </FartherShoreProvider>
  );
}

function ApiKeys() {
  const { data, loading, create, revoke, rotate } = useApiKeys();
  // …
}
HookReturns
useFartherShore()The raw client.
useBootstrap(), useProduct(), useDeclaredResources()Bootstrap + product + declared resources.
useSession()Session (+ signIn / signOut).
useApiKeys()Keys (+ create / revoke / rotate).
useUsage(), usePinnedUsageRows()Usage snapshot + pinned billing rows.
useBilling()Subscription (+ openBillingPortal).
usePlans(), useCreditBalance(), useSpendCap()Catalog, prepaid balance, spend cap.
useEntitlements(), useFeatureGate(), useCapability(), useCapabilityUsage()Entitlement + capability checks.
useApiRateLimit(), useFeature(name)Rate-limit snapshot; a Gateway feature handle.
useMe(), useSubscriptionContexts()The current subscriber + their subscription contexts.
useTeam(), useAuditLogs(), usePaginatedAuditLogs()Team + audit logs.
useResourcesList(), useResource(), useResourceUsage()Counted resources.
useUpgrade(), useResourceCap(), useReconcileAfterCheckout()Upgrade targets; checkout-return reconciliation.
useOrganization()Multi-org reactivity (the provider mounts the layer automatically).

Components (/components)

The managed component kit. Every component works with zero props under <FartherShoreRoot> (data via the SDK hooks); props are optional overrides, and every one accepts className. Import the stylesheet once: import "@farthershore/farthershore-js/components/styles.css".

import { FartherShoreRoot, PlansTable, UsageCard, BillingSummary, ApiKeysPanel }
  from "@farthershore/farthershore-js/components";

<FartherShoreRoot>
  <PlansTable />
  <UsageCard />
  <BillingSummary />
  <ApiKeysPanel />
</FartherShoreRoot>;
GroupComponents
Mount + chromeFartherShoreRoot, useBoot, FsErrorBoundary, FsBranding, FsThemeToggle, FsFooter, FsSplash
ThemingFsThemeProvider, useFsTheme
Auth (managed)FsAuthProvider, useFsAuth, useOptionalFsAuth, FsSignIn, FsSignInButton, FsSignOutButton, FsUserButton, SignedIn, SignedOut, AuthLoading
Auth-gated routingRequireAuth, useAuthGuard, planAuthGuard, resolveSignInDestination
DataPlansTable, ApiKeysPanel, UsageCard, BillingSummary, CreditBalance, FeaturePanel, ResourcesPanel, DocsLegal
Gating + promptsFeatureGate, RequireCapability, UpgradePrompt, TopUpPrompt, SpendCapControl, OrgSwitcher, FsLimitBoundary, useLimitHandler
Data-richTeamPanel, CancelSubscription, TrialBanner, CapabilityUsageCard, OnboardingView, AutoKeyBanner, PaymentHealthBanner, AuditLogTable, RateLimitDisplay, BillEstimator
Manifest navFsManifestNav — renders a product-authored frontendManifest.nav after a fork
CompositeFartherShoreApp, FsPricing — one-tag portal
DocsProductDocs, useProductDocs, plus the composable shell parts and markdown renderers

<FartherShoreRoot> is one wrapper = provider + bootstrap gate + theme-from-branding

  • managed auth (Clerk satellite / persona, picked from the environment). No host glue.

Errors and deny codes

Branch on FartherShoreApiError.code against the gateway deny vocabulary. See response & deny codes.

import {
  FartherShoreApiError, LimitExceededError, FartherShoreRateLimitedError,
  FS_DENY_CODES, isThrottled, isRetryable,
} from "@farthershore/farthershore-js";

try {
  await fs.feature("cron-jobs").json("/v1/cron-jobs");
} catch (err) {
  if (err instanceof FartherShoreApiError && err.code === FS_DENY_CODES.rate_limited) {
    // back off and retry
  }
}

Typed error classes: FartherShoreApiError, FartherShoreNetworkError, FartherShoreAbortError, FartherShoreNotReadyError, FartherShoreConfigError, LimitExceededError, FartherShoreRateLimitedError, FeatureNotGrantedError, FartherShoreLifecycleBlockedError, FartherShoreSubscriptionConflictError, FartherShoreBillingNotConfiguredError. Guards: isRetryable, isThrottled, isBillingNotConfigured; parsers: parseLimitDescriptor, parseRetryAfterSeconds, parseRateLimit.

Catalog helpers

Pure display helpers (a port of the SSR portal's renderers) so any frontend renders the catalog identically: classifyPlan, isFreePlan, formatPlanPrice, formatCents, formatPriceFromMicros, formatDate, summarizeMeterPricing, entitlementBullets, buildGrantRows, quotaForDimension, estimateBill, describePlanLimit, subscriptionStatusChip, trialDaysRemaining, paymentHealth, plus the CSV exporters (usageToCsv, downloadCsv) and top-up bounds (TOP_UP_MIN_CENTS, validateTopUpAmount).

Pin all three SDKs to the same exact version (currently 0.8.2). Under SemVer 0.x a minor bump may break — caret ranges (^0.8) are unsafe; use an exact pin or a patch-only tilde (~0.8.2) until 1.0.0.