Skip to content

Build FUTO Notes from source (desktop, mobile, and sync server)

The source for the app and the sync server is public on gitlab.futo.org. The desktop app is a Tauri app, so building it takes Node, pnpm, Rust, and just. The sync server is a single Go binary and builds with one go build.

What you can do with a build you make yourself, and what you can share, is set by the source license. See FUTO Notes license.

What you need for the app

The versions below are pinned in the repository, and the build checks some of them.

ToolVersionWhere it is pinned
Node22.23.1.nvmrc
pnpm10.29.2packageManager in package.json
Rust1.89.0, with rustfmt and clippyrust-toolchain.toml
justany recentruns every build command in the justfile
Tauri CLIthe cargo tauri commandinstall with cargo install tauri-cli --locked

With rustup installed, rust-toolchain.toml makes cargo fetch Rust 1.89.0 on first use. fnm reads .nvmrc with fnm use, and Corepack (corepack enable) activates the pinned pnpm.

Each desktop platform also needs its native toolchain:

  • Linux: the WebKitGTK 4.1 and GTK 3 development packages. On Debian and Ubuntu, the project’s CI installs libwebkit2gtk-4.1-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev libssl-dev patchelf, plus libfuse2 for building the AppImage.
  • macOS: Xcode or the Xcode Command Line Tools.
  • Windows: the Visual Studio C++ build tools and NSIS for the installer.

Get the source

git clone https://gitlab.futo.org/futo-notes/futo-notes.git
cd futo-notes
git checkout v1.8.0 # the current release; skip this to build the main branch
just install

just install runs pnpm install. On the main branch, just setup desktop does the same and also checks that the pinned Node and pnpm, cargo, and on Linux the WebKitGTK packages are present. Run just with no arguments to list every recipe.

Run a development build

just tauri-dev

This starts the desktop app with hot reload. A development build is kept apart from the real app so it cannot touch your notes:

  • It uses a separate app ID, com.futo.notes.dev, and is named “FUTO Notes Dev”.
  • Its notes live in ~/Documents/fake-notes, which is seeded with test notes on first launch.
  • It never checks for updates on its own. It discards crash reports instead of sending them, and it sends feedback to a local test collector unless you switch the form to FUTO’s staging server.
  • Settings shows extra debugging sections that release builds don’t have.

On Linux, the dev script starts the app with the Wayland backend.

Build a release desktop app

just tauri-build

This builds the web front end, then runs cargo tauri build. The installers land under target/release/bundle/: an AppImage, a .deb, and an .rpm on Linux, an app bundle and disk image on macOS, and an NSIS installer on Windows. Builds are for the platform you run them on.

Warning: A release build is not isolated the way a dev build is. It uses the same app ID, com.futo.notes, and the same default notes folder, ~/Documents/futo-notes, as the official app, so it opens your real notes. It also behaves like the official app on the network: on macOS, Windows, and the AppImage it checks FUTO’s GitLab for updates, and installing one replaces your build with the official release. Turn off Settings → Updates → Automatically check for updates to keep your build. Its crash reports and feedback go to FUTO’s server, as described in crash reports and feedback.

Build the iOS and Android apps

The mobile apps are native (SwiftUI on iOS, Jetpack Compose on Android) and share the Rust core and the editor with the desktop app. Both recipes build a debug build, which is isolated from the store version of the app.

iOS needs a Mac with Xcode, an iOS simulator runtime, xcodegen, and the Rust targets aarch64-apple-ios and aarch64-apple-ios-sim (rustup target add ...). Boot a simulator, then run:

just ios-native

That builds and installs the app on the booted simulator with no code signing. just ios-native-device targets a connected iPhone and needs your own Apple development team, set with FUTO_DEV_TEAM.

Android needs the Android SDK (ANDROID_HOME), the NDK version pinned in apps/android/app/build.gradle.kts (ANDROID_NDK_HOME), JDK 17, cargo install cargo-ndk, and the Android Rust targets (rustup target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-android i686-linux-android). With a device or emulator connected:

just android-native

The debug build installs as com.futo.notes.dev, next to the store app, with its own storage.

Build the sync server

The server needs Go 1.27, the version in go.mod. With an older Go, prefix commands with GOTOOLCHAIN=auto and Go downloads the right toolchain.

git clone https://gitlab.futo.org/futo-notes/futo-notes-server.git
cd futo-notes-server
go build -o futo-notes-server ./cmd/server

Run it with a sync password and a place for the encrypted blobs:

FUTO_NOTES_PASSWORD='your sync password' \
BLOB_DIR="$PWD/blobs" \
PORT=3005 \
./futo-notes-server

SQLite is the default database, at ./data/notes.db relative to the directory you start it from. Point the app at http://<this-machine>:3005. For running it permanently, with Docker or systemd, see Self-host FUTO Notes sync and the server README.

Other things you can build from the server repository:

  • A Docker image: docker build -t futo-notes-server:local .
  • Release binaries for Linux amd64/arm64, macOS amd64/arm64, and Windows amd64, with a checksum file: scripts/build-release.sh <version>, which writes to dist/.
  • Tests: go test ./... needs no database setup.

Warning: AUTH_MODE=dev starts the server with no password and an extra login route that signs anyone in by email address. It exists for server development only. Never run it on a machine other people can reach. The app signs in with a password, so test the app against a server started with FUTO_NOTES_PASSWORD, as above.

Run the app’s tests

just test # the fast unit and editor suites
just check # lint, tests, and build checks

The repository’s CONTRIBUTING.md and AGENTS.md cover the rest of the development setup, including the sync test harness.

Next steps