Open the studio and press Play. No install, no account.
SonicStudio is a browser-native composition studio built with React and Tone.js. It is aimed at fast song sketching, sound design, arrangement editing, and practical workflow exits inside the browser.
The current build supports an actual writing flow:
- build phrases in the step sequencer
- arrange clips and order sections in the same view
- shape lanes with synth and sample sources
- bounce a mix to WAV
- import and export MIDI
- recover safely with checkpoints and snapshots
- A step sequencer with inline piano-roll, arrangement, and timeline panels, plus a mixer and a sound desk, all tied to one serializable project state
- Synth lanes and sample lanes with slice-aware triggering, and a live spectrum in the transport
- Song markers, loop ranges, clip editing, pattern transforms, and section duplication
- MIDI import and scoped MIDI export
- WAV bounce with scope selection, print targets, analysis, and bounce history
- Master presets, master snapshots, track sound recall, and recovery checkpoints
- A genre-spanning starter library with a featured scene that rotates daily, plus compressed share links that reopen a session in one click
The codebase is now split around a few real boundaries:
src/context/AudioContext.tsxThin integration shell for the audio provider. It now wires controllers, reducer state, persistence, keyboard shortcuts, and the public context surface instead of owning the reducer internals directly.src/context/editor/projectMutations.tsPure arranger clip and track mutation helpers used by the reducer.src/context/editor/editorDispatchers.tsDispatch-bound action methods used by the provider so action wiring is no longer handwritten inline.src/context/editor/keyboardShortcuts.tsRuntime keyboard shortcut bridge for undo, redo, save, transport, metronome, and pattern focus.src/context/editor/reducer/*Domain reducer ownership split across UI, project, track source, note-event editing, note-pattern editing, clip-pattern step editing, clip-pattern event editing, automation, transforms, track structure, arranger, and history action maps, plus reducer utilities and editor state types.src/context/editor/transportController.tsPlayback, recording, preview, and transport reset orchestration for the provider layer.src/context/editor/renderController.tsProvider-facing mix, stem, MIDI, and bounce-history orchestration.src/context/editor/sessionController.tsProvider-facing session import, export, restore, checkpoint, and template-load orchestration.src/app/routeController.tsExplicit launch and deep-link state resolution so first run, persisted sessions, and query-driven entry all follow one path.src/services/renderWorkflow.tsRender and bounce orchestration.src/services/sessionWorkflow.tsPersistence, checkpoint, and import orchestration.src/components/settings/*Workspace, track, and output controls broken into smaller panels.src/components/arranger/*Arranger selector logic, interaction utilities, clip drag and paint hooks, viewport and shortcut hooks, inspector panels, and hero-surface view modules.
The reducer is now split across small, focused action maps (the largest is under 300 lines), and every provider seam has its own test file: transport, session restore and checkpoints, render and export scope, and route-driven entry. The per-keystroke corpus summary has also been moved off the edit hot path — it recomputes after edits settle rather than on every toggle.
The provider's stable callbacks now live in their own actions context
(useAudioActions), so a component that only dispatches no longer re-renders
when tracks, selection, or the playhead change; the per-step playhead has its own
context as well. The remaining targets are smaller and more contained:
- device-rack source ownership is still concentrated in the slice and source-window authoring path
- heavy views still read editor state through one shared context, so narrowing those reads to per-slice subscriptions is the next render-churn lever if large projects ever need it
- Start the dev server or open the hosted build
- Use the launch surface to open a real scene, start blank, or import MIDI
- Load
Beat Labfor rhythm work orNight Transitfor a fuller song sketch - Open the Arrangement panel in the sequencer to inspect clips and sections
- Open the Notes panel for tighter pitch and gate editing
- Export MIDI from the Setup menu, or bounce a WAV from Output settings
Prerequisite: Node.js 20+
npm install
npm run devVite serves the studio at http://localhost:3000/.
For a portable static bundle that works on root-based static servers, use:
npm run buildFor GitHub Pages under /SonicStudio/, use:
npm run build:pagesThe README and Open Graph images (public/share/) are captured from the running
app, so they stay honest after UI changes. With a dev server up, regenerate them:
npm run dev # serves the studio
npx playwright install chromium # once
CAPTURE_URL=http://127.0.0.1:3000 npm run capture:heronpm run lint
npm test
npm run buildnpm run lint runs the TypeScript compiler and ESLint (typescript-eslint plus the React hooks rules); npm test runs the Vitest suite; npm run build type-checks and produces the production bundle.
Current test coverage includes reducer invariants, arranger selector and interaction logic, clip mutation helpers, note edit hydration, MIDI round trips, transport-controller behavior, render workflow behavior, session workflow behavior, explicit route resolution, controller-level render and restore seams, component render smoke tests, the share-link codec and lazy-load retry, and registry integrity checks that build every starter scene and validate every voice preset.
The strongest next milestones are:
- keep shrinking reducer concentration in note-pattern and clip-pattern step ownership
- expand correctness coverage around reducer action-map behavior, checkpoint restore, transport state, render-scope replay, and route-driven entry
- keep the device rack moving toward true source, shape, space, slicing, and recall ownership boundaries, with the slice and source-window path next
- keep the arranger focused on composition fluency instead of growing every side feature equally
- keep the launch surface and route entry logic explicit instead of drifting back into layered shell clutter
