Let's get your academy live
Five sections, about 35 minutes. Each one has a short video and exactly what to copy. Work top to bottom — by the last section you're taking payments.
Your remix link drops a full copy — landing page, dashboard, and auth screens — into your Framer account. You'll wire it up over the next sections.
In FrameAuth, open Account Creation — it controls how new users can create accounts and whether they need approval. Set it to Checkout. This makes purchase the only way to get an account: nobody can sign up for the web app without first buying. There's no open registration to gate after the fact.
Create a tag for full access (e.g. members) and attach it to the digital product people buy. When a purchase completes, FrameAuth issues an account and applies that tag automatically — the tag is what corresponds to "this person paid for the product." You'll copy the tag's ID into the Worker in the next section.
No payment code in your Worker. FrameAuth handles checkout, account creation, and tagging. Your Worker only ever reads whether a visitor carries the access tag.
What is a Worker? A Cloudflare Worker is a tiny piece of backend code that runs securely on Cloudflare's global edge network. It acts as the bridge for your app — generating protected download links, securely sending emails via Resend, and validating users so you never have to expose sensitive API keys in your frontend code.
This is the only Worker you need — the same one in Library → Worker, where you set your submission limits. In Cloudflare open Workers & Pages → Create → Edit code, clear the default, paste this, and hit Deploy. Don't edit it.
Under Settings → Variables and Secrets, add these three. Mark FRAMEAUTH_API_KEY as encrypted.
After deploying, Cloudflare shows a URL ending in .workers.dev. Paste it below — it saves to your Dashboard so every component you add later just works. No pasting URLs into code.
In Cloudflare go to R2 → Create bucket. Name it exactly this — names can't be changed later:
Open your Worker → Settings → Bindings → Add → R2 bucket. Set the variable name to FILES and choose course-downloads. That binding is what lets the Worker hand out secure, expiring download links.
The bucket name must match exactly. Anything other than course-downloads and downloads return "file not found" until the names line up.
This step is required. Until your domain is verified, Resend won't send on your behalf and welcome emails and receipts will bounce or land in spam. Do this before wiring the Worker.
In Resend go to Domains → Add Domain and enter the domain you'll send from. Resend gives you a set of DNS records to add at your registrar (Cloudflare, Namecheap, GoDaddy, etc.).
Copy each record Resend shows into your DNS. DKIM signs your mail, SPF authorizes Resend's servers to send for you, and DMARC (optional but recommended) tells inboxes how to treat anything that fails. Then flip Enable Sending on.
DNS can take a few minutes to a couple of hours to propagate. When every record shows a green check in Resend, your domain is verified and you're ready for the next step.
No new Worker — open your existing one under Settings → Variables and Secrets and add these. Only credentials live here; your email addresses are set in Library → Worker, not as variables.
In Library → Worker, fill in Notify email (where submissions are sent) and From address (using the domain you just verified). They're baked into the Worker code — re-copy and redeploy after changing them.
Email is optional. Skip all of this and everything still works — uploads and forms succeed, contacts just won't be emailed or added to your audience. Add it whenever you're ready.
Components
Drop-in Framer code components, already wired to your Worker — your saved Worker URL is baked into the code when you copy it, so there's nothing to paste into props. The gated ones read the signed-in member's email (via your template's CaptureEmail override) and the Worker verifies it against FrameAuth, so access and limits follow the member, not the browser.
Gated file upload to your R2 bucket. The Worker verifies the signed-in member against FrameAuth before accepting, and the per-period limit is keyed on the member — so clearing the browser doesn't reset it. Confirmation step, progress ring.
A configurable form — your own fields, an optional terms/agreement modal, and the same per-member limit. The Worker verifies membership before accepting; submissions are emailed to you via Resend.
A members-only lesson player for CMS pages. It auto-detects the page slug, the Worker verifies the member and returns the unlisted YouTube id — so the id never sits in your page. Custom controls, YouTube chrome hidden.
A members-only "Join the Discord" button. It verifies the signed-in member against FrameAuth, then the Worker hands back your private invite — which lives server-side and never appears in your page.
A two-step email then name capture that adds the contact to your Resend audience. Public — no membership needed. Animated, compact, drops onto any page.
Worker
This is the single serverless engine behind every Course Maker component. It verifies membership, takes file uploads and form submissions into your R2 bucket, sends email through Resend, and enforces your submission limits. You deploy it once — paste the whole file into a Cloudflare Worker and hit Deploy.
Submission limits
Video lessons & Discord invite
Email Templates
Beautiful HTML email templates to use with Resend. Download the raw HTML files and paste them directly into your Resend email workflows. The styling matches your academy's premium dark theme.
The perfect welcome email for new members. Includes a nice hero section, a link to the academy, and next steps.
A beautifully formatted template for broadcasting updates and new content drops to your audience.
All videos
Every setup video in one place. Rewatch any section on its own.
Settings
Your Dashboard values. The Worker URL here is what every component uses.