diff --git a/.github/workflows/build-deploy-moonweb.yml b/.github/workflows/build-deploy-moonweb.yml
new file mode 100644
index 0000000..043b0b3
--- /dev/null
+++ b/.github/workflows/build-deploy-moonweb.yml
@@ -0,0 +1,195 @@
+name: Build & Deploy moonweb.org
+
+on:
+ push:
+ branches: [main]
+ paths-ignore:
+ - 'stefankoelle/**'
+ - '.github/workflows/deploy-stefankoelle.yml'
+ pull_request:
+ branches: [main]
+ paths-ignore:
+ - 'stefankoelle/**'
+ - '.github/workflows/deploy-stefankoelle.yml'
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+env:
+ NODE_VERSION: "22"
+
+jobs:
+ build:
+ name: Build ${{ matrix.site }}
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ site: [hub, infra, smarthome, code, retro]
+ steps:
+ - uses: actions/checkout@v7
+
+ - uses: actions/setup-node@v7
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+ cache: "npm"
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Build ${{ matrix.site }}
+ run: npm run build:${{ matrix.site }}
+
+ - name: Validate build output
+ run: |
+ if [ ! -d "dist/${{ matrix.site }}" ]; then
+ echo "Error: dist/${{ matrix.site }} not found"
+ exit 1
+ fi
+ if [ -z "$(ls -A dist/${{ matrix.site }} 2>/dev/null)" ]; then
+ echo "Error: dist/${{ matrix.site }} is empty"
+ exit 1
+ fi
+ echo "Build output:"
+ find dist/${{ matrix.site }} -type f | head -20
+
+ - name: Upload build artifact
+ uses: actions/upload-artifact@v7
+ with:
+ name: dist-${{ matrix.site }}
+ path: dist/${{ matrix.site }}
+ retention-days: 7
+
+ build-timecapsule:
+ name: Build timecapsule
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v7
+
+ - uses: actions/setup-node@v7
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+
+ - name: Install timecapsule dependencies
+ run: cd timecapsule && npm ci
+
+ - name: Build timecapsule
+ run: npm run build:timecapsule
+
+ - name: Validate build output
+ run: |
+ if [ ! -d "dist/timecapsule" ]; then
+ echo "Error: dist/timecapsule not found"
+ exit 1
+ fi
+ if [ -z "$(ls -A dist/timecapsule 2>/dev/null)" ]; then
+ echo "Error: dist/timecapsule is empty"
+ exit 1
+ fi
+ echo "Build output:"
+ find dist/timecapsule -type f | head -20
+
+ - name: Upload build artifact
+ uses: actions/upload-artifact@v7
+ with:
+ name: dist-timecapsule
+ path: dist/timecapsule
+ retention-days: 7
+
+ merge:
+ name: Merge all sites
+ needs: [build, build-timecapsule]
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v7
+
+ - name: Download all artifacts
+ uses: actions/download-artifact@v8
+ with:
+ path: artifacts/
+
+ - name: Merge into dist/
+ run: |
+ mkdir -p dist
+
+ # Hub becomes root
+ cp -r artifacts/dist-hub/* dist/
+
+ # Subdirectories
+ for site in infra smarthome code retro timecapsule; do
+ if [ -d "artifacts/dist-$site" ]; then
+ cp -r "artifacts/dist-$site" "dist/$site"
+ fi
+ done
+
+ # Copy shared CSS to root (accessible from all subdirectories)
+ cp shared/base.css dist/shared-base.css
+ cp shared/favicon/hub.svg dist/favicon.svg
+
+ echo "Final structure:"
+ find dist -maxdepth 2 -type f | sort | head -40
+ echo "..."
+ echo "Total files:"
+ find dist -type f | wc -l
+
+ - name: Upload merged artifact
+ uses: actions/upload-artifact@v7
+ with:
+ name: dist-moonweb-merged
+ path: dist/
+ retention-days: 7
+
+ deploy:
+ name: Deploy to IONOS
+ needs: merge
+ runs-on: ubuntu-latest
+ if: github.ref == 'refs/heads/main' && github.event_name == 'push'
+ steps:
+ - name: Download merged artifact
+ uses: actions/download-artifact@v8
+ with:
+ name: dist-moonweb-merged
+ path: dist/
+
+ - name: Deploy via SFTP
+ uses: wlixcc/SFTP-Deploy-Action@v1.2.6
+ with:
+ local_path: './dist/*'
+ server: ${{ secrets.IONOS_SFTP_HOST }}
+ username: ${{ secrets.IONOS_SFTP_USER }}
+ password: ${{ secrets.IONOS_SFTP_PASSWORD }}
+ remote_path: '/websites/moonweb/'
+ port: 22
+ sftp_only: true
+
+ summary:
+ name: Deploy Summary
+ needs: deploy
+ runs-on: ubuntu-latest
+ if: always()
+ steps:
+ - name: Print deployment summary
+ run: |
+ echo "## Deployment Summary" >> $GITHUB_STEP_SUMMARY
+ echo "" >> $GITHUB_STEP_SUMMARY
+ if [ "${{ needs.deploy.result }}" = "success" ]; then
+ echo "moonweb.org deployed successfully!" >> $GITHUB_STEP_SUMMARY
+ else
+ echo "Deployment failed. Check the deploy jobs for details." >> $GITHUB_STEP_SUMMARY
+ fi
+ echo "" >> $GITHUB_STEP_SUMMARY
+ echo "### Sites" >> $GITHUB_STEP_SUMMARY
+ echo "| Site | URL |" >> $GITHUB_STEP_SUMMARY
+ echo "|------|-----|" >> $GITHUB_STEP_SUMMARY
+ echo "| hub | https://www.moonweb.org/ |" >> $GITHUB_STEP_SUMMARY
+ echo "| infra | https://www.moonweb.org/infra/ |" >> $GITHUB_STEP_SUMMARY
+ echo "| smarthome | https://www.moonweb.org/smarthome/ |" >> $GITHUB_STEP_SUMMARY
+ echo "| code | https://www.moonweb.org/code/ |" >> $GITHUB_STEP_SUMMARY
+ echo "| retro | https://www.moonweb.org/retro/ |" >> $GITHUB_STEP_SUMMARY
+ echo "| timecapsule | https://www.moonweb.org/timecapsule/ |" >> $GITHUB_STEP_SUMMARY
+
+# Required repo secrets:
+# IONOS_SFTP_HOST — IONOS SFTP server hostname
+# IONOS_SFTP_USER — IONOS SFTP username
+# IONOS_SFTP_PASSWORD — IONOS SFTP password
diff --git a/.github/workflows/build-deploy.yml b/.github/workflows/build-deploy.yml
deleted file mode 100644
index 59232bd..0000000
--- a/.github/workflows/build-deploy.yml
+++ /dev/null
@@ -1,139 +0,0 @@
-name: Build & Deploy moonweb-site
-
-on:
- push:
- branches: [main]
- paths-ignore:
- - 'stefankoelle/**'
- - '.github/workflows/deploy-stefankoelle.yml'
- pull_request:
- branches: [main]
- paths-ignore:
- - 'stefankoelle/**'
- - '.github/workflows/deploy-stefankoelle.yml'
-
-# Cancel in-progress runs for the same branch
-concurrency:
- group: ${{ github.workflow }}-${{ github.ref }}
- cancel-in-progress: true
-
-env:
- NODE_VERSION: "22"
-
-jobs:
- build:
- name: Build ${{ matrix.site }}
- runs-on: ubuntu-latest
- strategy:
- fail-fast: false
- matrix:
- site: [hub, infra, smarthome, code, retro]
- steps:
- - uses: actions/checkout@v7
-
- - uses: actions/setup-node@v7
- with:
- node-version: ${{ env.NODE_VERSION }}
- cache: "npm"
-
- - name: Install dependencies
- run: npm ci
-
- - name: Build ${{ matrix.site }}
- run: npm run build:${{ matrix.site }}
-
- - name: Validate build output
- run: |
- if [ ! -d "dist/${{ matrix.site }}" ]; then
- echo "Error: dist/${{ matrix.site }} not found"
- exit 1
- fi
- if [ -z "$(ls -A dist/${{ matrix.site }} 2>/dev/null)" ]; then
- echo "Error: dist/${{ matrix.site }} is empty"
- exit 1
- fi
- echo "Build output:"
- find dist/${{ matrix.site }} -type f | head -20
-
- - name: Upload build artifact
- uses: actions/upload-artifact@v7
- with:
- name: dist-${{ matrix.site }}
- path: dist/${{ matrix.site }}
- retention-days: 7
-
- deploy:
- name: Deploy ${{ matrix.site }}
- needs: build
- runs-on: ubuntu-latest
- if: github.ref == 'refs/heads/main' && github.event_name == 'push'
- strategy:
- fail-fast: false
- matrix:
- include:
- - site: hub
- cf_project: moonweb-hub
- - site: infra
- cf_project: moonweb-infra
- - site: smarthome
- cf_project: moonweb-smarthome
- - site: code
- cf_project: moonweb-code
- - site: retro
- cf_project: moonweb-retro
- steps:
- - name: Download build artifact
- uses: actions/download-artifact@v8
- with:
- name: dist-${{ matrix.site }}
- path: dist/${{ matrix.site }}
-
- - name: Create wrangler.toml for Worker
- run: |
- echo 'name = "${{ matrix.cf_project }}"' > wrangler.toml
- echo 'compatibility_date = "2024-01-01"' >> wrangler.toml
- echo '' >> wrangler.toml
- echo '[assets]' >> wrangler.toml
- echo 'directory = "./dist/${{ matrix.site }}"' >> wrangler.toml
- echo 'not_found_handling = "404-page"' >> wrangler.toml
-
- - name: Deploy to Cloudflare Workers
- uses: cloudflare/wrangler-action@v4
- with:
- apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
- accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
- command: deploy
-
- summary:
- name: Deploy Summary
- needs: deploy
- runs-on: ubuntu-latest
- if: always()
- steps:
- - name: Print deployment summary
- run: |
- echo "## Deployment Summary" >> $GITHUB_STEP_SUMMARY
- echo "" >> $GITHUB_STEP_SUMMARY
- if [ "${{ needs.deploy.result }}" = "success" ]; then
- echo "✅ All sites deployed successfully!" >> $GITHUB_STEP_SUMMARY
- else
- echo "❌ Deployment failed. Check the deploy jobs for details." >> $GITHUB_STEP_SUMMARY
- fi
- echo "" >> $GITHUB_STEP_SUMMARY
- echo "### Sites" >> $GITHUB_STEP_SUMMARY
- echo "| Site | URL |" >> $GITHUB_STEP_SUMMARY
- echo "|------|-----|" >> $GITHUB_STEP_SUMMARY
- echo "| hub | https://hub.moonweb.org |" >> $GITHUB_STEP_SUMMARY
- echo "| infra | https://infra.moonweb.org |" >> $GITHUB_STEP_SUMMARY
- echo "| smarthome | https://smarthome.moonweb.org |" >> $GITHUB_STEP_SUMMARY
- echo "| code | https://code.moonweb.org |" >> $GITHUB_STEP_SUMMARY
- echo "| retro | https://retro.moonweb.org |" >> $GITHUB_STEP_SUMMARY
-
-# Required repo secrets:
-# CLOUDFLARE_API_TOKEN — Cloudflare API token with Workers:Edit permission
-# CLOUDFLARE_ACCOUNT_ID — Cloudflare account ID
-#
-# Required one-time setup (see PLAN.md Phase 2):
-# Create Cloudflare Workers and bind custom domains.
-# DNS is already on Cloudflare (SPEC.md §4.6).
-#
diff --git a/AGENTS.md b/AGENTS.md
index f0ddc14..ec71fc6 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -1,18 +1,19 @@
# AGENTS.md — moonweb-site
-## Projektübersicht
+## Projektuebersicht
-Monorepo für 5 statische Websites unter moonweb.org + stefankoelle.de, basierend auf Eleventy (11ty).
+Monorepo fuer 6 statische Websites unter www.moonweb.org + stefankoelle.de, basierend auf Eleventy (11ty).
-### Websites (Cloudflare Pages)
+### Websites (IONOS SFTP)
-| Site | Domain | Zweck | Status |
-|------|--------|-------|--------|
-| hub | hub.moonweb.org | Zentrale Indexseite, verlinkt alles | Fertig |
-| infra | infra.moonweb.org | Infrastruktur-Übersicht (Proxmox, Synology, Netzwerk) | Übersicht + 3 Detailseiten |
-| smarthome | smarthome.moonweb.org | Smart Home Projekte und Dashboards | Übersicht + 6 Detailseiten |
-| code | code.moonweb.org | GitHub-Projekte (aggregiert via .moonweb.yml) | Fertig (14 Repos) |
-| retro | retro.moonweb.org | Physische Retro-Hardware | Nur Übersicht (WIP) |
+| Site | URL | Zweck | Status |
+|------|-----|-------|--------|
+| hub | www.moonweb.org/ | Zentrale Indexseite, verlinkt alles | Fertig |
+| infra | www.moonweb.org/infra/ | Infrastruktur-Uebersicht (Proxmox, Synology, Netzwerk) | Uebersicht + 8 Detailseiten |
+| smarthome | www.moonweb.org/smarthome/ | Smart Home Projekte und Dashboards | Uebersicht + 9 Detailseiten |
+| code | www.moonweb.org/code/ | GitHub-Projekte (aggregiert via .moonweb.yml) | Fertig |
+| retro | www.moonweb.org/retro/ | Physische Retro-Hardware | Uebersicht + 13 Detailseiten |
+| timecapsule | www.moonweb.org/timecapsule/ | 2000er Internet-Zeitkapsel (altes Design) | Fertig |
### Externe Sites (SFTP-Deployment)
@@ -22,19 +23,23 @@ Monorepo für 5 statische Websites unter moonweb.org + stefankoelle.de, basieren
### Andere Sites (nicht im Monorepo)
-- www.moonweb.org — 2000er Internet-Zeitkapsel
- 28k8.moonweb.org — 90er BBS/Scene-Archiv
+- buildbroken.moonweb.org — .NET Open Space Blog Archiv
## Dateistruktur
```
moonweb-site/
├── hub/ # Eleventy-Config + index.njk
-├── infra/ # Eleventy-Config + index.njk + 3 Subseiten
-├── smarthome/ # Eleventy-Config + index.njk + 6 Subseiten
+├── infra/ # Eleventy-Config + index.njk + 8 Subseiten
+├── smarthome/ # Eleventy-Config + index.njk + 9 Subseiten
├── code/ # Eleventy-Config + index.njk
│ └── _data/repos.json
-├── retro/ # Eleventy-Config + index.njk
+├── retro/ # Eleventy-Config + index.njk + 13 Subseiten
+├── timecapsule/ # Eleventy 2.x (eigene Config)
+│ ├── eleventy.config.js
+│ ├── package.json
+│ └── src/ # 2001er Retro-Content
├── stefankoelle/ # Eleventy-Config + Onepager
│ ├── eleventy.config.js
│ ├── _includes/
@@ -52,10 +57,11 @@ moonweb-site/
│ ├── base.css
│ └── theme-*.css
├── scripts/
-│ └── github-aggregator/
+│ ├── github-aggregator/
+│ └── merge-moonweb.sh # Merge-Skript fuer Deployment
├── .github/workflows/
-│ ├── build-deploy.yml # CI/CD: Cloudflare Pages (5 Sites)
-│ └── deploy-stefankoelle.yml # CI/CD: IONOS SFTP (stefankoelle.de)
+│ ├── build-deploy-moonweb.yml # CI/CD: IONOS SFTP (www.moonweb.org)
+│ └── deploy-stefankoelle.yml # CI/CD: IONOS SFTP (stefankoelle.de)
├── DESIGN.md
├── SPEC.md
├── PLAN.md
@@ -66,10 +72,11 @@ moonweb-site/
## Technischer Stack
-- **SSG:** Eleventy (11ty) v3.1.6
+- **SSG:** Eleventy (11ty) v3.1.6 (hub, infra, smarthome, code, retro)
+- **SSG:** Eleventy v2.0.1 (timecapsule - retro 2001 Design)
- **Templates:** Nunjucks (.njk)
- **CSS:** Variables-basiert mit Accent-Farben pro Site
-- **Deploy (moonweb):** Cloudflare Pages (5 separate Projects)
+- **Deploy (moonweb):** IONOS SFTP
- **Deploy (stefankoelle):** IONOS SFTP
- **CI/CD:** GitHub Actions (2 Workflows)
@@ -77,32 +84,54 @@ moonweb-site/
```bash
npm install
-npm run prebuild # Pre-Build Tasks (CV PDF generieren)
-npm run dev:hub # localhost:8081
-npm run dev:infra # localhost:8082
-npm run dev:smarthome # localhost:8083
-npm run dev:code # localhost:8084
-npm run dev:retro # localhost:8085
-npm run dev:stefankoelle # localhost:8086
-npm run build # Alle Sites bauen
+cd timecapsule && npm install # Timecapsule Dependencies
+npm run prebuild # Pre-Build Tasks (CV PDF generieren)
+npm run dev:hub # localhost:8081
+npm run dev:infra # localhost:8082
+npm run dev:smarthome # localhost:8083
+npm run dev:code # localhost:8084
+npm run dev:retro # localhost:8085
+npm run dev:stefankoelle # localhost:8086
+npm run dev:timecapsule # localhost:8087
+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
1. **Header konsistent** — Identischer Site-Switcher auf allen Home-Sites
-2. **Content flexibel** — Detailseiten dürfen eigenes Layout haben
+2. **Content flexibel** — Detailseiten duerfen eigenes Layout haben
3. **Accent-Farben:** hub=#3b6ea5, infra=#99333A, smarthome=#1f8a8a, code=#3E5098, retro=#8a6d3b
4. **Englisch** — Alle Sites komplett auf Englisch
5. **Keine Analytics** — Keine Tracking-Tools
-6. **Sensible Daten** — Infra-Content wird manuell redigiert (keine IPs, Keys, Passwörter)
+6. **Sensible Daten** — Infra-Content wird manuell redigiert (keine IPs, Keys, Passwoerter)
+
+## URL-Struktur
+
+Alle Sites sind unter `www.moonweb.org` als Subverzeichnisse erreichbar:
+- `www.moonweb.org/` — Hub (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/` — Timecapsule (2001 Design)
+- `www.moonweb.org/impressum/` — Impressum
+
+Cloudflare Redirects leiten alte Subdomains weiter:
+- `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/*`
## stefankoelle.de
- Eigene Eleventy-Config (nicht shared base.njk)
- Eigenes CSS-Design (nicht moonweb design system)
- Onepager mit Anchor-Links (bleibt so)
-- Deploy via SFTP auf IONOS `/deploy/stefankoelle/`
-- CV-Partial zentral pflegbar (einmal aendern → Web + PDF aktualisieren)
+- Deploy via SFTP auf IONOS `/websites/stefankoelle/`
+- CV-Partial zentral pflegbar (einmal aendern -> Web + PDF aktualisieren)
- LED Matrix als eigene Seite unter stefankoelle.de/ledmatrix/
### CV PDF Generierung
@@ -116,7 +145,7 @@ npm run prebuild # Alle Pre-Build Tasks (inkl. CV PDF)
Dateien:
- `stefankoelle/pdf/cv-style.css` — WeasyPrint-Stylesheet (A4, Typografie)
-- `stefankoelle/pdf/build-pdf.sh` — Shell-Skript für PDF-Generierung
+- `stefankoelle/pdf/build-pdf.sh` — Shell-Skript fuer PDF-Generierung
- `stefankoelle/cv-print.njk` — Standalone HTML-Template (nur CV-Content)
- `stefankoelle/pdf/cv.pdf` — Generiertes PDF (Output)
@@ -124,21 +153,22 @@ Wichtig: Das PDF wird via Eleventy-Passthrough ins Build-Output kopiert (`dist/s
### CSS Cache-Busting
-CSS-Dateien werden als Passthrough kopiert (kein Hash im Dateinamen). Bei CSS-Änderungen muss der Query-String in der `?v=N` Inkludierung erhöht werden:
+CSS-Dateien werden als Passthrough kopiert (kein Hash im Dateinamen). Bei CSS-Aenderungen muss der Query-String in der `?v=N` Inkludierung erhoeht werden:
- `stefankoelle/index.njk`: ``
- `stefankoelle/ledmatrix/index.njk`: ``
-Bei jeder CSS-Anpassung `?v=N` um 1 erhöhen, sonst cached der Browser die alte Datei.
+Bei jeder CSS-Anpassung `?v=N` um 1 erhoehen, sonst cached der Browser die alte Datei.
## CI/CD
-### Cloudflare Pages (moonweb)
-`.github/workflows/build-deploy.yml` baut hub, infra, smarthome, code, retro.
+### IONOS SFTP (www.moonweb.org)
+`.github/workflows/build-deploy-moonweb.yml` baut alle moonweb Sites (hub, infra, smarthome, code, retro, timecapsule) und deployed per SFTP.
Benötigte Secrets:
-- `CLOUDFLARE_API_TOKEN`
-- `CLOUDFLARE_ACCOUNT_ID`
+- `IONOS_SFTP_HOST`
+- `IONOS_SFTP_USER`
+- `IONOS_SFTP_PASSWORD`
### IONOS SFTP (stefankoelle.de)
`.github/workflows/deploy-stefankoelle.yml` baut stefankoelle.de und deployed per SFTP.
@@ -150,9 +180,11 @@ Benötigte Secrets:
## Offene Punkte
-- retro/ ist bewusst rudimentär gehalten
+- retro/ ist bewusst rudimentaer gehalten
- Querverlinkungen stefankoelle.de <-> smarthome (zukuenftig)
- Ledmatrix ggf. nach smarthome verschieben (when ready)
+- Cloudflare Redirects einrichten (nach Deploy)
+- Google Search Console: Neue Property www.moonweb.org
## GitHub Aggregator
@@ -191,10 +223,10 @@ python3 -m venv .venv
## Text / Stil
-- Keine Em-Dashes (—) verwenden, stattdessen umformulieren (Komma, Satzzeichen, neu formulieren)
+- Keine Em-Dashes verwenden, stattdessen umformulieren (Komma, Satzzeichen, neu formulieren)
## Python / pip
-- Niemals `pip install` direkt ausführen
+- Niemals `pip install` direkt ausfuehren
- Immer ein virtuelles Umfeld (`.venv`) anlegen und darin arbeiten
- `python3 -m venv .venv` im Projektverzeichnis
diff --git a/README.md b/README.md
index d513416..16260cb 100755
--- a/README.md
+++ b/README.md
@@ -1,88 +1,67 @@
-# 🌙 moonweb-site
+# moonweb-site
-Monorepo for the **moonweb.org** homelab — five static sites built with [Eleventy](https://www.11ty.dev/), deployed to [Cloudflare Pages](https://pages.cloudflare.com/).
+Monorepo for the **moonweb.org** homelab — six static sites built with [Eleventy](https://www.11ty.dev/), deployed to [IONOS SFTP](https://www.ionos.de/).
```
-hub.moonweb.org → 🏠 Central index & gateway
-infra.moonweb.org → 🏗️ Infrastructure overview (Proxmox, Synology, Docker)
-smarthome.moonweb.org → 🏡 Smart home projects & dashboards
-code.moonweb.org → 💻 Curated GitHub project catalog
-retro.moonweb.org → 🕹️ Physical retro hardware collection
-stefankoelle.de → 👤 CV, career, personal site (LED Matrix docs)
+www.moonweb.org/ -> Central index & gateway
+www.moonweb.org/infra/ -> Infrastructure overview (Proxmox, Synology, Docker)
+www.moonweb.org/smarthome/ -> Smart home projects & dashboards
+www.moonweb.org/code/ -> Curated GitHub project catalog
+www.moonweb.org/retro/ -> Physical retro hardware collection
+www.moonweb.org/timecapsule/ -> 2000s internet time capsule (retro design)
+stefankoelle.de -> CV, career, personal site (LED Matrix docs)
```
-> **Other sites** (not in this monorepo): [www.moonweb.org](https://www.moonweb.org) (2000s time capsule), [28k8.moonweb.org](https://28k8.moonweb.org) (90s BBS archive).
+> **Other sites** (not in this monorepo): [28k8.moonweb.org](https://28k8.moonweb.org) (90s BBS archive), [buildbroken.moonweb.org](https://buildbroken.moonweb.org) (.NET Open Space blog).
---
-## 📐 Architecture
+## Architecture
```
-┌─────────────────────────────────────────────────────────────┐
-│ GitHub Actions CI │
-│ ┌───────────┐ ┌────────────┐ ┌─────────────┐ ┌─────────┐ │
-│ │ build:hub │ │build:infra │ │ build:smart │ │ build:… │ │
-│ └─────┬─────┘ └─────┬──────┘ └──────┬──────┘ └────┬────┘ │
-│ │ │ │ │ │
-│ ▼ ▼ ▼ ▼ │
-│ dist/hub/ dist/infra/ dist/smarthome/ dist/…/ │
-└────────┬───────────────────────────────────────────┬────────┘
- │ │
- ▼ ▼
-┌──────────────────┐ ┌─────────────────┐
-│ Cloudflare Pages │ │ IONOS SFTP │
-│ (5 sites) │ │ (stefankoelle) │
-└────────┬─────────┘ └────────┬────────┘
- ▼ ▼
- hub / infra / ... stefankoelle.de
++-------------------------------------------------------------------+
+| GitHub Actions CI |
+| +-----------+ +------------+ +-------------+ +---------+ +------+ |
+| | build:hub | |build:infra | | build:smart | | build:... | | build:timecapsule | |
+| +-----+-----+ +-----+------+ +------+------+ +----+----+ +----+----+ +--------+ |
+| | | | | | | |
+| v v v v v v |
+| dist/hub/ dist/infra/ dist/smarthome/ dist/.../ dist/timecapsule/ |
++--------+---------------------------------------------------+--------------------+
+ | |
+ v v
++------------------+ +------------------+
+| IONOS SFTP | | IONOS SFTP |
+| (www.moonweb.org)| | (stefankoelle.de)|
++--------+---------+ +--------+---------+
+ v v
+ www.moonweb.org/* stefankoelle.de
```
---
-## 🛠️ Tech Stack
+## Tech Stack
| Layer | Technology | Why |
|-------|-----------|-----|
-| **SSG** | [Eleventy 3.1.6](https://www.11ty.dev/) | Markdown/YAML-first, minimal JS, `_data` folders map directly to aggregator output, low maintenance for 5 sites |
+| **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 |
| **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, no build step needed |
+| **Styling** | Custom CSS (variables-based) | `base.css` for shared layout, `theme-*.css` per domain accent color |
| **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 5 sites, artifact upload, parallel deploy |
-| **Deploy** | [Cloudflare Workers](https://workers.cloudflare.com/) | Static asset hosting via `wrangler pages deploy`, one worker per site |
-| **DNS** | Cloudflare | Already managing DNS — zero additional setup for Pages custom domains |
+| **CI/CD** | [GitHub Actions](https://github.com/features/actions) | Matrix build for all sites, artifact upload, merge step, parallel deploy |
+| **Deploy** | IONOS SFTP | Static hosting via SFTP upload |
+| **DNS** | Cloudflare | DNS management + redirects from old subdomains |
| **GitHub Catalog** | Python aggregator | Reads `.moonweb.yml` from each repo, outputs `repos.json` |
-| **Runtime** | Fully static | No server-side code, no containers, no database — pure HTML/CSS/JS |
+| **Runtime** | Fully static | No server-side code, no containers, no database |
---
-## 🎨 Design System
-
-### Header-consistent, content-flexible
-
-- **Header is identical** across all home-section sites: site-switcher (hub · infra · smarthome · code · retro · cv), domain accent color, Lobster title font.
-- **Index pages** use a shared card-grid layout with grouped sections.
-- **Detail pages** keep the same header but use a freer layout below it (e.g., pin tables, API docs, photos in free arrangement).
-
-### Accent colors
-
-| Domain | Color | Hex |
-|--------|-------|-----|
-| hub | Neutral blue | `#3b6ea5` |
-| infra | Grey-blue | `#99333A` |
-| smarthome | Teal | `#1f8a8a` |
-| code | Violet | `#3E5098` |
-| retro | Warm brown | `#8a6d3b` |
-
-### Emojis
-
-Each card on index pages has an emoji for visual navigation — consistent across hub, infra, smarthome, code, and retro.
-
----
-
-## 🚀 Local Development
+## Local Development
```bash
npm install # install Eleventy + deps
+cd timecapsule && npm install # timecapsule has own deps (Eleventy 2.x)
npm run dev:hub # http://localhost:8081
npm run dev:infra # http://localhost:8082
@@ -90,8 +69,9 @@ npm run dev:smarthome # http://localhost:8083
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 6 in parallel
+npm run dev # all 7 in parallel
```
Each site has its own minimal Eleventy config (`
- Scope of this legal notice: This legal notice and the privacy policy below apply to the following websites, all operated by Stefan Kölle: hub.moonweb.org, smarthome.moonweb.org, infra.moonweb.org, code.moonweb.org, retro.moonweb.org, buildbroken.moonweb.org, 28k8.moonweb.org, www.moonweb.org, and stefankoelle.de. All of these sites are part of the same personal project network and are covered jointly by this single document. + Scope of this legal notice: This legal notice and the privacy policy below apply to the following websites, all operated by Stefan Kölle: www.moonweb.org (including /infra/, /smarthome/, /code/, /retro/, /timecapsule/), buildbroken.moonweb.org, 28k8.moonweb.org, and stefankoelle.de. All of these sites are part of the same personal project network and are covered jointly by this single document.
@@ -41,7 +41,7 @@ layout: base.njk
- The moonweb.org subdomains (hub, smarthome, infra, code, retro) 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. www.moonweb.org is an archived version of my original website from 2001. 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 (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.
- Hosted via Cloudflare Pages, operated by Cloudflare, Inc., 101 Townsend St, San Francisco, CA 94107, USA. Cloudflare processes connection-level data (e.g. your IP address, request headers) as part of its content delivery and DDoS/security systems. This is governed by Cloudflare's Data Processing Addendum, which incorporates the EU Standard Contractual Clauses (2021) as a safeguard for the transfer of data to the USA. See cloudflare.com/privacypolicy. -
- -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).
+- Legal basis for both: Art. 6(1)(f) GDPR (legitimate interest in reliable, secure delivery of the websites). -
+ 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). + + +diff --git a/hub/index.njk b/hub/index.njk index 75291b4..f484fc4 100644 --- a/hub/index.njk +++ b/hub/index.njk @@ -9,19 +9,19 @@ sections: cards: - title: "infra" summary: "Stack overview: Proxmox, Synology, network, backups, and how I work." - href: "https://infra.moonweb.org" + href: "/infra/" emoji: "🏗️" - title: "smarthome" summary: "What's actually running on the homelab, and why." - href: "https://smarthome.moonweb.org" + href: "/smarthome/" emoji: "🏠" - title: "code" summary: "Curated catalog of my GitHub projects." - href: "https://code.moonweb.org" + href: "/code/" emoji: "💻" - title: "retro" summary: "Physical retro hardware collection." - href: "https://retro.moonweb.org" + href: "/retro/" emoji: "🕹️" - heading: "About me" cards: @@ -37,7 +37,7 @@ sections: emoji: "💾" - title: "www.moonweb.org" summary: "The 2000s internet projects, networking and engineering." - href: "https://www.moonweb.org" + href: "/timecapsule/" emoji: "🌐" - title: "inseco.de" summary: "Internet services & consulting for gastronomy and clubs, Peak 2003–2008. Custom PHP/CMS." @@ -63,7 +63,7 @@ sections: