Soundorv0.13.0

Workflow

Select checks, regenerate derived files and prepare a pull request.

Run repository checks

pnpm format    # oxfmt and native clang-format checks
pnpm lint      # oxlint and native clang-tidy
pnpm build     # TypeScript checks and package bundles
pnpm test      # Vitest and the engine's native dev workflow
pnpm check     # all of the above, in order

TypeScript uses oxfmt and oxlint. Native C++ uses clang-format 18 and clang-tidy with the root configuration. pnpm format:fix applies formatting; pnpm lint:fix applies supported TypeScript lint fixes.

Root build excludes apps, examples and tools. Root tests include website unit tests but exclude examples and tools. Run example and benchmark commands explicitly when changing them. Turborepo test tasks depend on dependency builds, so build dependencies before invoking Vitest directly.

Focus on one package

pnpm turbo run build --filter=@soundor/react...
pnpm --filter @soundor/react test
pnpm --filter soundor test
pnpm --filter @soundor/react-tests exec vitest run src/modal.test.tsx

The renderer delegates its suites to a private React test workspace. This keeps testing tools out of the renderer dependency graph. Application tests should use the public helpers in the testing guide.

For frontend work, the DevTools client guide describes its local simulator, unit/integration tests, Playwright coverage, and attachment to a live native backend. The server guide describes testing the protocol without a plugin.

Change a shared behavior

Trace a behavior through the contract before changing an implementation:

  1. Update config validation, declarations, and code generation when the public contract changes.
  2. Keep native, web, and simulated runtime behavior aligned where applicable.
  3. Update React props and helpers if they expose the behavior.
  4. Add focused tests at the layer that owns the behavior.
  5. Update the relevant guide or reference in apps/website/content/docs/.

Native code must preserve the thread, lifetime, symbol-isolation, dependency, and GPU invariants described in Architecture and the engine reference. Keep framework-specific adapters out of the backend-independent engine.

Dependencies use the workspace catalog in pnpm-workspace.yaml. Before editing turbo.json, consult the docs shipped with the installed Turbo package, resolved with node -p "require.resolve('turbo/package.json')".

Regenerate checked-in files

From the repository root:

UPDATE_GOLDEN=1 pnpm --filter @soundor/juce-runtime test
pnpm --filter @soundor/core build
pnpm --filter @soundor/core gen:runtime-types
pnpm --filter @soundor/juce-runtime gen:webgl

These update the native API golden C++, shared runtime declarations, and WebGL bindings respectively. Use only the relevant generator, and include its output in the change. The WebGL code generation notes explain the IDL inputs.

Measure performance changes

Use the benchmark guide to compare a saved build and the changed build alternately in the same session:

pnpm --filter soundor-benchmark bench --save main
pnpm --filter soundor-benchmark bench --against main

Save the baseline from the base branch before measuring the changed branch. Timing drifts between sessions. Work counts such as layouts, native calls, uploads, and readbacks do not depend on timing and help explain a change.

Prepare a pull request

Describe the concrete behavior or reader experience that changes, why it changes, and the checks run. Follow the pull request template. Keep related implementation, generated files, tests and documentation together.

Add a changeset for a published-package change with pnpm changeset. The fourteen public packages under packages/ form a fixed version group; the engine and runtime packages have their own versions. The source of truth is Changesets config. Before 1.0, breaking changes use a minor changeset. Website-only documentation changes do not need a package release.

Native CI jobs follow affected packages: engine tests follow @soundor/engine, JUCE integration follows @soundor/juce-runtime, and benchmark smoke follows soundor-benchmark. Each build input must be a dependency of the package whose job consumes it. See native-changes.mjs and verify.yml.

On this page