HTML, CSS, and Vue primitives that mirror Ableton’s Live styling — dark and light, device knobs and faders, waveforms, dialogs that feel native.
No @ableton-extensions/sdk here. This is the paint and paneling; your extension brings the engine; this is a personal initiative, not Ableton one;
License: Apache-2.0. Ships TypeScript/Vue source (consumers bundle with esbuild or Vite).
Start with the Quick Start guide — build a real Live extension with plain HTML (no Vue). Includes a full sample project: examples/starter-extension/.
| Resource | Link |
|---|---|
| Quick Start (repo) | docs/quick-start.md |
| Quick Start (wiki) | GitHub Wiki |
| Starter extension | examples/starter-extension/ |
| Static HTML demos | examples/ |
| Vue layout gallery | npm run dev:examples → http://127.0.0.1:5199 |
Building an Ableton extension should not mean reinventing pill buttons, modal chrome, rotary knobs, and “why does my webview look like a 2009 blog.”
- Themes track Live — flip
data-qa-themebetween dark and light tokens. - Layouts match real extensions — toolbar → panel → status bar, plus synth/device/mixer UIs.
- CSS works without Vue — ship a tiny HTML panel for buttons, sliders, and selects.
Live demo — interactive Vue layout gallery (dark/light, knobs, waveforms, synth playground). Deployed from main via GitHub Pages.
Run the gallery locally:
npm run dev:examplesThen open http://127.0.0.1:5199. Toggle layouts in the sidebar, mash the theme button, resize the window — these demos target the narrow webview column Live gives you.
The full sandwich: project toolbar, transport strip (play, tempo, master meter), tabbed session panel — particle browser with waveform thumbs and a selected-track editor, mini mixer with animated meters, macro page with accent knobs and XY pad — and a status bar that commits pending changes. Press play for fake playback: beat LED, moving playhead, pulsing meters.
| Dark | Light |
|---|---|
![]() |
![]() |
Device-style parameter rows — drive, tone, mix, bypass. Copy this for audio/MIDI utilities.
| Dark | Light |
|---|---|
![]() |
![]() |
Modal form with QaDialog + QaTextInput. Escape to cancel, Enter to submit — same ergonomics as SDK examples.
| Dark | Light |
|---|---|
![]() |
![]() |
Synth-style device chrome with knobs, segmented tabs, filter select, and value field.
| Dark | Light |
|---|---|
![]() |
![]() |
Mixer strip: pan, sends, fader, stereo meter, mute/solo/arm toggles.
| Dark | Light |
|---|---|
![]() |
![]() |
Interactive waveform with playhead, selection, transport, warp mode, and loop toggle.
| Dark | Light |
|---|---|
![]() |
![]() |
Device panels with XY pad, fold, and power states.
| Dark | Light |
|---|---|
![]() |
![]() |
Web Audio demo — power on to hear a live synth with meter and waveform (idle state in screenshots).
| Dark | Light |
|---|---|
![]() |
![]() |
- Project toolbar — link/sync actions + autocomplete (dark · light)
- Status chrome — connection glyph, info action, embedded theme toggle (dark · light)
Source for every layout: examples/vue/src/layouts/. Static HTML demos (buttons, sliders, select — no build step): examples/.
Regenerate screenshots after UI changes:
npm run screenshotsnpm install @quantumaudio/ableton-extension-sdkPeer dependency: vue ^3.5 (Vue components only). Plain CSS entry points work without Vue.
Requires Node ≥ 24 for typechecking.
| Import | Use |
|---|---|
@quantumaudio/ableton-extension-sdk |
Theme provider, dialog helpers, param utils, peak extraction |
@quantumaudio/ableton-extension-sdk/vue |
Vue 3 components |
@quantumaudio/ableton-extension-sdk/theme.css |
CSS variables / theme |
@quantumaudio/ableton-extension-sdk/styles.css |
Bundled component styles |
@quantumaudio/ableton-extension-sdk/button.css |
À la carte CSS |
@quantumaudio/ableton-extension-sdk/slider.css |
Horizontal parameter slider |
@quantumaudio/ableton-extension-sdk/knob.css |
Rotary knob (use with QaKnob) |
@quantumaudio/ableton-extension-sdk/fader.css |
Vertical fader |
@quantumaudio/ableton-extension-sdk/meter.css |
Level meter |
@quantumaudio/ableton-extension-sdk/device.css |
Device panel chrome |
@quantumaudio/ableton-extension-sdk/waveform.css |
Waveform canvas |
@quantumaudio/ableton-extension-sdk/input.css |
Text inputs, dialogs |
@quantumaudio/ableton-extension-sdk/select.css |
Native select styling (via styles.css) |
| Component | Purpose |
|---|---|
QaToolbar |
Horizontal tool row |
QaPanel |
Labeled content panel |
QaStatusBar |
Bottom status line |
QaDevicePanel |
Live device title bar with power, fold, and body |
QaDialog |
Modal overlay |
QaWindowControls |
Electron minimize/maximize/close |
| Component | Purpose |
|---|---|
QaButton / QaIconButton |
Pill and icon buttons |
QaButtonGroup |
Joined button row |
QaToggle |
Square on/off device button |
QaPowerButton |
Round device power switch |
QaSegmented |
Tab-style segmented control |
QaBadge |
Numeric/status badge |
QaLed |
Tiny round indicator |
Icons use vue-material-design-icons via the QaMdiIcon wrapper and named Icon* exports (IconClose, IconPlay, IconLoader, …). Import icons per file for tree-shaking:
<script setup lang="ts">
import { QaIconButton, QaMdiIcon } from "@quantumaudio/ableton-extension-sdk/vue";
import RefreshIcon from "vue-material-design-icons/Refresh.vue";
</script>
<template>
<QaIconButton aria-label="Refresh">
<QaMdiIcon :icon="RefreshIcon" :size="16" />
</QaIconButton>
</template>QaMdiIcon— normalizes MDI size (default 16px),currentColor, and theqa-icon/qa-icon-loaderclasses.Icon*— stable SDK exports for common chrome (window controls, transport, zoom, theme). Prefer these when available.- Custom SVG — only when MDI has no suitable glyph (e.g. brand-specific artwork). Keep the same
qa-iconclass and 16–20px sizing.
Optional Vite alias: @mdi → vue-material-design-icons (see QuantumAgent vite.config.ts).
| Component | Purpose |
|---|---|
QaSlider |
Horizontal device parameter slider |
QaKnob |
Rotary macro knob (drag + keyboard) |
QaFader |
Vertical mixer fader |
QaValueField |
Draggable/editable number box (integer for whole numbers) |
QaXYPad |
2D XY control pad |
QaSelect |
Native chooser dropdown |
| Component | Purpose |
|---|---|
QaMeter |
Mono/stereo level meter (consumer-driven levels) |
QaWaveform |
Canvas waveform with playhead, selection, seek, optional zoom (zoomable: Ctrl+scroll to zoom, Shift+scroll to pan, scrollbar when zoomed) |
QaWaveformThumb |
Compact list thumbnail |
| Component | Purpose |
|---|---|
QaTextInput |
Labeled text field |
QaAutocomplete |
Filterable dropdown with optional create |
QaThemeToggle |
Dark/light theme switch |
Knob with log frequency taper:
<script setup lang="ts">
import { ref } from "vue";
import { QaKnob } from "@quantumaudio/ableton-extension-sdk/vue";
import { formatHz } from "@quantumaudio/ableton-extension-sdk";
const cutoff = ref(1200);
</script>
<template>
<QaKnob
v-model="cutoff"
label="Cutoff"
:min="20"
:max="20000"
taper="log"
:format="formatHz"
/>
</template>Integer value field (track number, voice count):
<QaValueField
v-model="voices"
label="Voices"
:min="1"
:max="16"
:default-value="8"
integer
/>Waveform with fake peaks (demo/screenshot):
<script setup lang="ts">
import { fakePeaks } from "@quantumaudio/ableton-extension-sdk";
import { QaWaveform } from "@quantumaudio/ableton-extension-sdk/vue";
const peaks = fakePeaks("my-clip", 400);
</script>
<template>
<QaWaveform :peaks="peaks" :height="64" interactive />
</template>Device panel:
<script setup lang="ts">
import { ref } from "vue";
import { QaDevicePanel, QaKnob } from "@quantumaudio/ableton-extension-sdk/vue";
const enabled = ref(true);
const mix = ref(50);
</script>
<template>
<QaDevicePanel v-model:enabled="enabled" title="QA Saturator">
<QaKnob v-model="mix" label="Mix" :min="0" :max="100" unit="%" />
</QaDevicePanel>
</template>Knobs, faders, meters, XY pads, and waveforms are Vue components. Only buttons, sliders, labels, and
.qa-selecthave standalone CSS demos.
Framework-free helpers exported from the main entry:
| Export | Purpose |
|---|---|
decodeWavPeaks(bytes, buckets) |
Bucketed peaks from WAV bytes |
peaksFromAudioBuffer(buffer, buckets) |
Peaks from Web Audio AudioBuffer |
fakePeaks(seed, buckets) |
Deterministic demo peaks |
normalize / denormalize |
Linear/log parameter mapping |
formatDb / formatHz / formatPercent |
Display formatters |
accentClasses |
Map accent prop → qa-accent / qa-accent-{color} CSS classes |
import { accentClasses, decodeWavPeaks, fakePeaks } from "@quantumaudio/ableton-extension-sdk";
accentClasses("red"); // ["qa-accent-red"]
const fromWav = decodeWavPeaks(wavBytes, 200);
const demo = fakePeaks("kick-01", 120);For a full Ableton extension (manifest, build, Live API), use docs/quick-start.md and examples/starter-extension/.
1. Theme + styles (extension webview or Vite app):
import { createThemeProvider } from "@quantumaudio/ableton-extension-sdk";
import "@quantumaudio/ableton-extension-sdk/theme.css";
import "@quantumaudio/ableton-extension-sdk/styles.css";
createThemeProvider(document.documentElement, { defaultTheme: "dark" });Per-component accent colors tint fill controls (slider track, knob arc, fader, XY pad handle) or give buttons/badges a persistent colored surface. Toggle and segmented controls tint the selected/on state only.
| Class / prop | Effect |
|---|---|
qa-accent / accent |
Default Live orange |
qa-accent-red / accent="red" |
Red |
qa-accent-blue / accent="blue" |
Blue |
qa-accent-green / accent="green" |
Green |
qa-accent-purple / accent="purple" |
Purple |
Apply classes directly on each control — accent does not cascade from a parent container.
<QaButton accent>Save</QaButton>
<QaButton accent="red">Delete</QaButton>
<QaSlider v-model="mix" label="Mix" accent="blue" /><button class="qa-button qa-accent-red">Delete</button>
<input class="qa-slider qa-accent-green" type="range" />highlight (toolbar toggle pattern) and accent (chromatic CTA / custom fill hue) are separate — use highlight + active for neutral-until-active toolbar buttons.
variant="ghost" removes the pill border for list rows, sidebar items, and section toggles. QaIconButton defaults to ghost; pass variant="default" when you need the bordered chrome.
2. Vue panel — steal a layout from the gallery or compose your own:
<script setup lang="ts">
import {
QaButton,
QaPanel,
QaStatusBar,
QaThemeToggle,
QaToolbar,
} from "@quantumaudio/ableton-extension-sdk/vue";
</script>
<template>
<main class="qa-app">
<QaToolbar><!-- tools --></QaToolbar>
<QaPanel label="My extension" grow><!-- body --></QaPanel>
<QaStatusBar message="Ready." />
<QaThemeToggle />
</main>
</template>Extensions typically bundle with esbuild (loader: { ".html": "text" } per the Extensions SDK). The Vue gallery uses Vite with aliases — see examples/vue/vite.config.ts.
git clone https://github.com/QaAudio/qa-ableton-extension-sdk.git
cd qa-ableton-extension-sdk
npm ci
npm run typecheck
npm run dev:examples # Vue layout gallery| Script | What it does |
|---|---|
npm run typecheck |
vue-tsc on library source |
npm run dev:examples |
Vite dev server for Vue layouts |
npm run build:examples |
Production build of the gallery |
npm run screenshots |
Rebuild gallery + capture docs/screenshots/ |
| Project | Repo |
|---|---|
| MCP + Live agent stack | qa-ableton-mcp |
| Knowledge / SDK docs search | qa-knowledge + qa-library-mcp (search_knowledge, get_knowledge_chunk) |
PRs welcome. Keep CSS token-driven; avoid hard-coded colors outside src/theme/. See AGENTS.md.
If you add a component, give it a row in the gallery or a static HTML demo, register it in scripts/capture-screenshots.mjs, and re-run npm run screenshots.















