leDailySquirrel/STATUS.md
Dirty REdOG 71df81e9dd
All checks were successful
Deploy to Cloudflare Pages / publish (push) Successful in 44s
status md
2026-07-04 22:39:09 -05:00

5.6 KiB

Le Daily Squirrel — Project Status

Date: 2026-07-04 Repo: AutomationWise/leDailySquirrel on Forgejo (gf.automationwise.com) Production: https://news.opelousas.org (Cloudflare Pages, project news-opelousas-org)

A satirical daily newspaper for Opelousas — vintage faded-newsprint aesthetic, edition-based publishing, self-hosted GitOps pipeline, with AI journalist agents planned as the content authors.


Architecture

Piece Where Notes
Git forge (Forgejo 9) kiln (Fedora), rootless Podman Quadlet HTTP 127.0.0.1:3000 behind Caddy at gf.automationwise.com; SSH on host port 3022 (LAN only, blocked at edge)
Reverse proxy Caddy on kiln Owns 80/443, auto TLS; also fronts Vaultwarden and Tuwunel
CI runner kiln, Podman Quadlet (forgejo-runner 3.4.1) Org-level runner kiln-worker, label ubuntu-latest:docker://node:20-bookworm, uses host Podman socket (UserNS=keep-id, SecurityLabelDisable=true, socket path identical inside/outside container)
Static site generator Eleventy v3.1.6 Input content/, includes ../_includes, output dist/
Hosting Cloudflare Pages, Direct Upload mode Deployed via wrangler pages deploy dist --project-name=news-opelousas-org --branch main from .forgejo/workflows/deploy.yml on push to main
Dev box anvil Git remote over SSH: ssh://git@gf.automationwise.com:3022/... with ~/.ssh/config host override to kiln's LAN IP (NAT hairpin workaround)

Secrets: CF_ACCOUNT_ID + CF_API_TOKEN in Forgejo repo Actions secrets. Token permissions: Account→Cloudflare Pages→Edit, Account→Workers Scripts→Edit, User→User Details→Read, scoped to the account.

Site mechanics

  • Editions live at content/editions/YYYY-MM-DD/index.md; URLs are /editions/YYYY-MM-DD/.
  • Front matter: layout: edition, edition_number (int), volume (int — must be a number, the roman filter converts; storing "I" breaks it), date, status: draft|published, title.
  • Collections (eleventy.config.js): publishedEditions (all published, newest first), currentEdition (newest one only).
  • Homepage (content/index.njk): paginates over currentEdition (size 1) and renders it at / — render, not redirect. content/index.11tydata.js maps title, date, edition_number, volume up from the paginated item.
  • Filters: newsDate (UTC-forced long date — fixes the CST off-by-one-day), roman (int → Roman numeral).
  • 404: content/404.mddist/404.html. Required — without it Cloudflare Pages SPA-fallbacks every unknown path to / with a 200 (this was the "every URL shows the current edition" bug). Todo → more Squirreliness.
  • Masthead: inline SVG (Inkscape export, single path, mm-scale coordinates, viewBox="0 0 381 170"). Fill flows from fill="var(--ink)" on the <g> (path's inline fill style removed). CSS squirrel-flip animation rotates it 180° on a 50/50 duty cycle (~24s period), with a prefers-reduced-motion opt-out.
  • Lifecycle tooling: make publication (scaffolds next edition, enforces one open draft, creates edition/<date>/open branch), make publish (seds status: draftpublished), make build / make serve.

Hard-won gotchas (do not relearn these)

  • Quadlet units can't be systemctl enabled — the [Install] block in the .container file handles boot; just daemon-reload + start. Lingering is enabled for the user on kiln.
  • Rootless Podman + SELinux: never :Z a socket mount; socket path must match host↔container when the runner asks the host to mount it into job containers.
  • Wrangler CI deploys need --branch main or they land as Preview, not Production.
  • Eleventy config must be a single module.exports; run builds from repo root only.
  • Front matter beats directory data files (editions.json) — data bugs hide there.

Current status

Working end-to-end: push to main → runner builds → Cloudflare production deploy. Volume renders as Roman numerals, archive URLs serve the correct historical edition, fake URLs 404, custom domain live, SVG masthead in place with periodic flip.

In development / not yet done:

  1. Edition immutability (freeze-at-publish) — designed, not implemented. Plan: make publish builds once, snapshots rendered HTML to committed frozen/editions/<date>/, marks source frozen: true; editions.11tydata.js returns permalink: false for frozen editions; addPassthroughCopy({ "frozen/editions": "editions" }) serves snapshots verbatim. Homepage stays dynamic; only /editions/<date>/ freezes. Past editions from the pre-freeze era are expendable (still in dev).
  2. Archive ledger — no /archive/ (or /editions/) index page listing past editions yet.
  3. AI journalist pipeline — the actual point of the project. Agents ingest daily material, write articles in the three-column structure, and open PRs against the open edition/<date>/open draft branch. Likely imp (OpenClaw on liminal) via NadirClaw routing, following the spec-first handoff pattern. Not started.
  4. Maintenance-mode toggle — deferred; plan is a Cloudflare Page Rule redirect to a /maintenance/ page.
  5. Masthead spacing polish — minor viewBox/padding nudges deferred.

Suggested next steps, in order

  1. Implement the freeze-at-publish flow while there's only throwaway content to test against (touching publish.sh, eleventy.config.js, new content/editions/editions.11tydata.js).
  2. Build the archive index page off collections.publishedEditions.
  3. Define the agent contract: article markdown format, column assignment, front-matter rules, PR-to-draft-branch workflow — then wire the first agent.