Compare commits

..
Author SHA1 Message Date
stefankoelle a3829f1c48 Fix README: architecture diagram shows dist/moonweb/ instead of dist/ 2026-09-11 14:55:21 +02:00
stefankoelle b202efaefc Add start-dev.sh: launches all 3 dev servers in parallel
8081 (moonweb), 8086 (stefankoelle), 8087 (timecapsule)
2026-09-11 14:42:15 +02:00
stefankoelle 2e9f9a2395 Update timecapsule card: 'moonweb.org 2001' with clearer description 2026-09-11 14:39:51 +02:00
stefankoelle 8e54383b5a Rename hub to home in impressum and stefankoelle nav
- impressum.njk: (hub, smarthome, ...) -> (home, smarthome, ...)
- stefankoelle/_includes/base.njk: nav link 'hub' -> 'home'
2026-09-11 14:24:40 +02:00
stefankoelle 19f492b7e0 Fix stefankoelle build: .eleventyignore blocks standalone build
- build:stefankoelle now temporarily renames .eleventyignore during build
- build-pdf.sh: restore .eleventyignore rename trick
- The root eleventy build ignores stefankoelle/ (uses shared/_includes
  which lacks stefankoelle.njk layout), so the standalone build must
  bypass the ignore file
2026-09-11 14:20:52 +02:00
stefankoelle a5b4a20895 Separate build outputs: moonweb -> dist/moonweb/, stefankoelle -> dist/stefankoelle/
- eleventy.config.js: output to dist/moonweb/ (was dist/)
- build-deploy-moonweb.yml: deploy from dist/moonweb/
- package.json: timecapsule copies to dist/moonweb/timecapsule/
- Rename prebuild -> prebuild:cv to prevent npm lifecycle hook from
  running before build (build-pdf.sh was contaminating dist/ with
  stefankoelle output)
2026-09-11 14:17:30 +02:00
stefankoelle 9ffbadb3db Update all documentation for consolidated www.moonweb.org structure
- AGENTS.md: new file structure, single config, correct commands
- README.md: updated architecture, project structure, CI/CD docs
- SPEC.md: updated sitemap, design system, repository structure, tech stack
- PLAN.md: completed migration phases, remaining items
- TODO.md: current status, completed tasks, remaining items
2026-09-11 14:07:05 +02:00
stefankoelle 01097ff89a Update stefankoelle link texts: replace old subdomain names with new paths
infra.moonweb.org → moonweb.org/infra, etc.
2026-09-11 14:00:10 +02:00
stefankoelle 79a47ceeaa Fix double-slash URLs in stefankoelle, remove unused theme CSS
- stefankoelle/index.njk: fix 15+ double-slash URLs (e.g. /infra//docker/)
- stefankoelle/index.njk: fix /network/ link to /timecapsule/network/
- Delete unused shared/theme-{infra,smarthome,code,retro}.css (accent
  colors now inlined via base.njk)
2026-09-11 13:56:05 +02:00
stefankoelle 26ec966b51 Add missing beginning subpage redirects: news, report, sitemap
These 3 pages existed under www.moonweb.org/beginning/ and need
redirects to /timecapsule/beginning/.
2026-09-11 13:46:42 +02:00
stefankoelle 09a170d5bf Remove redundant 404 pages, keep only root 404
IONOS serves the root 404.html for all paths. Updated link text
from 'Back to hub' to 'Back to home'.
2026-09-11 13:39:50 +02:00
stefankoelle 4ebd767cd1 Rename hub link to home in site-switcher nav 2026-09-11 13:34:09 +02:00
stefankoelle 9a1d1ebbfe Fix header: show moonweb.org/smarthome instead of smarthome.moonweb.org 2026-09-11 13:30:10 +02:00
stefankoelle 7843d0061a Fix favicons: use section-specific favicon.svg per site
Add <link rel="icon"> tag pointing to /favicon.svg for hub and
/{section}/favicon.svg for all other sections. Previously browsers
defaulted to root favicon (hub moon emoji) on all pages.
2026-09-11 13:25:01 +02:00
stefankoelle ecbda171a6 Fix code repos: move repos.json to root _data/ for Eleventy 3
Eleventy 3 only loads global data from inputDir/_data/, not from
subdirectory _data/ dirs. Moved code/_data/repos.json to _data/repos.json
and updated the GitHub aggregator output path.
2026-09-11 13:07:06 +02:00
stefankoelle 5b70c7df2f Fix card links on index pages: add section prefix to local hrefs
Links like /proxmox/ were missing the section prefix (e.g. /infra/proxmox/)
since all sites now share a single Eleventy build at root.
2026-09-11 13:00:57 +02:00
Stefan Koelle 177142fcf5 Merge pull request #3 from skoelle/feature/consolidate-www
Feature/consolidate www
2026-09-11 12:54:33 +02:00
33 changed files with 417 additions and 414 deletions
+8 -8
View File
@@ -43,15 +43,15 @@ jobs:
- name: Validate build output - name: Validate build output
run: | run: |
echo "Build output:" echo "Build output:"
find dist -maxdepth 2 -type f | sort | head -40 find dist/moonweb -maxdepth 2 -type f | sort | head -40
echo "..." echo "..."
echo "Total files:" echo "Total files:"
find dist -type f | wc -l find dist/moonweb -type f | wc -l
# Verify key directories exist # Verify key directories exist
for dir in "" infra smarthome code retro timecapsule; do for dir in "" infra smarthome code retro timecapsule; do
if [ -n "$dir" ] && [ ! -d "dist/$dir" ]; then if [ -n "$dir" ] && [ ! -d "dist/moonweb/$dir" ]; then
echo "Error: dist/$dir not found" echo "Error: dist/moonweb/$dir not found"
exit 1 exit 1
fi fi
done done
@@ -60,7 +60,7 @@ jobs:
uses: actions/upload-artifact@v7 uses: actions/upload-artifact@v7
with: with:
name: dist-moonweb name: dist-moonweb
path: dist/ path: dist/moonweb
retention-days: 7 retention-days: 7
deploy: deploy:
@@ -73,12 +73,12 @@ jobs:
uses: actions/download-artifact@v8 uses: actions/download-artifact@v8
with: with:
name: dist-moonweb name: dist-moonweb
path: dist/ path: dist/moonweb
- name: Deploy via SFTP - name: Deploy via SFTP
uses: wlixcc/SFTP-Deploy-Action@v1.2.6 uses: wlixcc/SFTP-Deploy-Action@v1.2.6
with: with:
local_path: './dist/*' local_path: './dist/moonweb/*'
server: ${{ secrets.IONOS_SFTP_HOST }} server: ${{ secrets.IONOS_SFTP_HOST }}
username: ${{ secrets.IONOS_SFTP_USER }} username: ${{ secrets.IONOS_SFTP_USER }}
password: ${{ secrets.IONOS_SFTP_PASSWORD }} password: ${{ secrets.IONOS_SFTP_PASSWORD }}
@@ -99,7 +99,7 @@ jobs:
if [ "${{ needs.deploy.result }}" = "success" ]; then if [ "${{ needs.deploy.result }}" = "success" ]; then
echo "moonweb.org deployed successfully!" >> $GITHUB_STEP_SUMMARY echo "moonweb.org deployed successfully!" >> $GITHUB_STEP_SUMMARY
else else
echo "Deployment failed. Check the deploy jobs for details." >> $GITHUB_STEP_SUMMARY echo "Deployment failed. Check the deploy job for details." >> $GITHUB_STEP_SUMMARY
fi fi
echo "" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY
echo "### Sites" >> $GITHUB_STEP_SUMMARY echo "### Sites" >> $GITHUB_STEP_SUMMARY
+28 -27
View File
@@ -30,12 +30,11 @@ Monorepo fuer 6 statische Websites unter www.moonweb.org + stefankoelle.de, basi
``` ```
moonweb-site/ moonweb-site/
├── hub/ # Eleventy-Config + index.njk ├── hub/ # Index + Redirects (.htm) + impressum.njk
├── infra/ # Eleventy-Config + index.njk + 8 Subseiten ├── infra/ # Index.njk + 8 Subseiten
├── smarthome/ # Eleventy-Config + index.njk + 9 Subseiten ├── smarthome/ # Index.njk + 9 Subseiten
├── code/ # Eleventy-Config + index.njk ├── code/ # Index.njk
│ └── _data/repos.json ├── retro/ # Index.njk + 13 Subseiten
├── retro/ # Eleventy-Config + index.njk + 13 Subseiten
├── timecapsule/ # Eleventy 2.x (eigene Config) ├── timecapsule/ # Eleventy 2.x (eigene Config)
│ ├── eleventy.config.js │ ├── eleventy.config.js
│ ├── package.json │ ├── package.json
@@ -53,15 +52,20 @@ moonweb-site/
├── shared/ # Gemeinsame Komponenten ├── shared/ # Gemeinsame Komponenten
│ ├── _includes/ │ ├── _includes/
│ │ ├── base.njk # Basis-Layout (Header, Site-Switcher, Footer) │ │ ├── base.njk # Basis-Layout (Header, Site-Switcher, Footer)
│ │ ── card-grid.njk # Card-Grid Template │ │ ── card-grid.njk # Card-Grid Template
├── base.css │ └── sitemap.njk # Zentrale Sitemap
── theme-*.css ── base.css # Shared CSS (Layout, Cards, Typografie)
│ └── favicon/ # Favicon-SVGs pro Section
├── _data/
│ └── repos.json # GitHub-Aggregator Output
├── scripts/ ├── scripts/
│ ├── github-aggregator/ │ ├── github-aggregator/ # Python: liest .moonweb.yml -> repos.json
│ └── merge-moonweb.sh # Merge-Skript fuer Deployment │ └── cloudflare/ # Redirect-Setup fuer alte Subdomains
├── .github/workflows/ ├── .github/workflows/
│ ├── build-deploy-moonweb.yml # CI/CD: IONOS SFTP (www.moonweb.org) │ ├── build-deploy-moonweb.yml # CI/CD: IONOS SFTP (www.moonweb.org)
│ └── deploy-stefankoelle.yml # CI/CD: IONOS SFTP (stefankoelle.de) │ └── deploy-stefankoelle.yml # CI/CD: IONOS SFTP (stefankoelle.de)
├── eleventy.config.js # Zentrale Eleventy-Config (alle moonweb Sites)
├── .eleventyignore # Schliesst stefankoelle/, timecapsule/ aus
├── DESIGN.md ├── DESIGN.md
├── SPEC.md ├── SPEC.md
├── PLAN.md ├── PLAN.md
@@ -72,10 +76,10 @@ moonweb-site/
## Technischer Stack ## Technischer Stack
- **SSG:** Eleventy (11ty) v3.1.6 (hub, infra, smarthome, code, retro) - **SSG:** Eleventy (11ty) v3.1.6 (hub, infra, smarthome, code, retro) - zentrale Config
- **SSG:** Eleventy v2.0.1 (timecapsule - retro 2001 Design) - **SSG:** Eleventy v2.0.1 (timecapsule - retro 2001 Design)
- **Templates:** Nunjucks (.njk) - **Templates:** Nunjucks (.njk)
- **CSS:** Variables-basiert mit Accent-Farben pro Site - **CSS:** Variables-basiert mit Accent-Farben (inlined in base.njk)
- **Deploy (moonweb):** IONOS SFTP - **Deploy (moonweb):** IONOS SFTP
- **Deploy (stefankoelle):** IONOS SFTP - **Deploy (stefankoelle):** IONOS SFTP
- **CI/CD:** GitHub Actions (2 Workflows) - **CI/CD:** GitHub Actions (2 Workflows)
@@ -85,24 +89,21 @@ moonweb-site/
```bash ```bash
npm install npm install
cd timecapsule && npm install # Timecapsule Dependencies cd timecapsule && npm install # Timecapsule Dependencies
npm run prebuild # Pre-Build Tasks (CV PDF generieren) npm run prebuild:cv # Pre-Build Tasks (CV PDF generieren)
npm run dev:hub # localhost:8081 npm run dev # Moonweb Sites (localhost:8081)
npm run dev:infra # localhost:8082 npm run dev:stefankoelle # stefankoelle.de (localhost:8086)
npm run dev:smarthome # localhost:8083 npm run dev:timecapsule # Timecapsule (localhost:8087)
npm run dev:code # localhost:8084 npm run build # Alle moonweb Sites
npm run dev:retro # localhost:8085 npm run build:stefankoelle # Nur stefankoelle
npm run dev:stefankoelle # localhost:8086 npm run build:timecapsule # Nur timecapsule
npm run dev:timecapsule # localhost:8087 npm run build:moonweb # Moonweb + Timecapsule (fuer Deployment)
npm run build # Alle Sites bauen
npm run build:moonweb # Nur moonweb Sites (ohne stefankoelle)
npm run merge:moonweb # Sites mergen fuer Deployment
``` ```
## Design-Prinzipien ## Design-Prinzipien
1. **Header konsistent** — Identischer Site-Switcher auf allen Home-Sites 1. **Header konsistent** — Identischer Site-Switcher auf allen Home-Sites
2. **Content flexibel** — Detailseiten duerfen eigenes Layout haben 2. **Content flexibel** — Detailseiten duerfen eigenes Layout haben
3. **Accent-Farben:** hub=#3b6ea5, infra=#99333A, smarthome=#1f8a8a, code=#3E5098, retro=#8a6d3b 3. **Accent-Farben:** hub=#3b6ea5, infra=#99333A, smarthome=#1f8a8a, code=#3E5098, retro=#8a6d3b (inlined in base.njk)
4. **Englisch** — Alle Sites komplett auf Englisch 4. **Englisch** — Alle Sites komplett auf Englisch
5. **Keine Analytics** — Keine Tracking-Tools 5. **Keine Analytics** — Keine Tracking-Tools
6. **Sensible Daten** — Infra-Content wird manuell redigiert (keine IPs, Keys, Passwoerter) 6. **Sensible Daten** — Infra-Content wird manuell redigiert (keine IPs, Keys, Passwoerter)
@@ -140,7 +141,7 @@ Das CV-PDF wird via WeasyPrint generiert:
```bash ```bash
npm run pdf:cv # Einzelnes PDF generieren npm run pdf:cv # Einzelnes PDF generieren
npm run prebuild # Alle Pre-Build Tasks (inkl. CV PDF) npm run prebuild:cv # Alle Pre-Build Tasks (inkl. CV PDF)
``` ```
Dateien: Dateien:
@@ -188,7 +189,7 @@ Benötigte Secrets:
## GitHub Aggregator ## GitHub Aggregator
Das Skript `scripts/github-aggregator/aggregate.py` liest aus jedem public Repo unter `skoelle` die `.moonweb.yml` und generiert `code/_data/repos.json`. Das Skript `scripts/github-aggregator/aggregate.py` liest aus jedem public Repo unter `skoelle` die `.moonweb.yml` und generiert `_data/repos.json`.
### .moonweb.yml Format ### .moonweb.yml Format
+57 -47
View File
@@ -1,64 +1,74 @@
# moonweb.org — Implementation Plan # moonweb.org — Implementation Plan
Companion to `SPEC.md`. Defines order of work. All sites (hub, infra, smarthome, code, retro, stefankoelle) launch **simultaneously** — no staged rollout by domain. Companion to `SPEC.md`. Documents the completed migration from separate subdomain sites to a unified `www.moonweb.org` subdirectory structure.
## Phase 0 — Repo & tooling setup ## Phase 0 — Repo & tooling setup
1. Create the `moonweb-site` monorepo (private until first launch, then can stay private since Pages deploys the built output, not the source). 1. Created the `moonweb-site` monorepo.
2. Initialize Eleventy project structure per `SPEC.md §10`. 2. Initialized Eleventy project structure per `SPEC.md §10`.
3. Set up `shared/layout-base.njk` (header + card-grid) and one `theme-*.css` per accent color (hub, infra, smarthome, code, retro). 3. Set up `shared/_includes/base.njk` (header + card-grid) with accent colors inlined.
4. Verify local dev server works per site (`npm run dev:<site>`) before any content work starts. 4. Verified local dev server works per site.
## Phase 1 — Content migration & authoring (per domain) ## Phase 1 — Content migration & authoring (per domain)
Work order within this phase is flexible since all domains launch together; suggested sequence based on how self-contained each domain's content is: 1. **code** — GitHub aggregator, `_data/repos.json`, overview page grouped by subcategory.
2. **smarthome** — overview + detail pages where content exists.
1. **code** — simplest case, no detail pages, no sensitive-data filtering needed. 3. **infra** — shallow overview with redaction pass (no IPs, keys, passwords).
- Add `.moonweb.yml` to each GitHub repo (see `SPEC.md §8`). 4. **retro** — minimal overview with WIP notices.
- Build the aggregator script, run it once, generate `code/_data/repos.json`. 5. **hub** — central index linking all sites, including redirect `.htm` files for old www.moonweb.org paths.
- Build the overview page grouped by subcategory (Automation & Sync, Dev-Tools, Web Apps, Firmware/Hardware, Misc). 6. **timecapsule** — integrated from moonweb-www, preserves original 2001 design under `/timecapsule/`.
2. **smarthome** — overview first, detail pages only where content already exists.
- Draft the overview: how the smart home is structured (buttons/control, sensors, calendar, weather, media).
- For each existing topic with enough material (HomematicIP/MQTT, Tasmota, LED-Matrix *reference only, no migration*, M5Stack/WT32SC01 dashboards, WetterAPI, AirPlay, OctoPi, TubeArchivist), decide case by case: enough content → detail page; too thin → mention in overview only, no placeholder.
- Translate source material to English during authoring (one-time AI pass per document, per `SPEC.md §7`).
3. **infra** — overview only, redaction pass required.
- Draft a shallow, structured overview: Proxmox/pve2, Synology, VLANs, Fritz!Box mesh, SSO, Docker hosting model, plus the "how I work" section (OpenClaw/OpenCode setup, dev workflow).
- Apply the redaction rule from `SPEC.md §6` while translating — strip IPs, keys, credentials, internal hostnames from every source document before it becomes public content.
- Skip detail pages unless a topic can be described without any sensitive detail.
4. **retro** — minimal effort, rudimentary only.
- One overview page listing what hardware exists.
- Add "work in progress" notices for anything that isn't ready — better an honest short page than none.
5. **hub** — build last within this phase since it links to all the others.
- One-line description + link per destination (infra, smarthome, code, retro, stefankoelle, and external links to www.moonweb.org, 28k8.moonweb.org).
## Phase 2 — CI/CD ## Phase 2 — CI/CD
1. Write `.github/workflows/build-deploy.yml`: builds all five sites in one job (or matrix), then deploys each output folder to its corresponding Cloudflare Pages project via `wrangler pages deploy`. 1. GitHub Actions workflow `build-deploy-moonweb.yml`: single Eleventy build for all moonweb sites + timecapsule build, deploy via IONOS SFTP.
2. Create five Cloudflare Pages projects (hub, infra, smarthome, code, retro), each bound to its target custom domain (DNS already on Cloudflare, no extra setup needed). 2. GitHub Actions workflow `deploy-stefankoelle.yml`: stefankoelle.de build, deploy via IONOS SFTP.
3. Do one full dry run per site locally before the first real deploy. 3. Cloudflare redirect rules for old subdomains (`scripts/cloudflare/`).
## Phase 3 — Launch ## Phase 3 — Consolidation to www.moonweb.org
1. Deploy all five sites simultaneously. All moonweb.org sites now live under `www.moonweb.org` as subdirectories:
2. Point the respective custom domains at their Pages projects.
3. Apex domain `moonweb.org` keeps redirecting to `www.moonweb.org` for now (no change in this launch).
4. Smoke-test cross-linking: hub → each site, site-switcher on infra/smarthome/code/retro, smarthome → external ledmatrix link, code cards → GitHub links.
## Phase 4 — Explicitly deferred (not part of this build) | URL | Content |
|-----|---------|
| `www.moonweb.org/` | Hub (root) |
| `www.moonweb.org/infra/` | Infrastructure |
| `www.moonweb.org/smarthome/` | Smart Home |
| `www.moonweb.org/code/` | Code catalog |
| `www.moonweb.org/retro/` | Retro hardware |
| `www.moonweb.org/timecapsule/` | 2000s time capsule |
| `www.moonweb.org/impressum/` | Legal notice |
- Deciding on 28k8.moonweb.org's future (stay separate vs. eventual monorepo inclusion). Cloudflare redirects forward old subdomains:
- Building any Perplexity-backchannel mechanism for reusing published site content in this project. - `hub.moonweb.org/*``www.moonweb.org/*`
- Redirecting the apex domain from `www.moonweb.org` to `hub.moonweb.org`. - `infra.moonweb.org/*` `www.moonweb.org/infra/*`
- Any analytics, "last updated" timestamps, or scheduled/automated content generation beyond the one-time GitHub aggregator run. - `smarthome.moonweb.org/*``www.moonweb.org/smarthome/*`
- `code.moonweb.org/*``www.moonweb.org/code/*`
- `retro.moonweb.org/*``www.moonweb.org/retro/*`
## Definition of done for this build ### Technical consolidation
- All sites live on their respective platforms: - Single `eleventy.config.js` at root with computed `pathPrefix` per section.
- hub, infra, smarthome, code, retro on Cloudflare Pages under their intended domains. - Shared `base.njk` layout with inlined accent colors (no per-site theme CSS).
- stefankoelle.de on IONOS via SFTP deployment. - Central `_data/repos.json` (moved from `code/_data/`).
- code.moonweb.org reflects the current GitHub repos via the `.moonweb.yml` aggregator, grouped by subcategory. - Central sitemap (`shared/_includes/sitemap.njk`) with all 36 pages.
- smarthome.moonweb.org gives an accurate picture of what's running on the homelab today, with detail pages only where content already existed. - Single `robots.txt` at root.
- infra.moonweb.org describes the stack shallowly with zero sensitive data leaked. - `.eleventyignore` excludes `stefankoelle/` and `timecapsule/` (built separately).
- retro.moonweb.org exists with an honest, minimal overview (WIP notices allowed). - `build-pdf.sh` temporarily renames `.eleventyignore` for stefankoelle build.
- hub.moonweb.org correctly links everything, including the external sites (www.moonweb.org, 28k8.moonweb.org).
- stefankoelle.de is a working onepager with CV, Projects, Languages, Impressum, and the LED Matrix documentation sub-page. ## Definition of done — Achieved
- All sites live under `www.moonweb.org` as subdirectories, deployed via IONOS SFTP.
- `www.moonweb.org/code/` reflects the current GitHub repos via the `.moonweb.yml` aggregator.
- `www.moonweb.org/smarthome/` gives an accurate picture of what's running on the homelab.
- `www.moonweb.org/infra/` describes the stack shallowly with zero sensitive data leaked.
- `www.moonweb.org/retro/` exists with an honest, minimal overview.
- `www.moonweb.org/` correctly links everything.
- `stefankoelle.de` is a working onepager with CV, Projects, Languages, Impressum, and LED Matrix documentation.
- Old subdomains redirect via Cloudflare to new paths.
- Old www.moonweb.org content preserved under `/timecapsule/`.
## Remaining items
- Cloudflare redirect rules need activation (script ready, needs `CLOUDFLARE_API_TOKEN` and `CLOUDFLARE_ZONE_ID` secrets, or manual dashboard setup).
- Google Search Console: new property `www.moonweb.org` not yet created.
- `moonweb-www` repository not yet archived.
+58 -74
View File
@@ -21,21 +21,26 @@ stefankoelle.de -> CV, career, personal site (LED Matrix docs)
``` ```
+-------------------------------------------------------------------+ +-------------------------------------------------------------------+
| GitHub Actions CI | | GitHub Actions CI |
| +-----------+ +------------+ +-------------+ +---------+ +------+ | | +-------------------+ +---------------------+ |
| | build:hub | |build:infra | | build:smart | | build:... | | build:timecapsule | | | | build-deploy- | | deploy-stefankoelle | |
| +-----+-----+ +-----+------+ +------+------+ +----+----+ +----+----+ +--------+ | | | moonweb | | | |
| | | | | | | | | +--------+----------+ +----------+----------+ |
| v v v v v v | | | | |
| dist/hub/ dist/infra/ dist/smarthome/ dist/.../ dist/timecapsule/ | | v v |
+--------+---------------------------------------------------+--------------------+ | npm run build npm run build:stefankoelle |
| | | + build:timecapsule | |
v v | | | |
+------------------+ +------------------+ | v v |
| IONOS SFTP | | IONOS SFTP | | dist/moonweb/ dist/stefankoelle/ |
| (www.moonweb.org)| | (stefankoelle.de)| +-----------+------------------------+-------------------------------+
+--------+---------+ +--------+---------+ | |
v v v v
www.moonweb.org/* stefankoelle.de +------------------+ +------------------+
| IONOS SFTP | | IONOS SFTP |
| (www.moonweb.org)| | (stefankoelle.de)|
+--------+---------+ +--------+---------+
v v
www.moonweb.org/* stefankoelle.de
``` ```
--- ---
@@ -47,9 +52,9 @@ stefankoelle.de -> CV, career, personal site (LED Matrix docs)
| **SSG** | [Eleventy 3.1.6](https://www.11ty.dev/) | Markdown/YAML-first, minimal JS, `_data` folders map directly to aggregator output | | **SSG** | [Eleventy 3.1.6](https://www.11ty.dev/) | Markdown/YAML-first, minimal JS, `_data` folders map directly to aggregator output |
| **SSG (timecapsule)** | [Eleventy 2.0.1](https://www.11ty.dev/) | Legacy 2001 design, CommonJS config | | **SSG (timecapsule)** | [Eleventy 2.0.1](https://www.11ty.dev/) | Legacy 2001 design, CommonJS config |
| **Templates** | [Nunjucks](https://mozilla.github.io/nunjucks/) | Shared `base.njk` layout with site-switcher header, `card-grid.njk` for index pages | | **Templates** | [Nunjucks](https://mozilla.github.io/nunjucks/) | Shared `base.njk` layout with site-switcher header, `card-grid.njk` for index pages |
| **Styling** | Custom CSS (variables-based) | `base.css` for shared layout, `theme-*.css` per domain accent color | | **Styling** | Custom CSS (variables-based) | `base.css` for shared layout, accent colors inlined in `base.njk` |
| **Fonts** | [Lobster](https://fonts.google.com/specimen/Lobster) (Google Fonts) | Distinctive heading font across all sites | | **Fonts** | [Lobster](https://fonts.google.com/specimen/Lobster) (Google Fonts) | Distinctive heading font across all sites |
| **CI/CD** | [GitHub Actions](https://github.com/features/actions) | Matrix build for all sites, artifact upload, merge step, parallel deploy | | **CI/CD** | [GitHub Actions](https://github.com/features/actions) | Single build job, parallel SFTP deploy |
| **Deploy** | IONOS SFTP | Static hosting via SFTP upload | | **Deploy** | IONOS SFTP | Static hosting via SFTP upload |
| **DNS** | Cloudflare | DNS management + redirects from old subdomains | | **DNS** | Cloudflare | DNS management + redirects from old subdomains |
| **GitHub Catalog** | Python aggregator | Reads `.moonweb.yml` from each repo, outputs `repos.json` | | **GitHub Catalog** | Python aggregator | Reads `.moonweb.yml` from each repo, outputs `repos.json` |
@@ -63,27 +68,19 @@ stefankoelle.de -> CV, career, personal site (LED Matrix docs)
npm install # install Eleventy + deps npm install # install Eleventy + deps
cd timecapsule && npm install # timecapsule has own deps (Eleventy 2.x) cd timecapsule && npm install # timecapsule has own deps (Eleventy 2.x)
npm run dev:hub # http://localhost:8081 npm run dev # moonweb sites (localhost:8081)
npm run dev:infra # http://localhost:8082 npm run dev:stefankoelle # stefankoelle.de (localhost:8086)
npm run dev:smarthome # http://localhost:8083 npm run dev:timecapsule # timecapsule (localhost:8087)
npm run dev:code # http://localhost:8084
npm run dev:retro # http://localhost:8085
npm run dev:stefankoelle # http://localhost:8086
npm run dev:timecapsule # http://localhost:8087
npm run dev # all 7 in parallel
``` ```
Each site has its own minimal Eleventy config (`<site>/eleventy.config.js`). Live reload is built in.
### Build ### Build
```bash ```bash
npm run prebuild # pre-build tasks (CV PDF) npm run prebuild:cv # pre-build tasks (CV PDF)
npm run build # builds all sites npm run build # builds all moonweb sites (hub, infra, smarthome, code, retro)
npm run build:moonweb # builds moonweb sites only (excludes stefankoelle) npm run build:stefankoelle # builds stefankoelle.de
npm run build:hub # build single site npm run build:timecapsule # builds timecapsule
npm run merge:moonweb # merge all moonweb sites into dist/ for deployment npm run build:moonweb # builds moonweb + timecapsule (for deployment)
``` ```
--- ---
@@ -92,18 +89,10 @@ npm run merge:moonweb # merge all moonweb sites into dist/ for de
``` ```
moonweb-site/ moonweb-site/
├── hub/ # Central index & gateway ├── hub/ # Central index + redirect .htm files
├── infra/ # Infra overview + 8 detail pages ├── infra/ # Infra overview + 8 detail pages
│ ├── backup-strategy/
│ ├── monitoring/
│ ├── dev-environment/
│ └── ...
├── smarthome/ # Smart home overview + 9 detail pages ├── smarthome/ # Smart home overview + 9 detail pages
│ ├── homematic-mqtt/
│ ├── tasmota-energy/
│ └── ...
├── code/ # GitHub catalog ├── code/ # GitHub catalog
│ └── _data/repos.json # populated by the aggregator
├── retro/ # Retro hardware + 13 detail pages ├── retro/ # Retro hardware + 13 detail pages
├── timecapsule/ # 2000s retro design (Eleventy 2.x) ├── timecapsule/ # 2000s retro design (Eleventy 2.x)
│ ├── eleventy.config.js │ ├── eleventy.config.js
@@ -111,27 +100,32 @@ moonweb-site/
│ └── src/ │ └── src/
├── stefankoelle/ # CV, career, personal site ├── stefankoelle/ # CV, career, personal site
│ ├── eleventy.config.js │ ├── eleventy.config.js
│ ├── index.njk # Onepager (CV, Projects, Languages) │ ├── index.njk
│ ├── cv-print.njk # CV-only for PDF generation │ ├── cv-print.njk
│ ├── ledmatrix/ # LED Matrix WebServer documentation │ ├── ledmatrix/
│ └── assets/ # CSS, JS, images, favicons │ └── assets/
├── shared/ # Shared components ├── shared/ # Shared components
│ ├── _includes/ │ ├── _includes/
│ │ ├── base.njk # base layout (header, site-switcher, footer) │ │ ├── base.njk # base layout (header, site-switcher, footer)
│ │ ── card-grid.njk # card-grid template with emoji support │ │ ── card-grid.njk # card-grid template
├── base.css # shared CSS (layout, cards, typography) │ └── sitemap.njk # central sitemap template
── theme-*.css # accent colors per domain ── base.css # shared CSS
│ └── favicon/ # favicon SVGs per section
├── _data/
│ └── repos.json # populated by the GitHub aggregator
├── scripts/ ├── scripts/
│ ├── github-aggregator/ # Python: reads .moonweb.yml -> repos.json │ ├── github-aggregator/ # Python: reads .moonweb.yml -> repos.json
│ └── merge-moonweb.sh # Merge script for deployment │ └── cloudflare/ # redirect setup for old subdomains
├── .github/workflows/ ├── .github/workflows/
│ ├── build-deploy-moonweb.yml # CI/CD: build + deploy to IONOS SFTP │ ├── build-deploy-moonweb.yml # CI/CD: IONOS SFTP (www.moonweb.org)
│ └── deploy-stefankoelle.yml # CI/CD: stefankoelle.de to IONOS SFTP │ └── deploy-stefankoelle.yml # CI/CD: IONOS SFTP (stefankoelle.de)
├── DESIGN.md # Initial concept ├── eleventy.config.js # single config for all moonweb sites
├── SPEC.md # Full specification ├── .eleventyignore # excludes stefankoelle/, timecapsule/
├── PLAN.md # Implementation plan ├── DESIGN.md
├── TODO.md # Open items & workflow ├── SPEC.md
── package.json # npm scripts for dev/build ── PLAN.md
├── TODO.md
└── package.json
``` ```
--- ---
@@ -145,24 +139,12 @@ Defined in `.github/workflows/build-deploy-moonweb.yml`:
``` ```
push to main push to main
| |
+-- Build (matrix: hub, infra, smarthome, code, retro) +-- Build
| +-- checkout -> setup-node (22) -> npm ci | +-- checkout -> setup-node (22) -> npm ci
| +-- npm run build:<site> | +-- npm run build (all moonweb sites in one Eleventy run)
| +-- validate dist/<site>/ exists & non-empty
| +-- upload artifact (7-day retention)
|
+-- Build timecapsule
| +-- cd timecapsule && npm ci
| +-- npm run build:timecapsule | +-- npm run build:timecapsule
| +-- upload artifact
|
+-- Merge
| +-- download all artifacts
| +-- merge into dist/ (hub=root, others=subdirs)
| +-- upload merged artifact
| |
+-- Deploy +-- Deploy
+-- download merged artifact
+-- SFTP upload to IONOS /websites/moonweb/ +-- SFTP upload to IONOS /websites/moonweb/
``` ```
@@ -223,7 +205,7 @@ Cloudflare redirects forward old subdomains:
2. Reads `.moonweb.yml` from each repo root 2. Reads `.moonweb.yml` from each repo root
3. Filters for `category: code` entries 3. Filters for `category: code` entries
4. Sorts by subcategory + title 4. Sorts by subcategory + title
5. Writes combined result to `code/_data/repos.json` 5. Writes combined result to `_data/repos.json`
### `.moonweb.yml` schema ### `.moonweb.yml` schema
@@ -241,8 +223,9 @@ repo_url: "https://github.com/skoelle/mvg-departures"
### Manual run ### Manual run
```bash ```bash
export GITHUB_TOKEN=ghp_xxx python3 -m venv .venv
python scripts/github-aggregator/aggregate.py .venv/bin/pip install pyyaml
.venv/bin/python scripts/github-aggregator/aggregate.py
``` ```
--- ---
@@ -276,6 +259,7 @@ All moonweb sites are written **entirely in English**. The timecapsule uses the
| `PLAN.md` | Phased implementation plan | | `PLAN.md` | Phased implementation plan |
| `TODO.md` | Open items, workflow, and current status | | `TODO.md` | Open items, workflow, and current status |
| `README.md` | This file - project overview for GitHub | | `README.md` | This file - project overview for GitHub |
| `AGENTS.md` | AI agent instructions for this codebase |
--- ---
+86 -67
View File
@@ -1,63 +1,69 @@
# moonweb.org — Specification # moonweb.org — Specification
Status: Concept finalized. This document defines *what* gets built. See `PLAN.md` for *how and in what order*. Status: Migration complete. All sites live under `www.moonweb.org` as subdirectories, deployed via IONOS SFTP.
## 1. Purpose ## 1. Purpose
A personal homelab hub consisting of a central index (`hub`) and several themed static sites, replacing the current unstructured presentation of infrastructure, smart home projects, and GitHub repos. cv (stefankoelle.de) remains external, linked from the hub and site-switcher. A personal homelab hub consisting of a central index (`hub` at root) and several themed static sites, all served under `www.moonweb.org` as subdirectories. The old timecapsule content (2001 design) is preserved under `/timecapsule/`. cv (stefankoelle.de) remains external, linked from the hub and site-switcher.
## 2. Sitemap ## 2. Sitemap
``` ```
moonweb-site (monorepo) moonweb-site (monorepo)
├── hub/ → hub.moonweb.org Central index & gateway ├── hub/ → www.moonweb.org/ Central index & gateway
├── infra/ → infra.moonweb.org System architecture / stack overview ├── infra/ → www.moonweb.org/infra/ System architecture / stack overview
├── smarthome/ → smarthome.moonweb.org What the homelab actually runs, and why ├── smarthome/ → www.moonweb.org/smarthome/ What the homelab actually runs, and why
├── code/ → code.moonweb.org Curated GitHub catalog ├── code/ → www.moonweb.org/code/ Curated GitHub catalog
├── retro/ → retro.moonweb.org Physical retro hardware collection ├── retro/ → www.moonweb.org/retro/ Physical retro hardware collection
── stefankoelle/→ stefankoelle.de CV, career, personal site (SFTP deploy) ── timecapsule/ www.moonweb.org/timecapsule/ 2001-era internet time capsule
└── stefankoelle/→ stefankoelle.de CV, career, personal site (SFTP deploy)
outside the monorepo, untouched: outside the monorepo, untouched:
├── www.moonweb.org finished, no overlap (2001-style internet time capsule) ├── 28k8.moonweb.org 90s BBS/scene archive
├── 28k8.moonweb.org 90s BBS/scene archive, separate approach, may migrate later (undecided) ├── buildbroken.moonweb.org .NET Open Space blog archive
``` ```
Apex domain `moonweb.org` currently redirects to `www.moonweb.org`. This stays as-is for now; a later redirect to `hub.moonweb.org` is possible but out of scope for this build. Old subdomain redirects (via Cloudflare):
- `hub.moonweb.org/*``www.moonweb.org/*`
- `infra.moonweb.org/*``www.moonweb.org/infra/*`
- `smarthome.moonweb.org/*``www.moonweb.org/smarthome/*`
- `code.moonweb.org/*``www.moonweb.org/code/*`
- `retro.moonweb.org/*``www.moonweb.org/retro/*`
## 3. Domain purposes ## 3. Domain purposes
| Domain | Purpose | Tone | | Domain | URL | Purpose | Tone |
|---|---|---| |---|---|---|---|
| hub | Gateway, links to everything, one-line description per destination | Minimal | | hub | `/` | Gateway, links to everything, one-line description per destination | Minimal |
| infra | Shallow, structured overview of the stack: Proxmox (PVE + pve2), Synology DS918+, VLANs, Fritz!Box mesh, SSO, plus how I work (OpenCode/OpenClaw dev environment) | Reference, high-level only | | infra | `/infra/` | Shallow, structured overview of the stack: Proxmox, Synology, VLANs, Docker hosting, dev environment | Reference, high-level only |
| smarthome | Why the homelab exists — what's actually running on the homelab as smart home: sensors, automation, calendar/contacts sync, dashboards, media | Project storytelling | | smarthome | `/smarthome/` | Why the homelab exists — sensors, automation, calendar/contacts sync, dashboards, media | Project storytelling |
| code | Curated, sorted GitHub catalog — overview only, always linking out to GitHub | Portfolio | | code | `/code/` | Curated, sorted GitHub catalog — overview only, always linking out to GitHub | Portfolio |
| retro | Physical retro hardware collection (not software/demos — that's 28k8's domain) | Simple, factual | | retro | `/retro/` | Physical retro hardware collection (not software/demos — that's 28k8's domain) | Simple, factual |
| timecapsule | `/timecapsule/` | Original www.moonweb.org content from 2001, preserved as-is | Retro 2001 design |
## 4. Design system ## 4. Design system
### 4.1 Header-consistent, content-flexible principle ### 4.1 Header-consistent, content-flexible principle
- **Header is identical** across infra/smarthome/code/retro: site-switcher (hub · infra · smarthome · code · retro), domain accent color, consistent branding. - **Header is identical** across all sites: site-switcher (home · infra · smarthome · code · retro · cv), section title (`moonweb.org` or `moonweb.org/smarthome`), domain accent color.
- **Overview (index) pages** use a shared card-grid layout (reference: clean card-grid layout with banner header, grouped card sections, sans-serif, generous whitespace, light theme only, no heavy JS). - **Overview (index) pages** use a shared card-grid layout (clean card-grid with banner header, grouped card sections, sans-serif, generous whitespace, light theme only, no heavy JS).
- **Detail/sub-pages** keep the same header but may use a freer layout below it (reference: `/ledmatrix/` on stefankoelle.de today — pin tables, API docs, photos in free layout instead of a rigid card grid). - **Detail/sub-pages** keep the same header but may use a freer layout below it.
Note: stefankoelle.de is now part of the monorepo but uses its own independent design — it does not follow this header-consistent principle. Note: stefankoelle.de uses its own independent design — it does not follow this header-consistent principle.
### 4.2 Accent colors per domain ### 4.2 Accent colors per domain
| Domain | Accent | | Domain | Accent | Implementation |
|---|---| |---|---|---|
| hub | Neutral blue | | hub | Neutral blue (#3b6ea5) | Inlined `<style>` in base.njk |
| infra | Grey-blue | | infra | Red (#99333A) | Inlined `<style>` in base.njk |
| smarthome | Teal | | smarthome | Teal (#1f8a8a) | Inlined `<style>` in base.njk |
| code | Violet | | code | Violet (#3E5098) | Inlined `<style>` in base.njk |
| retro | Own accent, still clean card-grid (no 90s styling — that belongs to 28k8) | | retro | Brown (#8a6d3b) | Inlined `<style>` in base.njk |
### 4.3 URL convention ### 4.3 URL convention
`domain/slug/` — lowercase, hyphenated, trailing slash, matching the existing stefankoelle.de pattern (e.g. `/ledmatrix/`) so future detail pages stay consistent even if content later migrates between sites. `/section/slug/` — lowercase, hyphenated, trailing slash. All sites share a single Eleventy build with computed `pathPrefix` per section.
## 5. Content depth rules (per domain) ## 5. Content depth rules (per domain)
@@ -77,20 +83,20 @@ Because infra must stay shallow and public-safe:
- **Allowed:** architecture level — Proxmox + Synology + Docker host, VLAN concept without concrete internal IP plans, which service types run, which tools are used. - **Allowed:** architecture level — Proxmox + Synology + Docker host, VLAN concept without concrete internal IP plans, which service types run, which tools are used.
- **Not allowed:** concrete IP addresses, WireGuard keys/preshared keys, passwords, internal hostnames that allow inference, backup targets with credentials. - **Not allowed:** concrete IP addresses, WireGuard keys/preshared keys, passwords, internal hostnames that allow inference, backup targets with credentials.
This rule applies to any domain but is most relevant for infra, since the source documents (e.g. Heimnetzwerk-Final-v3.2, GL_Flint2_Final_v2) currently contain real IPs and keys that must be actively stripped during migration. This rule applies to any domain but is most relevant for infra, since the source documents currently contain real IPs and keys that must be actively stripped during migration.
## 7. Language ## 7. Language
All sites in the monorepo are written **entirely in English**. Existing German source documents are translated once during migration via a single AI-assisted pass — not a recurring process. New `.moonweb.yml` metadata and generated content are authored in English from the start. All sites in the monorepo are written **entirely in English**. Existing German source documents are translated once during migration via a single AI-assisted pass — not a recurring process. New `.moonweb.yml` metadata and generated content are authored in English from the start.
## 8. GitHub automation (code.moonweb.org) ## 8. GitHub automation (www.moonweb.org/code/)
Each GitHub project repo gets a `.moonweb.yml` in its root: Each GitHub project repo gets a `.moonweb.yml` in its root:
```yaml ```yaml
title: "MVG Departures" title: "MVG Departures"
category: code # code | smarthome | infra category: code # code | smarthome | infra
subcategory: "Web Apps" # drives grouping on code.moonweb.org subcategory: "Web Apps" # drives grouping on www.moonweb.org/code/
status: active status: active
stack: [Python, FastAPI] stack: [Python, FastAPI]
hosted_on: "Docker Host Debian (PVE)" hosted_on: "Docker Host Debian (PVE)"
@@ -98,7 +104,7 @@ summary: "Compact MVG/S-Bahn departure monitor with configurable stations."
repo_url: "https://github.com/skoelle/mvg-departures" repo_url: "https://github.com/skoelle/mvg-departures"
``` ```
A local aggregator script reads `.moonweb.yml` from all repos via the GitHub API, an AI pass turns the raw YAML into readable card copy, and the result is committed into `code/_data/repos.json` inside the monorepo. This runs manually, on demand — no scheduled automation for now. A local aggregator script reads `.moonweb.yml` from all repos via the GitHub API, and the result is committed into `_data/repos.json` inside the monorepo. This runs manually, on demand — no scheduled automation for now.
## 9. Content maintenance ## 9. Content maintenance
@@ -112,47 +118,60 @@ A local aggregator script reads `.moonweb.yml` from all repos via the GitHub API
``` ```
moonweb-site/ moonweb-site/
├── hub/ ├── hub/ # Index + Redirects (.htm) + impressum.njk
├── infra/ ├── infra/ # Index.njk + 8 Subseiten
├── smarthome/ ├── smarthome/ # Index.njk + 9 Subseiten
├── code/ ├── code/ # Index.njk
│ └── _data/repos.json # populated by the GitHub aggregator ├── retro/ # Index.njk + 13 Subseiten
├── retro/ ├── timecapsule/ # Eleventy 2.x (eigene Config)
├── stefankoelle/ # CV, career, personal site
│ ├── eleventy.config.js │ ├── eleventy.config.js
│ ├── index.njk # Onepager (CV, Projects, Languages) │ ├── package.json
── cv-print.njk # CV-only for PDF generation ── src/
│ ├── ledmatrix/ # LED Matrix WebServer documentation ├── stefankoelle/ # Eleventy-Config + Onepager
── assets/ # CSS, JS, images, favicons ── eleventy.config.js
├── shared/ │ ├── index.njk
│ ├── cv-print.njk
│ ├── ledmatrix/
│ └── assets/
├── shared/ # Shared components
│ ├── _includes/ │ ├── _includes/
│ │ ├── base.njk # shared header + footer layout │ │ ├── base.njk # base layout (header, site-switcher, footer)
│ │ ── card-grid.njk # card-grid template │ │ ── card-grid.njk # card-grid template
├── base.css # shared CSS variables and layout │ └── sitemap.njk # central sitemap template
── theme-*.css # one accent color file per domain ── base.css # shared CSS
│ └── favicon/ # favicon SVGs per section
├── _data/
│ └── repos.json # populated by the GitHub aggregator
├── scripts/ ├── scripts/
── github-aggregator/ # reads .moonweb.yml from all repos ── github-aggregator/ # reads .moonweb.yml from all repos
├── DESIGN.md # initial concept and design decisions │ └── cloudflare/ # redirect setup for old subdomains
├── SPEC.md # what gets built (this document) ├── .github/workflows/
├── PLAN.md # how and in what order │ ├── build-deploy-moonweb.yml # builds all moonweb sites, deploys to IONOS SFTP
├── TODO.md # open items and workflow │ └── deploy-stefankoelle.yml # builds stefankoelle, deploys via IONOS SFTP
── .github/workflows/ ── eleventy.config.js # single Eleventy config for all moonweb sites
├── build-deploy.yml # builds all sites, deploys to Cloudflare Pages ├── .eleventyignore # excludes stefankoelle/, timecapsule/
└── deploy-stefankoelle.yml # builds stefankoelle, deploys via IONOS SFTP ├── DESIGN.md
├── SPEC.md
├── PLAN.md
├── TODO.md
└── package.json
``` ```
## 11. Technical stack ## 11. Technical stack
- **Static site generator:** Eleventy (11ty) — markdown/YAML-first, minimal JS, `_data` folders map directly onto the `.moonweb.yml` aggregator output, low maintenance for five sites at this scale. - **Static site generator:** Eleventy (11ty) v3.1.6 — single config at root, computed `pathPrefix` per section, per-section collections.
- **Static site generator (timecapsule):** Eleventy v2.0.1 — separate config, preserves original 2001 design.
- **Templates:** Nunjucks (.njk) — shared `base.njk` layout, `card-grid.njk` for index pages, `sitemap.njk` for central sitemap.
- **Styling:** Custom CSS (`base.css`) with accent colors inlined as `<style>` in `base.njk`. No per-site theme CSS files.
- **Build:** entirely in GitHub Actions. - **Build:** entirely in GitHub Actions.
- **Deploy:** Cloudflare Pages — five separate Pages projects (one per public domain: hub, infra, smarthome, code, retro), since Cloudflare Pages binds one custom-domain set per project. stefankoelle.de deploys via IONOS SFTP. Two GitHub Actions workflows handle deployment. - **Deploy:** IONOS SFTP — all sites deployed to `/websites/moonweb/`, stefankoelle.de to `/websites/stefankoelle/`.
- **Runtime:** fully static, no server-side code, no containers for the website itself (distinct from the actual homelab services running on the Docker host). - **DNS:** Cloudflare — DNS management + redirects from old subdomains (hub.moonweb.org, etc.).
- **DNS:** already on Cloudflare — no additional setup step needed for Pages custom domains. - **Runtime:** fully static, no server-side code, no containers for the website itself.
- **Local preview:** Eleventy's built-in dev server with live reload, run per-site (`npm run dev:<site>`) before any commit. - **Local preview:** Eleventy's built-in dev server with live reload (`npm run dev` for all moonweb sites, `npm run dev:stefankoelle`, `npm run dev:timecapsule`).
## 12. Explicitly out of scope for this build ## 12. Explicitly out of scope
- Migrating 28k8.moonweb.org into the monorepo — undecided, revisit later, likely never. - Migrating 28k8.moonweb.org into the monorepo — undecided, revisit later, likely never.
- Any Perplexity-backchannel mechanism (website content reusable inside this project) — deferred, no time invested now. - Any Perplexity-backchannel mechanism — deferred.
- Analytics of any kind. - Analytics of any kind.
- Automated content generation/translation pipelines beyond the one-time GitHub aggregator for code and the one-time translation pass during migration. - Automated content generation/translation pipelines beyond the one-time GitHub aggregator for code.
+61 -72
View File
@@ -1,87 +1,76 @@
# TODO: Consolidation zu www.moonweb.org # TODO: moonweb-site
## Uebersicht ## Status: Consolidation Complete
Alle moonweb.org Sites (hub, infra, smarthome, code, retro, timecapsule) unter `www.moonweb.org` als Subverzeichnisse vereinen. Deployment von Cloudflare Pages zu IONOS SFTP migrieren. All moonweb.org sites are consolidated under `www.moonweb.org` as subdirectories, deployed via IONOS SFTP. PR #3 merged to main.
**URL-Struktur nach Migration:**
| URL | Inhalt |
|-----|--------|
| `www.moonweb.org/` | Hub (neue Root) |
| `www.moonweb.org/infra/` | Infra |
| `www.moonweb.org/smarthome/` | Smarthome |
| `www.moonweb.org/code/` | Code |
| `www.moonweb.org/retro/` | Retro |
| `www.moonweb.org/timecapsule/` | Altes www (2001-Retro) |
| `stefankoelle.de/` | CV (bleibt separat) |
--- ---
## Phase 1: Timecapsule in Monorepo integrieren ## Completed
- [x] 1.1 Dateien aus ../moonweb-www/src/ nach timecapsule/src/ kopieren ### Phase 1: Timecapsule Integration
- [x] 1.2 timecapsule/eleventy.config.js erstellen (Eleventy 2.x) - [x] Copy files from moonweb-www/src/ to timecapsule/src/
- [x] 1.3 timecapsule/package.json erstellen (eigene Dependencies) - [x] Create timecapsule/eleventy.config.js (Eleventy 2.x)
- [x] 1.4 timecapsule/src/_data/site.json anpassen (Domain mit /timecapsule/) - [x] Create timecapsule/package.json (own dependencies)
- [x] 1.5 Alle internen Pfade mit /timecapsule/ prefixieren - [x] Adapt timecapsule internal paths with /timecapsule/ prefix
- [x] 1.6 Passthrough Copy in eleventy.config.js anpassen
- [x] 1.7 Build-Output pruefen (dist/timecapsule/)
## Phase 2: Eleventy-Configs aller Sites anpassen ### Phase 2: Single Eleventy Config
- [x] Create root eleventy.config.js with computed pathPrefix per section
- [x] Delete 5 per-site eleventy.config.js files (hub, infra, smarthome, code, retro)
- [x] Delete scripts/merge-moonweb.sh
- [x] Update shared/_includes/base.njk (inlined accent colors, root CSS path)
- [x] Update hub/index.njk card hrefs (relative paths)
- [x] Update hub/impressum.njk (hosting sections correct)
- [x] Update parent values in detail pages to include section prefix
- [x] Add tags to all pages for Eleventy collections
- [x] 2.1 hub/eleventy.config.js: site.url auf www.moonweb.org ### Phase 3: Build & Deploy
- [x] 2.2 infra/eleventy.config.js: site.url auf www.moonweb.org - [x] Create .github/workflows/build-deploy-moonweb.yml (single build job, SFTP deploy)
- [x] 2.3 smarthome/eleventy.config.js: site.url auf www.moonweb.org - [x] Delete old build-deploy.yml (matrix builds)
- [x] 2.4 code/eleventy.config.js: site.url auf www.moonweb.org - [x] Update .eleventyignore (exclude stefankoelle/, timecapsule/, markdown)
- [x] 2.5 retro/eleventy.config.js: site.url auf www.moonweb.org - [x] Fix build-pdf.sh to temporarily rename .eleventyignore for stefankoelle build
- [x] 2.6 shared/_includes/base.njk anpassen - [x] Fix timecapsule build path (../dist/ not ../../dist/)
- [x] 2.7 hub/index.njk: Card-Hrefs relativieren
- [x] 2.8 hub/impressum.njk: Domain-Liste aktualisieren
## Phase 3: Build-System anpassen ### Phase 4: Redirects & SEO
- [x] Create 20 redirect .htm files in hub/ for old www.moonweb.org paths
- [x] Create central sitemap.xml (36 pages)
- [x] Create single robots.txt at root
- [x] Set up Cloudflare redirect rules script (scripts/cloudflare/)
- [x] 3.1 package.json: Neue Scripts fuer timecapsule + merge ### Phase 5: Bug Fixes
- [x] 3.2 scripts/merge-moonweb.sh erstellen - [x] Fix card links on index pages (add section prefix to local hrefs)
- [x] 3.3 Lokal Build testen (alle Sites) - [x] Fix code repos missing (move repos.json to root _data/)
- [x] Fix favicons (use section-specific favicon.svg per site)
- [x] Fix header (show moonweb.org/smarthome instead of smarthome.moonweb.org)
- [x] Rename hub link to home in site-switcher nav
- [x] Remove redundant 404 pages, keep only root 404
- [x] Add missing beginning subpage redirects (news, report, sitemap)
- [x] Fix double-slash URLs in stefankoelle/index.njk
- [x] Remove unused theme-*.css files
- [x] Update stefankoelle link texts (replace old subdomain names with new paths)
## Phase 4: Deployment umstellen ### Phase 6: Documentation
- [x] Update AGENTS.md for new structure
- [x] 4.1 Neuen Workflow .github/workflows/build-deploy-moonweb.yml erstellen - [x] Update README.md for new structure
- [x] 4.2 Alten Workflow .github/workflows/build-deploy.yml entfernen - [x] Update SPEC.md for new structure
- [ ] 4.3 Alten deploy-moonweb.yml in moonweb-www deaktivieren - [x] Update PLAN.md for new structure
## Phase 5: Cloudflare Redirects
- [x] 5.1 Redirect-Regeln einrichten (via GitHub Action)
| Quell-Domain | Ziel-URL | Type |
|-------------|----------|------|
| `hub.moonweb.org/*` | `https://www.moonweb.org/$1` | 301 |
| `infra.moonweb.org/*` | `https://www.moonweb.org/infra/$1` | 301 |
| `smarthome.moonweb.org/*` | `https://www.moonweb.org/smarthome/$1` | 301 |
| `code.moonweb.org/*` | `https://www.moonweb.org/code/$1` | 301 |
| `retro.moonweb.org/*` | `https://www.moonweb.org/retro/$1` | 301 |
**Umsetzung:** `scripts/cloudflare/setup-redirects.sh` + GitHub Action `cloudflare-redirects.yml`
**Benötigte Secrets:** `CLOUDFLARE_API_TOKEN`, `CLOUDFLARE_ZONE_ID`
## Phase 6: SEO
- [ ] 6.1 Google Search Console: Neue Property www.moonweb.org
- [ ] 6.2 Sitemap submiten
## Phase 7: Cleanup
- [ ] 7.1 moonweb-www Repository archivieren
- [ ] 7.2 Cloudflare Pages Projects loeschen (nach Redirect-Test)
--- ---
## Abgeschlossen ## Remaining
Alle Code-Aenderungen sind fertig. Nächste Schritte: ### Cloudflare Redirects
1. Commit auf feature/consolidate-www Branch - [ ] Activate redirect rules (needs `CLOUDFLARE_API_TOKEN` and `CLOUDFLARE_ZONE_ID` secrets, or manual dashboard setup)
2. Push und PR erstellen - [ ] Verify redirects work after activation
3. Deployen
4. Cloudflare Redirects einrichten ### SEO
5. Google Search Console aktualisieren - [ ] Create Google Search Console property for www.moonweb.org
- [ ] Submit sitemap
### Cleanup
- [ ] Archive moonweb-www repository
- [ ] Delete Cloudflare Pages projects (after redirect verification)
### Future
- [ ] Cross-linking stefankoelle.de <-> smarthome
- [ ] Consider moving LED Matrix to smarthome (when ready)
-13
View File
@@ -1,13 +0,0 @@
---
title: "Page Not Found"
section: "code"
tags: "code"
description: "The page you are looking for does not exist."
layout: base.njk
permalink: /code/404.html
---
<div class="error-page">
<h1>404</h1>
<p>The page you are looking for does not exist or has been moved.</p>
<a class="back-link" href="/">← Back to code</a>
</div>
+7 -1
View File
@@ -76,12 +76,18 @@ module.exports = function (eleventyConfig) {
[`hub/${dir}/index.htm`]: `${dir}/index.html`, [`hub/${dir}/index.htm`]: `${dir}/index.html`,
}); });
} }
const beginningSubpages = ["news", "report", "sitemap"];
for (const name of beginningSubpages) {
eleventyConfig.addPassthroughCopy({
[`hub/beginning/${name}.htm`]: `beginning/${name}.html`,
});
}
return { return {
dir: { dir: {
input: ".", input: ".",
includes: "shared/_includes", includes: "shared/_includes",
output: "dist", output: "dist/moonweb",
}, },
serverOptions: { serverOptions: {
host: "0.0.0.0", host: "0.0.0.0",
+1 -1
View File
@@ -9,5 +9,5 @@ permalink: /404.html
<div class="error-page"> <div class="error-page">
<h1>404</h1> <h1>404</h1>
<p>The page you are looking for does not exist or has been moved.</p> <p>The page you are looking for does not exist or has been moved.</p>
<a class="back-link" href="/">← Back to hub</a> <a class="back-link" href="/">← Back to home</a>
</div> </div>
+11
View File
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="refresh" content="0;url=/timecapsule/beginning/news.html">
<title>Redirecting...</title>
</head>
<body>
<p>Redirecting to <a href="/timecapsule/beginning/news.html">/timecapsule/beginning/news.html</a>...</p>
</body>
</html>
+11
View File
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="refresh" content="0;url=/timecapsule/beginning/report.html">
<title>Redirecting...</title>
</head>
<body>
<p>Redirecting to <a href="/timecapsule/beginning/report.html">/timecapsule/beginning/report.html</a>...</p>
</body>
</html>
+11
View File
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="refresh" content="0;url=/timecapsule/beginning/sitemap.html">
<title>Redirecting...</title>
</head>
<body>
<p>Redirecting to <a href="/timecapsule/beginning/sitemap.html">/timecapsule/beginning/sitemap.html</a>...</p>
</body>
</html>
+2 -2
View File
@@ -43,7 +43,7 @@ layout: base.njk
<h3>2. Purpose of these Websites</h3> <h3>2. Purpose of these Websites</h3>
<p> <p>
The moonweb.org websites (hub, smarthome, infra, code, retro, timecapsule) document my private home-lab, home-automation and retro-computing hobby projects. buildbroken.moonweb.org is an archive of a blog I created with friends in our spare time. 28k8.moonweb.org is a homage to the 90s era. stefankoelle.de presents my professional CV and background as the same person. All are part of one personal project network and share this legal notice and privacy policy. The moonweb.org websites (home, smarthome, infra, code, retro, timecapsule) document my private home-lab, home-automation and retro-computing hobby projects. buildbroken.moonweb.org is an archive of a blog I created with friends in our spare time. 28k8.moonweb.org is a homage to the 90s era. stefankoelle.de presents my professional CV and background as the same person. All are part of one personal project network and share this legal notice and privacy policy.
</p> </p>
<h3>3. Hosting</h3> <h3>3. Hosting</h3>
@@ -51,7 +51,7 @@ layout: base.njk
Two different hosting providers are used within this network: Two different hosting providers are used within this network:
</p> </p>
<h4>a) www.moonweb.org (hub, infra, smarthome, code, retro, timecapsule) &mdash; IONOS SE</h4> <h4>a) www.moonweb.org (home, infra, smarthome, code, retro, timecapsule) &mdash; IONOS SE</h4>
<p> <p>
Hosted on web space provided by IONOS SE, Elgendorfer Str. 57, 56410 Montabaur, Germany, acting as a processor under Art. 28 GDPR (Data Processing Agreement in place). Hosted on web space provided by IONOS SE, Elgendorfer Str. 57, 56410 Montabaur, Germany, acting as a processor under Art. 28 GDPR (Data Processing Agreement in place).
</p> </p>
+2 -2
View File
@@ -37,8 +37,8 @@ sections:
summary: "tHE tEMPLE BBS Mailbox and 90s releases archive." summary: "tHE tEMPLE BBS Mailbox and 90s releases archive."
href: "https://28k8.moonweb.org" href: "https://28k8.moonweb.org"
emoji: "💾" emoji: "💾"
- title: "www.moonweb.org" - title: "moonweb.org 2001"
summary: "The 2000s internet projects, networking and engineering." summary: "The original www.moonweb.org as it was in 2001 — preserved as a time capsule."
href: "/timecapsule/" href: "/timecapsule/"
emoji: "🌐" emoji: "🌐"
- title: "inseco.de" - title: "inseco.de"
-13
View File
@@ -1,13 +0,0 @@
---
title: "Page Not Found"
section: "infra"
tags: "infra"
description: "The page you are looking for does not exist."
layout: base.njk
permalink: /infra/404.html
---
<div class="error-page">
<h1>404</h1>
<p>The page you are looking for does not exist or has been moved.</p>
<a class="back-link" href="/">← Back to infra</a>
</div>
+8 -8
View File
@@ -9,30 +9,30 @@ sections:
cards: cards:
- title: "🖥️ Proxmox host (PVE)" - title: "🖥️ Proxmox host (PVE)"
summary: "Hosting environment for running production VMs and LXC containers for the homelab." summary: "Hosting environment for running production VMs and LXC containers for the homelab."
href: "/proxmox/" href: "/infra/proxmox/"
- title: "💾 Synology DS918+" - title: "💾 Synology DS918+"
summary: "NAS running Docker services and acting as the primary backup repository." summary: "NAS running Docker services and acting as the primary backup repository."
href: "/synology/" href: "/infra/synology/"
- title: "🐳 Docker VMs (Debian)" - title: "🐳 Docker VMs (Debian)"
summary: "Primary target for new Docker/Compose services, running the monitoring exporters." summary: "Primary target for new Docker/Compose services, running the monitoring exporters."
href: "/docker/" href: "/infra/docker/"
- title: "📦 LxC Container" - title: "📦 LxC Container"
summary: "Pi-hole, Ubuntu-Worker and MariaDB running on slim LxC Containers." summary: "Pi-hole, Ubuntu-Worker and MariaDB running on slim LxC Containers."
href: "/lxc/" href: "/infra/lxc/"
- heading: "Strategies & Setup-Guides" - heading: "Strategies & Setup-Guides"
cards: cards:
- title: "🔄 Backup strategy" - title: "🔄 Backup strategy"
summary: "Layered backup approach covering NAS user content and VM/LXC backups across multiple locations." summary: "Layered backup approach covering NAS user content and VM/LXC backups across multiple locations."
href: "/backup-strategy/" href: "/infra/backup-strategy/"
- title: "📊 Prometheus/Grafana" - title: "📊 Prometheus/Grafana"
summary: "Central metrics collection and dashboards for hosts, containers, and hardware." summary: "Central metrics collection and dashboards for hosts, containers, and hardware."
href: "/monitoring/" href: "/infra/monitoring/"
- title: "💻 Dev environment" - title: "💻 Dev environment"
summary: "A disposable, daily-backed-up Xubuntu VM for AI-assisted, remote development via SSH and Chrome Remote Desktop." summary: "A disposable, daily-backed-up Xubuntu VM for AI-assisted, remote development via SSH and Chrome Remote Desktop."
href: "/dev-environment/" href: "/infra/dev-environment/"
- title: "🌐 OpenWrt Multi-WAN" - title: "🌐 OpenWrt Multi-WAN"
summary: "Multi-WAN router with WiFi and Powerline failover, plus IoT VLAN 189 isolation." summary: "Multi-WAN router with WiFi and Powerline failover, plus IoT VLAN 189 isolation."
href: "/openwrt/" href: "/infra/openwrt/"
--- ---
<p class="site-intro">A peek under the hood of my homelab. Proxmox, Synology, Docker, and how everything is wired together.</p> <p class="site-intro">A peek under the hood of my homelab. Proxmox, Synology, Docker, and how everything is wired together.</p>
+3 -3
View File
@@ -8,11 +8,11 @@
"dev:stefankoelle": "npx @11ty/eleventy --config=stefankoelle/eleventy.config.js --serve --port=8086", "dev:stefankoelle": "npx @11ty/eleventy --config=stefankoelle/eleventy.config.js --serve --port=8086",
"dev:timecapsule": "cd timecapsule && npx @11ty/eleventy --serve --port=8087", "dev:timecapsule": "cd timecapsule && npx @11ty/eleventy --serve --port=8087",
"build": "npx @11ty/eleventy", "build": "npx @11ty/eleventy",
"build:stefankoelle": "npx @11ty/eleventy --config=stefankoelle/eleventy.config.js", "build:stefankoelle": "mv .eleventyignore .eleventyignore.bak && npx @11ty/eleventy --config=stefankoelle/eleventy.config.js; mv .eleventyignore.bak .eleventyignore 2>/dev/null; true",
"build:timecapsule": "cd timecapsule && npx @11ty/eleventy && mkdir -p ../dist/timecapsule && cp -r _site/timecapsule/* ../dist/timecapsule/", "build:timecapsule": "cd timecapsule && npx @11ty/eleventy && mkdir -p ../dist/moonweb/timecapsule && cp -r _site/timecapsule/* ../dist/moonweb/timecapsule/",
"build:moonweb": "npm run build && npm run build:timecapsule", "build:moonweb": "npm run build && npm run build:timecapsule",
"pdf:cv": "bash stefankoelle/pdf/build-pdf.sh", "pdf:cv": "bash stefankoelle/pdf/build-pdf.sh",
"prebuild": "bash prebuild.sh" "prebuild:cv": "bash prebuild.sh"
}, },
"devDependencies": { "devDependencies": {
"@11ty/eleventy": "^3.1.6" "@11ty/eleventy": "^3.1.6"
-13
View File
@@ -1,13 +0,0 @@
---
title: "Page Not Found"
section: "retro"
tags: "retro"
description: "The page you are looking for does not exist."
layout: base.njk
permalink: /retro/404.html
---
<div class="error-page">
<h1>404</h1>
<p>The page you are looking for does not exist or has been moved.</p>
<a class="back-link" href="/">← Back to retro</a>
</div>
+13 -13
View File
@@ -9,51 +9,51 @@ sections:
cards: cards:
- title: "🖥️ The Mega ST Fleet" - title: "🖥️ The Mega ST Fleet"
summary: "Three Mega ST 4 machines and a Mega ST 2, each with a clearly defined role from heirloom to workstation." summary: "Three Mega ST 4 machines and a Mega ST 2, each with a clearly defined role from heirloom to workstation."
href: "/atari-mega-st-fleet/" href: "/retro/atari-mega-st-fleet/"
- title: "⚡ ET4000 Experiment" - title: "⚡ ET4000 Experiment"
summary: "Why bolting a graphics card onto a Mega ST overloads a 1980s power supply, and what actually solved the resolution problem." summary: "Why bolting a graphics card onto a Mega ST overloads a 1980s power supply, and what actually solved the resolution problem."
href: "/et4000-experiment/" href: "/retro/et4000-experiment/"
- title: "📺 Monitor Compatibility" - title: "📺 Monitor Compatibility"
summary: "The 15kHz problem explained, and which modern monitor panels actually cooperate with Atari colour modes." summary: "The 15kHz problem explained, and which modern monitor panels actually cooperate with Atari colour modes."
href: "/atari-monitor-compatibility/" href: "/retro/atari-monitor-compatibility/"
- title: "🔌 Networking & BBS" - title: "🔌 Networking & BBS"
summary: "Getting an Atari ST online via STinG and Wi-Fi modem hardware, and dialing into classic bulletin board systems." summary: "Getting an Atari ST online via STinG and Wi-Fi modem hardware, and dialing into classic bulletin board systems."
href: "/atari-networking-bbs/" href: "/retro/atari-networking-bbs/"
- heading: "Amiga Corner" - heading: "Amiga Corner"
cards: cards:
- title: "💾 AmigaOS on Modern Platforms" - title: "💾 AmigaOS on Modern Platforms"
summary: "Running AmigaOS 3.2.3 on MiSTer FPGA versus Amiberry on a Raspberry Pi, and the HDF pitfalls to avoid." summary: "Running AmigaOS 3.2.3 on MiSTer FPGA versus Amiberry on a Raspberry Pi, and the HDF pitfalls to avoid."
href: "/amiga-modern-platforms/" href: "/retro/amiga-modern-platforms/"
- title: "🥧 The PiMiga Journey" - title: "🥧 The PiMiga Journey"
summary: "Three generations of the PiMiga distro compared, and why the newest release isn't automatically the best one." summary: "Three generations of the PiMiga distro compared, and why the newest release isn't automatically the best one."
href: "/pimiga-journey/" href: "/retro/pimiga-journey/"
- title: "⚔️ Vampire, A600GS or MiSTer" - title: "⚔️ Vampire, A600GS or MiSTer"
summary: "Why comparing modern Amiga hardware by benchmark numbers alone is actively misleading." summary: "Why comparing modern Amiga hardware by benchmark numbers alone is actively misleading."
href: "/amiga-hardware-landscape/" href: "/retro/amiga-hardware-landscape/"
- title: "📦 The A1200" - title: "📦 The A1200"
summary: "What's confirmed so far about Retro Games Ltd.'s upcoming Amiga 1200 console, ahead of its 2026 launch." summary: "What's confirmed so far about Retro Games Ltd.'s upcoming Amiga 1200 console, ahead of its 2026 launch."
href: "/the-a1200/" href: "/retro/the-a1200/"
- heading: "FPGA & Emulation" - heading: "FPGA & Emulation"
cards: cards:
- title: "🧩 MiST and MiSTer" - title: "🧩 MiST and MiSTer"
summary: "Two FPGA boards with two very different personalities, and why the newer one doesn't win every category." summary: "Two FPGA boards with two very different personalities, and why the newer one doesn't win every category."
href: "/mist-mister-fpga/" href: "/retro/mist-mister-fpga/"
- title: "🛋️ Batocera in the Living Room" - title: "🛋️ Batocera in the Living Room"
summary: "The couch-friendly, software-emulation counterpart to the FPGA rigs, covering everything from Atari ST to arcade." summary: "The couch-friendly, software-emulation counterpart to the FPGA rigs, covering everything from Atari ST to arcade."
href: "/batocera-living-room/" href: "/retro/batocera-living-room/"
- title: "🕹️ Mini Arcades & Handhelds" - title: "🕹️ Mini Arcades & Handhelds"
summary: "A buyer's guide to compact retro gaming devices, and how to spot a bootleg clone before you buy one." summary: "A buyer's guide to compact retro gaming devices, and how to spot a bootleg clone before you buy one."
href: "/mini-arcade-handheld-roundup/" href: "/retro/mini-arcade-handheld-roundup/"
- heading: "DOS & PC" - heading: "DOS & PC"
cards: cards:
- title: "💻 The 486 DX2-66" - title: "💻 The 486 DX2-66"
summary: "A complete DOS environment rebuilt 1:1 on MiSTer FPGA, down to the original AUTOEXEC.BAT." summary: "A complete DOS environment rebuilt 1:1 on MiSTer FPGA, down to the original AUTOEXEC.BAT."
href: "/dos-486-tower/" href: "/retro/dos-486-tower/"
- heading: "Overview" - heading: "Overview"
cards: cards:
- title: "🏠 The Retro Corner Today" - title: "🏠 The Retro Corner Today"
summary: "A room-by-room snapshot of every retro system currently active across the home." summary: "A room-by-room snapshot of every retro system currently active across the home."
href: "/retro-corner-snapshot/" href: "/retro/retro-corner-snapshot/"
--- ---
<p class="site-intro">Hardware I've collected and kept running over the years. From Atari ST and Amiga to MiSTer FPGA and DOS environments.</p> <p class="site-intro">Hardware I've collected and kept running over the years. From Atari ST and Amiga to MiSTer FPGA and DOS environments.</p>
+1 -1
View File
@@ -14,7 +14,7 @@ import urllib.request
GITHUB_USER = "skoelle" GITHUB_USER = "skoelle"
API_ROOT = "https://api.github.com" API_ROOT = "https://api.github.com"
OUTPUT_PATH = os.path.join( OUTPUT_PATH = os.path.join(
os.path.dirname(__file__), "..", "..", "code", "_data", "repos.json" os.path.dirname(__file__), "..", "..", "_data", "repos.json"
) )
+3 -2
View File
@@ -20,6 +20,7 @@
<link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Lobster&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Lobster&display=swap" rel="stylesheet">
<link rel="icon" href="{% if section and section != 'hub' %}/{{ section }}/favicon.svg{% else %}/favicon.svg{% endif %}">
<link rel="stylesheet" href="/shared-base.css"> <link rel="stylesheet" href="/shared-base.css">
<style>:root { --accent: {% if section == 'infra' %}#99333A{% elif section == 'smarthome' %}#1f8a8a{% elif section == 'code' %}#3E5098{% elif section == 'retro' %}#8a6d3b{% else %}#3b6ea5{% endif %}; }</style> <style>:root { --accent: {% if section == 'infra' %}#99333A{% elif section == 'smarthome' %}#1f8a8a{% elif section == 'code' %}#3E5098{% elif section == 'retro' %}#8a6d3b{% else %}#3b6ea5{% endif %}; }</style>
<script type="application/ld+json"> <script type="application/ld+json">
@@ -65,10 +66,10 @@
<body> <body>
<header class="site-header"> <header class="site-header">
<div class="site-banner"> <div class="site-banner">
<span class="site-title">{{ section }}.moonweb.org</span> <span class="site-title">moonweb.org{% if section and section != 'hub' %}/{{ section }}{% endif %}</span>
</div> </div>
<nav class="site-switcher"> <nav class="site-switcher">
<a href="/">hub</a> <a href="/">home</a>
<a href="/infra/">infra</a> <a href="/infra/">infra</a>
<a href="/smarthome/">smarthome</a> <a href="/smarthome/">smarthome</a>
<a href="/code/">code</a> <a href="/code/">code</a>
-1
View File
@@ -1 +0,0 @@
:root { --accent: #3E5098; }
-1
View File
@@ -1 +0,0 @@
:root { --accent: #99333A; }
-1
View File
@@ -1 +0,0 @@
:root { --accent: #8a6d3b; }
-1
View File
@@ -1 +0,0 @@
:root { --accent: #1f8a8a; }
-13
View File
@@ -1,13 +0,0 @@
---
title: "Page Not Found"
section: "smarthome"
tags: "smarthome"
description: "The page you are looking for does not exist."
layout: base.njk
permalink: /smarthome/404.html
---
<div class="error-page">
<h1>404</h1>
<p>The page you are looking for does not exist or has been moved.</p>
<a class="back-link" href="/">← Back to smarthome</a>
</div>
+9 -9
View File
@@ -9,19 +9,19 @@ sections:
cards: cards:
- title: "Home dashboard" - title: "Home dashboard"
summary: "Lighting, music, and Tasmota device control shown on the home dashboard." summary: "Lighting, music, and Tasmota device control shown on the home dashboard."
href: "/home-dashboard-controls/" href: "/smarthome/home-dashboard-controls/"
emoji: "🎛️" emoji: "🎛️"
- title: "Tasmota & energy monitoring" - title: "Tasmota & energy monitoring"
summary: "Smart plugs and power monitoring across the flat, feeding daily usage stats." summary: "Smart plugs and power monitoring across the flat, feeding daily usage stats."
href: "/tasmota-energy/" href: "/smarthome/tasmota-energy/"
emoji: "⚡" emoji: "⚡"
- title: "HomematicIP + MQTT" - title: "HomematicIP + MQTT"
summary: "How HomematicIP room sensors are bridged into MQTT and stored in InfluxDB." summary: "How HomematicIP room sensors are bridged into MQTT and stored in InfluxDB."
href: "/homematic-mqtt/" href: "/smarthome/homematic-mqtt/"
emoji: "📡" emoji: "📡"
- title: "Balkon Pi" - title: "Balkon Pi"
summary: "Balcony sensor, lighting, and audio automation unit." summary: "Balcony sensor, lighting, and audio automation unit."
href: "/balkonpi/" href: "/smarthome/balkonpi/"
emoji: "🌿" emoji: "🌿"
- heading: "Dashboards & Hardware" - heading: "Dashboards & Hardware"
cards: cards:
@@ -39,7 +39,7 @@ sections:
emoji: "🖥️" emoji: "🖥️"
- title: "Air quality dashboard" - title: "Air quality dashboard"
summary: "Real-time temperature and humidity monitoring across all rooms with historical charts." summary: "Real-time temperature and humidity monitoring across all rooms with historical charts."
href: "/air-quality/" href: "/smarthome/air-quality/"
emoji: "🌡️" emoji: "🌡️"
- heading: "Personal services" - heading: "Personal services"
cards: cards:
@@ -63,19 +63,19 @@ sections:
cards: cards:
- title: "AirPlay audio" - title: "AirPlay audio"
summary: "Multi-room AirPlay receivers with software volume boost." summary: "Multi-room AirPlay receivers with software volume boost."
href: "/airplay-audio/" href: "/smarthome/airplay-audio/"
emoji: "🔊" emoji: "🔊"
- title: "OctoPrint" - title: "OctoPrint"
summary: "Remote 3D printer control and camera streaming." summary: "Remote 3D printer control and camera streaming."
href: "/octoprint/" href: "/smarthome/octoprint/"
emoji: "🖨️" emoji: "🖨️"
- title: "YouTube archiving" - title: "YouTube archiving"
summary: "TubeArchivist and TubeSync for self-hosted YouTube downloading on the Synology." summary: "TubeArchivist and TubeSync for self-hosted YouTube downloading on the Synology."
href: "/tubearchivist/" href: "/smarthome/tubearchivist/"
emoji: "📺" emoji: "📺"
- title: "Kids RFID MP3 Player" - title: "Kids RFID MP3 Player"
summary: "Arduino-based audio player for kids using RFID cards, built as a custom alternative to Hoerbert." summary: "Arduino-based audio player for kids using RFID cards, built as a custom alternative to Hoerbert."
href: "/kids-rfid-player/" href: "/smarthome/kids-rfid-player/"
emoji: "🎵" emoji: "🎵"
--- ---
<p class="site-intro">The heart of the homelab. Home Assistant, MQTT sensors, dashboards, and automation projects that make everyday life a little more interesting.</p> <p class="site-intro">The heart of the homelab. Home Assistant, MQTT sensors, dashboards, and automation projects that make everyday life a little more interesting.</p>
Executable
+17
View File
@@ -0,0 +1,17 @@
#!/usr/bin/env bash
set -euo pipefail
cleanup() { kill $(jobs -p) 2>/dev/null; }
trap cleanup EXIT
echo "==> Starting moonweb dev servers..."
echo " http://localhost:8081 (moonweb sites)"
echo " http://localhost:8086 (stefankoelle.de)"
echo " http://localhost:8087 (timecapsule)"
echo ""
npx @11ty/eleventy --serve --port=8081 &
npx @11ty/eleventy --config=stefankoelle/eleventy.config.js --serve --port=8086 &
cd timecapsule && npx @11ty/eleventy --serve --port=8087 &
wait
+1 -1
View File
@@ -26,7 +26,7 @@
<span class="site-title">{{ siteTitle | default(section + ".moonweb.org") }}</span> <span class="site-title">{{ siteTitle | default(section + ".moonweb.org") }}</span>
</div> </div>
<nav class="site-switcher"> <nav class="site-switcher">
<a href="https://www.moonweb.org/">hub</a> <a href="https://www.moonweb.org/">home</a>
<a href="https://www.moonweb.org/infra/">infra</a> <a href="https://www.moonweb.org/infra/">infra</a>
<a href="https://www.moonweb.org/smarthome/">smarthome</a> <a href="https://www.moonweb.org/smarthome/">smarthome</a>
<a href="https://www.moonweb.org/code/">code</a> <a href="https://www.moonweb.org/code/">code</a>
+19 -19
View File
@@ -25,30 +25,30 @@ layout: stefankoelle.njk
<h3>moonweb.org (since 2020)</h3> <h3>moonweb.org (since 2020)</h3>
<p>My personal corner on the internet, documenting the homelab, smart home setups, infrastructure experiments, retro hardware, and the code that ties it all together. Everything runs on a homelab that has been evolving since the mid-90s.</p> <p>My personal corner on the internet, documenting the homelab, smart home setups, infrastructure experiments, retro hardware, and the code that ties it all together. Everything runs on a homelab that has been evolving since the mid-90s.</p>
<ul> <ul>
<li><b><a href="https://www.moonweb.org/">hub.moonweb.org</a></b>: Overview of all sites and projects.</li> <li><b><a href="https://www.moonweb.org/">moonweb.org</a></b>: Overview of all sites and projects.</li>
<li><b><a href="https://www.moonweb.org/infra/">infra.moonweb.org</a></b>: Proxmox cluster, Synology NAS, Docker containers, networking, and backup strategies.</li> <li><b><a href="https://www.moonweb.org/infra/">moonweb.org/infra</a></b>: Proxmox cluster, Synology NAS, Docker containers, networking, and backup strategies.</li>
<li><b><a href="https://www.moonweb.org/smarthome/">smarthome.moonweb.org</a></b>: Home Assistant, MQTT sensors, AirPlay audio, energy monitoring, and ESP32 dashboards.</li> <li><b><a href="https://www.moonweb.org/smarthome/">moonweb.org/smarthome</a></b>: Home Assistant, MQTT sensors, AirPlay audio, energy monitoring, and ESP32 dashboards.</li>
<li><b><a href="https://www.moonweb.org/code/">code.moonweb.org</a></b>: Curated catalog of public GitHub projects, sorted by topic.</li> <li><b><a href="https://www.moonweb.org/code/">moonweb.org/code</a></b>: Curated catalog of public GitHub projects, sorted by topic.</li>
<li><b><a href="https://www.moonweb.org/retro/">retro.moonweb.org</a></b>: Atari ST, Amiga, DOS, MiSTer FPGA, and the retro computing corner.</li> <li><b><a href="https://www.moonweb.org/retro/">moonweb.org/retro</a></b>: Atari ST, Amiga, DOS, MiSTer FPGA, and the retro computing corner.</li>
</ul> </ul>
<h3>Home Network Projects (2025-2026)</h3> <h3>Home Network Projects (2025-2026)</h3>
<ul> <ul>
<li><b>Docker Host (Proxmox PVE)</b><br>Virtualized Docker host with Debian 12.2 running containerized services including Portainer, Prometheus, Grafana, Gitea, monitoring exporters, and more. Full architecture documented on <a href="https://www.moonweb.org/infra//docker/">infra.moonweb.org</a>.</li> <li><b>Docker Host (Proxmox PVE)</b><br>Virtualized Docker host with Debian 12.2 running containerized services including Portainer, Prometheus, Grafana, Gitea, monitoring exporters, and more. Full architecture documented on <a href="https://www.moonweb.org/infra/docker/">moonweb.org/infra</a>.</li>
<li><b>InfluxDB Time-Series Integration</b><br>Deployed InfluxDB 2.x for sensor data collection from Tasmota smart plugs and HomematicIP thermostats, replacing older MySQL-based storage with modern time-series architecture.</li> <li><b>InfluxDB Time-Series Integration</b><br>Deployed InfluxDB 2.x for sensor data collection from Tasmota smart plugs and HomematicIP thermostats, replacing older MySQL-based storage with modern time-series architecture.</li>
<li><b>LED Matrix ESP32 InfluxDB Integration</b><br>Data persistence layer for <a href="/ledmatrix/">LED Matrix ESP32</a> sensor systems (DHT22 temperature/humidity) with InfluxDB 2.x backend. Automated collection at 60-second intervals for historical trend analysis.</li> <li><b>LED Matrix ESP32 InfluxDB Integration</b><br>Data persistence layer for <a href="/ledmatrix/">LED Matrix ESP32</a> sensor systems (DHT22 temperature/humidity) with InfluxDB 2.x backend. Automated collection at 60-second intervals for historical trend analysis.</li>
<li><b>Air Quality Dashboard</b><br>Dynamic HTML5 dashboard consuming real-time sensor data from InfluxDB via Flux query API. Displays temperature and humidity across all network locations, accessible via nginx reverse proxy. See also <a href="https://www.moonweb.org/smarthome//air-quality/">smarthome.moonweb.org</a>.</li> <li><b>Air Quality Dashboard</b><br>Dynamic HTML5 dashboard consuming real-time sensor data from InfluxDB via Flux query API. Displays temperature and humidity across all network locations, accessible via nginx reverse proxy. See also <a href="https://www.moonweb.org/smarthome/air-quality/">moonweb.org/smarthome</a>.</li>
<li><b>Tasmota Energy Monitoring</b><br>Smart plug energy tracking with 8 Tasmota-enabled devices, integrating MQTT data collection and visualization. See also <a href="https://www.moonweb.org/smarthome//tasmota-energy/">smarthome.moonweb.org</a>.</li> <li><b>Tasmota Energy Monitoring</b><br>Smart plug energy tracking with 8 Tasmota-enabled devices, integrating MQTT data collection and visualization. See also <a href="https://www.moonweb.org/smarthome/tasmota-energy/">moonweb.org/smarthome</a>.</li>
<li><b>Network Hardware & Monitoring</b><br>Four Zyxel GS1200-8HP managed switches in the server room, living room, and study, plus a <a href="https://www.moonweb.org/infra//openwrt/">Multi-WAN OpenWrt router</a> for failover and VLAN segmentation. All switches feed into <a href="https://www.moonweb.org/infra//monitoring/">Prometheus monitoring</a> via SNMP exporters, and IoT devices are isolated in VLAN 189.</li> <li><b>Network Hardware & Monitoring</b><br>Four Zyxel GS1200-8HP managed switches in the server room, living room, and study, plus a <a href="https://www.moonweb.org/infra/openwrt/">Multi-WAN OpenWrt router</a> for failover and VLAN segmentation. All switches feed into <a href="https://www.moonweb.org/infra/monitoring/">Prometheus monitoring</a> via SNMP exporters, and IoT devices are isolated in VLAN 189.</li>
</ul> </ul>
<h3>Retro Computing (2022/2023)</h3> <h3>Retro Computing (2022/2023)</h3>
<ul> <ul>
<li>MiSTer and MiST FPGA Systems for preservation (see also <a href="https://www.moonweb.org/retro//mist-mister-fpga/">retro.moonweb.org</a>).</li> <li>MiSTer and MiST FPGA Systems for preservation (see also <a href="https://www.moonweb.org/retro/mist-mister-fpga/">moonweb.org/retro</a>).</li>
<li><a href="https://www.moonweb.org/retro//dos-486-tower/">DOS System</a>, <a href="https://www.moonweb.org/retro//the-a1200/">Amiga System</a>, and <a href="https://www.moonweb.org/retro//atari-mega-st-fleet/">Atari ST System</a> with the environment from the early 90s.</li> <li><a href="https://www.moonweb.org/retro/dos-486-tower/">DOS System</a>, <a href="https://www.moonweb.org/retro/the-a1200/">Amiga System</a>, and <a href="https://www.moonweb.org/retro/atari-mega-st-fleet/">Atari ST System</a> with the environment from the early 90s.</li>
</ul> </ul>
<h3>Upgrade of old <a href="https://www.moonweb.org/retro//atari-mega-st-fleet/">Atari Mega 4</a> (2021)</h3> <h3>Upgrade of old <a href="https://www.moonweb.org/retro/atari-mega-st-fleet/">Atari Mega 4</a> (2021)</h3>
<ul> <ul>
<li>Gotek Drive</li> <li>Gotek Drive</li>
<li>More RAM</li> <li>More RAM</li>
@@ -67,10 +67,10 @@ layout: stefankoelle.njk
<h3>Various Docker Systems (since 2016)</h3> <h3>Various Docker Systems (since 2016)</h3>
<ul> <ul>
<li><b>Monitoring:</b> <a href="https://www.moonweb.org/infra//monitoring/">Prometheus, Grafana, InfluxDB</a>, cAdvisor, Node Exporter, SNMP exporters</li> <li><b>Monitoring:</b> <a href="https://www.moonweb.org/infra/monitoring/">Prometheus, Grafana, InfluxDB</a>, cAdvisor, Node Exporter, SNMP exporters</li>
<li><b>Smart Home:</b> Mosquitto MQTT broker, <a href="https://www.moonweb.org/smarthome//homematic-mqtt/">Home Assistant</a></li> <li><b>Smart Home:</b> Mosquitto MQTT broker, <a href="https://www.moonweb.org/smarthome/homematic-mqtt/">Home Assistant</a></li>
<li><b>Infrastructure:</b> Portainer, Nginx Proxy Manager, Authelia (SSO), Watchtower, Healthchecks</li> <li><b>Infrastructure:</b> Portainer, Nginx Proxy Manager, Authelia (SSO), Watchtower, Healthchecks</li>
<li><b>Applications:</b> Gitea (GitHub mirror), <a href="https://www.moonweb.org/infra//docker/">Stirling PDF</a>, <a href="https://www.moonweb.org/smarthome//tubearchivist/">TubeArchivist</a>, <a href="https://www.moonweb.org/smarthome//tubearchivist/">TubeSync</a>, <a href="https://www.moonweb.org/infra//docker/">SearXNG</a></li> <li><b>Applications:</b> Gitea (GitHub mirror), <a href="https://www.moonweb.org/infra/docker/">Stirling PDF</a>, <a href="https://www.moonweb.org/smarthome/tubearchivist/">TubeArchivist</a>, <a href="https://www.moonweb.org/smarthome/tubearchivist/">TubeSync</a>, <a href="https://www.moonweb.org/infra/docker/">SearXNG</a></li>
</ul> </ul>
<h3>Walk-on Song (2019)</h3> <h3>Walk-on Song (2019)</h3>
@@ -80,7 +80,7 @@ layout: stefankoelle.njk
<li>MP3 Module for playback on attached speaker.</li> <li>MP3 Module for playback on attached speaker.</li>
</ul> </ul>
<h3><a href="https://www.moonweb.org/smarthome//kids-rfid-player/">Kids RFID MP3 Player</a> (2018)</h3> <h3><a href="https://www.moonweb.org/smarthome/kids-rfid-player/">Kids RFID MP3 Player</a> (2018)</h3>
<ul> <ul>
<li>Interactive audio playback system utilizing RFID technology.</li> <li>Interactive audio playback system utilizing RFID technology.</li>
<li>Powered by an Arduino Nano for compact and efficient operation.</li> <li>Powered by an Arduino Nano for compact and efficient operation.</li>
@@ -110,7 +110,7 @@ layout: stefankoelle.njk
<li>Managed a FreeBSD server with Apache, Sendmail, and Perl scripts.</li> <li>Managed a FreeBSD server with Apache, Sendmail, and Perl scripts.</li>
<li>Maintained an NT 4.0 file server.</li> <li>Maintained an NT 4.0 file server.</li>
<li>Administered Windows 98 and Windows 2000 hosts.</li> <li>Administered Windows 98 and Windows 2000 hosts.</li>
<li>More info at <a href="https://www.moonweb.org/network/" target="_blank">moonweb.org/network/</a></li> <li>More info at <a href="https://www.moonweb.org/timecapsule/network/" target="_blank">moonweb.org/timecapsule/network/</a></li>
</ul> </ul>
<h3>Mailbox/Fidonet (1994 - 2000)</h3> <h3>Mailbox/Fidonet (1994 - 2000)</h3>
@@ -146,7 +146,7 @@ layout: stefankoelle.njk
<h3>AI-Assisted Development</h3> <h3>AI-Assisted Development</h3>
<p>I've fully embraced the AI-assisted development paradigm since early 2025. At work, I've taught <strong>Claude Code</strong> a workflow for handling Jira stories end-to-end: it evaluates requirements, provides feedback to the PO, and creates a detailed implementation plan. From there, it's mostly about supervising the plan while the code generation runs largely autonomously. For code review, we use a second AI (e.g., Codex) as a quality gate to catch issues that might slip through. In migration projects, I define the exact plan upfront and Claude Code executes it with increasing independence. The output gain is massive, delivering in a fraction of the time.</p> <p>I've fully embraced the AI-assisted development paradigm since early 2025. At work, I've taught <strong>Claude Code</strong> a workflow for handling Jira stories end-to-end: it evaluates requirements, provides feedback to the PO, and creates a detailed implementation plan. From there, it's mostly about supervising the plan while the code generation runs largely autonomously. For code review, we use a second AI (e.g., Codex) as a quality gate to catch issues that might slip through. In migration projects, I define the exact plan upfront and Claude Code executes it with increasing independence. The output gain is massive, delivering in a fraction of the time.</p>
<p>Privately, I work with <strong><a href="https://opencode.ai">OpenCode</a></strong> paired with OpenCode Zen, Merge Gateway, and OpenRouter, mostly for Python-based home lab and automation projects. See my <a href="https://www.moonweb.org/code/">GitHub projects</a> for examples and the <a href="https://www.moonweb.org/infra//dev-environment/">Dev VM setup</a> for the infrastructure behind this workflow.</p> <p>Privately, I work with <strong><a href="https://opencode.ai">OpenCode</a></strong> paired with OpenCode Zen, Merge Gateway, and OpenRouter, mostly for Python-based home lab and automation projects. See my <a href="https://www.moonweb.org/code/">GitHub projects</a> for examples and the <a href="https://www.moonweb.org/infra/dev-environment/">Dev VM setup</a> for the infrastructure behind this workflow.</p>
<h3>.NET Core</h3> <h3>.NET Core</h3>
<ul> <ul>
@@ -243,5 +243,5 @@ layout: stefankoelle.njk
<p>Stefan Kölle<br>Neumarkter Str. 86c<br>81673 München</p> <p>Stefan Kölle<br>Neumarkter Str. 86c<br>81673 München</p>
<p>Phone/Fax: +49-(89)-20006547<br>E-Mail: <a id="email-impressum" href="#">[email protected]</a></p> <p>Phone/Fax: +49-(89)-20006547<br>E-Mail: <a id="email-impressum" href="#">[email protected]</a></p>
<p>Responsible for content according to § 18 (2) MStV: Stefan Kölle, address as above.</p> <p>Responsible for content according to § 18 (2) MStV: Stefan Kölle, address as above.</p>
<p>Full legal notice & privacy policy for this website and the moonweb.org network: <a href="https://www.moonweb.org//impressum/">hub.moonweb.org/impressum</a> <p>Full legal notice & privacy policy for this website and the moonweb.org network: <a href="https://www.moonweb.org/impressum/">moonweb.org/impressum</a>
</div> </div>
-1
View File
@@ -17,7 +17,6 @@ echo "==> Installing WeasyPrint..."
pip install -q -r "$REQUIREMENTS" pip install -q -r "$REQUIREMENTS"
echo "==> Building stefankoelle with Eleventy..." echo "==> Building stefankoelle with Eleventy..."
# Temporarily hide .eleventyignore so the standalone stefankoelle build works
IGNORE_FILE="$PROJECT_DIR/.eleventyignore" IGNORE_FILE="$PROJECT_DIR/.eleventyignore"
if [ -f "$IGNORE_FILE" ]; then if [ -f "$IGNORE_FILE" ]; then
mv "$IGNORE_FILE" "$IGNORE_FILE.bak" mv "$IGNORE_FILE" "$IGNORE_FILE.bak"
Binary file not shown.