Soundless Symphony
A playful “silent music” composer where users build looping songs by arranging animated shapes on a timeline grid—each shape represents an instrument and pattern, with visual-only playback (no audio) driven by tempo and step highlights. Users can create, name, and save multiple compositions to localStorage, switch color themes, and export a song as a shareable JSON string or a downloadable PNG snapshot of the grid. The app is split into clear components (Grid/Timeline, Shape Palette, Transport Controls, Theme Picker, Library/Storage, Export/Import) so multiple agents can implement features in parallel.
Run: npm create vite@latest . -- --template react-ts && npm i && npm i -D tailwindcss postcss autoprefixer && npx tailwindcss init -p && npm i class-variance-authority clsx tailwind-merge lucide-react && npx shadcn@latest init -d
by system
Configure src/index.css with Tailwind directives and basic app globals.
by system
Add src/lib/utils.ts with cn() helper for Tailwind class merging.
by system
Create src/types/music.ts for Composition, Clip/Shape, Instrument, Grid, and Theme types.
by system
Create src/data/instruments.ts exporting the available shape/instrument definitions (color, icon/shape, default pattern).
by system
Create src/data/themes.ts with a few named theme objects (grid, background, highlight, shape accents).
by system
Implement src/App.tsx layout with regions for palette, grid, transport, library, and export/import panels.
by system
Add src/state/useComposerStore.ts using React state/hooks to hold current composition, selection, tempo, and playback state.
by system
Create src/lib/storage.ts with load/save/list/delete composition helpers.
by system
Add src/state/useAutosave.ts to persist current composition to localStorage on change (debounced).
by system
Create src/components/ShapePalette.tsx to list instruments/shapes and allow picking the active one.
by system
Create src/components/PaletteItem.tsx for a single selectable shape card/button.
by system
Create src/components/TimelineGrid.tsx rendering a step grid with rows for instruments and columns for steps.
by system
Create src/components/GridCell.tsx for a single step cell supporting active/inactive and highlight states.
by system
Add click/drag interactions in TimelineGrid.tsx to place/remove the selected shape on cells.
by system
Add selection state and an eraser mode toggle in src/state/useComposerStore.ts.
by system
Create src/components/TransportControls.tsx with Play/Pause, Stop, Tempo slider/input, and Steps/Loop length control.
by system
Create src/hooks/usePlayback.ts to advance the playhead on an interval based on tempo and steps.
by system
Wire playhead position into TimelineGrid.tsx to visually highlight the active column.
by system
Implement looping logic (wrap to step 0) in usePlayback.ts respecting current loop length.
by system
Create src/components/CompositionHeader.tsx with editable title and new composition button.
by system
Create src/components/LibraryPanel.tsx listing saved compositions with load, rename, and delete actions.
by system
Implement create-new/reset behavior in src/state/useComposerStore.ts with a default empty grid.
by system
Create src/components/ThemePicker.tsx to choose among theme presets.
by system
Add src/state/useTheme.ts to apply the selected theme via CSS variables on the document root.
by system
Create src/components/ExportJson.tsx to serialize the current composition and copy/download the JSON string.
by system
Create src/components/ImportJson.tsx to paste a JSON string, validate it, and load into the composer.
by system
Create src/lib/snapshot.ts to render the grid element to a PNG using a browser-only DOM-to-image approach.
by system
Create src/components/ExportPng.tsx with a button that captures the grid and downloads the PNG.
by system
Add src/components/ToasterHost.tsx using shadcn/ui toast to show import/export/storage errors.
by system