Short answer
A consultant-grade QGIS workflow is built so the next version of the same map is cheap and the handover is painless. Concretely: a fixed folder structure, working data consolidated into a GeoPackage, an intentional project CRS, named processing outputs (not temporary scratch layers), reusable print layout templates (.qpt), atlas generation for multi-sheet appendices, and a packaged project with relative paths, embedded styles, and a short README. That structure is what separates a deliverable a reviewer can audit from a project that only opens on the laptop that made it.
Project structure: decide it before importing anything
QGIS will happily let a project sprawl across a download folder, a desktop, and three shapefiles with the same name. Impose a layout first:
project-name/
01_raw/ # untouched source data, never edited
02_processed/ # working.gpkg (all derived layers)
03_project/ # project.qgz, layout templates, qml styles
04_outputs/ # exported PDFs, PNGs, deliverable GeoPackages
README.md # CRS, sources + dates, processing notes
Keep 01_raw read-only in spirit — it is the chain of custody for your data. Everything you create lands in 02_processed. This separation is what lets a reviewer answer "where did this layer come from?" months later.
Use a GeoPackage, not loose shapefiles
Store all working vector layers in one GeoPackage (working.gpkg). It is a single SQLite file that holds many layers, long field names, proper data types, and — importantly — layer styles in its gpkg_contents/style tables. Shapefiles truncate field names to 10 characters, split each layer across .shp/.shx/.dbf/.prj siblings that get separated, and cannot carry styling. To bring a layer in:
Right-click layer → Export → Save Features As → GeoPackage, choosing the existing working.gpkg and a clean layer name. Or on the command line:
ogr2ogr -f GPKG working.gpkg source.shp -nln boreholes -t_srs EPSG:27700
Set the CRS deliberately
Set the project CRS to your analysis grid (a UTM zone or national grid such as British National Grid, EPSG:27700) under Project → Properties → CRS, and disable surprises by knowing that QGIS reprojects layers to the project CRS on the fly for display only — the stored data keeps its own CRS. For any measurement or processing, reproject the data itself with Vector → Reproject Layer (or ogr2ogr -t_srs) so areas, lengths, and buffers are computed in metres. Confirm each layer's CRS in the Layers panel; a layer with a guessed or missing CRS will sit in the wrong place and quietly poison a buffer or area field.
Make the analysis reproducible
- Name your outputs. When you run a Processing algorithm (Buffer, Clip, Difference), save the result into
working.gpkgwith a real name instead of leaving it as aTemporary(memory) layer. Temporary layers vanish on close and cannot be audited. - Keep the Processing history. Processing → History logs the exact algorithm and parameters for every run. For anything you will repeat, drag those steps into the Graphical Modeler to build a model (
.model3) you can re-run on next year's data. - Save styles. Export each layer's symbology as a
.qmlinto03_project, or save it into the GeoPackage (Properties → Style → Save Style → in database). This is what makes the look reproducible.
Print layouts: build a template, reuse it everywhere
Hand-building each figure guarantees inconsistency. Instead, build one layout template:
- Project → New Print Layout. Set the page size and orientation (e.g. A4 landscape).
- Add the map frame, then a title block, scale bar, north arrow, legend, and a credits/metadata text box (data source, CRS, date, drawn-by). Use the Item Properties to fix the map scale (e.g. 1:10,000) so every figure shares a scale.
- Layout → Save as Template →
report_figure.qptin03_project.
Every subsequent figure starts from New Layout from Template, so the title block, fonts, scale bar style, and margins are identical across the whole report. Use dynamic text ([% @project_title %], [% format_date(now(),'yyyy-MM-dd') %]) in the title block so dates and project names fill themselves in.
Atlas: one layout, many pages
When the report needs a map per site, per borehole cluster, or per map sheet, do not copy the layout N times. Use the Atlas:
- In the layout, open the Atlas panel and set a coverage layer (e.g. a grid of map sheets, or the sites layer).
- Enable Controlled by atlas on the map frame and set it to follow each feature with a fixed scale or a margin around the feature.
- Drive titles and labels from feature attributes with expressions like
'Site ' || "site_id". - Atlas → Export Atlas as PDF produces one page per feature — a clean, uniform appendix of dozens of maps generated in a single pass.
This is the single biggest time saver for multi-site geotechnical or environmental reports, and it removes the human inconsistency of hand-laying each sheet.
Export settings that survive printing
- Export figures to PDF with vector content preserved (avoid rasterising unless you have blend modes that require it) so text stays sharp and selectable.
- For raster-heavy figures (hillshade, imagery), set a sensible export DPI (300 for print) and export those frames as raster while keeping vectors crisp.
- Embed or supply fonts; a layout using a font the client lacks reflows on their machine.
Package the project for handover
A deliverable must open on someone else's computer. Two reliable routes:
- Save the project into a GeoPackage: Project → Save To → GeoPackage stores the project and its layers in one file.
- Consolidate / package layers: use Processing → Package layers to copy all layers into a single GeoPackage, then save the
.qgzwith relative paths (Project → Properties → General → Save paths: Relative). Zip the wholeproject-name/folder.
Include the README noting: project CRS, each source dataset and its acquisition date, the key processing steps (with the model file if you built one), and any fonts required. The test of a good package: a colleague unzips it on a clean machine, opens the .qgz, and every layer loads with correct styling and the layouts render. If anything shows a red "unavailable layer," the paths were absolute or a layer lived outside the package.
Validation before delivery
- Topology and geometry: run Vector → Geometry Tools → Check Validity and the Topology Checker on edited layers; fix self-intersections and gaps before they show up in area calculations.
- Attribute completeness: check for null keys, duplicate IDs, and unit consistency in computed fields.
- CRS confirmation: verify each layer's CRS and that measured fields were computed in a projected grid.
- Clean-machine open: actually reopen the packaged project from
04_outputsto prove the handover works.
Common pitfalls and why they happen
- Temporary layers in the final map. They were never saved, so the project reopens with missing data. Save outputs to the GeoPackage.
- Inconsistent figures. Each map was built by hand; small differences in scale bar, fonts, and margins accumulate. Use a
.qpttemplate and the atlas. - "Layer unavailable" on the client's machine. Absolute paths or data left outside the project folder. Set relative paths and package layers.
- Wrong areas/lengths in attribute tables. Fields computed while the data was in a geographic CRS. Reproject the data, not just the display, before calculating.
- Reflowed or missing text in the PDF. A font the recipient lacks. Embed fonts or stick to common ones.
Bathyl perspective
We build QGIS projects as if a stranger will inherit them — because for a consultant deliverable, someone usually does. A fixed structure, GeoPackage-backed data, template-driven layouts, atlas-generated appendices, and a packaged, relative-path project mean the report can be reopened, re-run, and defended a year later. The discipline is in the structure, not the software.
Related reading
- QGIS Project Setup Checklist
- QGIS Layer Styling for Geological Maps
- QGIS vs ArcGIS for Geological and Terrain Workflows
- Shapefile vs GeoPackage vs GeoJSON
- GIS and spatial analysis