Skip to the content
Method 4

What I make and how I work

Four disciplines, each shown as a leaflet folded in three. Drag one open sideways or click it to see three live examples.

How a project runs

Every project follows 4 steps

The quality bar is set before the first line of code and checked before anyone else sees the work.

What it leaves

What a project delivers

The working product, the components it is built from and the measurements it was checked against, so the next change can be compared with the last.

Running workThe thing itself, in the browser, in light and dark, at phone and desktop widths
The partsThe tokens and components it is made of, each documented where it runs
The measuresSizes, colors and timings read in the browser, to check again after every change
A handoverThe order to build it in, and the numbers to compare against
How I build

The tools and checks behind every app

If you have a technical team, the chapters from here show them the tools and checks behind every app on this site, the work in numbers, and the command that counted each one.

On the device

Apps that work offline

The app saves each change on the device first and syncs it when a connection is available, so people can keep working without a network.

The databaseSQLite in the browser, stored in OPFS and synced to Postgres with PowerSync (ramtt.app).
The documentYjs documents in IndexedDB, merged character by character, with a server that stores the updates.
The app itselfA service worker that caches the app, so it opens without a network.
The stack

The front end and the back end

The front end
ReactReact with TanStack Router for apps, built with Vite.
vinextvinext on Vite and Cloudflare Workers, prerendered, for a site in two languages.
JavaScriptPlain JavaScript and esbuild where a page needs no framework, as on this site.
CSSPlain CSS on design tokens, with a linter and a check that measures every component on a rendered page.
The back end
WorkersCloudflare Workers, Durable Objects with SQLite, and WebSockets.
PostgresSupabase with Postgres and row-level security, with 109 migrations in RAMTT.
Sign inPasskeys verified on the server, and Web Crypto for encryption and signatures in the browser.
ServicesStripe with a verified webhook, Resend for email, and Claude through the Anthropic SDK.
Every change

Automated checks

A quick set of checks runs at every commit, and the full set runs on a build server for every pull request. A change that fails either is not merged.

The prototypes and this site pass 566 browser tests in Chromium. A second check compares 48,250 rendered values on 117 of their pages with the design system’s specification.

AuditsThe JavaScript size of each route, secrets in a change, the colors of the design tokens and the text users see.
Browser scriptsScripts that click and type through a page and measure it.
WritingA writing check of every text in RAMTT at each commit, and of every page of this site at each build.
Working with Claude

I write code with Claude, Anthropic’s SI model.

Its changes go through the same checks, browser tests and writing check as mine. The commands at the end of this page count every number on this site.

Numbers

The work in numbers

From 25 Jan 2026 to 11 Oct 2026 I made 9,057 commits in 15 repositories, on 214 of 260 days. The longest run of days with a commit is 67 days, and it runs to the last commit. 988 pull requests were merged.

The year, day by day

Drag along the days or throw them. The count is every commit up to the day under the needle. The busiest day was 5 Oct 2026, with 524 commits.

Around the clock

3,565 of the 9,057 commits were made between midnight and six in the morning, Copenhagen time.

Turn the hand, or use the arrow keys, to read any hour. Each bar is every commit made in that hour, on every day of the period.

On one scale

The rest of the counts stand on one logarithmic tape. Pull it under the needle; it stops at each number.

  • 12
  • 551
  • 39
  • 109
  • 117
  • 128
  • 168
  • 330
  • 566
  • 634
  • 988
  • 1,524
  • 4,111
  • 9,057
  • 11,334
  • 38,639
  • 48,250
  • 911,426
This site

How this site is made

The face, the colors and the weight of this page. Every value is read from the page while you look at it, or from the file named beside it.

One face, and its sizes

Inter Variable, served by the site and cut to the Latin letters and the weights the design draws. Each size is measured on this page, at this screen.

Day and night, one set of names

The tokens are read from the design system’s stylesheet as you look. Drag the seam: day on one side, night on the other. Click a color to copy its name.

An earlier front page, line by line

The markup of the site’s earlier front page, web/home/markup.html, with the commit that last changed each line. Loom, the Git I wrote from nothing, replays the same commits here and blames the file again.

What this page weighs

Measured by your browser while the page is open, with the interface that measured each value printed under it.

Sources

The command behind each number

The site runs these commands when it is built. They last ran on 11 Oct 2026. Find one by what it counts or by what it runs, copy it, or replay what it printed.

Commits

Each repository’s commits are read from every branch of its local copy, or from the GitHub API when it is only there. A commit is counted once, in the first repository that holds it, by its time and subject. Bots are left out, and the times are counted in Copenhagen time.

Commits in RAMTT monorepo

4,875

Read on 11 Oct 2026 in ~/Projects/RAMTT.

The command read 6,343 commits without bots, and 1,468 of them are counted in another repository that holds the same commit.

The command for commits in RAMTT monorepo
git -C ~/Projects/RAMTT fetch --quiet origin && git -C ~/Projects/RAMTT log --all --format=%aI%x09%an%x09%s

Commits in Zibaldone

1,565

Read on 11 Oct 2026 in ~/Projects/zibaldone.

The command read 1,570 commits without bots, and 5 of them are counted in another repository that holds the same commit.

The command for commits in Zibaldone
git -C ~/Projects/zibaldone fetch --quiet origin && git -C ~/Projects/zibaldone log --all --format=%aI%x09%an%x09%s

Commits in Design system

1,092

Read on 11 Oct 2026 in ~/Projects/ramtt-design-system.

The command read 1,132 commits without bots, and 40 of them are counted in another repository that holds the same commit.

The command for commits in Design system
git -C ~/Projects/ramtt-design-system fetch --quiet origin && git -C ~/Projects/ramtt-design-system log --all --format=%aI%x09%an%x09%s

Commits in Context bundle

76

Read on 11 Oct 2026 in ~/Projects/ramtt-context.

The command for commits in Context bundle
git -C ~/Projects/ramtt-context fetch --quiet origin && git -C ~/Projects/ramtt-context log --all --format=%aI%x09%an%x09%s

Commits in Portfolio

418

Read on 11 Oct 2026 in the portfolio folder.

The command for commits in Portfolio
git -C . fetch --quiet origin && git -C . log --all --format=%aI%x09%an%x09%s

Commits in Studio site

5

Read on 11 Oct 2026 in ~/Projects/cho52-studio.

The command for commits in Studio site
git -C ~/Projects/cho52-studio fetch --quiet origin && git -C ~/Projects/cho52-studio log --all --format=%aI%x09%an%x09%s

Commits in RAMTT marketing

27

Read on 11 Oct 2026 in ~/Projects/ramtt-marketing.

The command for commits in RAMTT marketing
git -C ~/Projects/ramtt-marketing fetch --quiet origin && git -C ~/Projects/ramtt-marketing log --all --format=%aI%x09%an%x09%s

Commits in Dotfiles

9

Read on 11 Oct 2026 in ~/Projects/dotfiles.

The command for commits in Dotfiles
git -C ~/Projects/dotfiles fetch --quiet origin && git -C ~/Projects/dotfiles log --all --format=%aI%x09%an%x09%s

Commits in RAMTT before the rewrite

115

Read on 11 Oct 2026 in ~/ramtt_bank/ramtt-arkiv/2026-08-omlaegningen/_mirror-foer-rewrite.git.

The command read 2,397 commits without bots, and 2,282 of them are counted in another repository that holds the same commit.

The command for commits in RAMTT before the rewrite
git -C ~/ramtt_bank/ramtt-arkiv/2026-08-omlaegningen/_mirror-foer-rewrite.git log --all --format=%aI%x09%an%x09%s

Commits in First platform

824

Read on 11 Oct 2026 in the GitHub API.

The command for commits in First platform
gh api --paginate "repos/RAMTT-HQ/ramtt-legacy-/commits?per_page=100" --jq '.[] | [.commit.author.date, .commit.author.name, (.commit.message | split("\n")[0])] | @tsv'

Commits in First website

21

Read on 11 Oct 2026 in the GitHub API.

The command for commits in First website
gh api --paginate "repos/RAMTT-HQ/ramtt-website/commits?per_page=100" --jq '.[] | [.commit.author.date, .commit.author.name, (.commit.message | split("\n")[0])] | @tsv'

Commits in Prototypes

7

Read on 11 Oct 2026 in the GitHub API.

The command for commits in Prototypes
gh api --paginate "repos/RAMTT-HQ/ramtt-build-prototypes-v2/commits?per_page=100" --jq '.[] | [.commit.author.date, .commit.author.name, (.commit.message | split("\n")[0])] | @tsv'

Commits in Second website

18

Read on 11 Oct 2026 in the GitHub API.

The command for commits in Second website
gh api --paginate "repos/maltetherkildsen-web/ramtt-website-v2/commits?per_page=100" --jq '.[] | [.commit.author.date, .commit.author.name, (.commit.message | split("\n")[0])] | @tsv'

Commits in RAMTT Cowork

3

Read on 11 Oct 2026 in the GitHub API.

The command for commits in RAMTT Cowork
gh api --paginate "repos/maltetherkildsen-web/RAMTT-Cowork/commits?per_page=100" --jq '.[] | [.commit.author.date, .commit.author.name, (.commit.message | split("\n")[0])] | @tsv'

Commits in Design Cowork

2

Read on 11 Oct 2026 in the GitHub API.

The command for commits in Design Cowork
gh api --paginate "repos/maltetherkildsen-web/ramtt_design_cowork/commits?per_page=100" --jq '.[] | [.commit.author.date, .commit.author.name, (.commit.message | split("\n")[0])] | @tsv'

Days in the period

260

It counts the days from the first commit to the last, both included. It is calculated from first commit and last commit.

Pull requests

Merged pull requests are read with the GitHub CLI.

Merged pull requests in RAMTT monorepo

497

Read on 11 Oct 2026 in the GitHub API.

The command for merged pull requests in RAMTT monorepo
gh pr list -R RAMTT-HQ/RAMTT --state merged --limit 5000 --json number,createdAt,mergedAt --jq '.[] | [.number, .createdAt, .mergedAt] | @tsv'

Merged pull requests in Zibaldone

317

Read on 11 Oct 2026 in the GitHub API.

The command for merged pull requests in Zibaldone
gh pr list -R RAMTT-HQ/zibaldone --state merged --limit 5000 --json number,createdAt,mergedAt --jq '.[] | [.number, .createdAt, .mergedAt] | @tsv'

Merged pull requests in Design system

13

Read on 11 Oct 2026 in the GitHub API.

The command for merged pull requests in Design system
gh pr list -R RAMTT-HQ/ramtt-design-system --state merged --limit 5000 --json number,createdAt,mergedAt --jq '.[] | [.number, .createdAt, .mergedAt] | @tsv'

Merged pull requests in Context bundle

13

Read on 11 Oct 2026 in the GitHub API.

The command for merged pull requests in Context bundle
gh pr list -R RAMTT-HQ/ramtt-context --state merged --limit 5000 --json number,createdAt,mergedAt --jq '.[] | [.number, .createdAt, .mergedAt] | @tsv'

Merged pull requests in Portfolio

147

Read on 11 Oct 2026 in the GitHub API.

The command for merged pull requests in Portfolio
gh pr list -R maltetherkildsen-web/portfolio --state merged --limit 5000 --json number,createdAt,mergedAt --jq '.[] | [.number, .createdAt, .mergedAt] | @tsv'

Merged pull requests in Dotfiles

1

Read on 11 Oct 2026 in the GitHub API.

The command for merged pull requests in Dotfiles
gh pr list -R maltetherkildsen-web/dotfiles --state merged --limit 5000 --json number,createdAt,mergedAt --jq '.[] | [.number, .createdAt, .mergedAt] | @tsv'

Languages

GitHub counts the bytes of each language in each repository.

Bytes per language

14 languages

Read on 11 Oct 2026 in the GitHub API, once for each repository on GitHub.

The command for bytes per language
gh api repos/<owner>/<repository>/languages

The codebase

These are counted with git in the local copies of the repositories.

Tracked files in the RAMTT monorepo

11,334

Read on 11 Oct 2026 in ~/Projects/RAMTT.

The command for tracked files in the RAMTT monorepo
git -C ~/Projects/RAMTT ls-files | wc -l

TypeScript lines in the RAMTT monorepo

911,426

Read on 11 Oct 2026 in ~/Projects/RAMTT.

The command for typeScript lines in the RAMTT monorepo
cd ~/Projects/RAMTT && git ls-files -z '*.ts' '*.tsx' | xargs -0 cat | wc -l

Test files in the RAMTT monorepo

1,122

Read on 11 Oct 2026 in ~/Projects/RAMTT.

The command for test files in the RAMTT monorepo
git -C ~/Projects/RAMTT ls-files | grep -E '\.(test|spec)\.(ts|tsx|mjs|js)$' | wc -l

Test files in Zibaldone

402

Read on 11 Oct 2026 in ~/Projects/zibaldone.

The command for test files in Zibaldone
git -C ~/Projects/zibaldone ls-files | grep -E '\.(test|spec)\.(ts|tsx|mjs|js)$' | wc -l

Database migrations

109

Read on 11 Oct 2026 in ~/Projects/RAMTT.

The command for database migrations
git -C ~/Projects/RAMTT ls-files | grep -i 'migrations/.*\.sql$' | wc -l

Guards and audits that fail a build

128

Read on 11 Oct 2026 in ~/Projects/RAMTT.

The command for guards and audits that fail a build
cd ~/Projects/RAMTT && node -e "const p=require('./package.json');console.log(Object.keys(p.scripts).filter(k=>/^(audit|lint|guard|check)[:-]/.test(k)).length)"

Browser scripts that drive a page

168

Read on 11 Oct 2026 in ~/Projects/RAMTT.

The command for browser scripts that drive a page
git -C ~/Projects/RAMTT ls-files | grep -E '(maal|measure)[^/]*\.(mjs|js|ts)$' | wc -l

Components specified in the design system

551

Read on 11 Oct 2026 in ~/Projects/ramtt-design-system.

The command for components specified in the design system
git -C ~/Projects/ramtt-design-system fetch --quiet origin r25 && git -C ~/Projects/ramtt-design-system show origin/r25:spec/components.json | python3 -c "import json,sys;c=json.load(sys.stdin)['components'];print(len(c), sum(len(x.get('rules', [])) for x in c.values()))"

Rules the design system measures its components by

4,111

Read on 11 Oct 2026 in ~/Projects/ramtt-design-system.

The command for rules the design system measures its components by
git -C ~/Projects/ramtt-design-system fetch --quiet origin r25 && git -C ~/Projects/ramtt-design-system show origin/r25:spec/components.json | python3 -c "import json,sys;c=json.load(sys.stdin)['components'];print(len(c), sum(len(x.get('rules', [])) for x in c.values()))"

The prototypes

These are read from the prototypes’ own code, their component library, the files their checks wrote and the last green run of those checks.

Components in the component library

634

Read on 11 Oct 2026 in the portfolio folder.

The command for components in the component library
find prototypes/components -mindepth 2 -maxdepth 2 -name index.html | wc -l

Shelves in the component library

12

Read on 11 Oct 2026 in the portfolio folder.

The command for shelves in the component library
grep -o 'data-shelf="[^"]*"' prototypes/components/index.html | sort -u | grep -vc '"all"'

Prototypes

39

Read on 11 Oct 2026 in the portfolio folder.

The command for prototypes
node --input-type=module -e "import('./prototypes/source/kit.mjs').then((m) => console.log(m.PROTOTYPES.length))"

Behavior checks in Chromium

566

Read on 8 Oct 2026 in the portfolio folder, from prototypes/source/test/last-check.json.

The command for behavior checks in Chromium
sh ~/scripts/queue.sh sh ~/scripts/heavy.sh sh prototypes/source/test/check-all.sh

Pages measured against the design system

117

Read on 8 Oct 2026 in the portfolio folder, from prototypes/source/test/last-check.json.

The command for pages measured against the design system
sh ~/scripts/queue.sh sh ~/scripts/heavy.sh sh prototypes/source/test/check-all.sh

Measured checks on those pages

48,250

Read on 8 Oct 2026 in the portfolio folder, from prototypes/source/test/last-check.json.

The command for measured checks on those pages
sh ~/scripts/queue.sh sh ~/scripts/heavy.sh sh prototypes/source/test/check-all.sh

Unit tests

330

Read on 8 Oct 2026 in the portfolio folder, from prototypes/source/test/last-check.json.

The command for unit tests
sh ~/scripts/queue.sh sh ~/scripts/heavy.sh sh prototypes/source/test/check-all.sh

Tests of the language’s official suite that Spark passes

38,639

Read on 11 Oct 2026 in the portfolio folder.

The command for tests of the language’s official suite that Spark passes
python3 -c "import json;t=json.load(open('prototypes/p39-spark/test262/summary.json'))['totals'];print(sum(x['pass'] for x in t.values()), sum(x['fail'] for x in t.values()))"

Tests of the language’s official suite that Spark fails

2

Read on 11 Oct 2026 in the portfolio folder.

The command for tests of the language’s official suite that Spark fails
python3 -c "import json;t=json.load(open('prototypes/p39-spark/test262/summary.json'))['totals'];print(sum(x['pass'] for x in t.values()), sum(x['fail'] for x in t.values()))"

How the totals add up

The totals are not counted by a command of their own. They are added up from the counts of each repository. Point at a number to see what it is made from; click it to read its source.

Rebuilding the site

The first command runs every command above and writes the numbers. The second builds the pages from them.

The commands that build the site
node site/collect.mjs
cd web && npm run build
Colophon

How the site is set and served

Set in Inter Variable, kept on the site’s own server and cut to the letters a Latin page uses and the weights from regular to bold, with the optical size kept. In the notes, Galley, the layout engine in the Lab, chooses the line breaks of each paragraph as TeX does and hyphenates with TeX’s patterns.

Built with vinext on Vite, rendered to HTML when the site is built, and served by a Cloudflare Worker at therkildsen.dev. The prototypes run on a second Worker at therkildsen.dev/lab, where a Durable Object with SQLite keeps their data and the contact form’s messages.

A service worker keeps every page on the device, so the site opens without a network, and a message written offline waits there until it can be sent.

The pages are drawn in the RAMTT design system: its tokens, its components and the site’s parts built from them.

Written and built by Malte Therkildsen.