Files
kontra/.pi/memory-vault/packs/kontra-day/60-observations/access-repository-structure-and-configuration-patterns.md

19 KiB
Raw Blame History

type, id, title, status, source_of_truth, freshness, last_reviewed, tags
type id title status source_of_truth freshness last_reviewed tags
observation observation.kontra-day.access-repository-structure-and-configuration-patterns access repository structure and configuration patterns active false current 2026-09-08
pack/kontra-day
agent-memory/observation
autolearn
rich-discovery
repo/access

access repository structure and configuration patterns

Structural/configuration observations (2026-09-08 02:23:28)

Great questions — let me answer each properly, because they cut right to the architecture.

1. GOTTH + .md files — yes, this is a strong fit

Go + templ + htmx + Alpine + Tailwind, with Goldmark (Go's CommonMark renderer) turning your .md into HTML at request time, is one of the best "text-first news site" stacks you can pick right now:

  • One static binary — build once, copy to .13, done. No Node, no PHP runtime, no container even needed.
  • Server-rendered HTML — SEO-friendly by default (great Lighthouse), fast.
  • templ gives type-safe components; htmx gives interactivity (paging, filters, comment forms later) without a JS framework; Alpine for small client bits.
  • Content = files — your Obsidian/editor workflow stays; go can even re-render on file change in dev.
  • Cost: the admin is DIY — auth, CRUD, media browser are all code you write. And per-request markdown parsing is fine at this scale (cache rendered HTML if you care).

2. Laravel as the "orchestrator" — honest answer: it's the wrong tool for that role

Laravel is excellent at being a web app (Blade+htmx admin, auth, queues, and — importantly — a genuinely great mail system for that email phase later). But you're proposing it as a publish-state manager perched over Go:

  • You'd run two servers (Go on :80, Laravel admin on :8080) both touching the same .md files and a shared DB. Every publish toggle, front-page order, archive move = a DB write Laravel makes and Go reads.
  • That works, but it's redundant — Go can own a small SQLite publish table itself, with an htmx admin page inside the same binary. One language, one process, zero sync.

So the real fork is:

Path Architecture When to pick
A. All Go Go serves site + a minimal htmx admin page managing publish/front-page/archive in SQLite. .md = content truth. You want the leanest thing. Email later = Go mail libs, or hand off to n8n/Postfix on your network.
B. Laravel owns it all Blade + htmx admin, Laravel serves pages, S3 media via its filesystem driver, Mailables for email later. Drop Go. You want Laravel's admin/mail/ecosystem and don't mind PHP runtime.
C. Go site + headless admin Go serves; PocketBase (already on .13) is the admin/publish/media store. You want a browser admin without writing one.
D. Go + Laravel, loosely coupled Go serves; Laravel admin only writes publish-state to a shared SQLite file + edits .md on disk. You specifically want Laravel's admin UX and Go's front. Viable, but it's path A with extra running parts.

"Is Laravel good for this?" — good at admin, great at email, overkill as a proxy. "Other PHP?" — Symfony (bulkier), Slim (micro), WordPress (off-the-shelf but you'd be fighting it). If PHP is the choice, Laravel+Filament is the right one.

3. Garage S3 media + .md coordination under Laravel

  • Showing media in admin: Laravel has a first-class S3 filesystem driver — configure a garage disk (endpoint, keys, bucket) and the admin lists objects and renders thumbnails. Public reads via a Caddy/nginx route (/media/* → bucket) rather than exposing Garage's own port; private buckets can use presigned URLs.
  • Coordination with .md: the cleanest pattern is shortcodes, not raw URLs. In your file you write {{media:cover}} or {{vimeo:12345}}; the renderer (Go or Laravel) resolves the slug to the actual S3 URL at render time. That way you can rename/migrate media later without touching every article — plain URLs pasted into .md freeze the path forever. Upload flow: admin uploads to bucket → returns URL → editor pastes it in the .md. Simple and inspectable.

4. Is markdown good? And what's the "scientific" one?

  • Yes — Markdown (GFM/CommonMark) + front-matter is ideal for text news/opinion with links, images, embeds.
  • Variants, in case the name escapes you: MDX (JSX components inside markdown), AsciiDoc (more structure — tables, includes; great for docs, overkill here), Org-mode, reStructuredText.
  • The new scientific one is almost certainly Typst (2023) — a modern typesetting language with gorgeous math, designed for documents/PDF. You can render it to SVG for web, but for a news site it's the wrong tool.
  • If you meant LSP (Language Server Protocol) — that's an editor autocomplete standard, not a format; ignore it here.
  • For the odd formula: keep markdown and add KaTeX/MathML via $...$ in Goldmark's math extension. You get scientific notation with zero new language.

5. My recommendation

Path A — all Go (templ + htmx + Alpine + Tailwind), .md files as content, SQLite publish-state with a small htmx admin for live/front-page/archive, {{media:...}} shortcodes resolved to Garage S3. Deploy = one binary behind Caddy on .13. Email phase later = Go mail lib or n8n handoff — revisit then, when requirements are real.

Want me to draft PLAN.md on Path A — or would you rather spec out Path B (Laravel-everything) or Path C (Go + PocketBase) instead?

Source paths observed

  • home/sam/home_network/web_sites/kontra_day/.pi
  • home/sam/home_network/web_sites/kontra_day/.pi/memory-vault
  • home/sam/home_network/web_sites/kontra_day/.pi/memory-vault/packs
  • home/sam/home_network/web_sites/kontra_day/.pi/memory-vault/packs/kontra-day
  • home/sam/home_network/web_sites/kontra_day/.pi/memory-vault/packs/kontra-day/00-system
  • home/sam/home_network/web_sites/kontra_day/.pi/memory-vault/packs/kontra-day/00-system/pi-agent
  • home/sam/home_network/web_sites/kontra_day/.pi/tasks
  • home/sam/.agents
  • extensions/pi-config/index.ts
  • extensions/ask-user-question/index.ts
  • sys/firmware/efi/efivars
  • publish/front-page/archive
  • admin/mail/ecosystem
  • admin/publish/media
  • live/front-page/archive

Evidence

  • Confidence: 82%
  • Reason: Captured factual repo structure/configuration patterns from rich discovery

Update (2026-09-08 03:36:06)

Structural/configuration observations (2026-09-08 03:36:06)

Great — this is the model clicking into place. Short version: the folder on disk is the website. Everything else is just an editor on top of it. Here's each question answered.

The mental model

        content/  (single git repo, remote = Gitea on your network)
           │
   ┌───────┼───────────┬────────────────┐
   │       │           │                │
Neovim  Obsidian   Decap (web)      Go binary
(files)  (vault)   (admin.domain)   (renders on request)
   │       │           │                │
   └───────┴───────────┴────────────────┘
        all write the SAME .md files
  • Neovim: edit a file → save → Go already sees it. The site always reflects the working tree — so nothing ever goes stale.
  • Obsidian: the same folder opens as a vault (it's plain markdown ✓), with Gitea as its git remote, exactly as you use it today.
  • Decap: a browser UI over the same files — click collection → articles, edit fields as forms, markdown body editor; on save it commits to git. No duplication, no import/export.
  • Go binary: renders markdown → HTML per request. It never "re-outputs" a static build, because there's no build step to run. (Optional in-memory cache later if you want it snappier.) Optional niceties: published: false front-matter → hidden from public, visible as preview on admin.kontra.day; publish_at: 2026-… → scheduled go-live.

"Editing in Neovim — will Decap/Obsidian sync?"

Almost. Everything reads the working tree, so Neovim saves are instantly live either way. The one wrinkle: Decap shows committed state, so an uncommitted Neovim edit may not show in the Decap UI until someone commits. Fix = a tiny file-watcher (inotify/systemd Path unit) on content/ that autocommits to git on any change from any editor. Then: any editor → autocommit → Gitea push → Decap in sync → Go serves. That one script is the "sync" you're imagining, and it's ~10 lines.

"How are templates created for the GOTH stack? Can we design them?"

Yes — this is exactly Phase Two of your AGENT.md, and it's data + code:

Template What it's made of
home (front page composition) templ component + editable blocks list
article / opinion / photo-essay / video templ component, chosen per page in front-matter
subject-index (each subject area) templ component + subject setting
archive, about, 404 templ components
Look & feel Tailwind + CSS design-token variables (--accent etc.)

Flow: we list the template set → I design 2–3 looks (demos/images) → you approve → they get built as .templ components in the binary, themed with tokens so colours/subject accents are admin-editable data, not code.


The architecture is now concrete enough to write down. Per your AGENT.md Phase One, next step is PLAN.md + Vikunja/Outline entries documenting this decision set. Want me to draft PLAN.md and register the phase tasks now — or do you want to change anything in this model first?

Source paths observed

  • www.wisp.blog/compare/winter/keystatic
  • github.com/wintercms/winter
  • plugins/winter/demo
  • www.luckymedia.dev/insights/decap-cms
  • users/roles/auth
  • slug/meta/sitemap/RSS

Evidence

  • Confidence: 82%
  • Reason: Captured factual repo structure/configuration patterns from rich discovery

Update (2026-09-08 03:44:05)

Structural/configuration observations (2026-09-08 03:44:05)

Confirmed the full topology. Here's the storage/sync reality and the plan for it.

The actual topology (verified)

Machine Role Relevant bits
.27 (this) Main dev, Obsidian + Neovim live here Obsidian vault at /home/sam/obsidian/
.13 Web host, always-on Sites in /var/www/, runs PocketBase, Caddy sits upstream
.35 Gitea (Docker, web :3001, SSH :2222) + Caddy reverse proxy gitea.lab.audasmedia.com.au
Garage S3 media bucket — need to confirm which host (Phase One item)

Where things should live — the key decision

The mistake to avoid: coupling the live site to .27 (your dev machine). So:

  • Gitea repo on .35 = the single source of truth for content (.md + config + media references). This is the "origin".
  • .27 = authoring clients (Obsidian vault + Neovim) — it's a clone of that repo, pushes to .35.
  • .13 = the always-on production clone at /var/www/kontra_day/, which the Go binary serves.
  • Caddy on .35 routes kontra.day → Go on .13, admin.kontra.day → Decap on .13.
  • Garage S3 = media objects, referenced from .md via {{media:...}} shortcodes.

How sync actually works (this is the part that matters)

Editor on .27          Gitea on .35          Production on .13
Neovim / Obsidian  ──push──▶  origin  ──webhook/poll──▶  git pull
   (clone)                          ▲                        │
                                    │                        ▼
Decap (admin.kontra.day)  ──commit──┘                 Go binary renders .md → HTML
  • Any change from any editor (Neovim save, Obsidian sync, Decap save) lands on Gitea, then auto-deploys to .13 via webhook + systemd Path watcher that runs git pull.
  • .13 never needs your .27 — it pulls straight from Gitea. Your dev machine can be off and the site stays live. ✅ this addresses exactly your concern.
  • No build step: Go re-renders .md → HTML per request (with an optional cache), so a pull = instant content update.
  • This is a strict upgrade over the current manual lsyncd .27→.13 pattern — you'd retire that for this site (same wiring though: systemd on .13).

Things that must be decided/verified in Phase One

  1. Which host runs Garage S3 (needs confirming — it's not in the skill list yet).
  2. Where the Go binary + Decap run on .13 — as a systemd service (users group, /var/www/kontra_day per the existing perms note) or Docker.
  3. Caddy config — which Caddy instance (skill says Caddy is on .35) owns the kontra.day/admin.kontra.day vhosts, and how it upstreams to .13.
  4. Obsidian vault wiring — make /home/sam/obsidian/.../kontra_day a git clone of the Gitea repo (Obsidian already git-links to Gitea, so this is a natural fit).
  5. Deploy trigger — Gitea webhook → .13 vs. a simple systemd timer git pull every 30s (fewer moving parts, good enough).

Recommendation

Gitea (.35) as origin → .13 always-on clone as live → .27 clients as editors. That keeps production decoupled from your dev box, gives you history/rollback on every .md, and matches the Gitea/Obsidian habits you already have.

Want me to fold this into PLAN.md now (with the open questions marked), and register the Phase One tasks in Vikunja/Outline?

Source paths observed

  • 2222/sam/pi-config.git
  • .pi/agent/settings.json
  • home/sam/.agents
  • gitea.lab.audasmedia.com.au/sam/pi-config
  • sys/firmware/efi/efivars
  • .config/lsyncd/lsyncd.conf.lua
  • zola/sprinkler/public
  • .config/environment.d/10-secrets.conf
  • .27/.13/.51
  • Gitea/Obsidian/Caddy
  • home/sam/obsidian
  • var/www/kontra_day
  • home/sam/obsidian/.../kontra_day

Evidence

  • Confidence: 82%
  • Reason: Captured factual repo structure/configuration patterns from rich discovery

Update (2026-09-08 05:34:12)

Structural/configuration observations (2026-09-08 05:34:12)

Skill active — and let me answer your Stitch workflow question with verified facts, because it determines how we run Phase Two.

What Google Stitch can actually export (as of the latest updates)

Export Works? Note
Copy code / download (HTML/CSS/Tailwind) ✅ Yes Its core output. Real components, not images — and Tailwind is exactly our stack.
To Figma ⚠️ Flaky Direct Stitch→Figma has been unreliable/long-queued (known bug threads); an MCP route exists. Not dependable.
To Google AI Studio ✅ Yes (Stitch 2.0+) Can push designs into AI Studio projects.
Project brief / DESIGN.md ❌ No direct feature Doesn't produce one — but this is what I do for you: I write the DESIGN.md (tokens + brief) from your Stitch panels, and that's what design-build consumes later.

What I'd actually recommend for Kontra Day

Stitch's real value here is visual exploration + a Tailwind reference. The practical pipeline:

  1. You keep designing panels in Stitch → screenshot what you like.
  2. I turn the approved panels into a DESIGN.md — exact palette, typography, spacing, radius + a written identity brief (the "project brief" you mentioned, as the file format this workflow already uses).
  3. I generate alternative directions via this skill's image-maker so you can compare.
  4. Build uses the tokens + Stitch's Tailwind export as reference → real templ components. (Stitch's HTML won't drop straight into templ, but it's a strong visual contract.)

So: yes — copy the Tailwind code and/or push to AI Studio, but treat both as reference; the lasting artifact is DESIGN.md. Figma isn't worth the friction for a solo project unless you like working there.

Fonts & readability (your instinct is right to think about this)

For a news-opinion site, the classic readable pairing:

  • Headlines: a strong serif or display face (e.g. Newsreader, Source Serif, Playfair) at large weight
  • Body: a humanist sans or print-style serif at 17–18px, ~65–75 chars/line, 1.5–1.65 line height — this is the actual readability driver, more than the font choice itself
  • Self-host the fonts (no Google CDN at runtime — performance + privacy), using variable fonts where possible
  • Typography choices go into DESIGN.md as tokens, so colours/fonts stay data-driven per our plan

So how do you want to start?

[tool:ask_user_question]

Source paths observed

  • getdesign.md/apple/design-md
  • github.com/VoltAgent/awesome-design-md
  • justinmckelvey.com/blog/google-stitch-vs-figma
  • HTML/CSS/Tailwind

Evidence

  • Confidence: 82%
  • Reason: Captured factual repo structure/configuration patterns from rich discovery