A practical, verified reference for building audio and instrument plugins for the Amorph host with Cmajor DSP and a single-file JavaScript Web Component UI.
This kit is a public, project-independent knowledge base. It collects hard-won
lessons from real plugin development and checks every claim against the official
Cmajor sources. Older, contradictory notes have been reconciled — see
STATUS.md for what was verified, what was corrected, and what is
still marked unverified.
Scope note. This is a documentation-first kit (the scaffold). Runnable templates and worked examples are being added incrementally — see the roadmap at the bottom.
An Amorph plugin has three decoupled layers. The DSP is one Cmajor
processor/graph. The UI is a single self-contained .js Web Component.
A small manifest (.cmajorpatch) links them and sets the window size. DSP and
UI never share memory and never call each other — they communicate only through
the parameter bridge (patchConnection): the UI writes with
sendEventOrValue, reads with addParameterListener + requestParameterValue,
and receives meters/scopes with addEndpointListener. The contract between the two
sides is the parameter list: parameters are named param1..paramN and the
number is the contract — renaming or renumbering after wiring breaks saved
presets.
New here? Start with GETTING_STARTED.md — zero to a
compiled plugin in ~15 minutes.
GETTING_STARTED.md Tutorial: scaffold, check, fill in DSP, compile, restyle.
STATUS.md Verification log: sources, what was confirmed/corrected, open questions.
docs/
01_ARCHITECTURE.md The three layers, the manifest, the bridge.
02_DSP_CMAJOR.md Writing the DSP: skeleton, parameters, sample rate, building blocks.
03_UI_WEBCOMPONENT.md Writing the UI: the single-file contract, the bridge, lifecycle, cleanup.
04_PARAMETERS.md Parameter design: ranges, naming, presets/state, pan law, bypass.
05_AMORPH_NOTES.md Amorph-specific WebView behaviour you must know.
06_OVERSAMPLING.md Per-node oversampling in Cmajor (verified) and when to use it.
07_SCALING.md The CSS-`zoom` scaling method + host-wrapper fixes (battle-tested).
08_UI_RENDERING.md Procedural/photoreal UI techniques — with Amorph compatibility caveats.
09_PITFALLS_CHECKLIST.md Quick pitfalls lookup + pre-flight, release and test checklists.
10_PLUGIN_TYPES.md The three Amorph plugin types and their I/O endpoint structure.
11_DSP_COOKBOOK.md Verified DSP building blocks (filters, dynamics, clip, LFO, …).
12_TESTING.md Unit-testing DSP with `cmaj test` + debugging patterns.
cookbook/Cookbook.cmajor The canonical, unit-tested cookbook library (copy what you need).
tests/Cookbook.cmajtest Unit tests for the cookbook (all passing, run in CI).
ai/
amorph_official/ The verbatim system prompts Amorph's own IDE emits (authoritative).
DSP_SYSTEM_PROMPT.md Condensed DSP system prompt (defers to amorph_official).
UI_SYSTEM_PROMPT.md Condensed UI system prompt (defers to amorph_official).
examples/ One worked plugin per type (FX / Instrument / MIDI), each passing preflight.
reference/
airwindows/README.md How to use the Airwindows plugins as a DSP reference (clone, don't vendor).
tools/ Reusable Python tools: scaffolder, DSP/UI linters, endpoint parser, preflight.
templates/ (roadmap) Copy-to-start plugin template: DSP + UI + manifest.
Recurring jobs are automated in tools/ — pure-stdlib Python, single-file,
easy to adapt:
python3 tools/new_plugin.py tools/examples/params.example.json --out ./MyPlugin # scaffold DSP+UI+manifest
python3 tools/preflight.py ./MyPlugin # endpoint summary + DSP lint + UI lint + DSP↔UI syncSee tools/README.md for all six tools and the param-spec format.
DSP (Cmajor)
- One top-level
processor/graph. Parameters areinput event/input valueendpoints namedparam1..paramN, each with a[[ name: ... ]]annotation and the 3-step pattern (endpoint → state variable →eventhandler). - Never use the reserved identifiers
input,output,streamas names. - There is no
double— usefloat64.sin/cos/pow/exp/sqrt/tanhreturnfloat64; cast back withfloat(...). - Every
main()loop iteration must writeout <-and then calladvance(), unconditionally. - Read the sample rate from
processor.frequency/processor.period— never hardcode. - Initialise all float state; clamp filter cutoffs below Nyquist.
- Oversampling works via graph-node oversampling:
node core = MyCore * 4;(sinc resampling is automatic). Seedocs/06_OVERSAMPLING.md.
UI (JavaScript Web Component)
- One self-contained
.jsfile. Noimport/require, no ES-module dependencies, no CDN, no external libraries. Inline all CSS, HTML and logic. export default function createPatchView(patchConnection)→ create the element, hand it the connection, return it. Register withcustomElements.define(guarded).- Two-way bind every control and add echo-loop protection so the DSP's echo doesn't fight a live drag.
- Scale with CSS
zoomon a fixed-size chassis — nevertransform: scale(). Seedocs/07_SCALING.md. - Avoid
backdrop-filterandvw/vhin Amorph. Clean up every listener / observer / RAF indisconnectedCallback.
Amorph runs without general web access — the reliable way to pull in external
material is git clone. To study the bridge API or the language in depth, clone
the official repository and read javascript/cmaj_api/ and docs/:
git clone https://github.com/cmajor-lang/cmajor
Do not import those files into an Amorph UI (the single-file rule) — they are for reference only.
Every factual claim in this kit is tagged where it matters:
- [verified] — confirmed against the official Cmajor source or docs (file/line cited in
STATUS.md). - [field-tested] — observed repeatedly in real Amorph plugins, not in the official spec.
- [unverified] — plausible but not yet confirmed; treat with care.
If you find a claim that no longer holds, open an issue or PR and update STATUS.md.
- Scaffold: verified core documentation, AI prompts, Airwindows reference.
- Official Amorph IDE prompts captured + reconciled (
ai/amorph_official/). - Python tools: scaffolder, DSP/UI linters, endpoint parser, sync check, preflight.
-
examples/— one worked plugin per type (oversampled saturator, poly synth, MIDI harmonizer), each passing preflight. - A meter output-event pattern with a Canvas visualiser (in the saturator example).
- More tools:
manifest_check.py,params_from_dsp.py, a pre-commit hook. - Audit against the real compiler (cmaj 1.0.3159) — see
STATUS.md. - Getting-started tutorial, DSP cookbook (unit-tested), testing guide.
- CI workflow: static checks + real compile +
cmaj test(.github/workflows/ci.yml). -
templates/Plugin/— minimal copy-to-start (or just usenew_plugin.py). -
runScript()golden-data regression test for a full example effect.
MIT — see LICENSE. Third-party references (e.g. Airwindows) keep their
own licenses; this kit only points to them, it does not vendor their source.