The source for omegaUp's contributor and architecture documentation, published at
docs.omegaup.com. It is a static site built with
Zensical (the successor to Material for MkDocs, from the same
team) and ships in four languages: English (en, the source of truth), Spanish (es),
Portuguese (pt), and Brazilian Portuguese (pt-BR).
New here? Read QUICKSTART.md for the two commands that get you a local preview, then come back for the details.
English is authored by hand; the other three languages are generated from it by
scripts/translate_docs.py. That single rule drives the whole workflow:
- Edit
docs/en/only. Never hand-editdocs/es/,docs/pt/, ordocs/pt-BR/— your changes there are overwritten on the next translation run. - Each language has its own
zensical.<lang>.tomlconfig (itsdocs_dir,site_dir,language, and navigation labels). The navigation structure — the file paths — is identical across all four; only the visible section titles are localized. - When you add, rename, or remove a page, update the nav in all four
zensical*.tomlfiles so every language builds cleanly.scripts/verify_docs_nav.py(run automatically bybuild_all.py) fails the build if any.mdfile is missing from its nav, andscripts/verify_docs_rendered.pyfails if any page produced no HTML.
Zensical is a Python package. Everything below assumes Python 3.10+.
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install zensicalIf the
zensicalconsole command isn't on yourPATH(e.g. a global install), usepython3 -m zensical …instead —build_all.pyalready does this for you.
python3 build_all.pyThis cleans site/, verifies every page is in nav, builds /en/, /es/, /pt/, and
/pt-BR/, verifies every page rendered, and writes a root redirect from / to /en/.
To build a single language while iterating:
python3 -m zensical build --clean --config-file zensical.toml # English
python3 -m zensical build --clean --config-file zensical.es.toml # Spanishpython3 serve_multilang.py # http://localhost:8000/ (redirects to /en/)Use this rather than zensical serve — the multi-language server maps /en/, /es/,
/pt/, and /pt-BR/ correctly so the language switcher works. zensical serve only
knows about one language directory and 404s on the others.
Only after the English tree is finalized and reviewed:
python3 scripts/translate_docs.py # all languages, all files
python3 scripts/translate_docs.py --langs pt # one language
python3 scripts/translate_docs.py --only getting-started # a subset, for testingRunning the translator before English is final wastes effort and creates drift, because
it overwrites es/pt/pt-BR wholesale.
Pushing to main triggers .github/workflows/deploy.yml, which builds all four
languages and publishes to GitHub Pages. The workflow is self-configuring — you do not
edit site_url by hand for a deploy:
- It computes
site_urlat build time from the repository owner/name (https://<owner>.github.io/<repo>/, or the apex form when the repo is named after the owner), rewriting everyzensical*.tomlbefore building. Thesite_urlcommitted in the toml files is only a placeholder for local builds. - It authenticates GitHub Pages with
secrets.PAGES_DEPLOY_TOKEN, falling back to the defaultgithub.token. The token is required for theomegauporg repository — the default token can't enable Pages on an org repo. - After building it rewrites asset paths for the Pages base path, forces the omegaUp
favicon, adds
.nojekyll, and writes the/ → /en/redirect.
For a custom domain (docs.omegaup.com), set the CNAME in the Pages settings; the
computed site_url still applies for path resolution.
ou-documentation/
├── .github/workflows/deploy.yml # Build + GitHub Pages deploy (self-configuring)
├── docs/
│ ├── en/ # English — the source of truth (edit here)
│ ├── es/ pt/ pt-BR/ # Generated by scripts/translate_docs.py — do not edit
│ └── <lang>/{assets,stylesheets,javascripts}/
├── overrides/ # Theme customizations (nav partial + custom icons)
├── scripts/
│ ├── translate_docs.py # Generate es/pt/pt-BR from en
│ ├── verify_docs_nav.py # Fail build if a page is missing from nav
│ ├── verify_docs_rendered.py # Fail build if a page produced no HTML
│ └── generate-gsoc-pages.py # Build GSoC pages from community/gsoc/_data
├── zensical.toml # English config (+ .es / .pt / .pt-BR siblings)
├── build_all.py # Build every language + verify + root redirect
├── serve_multilang.py # Local multi-language dev server (port 8000)
├── QUICKSTART.md # Fast path for new contributors
└── README.md # This file
site/, .cache/, and .venv/ are generated and gitignored.