---
title: Development
description: Build Sluurp from source, run it while you change it, and test it.
section: Development
order: 1
---

# Development

<p class="lead">Working on Sluurp itself: a Rust toolchain builds the binary, Node runs the browser tests, and the website you are reading is a Sluurp app served by what you just built.</p>

## A machine to build on

| What | Why |
|---|---|
| [Rust](https://rustup.rs), stable | the server; edition 2024 |
| a C compiler | SQLite, libgit2 and QuickJS are built from source: Xcode's command line tools on macOS, `build-essential` on Linux, Visual Studio's C++ build tools on Windows |
| `pkg-config` and `libssl-dev` (Linux only) | libgit2 links the system's OpenSSL |
| [Node](https://nodejs.org) 22+ and [pnpm](https://pnpm.io) | the browser tests and the client's unit tests; nothing Node ships in the binary |

```sh title="Terminal"
git clone https://github.com/SluurpHQ/sluurp
cd sluurp
cargo build
```

The first build compiles the three C libraries and takes a few minutes; later ones take seconds.

## Run it while you change it

```sh title="Terminal"
cargo run -- superuser you@example.com a-long-password
cargo run -- serve --public website
```

`serve` reloads as you work, with nothing to switch on:

- a saved `.tsx`, `.ts`, `.js` or `.css` file in the app is sent to the open pages, which swap the module in place;
- a saved Markdown page, layout or server-rendered route redraws the page.

A change to the Rust code needs a rebuild and a restart. On Windows a running `sluurp.exe` cannot be overwritten, so `node scripts/dev-server.mjs PORT --public DIR` ([the script](https://github.com/SluurpHQ/sluurp/blob/master/scripts/dev-server.mjs)) builds once and runs a copy, and `cargo build` keeps working beside it. [`.claude/launch.json`](https://github.com/SluurpHQ/sluurp/blob/master/.claude/launch.json) names the servers used while developing: the website, MikroSchool, the dashboard alone, and the examples.

Errors land in the dev overlay: a page that fails shows its error at its line in the source, with a link into your editor; what is not fatal is counted in a corner.

## Tests

```sh title="Terminal"
# The server: unit tests and the integration tests in tests/it, each against a real server on a real file
cargo test

# The client's pure code, such as the chart language
node --test tests/client/*.test.ts

# The browser tests, against the binary and a real database
cd e2e
pnpm install
pnpm exec playwright install chromium
pnpm test
```

`pnpm run smoke` in [`e2e/`](https://github.com/SluurpHQ/sluurp/tree/master/e2e) runs the quick subset. CI runs all of it on Linux and Windows, then `cargo fmt --check` and `cargo clippy -- -D warnings`.

## Benchmarks

```sh title="Terminal"
cargo run --release -- bench
```

It measures the storage layer (creates, reads, lists, updates, deletes, `asOf`), one caller and many, beside the same operations on bare SQLite, and ends with an overall score. `--json` prints the numbers, and `--out FILE` writes them, which is how [Why SQLite](/docs/why-sqlite) gets its table. Measure the release build: the debug one is much slower, and its numbers say little.

## A release

Pushing a tag such as `v0.2.0` runs [`.github/workflows/release.yml`](https://github.com/SluurpHQ/sluurp/blob/master/.github/workflows/release.yml). It builds the binary for Linux (x64, arm64), macOS (Intel, Apple silicon) and Windows, and attaches them with their checksums to a GitHub release, where [`install.sh`](https://github.com/SluurpHQ/sluurp/blob/master/install.sh) and [`install.ps1`](https://github.com/SluurpHQ/sluurp/blob/master/install.ps1) find the latest.
