Skip to content
⌂ Home

Workshop Developer Guide

This guide is for authors. To install someone else’s item, see Steam Workshop. The details below reflect the September 25, 2026 D:\ECHO source tree, SDK 1.17.0. Source, GitHub Releases, and the Steam starter item are released independently. Check the archive you actually downloaded with version --json.

GoalKind or starterBoundary
Colors, packaged CSS, replacement UItheme, for example --recipe css-themeCSS is scoped; replacement UI is sandboxed
Lyrics layout or backgroundlyrics-style; theme lyrics-background runtimeThe host owns lyric and playback facts
Reusable lyrics motionanimation-libraryBounded keyframe data interpreted by the host; no author code
Visualizer or EQ settingsvisualizer-preset / dsp-presetAudio Core executes DSP
Local VST3 adapter instructionsaudio-plugin-profileNo vendor binaries
Extra UI languagelocale-packMissing strings fall back
Commands, panels, source providersplugin-packageSandboxed by default; permissions are declared
Windows system shellnative-shellThe portable SDK supports authoring, but official Steam validation still rejects subscriber .exe / .dll

The theme, lyrics, visualizer and DSP, and plug-in tutorials cover individual kinds.

Authors need Node.js 20+. The SDK is not published to the public npm registry. Clone the SDK repository or install an archive actually attached to a GitHub Release. From the cloned SDK root in PowerShell:

Terminal window
node .\bin\echo-workshop-sdk.mjs version --json
node .\bin\echo-workshop-sdk.mjs init .\my-theme --recipe css-theme
cd .\my-theme
npm run next
npm run check
npm run dev

Edit content JSON for themes and presets, or src/plugin.js for plug-ins. check syncs the generated community.echo package and manifest hashes, then validates structure, quality, and fixtures. Do not hand-edit generated hashes. dev is a local mock console; npm run watch checks after saves. A passing local gate still needs validation in ECHO’s Steam Authoring Studio.

In the inner plug-in manifest, add a contributes.panels entry for an HTML file included in the package:

{
"contributes": {
"panels": [{
"id": "desk",
"title": "Library desk",
"description": "My library tools",
"path": "desk.html",
"placement": "page",
"group": "library",
"icon": "library"
}]
}
}

This is a fragment to merge into the generated inner manifest, not content/echo.workshop.json. On ECHO 26.9.25+, page creates a native sidebar entry and shows the same isolated iframe in the main content area. Older hosts display it as a main panel. One package can declare up to 8 pages. The sidebar shows at most 24 pages across enabled plug-ins; overflow pages remain accessible from the plug-in dock. group can be library, sources, playback, or plugins.

Use echo.ui.openPanel('desk') or echo.navigation.open('plugin:<plugin-id>:desk') for your own page; opening your own page does not require the navigation permission. echo.ui.closePanel() returns to the previous built-in route. getContext() and onContextChanged() expose host locale, viewport, appearance, and reduced-motion state. A visible panel can update its host-owned title, badge, and attention state with setPanelPresentation(). On a page, immersive hides only the host caption.

The same version adds mainMenus with optional shortcuts, trackContextMenus with selection: "multiple", and columns. Each references a declared command. Selection commands receive at most 100 tracks; a column command receives at most 40 visible tracks per batch, with 24-character values and at most two visible row chips. Consult the SDK’s plugin-package.schema.json and echo-workshop-plugin.d.ts when extending the plug-in tutorial.

The full set requires ECHO 26.9.16+:

  • lyrics-view runtimes receive revisioned current lyrics, host clock anchors, bounded interactions, and read-only audio events. Use the SDK’s lyrics-authoring.md and examples/lyrics-view-runtime/.
  • A theme’s runtime.presentation: "lyrics-background" draws behind host lyrics and controls, with only playback:read and audio:spectrum capabilities. Theme, lyric runtime, and background selections are independent.
  • animation-library exports bounded host-run motion data. Its local dev view previews triggers and intensity. It cannot run scripts or control playback.
  • Stable styling hooks use data-echo-part, data-echo-state, and semantic --echo-* variables instead of internal ECHO class names. Authoring Studio’s host preview uses simulated playback, so finish with a real playback check.

plugin-package runs in a sandbox by default. If a feature truly needs full system access, --recipe full-trust-plugin or add . --permission system:full pairs a separate .mjs trustedEntry with explicit subscriber approval. It can use normal Node.js system APIs. This differs from data-only animation libraries and native-shell; a mock pass does not prove full-system code ran in ECHO.

Before release, run npm run check with zero blockers and passing fixtures. Replace placeholder art, verify license, permissions, networkHosts, and compatibility.minEchoVersion. Launch ECHO from Steam, import the project under Workshop → Create, pass production validation, and publish manually. CLI and CI do not upload. Test subscribe → download → Use → disable with an ordinary account, and retain the PublishedFileID when updating. See Publish and update and Local dev workflow.

Existing projects can run upgrade . to refresh .echo-sdk, followed by npm run check. SDK package version 1.17.0 does not change the current source contract’s manifest schema 1 or plug-in API 2; verify your installed copy with version --json.