Skip to content

Code

Sylve is built with Go (backend) and SvelteKit in SPA mode (frontend), we’re API first so if you’re planning to work on the go side you don’t have to touch the web/ directory at all. For the best development experience, we recommend a FreeBSD -STABLE machine with pkgbase.

Install required tooling with pkg:

Terminal window
pkg update
pkg install -y git-lite go node npm

Verify your installation:

Terminal window
go version
node -v
npm -v

If your local machine is not FreeBSD, use a remote FreeBSD host for development.

VS Code Remote - SSH works great for this workflow:

Terminal window
git clone https://github.com/AlchemillaHQ/Sylve
cd Sylve

Install air:

Terminal window
go install github.com/air-verse/air@latest

In config.json, set (along with other properties):

{
"proxyToVite": true
}

With proxyToVite enabled, the Go backend proxies frontend requests to Vite, so you do not need to work with two separate ports directly.

Use tmux, zellij, or screen and split into two panes:

  1. In the repository root:
Terminal window
air .
  1. In the web/ directory:
Terminal window
npm run dev

Prefer simple, direct code over clever abstractions. A solution should be easy to read, trace, and change without requiring the reader to decode tricks or reconstruct hidden control flow.

Code should explain itself through precise names, small focused functions, straightforward data flow, and clear boundaries. We strongly dislike comments that merely restate what the code is doing; if a block needs that kind of explanation, simplify or rename it instead.

Use a comment only when the code cannot communicate the reason on its own; for example, to record an external constraint, a specific edge case, or the rationale behind a non-obvious compatibility decision. Comments should explain why, not narrate what.

If you use an LLM or other AI-assisted tooling, read and follow Sylve’s LLM / AI Contribution Policy before submitting your work. You remain responsible for understanding and testing everything you contribute, and contribution discussions must follow the policy as well.

Use a short, lowercase scope followed by a concise description:

area: summary
area: subsystem: summary

Choose the part of the repository affected by the change as the first scope, then add a narrower scope when it makes the commit easier to scan. Write the summary in the imperative mood and omit a trailing period.

system: route jailed restarts through graceful shutdown
web: vm: make request outcomes explicit
docs: app-docs: improve the getting-started page
ci/cd: add pull-request validation

Keep each commit focused on one coherent change. If more context is useful, leave a blank line after the subject and explain the motivation and important trade-offs in the commit body.

Run the checks relevant to your change before opening a pull request. The commands below mirror the repository’s automated pull-request workflows.

From the repository root, run the same code-quality gate used by CI:

Terminal window
make quality

This command does not intentionally modify source files. It:

  1. Checks every tracked or unignored Go file with gofmt and fails with a list of files that need formatting.
  2. Installs the exact frontend dependencies from web/package-lock.json using npm ci.
  3. Runs the frontend lint task, which checks Prettier formatting and ESLint rules.
  4. Runs svelte-check, treating warnings as failures.

If the formatting or lint steps fail, apply the available automatic fixes with:

Terminal window
make quality-fix

make quality-fix rewrites tracked and unignored Go files with gofmt, then runs Prettier and ESLint’s automatic fixes in web/. Review the resulting changes before committing. It does not install frontend dependencies or run svelte-check, so follow it with make quality to verify the complete quality gate:

Terminal window
make quality-fix
make quality

The fix target cannot resolve every lint or type-checking problem. If make quality still fails, address the reported issues manually and run it again.

From the repository root, format Go code and run the short unit-test suite:

Terminal window
go fmt ./...
make test

make test runs go test -short across the repository, including the ZFS test utilities. Run it on FreeBSD so packages that depend on FreeBSD interfaces are compiled and exercised in the supported environment.

Backend changes that interact with Jails, ZFS, networking, libvirt, migration, clustering, or replication should also run the integration suite:

Terminal window
doas make test-integration

Integration tests must run as root on FreeBSD with ZFS available. The target checks for leaked ZFS test resources before and after the suite and runs integration packages without the Go test cache.

The repository also provides more specialized suites:

Command Use it when
doas make test-acceptance A change affects end-to-end console workflows.
doas make test-acceptance-full You need the longer full acceptance run.
doas make test-smart-integration SMART_DEVICE=/dev/… A disk or SMART change must be tested against explicitly selected hardware. This target can interact with the named device, so review its options first.

These specialized targets are not part of the standard pull-request workflow, but maintainers may request them for relevant changes.

From the repository root, run:

Terminal window
npm run format --prefix web
npm run lint --prefix web
make frontend
npm run build:demo --prefix web

npm run format writes Prettier changes. npm run lint verifies formatting and ESLint rules. make frontend performs a clean dependency install, runs svelte-check with warnings treated as failures, builds the production frontend, and copies the generated assets into the Go embed directory. The final command verifies the separate demo build used by the project website.

If a frontend change adds, changes, or removes user-facing text, follow the translation contribution guide to extract, clean, and validate the locale catalogs before submitting it.

On a FreeBSD development host, build the complete application with:

Terminal window
make build

This builds the frontend assets first and then produces the FreeBSD sylve binary in bin/.

For pull requests that change application code, GitHub runs both the Test and Build workflows before merge:

Workflow Automated checks
Test Runs the short Go unit suite on FreeBSD 15. If it succeeds, prepares ZFS, PF, VMM, libvirt, and local SSH before running the integration suite. Test summaries and raw reports are uploaded as workflow artifacts.
Build Uses Node.js 24 to check and build the production frontend and demo frontend, then cross-builds FreeBSD 15 binaries for amd64 and arm64 and verifies each binary’s OS and architecture.

Both workflows cancel superseded runs when a pull request is updated. Their test and build checks are expected to pass before a pull request is merged. Because the workflows ignore changes confined to docs/**, documentation-only pull requests do not run the application test/build matrix.