Quickstart

Scaffold a Superwall Framework project, preview your first paywall in the studio, and ship it to production.

This guide takes you from nothing to a live paywall: scaffold a project inside your app, preview it locally, and push it to Superwall.

Before you start

You'll need:

  • Node 20+ (or Bun) and git.
  • A Superwall account with an application. The application must have the headless paywalls feature enabled — a push will tell you if it isn't.
  • The Superwall CLI:
bun add -g superwall
npm install -g superwall
  1. 1

    Create the project

    From the root of your app's repo:

    superwall create

    This scaffolds a self-contained superwall/ directory — its own package.json, a starter paywall, and everything wired up — then connects it to your Superwall app and installs dependencies. Your app itself needs no npm setup.

    To start from a working pattern instead, scaffold any example — each is a complete project:

    superwall create --example multi-page
  2. 2

    Preview in the studio

    superwall dev

    This opens the studio at http://localhost:6100: every paywall as a card with a live preview, and an editor per paywall with a device-frame view at exact logical size. Switch devices, toggle light and dark, rotate, change locales, and simulate purchases — the studio asks you to pick each outcome, so you can test every branch of your flow. See The studio for the full tour.

    Edits hot-reload as you save. Warnings about project problems (a stray file in app/, a duplicate route) appear here too — they're the same checks that block a push, so fix them as they come up.

  3. 3

    Make it yours

    Open superwall/paywalls/<id>/ and edit. A paywall is ordinary React:

    // app/index.tsx
    import { useProducts, usePurchase, useActions, useHaptics } from "superwall/hooks";
    
    export default function Paywall() {
      const { getProduct } = useProducts();
      const { purchase } = usePurchase();
      const { close } = useActions();
      const haptics = useHaptics();
      const annual = getProduct("annual");
    
      return (
        <main>
          <button aria-label="Close" onClick={() => { haptics.light(); close(); }}>×</button>
          <h1>Go Pro</h1>
          <button
            onClick={async () => {
              haptics.light();
              const result = await purchase("annual");
              if (result.status === "completed") haptics.success();
            }}
          >
            {annual?.variables.price ? `Subscribe · ${annual.variables.price}` : "Subscribe"}
          </button>
        </main>
      );
    }

    Two habits worth forming on day one:

    • Guard every product read. Prices arrive from the store at runtime; in dev they're undefined until the studio injects your dashboard's products. Degrade the copy — never invent a number. See Products.
    • Fire a haptic on every meaningful tap. iOS gives no feedback of its own inside a paywall. See Styling & mobile design.
  4. 4

    Point at real products

    config.ts declares product slots — the key is the name your code uses, the value is the store identifier:

    import { definePaywall } from "superwall/config";
    
    export default definePaywall({
      name: "Pro — Annual",
      products: {
        annual: "pro_5999_year",
      },
    });

    The identifiers must exist as products on your Superwall dashboard — a push refuses otherwise. Create them in the dashboard, or from the CLI with superwall products create. See Products.

  5. 5

    Push, then promote

    superwall push       # build + seal an immutable version — production untouched
    superwall promote    # point production at the latest push

    Push saves, promote ships — the same split as git push and a deploy. superwall publish does both in one step. The first push binds each paywall to your dashboard and records the binding in superwall.lock; commit that file so every machine and CI push to the same paywalls. See Push, promote & publish.

  6. 6

    Show it in your app

    Nothing changes on the app side: add the paywall to a campaign in the dashboard, and your existing register / placement calls present it. If you're new to Superwall, follow your platform's quickstart — iOS, Android, Expo, or Flutter — to get the SDK configured and a placement registered.

Where to next

How is this guide?

On this page