🕵️ SicherheitslückenHak5: Hackers Just Poisoned the Rust Supply Chain | Threat Wire(01.09.2026 um 14:00 Uhr)
🕵️ SicherheitslückenHak5: Hackers Found a Way Into Humanoid Robots | Threat Wire(04.09.2026 um 15:04 Uhr)
🔧 AI Nachrichten Bits und so #1021 (Passwort für Laufwerk)(31.08.2026 um 22:15 Uhr)
🔧 AI Nachrichten Bits und so #1022 (Wie Weißbier)(06.09.2026 um 20:39 Uhr)
🍏 iOS / Mac OSHue-App 6.0 ist da: das sind die Neuerungen(07.09.2026 um 17:21 Uhr)
🕵️ SicherheitslückenHak5: Hackers Just Poisoned the Rust Supply Chain | Threat Wire(01.09.2026 um 14:00 Uhr)
🕵️ SicherheitslückenHak5: Hackers Found a Way Into Humanoid Robots | Threat Wire(04.09.2026 um 15:04 Uhr)
🔧 AI Nachrichten Bits und so #1021 (Passwort für Laufwerk)(31.08.2026 um 22:15 Uhr)
🔧 AI Nachrichten Bits und so #1022 (Wie Weißbier)(06.09.2026 um 20:39 Uhr)
🍏 iOS / Mac OSHue-App 6.0 ist da: das sind die Neuerungen(07.09.2026 um 17:21 Uhr)

🔧 Programmierung 🕛 kürzlich 17 Min Lesezeit
0

I Contain Multitudes (and Also Three Git Repos)

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht

My blog is older than most of the tools I use to run it. The oldest posts started life on LiveJournal sometime in the early 2000s, got dragged through a WordPress import at some point in the mid-2000s, spent the better part of a decade as a Hugo site, and, about a week ago, moved into an Astro 5 site that reproduces every one of those old URLs byte for byte. That's 2,630 posts spanning 2001 to 2020, frozen exactly where they landed.



At the same time, :





  • mattstratton.com is the personal site. It carries the 2,630-post legacy archive and a newer, general-purpose /writing/ section for anything I want to write that isn't archival.


  • speaking.mattstratton.com is the talk archive: every deck, every video, every event, self-hosted.


  • mattstratton-dev-to isn't a website at all. It's a small tool that keeps dev.to drafts and this git repo in sync, and it's the thing that lets a post published on dev.to also show up natively on sets trailingSlash: 'always' and builds in directory format specifically to reproduce the old Hugo URLs exactly, which in turn had reproduced the WordPress URLs before that. Old inbound links, whether from a 2009 blog roll or a conference site linking a talk recap from 2014, still resolve. Nobody has to fix a dead link because I decided to rewrite my site in a different framework.



    The posts collection is the frozen 2001 to 2020 archive, bulk-converted from Hugo. It doesn't grow. It just needs to keep existing. Everything new goes into writing, and that one's got more going on than I expected when I started writing this post.






    The field guide: my own posts plus the good stuff I wrote elsewhere



    /writing/ used to be scoped much more narrowly. The working plan before this project had it locked to Postgres-focused, authority-building content, an idea inherited from a content strategy document written for a completely different audience than the one reading my personal blog. The pushback that killed that scoping was simple: I contain multitudes, and a personal site that can only hold one topic isn't really personal anymore.



    What's actually interesting about /writing/ now, though, is that it isn't only my own posts. It's a merge of two genuinely different things:




    • Native entries in src/content/writing/, defined by the schema in :




    CODE
    export interface FieldGuideLink {
    title: string;
    description: string;
    part: "mechanics" | "limits" | "traps" | "decision";
    url: string;
    }






    There are 14 of those right now, all pointing at tigerdata.com, each slotted into one of the same four part buckets native posts can opt into. is an Astro content-layer loader that calls one endpoint, GET /emails?ordering=-publish_date against Buttondown's API, follows pagination until it runs out of pages, and hands the result to Astro as the newsletter collection. Every issue page, the archive index, and the RSS feed are then just static output from a normal getCollection() call, same as any local markdown file.



    Two details worth calling out for anyone tempted to do the same thing:




    • If BUTTONDOWN_API_KEY isn't set, the loader logs a warning and returns an empty collection instead of failing the build. That's not an accident: it means anyone can clone this repo and build it locally without needing my API key.

    • Buttondown stores each issue's body as Markdown, so the loader runs it through marked.parse() before it ever reaches a template. The site never touches raw HTML from the API.




    CODE
    const key = import.meta.env.BUTTONDOWN_API_KEY ?? process.env.BUTTONDOWN_API_KEY;
    if (!key) {
    logger.warn("BUTTONDOWN_API_KEY not set: newsletter archive will build empty.");
    return;
    }









    speaking.mattstratton.com: getting my slides back from a CDN I don't own



    The old speaking site lived on Notist, and Notist had two problems that eventually became one problem: video embeds had already started quietly breaking, and every slide deck was served off Notist's CDN. The day that account lapses, the images and PDFs go with it. A core part of a speaker's professional identity, every talk I've ever given, was living in someone else's database with a thin export option.



    So the new site's whole design goal is asset ownership and durability. Plain content in my own repo, on my own domain, that keeps working with no third-party dependency that can be shut off or go quietly stale. Not a redesign. A portability project.



    The interesting piece is the slide pipeline, because it runs entirely locally, before a commit ever happens, and never on the deploy host:




    CODE
    originals/{id}.pdf --optimize(gs, 300dpi)--> public/slides/{id}.pdf --rasterize--> public/slides/{id}/{n}.webp
    (gitignored, full-res) (committed, served, downloadable) (committed, served, viewer images)






    The reason it has to run locally: static hosts don't give you root, and you need root (or at least a real package manager) to run pdftoppm and gs. Trying to shell out to Ghostscript from inside a Netlify build is a fight you will lose. Doing the rasterization on my own machine and committing the output keeps the actual deploy build a boring, fast, host-agnostic astro build.



    Video embeds got the same "own it, don't proxy it" treatment. Instead of reproducing Notist's approach (a proxy that, again, had already started breaking), each talk stores a plain provider and video ID in frontmatter, and the page renders a lightweight embed facade that only loads the real player on click.



    The current numbers: 106 talks from 2012 to 2026, 93 events, 36 videos, 3,684 slide images. All of it committed, none of it one CDN outage away from disappearing.






    Making the talks searchable



    Video is the one asset class the speaking site doesn't fully own. It can host the reference, but not the file itself. What it can own is the transcript, and that turned into a genuinely useful feature: full-text search across every talk I've ever given.



    Raw transcripts come from YouTube's auto-generated captions, pulled by Claude Code skill handles the cleanup pass, with a strict ruleset: fix punctuation, capitalization, and proper nouns, remove disfluencies, but never reword, paraphrase, or reorder anything actually said. When in doubt, the instruction is to leave the text alone rather than guess.



    Search itself runs client-side against two separate JSON payloads, built at deploy time:





    • is the heavy one, concatenating each talk's transcript and slide text into a single searchable blob, fetched lazily only once you actually type a query:




    CODE
    const parts = [readTranscript(talk.id), readSlideText(talk.id)].filter(Boolean);
    if (!parts.length) continue;
    records.push({ url: talkUrl(talk), text: parts.join(" ").replace(/\s+/g, " ") });






    , but the short version:



    It's tempting to think of this as bidirectional sync, keep dev.to and git in lockstep, push changes both ways. Don't do that. It produces an endless phantom-diff loop where each side keeps thinking it's the one with the real version. Instead, a post is dev.to-owned while it's being drafted, and git ignores it entirely. Once a human merges an import PR, it's git-owned forever, marked by the presence of an id field in its frontmatter. Ownership transfers exactly once, at a deliberate moment, and it never automatically flips back.



    Two small workflows do the actual work. runs on push to files under posts/, and pushes local edits back to dev.to, writing the id back on a post's very first publish. Their domains never overlap, which is the entire point.






    The crosspost pipeline (and yes, this post is going through it)



    Once a post is git-owned, I can opt it into crossposting by adding crosspost: true to its frontmatter, which republishes it as a native entry in mattstratton.com's /writing/ collection and rewrites the dev.to post's canonical_url to point back at mattstratton.com, via to work. They ran fine without it. But they now also include it, a permanent memory layer for AI agents, so that when I'm working with an agent on content, it can pull up what it already knows about a talk or a previous session instead of me re-explaining context every single time. Nice to have, not load-bearing.



    And /fitness pulls my workout history straight from while writing this post, because I'd apparently been assuming for a while that one already existed and it hadn't.



    A couple of others I'm actually looking forward to: for /writing/ and the legacy archive, since the crosspost script currently papers over that gap by embedding the cover image inline in the post body instead of rendering it properly. There's also the usual pile of housekeeping (a master to main rename, a Node 24 upgrade) that's real but not exactly a fun read.



    None of it was urgent enough to hold up shipping the parts that already work. That's usually how the good list gets built anyway.

    Vollständiger Original-Bericht
    Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
    ↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
1 Quelle
Hackers Just Poisoned the Rust Supply Chain | Threat Wire
1 Quelle
Hackers Found a Way Into Humanoid Robots | Threat Wire
1 Quelle
Bits und so #1021 (Passwort für Laufwerk)
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten I Contain Multitudes (and Also Three Git Repos)

Thematisch verwandte Begriffe: Contain, Multitudes, Also, Three · 6 Treffer

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...