Automatic Web Symbology
The three flavours of the Riverscapes viewer each require symbology files in different formats (see the table below). Generating all three by hand is a lot of work! In September 2026 we introduced a new system that automatically converts QGIS .qml symbology files into the JSON format used by the Riverscapes Viewer for the web. This page explains how that automation works so you know what to expect when you add or change QML files.
| Riverscapes Viewer | Symbology File Type |
|---|---|
| Riverscapes Viewer for QGIS | *.qml files |
| Riverscapes Viewer for ArcGIS Pro | *.lyrx files |
| Riverscapes Viewer for the Web | JSON files |
This saves symbology authors time: you focus on QGIS and let the automation produce a first pass at the web symbology. You should review each automatically generated web symbology, and you can always override it — either by editing what the automation produced or by uploading your own.
Note that ArcPro symbology regrettably uses the proprietary *.lyrx format and must always be generated by hand.
Directory Layout
The table below illustrates where you put your QGIS QML files and then where the automation outputs the web symbology JSON files.
| Directory | Contents | Who writes it |
|---|---|---|
Symbology/qgis/<Context>/ | Your .qml files, organized by program/context (e.g. BRAT/, Anthro/, Hydro/) | You (humans) |
Symbology/web/<Context>/ | Generated .json files, one per QML, mirroring the QGIS folder structure | The GitHub Action (bot) |
For example, a file named Symbology/qgis/BRAT/barrier_density.qml produces Symbology/web/BRAT/barrier_density.json. The generated JSON is also served publicly, so the viewer and external consumers read it from URLs like:
https://xml.riverscapes.xyz/Symbology/web/BRAT/barrier_density.json
When It Runs
The GitHub Action (.github/workflows/symbology_sync.yml) runs on every push to master that changes anything under Symbology/qgis/**. Importantly, the automation only creates missing web symbology JSON files — it never updates existing ones.
What the Automation Supports
The automation handles the common QGIS style features:
- Renderer types: graduated, single symbol, categorized, and rule-based renderers
- Geometry types: points/circles, lines, and fills (polygons)
- QML dialects: both
<Option>-style (QGIS 2) and<prop>-style (QGIS 3) attributes - Colours: solid and translucent (alpha) colours, converted to
rgb()/rgba()/hsla()strings - Labels: range labels (e.g.
"1 - 2","> 10") and category labels end up in the JSONlegendso the viewer can render a legend automatically
The output JSON contains a $schema reference plus a legend (list of [colour, label] pairs) and layerStyles (renderer paint/line/circle settings).
What is Not Created or Updated
The automation only creates missing JSON files. It never overwrites or regenerates existing ones (see Updating Existing Symbology for the workaround).
Specifically:
- Existing JSON files are left untouched. If you edit a QML whose JSON already exists, the action skips it and reports it as "skipped".
- Raster symbology is not produced.
.qmlfiles with a raster renderer are skipped (raster symbology is handled outside this converter).
Adding New Symbology (Recommended Workflow)
- Put your
.qmlfile in the folder that matches your program, e.g.Symbology/qgis/MyProject/.- The folder name becomes part of the output path and the URL, so choose it carefully.
- Each
.qmlfile gets its own JSON; a single QML containing several layers is also fine — the converter maps them into the JSONlayerStyles.
- Commit and push to
master. The push must include changes underSymbology/qgis/for the action to run. - Within a couple of minutes the action finishes and adds the new JSON to
Symbology/web/in a follow-up commit from the automation bot. - Reference the JSON in the viewer, e.g.
https://xml.riverscapes.xyz/Symbology/web/MyProject/my_style.json.
Updating Existing Symbology
Because the action never overwrites existing JSON, updating a style requires one extra step compared to adding new symbology:
- Edit or replace the
.qmlfile inSymbology/qgis/. - Delete the corresponding
.jsoninSymbology/web/. - Commit both the QML change and the JSON deletion together, then push to
master. (Deleting only the JSON won't trigger the action — the trigger watchesSymbology/qgis/, notSymbology/web/.) - The action detects the missing JSON and regenerates it from your updated QML.
Alternatively, regenerate locally and push the result yourself:
cd python
uv run python QML2WebSymbology.py --dir MyProject --force