A JS/TS package to interact with multiplayer projects of the Audiotool DAW in real time. Read more at Overview.
Known supported platforms:
The Nexus Platform and this package are under heavy development, and as a result might still break when we make changes to the backend.
Join our Discord Server to receive updates, submit bug reports, ask questions, show what you've done!
npm install @audiotool/nexus
OAuth redirects require 127.0.0.1, not localhost. Configure your dev server in vite.config.ts:
import { defineConfig } from "vite"
export default defineConfig({
server: {
host: "127.0.0.1",
port: 5173,
},
})
Register your app on developer.audiotool.com/applications with redirect URI http://127.0.0.1:5173/ and scope project:write.
Then in your main.ts:
import { audiotool } from "@audiotool/nexus"
// Authenticate — redirectUrl must match your vite.config.ts host and the URI registered for your app
const at = await audiotool({
clientId: "<client-id of your app>", // hardcode this — it's not a secret
redirectUrl: "http://127.0.0.1:5173/",
scope: "project:write",
})
if (at.status === "unauthenticated") {
const button = document.createElement("button")
button.textContent = "Login"
button.onclick = () => at.login()
document.body.appendChild(button)
throw await new Promise(() => {}) // stop here until logged in
}
// Open a project — copy the URL from beta.audiotool.com
const nexus = await at.open("https://beta.audiotool.com/studio?project=your-project-id")
// Listen for changes
nexus.events.onCreate("tonematrix", (tm) => {
console.log("New tonematrix created!", tm.fields.patternIndex.value)
})
// Start syncing with the backend
await nexus.start()
// Create a tonematrix
await nexus.modify((t) =>
t.create("tonematrix", {
displayName: "My first device!",
positionX: 100,
positionY: 200,
}),
)
// Stop syncing when done
await nexus.stop()
For more detail, see Getting Started or Authentication.
Authenticate users in the browser, export their tokens, and use them on the server:
Browser side:
const at = await audiotool({...})
if (at.status === "authenticated") {
const tokens = at.exportTokens()
await fetch("/api/store-session", {
method: "POST",
body: JSON.stringify(tokens),
})
}
Server side (Node.js):
import { createAudiotoolClient, createServerAuth } from "@audiotool/nexus"
import { createNodeTransport, createDiskWasmLoader } from "@audiotool/nexus/node"
const client = await createAudiotoolClient({
auth: createServerAuth({
accessToken, refreshToken, expiresAt,
clientId: "your-client-id",
}),
transport: createNodeTransport(),
wasm: createDiskWasmLoader(),
})
const projects = await client.projects.listProjects({})
For personal scripts, see PAT-based authentication.
// Create a delay effect
const delay = t.create("stompboxDelay", {
feedbackFactor: 0.3,
mix: 0.3,
stepLengthIndex: 2,
})
// Create audio connection
t.create("desktopAudioCable", {
fromSocket: sourceDevice.fields.audioOutput.location,
toSocket: delay.fields.audioInput.location,
})
// Create a note track
const noteTrack = t.create("noteTrack", {
orderAmongTracks: 0,
player: heisenberg.location,
})
// Add a note region
const noteRegion = t.create("noteRegion", {
track: noteTrack.location,
region: {
positionTicks: Ticks.SemiBreve, // one whole note in a bar (4/4 time signature)
durationTicks: Ticks.SemiBreve * 4,
},
})
See utils.Ticks for constants representing musical time divisions.
// Find all delay effects
const delays = nexus.queryEntities.ofTypes("stompboxDelay").get()
// Find connected devices
const connected = nexus.queryEntities.pointedToBy
.types("desktopAudioCable")
.get()
You can create an offline version of the document by calling index.createOfflineDocument. This will create a document instance that isn't synced to the backend and can immediately be modified.
This is useful for writing integration tests for your app. Example:
import { createOfflineDocument } from "@audiotool/nexus"
const nexus = await createOfflineDocument()
nexus.events.onCreate("tonematrix", () => {
console.debug("tonematrix created")
})
await nexus.modify((t) => {
t.create("tonematrix", {})
})
In offline mode, you can turn off validation of the document by passing in a flag:
const nexus = await createOfflineDocument({ validated: false })
This will result in fewer transaction errors being created, which can help during integration tests.
Ready? Start with our Getting Started guide!