N
HeadlessCoreHeadless Core
Back to Home

Licensing

HeadlessCore uses an open-core licensing model. The core codebase is MIT-licensed and works fully without a license key. A valid key unlocks pro features.

Free tier (no key required)

  • All 8 site modes and demo layouts
  • WPGraphQL schema, CPTs, contact form
  • ISR, revalidation, preview mode
  • CLI scaffold, Docker, documentation
  • Footer shows: POWERED BY WP-GRAPHQL & NEXTJS APP ROUTER

Pro tier (valid license key)

Currently unlocked with a valid key:

  • Removes frontend attribution footer automatically
  • White-label branding — custom brand name (replaces "HeadlessCore" in wp-admin menu, page titles, JSON-LD, and frontend chrome), custom wp-admin footer text, custom login-screen logo, and an option to hide WordPress version/links from wp-admin entirely. Configure under Headless Core → Settings → White-Label Branding.
  • Pro Gutenberg blocks — CTA Banner, Pricing Table, FAQ Accordion, Testimonial Slider, Team Grid, Stats Counter, Logo Cloud, Tabs, Countdown Timer, Newsletter Signup, Contact Form, Image Gallery, Video Embed, Comparison Table, Team Slider, Photo Album, Feature Grid, Hero Banner, Steps, Callout, Icon List, and Magazine Category Grid blocks become insertable in the editor. Newsletter Signup and Contact Form are functionally wired to the real subscribeNewsletter/submitContactForm mutations (via /api/newsletter-block and /api/contact-block), not just static display. Content built with these blocks keeps rendering even if the license later lapses — only inserting new pro blocks requires an active key.
  • Pluggable search — Meilisearch/Algolia cross-content-type indexing (configure under Headless Core → Settings → Search).
  • AI content tools — Claude/OpenAI SEO descriptions and image alt text from the post editor sidebar.
  • CRM integration — HubSpot/Mailchimp push from contact form and newsletter submissions.
  • Theme auto-updates — License-gated downloads via your Next.js URL (see Auto-Updates).

Purchasing a key no longer has to be manual — see Automated delivery via Stripe below.

Future pro features (planned):

  • Priority support tier

How verification works

  1. License keys are RSA-2048 signed offline — no license server, no telemetry
  2. Public key ships in functions.php (HEADLESSCORE_LICENSE_PUBLIC_KEY_PEM)
  3. Private key is generated offline and never distributed — unless you opt into the Stripe integration below, which changes this specific guarantee
  4. WordPress verifies signature with openssl_verify() on each themeSettings GraphQL request
  5. Result is cached in WordPress transients

Verification is always fully offline, regardless of which signing path you use — the section below only changes how (and where) keys are signed.

Generating keys (project owner only)

1. Generate keypair

node scripts/generate-license-keypair.js

Creates keys/ at the repo root (gitignored):

  • license-private.pem — keep secret, never commit
  • license-public.pem — embed in theme or distribute

2. Issue a license key

node scripts/generate-license-key.js \
  --tier=pro \
  --customer="Acme Agency" \
  --expires=2027-12-31

Output format: hc1.{base64url-payload}.{base64url-signature}

3. Activate in WordPress

Headless Core → Settings → Licensing → License Key

Paste the key and save. The status indicator shows:

  • ✓ Active — tier: pro
  • Free tier — no valid license key configured

GraphQL license fields

themeSettings {
  license {
    valid
    tier
    customer
    expiresAt
  }
  brandName
}

Next.js reads license.valid in layout.tsx to conditionally hide the attribution footer.

brandName resolves to your configured brand name only when the license is valid — otherwise it always resolves to "HeadlessCore", even if a brand name is saved in WordPress. This is resolved WordPress-side (not just hidden on the frontend) so a lapsed license can't leak a stale brand name through the API.

Automated delivery via Stripe

The manual CLI flow above remains the lower-risk default — it's fully offline and never puts the signing key anywhere near a running server. Stripe-integrated delivery is opt-in and trades some of that isolation for automation. Full setup: Stripe Licensing.

The tradeoff, stated plainly: enabling this means the RSA private key lives as LICENSE_SIGNING_PRIVATE_KEY_PEM, a server-only env var on your Next.js deployment, read at request time inside /api/stripe-webhook to sign new keys on the fly. This is a real, permanent change to the threat model — before, minting a valid license required local/physical access to the offline keys/ directory; with Stripe delivery enabled, compromising your Next.js deployment's environment also compromises the ability to mint valid licenses. Verification stays exactly as offline as before (the public key + openssl_verify() path is unchanged) — only signing moves online, and only if you deliberately set that env var.

If you'd rather not accept that tradeoff, skip the Stripe route and keep using node scripts/generate-license-key.js manually — everything else in this doc still applies.

Security properties

Property Detail
Offline verification No network calls to license server
No telemetry Key validation is local only
Tamper-resistant RSA signature prevents forgery
Expiry support Optional expiresAt in payload

FAQ

Can I use HeadlessCore commercially without a key?
Yes. MIT license allows commercial use. Attribution footer remains unless you have a pro key.

What if my key expires?
Frontend reverts to free tier (attribution returns). Content and functionality are unaffected.

Can I self-issue keys?
Only if you generate your own keypair and replace the public key in functions.php.

Does automated (Stripe) delivery weaken the offline verification guarantee?
No — verification is still fully offline (public key, openssl_verify(), no network calls). Signing is no longer offline once you opt into the Stripe integration, since the private key then lives in a server-side env var. See Automated delivery via Stripe above.