Pages and domains — how a landing page becomes a site under your domain
Pages and domains
There is a big distance between "I made a landing page" and "I have a site on my domain." Many landing page tools leave you stuck at the first: you build the page, but it lives at an ugly vendor URL, and joining several pages into a coherent site under www.yourcompany.com is another problem, often another product.
LaunchWithAgency's Pages product was modeled to cross that whole distance. It has two layers — the page, built from blocks, and the site, a custom domain that brings together pages and a blog. This article walks through both and shows how they fit.
Layer 1: the page as blocks
A landing page (landing_pages) in LaunchWithAgency isn't an HTML document you edit by hand. It is a composition of blocks.
The source of truth for the content is the blocksJson field: a structure with a version and an array of blocks, each block with an id, a kind and its props. The block kinds are the components of the suite's own design system — hero, bento, CTA, comparison. Building a page is composing those blocks and filling in their properties; the entire structure is serialized as JSON in the table.
On save, the system renders that structure to HTML and stores the result in bodyHtml. That is a deliberate performance choice: the public route doesn't recompose the page on every visit — it serves the already-rendered HTML, directly. The page has blocksJson as the editable truth and bodyHtml as the servable cache. There are also its own SEO fields (seoTitle, seoDescription, ogImage) and a theme. And, like everything in the suite, it carries locale — a landing page exists per language, with uniqueness over (ownerId, slug, locale).
> You don't edit the page's HTML. You compose blocks, and the HTML is the consequence. The content's truth is a structure, not a string.
Layer 2: the site as a domain
A page on its own is already servable — under domain.com/<your-handle>/lp/<slug>. But the leap from "page" to "site" happens when the second layer enters: the custom domain.
In the schema, a site is a row in domain_routes. And the schema's own comment is clear about what that row is: "a domain_routes row IS a site." It has a domain — a hostname like www.client.com, globally unique, because a hostname can only point at one site —, and an optional blogId, referencing the blog that will be served under /blog of that site.
How do pages link to that site? From their own side. A landing page has two fields — domainRouteId and sitePath — by which it attaches to a site. The sitePath is where it appears on that domain. A page attached with sitePath equal to / is the site's home. One attached with /pricing is served at www.client.com/pricing. The blog referenced by blogId appears at www.client.com/blog.
The result: a custom domain, several landing pages at clean paths, and a blog — all composing a complete site, and all still inside the same suite, the same database, the same login.
How the domain points at the suite: the CNAME
For www.client.com to serve your site, that domain's DNS needs to point at the platform. This is done with a CNAME record: in your domain's DNS provider, you configure that www.client.com is an alias for the platform's host.
The schema handles this with care and honesty. The domain_routes row has a verifiedAt field, and the comment is explicit: it is set only when a DNS check confirms the CNAME actually resolves to the platform host. And — the important part — "an unverified site does not serve traffic." You cannot hijack a domain you don't control: until the CNAME is provably pointing at the platform, the site stays inert. Verification isn't bureaucracy; it is the guarantee that only whoever controls a domain's DNS can publish under it.
There is also a robustness detail in the schema: if the blog referenced by a site is deleted, the blogId becomes null, but the site survives. The comment explains: this way the owner can re-point the site at another blog. The domain's infrastructure is treated as more durable than the content it serves.
Why this belongs to the single-database suite
You could imagine Pages as a standalone product. But notice how much of its usefulness comes from it not being standalone.
The landing page captures a lead — and that lead is a row in newsletter_subscribers, the same table the News product reads, with no export. The custom site serves, under /blog, a blog that is the same blog from the Blogs product, bilingual, with SEO. A Flows automation can react to a subscription made on a landing page with no integration whatsoever, because the subscription is an event in the same database.
Pages, on its own, would be a good landing page builder. Inside the single-database suite, it is the publishing layer of an entire operation: the place where content, capture and domain meet — and where "I made a page" finally becomes "I have a site."