Just a moment.

A sheet-music marketplace that digitises and corrects scores without leaving the app

Browse the catalogue, buy or sell access to a work, and upload your own scanned score to transcribe and correct it right there. An optical-recognition engine measures its key, its time signature and its range: no need to type them by hand, or switch to another app.

ProjectSheetifyYear2026RepositoryGitHub
MUSICMARKETPLACEOMR
OVERVIEW
Type
Cross-platform desktop app
Catalogue
57 scores · 3 eras · 4 ensembles · 19 instruments
Engine
Audiveris 5.11, inside the app
Year
2026

What it is

Sheetify brings together in a single desktop app what today takes three: browsing a catalogue, digitising your own scores and buying or selling access to them.

The piece that makes it possible is optical recognition. A musician uploads a work's PDF and Audiveris transcribes it to MusicXML; from that notation the app measures the musical data instead of asking the uploader for it: key, time signature, tempo, bar count, range per voice and actual instrumentation.

That data is what feeds the catalogue's facets and a difficulty index computed by a separate Python service. Access is sold as time-limited licences: 90 days, 180 days, a year or permanent.

Sheetify
THE PROBLEM

A musician uses one tool to read their scores, another to buy them and another to keep them organised. None of the three avoids the same thing: ending up typing by hand what the score already says.

DIGITISE

A scanner only takes photos

Moving paper to digital usually produces a static PDF: to the computer it's a mute image, not a score, and there's no way for the app to understand the music it contains.

MEASURE

If nothing reads the work, everything gets typed by hand

Because the file is blind, neither the marketplace where you buy it nor the folder where you keep it knows what the work is about: the data is typed by hand by whoever uploads it, and there it stays.

CENTRALISE

The chaos of paper and loose files

You read in an app, buy on a website and pile up digital files that live alongside paper folders on the music stand at home. Your repertoire is scattered across places that don't talk to each other.

THE PIPELINE

From a scan to musical data

Everything the catalogue knows about a work comes out of this journey. None of it is typed by whoever uploads the score.

  • Transcription: Audiveris 5.11 runs embedded in the app's own window: you transcribe in two clicks and fix whatever it misread right there, before exporting. It sits apart from the rest of the code because it's Java and AGPL: it runs as a separate process rather than linked into the app.

  • Metadata extraction: from the MusicXML come key, time signature, tempo, bar count, range per voice and instrumentation.

  • Features: note density, interval leaps, rhythmic complexity, accidentals and polyphony.

  • Difficulty index: a FastAPI service combines those features, calibrated against the corpus, into a number from 1 to 10.

The result is stored on the score and becomes one more facet of the catalogue: you can filter by difficulty just like by era or instrument.

It's an index, not a prediction

There's no set of labelled scores to train a regressor on. What there is is a combination of measured features, turned into a number from 1 to 10.

PRODUCT

A complete journey, from browsing to selling

Browsing the catalogue, reading a score page by page, uploading and transcribing a work, buying a licence and seeing what you've sold.

The facets aren't hand-applied labels: they're the data that came out of the pipeline. Filtering by time signature or by difficulty works because someone measured them, not because someone typed them.

PURCHASES

Buying twice at once

Access is sold as time-limited licences, and buying is the operation that costs most if it fails halfway. The whole checkout goes through four guarantees.

  1. Single transaction

    The order is created, the licence is issued and the sale is recorded, or nothing is touched.

    Avoidsa half-finished order, with the licence unissued or the sale unrecorded
  2. Partial unique index

    Buying "forever" twice is impossible by construction, whatever the isolation level. The full rule (you already hold this work with an equal or higher licence) lives inside the same transaction.

    Avoidstwo simultaneous purchases of the same work, both passing the prior check under Read Committed
  3. Receipt after the commit

    The PDF is derived data, rebuildable from the order: it's generated only once the transaction has committed.

    Avoidsa failure drawing the PDF undoing a purchase that already went through
  4. Tests against a real PostgreSQL

    One fires two checkouts at once and asserts a single order; another forces a failure on the last step and asserts zero rows, with the cart intact.

    Avoidswhat an in-memory provider would never prove
THE REWRITE

The same product, rewritten from scratch

Sheetify is the rebuild of my 2025 final-year project: WinForms, Windows only, a single project without a single layer. It does the same thing as the original. The difference is in how it's written, and it can be spelled out.

Final project, 2025Sheetify, 2026
ScopeWinForms on .NET Framework: Windows only.Avalonia: Windows, Linux and macOS, with a light and dark theme.
PaymentZero transactions. A failure mid-purchase left the order created and the licence unissued.The checkout is a single transaction, with rollback and concurrency tests against a real PostgreSQL.
PricingSheetDetailControl and CartControl each computed the price on their own; an unrecognised tier sold the score for €0.LicensePricing lives in Domain with an exhaustive switch and no default: a tier without a price is a compile error, not a €0 sale.
Data access78 SqlCommands hand-written inside UI classes, 7 built by concatenating user text.All access goes through repositories and IQueryable. Not one query in the view layer.
UINot a single await: the window froze on every database query.Fully async.
Password recoverySix-digit code from new Random(), stored in the client's memory and compared right there; no limit on attempts or requests.Single-use token, hashed on the server, expires after 15 minutes and at most 3 requests per hour.
StructureOne project, no layers, no dependency injection, no logging and no tests.Five projects with the dependencies verified by architecture tests.
Code, decisions and architecture in the repository.GitHub
NEXT PROJECT
MedFlow