diff --git a/.forgejo/workflows/main.yaml b/.forgejo/workflows/main.yaml
new file mode 100644
index 0000000..78facd9
--- /dev/null
+++ b/.forgejo/workflows/main.yaml
@@ -0,0 +1,18 @@
+on: [push]
+jobs:
+ job:
+ container:
+ image: ${{vars.DOCKER}}debian:bookworm
+ steps:
+ - name: spcd
+ env:
+ SPCD: ${{vars.SPCD}}
+ SPCD_SSH_HOSTS: ${{vars.SPCD_SSH_HOSTS}}
+ SPCD_SSH_KEY: ${{secrets.SPCD_SSH_KEY}}
+ SPCD_TXT_LOCALE: ${{vars.SPCD_TXT_LOCALE}}
+ run: ${{vars.SPCD}}
+
+ - run: spcd-check-project
+ - run: spcd-build-project
+ - run: spcd-browse-workspace
+ - run: spcd-synchronize
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e2e7327
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/out
diff --git a/build.py b/build.py
new file mode 100755
index 0000000..81ffcd9
--- /dev/null
+++ b/build.py
@@ -0,0 +1,41 @@
+#! /usr/bin/env python3
+"""Build web."""
+
+from pathlib import Path
+
+from rwx.fs import make_directory, read_file_text, write
+from rwx.ps import run
+
+if __name__ == "__main__":
+ root = Path(__file__).parent
+ out = root / "out" / "web"
+ gv = root / "index.gv"
+ svg = out / "index.svg"
+ make_directory(out)
+ run("dot", str(gv), "-Tsvg", "-o", str(svg))
+ text = read_file_text(svg)
+ write(
+ out / "index.css",
+ """\
+html {
+background-color: #202020;
+}
+""",
+ )
+ write(
+ out / "index.html",
+ f"""\
+
+
+
+
+
+todo.rwx.work
+
+
+
+{text}
+
+
+""",
+ )
diff --git a/index.gv b/index.gv
new file mode 100644
index 0000000..ac4ab30
--- /dev/null
+++ b/index.gv
@@ -0,0 +1,262 @@
+# ╭───────╮
+# │ Graph │
+# ╰───────╯
+digraph "index" {
+bgcolor="transparent"
+color="#C0C000"
+fontcolor="#FF8000"
+fontname="DejaVu Sans"
+penwidth="2"
+rankdir="RL"
+
+# ╭───────┬──────╮
+# │ Graph │ Edge │
+# ╰───────┴──────╯
+edge [
+fontcolor="#FF4040"
+fontname="DejaVu Sans"
+style="filled"
+]
+
+# ╭───────┬──────╮
+# │ Graph │ Edge │
+# ╰───────┴──────╯
+node [
+color="#C0C0C0"
+fontcolor="#FFFFFF"
+fontname="DejaVu Sans"
+penwidth="2"
+shape="record"
+style="filled"
+]
+
+{ rank="max"
+"" [style="invis"]
+}
+
+edge [color="#008000"]
+node [fillcolor="#408040"]
+
+# ╭────────╮
+# │ DevOps │
+# ╰────────╯
+
+subgraph "cluster/devops" {
+label="DevOps"
+
+"devops/dev/plan" -> "devops/ops/release" [style="invis"]
+"devops/dev/test" -> "devops/ops/monitor" [style="invis"]
+
+# ╭────────┬─────╮
+# │ DevOps │ Dev │
+# ╰────────┴─────╯
+
+subgraph "cluster/devops/dev" {
+label="Dev"
+
+"devops/dev/plan" [label="Plan"]
+"devops/dev/code" [label="Code"]
+"devops/dev/build" [label="Build"]
+"devops/dev/test" [label="Test"]
+
+}
+
+"devops/dev/plan" -> "devops/dev/code" -> "devops/dev/build" -> "devops/dev/test" -> "devops/dev/plan"
+
+# ╭────────┬─────╮
+# │ DevOps │ Ops │
+# ╰────────┴─────╯
+
+subgraph "cluster/devops/ops" {
+label="Ops"
+
+"devops/ops/release" [label="Release"]
+"devops/ops/deploy" [label="Deploy"]
+"devops/ops/operate" [label="Operate"]
+"devops/ops/monitor" [label="Monitor"]
+
+}
+
+"devops/ops/release" -> "devops/ops/deploy" -> "devops/ops/operate" -> "devops/ops/monitor" -> "devops/ops/deploy"
+
+# ╭────────╮
+# │ DevOps │
+# ╰────────╯
+
+"devops/dev/test" -> "devops/ops/release"
+"devops/ops/monitor" -> "devops/dev/plan"
+
+}
+
+edge [color="#FF0000"]
+node [fillcolor="#303030"]
+
+# ╭─────╮
+# │ DNS │
+# ╰─────╯
+
+subgraph "cluster/dns" {
+label="Domains"
+
+# ╭─────┬─────╮
+# │ DNS │ RWX │
+# ╰─────┴─────╯
+
+subgraph "cluster/dns/rwx" {
+label="rwx.work"
+URL="https://rwx.work"
+
+"dns/rwx/blog" [
+fontcolor="#8080FF"
+label="Blog"
+URL="https://blog.rwx.work"
+]
+
+"dns/rwx/forge" [
+fontcolor="#8080FF"
+label="Forge"
+URL="https://forge.rwx.work"
+]
+
+"dns/rwx/ilos" [
+fontcolor="#8080FF"
+label="ILOS:\nIncremental Live\nOperating System"
+URL="https://ilos.rwx.work"
+]
+
+subgraph "cluster/dns/rwx/lsgm" {
+label="LSGM:\nLive Scan Grub Menu"
+URL="https://lsgm.rwx.work"
+
+"dns/rwx/lsgm/python" [label="Python"]
+"dns/rwx/lsgm/shell" [label="Shell"]
+
+}
+
+"dns/rwx/ofsp" [
+fontcolor="#8080FF"
+label="OFSP:\nOperating File\nSystem Profile"
+URL="https://ofsp.rwx.work"
+]
+
+"dns/rwx/prj" [
+fontcolor="#8080FF"
+label="PRJ:\nPRJ"
+URL="https://prj.rwx.work"
+]
+
+"dns/rwx/rtfd" [
+fontcolor="#8080FF"
+label="RTFD:\nRead The\nFancy Docs"
+URL="https://rtfd.rwx.work"
+]
+
+subgraph "cluster/dns/rwx/rwx" {
+label="RWX:\nRead Write eXecute"
+URL="https://rwx.rwx.work"
+
+"dns/rwx/rwx/python" [label="Python"]
+"dns/rwx/rwx/shell" [label="Shell"]
+
+}
+
+"dns/rwx/spcd" [
+fontcolor="#8080FF"
+label="SPCD:\nShell to Python\nContinuous Deployment"
+URL="https://spcd.rwx.work"
+]
+
+"dns/rwx/srmp" [
+fontcolor="#8080FF"
+label="SRMP:\nSoftware Repositories\nMirror Profile"
+URL="https://srmp.rwx.work"
+]
+
+"dns/rwx/todo" [
+fontcolor="#8080FF"
+label="TODO:\nTO\nDO"
+URL="https://todo.rwx.work"
+]
+
+}
+
+# ╭─────┬─────┬───────╮
+# │ DNS │ RWX │ Forge │
+# ╰─────┴─────┴───────╯
+
+"dns/rwx/forge/marc" [
+fontcolor="#8080FF"
+label="Marc"
+URL="https://forge.rwx.work/marc.beninca"
+]
+"dns/rwx/forge/marc" -> "dns/rwx/forge"
+
+# ╭─────┬─────┬──────╮
+# │ DNS │ RWX │ OFSP │
+# ╰─────┴─────┴──────╯
+
+{
+"dns/rwx/ofsp/python" [label="Python"]
+"dns/rwx/ofsp/shell" [label="Shell"]
+} -> "dns/rwx/ofsp"
+
+# ╭─────┬─────┬──────╮
+# │ DNS │ RWX │ RTFD │
+# ╰─────┴─────┴──────╯
+
+{
+"dns/rwx/rtfd/forgejo" [label="Forgejo"]
+} -> "dns/rwx/rtfd"
+
+# ╭─────┬─────┬─────┬────────╮
+# │ DNS │ RWX │ RWX │ Python │
+# ╰─────┴─────┴─────┴────────╯
+{
+"dns/rwx/rwx/python/codium" [label="Codium"]
+"dns/rwx/rwx/python/ffmpeg" [label="FFMPEG"]
+"dns/rwx/rwx/python/freetube" [label="FreeTube"]
+"dns/rwx/rwx/python/gource" [label="Gource"]
+"dns/rwx/rwx/python/logo" [label="Logo"]
+"dns/rwx/rwx/python/venvs" [label="Build VEnvs"]
+} -> "dns/rwx/rwx/python"
+# ╭─────┬─────┬─────┬───────╮
+# │ DNS │ RWX │ RWX │ Shell │
+# ╰─────┴─────┴─────┴───────╯
+{
+"dns/rwx/rwx/shell/cs" [label="CryptSetup"]
+"dns/rwx/rwx/shell/ffmpeg" [label="FFMPEG"]
+"dns/rwx/rwx/shell/git" [label="Git"]
+"dns/rwx/rwx/shell/venv" [label="Use VEnv"]
+} -> "dns/rwx/rwx/shell"
+
+# ╭─────┬─────┬──────╮
+# │ DNS │ RWX │ SRMP │
+# ╰─────┴─────┴──────╯
+{
+"dns/rwx/srmp/alma" [label="Alma"]
+"dns/rwx/srmp/debian" [label="Debian"]
+"dns/rwx/srmp/docker" [label="Docker"]
+"dns/rwx/srmp/msys" [label="MSys"]
+"dns/rwx/srmp/pypi" [label="PyPI"]
+"dns/rwx/srmp/python" [label="Python"]
+} -> "dns/rwx/srmp"
+
+# ╭─────┬─────┬──────┬────────╮
+# │ DNS │ RWX │ SRMP │ Debian │
+# ╰─────┴─────┴──────┴────────╯
+{
+"dns/rwx/srmp/debian/codium" [label="Codium"]
+"dns/rwx/srmp/debian/incus" [label="Incus"]
+} -> "dns/rwx/srmp/debian"
+
+# ╭─────┬─────┬──────╮
+# │ DNS │ RWX │ TODO │
+# ╰─────┴─────┴──────╯
+{
+"dns/rwx/todo/name" [label="Name"]
+"dns/rwx/todo/subdomain" [label="Subdomain"]
+} -> "dns/rwx/todo"
+
+}
+
+}
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..2c784a4
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,49 @@
+# Track Ongoing DevOps
+
+A graph to track things to do.
+
+---
+
+## Why
+
+Dependencies between tasks of projects.
+
+---
+
+## How
+
+A tree to identify leafs.
+
+---
+
+## What
+
+Generate:
+
+* [X] SVG with GraphViz
+* [X] HTML including SVG
+
+---
+
+## Authors
+
+* [Marc Beninca](https://marc.beninca.link)
+
+---
+
+## Where
+
+### Chat
+
+* [Discord](https://discord.com/channels/983145051985154108/1315476519325274112)
+* [IRC](ircs://irc.libera.chat/#todo)
+
+### Forge
+
+* [Repository](https://forge.rwx.work/rwx.work/todo)
+* [RSS](https://forge.rwx.work/rwx.work/todo.rss)
+* [Workflows](https://forge.rwx.work/rwx.work/todo/actions)
+
+### Deployment
+
+* [Site](https://todo.rwx.work)