Migrating from the editor
Rebuild a paywall made in Superwall's visual editor as a framework paywall: what the CLI scaffolds, what an agent rebuilds, how you review it against the original, and how the switch happens.
A paywall built in the visual editor becomes a framework paywall by being rebuilt as code: the same design, products, pages and actions, written as routes, hooks and your own CSS. The CLI does the part that is deterministic, a coding agent rebuilds the pages, you review the result next to the original in the studio, and the original keeps serving until a campaign points at the new one.
Start from the dashboard paywall
In your app's root (or an empty directory), with the paywall's id from the dashboard URL:
superwall create --from 65920This reads the paywall and its served document, then scaffolds a project with:
paywalls/<slug>/config.tscarrying the name, platform, product slots, presentation style and geometry, feature gating, scroll, game controller and cache settings, and the background color, all as the paywall has them today. Nothing underapp/is migrated; it is the starter, to be replaced.paywalls/<slug>/MIGRATION.md, the brief: the source URL, the dashboard screenshot, a product table, and an inventory of the pages, drawers, elements, actions, product variables and locales the source uses.- An
originsentry insuperwall.lock, which is what puts Original in the studio's Compare menu. - The project connected to the same app, so the new paywall lands beside the old one.
--from needs a login and cannot be combined with --example or --no-connect. A paywall that is already built with the framework is refused; pull its source from the dashboard instead.
Template paywalls have no real products: their slots show "missing" in config.ts, and a push refuses them. Point each slot at a real product (or create one with superwall products create) before pushing.
Rebuild the pages
The rebuild is agent work with you in the loop, and the CLI offers it as soon as the scaffold is done:
◇ Rebuild the pages now?
› With Claude Code runs here, headless; you review in the studio after
Copy the prompt paste it into Claude Code, Codex, Cursor, or another agent
Not now superwall migrate 65920 picks this up laterThe same choice is one command away at any time, and it scaffolds first if the paywall isn't in the project yet:
superwall migrate 65920 # in the app root, or inside superwall/
superwall migrate 65920 --skill # print the prompt instead, once it is scaffoldedRunning it with your agent hands it the brief and the rebuild playbook from the superwall-framework skill (references/migrate-from-editor.md), headless, in the superwall/ directory, with a fixed order of work: confirm the inventory against the editor's document store embedded in the served page, lift the design tokens, one route per page with shared chrome in layout.tsx, every action as a hook call, every state and locale rebuilt, typecheck green. It cannot push, promote or touch campaigns. The mapping it follows (a navigation element's children become routes, a drawer becomes a sheet, a tap action becomes a hook call, Liquid product templates become useProducts() reads) is the superwall-framework skill's references/migrate-from-editor.md, which the agent reads as well.
Copying the prompt gives you the same instructions without the headless protocol, for an agent you drive yourself, which is the way to keep the inventory step conversational: ask for the inventory first and approve it before any code is written.
Review against the original
When the agent finishes, the CLI offers to open the studio, and opens it straight onto the rebuilt paywall with Original in the second pane: the dashboard paywall served exactly as it is today, beside your local build. The same view is in the toolbar's Compare menu at any time, and a link with ?compare=origin lands on it. Walk every page on a phone with a Dynamic Island, an iPhone SE, a Pixel and an iPad, in both color schemes, and compare.
It is your code now. Anything that doesn't match is a tweak to ask your agent for, or to make yourself, under paywalls/<slug>/; the studio reloads as you save.
The Original pane is view-only. It does not receive the studio's theme, locale, device or product variables, so it renders in light mode with the editor's example prices. Your side does receive them, which is how you check the dark scheme and the real prices the original never showed.
Switch when you are ready
superwall push creates a new dashboard paywall and binds it in superwall.lock; the editor paywall is untouched and keeps serving. To go live, point the campaign's variant at the new paywall in the dashboard. Rolling back is pointing it at the old one again. Nothing about a migration promotes on its own, and an agent following the playbook pushes only when asked and never touches campaigns.
Delete MIGRATION.md once you are satisfied. The origins entry in the lock stays, so Compare › Original keeps working for later edits.
What does not carry over
- The original cannot be converted in place; a framework paywall is always a new dashboard paywall.
- Editor-only behavior with no framework equivalent, such as surveys attached to the paywall, is not carried over. The playbook names each such item in its hand-off rather than approximating it.
- The editor's example prices. The framework never invents a price; every product variable is guarded and the unpriced state is designed, as everywhere else in the framework.
How is this guide?
Push, Promote & Publish
Ship paywalls with git semantics: push seals an immutable version, promote points production at it, publish does both.
Migrating native screens
Turn a SwiftUI, UIKit, Jetpack Compose, Android Views, React Native or Flutter screen into a Superwall surface the app can change without a release: what the CLI reads from the source, what an agent rebuilds, how you review it against a simulator screenshot, and how the app is wired afterwards.