19 KiB
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 |
|
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
.mdfiles 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
publishtable 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
garagedisk (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.mdfreeze 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/.pihome/sam/home_network/web_sites/kontra_day/.pi/memory-vaulthome/sam/home_network/web_sites/kontra_day/.pi/memory-vault/packshome/sam/home_network/web_sites/kontra_day/.pi/memory-vault/packs/kontra-dayhome/sam/home_network/web_sites/kontra_day/.pi/memory-vault/packs/kontra-day/00-systemhome/sam/home_network/web_sites/kontra_day/.pi/memory-vault/packs/kontra-day/00-system/pi-agenthome/sam/home_network/web_sites/kontra_day/.pi/taskshome/sam/.agentsextensions/pi-config/index.tsextensions/ask-user-question/index.tssys/firmware/efi/efivarspublish/front-page/archiveadmin/mail/ecosystemadmin/publish/medialive/front-page/archive
Evidence
- Confidence: 82%
- Reason: Captured factual repo structure/configuration patterns from rich discovery
Related
Related learned memories
- session: packs/kontra-day/80-sessions/rich-discovery-access-2026-09-08-02-23-28
- context: packs/kontra-day/20-context/access
- runbook: packs/kontra-day/70-runbooks/access-deployment-operations
- observation: packs/kontra-day/60-observations/access-repository-structure-and-configuration-patterns
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: falsefront-matter → hidden from public, visible as preview onadmin.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/keystaticgithub.com/wintercms/winterplugins/winter/demowww.luckymedia.dev/insights/decap-cmsusers/roles/authslug/meta/sitemap/RSS
Evidence
- Confidence: 82%
- Reason: Captured factual repo structure/configuration patterns from rich discovery
Related learned memories
- session: packs/kontra-day/80-sessions/rich-discovery-files-2026-09-08-03-36-06
- context: packs/kontra-day/20-context/files
- runbook: packs/kontra-day/70-runbooks/access-deployment-operations
- observation: packs/kontra-day/60-observations/access-repository-structure-and-configuration-patterns
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
.mdvia{{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
- Which host runs Garage S3 (needs confirming — it's not in the skill list yet).
- Where the Go binary + Decap run on .13 — as a systemd service (
usersgroup,/var/www/kontra_dayper the existing perms note) or Docker. - Caddy config — which Caddy instance (skill says Caddy is on .35) owns the
kontra.day/admin.kontra.dayvhosts, and how it upstreams to .13. - Obsidian vault wiring — make
/home/sam/obsidian/.../kontra_daya git clone of the Gitea repo (Obsidian already git-links to Gitea, so this is a natural fit). - Deploy trigger — Gitea webhook → .13 vs. a simple systemd timer
git pullevery 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.jsonhome/sam/.agentsgitea.lab.audasmedia.com.au/sam/pi-configsys/firmware/efi/efivars.config/lsyncd/lsyncd.conf.luazola/sprinkler/public.config/environment.d/10-secrets.conf.27/.13/.51Gitea/Obsidian/Caddyhome/sam/obsidianvar/www/kontra_dayhome/sam/obsidian/.../kontra_day
Evidence
- Confidence: 82%
- Reason: Captured factual repo structure/configuration patterns from rich discovery
Related learned memories
- session: packs/kontra-day/80-sessions/rich-discovery-individually-2026-09-08-03-44-05
- context: packs/kontra-day/20-context/individually
- runbook: packs/kontra-day/70-runbooks/individually-deployment-operations
- observation: packs/kontra-day/60-observations/access-repository-structure-and-configuration-patterns
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:
- You keep designing panels in Stitch → screenshot what you like.
- 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). - I generate alternative directions via this skill's
image-makerso you can compare. - 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-mdgithub.com/VoltAgent/awesome-design-mdjustinmckelvey.com/blog/google-stitch-vs-figmaHTML/CSS/Tailwind
Evidence
- Confidence: 82%
- Reason: Captured factual repo structure/configuration patterns from rich discovery
Related learned memories
- session: packs/kontra-day/80-sessions/rich-discovery-getdesign-md-2026-09-08-05-34-12
- context: packs/kontra-day/20-context/getdesign-md
- runbook: packs/kontra-day/70-runbooks/getdesign-md-deployment-operations
- observation: packs/kontra-day/60-observations/access-repository-structure-and-configuration-patterns