Custom domain and white-label
Every organization gets a Cursiva address the day it is created, and can graduate to its own domain. This page explains the two addresses your school lives at, how to connect your own, and the one invisible seam — login — that keeps the white-label experience seamless.
The org subdomain and public storefront
The moment an organization exists it is reachable at its own subdomain: {slug}.cursiva.io, where slug is the organization's slug. All host-based routing happens at the edge (in proxy.ts): a request to acme.cursiva.io is rewritten into that organization's /[org]/… routes, so the school never has to configure anything to go live.
A handful of subdomains are reserved and can never be taken as an org slug — www, app, api, docs, cdn, assets, and mail. Everything else under cursiva.io that resolves to a single label is treated as an org slug.
Two public surfaces are built from the organization's published catalog:
| Surface | Route | What it shows |
|---|---|---|
| Storefront | /[org] (served at {slug}.cursiva.io) | The organization's branding — logo, name, bio — over its published, listed courses as cards. |
| Explore | /explore | The cross-organization marketplace: every published, listed course on Cursiva. |
The storefront lists only content that is published and listed for that organization, drawn from listPublished, with review stars per course. A visitor who lands there sees the school's own page; the Explore all button links out to the shared /explore catalog.
Connecting your own domain
An organization can serve its storefront and courses from a domain it owns — escola.com.br, courses.yourbrand.com — under Settings → Domains. You enter the domain, add two DNS records at your registrar, and Cursiva takes care of the rest.
The DNS records
Saving a domain produces exactly two records to add at your DNS provider, both with a TTL of 3600 (kept low so the change propagates fast enough for automatic verification):
| Type | Name | Value | Purpose |
|---|---|---|---|
CNAME | your domain (e.g. escola.com.br) | cname.vercel-dns.com | Points the domain at Cursiva's hosting so requests reach the app. |
TXT | _cursiva-verify.<your-domain> | a unique verification token | Proves you own the domain before it goes live. |
Each value has a copy button in the Domains card, so you can paste it straight into your registrar.
Automatic verification and TLS
Once the domain is saved but not yet verified, the Domains card polls your DNS automatically every few seconds — you never have to click anything. When the TXT record at _cursiva-verify.<domain> matches the expected token, Cursiva:
- Registers the domain on Vercel, which provisions and renews the TLS certificate and routes the host to the app.
- Marks the domain verified, and the card flips to a live confirmation linking to
https://<your-domain>.
A manual Verify button is available too, for when you would rather not wait for the next poll. Until the records resolve, the card simply keeps checking and shows the pending DNS instructions.
Behind the scenes, the edge resolves an incoming custom-domain request to its organization and serves that org's public routes — the same /[org] storefront and course pages, just on your host.
The white-label learner experience
On a connected domain, a learner browses the catalog and takes the entire course on the school's own domain. Reading, progress, drip release, community — all of it happens at escola.com.br. There is one exception, and it is invisible: the login step runs on Cursiva and hands the session back.
Why login makes a detour
Two hard facts about the web force this design:
- Cookies do not cross domains. A session cookie set on
.cursiva.iois simply not sent toescola.com.br— the browser will not share it. Each domain needs its own cookie. - OAuth, 2FA, and passkeys are registered on the canonical host. Social sign-in redirect URLs, TOTP two-factor, and passkey credentials are all bound to Cursiva's own hostname. They cannot be re-registered per custom domain.
So authentication happens where it is set up — on the canonical {slug}.cursiva.io — and the result is carried back to the custom domain.
How the hand-off works
When a learner on the custom domain hits a login-related path, the edge sends them through a one-time-token bridge:
- The custom domain redirects the shared auth path to
/sso/bridgeon the canonical host{slug}.cursiva.io, carrying the target domain and where to land afterward (next). - The bridge signs the learner in normally — here cookies live on
.cursiva.ioand OAuth works. If they are not signed in yet, it sends them to/loginand returns to the bridge afterward. - Once signed in, the bridge mints a one-time token and bounces the browser to
/api/sso/consumeon the custom domain. - Consume verifies the token, lets Better Auth create the session, and re-scopes that cookie to this host only — dropping the
.cursiva.iodomain so it becomes a host-only cookie onescola.com.br.
From then on the learner is signed in on the custom domain and stays there for the whole course. The token is single-use and short-lived; an invalid or expired one simply returns the learner to the page, logged out.
What stays on Cursiva
The public, learner-facing experience is what white-labels. The admin dashboard does not: producers and staff always manage their school from Cursiva itself.
- The dashboard (
/dashboard) — the editor, learners, sales, insights, and settings — is served from the app host (app.cursiva.io) and gated on a session cookie. It is not rewritten onto custom domains. - Shared auth pages (
/login,/signup,/two-factor,/accept-invitation, and the/ssobridge) render on the canonical.cursiva.iohosts, where the session cookie is valid across subdomains.
In short: learners live on your domain, the team works in Cursiva.