Linter, validator, and formatter for MapLibre GL / Mapbox GL style JSON.
Catch spec violations, enforce best practices, and keep style files consistent — in CI or locally.
GL style JSON files grow fast. A single typo in a source reference silently breaks tiles. An invisible layer left in production wastes render time. Legacy filter syntax slips through code review unnoticed.
styl is the cargo clippy for your map styles — runs in milliseconds, integrates with CI, and tells you exactly what is wrong and why.
$ styl check style.json
warning[W002] layers[9].layout.visibility: layer "Building" is permanently invisible
--> style.json
hint: remove the layer or set visibility to "visible" if it should be shown
warning[W011] layers[3].filter: layer "Landuse" uses deprecated legacy filter syntax
--> style.json
hint: migrate to expression-based filters: https://maplibre.org/maplibre-style-spec/expressions/
error[E003] sources.roads: vector source missing required field "url" or "tiles"
--> style.json
| Feature | Description |
|---|---|
| Validator | Spec violations: missing fields, invalid values, broken source refs (E-codes) |
| Linter | Best-practice warnings: duplicate IDs, invisible layers, legacy filters, perf anti-patterns (W-codes) |
| Formatter | Canonical key ordering with --check mode for CI enforcement |
| Multiple output formats | Human-readable, JSON (for tooling), GitHub Actions annotations |
| Config file | Per-project .stylrc — per-rule severity overrides, indent settings |
| Stdin support | cat style.json | styl check --stdin — pipe-friendly |
brew tap navidnabavi/tap
brew install stylcurl -fsSL https://raw.githubusercontent.com/navidnabavi/styl/main/install.sh | bashDetects your OS and architecture, downloads the correct binary, installs to /usr/local/bin.
cargo install --git https://github.com/navidnabavi/stylgit clone https://github.com/navidnabavi/styl
cd styl
cargo build --release
# binary at: target/release/stylstyl check style.json # validate + lint (most common)
styl validate style.json # spec violations only (E-codes)
styl lint style.json # best-practice warnings only (W-codes)
styl fmt style.json # format in-place
styl fmt --check style.json # CI: exit 1 if formatting would change
styl check --format json style.json # machine-readable output
styl check --format github style.json # GitHub Actions annotations
cat style.json | styl check --stdin # read from stdin| Code | Meaning |
|---|---|
0 |
Clean — no diagnostics |
1 |
Diagnostics found (errors or warnings) |
2 |
Tool error (bad JSON, I/O failure) |
GitHub Action (Recommended):
- uses: navidnabavi/styl@v0.0.4
with:
style_file: style.jsonAdvanced usage:
- uses: navidnabavi/styl@latest
with:
style_file: style.json
command: check # check (default), validate, lint, fmt
format: github # github (default), human, json, html
version: v0.0.4 # pin styl version (optional)Pre-commit hook:
styl fmt --check style.json && styl check style.jsonDrop a .stylrc at your project root:
[rules]
W002 = "error" # invisible layers → hard error
W003 = "off" # unused layers → silence
W011 = "warn" # legacy filters → warn (default)
[format]
indent = 4styl walks up the directory tree to find it automatically.
| Document | Description |
|---|---|
| CLI Reference | All subcommands and flags |
| Validators | E-code spec violations |
| Linter Rules | W-code best-practice warnings |
| Expressions | Supported expression operators |
| Formatter | Key ordering and --check mode |
| Configuration | .stylrc reference |
| Layer Properties | Valid paint/layout props per layer type |
- MapLibre GL Style Spec v8 (default) — maplibre.org/maplibre-style-spec
- Mapbox GL Style Spec v8 — pass
--spec mapbox
See CONTRIBUTING.md. New validators and linter rules are welcome — the architecture makes adding them straightforward.
cargo build && cargo test && cargo clippy -- -D warnings && cargo fmt --checkAll four must pass before opening a PR.
MIT