- Create lightsync/frontend/timeline/timeline.js with TimelineCanvas class
- Per-device horizontal tracks with track headers and time axis
- HiDPI canvas rendering with devicePixelRatio handling
- Waveform peaks background layer, beat marks overlay, cue block rendering
- Playback cursor synced to audio.currentTime via requestAnimationFrame
- Auto-scroll when cursor approaches right edge
- Mouse wheel scrolling on timeline canvas
- loadTracks(), loadWaveform(), loadBeats() data loading methods
- Empty state messages when no devices or audio loaded
- Add timeline CSS to style.css (toolbar, canvas, inspector strip, snap button)
- Wire timeline into app.js: import, initTimeline(), zoom/beat-offset/snap controls
- Remove old animation-grid click listener (element no longer exists in main-area)
- Populate animation palette dynamically in sidebar with 7 animation types
- Options use /app/shows/filename as value
- Upload response returns /app/shows/filename as path
- Pass path directly to refreshFileList so pre-selection matches
- Replace timeline placeholder with waveform canvas + playback cursor
- Replace transport placeholder with full transport bar controls
- Add play/pause/stop buttons, seek slider, time display, audio path input
- Add drawWaveform(), loadWaveform(), updatePosition(), formatTime() to app.js
- Dispatch msg.type=tick to updatePosition in handleMessage
- Wire transport buttons via WebSocket commands
- Add transport/waveform styles to style.css using existing CSS variables
- Deploy via ~/bin/deploy.sh
- Add <form id='add-device-form'> to DEVICES panel with 5 inputs (name, strip_type, led_count, ip, port) and submit button
- Add apiPost() and apiDelete() helper functions to app.js
- Update loadDevices() to render device rows with remove button (.device-remove)
- Add removeDevice(id) function with DELETE /api/devices/{id} + window export for onclick
- Add form submit handler: POST /api/devices, form reset, refresh device list
- Add panel IDs: devices-panel, animations-panel, timeline-panel, transport-panel to index.html
- DeviceRegistry with load/save/add/remove/instantiate and _DEVICE_CLASSES dict
- ShowStore with save/load/list_ids using aiofiles for async I/O
- FastAPI app with lifespan hook (startup: load registry/store, shutdown: save registry)
- API routes: GET/POST /api/devices/, DELETE /api/devices/{id}, GET/POST /api/shows/, GET /api/shows/{id}
- WebSocket stub at /ws with ConnectionManager and ack echo
- Frontend shell: DAW layout with header, sidebar (DEVICES + ANIMATIONS), TIMELINE, TRANSPORT
- Terminal aesthetic: dark theme, cyan accents, monospace fonts, no drop shadows
- .gitignore for runtime data (devices.json, shows/, __pycache__, .venv)