A cross-platform, WYSIWYG sheet-music editor that composes, edits, plays back, and exports professional sheet music.
Built with TypeScript, React, VexFlow, and Tauri.
- WYSIWYG Staff Editor: Drag-and-drop note entry, selection, copy/paste, multi-measure edit, undo/redo
- Multi-Staff Support: Piano grand staff, orchestral, choir templates
- Full Notation: Clefs, key/time signatures, tuplets, ties, slurs, beams, rests, articulations, dynamics, grace notes, chord symbols, lyrics, repeats, volta endings
- Playback: MIDI event scheduling, tempo automation, metronome, per-staff mute/solo
- Import/Export: MusicXML (round-trip), MIDI, native project file (
.osmproj), PDF (print quality), WAV audio - Accessibility: Keyboard navigation, screen-reader labels, high-contrast mode
- Cross-Platform: macOS
.app/.dmg, Windows.exe/.msi, Linux.deb/.AppImage
- Node.js 20+
- Rust (stable toolchain)
- Platform-specific dependencies for Tauri: see Tauri Prerequisites
npm ci
npm run devnpm run build
npm run tauri:buildnpm testnpm run check:commentsOpenSheetMusic/
├── src/
│ ├── core/ # Document model, mutations, I/O, playback
│ │ ├── document-model.ts # Immutable score data types and constructors
│ │ ├── undo-manager.ts # Snapshot-based undo/redo
│ │ ├── musicxml-io.ts # MusicXML parser and serializer
│ │ ├── midi-converter.ts # MIDI conversion
│ │ ├── playback-engine.ts # WebAudio playback
│ │ ├── pdf-exporter.ts # PDF generation
│ │ ├── wav-exporter.ts # WAV audio export
│ │ ├── project-file.ts # Native .osmproj format
│ │ ├── score-mutations.ts # Immutable score operations
│ │ └── index.ts
│ ├── ui/ # React UI components
│ │ ├── App.tsx # Main application component
│ │ ├── ScoreRenderer.tsx # VexFlow-based notation renderer
│ │ ├── Toolbar.tsx # Editing toolbar
│ │ ├── StaffPanel.tsx # Staff mixer panel
│ │ └── StatusBar.tsx # Status bar
│ ├── main.tsx # Entry point
│ └── styles.css # Application styles
├── src-tauri/ # Rust/Tauri backend
│ ├── src/
│ │ ├── main.rs # Tauri application entry
│ │ └── midi_bridge.rs # Native MIDI file handling
│ ├── Cargo.toml
│ └── tauri.conf.json
├── tests/ # Unit tests
├── tools/ # Build and CI tools
│ ├── check-no-comments.mjs # Comment-free enforcement script
│ └── pre-commit # Git pre-commit hook
├── .github/workflows/
│ └── release.yml # CI/CD pipeline
├── package.json
├── tsconfig.json
├── vite.config.ts
├── CONTRIBUTING.md
├── CODE_OF_CONDUCT.md
└── LICENSE (MIT)
The score is represented as an immutable data structure. All mutations return new score objects, enabling simple snapshot-based undo/redo with the UndoManager.
VexFlow renders musical notation directly in SVG within the browser/Tauri webview. Only visible measures are rendered for performance with large scores.
Uses the WebAudio API for synthesis. MIDI events are scheduled with deterministic timestamps for accurate playback. The Rust backend provides native MIDI file parsing and writing via the midly crate.
- MusicXML: Bidirectional conversion targeting lossless round-trip fidelity
- MIDI: Score-to-MIDI and MIDI-to-Score conversion
- Project File: JSON-based
.osmprojformat preserving full score state - PDF: Print-quality export via jsPDF
- WAV: Direct audio synthesis export
| Key | Action |
|---|---|
| C-B | Add note (C through B at octave 4) |
| R | Add rest |
| 1-6 | Select duration (whole through 32nd) |
| Delete/Backspace | Delete selected element |
| Ctrl+Z | Undo |
| Ctrl+Shift+Z / Ctrl+Y | Redo |
| Ctrl+S | Save project |
| Ctrl+N | New score |
| Space | Play/Pause |
| Escape | Stop playback |
| Arrow Keys | Navigate staves and measures |
The GitHub Actions pipeline (.github/workflows/release.yml):
- Checks for comments in source files
- Runs unit tests
- Builds web assets
- Builds Tauri desktop apps for macOS, Windows, and Linux
- Creates a GitHub Release with downloadable artifacts (on tag push)
To enable code signing for releases, add these secrets to your GitHub repository:
macOS:
APPLE_CERTIFICATE: Base64-encoded.p12certificateAPPLE_CERTIFICATE_PASSWORD: Certificate passwordAPPLE_SIGNING_IDENTITY: Signing identity stringAPPLE_ID: Apple ID for notarizationAPPLE_PASSWORD: App-specific password
Windows:
WINDOWS_CERTIFICATE: Base64-encoded.pfxcertificateWINDOWS_CERTIFICATE_PASSWORD: Certificate password
The build will succeed without signing credentials but produce unsigned binaries.
All source files must contain zero comments. This is enforced by:
- A CI job that scans all tracked source files
- A pre-commit hook (
tools/pre-commit) - The
npm run check:commentsscript
To install the pre-commit hook:
cp tools/pre-commit .git/hooks/pre-commit
chmod +x .git/hooks/pre-commitAll dependencies are open-source:
| Dependency | License | Purpose |
|---|---|---|
| React | MIT | UI framework |
| VexFlow | MIT | Music notation rendering |
| Tauri | MIT/Apache-2.0 | Desktop app shell |
| jsPDF | MIT | PDF generation |
| uuid | MIT | ID generation |
| midly (Rust) | MIT | MIDI file parsing |
| Vite | MIT | Build tool |
| Vitest | MIT | Test framework |
MIT License - see LICENSE for details.
Copyright (c) 2026 Zorvia