Files
werkbaum/README.md
T
mhoennigandClaude Opus 4.8 6836352e84 deploy: „fertig" wird erst beim Deploy „in Produktion" (D30)
Der mitgelieferte Werkbaum-Plan behauptete [^] für Funktionen, die nur auf der
automatisch deployten Pages-Instanz lagen, nicht auf werkbaum.javagil.de
(manueller Deploy, D16). Ausgerechnet das Dokument, das den Stand beschreiben
soll, war ungenau — und „Was ist neu?" (D28) meldete Dinge als live, die es
dort nicht waren.

Die Unterscheidung gibt es längst: SPEC §4 trennt [x] fertig von [^] in
Produktion. Der Plan hat sie für sich selbst nie benutzt. Konvention ab jetzt:
beim Mergen [x], der Deploy befördert — nur er weiß, wann die Aussage wahr wird.

- scripts/promote-shipped.sh schreibt Statusboxen am Zeilenanfang von [x] auf
  [^] und hält das als eigenen Commit fest (-n zeigt nur, -y ohne Rückfrage).
  Bricht ab, wenn die Plandatei uncommittete Änderungen hat; committet nur
  diesen einen Pfad; pusht nicht.
- deploy-prod.sh ruft es als Schritt 0 auf (--no-promote schaltet es ab) und
  warnt, wenn HEAD noch nicht auf origin liegt — der Footer-Versionslink zeigt
  sonst auf einen Commit, den GitHub nicht kennt.

Warum ein Commit und kein Rewrite beim Bauen: Ein Rewrite macht GENAU EINE
Installation ehrlich; Pages untertriebe dauerhaft und die Neu-Anzeige wäre dort
für immer stumm. Der Commit wird von beiden Pipelines gesehen (Pages beim Push,
prod beim rsync), das Artefakt bleibt inhaltsgleich mit dem Repo — die
vorhandenen sed-Regeln (D16) fassen nur Pfade und Version an, Infrastruktur,
kein Rewrite dessen, was das Dokument aussagt. Außerdem Präzedenzfall D16:
VERSION per bewusstem Bump-Commit, „vollständig aus dem Repo reproduzierbar".

Einmalige Nachholung, exakt statt geschätzt: Der Footer der stabilen Instanz
verlinkt den deployten Commit (4061362); alles danach ist dort nicht drin. Es
sind GENAU ZWEI Knoten — „Optional nodes" (D29) und „Show what is new since
your last visit" (D28) —, nicht das Dutzend, das ich vorher grob geschätzt
hatte. Beide stehen jetzt auf [x] und leuchten beim nächsten Prod-Deploy als
neu auf. Eine Demotion [^]→[x] löst kein Falschleuchten aus: freshProdSet
meldet nur Knoten, die JETZT [^] sind (test-abgedeckt).

Umfang: nur example-werkbaum.werkbaum. Die übrigen Beispieldateien sind
erfunden und sagen nichts über ein Deployment aus.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 12:38:21 +02:00

222 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<p>
<img src="docs/brand/logo.svg" width="72" alt="Werkbaum logo">
</p>
# Werkbaum
**English** · [Deutsch](README.de.md)
**▶ Try it live: <https://werkbaum.javagil.de>** (stable) · <https://mhoennig.github.io/werkbaum/> (latest build 🚧)
A textual, Markdown-like notation for work breakdown structures with
and/or decomposition — plus a live editor that renders it as a diagram.
```
[~] Werkbaum (XL) https://wiki.example.de/relaunch
- [~] Document store
| [x] Text file with copy+paste in the frontend (S)
- [x] Parser
- [x] Text input field in the frontend
| [ ] Backend
- [~] Display/rendering (XL)
- [/] H (S) @anna
- [ ] CMS integration (M)
| [ ] WordPress
| [?] Headless CMS
```
`-` = mandatory sub-package (all of, side by side in the diagram) ·
`|` = alternative (any of, stacked) · `[…]` = status ·
`(M)` = T-shirt effort · `@name` = responsibility · `%%` = comment.
## Usage
![Werkbaum editor: live diagram on top, text notation below, with status colours, T-shirt sizes, tags and export buttons](docs/screenshot.png)
Open the [hosted editor](https://werkbaum.javagil.de) — edit text on
the left, the diagram is built live on the right. Toggles: transposed (narrow)
layout, show discarded elements.
### Jumping between diagram and text
Diagram and editor are linked in both directions:
- **Alt+click a node** (keyboard: **Alt+Enter**, touch: **long press**) selects
its line in the text editor — collapsed editor panel opens first.
- **Moving the cursor in the text** highlights the matching node in the diagram.
A plain click keeps its old meaning: a node carrying a URL still opens it.
### Loading a diagram from a URL
The editor can pull its notation text from an external text file via the
`sourceUrl` query parameter — handy for sharing a plan or keeping the source in
Git or a wiki:
```
https://mhoennig.github.io/werkbaum/?sourceUrl=https://raw.githubusercontent.com/mhoennig/werkbaum/main/docs/examples/example-plan-0.werkbaum
```
Ready-made examples in [`docs/examples/`](docs/examples/) — **open them one
after another**, each becomes its own document, so afterwards you can switch
between all of them in the editor title bar:
| Example | Shows |
|---|---|
| **▶ [0 · Online shop relaunch](https://mhoennig.github.io/werkbaum/?sourceUrl=https://raw.githubusercontent.com/mhoennig/werkbaum/main/docs/examples/example-plan-0.werkbaum)** | a software project with all eight states |
| **▶ [1 · New kitchen](https://mhoennig.github.io/werkbaum/?sourceUrl=https://raw.githubusercontent.com/mhoennig/werkbaum/main/docs/examples/example-plan-1.werkbaum)** | a non-software plan, lots of alternatives — good for the cheapest-path toggle |
| **▶ [2 · Community conference](https://mhoennig.github.io/werkbaum/?sourceUrl=https://raw.githubusercontent.com/mhoennig/werkbaum/main/docs/examples/example-plan-2.werkbaum)** | a wide plan with many people; compare horizontal vs. compact |
| **▶ [3 · Three workstreams](https://mhoennig.github.io/werkbaum/?sourceUrl=https://raw.githubusercontent.com/mhoennig/werkbaum/main/docs/examples/example-plan-3.werkbaum)** | several roots = several trees side by side |
| **▶ [Werkbaum itself](https://mhoennig.github.io/werkbaum/?sourceUrl=https://raw.githubusercontent.com/mhoennig/werkbaum/main/docs/examples/example-werkbaum.werkbaum)** | what exists today and where it could go |
(The links point at the latest build 🚧; the stable instance supports
`sourceUrl` from its next production deploy on.)
The loaded text becomes its own document whose **name is the URL**, so your own
documents stay untouched; the same link updates that one document instead of
piling up copies. The URL is the source of truth — it is re-fetched on every
load, so local edits to it do not survive a reload.
Notation files use the extension **`.werkbaum`** (UTF-8; see `docs/SPEC.md` §12
and D24) — a convention, not a contract: `sourceUrl` reads any text file over
http(s) regardless of extension or content type.
**Caveat — CORS:** the browser only fetches a foreign host if it sends
`Access-Control-Allow-Origin`. `raw.githubusercontent.com` and GitLab raw links
do; an arbitrary web server often does not. If loading fails the previous
content stays and a warning explains why. Only `http`/`https` are allowed.
### Running it locally
The editor source now lives as ES modules under `frontend/src/`, bundled by
[Vite](https://vitejs.dev/) (see `docs/DECISIONS.md` D19). Because browsers block
ES-module imports over `file://`, opening `frontend/index.html` directly no
longer works — use one of:
```bash
cd frontend
npm install # once
npm run dev # dev server at http://localhost:8137
npm test # Vitest unit tests
npm run build # -> frontend/dist/index.html (single self-contained file)
```
The built `dist/index.html` inlines all JS, CSS and the favicon, so **that** file
does open standalone via `file://` and is what gets deployed.
### Build hint & your own production install
Non-production builds carry a small hint next to the title (symbol + tooltip) so
it's clear this is **not** the stable instance:
- **Dev server** (`npm run dev`) → 🔧 "Preview local development build"
- **Default build** (`npm run build`, incl. the GitHub Pages deploy) → 🚧
"Latest build may still be buggy"
For **your own production install** the hint is switched off:
```bash
cd frontend
npm ci # or: npm install
npm run build:prod # -> frontend/dist/index.html WITHOUT the hint
```
`build:prod` runs Vite in mode `prod`; `frontend/.env.prod` sets
`VITE_BUILD_BADGE=none`, so the badge code is tree-shaken away entirely (it isn't
even present in the output source). Drop the resulting `dist/index.html` onto your
web space/server (standalone, `file://`-capable). Details: `app.js`
(`mountBuildBadge`), `docs/DECISIONS.md` D16.
Two things otherwise handled only by the Pages workflow, to fix up yourself when
self-hosting: the footer **MIT-License** link is relative to `../LICENSE` (place
that file one level above `index.html`, or adjust the link), and the **version
number** stays the source placeholder `1.0` (the workflow otherwise replaces it
from `VERSION` + commit count).
**Easier: `scripts/deploy-prod.sh`.** The script runs exactly that prod build
**and** both fix-ups (drop `LICENSE` alongside + straighten the link, footer
version + commit link just like the Pages workflow) and mirrors the result to a
server via rsync/SSH:
```bash
scripts/deploy-prod.sh mih00@mih00.hostsharing.net:~/doms/werkbaum.javagil.de/htdocs-ssl
```
The target is either this argument or — with no argument — the `DEPLOY_TARGET`
variable from the **git-ignored** file `.env` (template:
`.env.example`, copy it once and fill in the path). An argument
takes precedence.
Without `-y` it first shows a `--dry-run` preview and asks for confirmation.
`rsync --delete` ensures **nothing old** is left at the target — so the target
directory is treated as exclusive to Werkbaum (an in-flight Let's Encrypt
challenge under `.well-known/` is spared via `--filter=protect`, and web-friendly
755/644 permissions are enforced). (Hostsharing: a **directly-served** domain is
served from `…/htdocs-ssl/`; as a **subdomain** under another domain the web
directory would be `…/subs-ssl/<name>/`.)
## Project documents
- `frontend/` — editor · `backend/` — Kotlin/Spring (scaffold to follow, see backend/README.md)
- `docs/SPEC.md` — normative language definition
- `docs/DECISIONS.md` — design decisions with rationale
- `docs/ROADMAP.md` — Mermaid plugin, Taiga integration, Tenzu
- `docs/TASKS.md` — open tasks (checkboxes)
- `docs/brand/BRAND.md` — logo, wordmark, usage rules
- `docs/design/` — design derivation of the brand
- `CLAUDE.md` — project context for Claude Code
> **Note:** The detailed project documentation under `docs/` is maintained in
> German, the project's source language (see `CLAUDE.md`). This README is
> available in [English](README.md) and [German](README.de.md).
## Deployment
The editor is published as a static page on **GitHub Pages** via GitHub
Actions (workflow: `.github/workflows/pages.yml`). Triggered on every push to
`main` and manually (`workflow_dispatch`).
The workflow sets up Node, runs `npm ci`, `npm test` (Vitest) and `npm run build`
(Vite), then publishes the bundled `frontend/dist/index.html` as `index.html` at
the root URL, plus `LICENSE` for the MIT link in the footer. The favicon is
already inlined into the build, so nothing else needs copying; only the runtime
`../LICENSE` link is straightened on the copy. A failing test blocks the deploy.
`backend/` and the remaining `docs/` are not published.
While assembling the site, the workflow also stamps the version into the footer:
**major.minor** comes from the `VERSION` file (bumped by an explicit "bump
commit"), and the **micro** part is the number of commits since that last bump —
so it grows with every commit and resets to `0` right after a bump
(`Werkbaum 1.0.0`, `1.0.1`, … then bump `VERSION` to `1.1``1.1.0`). Nothing is
written back to the repo. In the footer the name **Werkbaum** links to the
repository, while the **version number** links to that exact commit
(`…/commit/<sha>`). Opened locally, the editor shows the source placeholder
(`Werkbaum 1.0`).
**One-time setup:** In the repo settings under **Pages**, select **Source** =
"GitHub Actions". The repo must be **public** for this (GitHub Pages via Actions
is only available for private repos on a paid plan).
### Stable instance
`scripts/deploy-prod.sh` mirrors a badge-free production build to a server over
SSH (target in `.env`, template `.env.example`). Unlike Pages this is a
**deliberate** step, so it is also the moment a feature actually goes live.
The script therefore starts by running `scripts/promote-shipped.sh`, which turns
`[x]` (done) into `[^]` (in production) in `docs/examples/example-werkbaum.werkbaum`
— the shipped plan describing Werkbaum itself — and records that as its own
commit. The convention is: mark a finished feature `[x]` when it is merged and
let the deploy promote it. That keeps the plan honest on both instances and
keeps the "what's new" highlighting meaningful. Skip it with `--no-promote`; see
[docs/DECISIONS.md](docs/DECISIONS.md) D30.
The commit is **not** pushed automatically — run `git push` afterwards, or the
footer version link points at a commit GitHub does not know yet.
## License
MIT — see [LICENSE](LICENSE). © 2026 Michael Hönnig. The bundled IBM Plex fonts
are under the SIL Open Font License 1.1 (see [LICENSE](LICENSE) and
`frontend/src/fonts/OFL.txt`).