From c77ad91e0efe4c3775723795c253138841dd7e32 Mon Sep 17 00:00:00 2001 From: Stefan Koelle Date: Fri, 11 Sep 2026 12:31:47 +0200 Subject: [PATCH] Consolidate all moonweb sites into single Eleventy config - Single eleventy.config.js at root with computed pathPrefix per section - Accent colors inlined in base.njk (no per-site theme.css needed) - Hub pages output at root via explicit permalinks - Per-section sitemaps with tag-based collections - .eleventyignore excludes stefankoelle, timecapsule, markdown files - Deleted: 5 per-site configs, merge script - Simplified: package.json (single build/dev commands) - Simplified: GitHub Actions workflow (no matrix, no merge job) - Fixed: parent links for sub-site detail pages --- .eleventyignore | 17 +++ .github/workflows/build-deploy-moonweb.yml | 109 +++---------------- code/404.html | 3 +- code/eleventy.config.js | 20 ---- code/index.njk | 1 + code/sitemap.xml.njk | 3 +- eleventy.config.js | 93 ++++++++++++++++ hub/404.html | 1 + hub/eleventy.config.js | 46 -------- hub/impressum.njk | 2 + hub/index.njk | 2 + hub/sitemap.xml.njk | 1 + infra/404.html | 3 +- infra/backup-strategy/index.njk | 3 +- infra/dev-environment/index.njk | 3 +- infra/docker/index.njk | 3 +- infra/eleventy.config.js | 20 ---- infra/index.njk | 1 + infra/lxc/index.njk | 3 +- infra/monitoring/index.njk | 3 +- infra/openwrt/index.njk | 3 +- infra/proxmox/index.njk | 3 +- infra/sitemap.xml.njk | 3 +- infra/synology/index.njk | 3 +- package.json | 17 +-- retro/404.html | 3 +- retro/amiga-hardware-landscape/index.njk | 3 +- retro/amiga-modern-platforms/index.njk | 3 +- retro/atari-mega-st-fleet/index.njk | 3 +- retro/atari-monitor-compatibility/index.njk | 3 +- retro/atari-networking-bbs/index.njk | 3 +- retro/batocera-living-room/index.njk | 3 +- retro/dos-486-tower/index.njk | 3 +- retro/eleventy.config.js | 20 ---- retro/et4000-experiment/index.njk | 3 +- retro/index.njk | 1 + retro/mini-arcade-handheld-roundup/index.njk | 3 +- retro/mist-mister-fpga/index.njk | 3 +- retro/pimiga-journey/index.njk | 3 +- retro/retro-corner-snapshot/index.njk | 3 +- retro/sitemap.xml.njk | 3 +- retro/the-a1200/index.njk | 3 +- scripts/merge-moonweb.sh | 49 --------- shared/_includes/base.njk | 4 +- shared/_includes/sitemap.njk | 5 +- smarthome/404.html | 3 +- smarthome/air-quality/index.njk | 3 +- smarthome/airplay-audio/index.njk | 3 +- smarthome/balkonpi/index.njk | 3 +- smarthome/eleventy.config.js | 20 ---- smarthome/home-dashboard-controls/index.njk | 3 +- smarthome/homematic-mqtt/index.njk | 3 +- smarthome/index.njk | 1 + smarthome/kids-rfid-player/index.njk | 3 +- smarthome/octoprint/index.njk | 3 +- smarthome/sitemap.xml.njk | 3 +- smarthome/tasmota-energy/index.njk | 3 +- smarthome/tubearchivist/index.njk | 3 +- 58 files changed, 220 insertions(+), 324 deletions(-) create mode 100644 .eleventyignore delete mode 100644 code/eleventy.config.js create mode 100644 eleventy.config.js delete mode 100644 hub/eleventy.config.js delete mode 100644 infra/eleventy.config.js delete mode 100644 retro/eleventy.config.js delete mode 100755 scripts/merge-moonweb.sh delete mode 100644 smarthome/eleventy.config.js diff --git a/.eleventyignore b/.eleventyignore new file mode 100644 index 0000000..8f47361 --- /dev/null +++ b/.eleventyignore @@ -0,0 +1,17 @@ +stefankoelle/ +timecapsule/ +scripts/ +.tmp/ + +# Root markdown files (not templates) +/*.md + +# Hub static redirect files (handled by passthrough copy) +hub/hardware.html +hub/users.html +hub/index2.html +hub/index3.html +hub/new.html +hub/links.html +hub/infos.html +hub/start.html diff --git a/.github/workflows/build-deploy-moonweb.yml b/.github/workflows/build-deploy-moonweb.yml index 043b0b3..43ed77c 100644 --- a/.github/workflows/build-deploy-moonweb.yml +++ b/.github/workflows/build-deploy-moonweb.yml @@ -21,12 +21,8 @@ env: jobs: build: - name: Build ${{ matrix.site }} + name: Build moonweb sites runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - site: [hub, infra, smarthome, code, retro] steps: - uses: actions/checkout@v7 @@ -38,118 +34,45 @@ jobs: - 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 all moonweb sites + run: npm run build - 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 + # Verify key directories exist + for dir in "" infra smarthome code retro timecapsule; do + if [ -n "$dir" ] && [ ! -d "dist/$dir" ]; then + echo "Error: dist/$dir not found" + exit 1 + fi + done + + - name: Upload build artifact uses: actions/upload-artifact@v7 with: - name: dist-moonweb-merged + name: dist-moonweb path: dist/ retention-days: 7 deploy: name: Deploy to IONOS - needs: merge + needs: build runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' && github.event_name == 'push' steps: - - name: Download merged artifact + - name: Download build artifact uses: actions/download-artifact@v8 with: - name: dist-moonweb-merged + name: dist-moonweb path: dist/ - name: Deploy via SFTP diff --git a/code/404.html b/code/404.html index 7b6d6dc..a836dc6 100644 --- a/code/404.html +++ b/code/404.html @@ -1,9 +1,10 @@ --- title: "Page Not Found" section: "code" +tags: "code" description: "The page you are looking for does not exist." layout: base.njk -permalink: /404.html +permalink: /code/404.html ---

404

diff --git a/code/eleventy.config.js b/code/eleventy.config.js deleted file mode 100644 index c64b2dc..0000000 --- a/code/eleventy.config.js +++ /dev/null @@ -1,20 +0,0 @@ -module.exports = function (eleventyConfig) { - eleventyConfig.addGlobalData("site", { url: "https://www.moonweb.org", pathPrefix: "/code" }); - eleventyConfig.addFilter("date", (d) => d.toISOString()); - eleventyConfig.addPassthroughCopy({ "shared/theme-code.css": "theme.css" }); - eleventyConfig.addPassthroughCopy({ "shared/base.css": "shared-base.css" }); - eleventyConfig.addPassthroughCopy({ "shared/favicon/code.svg": "favicon.svg" }); - eleventyConfig.addPassthroughCopy({ "code/robots.txt": "robots.txt" }); - - return { - dir: { - input: "code", - includes: "../shared/_includes", - output: "dist/code" - }, - serverOptions: { - host: "0.0.0.0", - port: 8084 - } - }; -}; diff --git a/code/index.njk b/code/index.njk index 715717e..9ab341c 100644 --- a/code/index.njk +++ b/code/index.njk @@ -1,6 +1,7 @@ --- title: "Open Source Projects — GitHub Repos & Code | moonweb" section: "code" +tags: "code" description: "Curated catalog of my public GitHub projects — automation, dev tools, web apps, and firmware." layout: base.njk subcategories: diff --git a/code/sitemap.xml.njk b/code/sitemap.xml.njk index 7cbc214..a8197b8 100644 --- a/code/sitemap.xml.njk +++ b/code/sitemap.xml.njk @@ -1,5 +1,6 @@ --- -permalink: /sitemap.xml +permalink: /code/sitemap.xml +sitemapCollection: "code" eleventyExcludeFromCollections: true --- {% include "sitemap.njk" %} diff --git a/eleventy.config.js b/eleventy.config.js new file mode 100644 index 0000000..02ac173 --- /dev/null +++ b/eleventy.config.js @@ -0,0 +1,93 @@ +const SITES = { + hub: { pathPrefix: "" }, + infra: { pathPrefix: "/infra" }, + smarthome: { pathPrefix: "/smarthome" }, + code: { pathPrefix: "/code" }, + retro: { pathPrefix: "/retro" }, +}; + +module.exports = function (eleventyConfig) { + eleventyConfig.addGlobalData("site", { url: "https://www.moonweb.org" }); + eleventyConfig.addFilter("date", (d) => d.toISOString()); + + // Computed pathPrefix based on page's section front matter + eleventyConfig.addGlobalData("eleventyComputed", { + pathPrefix: (data) => SITES[data.section]?.pathPrefix ?? "", + }); + + // Per-section collections (for sitemaps) + for (const section of Object.keys(SITES)) { + eleventyConfig.addCollection(section, (collectionsApi) => + collectionsApi.getFilteredByTag(section) + ); + } + + // --- Passthrough copies --- + + // Root-level shared assets + eleventyConfig.addPassthroughCopy({ "shared/base.css": "shared-base.css" }); + eleventyConfig.addPassthroughCopy({ "shared/favicon/hub.svg": "favicon.svg" }); + + // Per-section assets: favicon, robots.txt + for (const [section, cfg] of Object.entries(SITES)) { + const prefix = cfg.pathPrefix || "."; + eleventyConfig.addPassthroughCopy({ + [`shared/favicon/${section}.svg`]: `${prefix}/favicon.svg`, + }); + eleventyConfig.addPassthroughCopy({ + [`${section}/robots.txt`]: `${prefix}/robots.txt`, + }); + } + + // Hub: profile photo + eleventyConfig.addPassthroughCopy({ + "hub/stefan-koelle-foto.jpg": "stefan-koelle-foto.jpg", + }); + + // Hub: old www.moonweb.org redirects (.htm → .html) + const htmRedirects = [ + "start", + "index2", + "index3", + "new", + "links", + "infos", + "hardware", + "users", + ]; + for (const name of htmRedirects) { + eleventyConfig.addPassthroughCopy({ + [`hub/${name}.htm`]: `${name}.html`, + }); + } + const htmSubdirs = [ + "beginning", + "projects", + "products", + "acoustics", + "location", + "background", + "partners", + "contact", + "network", + "stefan", + "legal-notice", + ]; + for (const dir of htmSubdirs) { + eleventyConfig.addPassthroughCopy({ + [`hub/${dir}/index.htm`]: `${dir}/index.html`, + }); + } + + return { + dir: { + input: ".", + includes: "shared/_includes", + output: "dist", + }, + serverOptions: { + host: "0.0.0.0", + port: 8081, + }, + }; +}; diff --git a/hub/404.html b/hub/404.html index 66bde92..65a7ba4 100644 --- a/hub/404.html +++ b/hub/404.html @@ -1,6 +1,7 @@ --- title: "Page Not Found" section: "hub" +tags: "hub" description: "The page you are looking for does not exist." layout: base.njk permalink: /404.html diff --git a/hub/eleventy.config.js b/hub/eleventy.config.js deleted file mode 100644 index ea2d0e5..0000000 --- a/hub/eleventy.config.js +++ /dev/null @@ -1,46 +0,0 @@ -module.exports = function (eleventyConfig) { - eleventyConfig.addGlobalData("site", { url: "https://www.moonweb.org" }); - eleventyConfig.addFilter("date", (d) => d.toISOString()); - eleventyConfig.addPassthroughCopy({ "shared/theme-hub.css": "theme.css" }); - eleventyConfig.addPassthroughCopy({ "shared/base.css": "shared-base.css" }); - eleventyConfig.addPassthroughCopy({ "shared/favicon/hub.svg": "favicon.svg" }); - eleventyConfig.addPassthroughCopy({ "hub/robots.txt": "robots.txt" }); - eleventyConfig.addPassthroughCopy({ "hub/stefan-koelle-foto.jpg": "stefan-koelle-foto.jpg" }); - - // Old www.moonweb.org redirects (root-level HTML shortcuts) - // .htm files are excluded from Eleventy processing, renamed to .html on output - eleventyConfig.addPassthroughCopy({ "hub/start.htm": "start.html" }); - eleventyConfig.addPassthroughCopy({ "hub/index2.htm": "index2.html" }); - eleventyConfig.addPassthroughCopy({ "hub/index3.htm": "index3.html" }); - eleventyConfig.addPassthroughCopy({ "hub/new.htm": "new.html" }); - eleventyConfig.addPassthroughCopy({ "hub/links.htm": "links.html" }); - eleventyConfig.addPassthroughCopy({ "hub/infos.htm": "infos.html" }); - eleventyConfig.addPassthroughCopy({ "hub/hardware.htm": "hardware.html" }); - eleventyConfig.addPassthroughCopy({ "hub/users.htm": "users.html" }); - - // Old www.moonweb.org redirects (content subdirectories) - // .htm files are excluded from Eleventy processing, renamed to .html on output - eleventyConfig.addPassthroughCopy({ "hub/beginning/index.htm": "beginning/index.html" }); - eleventyConfig.addPassthroughCopy({ "hub/projects/index.htm": "projects/index.html" }); - eleventyConfig.addPassthroughCopy({ "hub/products/index.htm": "products/index.html" }); - eleventyConfig.addPassthroughCopy({ "hub/acoustics/index.htm": "acoustics/index.html" }); - eleventyConfig.addPassthroughCopy({ "hub/location/index.htm": "location/index.html" }); - eleventyConfig.addPassthroughCopy({ "hub/background/index.htm": "background/index.html" }); - eleventyConfig.addPassthroughCopy({ "hub/partners/index.htm": "partners/index.html" }); - eleventyConfig.addPassthroughCopy({ "hub/contact/index.htm": "contact/index.html" }); - eleventyConfig.addPassthroughCopy({ "hub/network/index.htm": "network/index.html" }); - eleventyConfig.addPassthroughCopy({ "hub/stefan/index.htm": "stefan/index.html" }); - eleventyConfig.addPassthroughCopy({ "hub/legal-notice/index.htm": "legal-notice/index.html" }); - - return { - dir: { - input: "hub", - includes: "../shared/_includes", - output: "dist/hub" - }, - serverOptions: { - host: "0.0.0.0", - port: 8081 - } - }; -}; diff --git a/hub/impressum.njk b/hub/impressum.njk index 6b0b021..a8e7191 100644 --- a/hub/impressum.njk +++ b/hub/impressum.njk @@ -1,6 +1,8 @@ --- title: "Legal Notice & Privacy Policy" section: "hub" +tags: "hub" +permalink: /impressum/index.html description: "Legal notice (Impressum) and privacy policy for moonweb.org." layout: base.njk --- diff --git a/hub/index.njk b/hub/index.njk index f484fc4..e584043 100644 --- a/hub/index.njk +++ b/hub/index.njk @@ -1,6 +1,8 @@ --- title: "Stefan Koelle — Homelab, Smart Home, Code & Retro Hardware | moonweb" section: "hub" +tags: "hub" +permalink: /index.html description: "Stefan Koelle — Senior Software Developer & Architect based in Munich. Homelab projects, smart home automation, open-source code, and retro hardware." layout: base.njk ogImage: "/stefan-koelle-foto.jpg" diff --git a/hub/sitemap.xml.njk b/hub/sitemap.xml.njk index 7cbc214..a3871f1 100644 --- a/hub/sitemap.xml.njk +++ b/hub/sitemap.xml.njk @@ -1,5 +1,6 @@ --- permalink: /sitemap.xml +sitemapCollection: "hub" eleventyExcludeFromCollections: true --- {% include "sitemap.njk" %} diff --git a/infra/404.html b/infra/404.html index 0597e48..a914d70 100644 --- a/infra/404.html +++ b/infra/404.html @@ -1,9 +1,10 @@ --- title: "Page Not Found" section: "infra" +tags: "infra" description: "The page you are looking for does not exist." layout: base.njk -permalink: /404.html +permalink: /infra/404.html ---

404

diff --git a/infra/backup-strategy/index.njk b/infra/backup-strategy/index.njk index e1bb576..66affd2 100644 --- a/infra/backup-strategy/index.njk +++ b/infra/backup-strategy/index.njk @@ -1,7 +1,8 @@ --- title: "Backup Strategy" section: "infra" -parent: "/" +tags: "infra" +parent: "/infra/" description: "Layered 3-2-1 backup strategy covering NAS snapshots, offsite copies, and cloud storage." layout: base.njk --- diff --git a/infra/dev-environment/index.njk b/infra/dev-environment/index.njk index b40343c..78acbc3 100644 --- a/infra/dev-environment/index.njk +++ b/infra/dev-environment/index.njk @@ -1,7 +1,8 @@ --- title: "Xubuntu Dev VM" section: "infra" -parent: "/" +tags: "infra" +parent: "/infra/" description: "A disposable, daily-backed-up Xubuntu VM for AI-assisted, remote development via SSH and Chrome Remote Desktop." layout: base.njk --- diff --git a/infra/docker/index.njk b/infra/docker/index.njk index d095e4c..f1e53f2 100644 --- a/infra/docker/index.njk +++ b/infra/docker/index.njk @@ -1,7 +1,8 @@ --- title: "Docker Container Strategy" section: "infra" -parent: "/" +tags: "infra" +parent: "/infra/" description: "How self-hosted services are organized across three Docker hosts on Proxmox and Synology, using Docker Compose as the single source of truth." layout: base.njk --- diff --git a/infra/eleventy.config.js b/infra/eleventy.config.js deleted file mode 100644 index c46e7ac..0000000 --- a/infra/eleventy.config.js +++ /dev/null @@ -1,20 +0,0 @@ -module.exports = function (eleventyConfig) { - eleventyConfig.addGlobalData("site", { url: "https://www.moonweb.org", pathPrefix: "/infra" }); - eleventyConfig.addFilter("date", (d) => d.toISOString()); - eleventyConfig.addPassthroughCopy({ "shared/theme-infra.css": "theme.css" }); - eleventyConfig.addPassthroughCopy({ "shared/base.css": "shared-base.css" }); - eleventyConfig.addPassthroughCopy({ "shared/favicon/infra.svg": "favicon.svg" }); - eleventyConfig.addPassthroughCopy({ "infra/robots.txt": "robots.txt" }); - - return { - dir: { - input: "infra", - includes: "../shared/_includes", - output: "dist/infra" - }, - serverOptions: { - host: "0.0.0.0", - port: 8082 - } - }; -}; diff --git a/infra/index.njk b/infra/index.njk index f743915..173211b 100644 --- a/infra/index.njk +++ b/infra/index.njk @@ -1,6 +1,7 @@ --- title: "Homelab Infrastructure — Proxmox, Docker & Networking | moonweb" section: "infra" +tags: "infra" description: "Homelab infrastructure overview: Proxmox hosts, Synology NAS, Docker VMs and Setup-Guides." layout: base.njk sections: diff --git a/infra/lxc/index.njk b/infra/lxc/index.njk index 76853cf..8bebac4 100644 --- a/infra/lxc/index.njk +++ b/infra/lxc/index.njk @@ -1,7 +1,8 @@ --- title: "LXC Container Strategy" section: "infra" -parent: "/" +tags: "infra" +parent: "/infra/" description: "Overview of the lightweight LXC containers running on the main Proxmox host, and why they are LXC instead of Docker." layout: base.njk --- diff --git a/infra/monitoring/index.njk b/infra/monitoring/index.njk index 7f29ed7..1657d75 100644 --- a/infra/monitoring/index.njk +++ b/infra/monitoring/index.njk @@ -1,7 +1,8 @@ --- title: "Monitoring" section: "infra" -parent: "/" +tags: "infra" +parent: "/infra/" description: "Prometheus and Grafana monitoring stack for hosts, containers, and hardware metrics." layout: base.njk --- diff --git a/infra/openwrt/index.njk b/infra/openwrt/index.njk index 3990d01..dddbb8a 100644 --- a/infra/openwrt/index.njk +++ b/infra/openwrt/index.njk @@ -1,7 +1,8 @@ --- title: "OpenWrt Multi-WAN Router" section: "infra" -parent: "/" +tags: "infra" +parent: "/infra/" description: "Multi-WAN OpenWrt router in the study with WiFi and Powerline failover, plus VLAN 189 for IoT isolation." layout: base.njk --- diff --git a/infra/proxmox/index.njk b/infra/proxmox/index.njk index 0548872..3853fbb 100644 --- a/infra/proxmox/index.njk +++ b/infra/proxmox/index.njk @@ -1,7 +1,8 @@ --- title: "Proxmox Virtualization" section: "infra" -parent: "/" +tags: "infra" +parent: "/infra/" description: "What Proxmox VE is, the hardware it runs on in my homelab, its key advantages, and a short setup walkthrough." layout: base.njk --- diff --git a/infra/sitemap.xml.njk b/infra/sitemap.xml.njk index 7cbc214..10e9710 100644 --- a/infra/sitemap.xml.njk +++ b/infra/sitemap.xml.njk @@ -1,5 +1,6 @@ --- -permalink: /sitemap.xml +permalink: /infra/sitemap.xml +sitemapCollection: "infra" eleventyExcludeFromCollections: true --- {% include "sitemap.njk" %} diff --git a/infra/synology/index.njk b/infra/synology/index.njk index 2bad928..41601f2 100644 --- a/infra/synology/index.njk +++ b/infra/synology/index.njk @@ -1,7 +1,8 @@ --- title: "Synology NAS" section: "infra" -parent: "/" +tags: "infra" +parent: "/infra/" description: "Model, storage setup and current role of the Synology NAS in the homelab after the late-2025 cleanup." layout: base.njk --- diff --git a/package.json b/package.json index 2699bcc..efaf23e 100644 --- a/package.json +++ b/package.json @@ -4,24 +4,13 @@ "private": true, "description": "Monorepo for hub/infra/smarthome/code/retro/timecapsule (Eleventy, static, deployed to IONOS SFTP)", "scripts": { - "dev:hub": "npx @11ty/eleventy --config=hub/eleventy.config.js --serve --port=8081", - "dev:infra": "npx @11ty/eleventy --config=infra/eleventy.config.js --serve --port=8082", - "dev:smarthome": "npx @11ty/eleventy --config=smarthome/eleventy.config.js --serve --port=8083", - "dev:code": "npx @11ty/eleventy --config=code/eleventy.config.js --serve --port=8084", - "dev:retro": "npx @11ty/eleventy --config=retro/eleventy.config.js --serve --port=8085", + "dev": "npx @11ty/eleventy --serve --port=8081", "dev:stefankoelle": "npx @11ty/eleventy --config=stefankoelle/eleventy.config.js --serve --port=8086", "dev:timecapsule": "cd timecapsule && npx @11ty/eleventy --serve --port=8087", - "dev": "npm run dev:hub & npm run dev:infra & npm run dev:smarthome & npm run dev:code & npm run dev:retro & npm run dev:stefankoelle & npm run dev:timecapsule", - "build:hub": "npx @11ty/eleventy --config=hub/eleventy.config.js", - "build:infra": "npx @11ty/eleventy --config=infra/eleventy.config.js", - "build:smarthome": "npx @11ty/eleventy --config=smarthome/eleventy.config.js", - "build:code": "npx @11ty/eleventy --config=code/eleventy.config.js", - "build:retro": "npx @11ty/eleventy --config=retro/eleventy.config.js", + "build": "npx @11ty/eleventy", "build:stefankoelle": "npx @11ty/eleventy --config=stefankoelle/eleventy.config.js", "build:timecapsule": "cd timecapsule && npx @11ty/eleventy && mkdir -p ../../dist/timecapsule && cp -r _site/timecapsule/* ../../dist/timecapsule/", - "build": "npm run build:hub && npm run build:infra && npm run build:smarthome && npm run build:code && npm run build:retro && npm run build:timecapsule && npm run build:stefankoelle", - "build:moonweb": "npm run build:hub && npm run build:infra && npm run build:smarthome && npm run build:code && npm run build:retro && npm run build:timecapsule", - "merge:moonweb": "bash scripts/merge-moonweb.sh", + "build:moonweb": "npm run build && npm run build:timecapsule", "pdf:cv": "bash stefankoelle/pdf/build-pdf.sh", "prebuild": "bash prebuild.sh" }, diff --git a/retro/404.html b/retro/404.html index 30ca8ac..8a321b7 100644 --- a/retro/404.html +++ b/retro/404.html @@ -1,9 +1,10 @@ --- title: "Page Not Found" section: "retro" +tags: "retro" description: "The page you are looking for does not exist." layout: base.njk -permalink: /404.html +permalink: /retro/404.html ---

404

diff --git a/retro/amiga-hardware-landscape/index.njk b/retro/amiga-hardware-landscape/index.njk index 39790da..98fdb4b 100644 --- a/retro/amiga-hardware-landscape/index.njk +++ b/retro/amiga-hardware-landscape/index.njk @@ -1,9 +1,10 @@ --- title: "Running AmigaOS in 2026: MiSTer FPGA vs Amiberry on Pi" section: "retro" +tags: "retro" description: "Two very different ways to get a fully working AmigaOS 3.2.3 desktop running today." layout: base.njk -parent: "/" +parent: "/retro/" ---

Running AmigaOS in 2026: MiSTer FPGA vs Amiberry on Pi

diff --git a/retro/amiga-modern-platforms/index.njk b/retro/amiga-modern-platforms/index.njk index 0fa568f..577e0a0 100644 --- a/retro/amiga-modern-platforms/index.njk +++ b/retro/amiga-modern-platforms/index.njk @@ -1,9 +1,10 @@ --- title: "Vampire V4, A600GS or MiSTer: Amiga Hardware Isn't a Simple Speed Race" section: "retro" +tags: "retro" description: "Why raw benchmark numbers are actively misleading when comparing modern Amiga hardware options." layout: base.njk -parent: "/" +parent: "/retro/" ---

Vampire V4, A600GS or MiSTer: Amiga Hardware Isn't a Simple Speed Race

diff --git a/retro/atari-mega-st-fleet/index.njk b/retro/atari-mega-st-fleet/index.njk index acb3c81..bf242e1 100644 --- a/retro/atari-mega-st-fleet/index.njk +++ b/retro/atari-mega-st-fleet/index.njk @@ -1,9 +1,10 @@ --- title: "The Atari Mega ST Fleet: Three Machines, Three Jobs" section: "retro" +tags: "retro" description: "How three Atari Mega ST computers ended up with completely different roles in a modern retro setup." layout: base.njk -parent: "/" +parent: "/retro/" ---

The Atari Mega ST Fleet: Three Machines, Three Jobs

diff --git a/retro/atari-monitor-compatibility/index.njk b/retro/atari-monitor-compatibility/index.njk index 21911b0..8e73d0a 100644 --- a/retro/atari-monitor-compatibility/index.njk +++ b/retro/atari-monitor-compatibility/index.njk @@ -1,9 +1,10 @@ --- title: "The 15kHz Problem: Finding a Monitor That Speaks Atari" section: "retro" +tags: "retro" description: "Why most modern monitors refuse to display Atari ST colour modes, and which ones actually work." layout: base.njk -parent: "/" +parent: "/retro/" ---

The 15kHz Problem: Finding a Monitor That Speaks Atari

diff --git a/retro/atari-networking-bbs/index.njk b/retro/atari-networking-bbs/index.njk index 4ba1025..3f89807 100644 --- a/retro/atari-networking-bbs/index.njk +++ b/retro/atari-networking-bbs/index.njk @@ -1,9 +1,10 @@ --- title: "Getting a 40-Year-Old Computer Online: Atari ST Networking and BBS Access" section: "retro" +tags: "retro" description: "Connecting an Atari ST to the modern internet and to dial-up-era bulletin board systems, warts and all." layout: base.njk -parent: "/" +parent: "/retro/" ---

Getting a 40-Year-Old Computer Online: Atari ST Networking and BBS Access

diff --git a/retro/batocera-living-room/index.njk b/retro/batocera-living-room/index.njk index b8ca972..36b6cf9 100644 --- a/retro/batocera-living-room/index.njk +++ b/retro/batocera-living-room/index.njk @@ -1,9 +1,10 @@ --- title: "Batocera in the Living Room: One Box, Every Retro System" section: "retro" +tags: "retro" description: "Why the living room emulation station takes a completely different approach than the FPGA rigs upstairs." layout: base.njk -parent: "/" +parent: "/retro/" ---

Batocera in the Living Room: One Box, Every Retro System

diff --git a/retro/dos-486-tower/index.njk b/retro/dos-486-tower/index.njk index 156f3f2..858a834 100644 --- a/retro/dos-486-tower/index.njk +++ b/retro/dos-486-tower/index.njk @@ -1,9 +1,10 @@ --- title: "The 486 DX2-66: Rebuilding a DOS Era on MiSTer FPGA" section: "retro" +tags: "retro" description: "Recreating a Vobis-Highscreen 486 DX2-66 setup on MiSTer FPGA, down to the original DOS configuration." layout: base.njk -parent: "/" +parent: "/retro/" ---

The 486 DX2-66: Rebuilding a DOS Era on MiSTer FPGA

diff --git a/retro/eleventy.config.js b/retro/eleventy.config.js deleted file mode 100644 index 434386e..0000000 --- a/retro/eleventy.config.js +++ /dev/null @@ -1,20 +0,0 @@ -module.exports = function (eleventyConfig) { - eleventyConfig.addGlobalData("site", { url: "https://www.moonweb.org", pathPrefix: "/retro" }); - eleventyConfig.addFilter("date", (d) => d.toISOString()); - eleventyConfig.addPassthroughCopy({ "shared/theme-retro.css": "theme.css" }); - eleventyConfig.addPassthroughCopy({ "shared/base.css": "shared-base.css" }); - eleventyConfig.addPassthroughCopy({ "shared/favicon/retro.svg": "favicon.svg" }); - eleventyConfig.addPassthroughCopy({ "retro/robots.txt": "robots.txt" }); - - return { - dir: { - input: "retro", - includes: "../shared/_includes", - output: "dist/retro" - }, - serverOptions: { - host: "0.0.0.0", - port: 8085 - } - }; -}; diff --git a/retro/et4000-experiment/index.njk b/retro/et4000-experiment/index.njk index 3ec5ce3..5ed0dde 100644 --- a/retro/et4000-experiment/index.njk +++ b/retro/et4000-experiment/index.njk @@ -1,9 +1,10 @@ --- title: "Why an ET4000 Graphics Card and a Mega ST Don't Mix (Yet)" section: "retro" +tags: "retro" description: "A cautionary tale about pushing 1980s power supplies past their limits with a modern-ish graphics card." layout: base.njk -parent: "/" +parent: "/retro/" ---

Why an ET4000 Graphics Card and a Mega ST Don't Mix (Yet)

diff --git a/retro/index.njk b/retro/index.njk index be06473..b241dd6 100644 --- a/retro/index.njk +++ b/retro/index.njk @@ -1,6 +1,7 @@ --- title: "Retro Computing — Vintage Hardware & FPGA | moonweb" section: "retro" +tags: "retro" description: "Physical retro hardware collection — Raspberry Pi units, Pi 400, and vintage computing setups." layout: base.njk sections: diff --git a/retro/mini-arcade-handheld-roundup/index.njk b/retro/mini-arcade-handheld-roundup/index.njk index ab3d8ce..82457c9 100644 --- a/retro/mini-arcade-handheld-roundup/index.njk +++ b/retro/mini-arcade-handheld-roundup/index.njk @@ -1,9 +1,10 @@ --- title: "Mini Arcades and Handhelds: Sorting the Real Deal from the Bootlegs" section: "retro" +tags: "retro" description: "A buyer's guide to compact retro gaming devices, and why the cheapest option is almost never the right one." layout: base.njk -parent: "/" +parent: "/retro/" ---

Mini Arcades and Handhelds: Sorting the Real Deal from the Bootlegs

diff --git a/retro/mist-mister-fpga/index.njk b/retro/mist-mister-fpga/index.njk index ba5b5c3..58a425c 100644 --- a/retro/mist-mister-fpga/index.njk +++ b/retro/mist-mister-fpga/index.njk @@ -1,9 +1,10 @@ --- title: "MiST and MiSTer: Two FPGA Boxes, Two Very Different Personalities" section: "retro" +tags: "retro" description: "Why the newer, more powerful MiSTer isn't automatically the better choice for every retro system." layout: base.njk -parent: "/" +parent: "/retro/" ---

MiST and MiSTer: Two FPGA Boxes, Two Very Different Personalities

diff --git a/retro/pimiga-journey/index.njk b/retro/pimiga-journey/index.njk index 38000a7..4e21dba 100644 --- a/retro/pimiga-journey/index.njk +++ b/retro/pimiga-journey/index.njk @@ -1,9 +1,10 @@ --- title: "PiMiga 3 to 5: Chasing the Perfect Amiga-on-a-Pi Distro" section: "retro" +tags: "retro" description: "Three generations of PiMiga later, here's what actually changed — and why newer isn't always better." layout: base.njk -parent: "/" +parent: "/retro/" ---

PiMiga 3 to 5: Chasing the Perfect Amiga-on-a-Pi Distro

diff --git a/retro/retro-corner-snapshot/index.njk b/retro/retro-corner-snapshot/index.njk index 82ea0f7..fee3a18 100644 --- a/retro/retro-corner-snapshot/index.njk +++ b/retro/retro-corner-snapshot/index.njk @@ -1,9 +1,10 @@ --- title: "The Retro Corner Today: A Snapshot of the Whole Setup" section: "retro" +tags: "retro" description: "A tour through every retro system currently active across the home, room by room." layout: base.njk -parent: "/" +parent: "/retro/" ---

The Retro Corner Today: A Snapshot of the Whole Setup

diff --git a/retro/sitemap.xml.njk b/retro/sitemap.xml.njk index 7cbc214..5e87748 100644 --- a/retro/sitemap.xml.njk +++ b/retro/sitemap.xml.njk @@ -1,5 +1,6 @@ --- -permalink: /sitemap.xml +permalink: /retro/sitemap.xml +sitemapCollection: "retro" eleventyExcludeFromCollections: true --- {% include "sitemap.njk" %} diff --git a/retro/the-a1200/index.njk b/retro/the-a1200/index.njk index 601cd3c..0c100a7 100644 --- a/retro/the-a1200/index.njk +++ b/retro/the-a1200/index.njk @@ -1,9 +1,10 @@ --- title: "The A1200: What We Know Before It Ships" section: "retro" +tags: "retro" description: "A close look at Retro Games Ltd.'s upcoming Amiga 1200 console, based on everything public so far." layout: base.njk -parent: "/" +parent: "/retro/" ---

The A1200: What We Know Before It Ships

diff --git a/scripts/merge-moonweb.sh b/scripts/merge-moonweb.sh deleted file mode 100755 index d2b50f8..0000000 --- a/scripts/merge-moonweb.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash -set -e - -echo "Merging moonweb sites for deployment..." - -# Clean previous merge -rm -rf dist/root - -# Hub becomes root -echo " hub → dist/ (root)" -cp -r dist/hub dist/root -rm -rf dist/hub - -# Copy timecapsule from its build output -if [ -d "timecapsule/_site/timecapsule" ]; then - echo " timecapsule → dist/root/timecapsule/" - cp -r timecapsule/_site/timecapsule dist/root/timecapsule -else - echo " WARNING: timecapsule/_site/timecapsule not found, skipping" -fi - -# Subdirectories -for site in infra smarthome code retro; do - if [ -d "dist/$site" ]; then - echo " $site → dist/root/$site/" - cp -r "dist/$site" "dist/root/$site" - else - echo " WARNING: dist/$site not found, skipping" - fi -done - -# Copy CSS to root (accessible from all subdirectories) -echo " Copying shared CSS to root..." -cp shared/base.css dist/root/shared-base.css -cp shared/favicon/hub.svg dist/root/favicon.svg - -# Theme CSS files are already copied during build as theme.css -# The root theme is hub's theme -if [ -f "dist/root/theme.css" ]; then - echo " Root theme.css already in place" -fi - -echo "" -echo "Merge complete. Final structure:" -find dist/root -maxdepth 2 -type f | sort | head -50 -echo "..." -echo "" -echo "Total files:" -find dist/root -type f | wc -l diff --git a/shared/_includes/base.njk b/shared/_includes/base.njk index 19e1840..70fe200 100644 --- a/shared/_includes/base.njk +++ b/shared/_includes/base.njk @@ -20,8 +20,8 @@ - - + +