Skip to content
Heatmaps are here: see where visitors click
Mockly

Developers

A language for websites where experiments are built in.

Mockly is a strict subset of TSX with experiments, goals, and forms in the language. A compiler checks it as you type and turns it into HTML and small scripts when you publish, so nothing is interpreted while visitors wait.

Read the docsStart free

How it works

Smart compiler, simple server. Everything that can be decided at publish time is.

  1. 01Source

    TSX you already know

    Pages and components, with experiments, goals, and forms built into the language.

    • pages/index.tsx
    • components/hero.tsx
  2. 02Compile

    Checked, then lowered

    One parser and one intermediate representation, read by an emitter for the server and one for the browser.

    • Diagnostics with stable codes
    • Types checked as you type
  3. 03Publish

    Every variant, built ahead

    Each page is rendered once per variant. Interactive parts become small scripts.

    • HTML for every variant
    • Island scripts, CSS, a manifest
  4. 04Serve

    Pick, join, send

    The server reads the manifest, picks the visitor's variants, and joins pre-built HTML.

    • Sticky assignment per visitor
    • No rendering per request

No eval. The compiler emits real JavaScript once. Nothing evaluates expressions per request.

One escaping module. Server rendering and browser updates escape through the same code.

A portable runtime. Serving needs no Node.js APIs or database access, so it can move closer to visitors.

The language

Familiar on purpose. Strict where it counts.

If you've written a React component, you can write a Mockly page. The difference is what the compiler knows: which parts are experiments, which are interactive, and which never change, so it can build each one the cheapest way.

<Page>
Title, description, share image, fonts, structured data, and an optional goal.
<Experiment>
Variants as <Variant> blocks, or inline with variants={…}.
<Form>
Posts to your site, records a goal, and forwards to a webhook.
<Show> · <For>
Conditions and lists, rendered on the server and kept up to date in islands.
state · derived
State that makes a component an island, and values computed from it.
fetchJson · secret
JSON fetched at publish time, with secrets that never reach the page.
track
Records a goal from a handler; or add track="goal" to any element.
<Window> · <Timer>
Page-wide events and timers for islands, with no setup.
pages/index.tsx
import { Experiment, Page } from "mockly"; export default function Home() {  return (    <Page title="Acme">      <h1>Launch pages that learn</h1>      <Experiment name="cta" goal="signup"        variants={["control", "green"]}>        {(v) => (          <a href="/signup" track="signup"            class={v === "green" ? "bg-green-600" : "bg-black"}>            {v === "green" ? "Start free trial" : "Get started"}          </a>        )}      </Experiment>    </Page>  );}
components/faq-item.tsx
import { Show, state } from "mockly"; export function FaqItem({ q, a }: { q: string; a: string }) {  const open = state(false);  return (    <div>      <button type="button"        onClick={() => { open.value = !open.value; }}>        {q}      </button>      <Show when={open.value}>        <p>{a}</p>      </Show>    </div>  );}

Diagnostics

Every mistake, explained. With a code that never changes.

Each error and warning has a stable code, the smallest range that shows the problem, a one-sentence message, and a hint. The studio shows them as you type; the CLI prints them, or returns them as JSON for CI and tools.

  • MK4005errorExperiment "cta" needs exactly one variant named "control".
  • MK4010warningGoal "signup" is never tracked anywhere in the site.
  • MK2015warning"/signup" doesn't match a page in this site.
  • TS2367errorThis comparison appears to be unintentional because the types '"control" | "green"' and '"gren"' have no overlap.
Terminal
$ mockly check ./sitepages/index.tsx:7:8  error  MK4005  Experiment "cta" needs exactly one variant named "control".  6 |       <h1>Launch pages that learn</h1>> 7 |       <Experiment name="cta" goal="signup"    |        ^^^^^^^^^^  8 |         variants={["blue", "green"]}>  hint: Name the baseline variant "control". 2 file(s): 1 error(s), 0 warning(s)

Add --json and the same diagnostics come back as data.

Coming soon

Mockly Agent. An AI that runs experiments for you, safely.

Mockly was designed from the start to be written by an agent as well as a person. Describe what you want to learn, and the agent proposes a test, writes the variant, checks it with the compiler, and watches the results until there's an answer.

Start freeBecome a design partner
  • It can't ship a typo. Every change goes through the same compiler and diagnostics you use, with stable codes it can act on.

  • It can't manufacture a winner. Results stay valid however often they're checked, so an agent polling every minute is as safe as you checking once.

  • You stay in charge. Every change is a version you can read, compare, and restore, and shipping a winner is your call.

Write your first experiment today. It's one tag and a few lines.

Start freeBook a demo

Free to start. No credit card required.