# How GeoLibre Pre-Commit Hooks Manage the npm-build Hook and Enforce Contribution Conventions

> Discover how GeoLibre pre-commit hooks manage the npm-build hook for type safety and production build integrity, enforcing strict contribution conventions for a robust JavaScript workspace.

- Repository: [Open Geospatial Solutions/GeoLibre](https://github.com/opengeos/GeoLibre)
- Tags: how-to-guide
- Published: 2026-08-05

---

**GeoLibre uses a monolithic pre-commit configuration anchored by a local `npm-build` hook that executes `npm run typecheck` (running `tsc -b && vite build`) to ensure every commit maintains type safety and production build integrity across the entire JavaScript workspace.**

The opengeos/GeoLibre repository employs a rigorous **pre-commit hook** strategy to maintain quality across its complex monorepo structure, which includes interdependent JavaScript packages, a Python FastAPI sidecar, and Tauri desktop applications. The **npm-build hook** specifically guards against broken imports and missing assets by enforcing a full type-check and Vite production build before any code reaches the main branch. Understanding how this hook functions alongside the project's contribution conventions is essential for developers contributing to this geospatial visualization platform.

## How the npm-build Pre-Commit Hook Works

GeoLibre defines its quality gates in [`.pre-commit-config.yaml`](https://github.com/opengeos/GeoLibre/blob/main/.pre-commit-config.yaml), where the local `npm-build` hook serves as the primary defense against build-breaking changes. Because the repository contains many inter-dependent packages—including apps, packages, and workers—the hook guarantees that every change keeps the whole application buildable.

### Build Verification and Type Safety

When developers run `pre-commit run` locally, the hook executes `npm run typecheck`, which internally runs `tsc -b && vite build`. This performs a **type-checking pass and a production-grade Vite build**, ensuring that:

- All TypeScript definitions are consistent across workspaces.
- All generated assets (such as the embedded web app bundled into the Python package) are up-to-date.
- Any change that would cause a runtime failure in the desktop, web, or Jupyter environments is caught early.

The hook prevents broken imports or missing assets from slipping into the main branch by validating the entire JavaScript workspace, not just the files being committed.

### Optimizing Hook Performance with Scoped Execution

Because a full build can be **slow and affect unrelated parts of the codebase**, the repository recommends **scoping the hook** to only the files you changed. This speeds up local feedback while still guaranteeing that the changed code integrates correctly with the rest of the monorepo.

Run the scoped hook locally using:

```bash
pre-commit run --files path/to/changed/file.ts

```

This approach allows developers to maintain rapid iteration cycles while adhering to the strict build requirements defined in the `npm-build` hook.

## GeoLibre Contribution Conventions

GeoLibre follows a well-defined workflow that balances rapid development with strict quality gates. Contributors must adhere to specific conventions regarding branching, testing, and platform-specific requirements.

### Branching Strategy and Pull Request Workflow

**Never commit directly to `main`.** All contributions must be developed in feature branches and submitted via Pull Request (PR). This ensures that CI pipelines and code review processes validate changes before integration.

### Testing Requirements Across Platforms

Contributors must run the appropriate test suites before pushing, depending on which components they modified:

- **`npm run test:frontend`** – Runs all frontend tests. Frontend coverage must stay above **78% lines/branches** and **63% functions**.
- **`npm run test:backend`** – Runs the FastAPI sidecar tests. Install the *test* extra to include optional engines. Backend coverage must stay above **55%**.
- **`npm run test:e2e`** – Executes Playwright end-to-end tests against a built web app.

These commands ensure that changes work correctly across the web interface, Python API, and desktop application.

### Type Safety and Build Verification

The **`npm run typecheck` command must succeed** before submitting a PR. This command runs `tsc -b && vite build` and is invoked automatically by the pre-commit `npm-build` hook. Maintaining type safety across the monorepo prevents runtime errors in the desktop, web, and embedded environments.

### Python Sidecar and Desktop Application Standards

When working with the Python backend or Tauri desktop app, additional conventions apply:

**Python Sidecar Dependencies:**
After editing [`backend/geolibre_server/pyproject.toml`](https://github.com/opengeos/GeoLibre/blob/main/backend/geolibre_server/pyproject.toml), synchronize the lockfile using:

```bash
uv lock --project backend/geolibre_server

```

Ensure the updated `uv.lock` file is committed alongside your changes.

**Tauri Desktop CSP Configuration:**
When adding new external map or tile hosts, update the CSP allowlist in [`apps/geolibre-desktop/src-tauri/CSP.ts`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/src-tauri/CSP.ts):

```typescript
// apps/geolibre-desktop/src-tauri/CSP.ts
export const CSP_ALLOWLIST = [
  // existing hosts…
  "https://mynewtileserver.com",
];

```

**Plugin Registration:**
Built-in plugins must be registered via [`apps/geolibre-desktop/src/hooks/usePlugins.ts`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/src/hooks/usePlugins.ts), while external plugins follow the manifest format described in [`docs/plugin-api.md`](https://github.com/opengeos/GeoLibre/blob/main/docs/plugin-api.md).

## Summary

- **Pre-commit hooks** in GeoLibre are defined in [`.pre-commit-config.yaml`](https://github.com/opengeos/GeoLibre/blob/main/.pre-commit-config.yaml) and center on a local `npm-build` hook that runs `npm run typecheck` (`tsc -b && vite build`).
- The hook ensures type safety and production build integrity across all JavaScript workspaces, preventing broken builds from reaching the main branch.
- Contributors should use `pre-commit run --files <path>` to scope hooks to changed files and avoid lengthy build times.
- **Contribution conventions** require feature branches (never direct `main` commits), comprehensive testing (frontend, backend, and e2e), and minimum coverage thresholds (78%/63% frontend, 55% backend).
- Python sidecar changes require `uv lock` updates, while Tauri desktop changes may require CSP allowlist modifications in [`apps/geolibre-desktop/src-tauri/CSP.ts`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/src-tauri/CSP.ts).

## Frequently Asked Questions

### How do I run pre-commit hooks only on files I changed in GeoLibre?

Use the `--files` flag to scope the hook execution to specific paths. For example, run `pre-commit run --files src/app/my-feature.tsx` to lint and build only the files you touched. This significantly speeds up local feedback while ensuring your changes integrate correctly with the monorepo.

### What tests must pass before submitting a PR to GeoLibre?

You must run three test suites depending on your changes: `npm run test:frontend` for UI components, `npm run test:backend` for the FastAPI sidecar (with test extras installed), and `npm run test:e2e` for Playwright end-to-end tests. Additionally, `npm run typecheck` must succeed to verify TypeScript consistency.

### How do I update dependencies in the Python sidecar?

After modifying [`backend/geolibre_server/pyproject.toml`](https://github.com/opengeos/GeoLibre/blob/main/backend/geolibre_server/pyproject.toml), navigate to the sidecar directory and run `uv lock --project backend/geolibre_server` to regenerate the lockfile. Commit both the [`pyproject.toml`](https://github.com/opengeos/GeoLibre/blob/main/pyproject.toml) and `uv.lock` files to ensure reproducible builds for the Python backend.

### What coverage thresholds are required for GeoLibre contributions?

Frontend contributions must maintain coverage above **78% for lines and branches** and **63% for functions**. Backend contributions must maintain coverage above **55%**. These thresholds are enforced to ensure code quality across the web interface and Python API components.