# The screenshot in the README is the test

> mani is a Kotlin Multiplatform demo where the same server compiles to the JVM and to a native binary — and where the picture advertising the interface cannot drift from it.

Page: https://kotlin.website/blog/the-screenshot-is-the-test · Published: 2026-02-08

[mani](https://github.com/youndie/mani) is a budget planner, and it is a demo on purpose.
It exists to show what a full Kotlin stack looks like when every part of it is real rather
than sketched: Compose Multiplatform clients for Android, iOS, desktop and the browser, a
Ktor server that compiles **both** to the JVM and to a native Linux binary, and one shared
module holding the API contract for all of them.

## The same code on both sides of the wire

The interesting part of KMP is not that clients share code. It is that the contract does.

The same `@Resource` classes route requests on the server and build URLs on the client.
Rename a path and both ends move together; there is no place for a string on one side to
disagree with a string on the other, because there is only one string.

The same code signs a token in the JVM build and in the native build. That is a stronger
claim than it looks: two server binaries, two runtimes, one implementation of the thing
that must not differ between them.

## The screenshot cannot lie

The image at the top of the README is not a screenshot somebody took and committed.

It *is* one of the goldens the screenshot tests compare against, referenced from its path
in `composeApp/src/desktopTest/snapshots`. Re-recording the goldens redraws the README
picture in the same commit.

This is a small trick with a disproportionate effect. Every project's README screenshot
starts accurate and ends up eighteen months stale, showing a screen that no longer exists.
Pointing the README at the golden makes staleness impossible: if the picture is old, the
tests are failing.

The goldens come from [viddik](https://github.com/youndie/viddik), which renders through
Compose Desktop, so they hold across machines.

## Two of its dependencies were written for it

Two moving parts exist because this project needed them and nothing else fit.

**[mongkn](https://github.com/youndie/mongkn)** — a MongoDB driver for Kotlin/Native over
the C driver via cinterop. There is no official one, and the native server build has to
talk to the same database as the JVM build, in the same document shape. That constraint is
what made the driver necessary rather than interesting.

**[viddik](https://github.com/youndie/viddik)** — the screenshot testing above.

Building the demo is what surfaced the gaps; the libraries are what came out of them.
Which is roughly how every useful library I have written started.

## What it is not

There is no email confirmation, no password recovery, no rate limiting, and passwords are
hashed with salted SHA-256 rather than a slow KDF.

Saying so is the point. A demo that quietly omits the security work invites someone to copy
it, and the omissions are exactly what a reader cannot see. The public instance is a
playground — please do not keep anything you would miss in it.

---

Source: [github.com/youndie/mani](https://github.com/youndie/mani) ·
live at [mani.kotlin.website](https://mani.kotlin.website)
