Inside QGIS-Website: the Hugo repository that serves qgis.org
Official Website for QGIS.org
At a glance
- What is it?
- qgis/QGIS-Website holds the source for the main QGIS Project site and nothing else, built with a two tree Makefile target, Prettier checks and Playwright tests. Anyone changing content on qgis.org needs I18N.md, DEVELOPMENT.md and the shortcode spacing rules the project writes down twice.
- Who is it for?
- Use this repository when the change belongs on qgis.org itself, since every other QGIS subdomain site has its own codebase and contribution process. Before planning around its tooling, read DEVELOPMENT.md for the per language build and media dedup behaviour, and confirm the deployment path yourself, because the deploy target is not spelled out.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.
Star history
- qgis/QGIS-Website75 ★ · +5
| Repository | 2026-08-21 | 2026-11-14 |
|---|---|---|
| qgis/QGIS-Website | 70 | 75 |
5 Stars in the last 85 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
Only qgis.org lives here, the eight subdomain sites do not
qgis/QGIS-Website holds the source code for the main QGIS Project website at https://qgis.org and nothing beyond it. The opening note is emphatic on that point: this repository is only for the main site, and anyone looking for a subdomain has to go somewhere else. Each one has its own codebase and its own contribution process, and the eight named in the README are plugins.qgis.org in QGIS-Plugins-Website, hub.qgis.org in QGIS-Hub-Website, feed.qgis.org in qgis-feed, planet.qgis.org in QGIS-Planet-Website, members.qgis.org in QGIS-Members-Website, certification.qgis.org in QGIS-Certification-Website, changelog.qgis.org in QGIS-Changelog-Website and conference.qgis.org in QGIS-UC-Website. That list is the first thing to read if you arrived hunting for the plugins repository or the user conference site and found neither. The Python language label on the repository refers to the scripts it carries, not to the site itself, which is a Hugo project built from markdown, templates and data files.
The build target assembles two production trees and stamps the commit hash
The Makefile generates its own help text. The help target greps for target names followed by a comment marker and pipes the pairs through awk, so a new target documents itself by carrying that comment rather than by being added to a list somewhere. The build target is the one worth reading twice. It runs the commit hash script first, then builds qgis.org into public_prod.build using config/config.prod.toml, and builds www.qgis.org into public_www.build using config/config.www.toml. Each finished directory is then swapped into place: the existing public_prod is moved aside to public_prod.old, the freshly built directory takes the plain name, and the old copy is deleted.
sh ./scripts/get_commit_hash.sh
PUBLIC_DIR=public_prod.build CONFIG_PROD=config/config.prod.toml bash scripts/build_prod_per_lang.sh
PUBLIC_DIR=public_www.build CONFIG_PROD=config/config.www.toml bash scripts/build_prod_per_lang.shTwo environment variables carry the whole difference between the two halves of the build: PUBLIC_DIR picks the output directory and CONFIG_PROD picks which Hugo config gets loaded. The script name says the rest, since build_prod_per_lang.sh runs the production build once per language rather than for all of them at once. get_commit_hash.sh writes the current commit hash into config/commit.toml, which is what the version display in the footer of every page reads, so a build that skips it ships a version line from an earlier commit. A deploy target sits immediately below build in the same file, though the commands it runs are not shown there, so treat the deployment path as undocumented rather than guessing at it.
Prettier with a Go template plugin, and two different license fields
Formatting runs through a package.json named prettier-hugo whose three scripts call Prettier directly.
"format:check": "prettier --check .",
"format:debug-check": "prettier --debug-check .",
"format:write": "prettier --write ."The first reports files that differ from Prettier's output, the second reports what Prettier would do to a file rather than rewriting it, and the third applies the changes. Two devDependencies carry the weight: prettier at ^3.1.1 and prettier-plugin-go-template at ^0.0.15, so Go templates inside the layouts directory are formatted by the same tool as everything else. Configuration lives in .prettierrc.json at the root, with .prettierignore next to it. One detail is easy to misread: this package.json declares its own license field as ISC while the project itself is licensed under the MIT License, and the Makefile help banner credits Kartoza (Pty) Ltd. When the two disagree, the LICENSE file at the repository root is the one that describes the project's terms.
Hugo directories sit beside three separate translation trees
The tree follows Hugo conventions. config/ holds the Hugo configuration files, layouts/ the templates and partials, content/ the markdown files for pages and posts, data/ the YAML, JSON and TOML files that feed site variables, and public/ the generated site output. assets/ is used mainly to store the schedule.csv file, while docs/ holds project documentation and img/ holds the images used by the README itself. Contributor documentation is spread over several files at the root: CONTRIBUTING.md, CONTRIBUTORS_PAGE.md, DEVELOPMENT.md and I18N.md. Around the Hugo core sit three separate translation trees, content-translated/, translations/ and i18n/, along with a .tx/ directory for translation services. The Python side of the tooling shows up as .python-version, Pipfile, Pipfile.lock and REQUIREMENTS.txt. flake.nix and flake.lock, a nix/ folder and an .envrc point at a Nix shell, and themes/, source/ and static/ carry additional assets. Tests come in two flavours, test/ with pytest.ini for the Python side and playwright/ for end to end browser checks, with a test-results/ directory at the root where those runs leave their output.
Harvest scripts write straight into content and data
Two scripts pull outside data into the site, and the destinations are named precisely. fetch_feeds.py gets sustaining members and other feeds, and the parts it touches are the sustaining members page under content/funders/, the news feeds in data/feed.json and the Flickr gallery under content/flickr-images/. It sits at the repository root while its siblings live in scripts/, which is a small inconsistency worth knowing about when you go looking for it in the wrong folder. scripts/changelog_harvest.py creates or updates the visual changelogs at content/project/visual-changelogs based on the data at data/conf.json, so those changelog pages are derived from a configuration file rather than written page by page. A third script, scripts/get_commit_hash.sh, writes into config/commit.toml and feeds the footer version info across all pages. The same table lists vscode.sh, which launches VSCode with the settings and extensions needed to work on the project and affects the development environment only, with no effect on the built site.
Shortcode spacing rules that translations get wrong
The internationalization and translation workflow is written down in I18N.md, and the development and production build guide is DEVELOPMENT.md, which covers incremental per language builds and media dedup. The authoring rules stated for translated content are narrow and mechanical: use shortcode params with spaces around the equals sign, keep a shortcode's closing delimiter on the same line, and do not use inline HTML in markdown files. The same guidance is pointed at from CONTRIBUTING.md, so a translator reading either file gets the three rules. None of them changes what a page means, which is why they are easy to lose in a bulk translation pass: a param written tight against its key still parses, and inline HTML in a markdown file still renders. The three translation directories and .tx/ at the root are where that work lands, and DEVELOPMENT.md's per language builds are what let a translator rebuild a single language instead of the whole site.
Generated text has to arrive with the prompt that produced it
The project sets out three conditions for machine assisted contributions, and they are numbered rather than optional. Repeatability: when output from a large language model or generative machine learning tool is used verbatim, the prompt that generated the resource must be supplied with it, even though repeatability in general is not achievable. Declaration: supplying that prompt counts as declaring that a machine learning assistant took part, and where it is not obvious that a piece of work was generated, the robot icon goes next to the code snippet or text snippet in question. Validation: generated output should always be checked by a human, and the contributor, not the tool, takes ultimate responsibility for the correct functionality of any code and the correct expression of any text or media submitted. For a pull request this means a generated translation or snippet arrives with its prompt attached and with a person standing behind it.
What the badge table actually checks
The QA section is a table of badges, and the descriptions tell you which checks run on a change: end to end tests through Playwright, deployment status to GitHub Pages, and an internal link check on the built site. Those three are the automatic gates a contribution has to pass. Four more rows are listed for website availability, the repository license, open and closed issue counts and open and closed pull request counts, but no status value is captured alongside them, and a Project Stars section sits empty in what the README shows. So the availability of the live site is not something this repository records for you to consult before assuming qgis.org is answering. The project itself publishes no GitHub releases either, which leaves the commit history and the generated visual changelogs as the record of what changed. The last push on record is 30 September 2026, so activity is current.
Editorial conclusion
Use this repository when the change belongs on qgis.org itself, since every other QGIS subdomain site has its own codebase and contribution process. Before planning around its tooling, read DEVELOPMENT.md for the per language build and media dedup behaviour, and confirm the deployment path yourself, because the deploy target is not spelled out. The last push on record is 30 September 2026 and the project publishes no GitHub releases, so there is no tagged version to pin a checkout to and no changelog beyond the generated visual changelogs.
Frequently asked questions
Is QGIS.org a legitimate website?
qgis/QGIS-Website says it hosts the source code for the official QGIS Project website, served at https://qgis.org. The repository carries an MIT license, publishes on its main branch, and its last push was 30 September 2026.
Is the qgis website down?
The repository records no status for it. A badge row for website availability is listed with no captured value, so the repository cannot tell you whether the live site is serving right now.
Which qgis.org sites are built from other repositories?
Eight of them, each with its own codebase and contribution process: plugins.qgis.org, hub.qgis.org, feed.qgis.org, planet.qgis.org, members.qgis.org, certification.qgis.org, changelog.qgis.org and conference.qgis.org. This repository covers only the main site at qgis.org.
How does the QGIS-Website build target differ between qgis.org and www.qgis.org?
Both halves run the same script with different settings. qgis.org builds into public_prod.build with config/config.prod.toml, and www.qgis.org builds into public_www.build with config/config.www.toml. Each finished directory is then moved over the existing one, and the previous copy is deleted.
How does the project handle text written with a machine learning assistant?
Three rules apply. The prompt that generated any output used verbatim must be supplied with it, the robot icon marks generated snippets where it is not already obvious, and a human must validate the result before it is submitted.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/qgis-qgis-website)Star history chart for your README
[](https://hysenlabs.com/projects/qgis-qgis-website)Was this useful?