Headlessly

Landing Pages

Build, publish, and A/B test landing pages with the Content entity.

Landing pages are Content entities with type: 'LandingPage'. They get strongly-typed props -- headline, subheadline, CTA, features, testimonials -- that render automatically through mdxui. No CMS to configure, no template to pick. Create it, publish it, measure it.

import { Content } from '@headlessly/content'

const page = await Content.create({
  title: 'Ship AI Products 10x Faster',
  slug: 'launch',
  type: 'LandingPage',
  status: 'Draft',
  props: {
    headline: 'Ship AI Products 10x Faster',
    subheadline: 'The operating system for agent-first startups',
    cta: { text: 'Get Started', href: '/signup' },
    features: [
      { title: 'CRM', description: 'Every contact, deal, and organization in one graph' },
      { title: 'Billing', description: 'Stripe-backed subscriptions from day one' },
      { title: 'Analytics', description: 'Events, funnels, and goals without setup' },
    ],
  },
})

await Content.publish({ id: page.$id })

Create a Landing Page

The type: 'LandingPage' discriminator unlocks structured props that mdxui renders into a complete page:

import { Content } from '@headlessly/content'

await Content.create({
  title: 'Pricing',
  slug: 'pricing',
  type: 'LandingPage',
  status: 'Draft',
  props: {
    headline: 'Simple, transparent pricing',
    subheadline: 'One plan. Everything included.',
    cta: { text: 'Start Free', href: '/signup' },
    features: [
      { title: 'Unlimited contacts', description: 'No per-seat pricing' },
      { title: '35 entities', description: 'CRM, billing, projects, and more' },
    ],
    testimonials: [
      { quote: 'We replaced 6 SaaS tools on day one.', author: 'Jamie, Founder' },
    ],
  },
})

Other Page Types

Not every launch page is a LandingPage. Use Page for simpler static content:

import { Content } from '@headlessly/content'

await Content.create({
  title: 'About',
  slug: 'about',
  type: 'Page',
  body: '# About Us\n\nWe build the operating system for agent-first startups.',
  status: 'Draft',
})

Publish and Unpublish

Content has three verbs for lifecycle management:

import { Content } from '@headlessly/content'

// Publish a draft
await Content.publish({ id: 'content_nR7kTfYxQ' })

// Return to draft
await Content.draft({ id: 'content_nR7kTfYxQ' })

// Remove from public view
await Content.archive({ id: 'content_nR7kTfYxQ' })

React to publish events to trigger downstream workflows:

import { Content } from '@headlessly/content'
import { Event } from '@headlessly/analytics'

Content.published((content) => {
  Event.track({
    name: 'page_published',
    properties: { slug: content.slug, type: content.type },
  })
})

A/B Test Landing Pages

Create two variants of a page and use an Experiment to split traffic:

import { Content } from '@headlessly/content'
import { Experiment } from '@headlessly/experiments'

const variantA = await Content.create({
  title: 'Launch - Variant A',
  slug: 'launch',
  type: 'LandingPage',
  status: 'Published',
  props: {
    headline: 'Ship AI Products 10x Faster',
    cta: { text: 'Get Started Free', href: '/signup' },
  },
})

const variantB = await Content.create({
  title: 'Launch - Variant B',
  slug: 'launch-b',
  type: 'LandingPage',
  status: 'Published',
  props: {
    headline: 'The OS for AI Startups',
    cta: { text: 'Start Building', href: '/signup' },
  },
})

await Experiment.create({
  name: 'Landing Page Headline Test',
  type: 'ABTest',
  variants: [
    { id: 'a', content: variantA.$id, weight: 50 },
    { id: 'b', content: variantB.$id, weight: 50 },
  ],
  goal: 'signup_completed',
})

MCP

headless.ly/mcp#search
{ "type": "Content", "filter": { "type": "LandingPage", "status": "Published" } }
headless.ly/mcp#fetch
{ "type": "Content", "id": "content_nR7kTfYxQ" }
headless.ly/mcp#do
await $.Content.publish({ id: 'content_nR7kTfYxQ' })

CLI

npx @headlessly/cli Content.create --title "Launch" --slug launch --type LandingPage --status Draft
npx @headlessly/cli do Content.publish content_nR7kTfYxQ
npx @headlessly/cli Content.find --type LandingPage --status Published

What's Next

On this page