Contributing
Dev setup, quality gates, project structure, and release flow.
Development setup
Prerequisites
- Vite+ (
vp): the sole developer command interface for dependencies, tasks, checks, builds, and development servers. - Bun: runtime, package manager, test runner, and compiler used underneath Vite+. CI uses the version pinned in
package.json.
Use vp for every command you run directly. vp run dispatches package scripts, which may use Bun for tests, scripts, and single-binary compilation.
Clone and install
git clone https://github.com/czbiohub-sf/nd-embedding-atlas.git
cd nd-embedding-atlas
vp install
cd docs && vp install && cd ..The root install resolves the application and shared packages. The docs app keeps its own
lockfile and install under docs/.
Dependency management
# Audit root tooling and every workspace
vp outdated
vp outdated -r
# Update workspace resolutions within declared ranges
vp update -r
# Add or remove a dependency in the selected workspace
vp add --filter @ndea/app <package>
vp remove --filter @ndea/app <package>
# Update the independent docs application
cd docs
vp outdated
vp updateShared catalog constraints live in the root package.json; update each constraint there
once, then run vp install. Update root-only tooling packages reported by vp outdated
explicitly with vp update <package...>; a blanket root update would replace unrelated
catalog: references with package-local ranges. Review overrides separately because they
are deliberately pinned.
Development workflow
# Full dev stack: backend on :5055 + Vite frontend on :5173 with HMR
vp run dev path/to/data.zarrThe command starts apps/ndea/src/cli/index.ts and the app's Vite server.
Production builds open a shipped --preset layout (annotate by default).
Frontend-only when the backend already runs separately:
vp dev apps/ndeaQuality gates
vp check vite.config.ts bunli.config.ts scripts
vp run -r check # package checks in dependency order
vp run -r test # package tests in dependency order
vp run build # frontend + single-file binaryCI runs the same checks and tests, verifies generated CLI metadata, and builds the native binary matrix.
Optional code-health audit
Fallow checks for dead code, duplication, complexity, and dependency problems. Run it through the root Vite+ task when reviewing a branch:
vp run audit --changed-since mainThis audit is optional and does not run in CI.
Code style
Enforced by vp check:
- TypeScript 6 strict: no implicit any,
import typefor type-only imports - Oxlint + Oxfmt: config in
vite.config.tslint/fmtblocks - 2-space indent, double quotes, trailing commas, semicolons
@/path alias →apps/ndea/src/frontend/- Kebab-case ordinary modules, PascalCase React component modules, and
useXhook modules. Oxlint enforces these filename shapes; review enforces each file's semantic role. - Shared packages use canonical
@ndea/*barrels.
Project structure
apps/ndea/ # CLI, server, frontend, and binary builder
packages/protocol/ # Shared Zod request and response schemas
packages/sdk/ # Host contracts and shared application types
packages/zarr/ # Bun-backed AnnData, MuData, and OME-Zarr I/O
docs/ # Independent Waku app and lockfileSee AGENTS.md for the canonical command catalogue, key abstractions, and gotchas.
Releases
| Channel | How it ships |
|---|---|
stable | Manual: tag vX.Y.Z and push; release.yml builds + publishes |
pre-release | Manual: tag vX.Y.Z-alpha.N / -beta.N / -rc.N and push |
A pre-release cut opens an auto-generated PR that bumps manifest.json's pre-release pointer. Merge to activate.
The release workflow uploads scripts/install.sh as a per-tag asset, so users can pin the installer URL: curl …/releases/download/v0.X.Y/install.sh | sh. The canonical …/main/install.sh always reflects the latest installer.
After editing apps/ndea/src/cli/commands/**, regenerate the completion metadata:
vp run genUpdates .bunli/commands.gen.ts, which feeds shell-completion script generation. CI fails on drift (.github/scripts/check-bunli-gen.sh).
Verifying a build
vp run build
./dist/ndea doctorndea doctor prints binary path, symlink integrity, active version, and the installed-versions tree. Exit code 1 on hard anomalies (broken symlink, missing active binary). Add --check-network to probe manifest.json reachability with a 3-second timeout.
Editing this docs site
This site is built with Fumapress (Fumadocs + Waku). Pages are MDX under docs/content/; the app lives in docs/ with its own package.json and node_modules, isolated from the main project's dependency graph.
# From the repository root
vp run docs:build
vp run docs:serve # http://localhost:8080/nd-embedding-atlas/
# Local development with hot reload
vp run docs:devBecause pages are MDX, they can embed React. vp run docs:build writes
docs/dist/public; CI deploys that directory to GitHub Pages.