| name | update-docs |
| description | Update Sowel documentation site (MkDocs Material). Use when implementing features, fixing bugs, or when user asks to update/add documentation. |
| user-invocable | true |
| argument-hint | [page-or-topic] |
Sowel Documentation Update Workflow
Topic to document: $ARGUMENTS
Step 1: Identify Pages to Update
| Change type | Pages to update |
|---|
| New API endpoint | docs/technical/api-reference.md |
| New equipment type | docs/user/equipments.md + docs/technical/data-model.md |
| New plugin | docs/technical/plugin-development.md (if patterns changed) |
| New UI feature | Relevant docs/user/*.md page |
| Architecture change | docs/technical/architecture.md |
| New recipe | docs/technical/recipe-development.md |
| New integration | docs/user/getting-started.md + docs/technical/architecture.md |
| Schema change | docs/technical/data-model.md |
Step 2: Read Existing Content First
ALWAYS read the target page before editing it. Understand the existing structure, style, and level of detail before making changes.
Step 3: Update the Documentation
Rules:
- Write in English only
- Use MkDocs Material extensions:
!!! tip, !!! warning, !!! note, code blocks with language, tables
- User guide (
docs/user/): non-technical, task-oriented ("You can...", "To create a zone, click...")
- Technical guide (
docs/technical/): detailed with code examples and type signatures
- No emojis unless already present in the page
Step 4: Update Navigation (if new page)
If you added a new page, update mkdocs.yml nav section.
Step 5: Screenshots
Screenshots live under docs/screenshots/ and are referenced from .md files via .
Naming convention
<topic>-<context>-<lang>.png — e.g., energy-live-en.png, zone-view-fr.png. Always provide both -en.png and -fr.png and reference each from the matching locale file.
Quality rules — non-negotiable
- Take screenshots on a 1920×1080 viewport with
fullPage: true. Existing reference screenshots (energy, getting-started) are 1920×1080. Smaller crops get scaled up by the docs theme and look pixelated. Tight element crops (section:has(...)) are forbidden for that reason.
- Show the surrounding context. A reader landing on the page should understand where the feature lives in the UI. Capture the full zone view, not just one panel.
- For mobile, use a 390×844 viewport (iPhone 13) with
fullPage: true. The page is allowed to be tall (a scrollshot is fine).
- Hide live noise before shooting: pause polling tasks, dismiss toasts, ensure the WS connection pill reads
● live (not ○ offline).
- Never shoot on prod (
sowelox / 192.168.0.230:3000) and never use ./scripts/run-swap.sh local for screenshots:
- Prod data leaks family names (PIR Marc, Chambre Victor, etc.) and the actual home topology into public docs.
run-swap.sh local does ssh sowelox 'docker stop sowel' over SSH, which crashes the user's real home automation.
- Use the demo instance and the anonymized showroom fixture instead — see "Screenshot pipeline" below.
Screenshot pipeline (anonymized via demo instance)
The demo instance lives on domopi.local:3001 (Raspberry Pi). Two stages:
1. Build anonymized fixtures from a fresh prod backup
python3 -c "
import urllib.request, json
req = urllib.request.Request('http://192.168.0.230:3000/api/v1/auth/login',
data=json.dumps({'username':'admin','password':'<see reference_sowel_access memory>'}).encode(),
headers={'Content-Type':'application/json'}, method='POST')
tok = json.loads(urllib.request.urlopen(req).read())['accessToken']
req = urllib.request.Request('http://192.168.0.230:3000/api/v1/backup',
headers={'Authorization':'Bearer '+tok})
open('/tmp/prod-backup.zip','wb').write(urllib.request.urlopen(req).read())
"
python3 scripts/doc/build-fixtures.py /tmp/prod-backup.zip
The script uses ZONE_RENAME_FR, EQUIPMENT_RENAME_FR, and the FR→EN ZONE_TRANSLATE / EQUIPMENT_TRANSLATE maps in scripts/doc/build-fixtures.py. If a new name appears that needs anonymization or translation, add it to the maps in the script first.
2. Deploy fixture to demo + shoot (per language)
ssh mchacher@domopi.local 'cd /home/mchacher/sowel-demo && docker compose down -v && docker compose pull && docker compose up -d'
Demo compose file: /home/mchacher/sowel-demo/docker-compose.yml. Keep image: ghcr.io/mchacher/sowel:<version> aligned with the prod release. Demo port 3001 maps to container 3000.
Playwright MCP recipe (preferred)
mcp__playwright__browser_resize({ width: 1920, height: 1080 });
mcp__playwright__browser_navigate({ url: "http://localhost:5173/<page>" });
mcp__playwright__browser_wait_for({ time: 3 });
mcp__playwright__browser_take_screenshot({
type: "png",
filename: "<topic>-en.png",
fullPage: true,
});
For the language swap between -en and -fr files, switch via localStorage.setItem("sowel_language", "en"|"fr") then location.reload() and re-shoot.
When you must crop tight
If you absolutely need a close-up of a control (e.g., to highlight a toggle button), do it on top of the wider page screenshot in a second image and label the cropped one clearly (-detail- infix). Never replace the wide context shot with the crop.
Step 6: Verify
mkdocs build --strict
Step 7: Commit
Documentation auto-deploys to GitHub Pages when pushed to main.
git add docs/ mkdocs.yml
git commit -m "docs: <description>"
Documentation Structure
docs/
├── index.md # Home page
├── technical/ # Technical Guide
│ ├── architecture.md # System design, pipeline
│ ├── api-reference.md # REST API, WebSocket
│ ├── plugin-development.md # Plugin creation guide
│ ├── recipe-development.md # Recipe template guide
│ ├── data-model.md # SQLite schema, types
│ └── contributing.md # Dev setup, conventions
└── user/ # User Guide
├── getting-started.md # Installation, first login
├── equipments.md # Equipment types, bindings
├── dashboard.md # Widgets, customization
├── zones.md # Zones, aggregation
├── modes.md # Modes, calendar
├── energy.md # Energy monitoring
└── remote-access.md # HTTPS, tunnel