This docs platform¶
How this site itself is built and operated. Adding a page, translating it and deploying it — it is all here.
Technology¶
| Component | Choice |
|---|---|
| Engine | MkDocs |
| Theme | Material for MkDocs |
| Multilingual | mkdocs-static-i18n |
| Diagrams | Mermaid (built into Material) |
| Output | Static HTML — no runtime |
The same stack as the documentation in the ecosystem's other repositories — which makes it easy to move a page or copy a configuration from one repo to another.
Repository layout¶
docs-gerege-mn/
├── mkdocs.yml # Site configuration, nav, i18n
├── requirements.txt # mkdocs-material, mkdocs-static-i18n
├── docs/ # ← The published content
│ ├── index.md
│ ├── assets/logo.webp
│ ├── stylesheets/brand.css
│ ├── ecosystem/
│ ├── platforms/
│ ├── standards/
│ └── operations/
├── deploy/ # Deployment tooling (NOT part of the site)
│ ├── README.md # The host runbook
│ ├── deploy.sh
│ ├── docker-compose.yml
│ ├── nginx-site.conf
│ └── edge/
│ └── docs.gerege.mn.conf
└── .github/workflows/
├── ci.yml
└── deploy.yml
Anything inside docs/ becomes public
The site is open to the internet. Server addresses, credentials and internal
risk registers must never live inside docs/. Such material belongs in
deploy/ (inside the private repository, and not part of the site).
Running it locally¶
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
# Development server — changes appear immediately
.venv/bin/mkdocs serve
# Production build (strict — warnings become errors)
.venv/bin/mkdocs build --clean --strict
mkdocs serve starts on http://127.0.0.1:8000.
Adding a page¶
- Create the file — a
.mdfile in the appropriate directory (for exampledocs/platforms/new.md). - Register it in
nav— add it to thenavlist inmkdocs.yml. - Nav translations — if you added a new menu label, add it to
nav_translationsfor all six locales (en·ar·zh·fr·ru·es). - Check with a strict build —
mkdocs build --strict.
Why strict mode matters
--strict turns warnings into errors: broken internal links, files listed
in nav that do not exist, and files that exist but are missing from nav.
CI runs in the same mode, so checking locally saves the PR from failing.
Adding a translation¶
The site is served in Mongolian plus the six official UN languages. It uses
the suffix layout — page.md (Mongolian) alongside versions carrying a language
code:
docs/platforms/sso.md ← Монгол (source)
docs/platforms/sso.ar.md ← العربية
docs/platforms/sso.zh.md ← 中文
docs/platforms/sso.en.md ← English
docs/platforms/sso.fr.md ← Français
docs/platforms/sso.ru.md ← Русский
docs/platforms/sso.es.md ← Español
When adding a page:
- Write the Mongolian original and stabilise it with a strict build.
- Add the six translations together — doing it piecemeal lets the content drift apart.
- Add the menu label to
nav_translationsinmkdocs.ymlfor all six locales.
Because fallback_to_default: true, the site stays whole even with translations
missing — the page shows the Mongolian original rather than a 404.
See Internationalisation for the detail.
Theme and brand¶
The colours are concentrated in a single block inside
docs/stylesheets/brand.css:
:root {
--grg-blue: #004eb6; /* header / deep cobalt */
--grg-blue-2: #0064e1; /* brand */
--grg-blue-deep: #003a8a;
--grg-blue-light: #3990ff; /* links in dark mode */
--grg-gold: #e4b24a; /* ONLY for emphasis / marks of trust */
}
Do not add new hex values outside this block. Gold is not a brand colour — it is only for emphasis and marks of trust.
Status badges¶
<span class="grg-badge grg-badge--live">Production</span>
<span class="grg-badge grg-badge--wip">Partial</span>
<span class="grg-badge grg-badge--plan">Planned</span>
Deployment architecture¶
Internet → edge nginx (gerege-nginx)
│ docs.gerege.mn vhost
▼
docs-gerege-web (nginx:alpine container)
│ shared `gerege` Docker network
▼
<deploy path>/site (the built static HTML)
The site is updated in place with rsync — replacing the directory wholesale
would leave the container still looking at the old inode, so the new content
would never appear.
Why a separate container? Adding a new mount to the edge nginx container requires recreating it — and that briefly takes every domain down. Serving the static site from its own small container means the edge only needs a configuration addition and a reload.
Configuration ownership¶
This site owns its own edge vhost — deploy/edge/docs.gerege.mn.conf. On
every deploy that file is installed into the edge nginx conf.d, validated with
nginx -t and applied with a reload. The Developer Portal and the Template
Platform have moved to the same pattern; sso · dan · gsign · xyp are for
now still served from the central file.
The effect is that any change to docs.gerege.mn is finished inside this
repository — no PR to another repo, no waiting on another team's deploy.
To be fully independent, the vhost has its own rate-limit zone and its own port-80 block (ACME + redirect) — it depends on no zone or default server defined in another file.
The general principle
Configuration that concerns only one service belongs in that service's repository. Putting it in a central file means every change has to be coordinated with another team's deploy, and ownership becomes blurred.
For how this pattern was arrived at, and why each decision was made, see Work log.
Deploy¶
Deployment happens automatically through CI — on a push to main:
- MkDocs
--strictbuild, - copy the
site/archive to the server, - update it in place with
rsync, - refresh the container,
- install the edge vhost →
nginx -t→ reload, - check the live site.
If nginx -t fails, the previous configuration is restored and no reload
happens — the running nginx carries on with its last good configuration.
If a manual deploy is needed there is a deploy/deploy.sh script — for
host-specific detail see the closed runbook in deploy/README.md.
Contributing¶
- Create a branch (
docs/<topic>orfeat/<topic>). - Make your change and run
mkdocs build --strictlocally. - Open a PR — CI runs the strict build.
- After merging it is published automatically.
House style¶
- Write the source text in Mongolian.
- Make the heading say what the page is about — more specific beats "Overview" or "Introduction".
- Write down the reason for a decision, not only what was done. "Why" is the information that goes stale most slowly.
- Put risks and cautions in a
!!! warningblock. - A table beats a long list.