# Build Tools Used in Automattic/harper: Complete Polyglot Build System Guide

> Discover the polyglot build tools in Automattic/harper. Learn how Just orchestrates Cargo, wasm-pack, pnpm, Vite, Tauri, and Biome for a streamlined development workflow.

- Repository: [Automattic/harper](https://github.com/Automattic/harper)
- Tags: how-to-guide
- Published: 2026-07-26

---

**The Automattic/harper repository uses Just as its primary task runner, coordinating Cargo for Rust compilation, wasm-pack for WASM generation, pnpm for Node.js package management, Vite for frontend bundling, Tauri for desktop application packaging, and Biome for code formatting.**

The Harper codebase is a polyglot monorepo combining Rust, WebAssembly, Node.js, and native desktop tooling. Understanding the build tools used in Automattic/harper is essential for contributors compiling the core engine, building JavaScript packages, or packaging the desktop application. The entire build process is orchestrated through a root `justfile` that provides a single entry point for all development tasks.

## Just: The Central Build Orchestrator

The repository uses **Just** (a command runner) as its universal entry point for build operations. The `justfile` at the repository root defines high-level recipes that invoke underlying language-specific tools, ensuring consistent execution across development environments.

Key recipes defined in the `justfile` include:

- `just clean` – removes Cargo `target` directories and `node_modules` artifacts
- `just build-web` – executes the full web build pipeline
- `just dev-desktop` – launches the Tauri development server
- `just precommit` – runs formatting and linting validation

These recipes abstract the complexity of coordinating Rust and JavaScript build steps.

## Rust and WebAssembly Tooling

### Cargo for Core Compilation

**Cargo** compiles the three main Rust crates in the workspace:

- `harper-core` – the spell-checking engine
- `harper-ls` – the language server protocol implementation
- `harper-cli` – the command-line interface

The `justfile` invokes Cargo commands directly for specific tasks. For instance, `cargo clean` appears in the justfile around lines 11-12, while `cargo fmt` and `cargo clippy` handle formatting and linting around lines 42-43. The desktop binary compilation uses `cargo build`, referenced near lines 81-82.

### wasm-pack for WebAssembly Generation

**wasm-pack** packages the Rust core as WebAssembly modules for JavaScript consumers. The `build-wasm` recipe in the `justfile` (lines 63-76) executes two build targets:

```bash
just build-wasm

```

This command runs:

```bash
wasm-pack build --target web --out-name harper_wasm
wasm-pack build --target web --out-name harper_wasm_slim --no-default-features

```

The output feeds into the `harper-wasm` package, enabling browser and Node.js integration.

## JavaScript and Frontend Pipeline

### pnpm for Package Management

**pnpm** manages dependencies across the `packages/*` directory. The `justfile` invokes `pnpm install` before most build steps to ensure Node modules are present. Specific build recipes like `build-components` and `build-harper-editor` (lines 45-53 and 55-61) rely on `pnpm build` to compile individual packages.

Distribution commands include:

- `pnpm zip-for-chrome` – packages the Chrome extension into a distributable zip
- `pnpm plugin-zip` – creates the WordPress plugin archive
- `pnpm zip-for-firefox` – bundles the Firefox extension

### Vite for Bundling and Development

**Vite** serves as the frontend bundler for the website, documentation, and browser extensions. The repository uses Vite via pnpm scripts, with configuration residing in [`packages/web/vite.config.ts`](https://github.com/Automattic/harper/blob/main/packages/web/vite.config.ts). Vite versions are locked in [`pnpm-lock.yaml`](https://github.com/Automattic/harper/blob/main/pnpm-lock.yaml), ensuring reproducible builds across the SvelteKit-based applications.

Common Vite workflows include:

- `pnpm dev` – starts the development server
- `pnpm build` – creates production bundles for deployment

### Biome for Formatting and Linting

**Biome** handles JavaScript and TypeScript formatting, invoked via `pnpm run format`. This works alongside Rust's native tooling: `cargo fmt` for Rust code and `cargo clippy` for linting. These tools are coordinated in the `justfile` around lines 38-44, ensuring consistent code style across the polyglot codebase.

## Desktop Application Build System

### Tauri for Native Packaging

**Tauri v2** builds the native Harper Desktop application as a Rust-backed binary with a SvelteKit frontend. The `justfile` coordinates this through the `dev-desktop` recipe (lines 68-74):

```bash
just dev-desktop

```

This recipe performs:

1. `pnpm install` – installs Node dependencies
2. `pnpm tauri dev` – launches the Tauri development environment with hot reloading

The Tauri configuration is defined in [`harper-desktop/src-tauri/tauri.conf.json`](https://github.com/Automattic/harper/blob/main/harper-desktop/src-tauri/tauri.conf.json), specifying windowing behavior and bundling parameters for cross-platform distribution.

## Testing Infrastructure

The build system integrates multiple testing frameworks:

- **Cargo test** – runs Rust unit tests via `cargo test`
- **pnpm test** – executes JavaScript unit and integration tests
- **Playwright** – handles browser automation for extension testing

The `justfile` provides convenient aggregation commands:

- `just test-harperjs` – runs the JavaScript test suite (lines 94-99)
- `just test-chrome-plugin` – executes Playwright tests for the Chrome extension (lines 91-107)

## Key Configuration Files

| File | Role |
|------|------|
| `justfile` | Central build orchestration defining all Just recipes |
| [`package.json`](https://github.com/Automattic/harper/blob/main/package.json) | Declares Node engine version, pnpm version, and dev dependencies including `@biomejs/biome` |
| [`pnpm-lock.yaml`](https://github.com/Automattic/harper/blob/main/pnpm-lock.yaml) | Locks exact versions of Vite, SvelteKit plugins, and Tailwind CSS |
| [`packages/web/vite.config.ts`](https://github.com/Automattic/harper/blob/main/packages/web/vite.config.ts) | Configures Vite and SvelteKit for the documentation website |
| [`harper-desktop/src-tauri/tauri.conf.json`](https://github.com/Automattic/harper/blob/main/harper-desktop/src-tauri/tauri.conf.json) | Tauri desktop application configuration and bundling settings |

## Summary

- **Just** provides the primary build interface, offering commands like `just build-web` and `just dev-desktop`
- **Cargo** compiles Rust crates while **wasm-pack** generates WebAssembly modules for JavaScript consumption
- **pnpm** manages Node.js dependencies and **Vite** bundles frontend assets for the website and browser extensions
- **Tauri** packages the desktop application, combining Rust binaries with the SvelteKit SPA frontend
- **Biome** and **Cargo** formatting tools enforce code quality alongside **Playwright** integration tests

## Frequently Asked Questions

### What is the main build command for the entire Harper project?

Run `just build-web` from the repository root. This executes the full pipeline defined in the `justfile`: building the WASM module with `wasm-pack`, compiling JavaScript packages with `pnpm build`, and bundling the website through Vite.

### How do I build only the WebAssembly components?

Execute `just build-wasm` to invoke `wasm-pack build` with targets for both full and slim WASM builds. This is useful when iterating on `harper-core` without rebuilding the entire frontend, as it skips the Node.js package compilation steps.

### Can I develop the desktop application without installing Rust?

No, the desktop application requires both Rust and Node.js toolchains. Use `just dev-desktop`, which automatically installs Node dependencies via `pnpm install` and launches `pnpm tauri dev` to build the Rust backend and SvelteKit frontend simultaneously.

### Which formatting tools does the project enforce?

The project uses **Biome** for JavaScript and TypeScript formatting (invoked via `pnpm run format`) and **Cargo**'s built-in tools for Rust code (`cargo fmt` and `cargo clippy`). Run `just precommit` to validate both formatting and linting before submitting changes, as defined in the `justfile` around lines 38-44.