# GeoLibre Coding Standards: A Complete Guide for Contributors

> Contribute to opengeos/GeoLibre with ease. Discover GeoLibre coding standards: strict linting, Conventional Commits, and pre-commit hooks ensure code quality for JavaScript, TypeScript, and Python.

- Repository: [Open Geospatial Solutions/GeoLibre](https://github.com/opengeos/GeoLibre)
- Tags: best-practices
- Published: 2026-08-16

---

**GeoLibre enforces minimal but strict linting rules for JavaScript/TypeScript and Python, requires Conventional Commits, and gates contributions through pre-commit hooks and coverage thresholds.**

The opengeos/GeoLibre repository maintains a deliberately narrow coding standards philosophy: catch critical errors early without burdening developers with stylistic debates. This guide walks through every standard that governs the codebase, from ESLint hook rules to Python Ruff configuration.

## JavaScript and TypeScript Standards

All front-end code in GeoLibre is linted through a single **ESLint flat config** located at `eslint.config.mjs`. The configuration takes a minimal approach—it enables only the React Hooks plugin rather than an extensive rule set.

### ESLint Configuration

The config parses all source files matching `*.ts`, `*.tsx`, `*.js`, `*.jsx`, `*.mjs`, and `*.cjs` using the `typescript-eslint` parser. It explicitly ignores build artifacts: generated bundles, distribution folders, and type-definition files.

Two rules are enforced:

- **`react-hooks/rules-of-hooks: error`** — Catches hook misuse that violates React's "rules of hooks" (calling hooks conditionally or outside components)
- **`react-hooks/exhaustive-deps: warn`** — Flags missing dependencies in hook arrays

This means developers must respect hook ordering and dependency arrays, but other stylistic choices remain discretionary.

### Correct Hook Usage Example

```tsx
import { useEffect, useState } from "react";

export function MyComponent() {
  const [data, setData] = useState(null);

  // ✅ Proper placement of useEffect before early returns
  useEffect(() => {
    fetch("/api/data").then((r) => r.json()).then(setData);
  }, []); // exhaustive-deps warning if dependencies omitted

  if (!data) return <div>Loading…</div>;

  return <div>{JSON.stringify(data)}</div>;
}

```

## Python Coding Standards

Python components—the `python/` package and FastAPI backend—are linted with **Ruff** via [`ruff.toml`](https://github.com/opengeos/GeoLibre/blob/main/ruff.toml). The configuration targets Python 3.10 as the minimum supported version.

### Ruff Configuration in [`ruff.toml`](https://github.com/opengeos/GeoLibre/blob/main/ruff.toml)

Key settings include:

- **Line length:** 100 characters
- **Quote style:** Double quotes for strings
- **Trailing commas:** Magic trailing commas respected

Enabled rule groups:

- **F** — Pyflakes (unused imports/variables, undefined names)
- **I** — isort (import ordering: stdlib → third-party → first-party)
- **W** and **E** — pycodestyle warnings and errors

Per-file exclusions apply to [`whitebox.py`](https://github.com/opengeos/GeoLibre/blob/main/whitebox.py) and [`test_map.py`](https://github.com/opengeos/GeoLibre/blob/main/test_map.py), which embed long string literals exempt from line-length checks.

### Ruff-Compliant Python Example

```python
"""Utility module for GeoLibre."""
from __future__ import annotations

import json
from typing import Any, Dict

def load_geojson(path: str) -> Dict[str, Any]:
    """Load a GeoJSON file and return its dictionary."""
    with open(path, "r", encoding="utf-8") as f:
        return json.load(f)

```

## Commit Message Standards

All contributions must follow the **Conventional Commits** specification. This enables automated changelog generation and clear version bumping.

Valid prefixes include `feat:`, `fix:`, `docs:`, `style:`, `refactor:`, `test:`, and `chore:`.

Example commit message:

```

feat: add support for remote MBTiles layers

- Register new plugin entry
- Update UI to expose MBTiles source option
- Add unit tests for validation logic

```

The complete policy is documented in [`CONTRIBUTING.md`](https://github.com/opengeos/GeoLibre/blob/main/CONTRIBUTING.md).

## Pre-commit Hooks

The repository ships a local `npm-build` pre-commit hook defined in [`.pre-commit-config.yaml`](https://github.com/opengeos/GeoLibre/blob/main/.pre-commit-config.yaml). This hook ensures the entire application builds successfully before any commit is accepted.

Run hooks manually with:

```bash
pre-commit run --all-files

```

## Testing and Coverage Gates

Coverage thresholds enforce quality without overhead.

### Frontend Coverage

- **Lines:** ≥ 78%
- **Branches:** ≥ 78%
- **Functions:** ≥ 63%

Enforcement logic lives in `scripts/coverage-check.mjs`. Tests run via `npm run test:frontend`.

### Backend Coverage

- **Minimum:** 55%

Backend tests use `pytest` with `pytest-cov`. Configuration resides in [`backend/geolibre_server/pyproject.toml`](https://github.com/opengeos/GeoLibre/blob/main/backend/geolibre_server/pyproject.toml), which declares the `test` extra and pulls in coverage tools.

## Key Configuration Files

| File | Purpose |
|------|---------|
| `eslint.config.mjs` | ESLint flat config with React Hooks rules |
| [`ruff.toml`](https://github.com/opengeos/GeoLibre/blob/main/ruff.toml) | Python linting rules, line length, import ordering |
| [`.pre-commit-config.yaml`](https://github.com/opengeos/GeoLibre/blob/main/.pre-commit-config.yaml) | Pre-commit hook definitions |
| [`CONTRIBUTING.md`](https://github.com/opengeos/GeoLibre/blob/main/CONTRIBUTING.md) | Contribution workflow and commit conventions |
| `scripts/coverage-check.mjs` | Frontend coverage threshold enforcement |
| [`backend/geolibre_server/pyproject.toml`](https://github.com/opengeos/GeoLibre/blob/main/backend/geolibre_server/pyproject.toml) | Backend test dependencies and pytest configuration |

## Summary

GeoLibre coding standards prioritize correctness over style:

- **React Hooks** violations are caught statically before runtime
- **Python code** stays PEP-8 compliant through Ruff with minimal, focused rule sets
- **Conventional Commits** ensure every contribution is documented and machine-readable
- **Pre-commit hooks** guarantee builds pass before code enters the repository
- **Coverage gates** prevent regression in test quality

These standards scale across the repository's mixed JavaScript/TypeScript frontend and Python backend without requiring large-scale refactors or lengthy style debates.

## Frequently Asked Questions

### How do I run the linter locally for JavaScript changes?

Run `npx eslint .` from the repository root. The flat config in `eslint.config.mjs` picks up all relevant source files automatically. No additional flags are required.

### What happens if my commit message doesn't follow Conventional Commits?

The project does not block commits at the git hook level for message format, but CI processes and release automation expect this format. Non-compliant messages may break changelog generation and require manual correction during review.

### Why is the Python line length set to 100 instead of 88?

The 100-character limit in [`ruff.toml`](https://github.com/opengeos/GeoLibre/blob/main/ruff.toml) balances readability with the complex type signatures common in geospatial code. It exceeds Black's default of 88 while staying below the traditional 120-character threshold.

### Can I disable Ruff rules for specific files?

Yes. The [`ruff.toml`](https://github.com/opengeos/GeoLibre/blob/main/ruff.toml) already excludes [`whitebox.py`](https://github.com/opengeos/GeoLibre/blob/main/whitebox.py) and [`test_map.py`](https://github.com/opengeos/GeoLibre/blob/main/test_map.py) from line-length checks. Add files to the `ignore` list under `[tool.ruff.lint.per-file-ignores]` following the existing pattern.