A browser-based music notation editor built on Smoosic, with a modular architecture for future AI composing agent integration.
| Layer | Technology |
|---|---|
| Frontend | Next.js 14 (Pages router) + React 18 + TypeScript |
| Notation engine | Smoosic (CDN, via window.Smo) |
| Backend | Python 3.11 + FastAPI |
cd frontend
cp .env.local.example .env.local # adjust if backend runs elsewhere
npm install
npm run dev # http://localhost:3000
cd backend
python3 -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
uvicorn main:app --reload # http://localhost:8000
To show Aria MLX model logs when running the API server, set ARIA_LOG_LEVEL:
cd backend
source venv/bin/activate
ARIA_LOG_LEVEL=INFO uvicorn main:app --reload
# or
ARIA_LOG_LEVEL=DEBUG uvicorn main:app --reload
The MLX continuation path uses a locally downloaded model folder and does not download from Hugging Face during each inference call.
cd backend
source venv/bin/activate
python -m ai.download_mlx_model
Default local model directory:
backend/ai/mlx_model/napanto-jazz-piano-performance-modeling/aria-real-time/mlx-deployed
To use a different local model directory, set:
export ARIA_MLX_MODEL_DIR="/absolute/path/to/mlx-model-dir"
You can run continuation directly from a MusicXML file using the MLX Aria model:
cd backend
source venv/bin/activate
python -m ai.continue_from_musicxml_mlx \
--input-xml tests/resources/input/prime_sample_1.musicxml \
--output tests/resources/output/prime_sample_1_continued
The command writes three files based on --output:
<output>.midi<output>.xml<output>-one-staff.xml| Feature | Status |
|---|---|
| New empty piano score (treble + bass grand staff) | ✅ |
Open existing SMO score (.json) | ✅ |
| Import MusicXML | ✅ |
| Import MIDI | ✅ |
| Export MusicXML | ✅ |
| Save score (SMO JSON) | ✅ |
| Select parts of the score | ✅ (built-in Smoosic UI) |
| Right-click context menu on notes | ✅ (hook wired, placeholder items) |
| Play / pause score | ✅ |
| Full score editing (notes, rhythms, dynamics, …) | ✅ (Smoosic built-in editor UI) |
| Backend score storage | ✅ (in-memory; swap for DB in production) |
frontend/
├── pages/
│ ├── _document.tsx # Loads jQuery + Smoosic CSS/JS from CDN
│ ├── _app.tsx # Context providers
│ └── index.tsx # Main editor page
├── components/editor/
│ ├── SmoosicEditor.tsx # No-SSR Smoosic container
│ ├── EditorToolbar.tsx # File & playback operations bar
│ └── ContextMenu.tsx # Right-click context menu
├── context/
│ ├── ScoreContext.tsx # Score state + file operations
│ └── EditorContext.tsx # Selection state
└── lib/smoosic/
└── bridge.ts # ← AI seam: SmoosicBridge wraps Smoosic API
backend/
├── main.py # FastAPI app
├── routers/scores.py # Score CRUD
└── models/score.py # Pydantic models
SmoosicBridgelib/smoosic/bridge.ts is the single interface between the application and Smoosic. All public methods are async and return plain serializable data, making it straightforward to expose them over REST or WebSocket for Phase 2:
AI Agent (Python) ──→ FastAPI backend ──→ REST/WS ──→ SmoosicBridge ──→ Smoosic
bridge.getScoreJson(), sends mutations back)9 commits
Python
72.5%
TypeScript
23.3%
CSS
4.1%
A browser-based music notation editor built on Smoosic, with a modular architecture for future AI composing agent integration.
| Layer | Technology |
|---|---|
| Frontend | Next.js 14 (Pages router) + React 18 + TypeScript |
| Notation engine | Smoosic (CDN, via window.Smo) |
| Backend | Python 3.11 + FastAPI |
cd frontend
cp .env.local.example .env.local # adjust if backend runs elsewhere
npm install
npm run dev # http://localhost:3000
cd backend
python3 -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
uvicorn main:app --reload # http://localhost:8000
To show Aria MLX model logs when running the API server, set ARIA_LOG_LEVEL:
cd backend
source venv/bin/activate
ARIA_LOG_LEVEL=INFO uvicorn main:app --reload
# or
ARIA_LOG_LEVEL=DEBUG uvicorn main:app --reload
The MLX continuation path uses a locally downloaded model folder and does not download from Hugging Face during each inference call.
cd backend
source venv/bin/activate
python -m ai.download_mlx_model
Default local model directory:
backend/ai/mlx_model/napanto-jazz-piano-performance-modeling/aria-real-time/mlx-deployed
To use a different local model directory, set:
export ARIA_MLX_MODEL_DIR="/absolute/path/to/mlx-model-dir"
You can run continuation directly from a MusicXML file using the MLX Aria model:
cd backend
source venv/bin/activate
python -m ai.continue_from_musicxml_mlx \
--input-xml tests/resources/input/prime_sample_1.musicxml \
--output tests/resources/output/prime_sample_1_continued
The command writes three files based on --output:
<output>.midi<output>.xml<output>-one-staff.xml| Feature | Status |
|---|---|
| New empty piano score (treble + bass grand staff) | ✅ |
Open existing SMO score (.json) | ✅ |
| Import MusicXML | ✅ |
| Import MIDI | ✅ |
| Export MusicXML | ✅ |
| Save score (SMO JSON) | ✅ |
| Select parts of the score | ✅ (built-in Smoosic UI) |
| Right-click context menu on notes | ✅ (hook wired, placeholder items) |
| Play / pause score | ✅ |
| Full score editing (notes, rhythms, dynamics, …) | ✅ (Smoosic built-in editor UI) |
| Backend score storage | ✅ (in-memory; swap for DB in production) |
frontend/
├── pages/
│ ├── _document.tsx # Loads jQuery + Smoosic CSS/JS from CDN
│ ├── _app.tsx # Context providers
│ └── index.tsx # Main editor page
├── components/editor/
│ ├── SmoosicEditor.tsx # No-SSR Smoosic container
│ ├── EditorToolbar.tsx # File & playback operations bar
│ └── ContextMenu.tsx # Right-click context menu
├── context/
│ ├── ScoreContext.tsx # Score state + file operations
│ └── EditorContext.tsx # Selection state
└── lib/smoosic/
└── bridge.ts # ← AI seam: SmoosicBridge wraps Smoosic API
backend/
├── main.py # FastAPI app
├── routers/scores.py # Score CRUD
└── models/score.py # Pydantic models
SmoosicBridgelib/smoosic/bridge.ts is the single interface between the application and Smoosic. All public methods are async and return plain serializable data, making it straightforward to expose them over REST or WebSocket for Phase 2:
AI Agent (Python) ──→ FastAPI backend ──→ REST/WS ──→ SmoosicBridge ──→ Smoosic
bridge.getScoreJson(), sends mutations back)9 commits
Python
72.5%
TypeScript
23.3%
CSS
4.1%