Appfunnel is the infrastructure layer for Web2App funnels. From today, every funnel you build is real code underneath: the same funnel.ts and page components whether you built them by clicking or by typing. Payments, analytics, attribution, and A/B testing stay handled; the difference is you can now open the repo.
Plug-and-play, until you open the repo
The builder is still the fastest way to ship a funnel. But some teams need pixel-perfect control: a design system to match, checkout logic the editor doesn't expose, or funnels that live in version control. You no longer have to choose: the funnel you build in the browser is real React you can pull down, extend, and push back.
What shipped
- One spine,
funnel.ts: id, the pages and their routing, the responses you capture, the products you sell, and the checkout provider, all in one typed file - Pages as components: every page is a
.tsxfile with your UI; SDK hooks handle navigation, responses, and checkout - The CLI: run
pull,dev,push, andpublishto work locally, preview against real data, and ship to our infrastructure - Everything still handled: Stripe checkout, session tracking, attribution, A/B testing, and RevenueCat sync work exactly as they do in the builder
The shape of it
Your whole funnel is one file, plus a component per page:
// funnel.ts
import { defineFunnel } from '@appfunnel-dev/sdk'
export const config = defineFunnel({
id: 'funnel',
checkout: 'stripe',
responses: {
email: { type: 'string', default: '' },
},
// Products are SLOTS: a local name your pages reference → a catalog product.
products: { plan: null },
pages: [
{ key: 'welcome', type: 'default' },
{ key: 'email', type: 'email-capture' },
{ key: 'paywall', type: 'paywall' },
{ key: 'finish', type: 'finish' },
],
})// pages/paywall.tsx
import { definePage, useProduct, Checkout } from '@appfunnel-dev/sdk'
export default definePage(function Paywall() {
const product = useProduct('plan')
if (!product) return null
return (
<section>
<h1>{product.name}</h1>
<p>{product.price.formatted}</p>
<Checkout product="plan" surface="element" />
</section>
)
})Work locally, then publish in one step:
appfunnel pull my-funnel
appfunnel dev
appfunnel push && appfunnel publishWhat this means for Appfunnel
The funnel you build point-and-click and the funnel you write in code are the same artifact, so you can start plug-and-play and graduate to full control without migrating anything. The builder isn't going anywhere; it just stopped being a ceiling.