Notae

Notae: local-first sheet-music library for Android phones and tablets **Browse and search your sheet-music PDFs on an Android phone or tablet. No cloud, no account, no network access.** Version 0.7.0 · Android phone and tablet (arm64) · one maintainer · roadmap [![CI](https://github.com/eRgo35/notae/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/eRgo35/notae/actions/workflows/ci.yml) [![Latest release](https://img.shields.io/github/v/release/eRgo35/notae)](https://github.com/eRgo35/notae/releases/latest) [![MIT license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/eRgo35/notae/blob/main/LICENSE) [![Rust 1.98.1](https://img.shields.io/badge/Rust-1.98.1-orange?logo=rust)](https://github.com/eRgo35/notae/blob/main/rust-toolchain.toml) [![Android 8.0+ (API 26), arm64](https://img.shields.io/badge/Android-8.0%2B%20%7C%20arm64-3DDC84?logo=android&logoColor=white)](#install) [Download](https://github.com/eRgo35/notae/releases/latest) · [Quick start](#quick-start) · [Documentation](#documentation) · [Changelog](https://github.com/eRgo35/notae/blob/main/CHANGELOG.md) · [Roadmap](https://github.com/eRgo35/notae/blob/main/ROADMAP.md) · [Issues](https://github.com/eRgo35/notae/issues) · [Contributing](https://github.com/eRgo35/notae/blob/main/CONTRIBUTING.md) Notae Library in light theme: a collapsible sidebar and a grid of four score cards with first-page thumbnails Android emulator capture of a development build, with sample scores.

Why Notae

If you keep a few hundred scanned or exported scores as plain PDFs, a file manager gives you file names and nothing else; nothing can search the printed text inside a scan. Notae adds a private catalogue on top of your existing folder and leaves the PDFs exactly where they are. It does not render or annotate scores itself: it hands each PDF to the viewer you already use.

Features

Screenshots

Search with the query Hex: the matching score is listed with its lyric text highlighted; scope chips All, Titles, Composers, Lyrics and Tags are shown above
Search titles, composers, tags and lyrics.
Full-width score preview showing the first page next to the title, number, file name and an Open score button
Preview with details and an Open score action.
Notae Library as a dense list of four scores, each with a thumbnail, title, number and an info button
List view for dense libraries.
Notae Library in the dark theme with the sidebar and four score cards
Dark theme follows the system setting.

All screenshots are real captures from an Android 15 tablet emulator (2560×1600) of the v0.2.1 development build, showing sample scores, not from a physical tablet.

How it works

Notae reads the folder you pick through Android’s Storage Access Framework and builds its own private index from it.

flowchart LR
    subgraph tablet["Android tablet"]
        files[("Library folder<br/>PDFs")]
        app["Notae<br/>scan, browse, search,<br/>edit details"]
        viewer["Your PDF viewer<br/>(Samsung Notes, ...)"]
        files -->|"folder grant (SAF)"| app
        app -->|"open score"| viewer
    end

Notae never syncs or uploads anything. There is no on-device OCR yet; ADR 0001 accepts it as a manual, foreground step (#28), not yet built.

Install

[!NOTE] Notae is young. 0.5.0 rebuilds the app in Jetpack Compose with a new app id, com.c2yz.notae: it installs beside 0.3.0 or 0.4.0 instead of updating it. Use Export sets in the old app first and import the file on 0.5.0’s first screen to keep your favorites and sets (see the changelog). Please report anything odd.

Notae ships one Android artifact: a signed arm64 APK for Android phones and tablets with Android 8.0 (API 26) or newer, attached to each GitHub Release. The release workflow builds, signs and verifies it from the release tag.

  1. Download notae-<version>-arm64.apk and its .sha256 from the latest release.
  2. Verify it. The checksum only catches a corrupted download; the signature check is what proves the APK came from the Notae release key.

    V=0.7.0
    sha256sum -c "notae-$V-arm64.apk.sha256"
    apksigner verify --print-certs "notae-$V-arm64.apk" \
      | grep -i 'SHA-256 digest: be27cd781766c5c28a9db106c07b051ceee4e0003105964595e2a848f371f601'
    

    apksigner ships with the Android SDK build tools. The grep must print one line; if it prints nothing, do not install the APK. The same fingerprint, in the usual colon-separated form, is published in docs/android-release.md and pinned in .github/workflows/release.yml:

    BE:27:CD:78:17:66:C5:C2:8A:9D:B1:06:C0:7B:05:1C:EE:E4:E0:00:31:05:96:45:95:E2:A8:48:F3:71:F6:01
    
  3. Copy the APK to the tablet and open it (allow installs from your file manager or browser when Android asks), or run adb install "notae-$V-arm64.apk".

[!WARNING] Installed a self-built (debug) APK before? Uninstall it first. Android will not update an app signed with a different key, and uninstalling deletes Notae’s local data (folder access, index, metadata edits) but never your PDFs. Releases all use one key, so later upgrades work in place.

Quick start

1. Put your PDFs in a folder on the tablet. Name them <number> - <title>.pdf (for example 12 - Autumn Leaves.pdf) to get a number and title for free; other names work and simply have no number.

2. Open Notae and choose the folder. Tap Choose score folder, pick the folder in the Android picker, allow access, then start a scan from the Library. Notae indexes the PDFs. Coming from 0.3.0 or 0.4.0? Tap Import from a previous Notae first and pick the file the old app’s Export sets wrote. The import carries your favorites and sets only: details you edited (number, title, composer, tags) and the Recent list stay in the old app. Keep the old app installed until you have checked that 0.5.0 has what you need.

Using Notae

Build from source

Prerequisites - **Rust 1.98.1**, pinned by [`rust-toolchain.toml`](https://github.com/eRgo35/notae/blob/main/rust-toolchain.toml) (rustup selects it automatically, with `rustfmt` and `clippy`), with the `aarch64-linux-android` and `x86_64-linux-android` targets and `cargo-ndk` 4.1.2. - **Android toolchain:** a JDK (21 or newer), the Android SDK with platform 36, build-tools 36.0.0 and NDK r28c (`28.2.13676358`), and `ANDROID_HOME` pointing at it.
Build the Android app ```sh rustup target add aarch64-linux-android x86_64-linux-android cargo install --locked --version 4.1.2 cargo-ndk cd apps/notae-android ./gradlew assembleDebug # debug-signed APK, arm64-v8a and x86_64 (emulator) ./gradlew assembleRelease # unsigned arm64 release APK ``` Gradle builds the Rust core with cargo-ndk and generates its Kotlin bindings with UniFFI. Debug builds are signed with your Android SDK debug key, so they are **not** update-compatible with the official release APK. Release builds are signed only by the release workflow ([`docs/android-release.md`](https://github.com/eRgo35/notae/blob/main/docs/android-release.md)). See [`docs/android-debugging.md`](https://github.com/eRgo35/notae/blob/main/docs/android-debugging.md) for emulator setup.

scripts/check.sh runs the quality gates (format, Clippy, tests, docs, cargo deny, coverage, and the Gradle lint, tests, screenshot checks and release build); see CONTRIBUTING.md.

Project layout

crates/
  notae-domain/     Filename convention, note metadata, file identity.
  notae-index/      SQLite persistence, FTS5 search and the
                    rescan reconciler.
  notae-app-core/   The app logic (state, stores, browse, search, sets,
                    scans) behind a UniFFI API for the Kotlin app.
apps/
  notae-android/    The Android app (Gradle): Jetpack Compose UI and the
                    Storage Access Framework, PDF and speech platform code.
docs/               Release procedure, engineering standards, debugging guide,
                    design spec and plans.

The UI is Kotlin with Jetpack Compose; the app logic is Rust. Domain logic, indexing, search, sets and the screen state live in the host-tested crates; the Kotlin app draws the core’s snapshots and adds the platform code. The product scope and architecture are in the design spec.

Privacy & security

Found a vulnerability? Follow SECURITY.md and report it privately.

Documentation

Contributing

Bug reports, ideas and pull requests are welcome. Start with CONTRIBUTING.md for the development setup, quality gates, commit conventions and what must never be committed.

Known limitations

What comes next is in ROADMAP.md.

License

Notae is released under the MIT License. Third-party dependencies keep their own licenses; for the Rust crates the accepted set is enforced by cargo deny (deny.toml).