Tauri, Angular and Python desktop app that fixes the tags of a DJ's music library using Beatport and Bandcamp. It is distributed to around ten DJs. The user settles ambiguous matches, no file is modified before their confirmation and everything can be restored. In production.
Personal
Team
1 person
Mode
Remote
Duration
2 months
Context
Techno Tagger fixes the tags of a DJ's music library. The app extracts the tracks of a playlist, then rewrites their metadata, artwork included. The data comes from Beatport and Bandcamp, the reference platforms for electronic music. SoundCloud is used for manual recovery. All three sources go through my Techno Scraper API.
It fixes the most common issues: missing artwork, noise in titles, conventions that change from one source to another.
It replaces a Python CLI that only I could use. The code had to be edited before each use. It had a single source (Beatport), only handled MP3 and could not be shared.
Goal: let DJ friends install and use the tool without ever opening a terminal.
My role: design, development and distribution, solo.
Key achievements
Shipping the app to around ten DJs who aren't developers
Users aren't developers and have no development environment on their machine.
Solutions:
A Windows installer is published automatically with every release.
A signed update is offered at launch and installs in one click.
At startup, the app checks that its interface and its engine run the same version. If they differ, it shows a screen explaining what to do instead of an empty interface.
Antivirus: an unsigned application easily triggers them. The installer passes with no alert at all. Windows Defender wrongly flagged the engine: I reported it to Microsoft, which removed the detection.
Never corrupting a music library
Rewriting tags and renaming hundreds of files is the point of no return of a run. A crash halfway through must not leave a half-renamed library. A source that provides little information must not erase what the file already contained either.
Solutions:
No file is touched before the user confirms.
Before the first write, the original tags are saved and every rename is logged. A track or an entire run can be restored in one click for 30 days.
A field the source doesn't provide never changes the existing tag.
An interrupted run resumes where it stopped, without redoing the searches already made.
Track detail before and after tagging, field by field
Letting the user decide without blocking the run
When the right candidate isn't certain, the user picks from a list of plausible matches. The old CLI asked for confirmation on the keyboard, track by track, without showing the candidates side by side.
Solutions:
A dialog shows the candidates with their score, while searches keep running in the background. The user decides as they go or keeps everything for the end.
When Beatport only offers uncertain candidates, Bandcamp is queried only if the user rejects them, in the same window. This avoids doubling calls for nothing.
If nothing fits, the user pastes the URL of the right Beatport, Bandcamp or SoundCloud page.
Arbitration dialog between two ambiguous Beatport candidates
Auto-validating only safe matches
A wrongly validated match writes incorrect tags without any warning. The tricky cases are known:
a file name reduced to noise;
a remix mistaken for the original version;
several versions of the same title.
Solutions:
If cleanup leaves nothing usable, no search is launched: the track goes straight to manual recovery.
Version and collaboration mentions (remix, featuring) are kept during cleanup.
At the slightest version mismatch between the query and the candidate, such as "Pt. 1" versus "Pt. 2", automatic validation is blocked and the choice goes back to the user.
A serverless desktop app, with the business logic in Python
I wanted to keep the business logic in Python, whose audio libraries are the most mature. It had to be neither rewritten in Rust nor bundled with a whole browser, as Electron would do.
Solutions:
Tauri provides the window, Angular the interface and a Python engine launched alongside carries all the business logic.
The two communicate through a message protocol, testable without launching the interface. Almost nothing is written in Rust.
A packaging mode chosen on measurements makes the engine start in 335 ms instead of 2.3 s.
Centralizing title cleanup in the gateway
At first, the app cleaned the titles returned by the API itself. Other projects of mine did the same work, each in its own way, without seeing the sources' structured fields.
Solutions: I moved the cleanup into the gateway, the only one that sees those fields. The app compares candidates as they arrive and its matching code got lighter.
Reporting errors without personal data
A file path contains the Windows user name. A file name contains the artist and the title. Sending crashes as they were meant exposing users' libraries to a third-party service.
Solutions:
Error reporting keeps only technical crashes.
Paths and messages are masked, and data stays hosted in the EU region.
A test checks the content actually sent.
To improve matching, the user shares a report through an explicit action, after reviewing it.
Results
Around ten DJs in my circle use the app, installed and updated automatically
Eight weeks between the first commit and version 1.0
Four formats supported (MP3, WAV, AIFF and FLAC) versus MP3 only before
Two sources chained automatically (Beatport then Bandcamp) instead of one
No file modified before confirmation: everything stays restorable for 30 days
Engine started in 335 ms instead of 2.3 s
Over 2,200 tests, strict typing and lint blocking in CI
Zero cost: free services and an API hosted on a VPS already in place
Learnings
Shipping a first desktop application end to end: Tauri, Windows packaging, signed updates
Cleaning data where the information lives, rather than in every application that consumes it
Recording a decision before acting: a crash becomes harmless and resuming becomes trivial
What breaks in distribution doesn't show in development: test on the installed application, on someone else's machine
Better to ask the user than to silently validate a doubtful result: a crash shows, wrong tags go unnoticed
Turning a design system and a mockup into a faithful interface
Planned improvements
Broader Rekordbox compatibility (WAV, remixer, full release date)
Manual tag editing when no source fits
An AI agent backing up the matching, off by default, to settle ambiguous cases