Everything the hosted Serql business needs that is not part of the open-core product lives here, under the Serql Commercial License rather than the repository's AGPL-3.0 license. Delete this directory and the core app still builds and runs.
| Directory | What it is | Enabled by |
|---|---|---|
billing/ |
Stripe entitlements, checkout, portal, webhook handling, the /subscribe and settings/billing pages, and launch-audit scripts |
STRIPE_SECRET_KEY (server); NEXT_PUBLIC_STRIPE_ENABLED=true shows paid-plan UI links |
marketing/ |
Landing page, legal pages, changelog, newsletter signup | NEXT_PUBLIC_EE_MARKETING=true; NEXT_PUBLIC_MARKETING_ASSETS_URL for screenshots |
telemetry/ |
Consent-gated PostHog and Vercel Analytics/Speed Insights | NEXT_PUBLIC_POSTHOG_KEY, NEXT_PUBLIC_VERCEL_TELEMETRY=true |
src/ee/index.ts exposes the pure env predicates (isBillingEnabled(),
isMarketingEnabled(), ...). It has no side effects and is safe in client,
edge, and server code.
Core code (everything outside src/ee) must not import @/ee directly. It
is enforced by the no-restricted-imports rule in eslint.config.mjs and
the "Open-core boundary" CI job. The only places allowed to cross it are:
src/lib/access/**— the entitlement/billing-hooks seam. Core readsEntitlementvalues and callsbillingHooks; the seam picks the Stripe provider from@/ee/billingwhen billing is enabled and the unlimited provider otherwise.- Route shims in
src/app/**(page.tsx,layout.tsx,route.ts,actions/**,sitemap.ts) that re-export ee pages and handlers. Each ee page/handler returnsnotFound()/ a 404 JSON body when its feature is disabled. - A few explicit adapters:
src/lib/machine-route-bypass.ts(webhook paths),src/components/shared/consent-banner.tsx(renders only when a consent-gated integration exists), andsrc/app/(app)/app-layout-shell.tsx(support widget).
When adding an ee feature, extend the seam or add a shim; never import ee modules from other core files.
npm run test:ee-unitruns the billing, telemetry, and marketing unit tests.- Playwright specs under
tests/ee/skip themselves unless the matching env flag is set.