License

Setup

The first license doc to read. Gets a project from no key at all to Flux running Pro/Enterprise features on your domain — four env vars and one line of code, zero portal screenshots required to follow along.

Prerequisites
  • A portal account at tsworldtechflux.dev/portal
  • A createFlux() call already in place — see api/create-flux if not
1

Where your credentials come from

Every value on this page lives in exactly one place. There's no secondary source, no CLI-generated alternative — if a value below doesn't match what's on the License tab, the License tab is correct.
typescript
1// Every value on this page comes from ONE place — nowhere else:
2//
3// 1. Log into tsworldtechflux.dev/portal
4// 2. Buy a key, if you don't already have one
5// 3. Create a project — or open an existing one
6// 4. Link the key to that project
7// 5. Open the project's License tab
8//
9// A key by itself is not enough to run Flux. A key with no project
10// linked has no domains[], no token, and no secret — nothing to
11// unlock yet. The project is what turns a billing object into a
12// runnable license.
2

Four values, four jobs

Only FLUX_LICENSE_TOKEN is safe to expose to the browser. The other three stay server-side, and only matter once you wire up daily reporting.
bash
1# .envfour values, four separate jobs. Only ONE of these is safe
2# to expose to the browser.
3
4# The signed JWT your app ships to the browser. This is what
5# verifyLicense() checks client-side (Section 4.12) — tier, quota,
6# domains[], and webhook config, all signed, all tamper-evident.
7NEXT_PUBLIC_FLUX_LICENSE_TOKEN=eyJhbGciOiJFUzI1NiIs...
8
9# The billing account this project's license rolls up to. Not a
10# secret, but keep it server-side anywayit only needs to exist
11# inside your daily report call (license/webhook-setup), not in a
12# client bundle.
13FLUX_KEY_ID=flux_ent_xyz789
14
15# Which project within that key this report describes. Required
16# because one Enterprise key can back many projectswithout this,
17# the report endpoint has no way to know whose domains[]/quota/
18# webhook config a given day's numbers belong to.
19FLUX_PROJECT_ID=proj_abc123
20
21# Authenticates your server's daily report call. NEVER sent to the
22# browser, NEVER embedded in the token. If this leaks, someone could
23# submit forged usage reports for your projectregenerate it from
24# the License tab if that ever happens.
25FLUX_LICENSE_SECRET=sk_live_550e8400...
FLUX_PROJECT_ID vs. the project_id inside your token

These are related but not the same thing, and only one of them needs your attention.

typescript
1// Easy to conflate, so worth separating explicitly:
2//
3// FLUX_PROJECT_ID (the env var above) — a SERVER-side value, only
4// ever read inside your daily report call. Your client bundle never
5// sees it and doesn't need to.
6//
7// The project_id INSIDE your signed token — a different thing, even
8// though it's the same underlying ID. This one IS read client-side,
9// automatically, by verifyLicense() — it's how Flux knows which
10// project's public key to fetch when verifying a project-scoped
11// token's signature (see license/domain-binding, Step 1). You never
12// set this yourself; it's baked into the token at issuance.
13//
14// You will never need to read or pass project_id manually on the
15// client — this is purely for understanding what's happening when
16// you inspect a decoded token payload.
3

Minimal client-side wiring

This is the entire licensing surface on the client — one field on the config object passed to createFlux().
typescript
1import { createFlux } from '@tsworldtech/flux'
2import { createSupabaseAdapter } from '@tsworldtech/flux-supabase'
3
4const flux = createFlux({
5 adapter: createSupabaseAdapter(supabaseClient),
6 license: process.env.NEXT_PUBLIC_FLUX_LICENSE_TOKEN,
7})
8
9// That's the entire licensing surface on the client. No .init(), no
10// callback, no async wait — verifyLicense() and enforceOnBoot() run
11// inside createFlux() as a single step (Section 4.14) and never
12// block app startup, license valid or not.
4

What happens if you skip this entirely

Worth reading before assuming licensing is blocking anything — it isn't, by design.
typescript
1// What happens if you don't set FLUX_LICENSE_TOKEN at all:
2
3const flux = createFlux({
4 adapter: createSupabaseAdapter(supabaseClient),
5 // no license field
6})
7
8// - Every feature your tier would unlock still runs. Nothing is
9// feature-gated behind a missing key at the mechanism level.
10// - A styled console watermark appears — in production only, never
11// during local dev, staging, or preview deployments (the same
12// exemption list as license/domain-binding, Step 5).
13// - Nothing breaks. Nothing degrades. Nothing is time-bombed.
14//
15// This is deliberate, not an oversight — see
16// core-concepts/what-flux-is-not for why.
Nothing here is a kill switch

License enforcement is console-only and non-blocking. A missing or invalid token downgrades to free-tier behavior — it never breaks a build, never throws, and never disables the app.

Next up: license/domain-binding covers why your token is tied to a domain, what happens if it's used elsewhere, and the one case where verification touches the network. license/quotas covers what "500,000 events/month" actually counts. license/webhook-setup covers the server-side half — daily reports and theft-mismatch webhooks.