Push, Promote & Publish

Ship paywalls with git semantics: push seals an immutable version, promote points production at it, publish does both.

Shipping has git semantics on purpose: push saves, promote ships. Every push mints a sealed, immutable version; nothing your users see changes until promote points production at it.

superwall push                    # build + version. Production untouched.
superwall promote                 # point production at the latest push
superwall publish                 # push + promote in one step
superwall publish -m "Q3 test"    # record why

The scaffolded project mirrors these as package scripts (dev, push, promote, ship).

Pushing requires the headless paywalls feature to be enabled on your Superwall application — it's a server-side flag, so if a push says it isn't enabled, the account owner needs to have it turned on.

superwall push

Builds every paywall, versions the changed ones, and leaves production alone. Re-running with nothing changed is a no-op.

FlagWhat it does
--id <id>Limit the push to one paywall (repeatable)
--rename <old>=<new>Declare a directory rename (see below)
-m <note>Record why this version exists

The first push binds each paywall — creating it on Superwall if needed — and records the binding in superwall.lock. Commit that file: it's what makes every machine and CI push to the same paywalls. After that, push always updates the same paywall; no IDs ever appear in your code.

A push refuses — before anything is written — when:

  • A selected paywall has diagnostics. Publishing is immutable; fix the named problems first. They're the same warnings superwall dev prints.
  • A product in config.ts doesn't exist on the dashboard. Every variable on it would be undefined on device. Create the products first — see Products and the CLI reference.
  • A directory rename is unresolved (below).

Renames

Renaming a paywall directory is detected, never guessed. Interactively, push asks:

? `pro-upgrade` is not in superwall.lock. Is it a new paywall, or renamed?
  › Renamed from plus-upgrade   paywall 208540
    Create a new paywall

Choosing the rename keeps the live paywall attached to the new directory. In CI there's no one to ask, so declare it — anything unresolved stops the push rather than silently creating a duplicate:

superwall push --rename plus-upgrade=pro-upgrade

Deleting a paywall directory never blocks a push: the dashboard paywall keeps serving, and restoring the directory re-binds it.

Source snapshots

Every push also snapshots your superwall/ source to Superwall, so the dashboard can show — and diff — the exact code each version was built from. The -m "why" note is recorded there too.

What never leaves your machine: .env files, node_modules/, .superwall/, and anything your .gitignore lists.

If any import reaches outside the project directory, the push warns naming each offender, and the dashboard disables remote editing for that paywall — the pushed source can't be rebuilt elsewhere. Copy shared code into superwall/components/ instead. See Project structure.

superwall promote

Points production at a pushed version. Promote never rebuilds — it only moves the live pointer, so it's instant, and rollback is the same move in reverse:

superwall promote                              # latest push, every paywall
superwall promote --id plus-upgrade            # just one
superwall promote --id plus-upgrade --version 5
# → Rolled back version 7 → 5

--version/-v (with a single --id) picks a specific version — pinning forward or rolling back are the same operation.

superwall publish

Push + promote in one step. It also warns about other paywalls that are pushed-but-not-live, so nothing ships half-forgotten.

publish requires git — the source snapshot is part of every publish.

CI

Interactive machines authenticate once with superwall login. In CI, set SUPERWALL_API_KEY (an sk_… key) in the environment — superwall/.env works locally and is gitignored. dev needs no login at all.

A typical CI ship step:

superwall push --rename old=new -m "$COMMIT_MESSAGE"   # renames declared, reason recorded
superwall promote

Because superwall.lock is committed, CI pushes to exactly the same paywalls as every developer machine.

How is this guide?

On this page