/

Why every block compiles to TypeScript

Engineering

Published

Read time

6

min

Why every block compiles to TypeScript

Readable code you can review, test and take with you. Why we chose TypeScript as the output of every logic block.

DB

Daan Bakker

Runtime lead

On this page

Share

Every logic block on a Tessel canvas compiles to TypeScript. Across 1,900 teams that is a little over 410,000 published blocks, and each one has a code view you can read, diff, test and export. When we started in 2023, the plan was something else. This post explains why we changed course, and what the choice costs us at runtime.

Blocks are code

A block on the canvas is a picture of a function. It has a typed input, a typed output and a body. The canvas is the best way to see how blocks connect, but it is a poor way to review what one block does. Reviewers want a diff. Auditors want to read the rule. Engineers want to run a test before they publish.

So the canvas is an editor, and the compiled TypeScript is the source of truth. When you change a block on the canvas, the code changes. When you change the code, the canvas changes. Both are the same version.

Why TypeScript

We considered a custom language, Python and plain JSON. TypeScript won on four points.

  • Types we already had. Every block declares a schema for its input and output, and TypeScript types map onto those schemas almost one to one.

  • People can read it. Most operations teams have someone who can read TypeScript, even if they do not write it every day.

  • Tooling exists. Editors, linters, test runners and code review all work without anything from us.

  • It runs fast. The runtime executes compiled blocks in isolates, and the p95 per block, including connector calls, is 184 ms.

The YAML year

Our first prototype in 2023 stored blocks as YAML with small expressions inside. It was easy to generate from the canvas and hard to do anything else with. Two of our first customers asked to see "the real logic" during their security review, and we sent them YAML with embedded expressions. One of them replied with a list of 40 questions. That week we started on the compiler.

What the output looks like

Here is the match step from an invoice reconciliation workflow, as it appears in the code view.

import { block } from "@tessel/blocks";
import type { StripeInvoice, NetSuiteInvoice } from "@tessel/connectors";

export default block("match-invoice", {
  input: { paid: StripeInvoice, ledger: NetSuiteInvoice },
  run({ paid, ledger }) {
    const expected = ledger.lines.reduce((sum, l) => sum + l.amount, 0);
    const variance = Math.abs(paid.amountPaid - expected) / expected;
    return { matched: variance < 0.02, variance, lines: ledger.lines.length };
  },
});
import { block } from "@tessel/blocks";
import type { StripeInvoice, NetSuiteInvoice } from "@tessel/connectors";

export default block("match-invoice", {
  input: { paid: StripeInvoice, ledger: NetSuiteInvoice },
  run({ paid, ledger }) {
    const expected = ledger.lines.reduce((sum, l) => sum + l.amount, 0);
    const variance = Math.abs(paid.amountPaid - expected) / expected;
    return { matched: variance < 0.02, variance, lines: ledger.lines.length };
  },
});
import { block } from "@tessel/blocks";
import type { StripeInvoice, NetSuiteInvoice } from "@tessel/connectors";

export default block("match-invoice", {
  input: { paid: StripeInvoice, ledger: NetSuiteInvoice },
  run({ paid, ledger }) {
    const expected = ledger.lines.reduce((sum, l) => sum + l.amount, 0);
    const variance = Math.abs(paid.amountPaid - expected) / expected;
    return { matched: variance < 0.02, variance, lines: ledger.lines.length };
  },
});

No generated noise, no runtime calls hidden in the body. Connector types come from the same schemas the canvas uses.

Testing and review

Because a block is a function, you can test it like one. The code view includes a test file per block, and Tessel can fill it with real inputs taken from recent traces. Pull requests from a workspace to a Git repository show the compiled diff, so the review happens where your engineers already work.

If you cannot read what a block does, you cannot be responsible for it.

Taking it with you

Export gives you the compiled TypeScript for a whole workspace, with the connector types and a small runtime shim. It is not a full replacement for Tessel, since scheduling, tracing and approvals stay with us. It is a guarantee that your logic is yours, in a format you can read without us.

The runtime team works on the compiler, the isolates and the scheduler, and we are hiring. See open roles on the careers page.

DB

Daan Bakker

Runtime lead

Daan leads the runtime team, which owns the block compiler, the isolates and the scheduler. Before Tessel he built deployment tooling for a terminal operator in the Port of Rotterdam, where a slow release meant a crane stood still.

Keep reading

More from the blog. Picked for this post.

Engineering

9

min read

How we trace two billion runs a month

Inside the pipeline that stores inputs, outputs and timings for every block, and opens a 30-day trace in under 200 ms.

Engineering

5

min read

Replaying last week before you ship

How replay runs a draft workflow against seven days of real events and shows the diff before anything reaches production.

Product

7

min read

Agents need budgets, not just prompts

A prompt says what an agent should do. A spend cap, a tool list and a named approver say what it may never do.

Newsletter

New posts, monthly. Plain text, no tracking.

One email a month · Unsubscribe in one click

One email a month. Only what shipped.

A1

Product

C1

Layouts

D1

Company

E1

Template

F1

All systems operational
fra41 ms
iad38 ms
sin52 ms

C2

Elsewhere

XLinkedInGitHubYouTube

E2

Move across the wordmark168 blocks · iso 30°

One email a month. Only what shipped.

A1

Product

C1

Layouts

D1

Company

E1

Template

F1

All systems operational
fra41 ms
iad38 ms
sin52 ms

C2

Elsewhere

XLinkedInGitHubYouTube

E2

Move across the wordmark168 blocks · iso 30°

One email a month. Only what shipped.

A1

Product

C1

Layouts

D1

Company

E1

Template

F1

All systems operational
fra41 ms
iad38 ms
sin52 ms

C2

Elsewhere

XLinkedInGitHubYouTube

E2

Move across the wordmark168 blocks · iso 30°

Create a free website with Framer, the website builder loved by startups, designers and agencies.