{
  "version": "https://jsonfeed.org/version/1.1",
  "title": "brennan.day",
  "description": "Brennan Kenneth Brown is a Queer Métis writer and web developer exploring Indigenous identity, digital culture, and creativity. Personal essays on technology, craft, and human experience from Calgary, Alberta (Treaty 7).",
  "home_page_url": "https://brennan.day",
  "feed_url": "https://brennan.day/feed.json",
  "language": "en",
  "authors": [
    {
      "name": "Brennan Kenneth Brown",
      "url": "https://brennanbrown.ca",
      "email": "mail@brennanbrown.ca",
      "avatar": "https://brennan.day/assets/images/brennan.jpg"
    }
  ],
  "items": [
    {
      "id": "https://brennan.day/a-new-indieweb-publication-or-i-want-to-start-something-and-be-bad-at-it/",
      "url": "https://brennan.day/a-new-indieweb-publication-or-i-want-to-start-something-and-be-bad-at-it/",
      "title": "A New IndieWeb Publication? or: I Want to Start Something and Be Bad at It",
      "summary": "Inspired by Good Internet Magazine, I'm starting a new volunteer-run IndieWeb publication tentatively called Long Horizon. Exploring my readiness to launch a digital and physical magazine focused on creative non-fiction and lyric essays, and seeking collaborators who want to build something meaningful on the Internet together.",
      "content_html": "\nA freshly printed magazine has a scent different than a book. A book smells like paper that has been waiting patiently, yellowed and already committed. A magazine smells like a bet. Like ink still making up its mind.\n\n## Good Internet Magazine\n\nAs some of you may already know, the wonderful publication [Good Internet Magazine](https://www.goodinternetmagazine.com/), which has been running as both a digital and physical publication for the past year, is now on indefinite hiatus.\n\nI cannot overstate how inspiring and important I think the work of [Alexandra](https://xandra.cc/), the creator of Good Internet, has been. In addition to Good Internet, she is also one of the creators of [32-bit Cafe](https://32bit.cafe/), one of the only forums I frequent on a daily basis. She also created the collaborative webhosting project [Marigold Town](https://marigold.town/). Go listen to her podcast appearance on James' [Wonders of Webweaving](https://web-weaving.jamesg.blog/2) and support her.\n\nAlexandra wrote an excellent [post-mortem on the experience of running Good Internet](https://library.xandra.cc/starting-a-print-magazine/). As she explains: don't do it alone; plan to spend money you won't recoup; the shipping costs will eat you; your printer's schedule is not your schedule; your health will not hold; and above all else, \"establish what your values are early on and stick to them.\" She also notes, with disarming openness, that \"doing this alone is doable but a) you will miss every deadline you set and b) you will burn out.\" None of this is discouraging to me. To me, this is a map.\n\n## Where I Currently Stand\n\nI am in a fortuitous position. After the past couple weeks of getting the writing archive and community [fanfiction.lol](https://fanfiction.lol) online, the site already has over 200 registered members and just as many works uploaded. I've found myself already with a diligent mod team who wrangles tags and organizes things, letting me focus on the development work behind the scenes.\n\nI was happily surprised to see that, even with such activity, my underpowered homelab has been able to keep up with no problems at all—over 99.90% uptime and averaging 10% CPU usage. And I'm somebody who enjoys collecting computers, and I have far more powerful ones that I now know how to turn into homelabs with sites up and running just as easily. With RAM and storage shortages and absurd price increases, I recognize how this has become more and more of a privilege and starting projects like this is a way to use that privilege well.\n\nI'm also someone who's run an in-person [writing collective](https://writeclub.ca/about) for the past several years, and I did the layout and editing for the first [two](https://www.amazon.ca/Fringe-Collection-Filth-Dana%C3%AB-Webb/dp/B0CYQ1NRY9) [anthologies](https://www.amazon.ca/Fringe-Collection-Felix-Costa-Gomez/dp/B0F4PKFRZQ) independently published by the club, featuring dozens of emerging writers. I know what it is to hand someone their first physical copy. \n\nI would have loved to have gotten a degree in journalism in retrospect. But at least I have one in English. And a homelab. And nine of my own books independently published. And a few scars from the process.\n\nAll of this is to say that I'm in a position where I feel as though I have the editing, leadership, and technical skills required to start a publication myself—both digital and physical.\n\n## The Shape of Things\n\nNow, I am certainly not trying to be opportunistic here. The ideas I have in mind for such a publication don't directly overlap with Good Internet Magazine.\n\nI'm not interested in technology for its own sake. The internet has always been, to me, a vehicle for great storytelling about the condition of being human. One of my biggest influences has been the now-defunct podcast [Reply All](https://podcasts.apple.com/us/podcast/reply-all/id941907967), which has been described as a \"'podcast about the internet' that is actually an unfailingly original exploration of modern life and how to survive it.\" That's the bar. \n\nI'm interested in creative non-fiction and lyric essays. I'm interested in the confessional, the vulnerable. I'm interested in the new sincerity movement. In the stubborn insistence that earnestness is not naïve, that care is a form of courage, that the Internet is still a place where people tell each other the truth. I'm interested in stories that begin with a forum post or a strange subreddit, and end somewhere near the bone.\n\nI want writing beginning with a GIF and ending in grief. I want reported pieces that start with a server error and arrive at loneliness. I want personal essays from people who are making websites in their bedrooms and can't quite explain why it matters. The digital and the human should be indistinguishable from each other.\n\nThe IndieWeb is real to me because the people in it are real to me. And I think those people—including you—deserve a publication that treats that reality seriously.\n\n## The View Onward\n\nThe working name is **Long Horizon.** While the term originally came from investment culture, it has been co-opted by the generative AI techbros to describe complex tasks requiring a genAI agent to perform dozens or hundreds of sequential steps to reach an end goal. \n\nAnd I would love nothing more to reclaim the term for humanity. Tongue-in-cheek, at the very least. For the long horizon is ours and I have the optimism to see it as beautiful. I don't have to tell you there would be zero genAI anywhere in this project. I'm thinking past the refresh cycle. What's worth writing requires time to understand, and the things worth reading require time to absorb.\n\nLong Horizon would operate as a volunteer-run, not-for-profit publication. I would pay writers a stipend/honorarium for any work that gets accepted—not enough, but something. Ink. A subscription. The knowledge that their work appeared in print. I'm not going to pretend I can offer what a well-funded magazine can offer. But I can offer care, and I can offer the thing Alexandra's post-mortem keeps returning to: community. The thing that makes the labor feel like something other than labour.\n\n---\n\nI've been writing on [brennan.day](https://brennan.day) now for over half a year, posting near-daily. Lyric essays, technical write-ups, political rants, pop culture criticism, IndieWeb dispatches. What I've learned from that practice is that I *can* sustain this. I have more to say than I thought. There are readers who show up. And the essay can hold more than I ever expected. Grief, comedy, code, contradiction, the body, the archive, the screen.\n\nA publication would let me do that in collaboration. Which is the part I haven't yet tried. \n\nYou cannot do this alone. You need editors, designers, writers who are braver than you in the places you are timid. You need someone who knows InDesign, someone who knows how to make an email newsletter exciting, and someone who knows how to index a back issue.\n\nAnd that's what I'm looking for: Writers. Editors. Web developers. Graphic designers. Artists. Hypemen. People who have opinions about fonts. People who want to learn how to have opinions about things like fonts. If you are interested and you are wondering what you have to give, then you have something. I promise that.\n\nThere is nothing more exciting to me than starting something new and being bad at it. Than being a beginner once again. I would love nothing more than to sink a lot of time and money into this, even if it ends up going nowhere, even if it fails. At least then I can say I tried. \n\nIf any of this sounds interesting to you, please reach out. Comment below or reach out [by email](mailto:mail@brennanbrown.ca) or [anywhere I have an account](https://brennan.day/accounts/). I'm just using [Ghost](https://ghost.org/) (the web software that will power this) for the first time. I haven't even finalized the name. This is the very beginning, and the very beginning is my favourite place to be.",
      "date_published": "2026-06-13T20:00:00.000Z",
      "tags": [
        "IndieWeb",
        "publishing",
        "writing",
        "community",
        "collaboration",
        "creative non-fiction",
        "lyric essays"
      ],
      "author": {
        "name": "Brennan Kenneth Brown",
        "url": "https://brennanbrown.ca",
        "email": "mail@brennanbrown.ca"
      }
    },
    {
      "id": "https://brennan.day/yes-buy-them-a-coffee-support-and-mutual-aid-on-the-indieweb/",
      "url": "https://brennan.day/yes-buy-them-a-coffee-support-and-mutual-aid-on-the-indieweb/",
      "title": "Yes, Buy Them a Coffee: Support and Mutual Aid on the IndieWeb",
      "summary": "Responding to criticism of 'buy me a coffee' links on blogs, I argue that asking for support isn't commodification—it's mutual aid! Exploring the economic pressures on creators, the history of mutual aid, and why the IndieWeb needs community support mechanisms to sustain independent art.",
      "content_html": "\nAnother day, another blog post responding to a blog post. For what else is the Internet for? I stumbled upon Hakkerman's article, [\"No, I Won't Buy You a Coffee\"](https://hakkerman.eu/blog/i-wont-buy-you-a-coffee/) and felt a strong urge to correct a fundamental misunderstanding. Because this topic isn't just about blogging or the IndieWeb, it's about figuring out how we can create a liberated future of independent art.\n\nI've already written an article about [how you can support indie creators](https://brennan.day/how-you-can-support-indie-creators-and-you-need-to/), and why you need to. I'll try not to be redundant here.\n\nTo start, Hakkerman says he's exhausted with the \"rampant capitalization [sic] and constant advertisements\" of the world. And I'm sure countless many would agree with this sentiment.\n\nBut let's take a step back and interrogate why people are asking for support in the first place.\n\nMaybe you've had a job that hollowed you out. Where you felt like limestone hollowed by water, grain by grain, over years. At the end of your shift, you sit down at your laptop. You open a tab. You start to write. A blog post about a television show you love, or a deep-dive on software, or an essay about the neighbourhood you grew up in. You post it for free as you always have. And somewhere at the bottom, almost apologetically, you put a link: *If this meant something to you, you can buy me a coffee?*\n\nThat's what we're talking about. That's what Hakkerman can't stand.\n\nHakkerman isn't wrong about capitalism's draining effects, but he is wrong about what that tip jar *is*.\n\n[According to recent data](https://usafacts.org/answers/are-wages-keeping-up-with-inflation/country/united-states/), wages have grown 0.24 percentage points slower than inflation over the past year. Even workers who got raises are making less than they were before. The median salary in the United States sits around $59,384 annually, a reasonable figure until it dissolves against rent, groceries, and a world getting more expensive every quarter. [The gap between what workers produce and what workers earn](https://prosperousamerica.org/americas-cost-of-living-crisis-is-a-wage-problem-not-a-price-problem/) has been widening since the 1970s, when policy choices favouring deregulation and the suppression of labour unions severed the link between economic growth and worker compensation. Corporate profits in the United States have more than doubled as a share of GDP since 2000. The money is there and is not going to workers.\n\nAnd those workers are exhausted. [Research suggests that nearly 85% of workers experienced burnout or exhaustion in 2025](https://wellhub.com/en-us/blog/wellness-and-benefits-programs/work-related-stress-in-the-united-states/), with almost half forced to take time off for mental health. The [World Health Organization defines burnout](https://high5test.com/employee-burnout-statistics/) as a syndrome of chronic workplace stress. Exhaustion, cynicism, a creeping sense of ineffectiveness. This is just the standard condition of working life.\n\nSo, when someone comes home from that job and opens their laptop to write, for free, for the love of it, for the flickering hope that their words will find someone, and they put a link at the bottom? The appropriate response isn't to see an advertisement. The appropriate response is to see a person.\n\nHakkerman argues that \"creatives should get compensation in the same way as everyone else\" but \"that doesnt [sic] mean that every instance of creativity should be a venue for profit,\" and that \"this is not the place to equalize it.\" I believe this is where our fundamental disagreement lies.\n\nI am a firm believer that most people urgently need to pick up a creative hobby, and that hobby should be completely separate from monetization and commodification. And I also agree that, yes, hobbies cost money (though the amount is certainly far less than what consumerist culture leads people to believe).\n\nBut when people are asking for someone to buy them a coffee, at the bottom of a blog that is available to read for free, this is not commodification. This isn't turning a hobby into extractive labour. No, this is a human asking another human for support even if that support isn't a requirement.\n\nI recognize we are all in different places financially, and many people cannot afford a recreational budget to spend being a patron of the IndieWeb, but that's not everyone.\n\n## On Mutual Aid\n\n[Dean Spade](https://www.deanspade.net/2020/12/18/interview-with-the-nation-about-mutual-aid/), legal activist and professor at Seattle University School of Law, defines mutual aid as \"collective coordination to meet each other's needs, usually from an awareness that the systems we have in place are not going to meet them.\" [Spade distinguishes mutual aid sharply from charity](https://climateresilienceproject.org/strategies/mutual-aid/). Charity flows downward from those with power to those deemed \"deserving\", and on the terms of the giver. Mutual aid flows *between* instead, it is horizontal and rooted in a recognition that your survival and mine are bound together. When I support you, I am also building the kind of world I want to live in. \n\nThe term was coined by the [19th century anarchist Peter Kropotkin](https://climateresilienceproject.org/strategies/mutual-aid/) after he observed animals in the Siberian wilderness collaborating with one another rather than competing for survival. The practice is ancient and Indigenous. Resource sharing, reciprocity, and collective care are all ancestral technologies. \n\n[As early as the 1780s](https://www.radicalinprogress.org/spade-2020-summary-part-1), there are records of mutual aid traditions in Black communities in America, pooling resources to cover health costs, burials, support for widows and orphans, and the construction of Black alternatives to white exclusionary infrastructures. \n\nThis isn't capitalism sneaking in the back door of the IndieWeb. This is a person offering what they have (their words, their time, their knowledge, their care) and asking, without demanding, for something in return. Mutual aid doesn't ask you to prove you deserve it. It meets people where they are.\n\nAnd the IndieWeb does need to figure this out. If we support each other more, through the grassroots community mechanisms akin to mutual aid, then there is far more ethical longevity and sustainability to this great digital experiment. \n\nI'm sure I don't need to tell you that the ways people can make money often degrade the quality of their writing and site, whether that's intrusive advertising (such as AdSense), dishonest product reviews, or aggressive affiliate linking.\n\nIt's exactly because of this that people need ethical, non-exploitative ways to make money with their work. Platforms like [Ko-fi](https://ko-fi.com), which launched in 2011 as a simple way for fans to give creators small gifts without taking a cut on one-time tips, and [Buy Me a Coffee](https://www.buymeacoffee.com), both exist to solve this problem. \n\n## Personal Disclosure\n\nI also want to add that my own personal blog, [brennan.day](https://brennan.day), does not make anything beyond what the few wonderful people supporting me through [Ko-fi](https://ko-fi.com) and my [Toonie Club](https://brennan.day/toonie-club) provide. I don't run any advertisements, take sponsorships, or use affiliate links. And I never will. The only costs associated with my blog are the domain on Porkbun, which runs $10/year.\n\nThat said, I am one of those few very lucky writers that can say that I do make a living blogging online. I'm enrolled in [Medium's Partner Program](https://medium.com/partner-program), where I syndicate my blog posts on the platform and I'm paid based on views, reads, comments, etc. when I paywall my content. The wonderful thing is, though, that they allow me to have my writing on my own site with no paywall, so it really is a win-win. And it's important that you read this and go support another blogger instead of me, if you feel so inclined.\n\nThe entire point of creative endeavours like this is to escape the \"draining nature of capitalism,\" as Hakkerman states, and I completely agree. But support is needed for this, and that support is actually antithetical to capitalism.\n\n## The Public Broadcasting Service\n\nMaybe you're one of the many people that has, at some point, watched PBS on television.\n\nThe Public Broadcasting Service is an American public broadcaster and non-commercial, free-to-air television network. [Founded in 1970](https://www.ebsco.com/research-starters/education/public-broadcasting-service-airs-its-first-program) following the passage of the [Public Broadcasting Act of 1967](https://americanarchive.org/exhibits/station-histories/public-broadcasting-act), which President Lyndon B. Johnson signed into law with the promise that this new network would \"belong to all the people,\" PBS was conceived as a space on the airwaves for what its founders called [an \"urgent need\"](https://www.bunkhistory.org/resources/the-core-concepts-of-american-public-broadcasting-turn-50): programming that addressed educational, social, and cultural demands that commercial television couldn't (or wouldn't) meet. It was built to be a civic forum, with news, public affairs, arts, and children's programming. All for the people who couldn't afford cable or didn't have access to anything else. \n\n[Federal funding flowed through the Corporation for Public Broadcasting (CPB)](https://www.congress.gov/crs-product/R48545), a private nonprofit that distributed money to over 1,500 locally operated public television and radio stations, with much of the remainder going to PBS and National Public Radio. The CPB received approximately $535 million annually, a small slice of the federal budget to sustain a public media infrastructure that reached into rural communities, reservation lands, and urban neighbourhoods alike.\n\nThe Trump administration changed that. In May of 2025, [Trump signed an executive order aiming to eliminate federal subsidies to PBS and NPR](https://www.pbs.org/newshour/politics/trump-signs-executive-order-directing-federal-funding-cuts-to-pbs-and-npr), alleging political bias. His executive order immediately cut millions in Education Department funding for PBS children's programming, [forcing the system to lay off a third of PBS Kids staff](https://www.pbs.org/newshour/nation/judge-blocks-trumps-executive-order-to-end-federal-funding-for-pbs-and-npr). By July 2025, [Congress voted to rescind $1.1 billion in CPB funding](https://www.npr.org/2025/07/18/nx-s1-5469912/npr-congress-rescission-funding-trump)—the full amount allocated through the next two fiscal years—as part of a $9 billion package of cuts. By August 2025, [the CPB announced it was beginning an orderly wind-down of its operations](https://www.cnn.com/2025/08/01/media/trump-cpb-corporation-public-media-shuts-down). Most of its staff were told they would lose their jobs on September 30th.\n\nWhat happens when a public commons is stripped of its public funding? You probably know the answer already. PBS has asked this of viewers for fifty years, in those pledge-drive weeks when the regular programming pauses and someone stands in front of a camera and reminds you that PBS exists due to:\n\n> Support by viewers like you. Thank you!\n\nThat's what the IndieWeb needs, now more than ever.\n\n---\n\nThe next time you read something on a personal site that matters to you, and you see a small link at the bottom, I want you to consider: what kind of internet are you building with your dollar? What kind of world?\n\nBuy them a coffee. Or don't. If you can't, if you won't, that's fine. The writing is still there either way. That's the point. But if you *can*, and you're holding back because you've decided that asking is undignified, that wanting is capitulation, that the presence of a tip jar makes the whole thing somehow compromised? Then you're mixing up the revolution and the enemy.\n",
      "date_published": "2026-06-11T20:00:00.000Z",
      "tags": [
        "IndieWeb",
        "community",
        "economics",
        "mutual aid",
        "support",
        "capitalism",
        "writing"
      ],
      "author": {
        "name": "Brennan Kenneth Brown",
        "url": "https://brennanbrown.ca",
        "email": "mail@brennanbrown.ca"
      }
    },
    {
      "id": "https://brennan.day/why-make-your-website-accessible-anyways/",
      "url": "https://brennan.day/why-make-your-website-accessible-anyways/",
      "title": "Why Make Your Website Accessible, Anyways?",
      "summary": "Web accessibility isn't compliance theatre or checking off a list. It's about designing for everyone. Exploring the curb cut effect, why disability is more common than we think, and practical steps to make your website usable by as many people as possible.",
      "content_html": "\nI've done a lot of tinkering and attempts at optimization on [https://Brennan.day](https://brennan.day), and one of the foundational principles of the project was to be accessible from the start—making an accommodating website was not going to be an afterthought.\n\nBut what does that mean, exactly? I think it's good to actually write a blog post explaining that. An *accessible starting point*, if you will. [Web accessibility](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/Accessibility/What_is_accessibility) (sometimes shortened to a11y[^1]) is \"the practice of making your websites usable by as many people as possible.\" There is a wide range to consider here: visual impairments, hearing impairments, mobility impairments, cognitive impairments, and more.\n\n[^1]: a11y, as in a(ccessibilit)y, as there are 11 letters between the starting A and finishing letter Y. Similar to how i18n is short for internationalization, which is worth its own blog post another time!\n\nI'll start off, though, with some of the most important things that I think beginner web developers don't hear enough.\n\n## Designing for Disability Means Designing for Everyone\n\nAnytime you develop with accessibility in mind, or improve a product for someone with a disability, you're actually improving it for everyone. This is called the [curb cut effect](https://levelaccess.com/uncategorized/the-curb-cut-effect-how-digital-accessibility-elevates-ux-for-everyone/). \n\nIn the 1970s, disability activists in Berkeley, California, pushed for small ramps to be cut into sidewalk corners so that wheelchair users could move through their communities without being stopped every block by a four-inch drop. The ramps got built. And then? It turned out the curb cut helped everyone: Parents with hefty strollers. Delivery workers hauling hand trucks. Skateboarders. Tourists dragging rolling luggage through unfamiliar cities. A solution designed for a specific need became universal.\n\nThe same thing happens in digital design:\n\n* Closed captions were created for people who are deaf or hard-of-hearing, and they're wonderful for anyone watching video on a crowded commute, in a noisy café, or late at night beside a sleeping partner.\n* High-contrast text, originally designed to help people with low vision, makes your website more readable in bright sunlight.\n* Voice controls, built for people with motor impairments, became the hands-free layer underneath Siri and smart speakers. Text-to-speech turned out to be useful for driving, for cooking, for holding a baby while you need both hands and still want to hear what's next. \n\nThe reason we audit our websites for how much contrast there is between text and background, or add ARIA landmarks, or ensure there's full keyboard navigation access, isn't to satisfy a checklist and be done with it. It isn't compliance theatre. It's about making it more readable for someone on a cracked phone screen, for someone borrowing a laptop without a mouse, for someone who just got their pupils dilated at the optometrist and is trying to read something waiting for the blur to clear.\n\nThis is about understanding how to make your words and work better understood by everyone, not just the able-bodied population. This is about meeting people where they are, no matter what. \n\nReally, this is about connecting to humanity. \n\nIf you want to better understand disability and people with disabilities, I would recommend subscribing to Chris Ulmer's channel, [Special Books for Special Kids](https://www.youtube.com/SpecialBooksbySpecialKids). In addition to being one of the greatest YouTube channels around, SBSK is dedicated to \"creating a more inclusive world\" by interviewing people with disabilities from around the world \"of all ages and diagnoses\".\n\n## Disability Is More Normal Than You Think\n\nIf you wear glasses, you have impaired vision. That's a disability, and that's okay! The reason we rarely think of it that way is because the support infrastructure is widespread and robust. There's an optometrist in every city and frames at every drugstore for nine dollars.\n\nThink about the accommodations that *haven't* been normalized yet. In web design, that's screens that can't be navigated without a mouse, or forms with no label text. The video with no captions. The button that's a styled `<div>` with no keyboard event, invisible to screen readers.\n\nThese are day-to-day encounters on the web for millions of people. Low-grade friction that compounds over every session, every tab, every attempt to participate in digital life.\n\n[According to the WHO](https://www.who.int/news-room/fact-sheets/detail/disability-and-health), an estimated 1.3 billion people, roughly 1 in 6 of us, experience significant disability. In the United States, the CDC puts the figure at around 26% of adults. This is a growing number driven by aging populations and the rise of noncommunicable disease. \n\nThese are your readers, your users, the people who found your site from a search or a shared link and arrived hoping to read something you made.\n\nDisability is also not always permanent, either. A broken arm means weeks without reliable fine motor control. Migraines with light sensitivity can make light, small text unbearable. Similarly, burnout and grief and exhaustion from long work shifts all can make dense, unstructured text become difficult to parse. Anybody, and most everyone, will eventually move through the world with reduced capacity in some domain.\n\n## My Own Website\n\nI want to stress I'm certainly not an a11y expert, or someone with a major impairment myself (you can look at my [disability](https://brennan.day/disability) page to get a better understanding of that). I am just someone who wants to create a more inclusive Internet for everyone. With that in mind, here's a look at what [brennan.day](https://brennan.day) actually does:\n\nI use semantic HTML5 elements (`<header>`, `<main>`, `<nav>`, `<footer>`) to give my site a skeleton that screen readers can navigate. There's a [\"Skip to main content\"](https://www.a11y-collective.com/blog/skip-to-main-content/) link at the top of each page so keyboard users don't have to tab through the navigation every single time. Headings follow a logical hierarchy from `h1` down to ensure the heading tree isn't a scattered field. ARIA landmarks identify the major page regions. Focus states are visible and styled. All text meets or exceeds [WCAG 2.1 AA contrast ratios](https://www.w3.org/WAI/WCAG21/quickref/) (4.5:1 for normal text, 3:1 for large text).\n\nThe site was tested using the [WAVE Web Accessibility Evaluation Tool](https://wave.webaim.org/), and as of the most recent audit, it scores a 9.8 out of 10 on the AIM index, with zero errors and zero contrast errors. I resolved a longstanding issue where post graph links were generating \"empty link\" errors by adding `aria-label` attributes throughout. The scroll-to-top button was restyled for better visibility across both light and dark mode.\n\n## The Accessibility Issues That Must Not Be Named\n\nThere's a blog post on [AppleVis](https://www.applevis.com/blog/accessibility-issues-must-not-be-named) which goes over the \"Issues That Must Not Be Named,\" which go over other accessibility issues and the disability tax of common web design. One of these he calls *Complexifuscation*, when a page technically passes every accessibility checks but is still exhausting to use because it's built with so many nested elements and decorative wrappers and interstitial `<div>`s serving no semantic purpose, that screen reader navigation is frustrating. \n\nFacebook, in his example, requires nine `VO+Right Arrow` keystrokes to get from a post heading to the actual text of the post.\n\nAnother pattern he describes is *Screen Reader Agnosia*, where developers who are unfamiliar with how screen reader software works then go ahead and build custom accessibility shortcuts, duplicating the already-existing native functionality. The result is more things to memorize and more deviation from the muscle memory that screen reader users have spent years building.\n\nThis is what automated tools aren't designed to map. Audits like [WAVE](https://wave.webaim.org/) are starting points, not ending points.\n\nFor beginner webdevs, there's visual feedback when you style with CSS that you don't when learning things like semantic HTML. Styling a `<div>` to look like a button seems completely innocent at first, for instance. Or when you remove a default focus outline because you haven't been informed it's the only way a keyboard user knows where they are on the page. Or when you pick an aesthetic colour palette that's cute, but low-contrast and difficult to read.\n\n[According to the 2025 WebAIM Million report](https://www.a11y-collective.com/blog/how-to-overcome-avoid-the-7-common-digital-accessibility-issues/), fixing these six categories of errors would resolve 96% of all accessibility errors across the web: \n\n* low contrast text\n* missing alt text\n* missing form labels\n* empty links\n* empty buttons\n* and missing document language\n\n## Inaccessibility and the Olympics\n\nBruce Maguire, a blind Australian, filed a complaint with the Human Rights and Equal Opportunity Commission arguing that the Sydney Olympic Games organizing committee violated Australia's Disability Discrimination Act of 1992 in three ways: \n\n* by not providing ticketing information in braille, \n* by not providing a braille souvenir programme, \n* and by failing to maintain an accessible website. \n\nRegarding the website complaint, the committee ordered to add alt text to images and image map links, fix the schedule navigation, and ensure results tables would be accessible during the Games themselves. SOCOG largely didn't comply, and the commissioner found in Maguire's favour. SOCOG was ordered to pay $20,000 AUD in compensation.\n\nThis happened in 2000. The W3C's Web Content Accessibility Guidelines were just a year old. \n\nTwenty-six years later, [WebAIM's annual survey of the top one million websites](https://webaim.org/projects/million/) consistently finds that more than 95% of home pages have detectable WCAG failures.\n\n## What You Can Do\n\n* **Talk to people with disabilities and have them use your site.** Automated tools can only catch so much. Real human beings can actually tell you what the experience of using your site is like.\n* **Run [WAVE](https://wave.webaim.org/) on every page of your site.** Zero errors should be the start, not the end of your audit. Check every image for meaningful alt text. Check every form input for an associated label. Check every link for descriptive text. \"Click here\" tells a screen reader user nothing but \"read my essay on web accessibility\" tells them where they're going.\n* **Put your mouse away and navigate with only your keyboard.** Tab through your whole site. Can you reach everything? Can you tell where you are? Is the focus indicator visible? Does anything trap you, like a dropdown you can enter but can't leave, or a modal with no keyboard-accessible close button?\n* **Use semantic HTML.** A `<button>` is not the same as a styled `<div onclick>`. A `<nav>` is not the same as a `<div class=\"nav\">`. Semantic elements carry meaning that assistive technologies can use and styled divs carry only visual appearance. Use headings in order, use lists for lists, etc.\n* **Check your contrast.** The [Colour Contrast Analyser](https://www.tpgi.com/color-contrast-checker/) and [WebAIM's contrast checker](https://webaim.org/resources/contrastchecker/) are both great to use. The WCAG minimum is 4.5:1 for body text.\n* **Caption your media.** If you embed video, caption it. If you embed audio, provide a transcript.\n\nThe [W3C Web Accessibility Initiative](https://www.w3.org/WAI/) maintains the authoritative documentation, and the [A11y Project](https://www.a11yproject.com/) is a community-maintained, more approachable reference.\n\n---\n\nThere is already so much of the world that isn't accommodating, whether that's public infrastructure and architecture, or product design, or the many hundreds of other things able-bodied people take for granted. Changing those things, if possible at all, takes years of advocacy and legislation and bureaucratic friction and money and people who are willing to be loud about it for a long time.\n\nBut your website? The one you own and run? That is something that can be made more accessible by you. You can take the time to learn and implement good practices that will make what you create more easily understood and shared to all. That's the whole point, isn't it?\n",
      "date_published": "2026-06-10T20:00:00.000Z",
      "tags": [
        "IndieWeb",
        "accessibility",
        "web development",
        "design",
        "inclusive",
        "web design",
        "technical"
      ],
      "author": {
        "name": "Brennan Kenneth Brown",
        "url": "https://brennanbrown.ca",
        "email": "mail@brennanbrown.ca"
      }
    },
    {
      "id": "https://brennan.day/the-lanternfly/",
      "url": "https://brennan.day/the-lanternfly/",
      "title": "THE LANTERNFLY.",
      "summary": "The spotted lanternfly is beautiful and terrible, an invasive species that illuminates even as it destroys. AI-generated content is flooding the Internet, and authenticity is becoming a premium commodity. We must refuse the premise that human writing is a niche product.",
      "content_html": "\nMy legs tremble when I wake up now, I'm not sure why. I probably need to eat something—a garden salad the colours of sunset and bruises. I need caffeine and to stop making a list of things.\n\nThe nothing is always waiting and welcoming. Just for a minute, sit in the not-yet. But the monkey clatter bubbles up all the same, no different than well-taken care of sourdough. There's a name I keep turning over in my head.\n\n## Before The Light\n\n[The spotted lanternfly](https://www.fws.gov/story/stopping-spotted-lanternfly-its-tracks) is beautiful. The forewings like grey calligraphy paper, polka-dotted. Underwings a shock of red and black and white. Colouring belonging to a naturalist's illustration from the 19th century. \n\n*Lycorma delicatula*. Delicate. There's that word.\n\nThe lanternfly is also a [terrible, invasive planthopper](https://www.aphis.usda.gov/plant-pests-diseases/slf), arriving as egg masses on imported stone in Berks County, Pennsylvania in 2014. Spreading across North America ever since. \n\nThe lanternfly feeds on over 70 plant species, shitting a sticky honeydew promoting unhealthy, sooty mould growth. Don't worry, though, it [lacks the capacity to bite](https://trees.dc.gov/pages/invasive-species-spotted-lantern-fly). Causing enormous harm with innocence.\n\nThe lanternfly's favourite food is [*Ailanthus altissima*](https://caseytrees.org/2014/04/tree-month-tree-heaven/). The tree of heaven. This tree, too, is terrible and invasive. First brought from China to Europe in the 1740s as an ornamental garden specimen. The tree initially hailed as beautiful, and now grows [out of cement, out of cellar gratings](https://caseytrees.org/2014/04/tree-month-tree-heaven/), suppressing competition with allelopathic chemicals it shits into the soil. \n\nTwo invasive species locked in an ecological codependency. The lanternfly, spreading toward a tree that was never supposed to be here. The tree named for heaven, and it smells so foul when you crush its leaves. \n\nThe lanternfly is a lightbearer. A lantern-shaped body, underwings lit like a match. Beautiful things arrive uninvited. Creatures that don't belong somewhere can still illuminate that place.\n\n## The Flood\n\n[Well over half of new online articles are now AI-generated](https://techxplore.com/news/2025-11-articles-internet-written-ai-human.html). Mostly formulaic content—news updates, how-to guides, SEO filler. Not lyric essays about invasive insects, I presume. Not yet. \n\nThe pressure is not only in the volume, but the indoctrination. Constant suggestions nested in every product announcement, every LinkedIn post, every breathless tech newsletter. The droves of people who do not discern a meaningful difference between generated text and original writing. The droves of people who believe acceleration is the same as expression. That a writer who uses AI to \"enhance their workflow\" is simply being practical. A carpenter using a nailgun instead of a hammer.\n\nIn real life, have you noticed all the [restaurants becoming boring grey boxes?](https://www.delish.com/food/a68854138/why-are-all-fast-food-restaurants-gray/) When you go to the movie theatre, (if that's something you still do) do you notice the [recycled content?](https://www.queensjournal.ca/viewers-are-tired-of-hollywoods-recycled-ideas/). As though we have entered an age of monotony-as-safety. \n\nEvery major platform on the Internet in 2026, along with shoving an unnecessary genAI interface into their products because their aging shareholders believe it will mysteriously conjure profit, converge onto the same aesthetic as well. Frictionless, sterile, flat, spacious, white. Calm? Calm is what you design when you worry the user will leave if anything asks too much of them. \n\nThere is a lack of trust in all of this. The genAI autocompletes don't trust you have the capacity to write, yourself. The product designer and the Hollywood scriptwriter don't trust that creative expression will alienate (and cause a loss in profits, of course). In this lack of trust, there is a lack of love. A lack of understanding. We are all exhausted, guarded, and simply throwing anything at the wall to see if it sticks.\n\n[Authenticity is becoming a premium commodity](https://www.koinsights.com/the-authenticity-premium-why-consumers-are-rejecting-ai-generated-content/), how contradictory. Humanity becoming a market differentiator. Mess and error and personality the brand itself. The baseline is automated, and so everything that was once just \"all writing\" becomes \"human writing.\" A subcategory, a niche, a premium tier.\n\nI refuse the premise. Original writing is not premium. The earnest and considered and risky and human is the point. You cannot suddenly have the term encompass something else because it is so widespread and mainstream.\n\n---\n\nIt's easy to think that we are the ones being invaded—that the trends towards the artificial and sterile are encroaching on us. But in reality, this is the system working as intended. All systems functional and online. \n\nThose who dare to object, to expose their vulnerable soft flesh, to centre love instead of comfort—we have always been the misfits. The rebels. We are the invasive species.\n\nThe tree of heaven, that foul-smelling invasive, [was the last tree to come out of dormancy each spring](https://czzs.org/en/get-to-know-the-invasive-alien-plants-tree-of-heaven/). The locals along the lower Yellow River called it chunshu—the spring tree. The sign that winter was actually, finally over. \n\nA tree that shouldn't be here, that causes real harm, that grows out of concrete—also the harbinger of warmth. Both things true at once.\n\nI need to begin. I need to eat something. The lanternfly hasn't lit yet. But I can already see where it wants to go.\n",
      "date_published": "2026-06-07T20:00:00.000Z",
      "tags": [
        "writing",
        "creativity",
        "digital culture",
        "AI",
        "authenticity",
        "nature"
      ],
      "author": {
        "name": "Brennan Kenneth Brown",
        "url": "https://brennanbrown.ca",
        "email": "mail@brennanbrown.ca"
      }
    },
    {
      "id": "https://brennan.day/a-ship-in-harbour-is-safe/",
      "url": "https://brennan.day/a-ship-in-harbour-is-safe/",
      "title": "A Ship in Harbour is Safe",
      "summary": "Nassim Nicholas Taleb's concept of 'skin in the game' is the idea that true learning only happens when you have something to lose. And I look at IndieWeb principles of using what you make to publishing under your real name. Having risk and real stakes is essential for creative work. A ship in harbour is safe, but that's not what ships are built for.",
      "content_html": "\nIn 2018, Nassim Nicholas Taleb released the fifth book in his [Incerto series](https://en.wikipedia.org/wiki/Nassim_Nicholas_Taleb#Incerto_series), [*Skin in the Game*](https://www.goodreads.com/book/show/36064445-skin-in-the-game). The main idea is rather simple: it's actually good to have something to lose.\n\nTrue learning occurs only when you have something to lose from your mistakes, what Taleb calls *pathemata mathemata*. Learning through pain. You have a fire lit under your ass. It burns but you get things done because you don't really have any other option.\n\nTaleb was mostly writing about the professional class of advisors, consultants, and intellectuals who profit from appearing to know things without bearing any consequences for being wrong. But I think this applies greatly to creativity.\n\nTucked into the same book is a concept he calls \"[soul in the game](https://www.shortform.com/blog/nassim-taleb-skin-in-the-game/),\" reserved for a category he calls artisans. Writers, makers, craftspeople, anyone who does things for existential reasons first and financial ones second. The artisan would not sell something defective or even of compromised quality because it hurts. They have sacred taboos, things they would not do even if it markedly increased profitability. The artist, in Taleb's framing, is the most committed form of skin-in-the-game practitioner. Sacrificing not money or reputation, but something harder to name. The songwriting self. The written record of what they actually believe.\n\nIn poetics for example, you have the confessionals. Robert Lowell, Sylvia Plath, Anne Sexton, and their contemporaries. Poets making art out of personal history and autobiography, with direct expression as method. At the time, private experiences were considered taboo as primary subject matter. Yet, Plath published *Ariel* under her own name. Yet, Sexton read her poems about psychiatric wards and suicide attempts at universities and in living rooms. In the public sphere they wrestled with patriarchal expectations, motherhood, womanhood, and mental illness. The wager was real. The stakes were real. \n\nOne of the principles in the IndieWeb is to both [use what you make](https://indieweb.org/use_what_you_make) and make what you use. You might know this as [\"dogfooding,\"](https://en.wikipedia.org/wiki/Eating_your_own_dog_food) where a business uses the product they're selling. It's also known as \"drinking your own champagne\" to put a more positive spin on it, but it shouldn't have a positive spin. While you may eventually get to the point where you create something enjoyable to use, it won't start off that way.\n\nThis is skin in the game—you develop an immediate empathy from the impact of poor design choices or errors. You are no longer building hypothetical features for a fictional audience. You are building a real thing for you. And if you aren't going to use what you build, why would anybody else want to? This is a bodily thing, you feel the drag of a slow page load in your own impatience. The broken navigation. It's the potter who only makes pots she'd use, the carpenter who sleeps in the bed he built.\n\nMy blog certainly passes that test. I created it from scratch and use it every day, and I even have dipped my toes in [Developer Experience (DX)](https://brennan.day/i-made-my-eleventy-build-5-faster-with-five-changes/) to improve how much I enjoy the [workflow of writing each day here](https://brennan.day/my-blogging-workflow-a-routine-for-nearly-a-post-a-day-for-4-months-straight/).\n\nBut that's not the only way I put skin in the game. Another example is that [everything I do online](https://brennan.day/accounts) is connected directly to my real-life identity. My legal name is Brennan Kenneth Brown. Is there risk to this? Yes, and the risk is entirely the point. You know who I am, and so I have to live up to a real standard I set for myself—I'm held accountable, and it's inherently transparent. If I seriously fuck up, those fuck-ups are tied to who I am. Learning through pain.\n\nThere's a weight to being named. When I posted about my diagnosis, when I wrote critically about what others in my field depend on financially, there was the moment before I said something publicly that I knew I couldn't take back. That weight is proof that what you're doing matters. An anonymous post about mental illness is a contribution to discourse. A post with your name on it is a reckoning. Both might say the same words but only one costs you something.\n\nSimilarly, I follow the [Show Your Work](https://austinkleon.com/show-your-work/) philosophy of Austin Kleon. Along with my essays meandering about [spicy foods](https://brennan.day/spice-our-antifragile-biology/) and [Groundhog Day](https://brennan.day/groundhog-day-savescumming-and-our-endless-numbered-days/) are plenty about [how I write](https://brennan.day/a-thousand-cranes-why-i-write-every-day/) and [how I code](https://brennan.day/building-brennan-day-part-two-indieweb-new-features-and-three-months-of-iterations/). All of my technical work (and now creative writing work as well) is publicly available in open source repositories on [GitHub](https://github.com/brennanbrown) and [GitLab](https://gitlab.com/brennankbrown) and [Source.tube](https://source.tube/brennan).\n\nIf people fuck up on the Internet under an alias, and they practice good infosec, then they can go and move on with their life as though nothing has happened. No skin in the game.\n\nI've deeply enjoyed having my identity tied to what I do. I'm proud of my work and I think my track record shows somebody working in good faith. Taleb's idea, like many others he's written about that I've been influenced by, has been proven to be correct through my action.\n\nThe title of this article comes from a quote coined by John A. Shedd in his 1928 book *Salt from My Attic*. The full quote goes \"a ship in harbour is safe, but that is not what ships are built for.\" I think about it often, and I think it lends itself to how existential the importance of having skin in the game is.\n\nI've written before about my distaste for how we've become a culture of convenience and taking the path of least resistance, but we've also become a culture of taking the safest path forward as well. There is so much less to forage in the garden if we avoid anywhere weeds and thorns have sprouted up. Safety is so much smaller than risk.\n\nTo make something safe is to sand down the edges. You soften the claim. You write the essay and then spend twenty minutes asking yourself: *could this be misread? could this hurt someone? could this embarrass me in a year?* And then you chisel off the parts that answer yes, until what's left is smooth and inoffensive and inert, a thing that will neither wound nor illuminate. A ship in harbour, tied to its cleats, paint still fresh. Impressive, maybe. Inert, certainly. Safe as a ship can be, yes. Permanently, uselessly safe.\n\nI'm sure you've heard all of these empty platitudes already in self-help, business organization contexts, but it really is about the art for me. I do not think we are capable of creating great art unless there is a chance it will ruin us. Anytime I have an uneasy gut in my stomach about something I've posted, I know that means that it is something I *need* to share.\n\nI'll bring another one of these trite sayings up; Tennyson taught us 'tis better to have loved and lost than never to have loved at all. I know the ocean in the storm, I know the feeling of shipwreck, to be capsized and to lose near everything. But then you just build another ship. You set sail again.\n\nThe harbour has people who love you in it, and dry land, the smell of woodsmoke from somewhere warm. When you leave, you leave that too. The water is dark and deep, the swells are indifferent and there is no one out there who will save you from a mistake in the rigging. You knew this going in. You went in anyway. You are a sailor.\n\nYou have to be willing to not come back. That is what the art requires. That is what skin in the game means. It will cost you something you can't recover with a pseudonym and a new account. Your name is on the hull. Your name is on the work. You are in the water.\n",
      "date_published": "2026-06-05T20:00:00.000Z",
      "tags": [
        "IndieWeb",
        "philosophy",
        "writing",
        "creativity",
        "risk",
        "identity",
        "accountability"
      ],
      "author": {
        "name": "Brennan Kenneth Brown",
        "url": "https://brennanbrown.ca",
        "email": "mail@brennanbrown.ca"
      }
    },
    {
      "id": "https://brennan.day/i-need-to-stop-making-promises-i-cant-keep/",
      "url": "https://brennan.day/i-need-to-stop-making-promises-i-cant-keep/",
      "title": "I Need To Stop Making Promises I Can't Keep",
      "summary": "Building fanfiction.lol taught me that some promises are impossible to keep. I wanted canonical tags for everything and 'write whatever you want' as a tagline, but Canadian obscenity laws and the philosophical complexity of tag wrangling forced me to adjust. Here's what I learned about running a community archive, the legal constraints I face, and the promises I can still keep.",
      "content_html": "\nI'm an optimist and idealist. I see the best in people and always believe they're acting in good faith. Does this bite me in the ass? Sometimes. But it also gives me the will to survive an increasingly unstable, unknowable world.\n\nWhen I first began work on [fanfiction.lol](https://fanfiction.lol), there were a few things I wanted to be set in stone based on my values and beliefs. I wanted all tags to be canonical, unlike AO3 where the system is built on what archivists call a *[curated folksonomy](https://www.academia.edu/40409343/Fandom_Folksonomies_and_Creativity_the_case_of_the_Archive_of_Our_Own)*: you can tag your work however you like. Any phrasing, any form. And then, a volunteer army of *tag wranglers* works behind the scenes to link synonymous tags together so filtering still works. If you tag a fic \"steve and tony kiss\" and someone else tags theirs \"Steve Rogers/Tony Stark First Kiss,\" a wrangler connects both to the same canonical tag. It's designed as a deliberate compromise between a rigid [regulated taxonomy](https://archiveofourown.org/admin_posts/267) (like fanfiction.net, where you pick from a fixed list) and a pure free-for-all, and it means that tags are *not* canonical by default. They're free text until a wrangler acts on them. \n\nMy instinct was to skip that whole system and canonize everything from the start. In addition, I also wanted to have a wider range of archive warnings so people could better filter out stories they didn't want to see, and I wanted to add a diverse range of relationship types so people felt seen and represented.\n\nPerhaps most importantly, I wanted to be small, scrappy, and allow anybody to write anything on ff.lol. I didn't care about which fandoms, or tropes, or ships, or writing quality. I didn't care if you wrote fiction or original work or poetry or creative nonfiction or scripts. Making people, especially beginners or inexperienced writers, feel as though they could publish their work, was the most important thing for me.\n\nI think these are all really good values to have, and I still stand by all of them, but the past few days of actually figuring out the mechanics of running a site like this made some of these universal promises impossible to keep.\n\nI live in Canada, and the server is housed in Canada. I'm not using a remote VPS in another part of the world, I wanted this project to be on bare metal I own. I wanted to have access to everything and, also, not pay a monthly expense for computation.\n\nHowever, because of that, I need to follow Canadian law. While this doesn't change that you can write about whatever fandom, or ship, with whatever tropes, and whatever writing quality, it does prohibit certain topics. Talking to a lawyer I know, it was eye-opening how strict yet vague these laws are. \n\n## A Brief History of Obscenity in Canada\n\n[Section 163 of the Criminal Code](https://laws-lois.justice.gc.ca/eng/acts/c-46/section-163.html) defines obscenity as any publication whose dominant characteristic is the \"undue exploitation of sex,\" or sex combined with crime, horror, cruelty, or violence. The operative word is *undue*, and it has never really been defined. The standard set by the Supreme Court in [*R v Butler* (1992)](https://www.canlii.org/en/ca/scc/doc/1992/1992canlii124/1992canlii124.html) is not what Canadians personally find offensive, but what they would not tolerate *other* Canadians being exposed to. A community standards test that sounds reasonable in the abstract and has functioned as a weapon in practice. \n\nThe first obscenity charges laid after *Butler* were against [Glad Day Bookshop](https://www.gladday.ca/) in Toronto, for selling a lesbian magazine made by women for women. Canada Customs spent years systematically seizing shipments to [Little Sisters Book & Art Emporium](https://www.thecanadianencyclopedia.ca/en/article/little-sisters-book-and-art-emporium) in Vancouver—Queer books, erotic literature, lesbian photography—while the same materials arriving at mainstream booksellers passed through without inspection. The Supreme Court eventually ruled that the targeting violated the Charter, then *upheld* the underlying obscenity law anyway. The law has historically considered Queer sexuality, sexual violence written consensually between adults, and dark erotic fiction to fall within \"undue\" exploitation in ways that straight, vanilla content does not. This is not a value-free technical constraint I'm operating within. And I do not agree with these laws. They are not neutral, and they function as censorship. However, as the host of this archive, I must abide by them to keep the site running and protect myself legally. This is not a judgment on the validity of any work or anyone's creative choices. It's just a legal necessity.\n\nI started out with the tagline \"write whatever the hell you want\" and had to change it to \"express yourself freely within our [content guidelines](https://fanfiction.lol/tos)\" and that sucks. I'm sorry for that.\n\n## How Do You Organize Hundreds of Works of Creative Writing?\n\nThe next issue is a little more inside baseball. Regarding the tagging system, I thought it would be refreshing and validating to have tags be canonized by default; however, the more you look into how people use tags, the more impossibly philosophical the principle becomes.\n\nI'm not good at tag wrangling. I'm terrible at making judgment calls about which tags name the same thing, which are distinct concepts, which are specific enough to stand on their own. [Look at the current stats on my site](https://brennan.day) and you'll see I currently have 197 blog posts and 193 tags. That's absurd! There are redundancies, tags with very similar themes, upper/lowercase issues, plural vs. singular, I could go on.\n\nThat's why I've been so fortunate and lucky to have a head tag wrangler join me in organizing ff.lol, Jar. Beyond being incredibly organized and thoughtful about how the taxonomy of the site should be, you can check out [her other stuff here](https://jarinfo.carrd.co/), and I'd recommend you follow her! Fans like her are exactly why I created ff.lol in the first place.\n\n\"All tags are canon\" sounds nice on paper, but working through it in practice reveals a problem that's more philosophical than technical. Here's an abridged conversation from our Discord:\n\n> **Water:** Actually, I have a question about what a wrangler's aim should be in regards to canonizing and not canonizing? *Unrequited Crush* and *Unrequited Love*—these both currently synned to *Unrequited Feelings*, but they could become their own canonicals and then subbed to *Unrequited Feelings*. How far would you like us to go in wrangling canonicals that are similar enough to syn but still be considered somewhat different?\n>\n> **Brennan:** you ever have an idea that sounds nice at first but is actually deeply philosophical and requires a great amount of mental energy with no actual simple answers? \n>\n> **Jar:** *(about something else entirely)* \"How can it be that bad\" I'm trying to figure out concepts that we don't even know about as a society\n\nJar was talking about her own fic—but she accidentally summarized the tagging problem. *Unrequited Crush* and *Unrequited Love* feel intuitively distinct. For one, this is about longing for someone who doesn't know you exist; the other carries the full weight of love given and not returned. But the line between them is one that human experience blurs constantly, and the tagging system has to make a call. \n\nAnd that's just two tags. Multiply that across every emotional state, every AU type, every relationship permutation, and you start to see the scope of the problem. And over-granular tags tend to cause writers to start using the wrong ones, either because they can't find the right one or because the distinctions have become invisible to anyone who isn't already a power user.\n\nI've landed on the operating principle *canonization-first*: a tag gets canonized based on whether it's likely to be useful for filtering, calibrated against a normal distribution of how often that concept would plausibly appear in fics for a given fandom or character. \"Lesbian [character]\"? Canon, almost certainly recurs. \"Lesbian space pirate from the Edwardian era [character]\"? That's based as hell, but not getting canonized unless there's a canonical basis to make it likely. \n\nThe wrangling docs Jar put together also establish that tags are for filtering, not for self-expression: if something functions as a summary of plot events rather than a descriptor of content, it belongs in the fic's notes, not the tag field. Your tags get read by wranglers. Phrasing may be adjusted. Meaning won't be changed, but format will.\n\nBeing an English major, I took multiple courses on literary theory, where one of the main topics is debating how much of a work is in the hands of the author, the reader, or the work itself. The question maps onto tag wrangling a lot. \n\nRoland Barthes argued in his 1967 essay *[The Death of the Author](https://en.wikipedia.org/wiki/The_Death_of_the_Author)* that once a text is written, the author's intentions stop being authoritative and thus belongs to the reader, not the writer. Before him, Wimsatt and Beardsley's 1946 concept of the *[intentional fallacy](https://en.wikipedia.org/wiki/Intentional_fallacy)* made a similar case: a poem, once published, \"belongs to the public.\" The author can no longer control what it means. \n\nFor tags, that tension is not abstract theory. The writer tags their fic out of a felt sense of what it contains. The wrangler reads that tag as a data point in a taxonomy. The reader uses it as a filter. All three acts happen to the same string of text, and they don't always agree on what it means. \n\nAnd so, does it matter more to keep author intentions or to help make a work more accessible to readers? We've landed on: readers. Tags are infrastructure for discovery, not self-expression, and that means the reader's ability to use them takes priority over the writer's desire to use them however they want. I don't know if this is the right call, but I think it's still a good-enough compromise.\n\n## Promises Kept\n\nLuckily, there are some promises I am able to keep. ff.lol has a completely revamped relationship category system compared to AO3. You can see [a full visual list of them here](https://bkpoetry.com/post/818416685763690496/here-are-all-the-relationship-types-we-currently) (I coded the pride flags in pure CSS which I think is neat). I've also done a security audit and set up a robust backup system to ensure that, even if the site goes down for whatever reason, I'll be able to preserve the fics that have been published.\n\nI also am able to keep the site secure: the Rails application runs behind a [Cloudflare Tunnel](https://www.cloudflare.com/products/tunnel/), so the server itself is never directly exposed to the internet. No port forwarding, no direct IP exposure, with DDoS protection and SSL handled at the edge before traffic reaches my machine. The database is isolated on Docker's internal network, inaccessible from outside the container environment. No containers run as root or with elevated privileges. User data is encrypted at the application level using Active Record encryption. SSH access is key-based only. Sensitive credentials live in environment variables, not in config files. \n\nThe site is also compliant with [PIPEDA](https://www.priv.gc.ca/en/privacy-topics/privacy-laws-in-canada/the-personal-information-protection-and-electronic-documents-act-pipeda/) and Quebec's Law 25, because Canadian privacy law applies here too and I'd rather do that right from the start than patch it later.\n\nAnyway, as I've already said, creating this silly little site has taught me so much, and I'm really grateful for it. When it comes to what I'm trying to offer to people, I need to be measured.\n\n## Why Go Through So Much Effort for a Fanfic Site?\n\nThe entire reason why I created fanfiction.lol is because I want to [positively contribute to the commons of the Internet](https://brennan.day/good-standard-work-creating-the-commons/). It certainly isn't meant to be a replacement for AO3. It's just meant to be a low-barrier, accessible community-based archive of transformative works for anybody who wants an alternative, for whatever reason. Maybe you're too intimidated by AO3 and you want a smaller place to practice your writing. Maybe you just want to crosspost. Any answer is acceptable. That's the whole point.\n\nEven more important is that anybody can do this, with anything. You can buy a domain and start to learn how to make websites to share with people. I've even [made a beginner's guide for this for non-technical people](https://brennan.day/a-beginners-guide-to-the-indieweb-for-writers-who-dont-code-but-maybe-want-to-a-little/). I don't care if you use my website, but I do care about making the Internet a better place since we're all here so often.\n",
      "date_published": "2026-06-04T20:00:00.000Z",
      "tags": [
        "IndieWeb",
        "fanfiction",
        "community",
        "technical",
        "web development",
        "law",
        "moderation",
        "tagging"
      ],
      "author": {
        "name": "Brennan Kenneth Brown",
        "url": "https://brennanbrown.ca",
        "email": "mail@brennanbrown.ca"
      }
    },
    {
      "id": "https://brennan.day/be-a-lover-make-sure-the-quiet-wheel-gets-the-grease/",
      "url": "https://brennan.day/be-a-lover-make-sure-the-quiet-wheel-gets-the-grease/",
      "title": "Be a Lover: Make Sure the Quiet Wheel Gets the Grease",
      "summary": "The world isn't full of critics, it's full of quiet kind people who don't get nearly enough time or attention from us because we're born with a negativity bias. We need to proactively choose to be lovers and proactively grease the quiet wheels.",
      "content_html": "\nToday's blog post might be a rather cold take, but I think it's important to write nonetheless. It's still more processing thoughts as I've gone through the large amount of feedback I've gotten towards [fanfic.lol](https://fanfiction.lol). I have to say, creating something that has gotten so much feedback has taught me so much. I'm extremely grateful and lucky for what I've been able to learn.\n\nHave I gotten hostile, bad-faith arguments against the site, and by extension, me? Yes. But it really is a very small handful of people compared to the dozens who have been supporting me, with some people going out of their way to vocally defend the project and my intentions.\n\nI've spent my existence on the Internet trying to build goodwill organically. I've tried to show, with my actions, that I do not care about currency of any kind—money, clout, power—I am deeply disinterested in all of this. My [values](https://brennan.day/values) outline what I do care about.\n\nSo, I guess when this core aspect of my identity is denied and invalidated, that's when I feel the most need to explain myself at length.\n\nYou see, one person in particular made a rather long post trying to paint the project and me in a bad light: they said I was an extremely junior dev (despite the many years I have in the field), that forking a GPL-licensed open-source project was scummy (?), that the project was completely out of scope for me, that I was only making fanfic.lol to try to selfishly sell things I've created, I could go on. I spent a lot of time trying to explain to this person how I am following best practices and that I've made many projects and websites over the years, but it became clear the only answer they think would be acceptable would be that I take the site down and let AO3 continue to reign as the sole fanfiction site (despite the fact several other AO3 forks also exist). Anytime I wrote a comment to correct the record, they would update their post cherry-picking the worst things I said instead of having an actual conversation with me.\n\nAnd I think to myself, *why did I dedicate so much time and effort trying to convince a single person that I have good intentions and that I'm competent?* The answer was that they were an incredibly squeaky wheel.\n\nThe loudest people in the room are, more often than not, thought as being the most correct. At the very least, they're the ones listened to the most.\n\nAnd these people are usually critical instead of positive. They are usually tearing things down while not creating anything themselves or at the very least pouring themselves into advocacy and uplifting. They are not dedicating their time and energy to creating a better commons for everyone, or they are only interested in their own vision of what's best.\n\nAnd I think to myself, why do I not dedicate more time and effort to those who have been friendly and supportive? Why do I not write paragraphs upon paragraphs gushing about the things I love? (Okay, [I actually did do this recently](https://brennan.day/a-love-letter-to-everything/), that makes me feel a little better).\n\nMost of the things I've created throughout my life have gotten small amounts of feedback, but that feedback has almost always been positive and intentional. And I need to remind myself that I should focus on this—because these are the exact kind of people who fly under the radar.\n\nThe brain you're using to read this sentence is not neutral and never has been. Negativity bias is one of the oldest things about us. The idea was first named formally by [Paul Rozin and Edward Royzman in 2001](https://bpb-us-w2.wpmucdn.com/web.sas.upenn.edu/dist/7/206/files/2016/09/negbias198PSPR2001pap-1t7hm4j.pdf). Negative events have been proven to carry five times the psychological weight of positive ones of equal size. \n\nOne cutting remark, one hostile post, one person who decides you are a fraud, it lands as a stone in still water, and the ripples go on and on. Meanwhile, the dozen people who quietly told you the work mattered, who sent the small emails, who simply showed up and used the thing you made? Those ripples are smaller, faster to fade, easier to forget.\n\nOur ancestors who paid extra attention to the rustle in the grass, or the shift in the light, or the stranger's cold expression? They survived, of course. The ones who stayed soft and open to every positive stimulus, unbothered by threat, conversely did not pass on as many genes. The brain we inherited is a threat-detector first and a joy-register second. Your brain encodes the eyeroll and stores the criticism much better than any warm, good memory. Your prefrontal cortex, the part of you that is supposed to be rational and in charge, replays the embarrassing moments in the dark at three in the morning. It takes five deposits of warmth to balance a single moment of hostility.\n\nNeuroimaging has found that [brain activity spikes more intensely for negative stimuli than positive ones](https://pmc.ncbi.nlm.nih.gov/articles/PMC4830281/). [Infants as young as six months show stronger responses to a frowning face than a smiling one](https://pmc.ncbi.nlm.nih.gov/articles/PMC7695867/). Our threat recognition runs deeper than any belief you hold about how you want to move through the world.\n\nWhen I spent hours composing careful, measured replies to someone who had already decided I was lying—when I refreshed the page to see if they'd responded, if they'd understood, if something had shifted? That's how my neurology operates. The oldest instruction in our nervous system is *there is a threat. address the threat. do not look away.*\n\nThe problem is that instruction was written for a different world of predators and scarcity. In my world, the threat is never as dangerous as it feels. The critic will not kill me! They are a person with a keyboard and a certainty they didn't earn. And yet we hand them the microphone anyway. We give them the hours. We write the careful replies.\n\nWhat we can do, and what the research in positive psychology consistently recommends, is to consciously retrain the lens. Gratitude practices. Proactive acts of attention. \n\nNot toxic positivity, no. Not the *performance* of contentment, but the choice to use your will to notice what is good, to hold it a little longer than feels natural, to let it form a memory with the same durability as the bad ones. I am trying to do that now, here, in public, with you.\n\nWell-reasoned, nuanced, kind people do not cause the same seismic waves that loud, polarizing people do. And they deeply matter. The quiet among us who are doing work and giving positive feedback and enjoying life do not get nearly the time and attention they deserve.\n\nThere is no reason for our cultural vocabulary to have \"hater\" be so commonplace when \"lover\" is so absent. Speak up about what you love more, reach out to those who are kind and give them the kind of dedicated attention and energy you give people who are critical and long-winded.\n\nFandom exists in the first place because of lovers. Because of people who deeply connect with cultural experiences and channel that connection into their own artistic work and community. That's why I am doing any of this in the first place.\n\nWhen you pick up sand, the harder you squeeze and the harder you try to hold it, the less you'll have. When you cup your hand gently, the sand stays. I think that says a lot.\n\nSend a positive message today to someone who probably would love to hear it. \n\nWhen you love something, say so with the same energy you'd spend on outrage. More, even. Love is rarer on the Internet and it takes more courage, and it is doing more work in the world than any of us tend to notice.\n\nThe quiet wheel still needs the grease, it just asks quietly. And I think the lovers built everything worth keeping.\n\nBe a lover. Out loud. Today.\n",
      "date_published": "2026-06-03T20:00:00.000Z",
      "tags": [
        "IndieWeb",
        "community",
        "psychology",
        "writing",
        "digital culture"
      ],
      "author": {
        "name": "Brennan Kenneth Brown",
        "url": "https://brennanbrown.ca",
        "email": "mail@brennanbrown.ca"
      }
    },
    {
      "id": "https://brennan.day/the-internet-needs-more-cross-pollinators/",
      "url": "https://brennan.day/the-internet-needs-more-cross-pollinators/",
      "title": "The Internet Needs More Cross-Pollinators",
      "summary": "So, my silly little fanfic project blew up like crazy and received some really negative feedback. And I think I understand why. Exploring the concept of boundary spanning and cross-pollination in online communities. Drawing on organizational theory and the work of Michael Tushman. We need people who move between different online subcultures to seed ideas and build bridges.",
      "content_html": "\nA few days ago, I launched a silly little web project the same way I have been doing for years. This one was different though, because people cared about it. Or at least, they cared about talking about it.\n\nAs I wrote a few days ago, I launched [fanfiction.lol](https://fanfiction.lol), a fork of the open-source repository [Archive of Our Own](https://archiveofourown.org/). I decided [to post about it](https://www.tumblr.com/bk-poetry/818211983777284096/more-information?source=share) on my poetry Tumblr, since the only reason I use Tumblr at all is to post my poetry. And I also [blazed](https://www.tumblr.com/staff/682081646367981568/blaze-it) the post $10 for fun, which is the Tumblr version of advertising a post.\n\nI've blazed posts in the past, trying to get people interested in my [low-cost writing school](https://fireweed.school) or my [values-driven webdev studio](https://berryhouse.ca) and they got a dozen or so notes. So I naïvely assumed that this project would have a similar fate.\n\nIt didn't, it got thousands of notes, and the site got nearly 200 sign-ups so quickly that I exceeded the free plan of my email provider SendGrid—who then blocked me from paying for a monthly plan because their KYC policy meant I needed to send them my identity.\n\nNo thanks. I switched to [Resend](https://resend.com) which has a much more generous free tier of 3,000 emails a month. If I exceed that, then I'll freak out and figure out something else.\n\nHowever, the amount of people talking about my project on Tumblr was far, far higher than the amount of people signing up. I received a lot of negative feedback at first:\n\n> \"And do you have a legal fund to defend authors?\"  \n> \"how is this actually different from ao3?\"  \n> \"There already is a fanfiction website. Wtf\"  \n> \"1. nothing will replace ao3 2. i feel like you could have at least changed the ui?? the layout is identical\"  \n> \"Will you be able to host it for 5-10-15-20 years like ao3 does?\"  \n> \"all of this is somehow weirder and sketchier than ao3 already is\"  \n\nAll because I started a website running in my basement on a 2012 CPU, wow!\n\nIt didn't take long for the tides to turn and for the vast majority of people to be kind and defend the site and my choice to start this project, though. The backlash to the backlash, for a thing that's just begun.\n\nBut the truth is, I understand the small amount of negative, hostile reaction I got.\n\nWhen I first encountered [SuperLove](https://superlove.sayitditto.net/), before I even met the owner Melo, I could instantly tell it was a fork of AO3 and that, therefore, AO3 must be open-source. I've been a web developer for over a decade, and that kind of thing is intuitive to me.\n\nBut if you're someone who's grown up on the siloed corporate social media dystopian landscape of the Internet, and you've never encountered \"forks\" of projects or people creating websites for the sake of creativity and joy instead of for profit or clout, I can very much understand that upon first glance, it looks as though fanfiction.lol completely stole AO3's design and purpose.\n\nMany people online are skeptical and paranoid of new websites and new ventures on the Internet because, for the past decade, the Internet has only been the oligarchy of Meta, Twitter, Alphabet, and Amazon. Anytime anybody has launched something new, it's been an NFT or crypto rugpull or AI-generated or some other horseshit.\n\nFurthermore, these corporate oligarchs have instilled an idea of irrational platform loyalty and that the Internet is a zero-sum game. That you must dedicate yourself to a particular platform, with a particular subculture, and these other massive sites have their own subculture.\n\nAll of this is exactly why I've become such a loud, strong advocate for the IndieWeb. None of this is inherently true. The Internet is supposed to be hundreds of websites, created and owned by people and not massive for-profit companies. Take a look at [NeoCities](https://neocities.org/browse) or [NekoWeb](https://nekoweb.org/explore?page=1&sort=follows&by=name&q=) or [BearBlog](https://bearblog.dev/discover/) if you want a few positive examples. There are hundreds, if not thousands of websites on each of these platforms.\n\nAnd there are thousands more made from scratch just like mine, brennan.day.\n\nAll of this is to say we are in desperate need for cross-pollination on the Internet. About a month ago, I wrote a post where I [neurotically worried about being taken seriously as a writer](https://medium.com/@brennanbrown/being-taken-seriously-as-a-writer-453198c551f9?sk=8203ca4847f9f1f80ba8dec5987f1df7) because the kind of writing I do on this blog felt out of place compared to many other writers on the IndieWeb. But then I got this brilliant reply from researcher [Lori Ramey](https://medium.com/@loriramey):\n\n> \"or -- hear me out -- you are perfectly positioned to bring some of the intellectual intensity of the typical substack person into the cozier spaces where folks may find that they enjoy having something bigger to chew on once in a while.  \n>  \n> In org theory (one of my research areas), a while back it was trendy in the research to talk about individuals in organizations who inhabit multiple spheres. Sometimes they were called \"border-crossers\" or \"boundary-crossers\" (positive connotations). Those folks in an organization are literally worth gold. They're the designers who walk to another building to \"go check in with the engineering team\" or the PR person who makes sure they eat lunch at a different table every day so they get a sense of what's happening throughout the building. They seed ideas around, make friends, introduce people to others simply because they're aware that both people have similar interests.  \n>  \n> Cross-pollination pushes ideas forward. Writers who straddle spheres are important to that flow.\"\n\nThe idea has a body of literature behind it. The formal term goes back to organizational theorist [Michael Tushman's landmark 1977 paper](https://www.talkingaboutorganizations.com/73-organizing-innovation-michael-tushman/) in *Administrative Science Quarterly*, as \"boundary spanning.\" Tushman studied 345 researchers across 58 R&D projects and found the people who drove real innovation weren't the most technically brilliant people in the room. They were the ones who were well-connected both *inside and outside* their unit. Those who could hold two rooms in their heads at once and carry something living between them.\n\nLike pollen. A bee doesn't know it's doing anything revolutionary. It just moves. And in that movement, it carries what one flower made into the waiting dark of another.\n\nTushman called these people [gatekeepers and organizational liaisons](https://journals.aom.org/doi/10.5465/255842). Different roles, but the same gift of permeability. The ability to exist on the edge of one world without fully leaving it, while pressing into another. Later researchers, building on his work, described [boundary spanners](https://www.academia.edu/16657486/Crowding_at_the_frontier_boundary_spanners_gatekeepers_and_knowledge_brokers) as \"creative, lateral thinking rule-breakers\" with \"an appetite for opportunism,\" people who operate somewhat independent of formal structures, nurturing relationships that institutional walls would otherwise prevent. They don't wait for permission to go have lunch at the other table. They just go.\n\nThe web has its own version of this. Not in an office building where someone makes their rounds, but in the stranger, more diffuse architecture of hyperlinks and RSS feeds and posts drifting across platforms like seeds on wind. Someone posts a thinkpiece on Substack, a YouTuber makes a video essay, someone on Tumblr [webweaves quotes from it](https://everything2.com/title/web+weaving), and it lands in a Discord server, and three weeks later the idea has its NeoCities page and webring. That's cross-pollination. That's how the living parts of the Internet metabolize.\n\nBut it only works if someone actually moves. If someone is willing to be the weird person who is both here and there—in the fandom space and the IndieWeb space, in the literary blog world and the tech writing world, in the Tumblr reblog economy and messy craft of the independent personal site. \n\nThe Internet's structural holes—the gaps between communities that never talk to each other—don't close themselves. Someone has to be willing to be the bridge, willing to be nowhere solid.\n\nAnd this outlook changed everything for me. Yes, this is how the Internet moves forward and repairs and is liberated. The only reason I got that comment in the first place is specifically because I crosspost to Medium!\n\nAs I mentioned in [my announcement post](https://brennan.day/announcing-fanfiction-lol-a-manifesto-on-human-creativity-and-ao3/), I haven't been in fandom spaces for a long time. And I bring a lot of things from the other subcultures I'm involved in that I think could benefit the norms of fandom culture. I'm in contact with a lot of people who understand the philosophy of the IndieWeb, sure, but they are not on websites like Tumblr.\n\nAnd I can think of no better example of a border-crosser than [Melo](https://girlonthemoon.xyz/), the creator of the AO3 instance SuperLove. She is someone who is deeply invested in various fandoms and the IndieWeb and has gone out of her way to develop web infrastructure that is difficult to develop. I would have never gotten the idea to make fanfiction.lol if I hadn't met her or seen her project, and I certainly would have never been able to make it without her guide.\n\nIf the independent Internet is going to thrive, we must branch out. We must make the norms of radical generosity and creativity and creation into norms in the places we say we try to actively avoid out of principle. I deeply believe we must meet people where they are. That's all I've ever been trying to do since I began the brennan.day experiment.\n",
      "date_published": "2026-06-02T20:00:00.000Z",
      "tags": [
        "IndieWeb",
        "community",
        "Digital Culture",
        "philosophy",
        "Internet Culture"
      ],
      "author": {
        "name": "Brennan Kenneth Brown",
        "url": "https://brennanbrown.ca",
        "email": "mail@brennanbrown.ca"
      }
    },
    {
      "id": "https://brennan.day/announcing-fanfictionlol-a-manifesto-on-human-creativity-and-ao3/",
      "url": "https://brennan.day/announcing-fanfictionlol-a-manifesto-on-human-creativity-and-ao3/",
      "title": "Announcing Fanfiction.lol: A Manifesto on Human Creativity and AO3",
      "summary": "I deployed my own AO3 fork called fanfiction.lol, an independent fanfiction archive with no invite queue, fandom-agnostic moderation, and expanded content warnings. A manifesto on why fan communities deserve free infrastructure, the history of transformative works from Virgil to AO3, and the challenges of running a volunteer-powered archive at scale.",
      "content_html": "\nA few days ago, I wrote a [guide for setting up a cheap, accessible server](https://brennan.day/homelab-for-the-beginner-you-can-self-host-your-own-server-on-50-hardware/). In truth, after being a front-end developer for over a decade, I realized that the full-stack wasn't as scary as I thought it'd be. But with the server up and running, I needed a real project to sink my teeth into. Something that would force me to have skin in the game.\n\nBeing on the [IndieWeb](https://indieweb.org/) for half a year now, I've encountered a lot of impressive, talented web developers and webweavers—I went over a few of them in [my love letter post](https://brennan.day/a-love-letter-to-everything/). One of them is a sysadmin I know who runs [SuperLove](https://superlove.sayitditto.net/), a fork of the codebase [otwarchive](https://github.com/otwcode/otwarchive), the codebase powering the largest fanfiction archive in the world, [Archive of Our Own](https://archiveofourown.org/), or AO3.\n\nI was told this is notoriously difficult to set up, and that there are only a handful of these AO3 forks in existence. [SquidgeWorld](https://squidgeworld.org/), run by Walter, published the foundational bare-metal setup guide at [squidgeworld.org/works/34491](https://squidgeworld.org/works/34491). Squideworld was the [very first AO3 fork](https://fanlore.org/wiki/Squidge.org), launched in November 2020. Since then, a small constellation of independents has followed. \n\nI decided to try my hand at initializing and deploying one of my own, specifically because of the challenge. I purchased the domain fanfiction.lol for two bucks, set up my CloudFlare tunnel, populated the database, wrote quite a bit of janky Ruby script, and to my surprise things didn't take that long to get up and running (mostly though with the help of [Melo's guide](https://superlove.sayitditto.net/works/171), of course).\n\nLet me tell you, the stack is a bit of a beast. There's Ruby on Rails 8.1.0 running on Ruby 3.4.6, MySQL for the database, Redis, Elasticsearch (which takes 2GB of RAM alone), and Memcached. They're all containerized with Docker Compose. The otwarchive codebase is a full-featured archive with work search, kudos, comments, collections, and the well-known AO3 tagging system. I wrestled with database initialization, Elasticsearch indexing, site skins (the CSS is stored in the database, not files, which makes design work hell), and configuring SendGrid for SMTP email notifications.\n\nI deployed it to the server currently living in my basement behind a Cloudflare Tunnel, handling SSL and routing without opening my home ports to the internet. The whole thing runs in Docker containers: the Rails app, a background job worker, a scheduler for recurring tasks, and all the supporting services. It's a lot of moving parts, but Docker makes it manageable thankfully.\n\nSo, after sitting at my IDE for 20 hours straight and looking at site surprisingly running, I asked myself: do I actually want to do this for real? Do I want to be a webmaster for a fandom writing community?\n\nThe answer was an unhesitating yes.\n\n## The Fanfics of Virgil, Dante, and Shakespeare\n\nI've been writing my entire life, and have written a lot already about how I believe writing is sacred, even going as far as to proclaim it [is literal magic](https://brennan.day/storytelling-part-two-the-literal-magic-of-writing/). Writing is how we process the world and relieve some of that constant flooding of our minds. It's how we figure out our identity until something fits. Writing is good medicine.\n\nAnd [fandom](https://blog.brennanbrown.ca/fandom-is-awesome-furries-are-awesome-bronies-are-awesome-cringe-is-awesome-fuck-you-1c7b5558457b?sk=18dabe2ea92ddb5165fd718ce85960c4) in particular is where a lot of that writing lives. The history of [transformative works](https://fanlore.org/wiki/Fanworks) is much longer than most people assume. \n\nVirgil wrote *The Aeneid* as an expansion of Homer, Dante planted his self-insert and contemporaries in Hell, Shakespeare himself [recycled plots](https://www.thedailystar.net/daily-star-books/news/exploring-the-transformative-power-fanfiction-3371596) from Holinshed and Ovid with creative abandon. People have always extended or deconstructed stories. Always have yearned for a rewritten ending or to give a voice to a background character. You see, the practice of taking a story that matters to you and doing something new with it is as old as storytelling itself.\n\nAnd the Internet liberated the practice! LiveJournal in the early 2000s. FanFiction.net. Even zines before that, the physical stapled things circulated at conventions, mailed between strangers who found each other through classified ads in the back of genre magazines. [Fan communities](https://learnaboutpod.com/ep-132/) gave historically marginalised people (women and Queer people especially) spaces to write stories that the mainstream wouldn't write, to explore identities that the mainstream wouldn't represent, and to say things the mainstream wouldn't print. The shame often attached to fanfiction, the social condescension of \"oh, you write that kind of thing,\" has always been a shame aimed at the people who needed these spaces most.\n\nThere is an incredible outpouring of love and creative labour in fandom, often dismissed by the general population, as well as by the \"more serious\" writing circles I've moved through. Fanfiction communities produce extraordinary writers. They have produced communities that have held people through some of the hardest years of their lives. \n\nThey deserve independent, free infrastructure. And yes, it is that serious.\n\n## What AO3 Has Become\n\n[Archive of Our Own](https://archiveofourown.org/) is important. The [Organization for Transformative Works](https://www.transformativeworks.org/) built a non-profit, volunteer-run, ad-free archive legally defending fanwork as transformative expression. That is nothing short of remarkable. AO3 currently hosts over 18 million works across more than 77,000+ fandoms, and recently crossed 10 million registered users. That's a staggering amount of human creative energy freely shared.\n\nBut AO3 has, inevitably, become a massive institution. And institutions calcify. The OTW is an all-volunteer organization, and the strains of that model are visible. Internal documents have long acknowledged an \"existing burnout problem\" and volunteer hiring freezes, leaving time as a scarce resource across many projects. One OTW Volunteers and Recruiting chair described an \"epidemic\" of volunteer burnout and turnover that has plagued the organization since at least the early 2010s. The scale of the archive has only grown since then. Feature development that the community has requested for years moves slowly, when it moves at all. Policy and Abuse received approximately 28,000 tickets in 2024 alone, processed by volunteers. The bureaucratic overhead of running something this large, this carefully, and this democratically is enormous—and it shows.\n\nAnd then there's the invitation system. On Archive of Our Own, there are currently 144,235 people on the waiting list, and they send 4000 invitations every 12 hours. It would take over two weeks for you to get an invite if you're at the back of the line. The invitation system exists so that AO3 can grow in a controlled manner, but a project like mine doesn't have that problem.\n\n## What Makes `fanfiction.lol` different?\n\n**Anybody is free to register on [fanfiction.lol](https://fanfiction.lol).** Unlike AO3 and the other forks, there is no queue or invite system. On Archive of Our Own, there are currently 144,235 people on the waiting list, and they send 4000 invitations every 12 hours. It would take over two weeks for you to get an invite if you're at the back of the line. You want to post your story on fanfiction.lol, then sign up. That's it. \n\nThe site runs on the same open-source [otwarchive codebase](https://github.com/otwcode/otwarchive), which means it has the same robust tagging system, the same work search, the same kudos and comments and collections infrastructure.\n\nWhat does that mean in practice?\n\n**fanfiction.lol is fandom/discourse agnostic.** I care about the writing of fans, not discussions about what writing is good or problematic. There is no interest in fandom's internal politics. Write whatever you want. Tag it honestly so readers can find what they're looking for and avoid what they'd rather avoid.\n\n**I take content warnings seriously.** The archive warnings have been updated to include Systemic Oppression, Colonialism, Ableism, Homophobia/Transphobia, Racism, and Real Person Fiction. These are important signals for readers who need them. The relationship tags currently include Aromantic/Asexual Spectrum, QPR, Non-Binary/Genderqueer Focus, Poly/Ensemble, and more. A tagging system should reflect the full range of what people actually write. If you think I've missed something, let me know and I'll add it!\n\n**All tags are canonical.** On AO3, only certain approved tags are \"canonical\", which means they're searchable and wrangled by volunteers into consistent forms. The rest are secondary and freeform. Here, everything you tag goes into the searchable record.\n\n**It's small. It's personal. It's mine.** And yours, too, if you'd like.\n\n## My Limitations\n\nI have not been actively involved in fandom spaces since I was a teenager. I'm thirty years old now. I approach this with no existing allegiances, no current involvement in any fandom's internal debates, no stake in any ship war or discourse cycle. I understand that some people will read that as disqualifying. But there's a real benefit to bringing fresh eyes somewhere, I think.\n\nBut I have been chronically online since Windows 98, and [I've run a writing community before](https://writeclub.ca/about), for three years. I've learned a lot of lessons from that experience, and I understand the dynamics at play.\n\nSomething else important that I want to note is that multiple owners of AO3 forks have told me that this is a difficult, unforgiving role. That there are a lot of bad-faith entitled people they've had to deal with, and have gotten harassed and stalked simply for operating a fanfiction website. I am not ignorant or naïve to how the Internet and people on it can be, but I do know I can handle it. \n\nI know how to moderate a space, and I know how to hold a line, and I do not believe that the possibility of harassment is a reason to leave the commons ungoverned or un-built. The commons must not be destroyed. Someone has to tend the infrastructure.\n\n## Joy-as-priority\n\nAs the name makes obvious, [fanfiction.lol](https://fanfiction.lol) is supposed to be fun and joy in fandom and creation. It is supposed to be a place where the writing is the point. I care deeply about fans and their work, not the discourse around the writing, not status hierarchies, nor the arbiters of legitimacy. Write whatever you want and celebrate the fact that you made something.\n\nI am bringing the [same good-faith, big-tent philosophy](https://brennan.day/what-does-it-mean-to-be-a-good-editor/) I bring to the IndieWeb and my life in general.\n\n## Break Things, Please\n\nRight now the site has only a handful of users, and fanfiction.lol is very much in active development. Things may break, data may occasionally get obliterated, and I am one person running this alongside [a lot of other web projects](https://brennan.day/indieweb).\n\nIf you're someone who enjoys fandom, I'd love for you to [sign up](https://fanfiction.lol/signup) if only to poke around, try to break things! Tell me what you find. The source code lives at [source.tube/brennan/fanfiction.lol](https://source.tube/brennan/fanfiction.lol). You can find me at [brennan.day/accounts](https://brennan.day/accounts) across the web. Send an email to [mail@brennanbrown.ca](mailto:mail@brennanbrown.ca) or find me on Mastodon at [@brennan@social.lol](https://social.lol/@brennan).\n\nWrite whatever the hell you want!\n",
      "date_published": "2026-05-30T20:00:00.000Z",
      "tags": [
        "IndieWeb",
        "technical",
        "self-hosting",
        "fandom",
        "community",
        "open source"
      ],
      "author": {
        "name": "Brennan Kenneth Brown",
        "url": "https://brennanbrown.ca",
        "email": "mail@brennanbrown.ca"
      }
    },
    {
      "id": "https://brennan.day/homelab-for-the-beginner-you-can-self-host-your-own-server-on-50-hardware/",
      "url": "https://brennan.day/homelab-for-the-beginner-you-can-self-host-your-own-server-on-50-hardware/",
      "title": "Homelab For the Beginner: You Can Self-host Your Own Server on $50 Hardware",
      "summary": "A beginner-friendly guide to building your own homelab on inexpensive hardware. Covers finding old computers, setting up Linux, SSH, Docker, and self-hosting services like password managers, RSS readers, and your own Fediverse instance. Digital sovereignty doesn't require expensive equipment.",
      "content_html": "\nBuilding on my last post about the [Gemini and Gopher protocols](https://brennan.day/gemini-gophers-and-fingers-oh-my-alternative-internets-beyond-https/), I realized I wanted to take a step further in helping others reclaim web autonomy and sovereignty. So I'm writing this guide.\n\nA few months ago, I wrote about [permacomputing and computing for the apocalypse](https://brennan.day/computing-for-the-apocalypse/) where I briefly spoke about self-hosting and creating your own homelab. But I did not get into the \"how-to\" at all.\n\nI want to do that today, because I took another swing at creating a homelab, and though there was a lot of trial and error, I was overall really impressed by how much capability and functionality you can get out of old, inexpensive hardware.\n\nI originally shelved the project in January and put it on the backburner, because I'm the stereotypical dev that enjoys hopping from one new shiny idea to another. But more than that, [I am not a full-stack web developer](https://brennan.day/why-i-m-not-a-full-stack-dev/). I stick to the front-end and [JAMstack](https://jamstack.org/), avoiding databases, backend, and DevOps altogether.\n\nBut the Internet doesn't actually work that way. Sure, you can use [Netlify](https://www.netlify.com/) or [Vercel](https://vercel.com/) to host and deploy your front-end static sites or [Astro.js](https://astro.build/) solution or whatever else you might be building, typically for no cost. But this means you're relying on a company that could suddenly begin charging you money or change their licensing. Regardless, it's a fragile solution, albeit a really convenient one I'm still using.\n\nI want to [build for the long web](https://brennan.day/how-are-we-preparing-for-the-long-web/), and really, homelabbing can be a fun, useful hobby.\n\n## What Can Be Self-hosted, and Why?\n\nBefore we get into hardware, I want to make the case for *why this is worth doing at all*. It's easy to look at a list of Docker containers and wonder why the hassle is worth it.\n\nEvery service you use daily that you don't control is a liability. Companies shut down, or change their pricing, or get acquired, or start monetizing your data, or make unethical decisions that don't align with your values. I'm sure you've been there.\n\nSelf-hosting is the practice of running your own software on your own hardware. Taking back ownership of the tools you rely on. Here's a taste of what's possible:\n\n- **Instead of Google Drive/Dropbox** → [Nextcloud](https://nextcloud.com/) or [Seafile](https://www.seafile.com/). Your files synced to all your devices.\n- **Instead of 1Password/LastPass** → [Vaultwarden](https://github.com/dani-garcia/vaultwarden), a lightweight Bitwarden-compatible password manager you host yourself.\n- **Instead of Feedly/Feedbin** → [FreshRSS](https://freshrss.org/) or [Miniflux](https://miniflux.app/). Read the web on your own terms.\n- **Instead of GitHub** → [Forgejo](https://forgejo.org/) or [Gitea](https://gitea.com/). Your repositories, with no Microsoft or genAI training on your code.\n- **Instead of Discord/Slack** → [Matrix/Synapse](https://matrix.org/) or [Mattermost](https://mattermost.com/). Private and federated.\n- **Instead of Google Photos** → [Immich](https://immich.app/). A beautiful, fast, self-hosted photo library with mobile backup.\n- **Instead of Notion** → [AppFlowy](https://appflowy.io/) or a simple [DokuWiki](https://www.dokuwiki.org/). Flat-file format with no lock-in.\n- **Instead of Twitter/Mastodon (someone else's instance)** → [GoToSocial](https://gotosocial.org/) or [Mastodon](https://joinmastodon.org/). Your own Fediverse node, so your posts live on your server.\n- **Instead of Substack** → [Ghost](https://ghost.org/) or a static site generator like [Hugo](https://gohugo.io/).\n- **Instead of Google Analytics** → [Umami](https://umami.is/) or [Plausible](https://plausible.io/). Privacy-respecting analytics that don't treat website visitors as products.\n\n## The Spectrum of Homelab\n\nIt's important to be mindful that homelabbing is a very wide spectrum: You can have 48U 4-post cabinets in a dedicated, soundproofed, climate-controlled server room with redundant 30 kVA online double-conversion UPS systems backed by a natural-gas automatic standby generator.\n\nOr, you can have [an old Android phone](https://www.instructables.com/Old-Android-Phone-to-WebServer/) or a $15 [Raspberry Pi Zero](https://www.raspberrypi.com/products/raspberry-pi-zero/) with a 2GB microSD serving index.html with the command `darkhttpd /home/pi/site --port 8080`.\n\nThe overwhelming majority of home servers are far closer to the Pi Zero: A decommissioned work laptop, or a tower pulled from someone's curb, a SFF (small form factor) desktop bought at a garage sale. A machine considered e-waste can actually run web services, drawing only ~40–60 watts from the wall.\n\n## My Philosophy\n\nA popular reason people get into homelabbing and self-hosting is for private streaming of your personal media library, which is usually pirated. That's fine with me, all the power to the pirates! But that's not what this guide is going to be about.\n\nPrimarily, this is because software media systems like [Jellyfin](https://jellyfin.org/) are resource-intensive compared to the services I'm going to be going over. Hardware transcoding, large media libraries, and multiple simultaneous streams ask too much of modest old hardware.\n\nMy homelab, running at `brennan.cafe`, is a privacy-focused and self-hosted personal infrastructure built on sustainable principles. It represents a journey away from corporate cloud services toward digital sovereignty and ethical computing.\n\n### Why?\n\n- **Privacy:** Take back control of personal data\n- **Learning:** Understand the technology you use on a daily basis\n- **Sustainability:** Make use of existing hardware rather than consuming new resources\n- **Freedom:** Break free from vendor lock-in and surveillance capitalism\n\n### Principles\n\n- **[IndieWeb](https://indieweb.org/):** Own your content, interact with others on your terms\n- **[Permacomputing](https://permacomputing.net/):** Sustainable, mindful computing practices\n- **FOSS:** Free and Open Source Software exclusively\n- **Privacy:** Zero tracking, no surveillance, respect for users\n\n## Step Zero: Finding Your Hardware\n\nWhere do you get hardware for a homelab, self-hosting server? Anywhere, if you know how to look. With both RAM and storage options [becoming increasingly, absurdly expensive](https://www.pcgamer.com/hardware/memory/team-group-ceo-warns-that-dram-and-ssd-prices-will-still-rise-if-you-need-memory-we-recommend-purchasing-it-as-soon-as-possible/), I can only recommend buying used from the following places:\n\n- **Thrift stores and Goodwill**: In many cities, you can walk into a Value Village or local Goodwill and find towers and desktops from 2010–2016 selling for $20–$40. They're usually wiped, sometimes missing a hard drive, occasionally missing RAM. That's fine. Bring a USB stick with a Linux live image. Boot it up in the aisle (yes, you can ask staff). Check that the machine POSTs, that the CPU fans spin, that USB works.\n- **Facebook Marketplace and Kijiji**: Search \"computer\" filtered under $60 and sort by distance. You will find a graveyard of machines people are desperate to get out of their spare rooms. HP EliteDesks, Dell OptiPlexes, Lenovo ThinkCentres. All workhorses built for enterprise, which means they're far more reliable and better-cooled than consumer hardware of the same era. Look for machines with an **Intel Core i3/i5/i7 from the 3rd–7th generation**, or an **AMD FX series**, ideally with at least 4 cores and 8 GB of RAM.\n\n| Spec | Minimum | Sweet Spot |\n|------|---------|------------|\n| CPU | 4 cores, 2.4 GHz | 4–8 cores, 3.0+ GHz |\n| RAM | 4 GB | 8–16 GB |\n| Storage | 120 GB SSD | 250 GB+ SSD |\n| Network | 100 Mb/s | 1 Gb/s Ethernet |\n| Power | Anything with a standard ATX PSU | — |\n\nHaving a solid state drive will be far faster than a mechanical hard drive (the shiny metal ones that are much heavier), though they do have a shorter lifespan. If the machine you're buying has an HDD, budget $20–$40 for a used SATA SSD (Samsung 860 Evo, Crucial MX500), but keep the HDD for backup.\n\n### What To Avoid\n\n- Small form factor HP/Dell machines with *proprietary* power supplies (they fail, and replacements cost more than the machine itself, I learned this the hard way)\n- Anything with a Core 2 Duo or older unless you're *only* serving the most basic webpages.\n- Machines that have been stored in damp conditions (smell the vents)\n\n## My Homelab: The Tower in A Basement\n\n| Component | Specification |\n|-----------|---------------|\n| CPU | AMD FX-4130, 4 cores @ 3.8–3.9 GHz |\n| RAM | 7.24 GiB DDR3-1333 |\n| Storage | 228 GiB SSD (Samsung Evo 820) |\n| Motherboard | Gigabyte GA-78LMT-USB3 (AM3+ socket) |\n| Network | 1 Gb/s onboard Ethernet + USB Wi-Fi adapter |\n| OS | [Lubuntu](https://lubuntu.me/) 26.04 LTS (Resolute Raccoon) |\n| Desktop | LXQt / Openbox |\n\nMy own humble homelab server is a custom Acer Gigabyte full-tower I originally bought off Kijiji at the start of the pandemic six years ago for my little brother. It was advertised as a \"gaming PC\" and was really cheap. Unsurprisingly, it couldn't handle gaming whatsoever. The seller ghosted me when I tried to return it.\n\nAnd thank goodness he did, because now it's the perfect machine for this! :D\n\nIt lives in the basement, next to a spare bookshelf and synth organ. The tower sits on the carpet floor. A squat black rectangle, sticker residue on the side where a label was once peeled off. With the side panel removed, the fans pleasantly move the air around me while I'm tinkering and troubleshooting. A white $15 USB Wi-Fi adapter with a stubby antenna blinks green constantly. \n\nThis computer is terrible at being a desktop. If you try to even just move a window around, it stutters and lags. (I still have a ThinkPad X200T I bought for $40 that boots into Openbox and BunsenLabs and functions better as a desktop than this tower does) I'm pretty sure there's something wrong with the integrated graphics. But using it as a server you never look at? It works great! It's perfect. The limitation became the feature.\n\nIt did have a dedicated graphics card when I got it—a GT 700-something, one of those cards that's designed to look like a gaming GPU but is actually a low-end office card. I pulled it out and the connector pins looked possibly corroded, and I didn't investigate further.\n\nThe Gigabyte GA-78LMT-USB3 markets itself as being durable, shock-resistant and humidity-resistant. That's pretty funny—who is explicitly in the market for a *durable* motherboard? The answer is doomsday preppers and... homelabbers. The thing has survived being a failed gaming PC, six years of neglected basement storage, and a full server rebuild.\n\nBefore I set this up, I went salvaging for parts in one of the HP Elite Compaq 8200s my mom previously used for her remote job, and I was happily surprised to find a **Samsung Evo 820 250GB SSD** just sitting in it. Those little HPs are nifty machines, but they have a weird proprietary power supply that costs as much as the machine itself to replace.\n\n<figure>\n<img src=\"/assets/images/blog/homelab.jpg\" alt=\"A Beszel server monitoring dashboard showing the \"cafe\" host: status Up, running Ubuntu 26.04 LTS on an AMD FX(tm)-4130 Quad-Core Processor with 7.24 GB RAM and 52 hours uptime. The dark-themed interface displays stacked area charts for Docker CPU usage (peaking around 11%, total 5.29% across containers including coolify, gotosocial, and redis), Docker Memory Usage (steady near 2 GB), and Docker Network I/O (peaking at 1.3 MB/s).\">\n<figcaption>A reading from <a href=\"https://monitor.brennan.cafe\">monitor.brennan.cafe</a> using <a href=\"https://beszel.dev/\">Beszel</a></figcaption>\n</figure>\n\n## What's Running\n\nHere's everything currently live on `brennan.cafe`:\n\n📁 **Files** — [FileBrowser](https://filebrowser.org/)\nA clean, web-based file manager for browsing and managing everything on the server. Think of it as a lightweight personal Google Drive UI. `files.brennan.cafe`\n\n📦 **Archive** — [ArchiveBox](https://archivebox.io/)\nSelf-hosted internet archiving. Save web pages, bookmarks, videos, and full media captures before they disappear. The web is more ephemeral than anyone admits. `archive.brennan.cafe`\n\n📊 **Monitor** — [Beszel](https://beszel.dev/)\nLightweight system monitoring — CPU, RAM, disk, network, all in a simple dashboard. Useful for actually knowing what your machine is doing. `monitor.brennan.cafe`\n\n📈 **Status** — [Uptime Kuma](https://uptime.kuma.pet/)\nTracks uptime and response time for all my services. Sends me a notification if something goes down. Looks like a Better Uptime clone, except it's yours. `status.brennan.cafe`\n\n📋 **Logs** — [Dozzle](https://dozzle.dev/)\nReal-time Docker log viewer. When something breaks at 2am, this is how you find out why. `logs.brennan.cafe` (password protected)\n\n💾 **Backup** — [Duplicati](https://www.duplicati.com/)\nEncrypted, scheduled backups to multiple cloud destinations (Backblaze B2, S3, SFTP, whatever you want). A backup solution you actually control. `backup.brennan.cafe` (password protected)\n\n📖 **Wiki** — [DokuWiki](https://www.dokuwiki.org/)\nFlat-file wiki — no database, just Markdown files on disk. I use it to document my own server: commands I keep forgetting, troubleshooting notes, configs. Write it down the first time. `wiki.brennan.cafe`\n\n🚀 **Deploy** — [Coolify](https://coolify.io/)\nA self-hosted Heroku/Vercel alternative. Point it at a git repo, it handles deployment. More on this below. `deploy.brennan.cafe`\n\n🦥 **Social** — [GoToSocial](https://gotosocial.org/)\nA lightweight ActivityPub server for the Fediverse. My own personal Mastodon instance, running on my own hardware. `@brennan@brennan.cafe` — `social.brennan.cafe`\n\n📰 **RSS** — [FreshRSS](https://freshrss.org/)\nSelf-hosted RSS/Atom reader with a solid web interface and mobile app support. I read the web through FreshRSS instead of through algorithmic feeds. It uses SQLite by default, so no Postgres required. `rss.brennan.cafe`\n\n✍️ **Blog** — [Grav CMS](https://getgrav.org/)\nA modern flat-file CMS built on PHP. No database. Markdown content. A good middle ground between a static site generator and a full CMS if you want a GUI for writing. `blog.brennan.cafe`\n\n### And the Resource Usage?\n\nThis machine is currently running **eleven web services**, using:\n- **2 GB out of 8 GB RAM** (25%)\n- **30 GB storage**\n- **~20% CPU**\n\nThat's a quad-core CPU from 2012, 8 gigabytes of DDR3 RAM, and a fast SSD. That's all my server requires, and you could run a homelab on even less.\n\n## Service Recommendations\n\nBefore you start deploying services, it's helpful to know what's realistic for your hardware. Here are the resource requirements for common self-hosted services:\n\n| Service | RAM (Idle) | Storage | Priority | Notes |\n|---------|------------|---------|----------|-------|\n| **Vaultwarden** | 10–30 MB | ~100 MB | 🔴 High | Password manager, Bitwarden-compatible |\n| **Beszel + Agent** | ~35 MB | ~100 MB | 🔴 High | Server monitoring hub |\n| **Uptime Kuma** | ~150 MB | ~200 MB | 🔴 High | Uptime/status monitoring |\n| **Dozzle** | ~20 MB | ~0 MB | 🔴 High | Real-time Docker log viewer |\n| **Duplicati** | ~50 MB idle | ~200 MB | 🔴 High | Encrypted backup solution |\n| **FreshRSS** | ~50 MB | ~500 MB | 🟡 Medium | RSS/Atom feed reader |\n| **Miniflux** | ~30–50 MB | ~500 MB | 🟡 Medium | Minimalist RSS reader (requires PostgreSQL) |\n| **Linkding** | ~70 MB | ~200 MB | 🟡 Medium | Self-hosted bookmark manager |\n| **Shlink** | ~120 MB | ~200 MB | 🟢 Low | URL shortener with analytics |\n| **Pi-hole** | ~130 MB | ~500 MB | 🟢 Low | Network-wide ad blocker |\n\n> **Note:** These are idle/typical usage. RAM and storage will increase with actual usage (more feeds, more bookmarks, larger vaults, etc.).\n\nOn an 8 GB machine with the services listed above, you'd use roughly 655 MB of RAM and 2 GB of storage — leaving plenty of headroom for additional services.\n\n### Services to Avoid\n\nNot every self-hosted service is suitable for older, modest hardware. Here are services that will overwhelm a machine like the one described in this guide:\n\n| Service | Why |\n|---------|-----|\n| **Jellyfin / Plex** | Requires hardware video transcoding for smooth playback. Software transcoding on a 4-core CPU will peg the processor and affect all other services. |\n| **Elasticsearch** | Requires 2+ GB RAM minimum. Designed for enterprise-scale search workloads. |\n| **ClickHouse** | Column-store OLAP database designed for high RAM environments. |\n| **Nextcloud** | Technically possible, but heavy on CPU for file processing, thumbnail generation, and previews. Can slow down the entire server. |\n| **GitLab** | Requires 4+ GB RAM recommended. The self-hosted version is resource-intensive. |\n| **Matrix Synapse** | The original Matrix server is very RAM-heavy. Consider a lighter alternative like Conduit if you need Matrix. |\n\nBuild up to these! Start with lightweight services and understand your machine's limits. Only tackle heavier workloads when you're ready to upgrade hardware or dedicate more resources.\n\n---\n\n## THE GUIDE\n\nNow, finally, we get into the actual how-to. This is not a single-sitting setup. Depending on how much of this you tackle, you're looking at a weekend project, maybe two. But each piece builds on the last, and once you have the foundation of OS, SSH, tunnel, and Docker, then everything else is running commands.\n\n## Step 1: Choosing Your OS\n\nThere are many different options for what operating system your server runs. Most guides will point you toward [Ubuntu Server](https://ubuntu.com/download/server), and that's reasonable. It's lean, stable, well-documented, and has a massive community.\n\nBut Ubuntu Server is *headless*, which means there's no graphical interface at all. You get a black screen, a blinking cursor, and a login prompt. Everything is done through the terminal. That's fine if you're technical, and it *does* free up RAM and CPU that would otherwise go to running a desktop environment.\n\nMy personal recommendation for beginners, though, is [Lubuntu](https://lubuntu.me/). Here's why:\n\n1. **It has a GUI when you need it.** Sometimes you just want to drag a file somewhere, or open a browser to check something, or use a GUI text editor. Lubuntu's LXQt desktop is lightweight enough that it costs you almost nothing in resources while giving you this escape hatch.\n2. **It behaves like Ubuntu** underneath. Same package manager, same community documentation, same `apt install` everything.\n3. **It's forgiving.** If you mess up your SSH config and lock yourself out, you can still physically sit down at the machine and fix it without needing a rescue USB.\n\nUbuntu Server uses around 200–300 MB less RAM, so keep that in mind. If you want to start with Ubuntu Server anyway, go for it. The rest of this guide works the same way.\n\n## Step 2: Using Micro\n\nIf you're not used to working in the terminal, I recommend you install [Micro](https://micro-editor.github.io/) to start. This is the text editor you'll use for everything configuration-related on the server.\n\n```bash\nsudo apt install micro\n```\n\nMost Linux guides assume you use `nano` or `vim`. Nano is fine and Vim is powerful, but has a learning curve that is famously steep, the mere act of exiting is a meme. (The answer, by the way, is to press `Esc`, then type `:q!` and press Enter. `:wq` if you want to save first.) \n\nMicro, on the other hand, has cursor support and uses familiar shortcuts. `Ctrl+S` to save, `Ctrl+Q` to quit, `Ctrl+Z` to undo. It feels like a GUI text editor.\n\n## Step 3: SSH Keys\n\nNext, you'll need to get the local IP address of your server, run `ip addr` on the server itself for that. When you set up Ubuntu/Lubuntu, you'll provide a username. You put these together:\n\n`your-username@your-server-local-ip`\n\nFor example, mine is `brennan@192.168.1.66`\n\nSSH (Secure Shell) is then the backbone of everything that follows. It lets you connect to your server from any other machine, like your laptop in the living room, or in a coffee shop, anywhere really—and run commands as if you were sitting in front of the server.\n\nInstead of logging in with a password (which is less secure and more annoying), we use a key pair: a private key that lives on your computer, and a public key that goes on the server. The server will only let in machines that have the matching private key.\n\nThere are [detailed guides for this on ssh.com](https://www.ssh.com/academy/ssh/keygen), but the short version:\n\n```bash\n# On your local machine (not the server)\nssh-keygen -t ed25519 -C \"your-email@example.com\"\n```\n\nThis generates two files: `~/.ssh/id_ed25519` (your private key, **NEVER** share this) and `~/.ssh/id_ed25519.pub` (your public key, this goes on the server and can be shared).\n\nI also made [a handy script for generating keys at once](https://source.tube/brennan/omg.lol/src/branch/main/scripts/key-generator.sh) that I originally made for omg.lol. You can see all my public keys on my [/keys](https://brennan.day/keys) page!\n\nNext, copy your SSH key to your server:\n\n```bash\nssh-copy-id -i ~/.ssh/id_ed25519.pub your-username@your-server-local-ip\n```\n\nOnce your key is copied over, harden the SSH config:\n\n```bash\nsudo micro /etc/ssh/sshd_config\n```\n\nSet these values:\n\n```\nPasswordAuthentication no\nPubkeyAuthentication yes\nPermitRootLogin no\n```\n\nSave, then restart SSH:\n\n```bash\nsudo systemctl restart sshd\n```\n\nFrom this point forward, you can connect from your desktop computer to the server with the command:\n\n```bash\nssh your-username@your-server-local-ip\n```\n\n## Step 4: Keep the Server Running Indefinitely\n\nBy default, a desktop like Lubuntu will put itself to sleep after a period of inactivity. Great for a desktop, bad for a server. Here's how to disable that:\n\n```bash\n# Disable systemd sleep targets\nsudo systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target\n\n# Disable screen blanking (add to ~/.bash_profile or run at login)\nxset s off\nxset -dpms\nxset s noblank\n```\n\nIf you're using a laptop as your server, also disable lid-close sleep:\n\n```bash\nsudo micro /etc/systemd/logind.conf\n```\n\nSet:\n```\nHandleLidSwitch=ignore\nHandleLidSwitchExternalPower=ignore\n```\n\nThen:\n```bash\nsudo systemctl restart systemd-logind\n```\n\nTo prevent the display from turning off (optional, but nice if the machine has a monitor you occasionally glance at):\n\n```bash\nsudo micro /etc/X11/xorg.conf.d/10-noblank.conf\n```\n\n```\nSection \"ServerFlags\"\n  Option \"BlankTime\" \"0\"\n  Option \"StandbyTime\" \"0\"\n  Option \"SuspendTime\" \"0\"\n  Option \"OffTime\" \"0\"\nEndSection\n```\n\nIf you're using WiFi for server connectivity (instead of Ethernet), the WiFi adapter may enter power-save mode and stop responding to connections. For me, this caused a confusing situation where your site is online but you can't SSH in.\n\n**Symptoms:**\n- Local SSH unreachable but Cloudflare Tunnel works\n- ARP table shows \"incomplete\" for server IP\n- `ip link` shows WiFi interface in DORMANT state\n\n**Disable WiFi Power Save:**\n\n```bash\n# Find your WiFi interface name\nip link show\n# Look for something like wlxbc071d481e84 or wlan0\n\n# Disable power save immediately (replace with your interface name)\nsudo iw dev YOUR_INTERFACE set power_save off\n\n# Verify it's disabled\nsudo iw YOUR_INTERFACE get power_save\n# Should show: Power save: off\n```\n\n**Make it persistent across reboots:**\n\n```bash\n# Create a systemd service\nsudo tee /etc/systemd/system/wifi-powersave-off.service > /dev/null << 'EOF'\n[Unit]\nDescription=Disable WiFi power save\nAfter=network.target\n\n[Service]\nType=oneshot\nExecStart=/usr/sbin/iw dev YOUR_INTERFACE set power_save off\n\n[Install]\nWantedBy=multi-user.target\nEOF\n\n# Enable and start the service\nsudo systemctl enable wifi-powersave-off.service\nsudo systemctl start wifi-powersave-off.service\n```\n\nReplace `YOUR_INTERFACE` with your actual WiFi interface name from `ip link show`.\n\n**Alternative: NetworkManager configuration**\n\n```bash\nsudo tee /etc/NetworkManager/conf.d/wifi-powersave.conf > /dev/null << 'EOF'\n[connection]\nwifi.powersave = 2\nEOF\n\nsudo systemctl restart NetworkManager\n```\n\n**Note:** If possible, use Ethernet instead of WiFi for your server. Ethernet is more reliable, has lower latency, and doesn't have power management issues.\n\n## Step 5: Port Forwarding vs. Cloudflare Tunnel\n\nThis is the moment where most beginner guides gloss over an important decision: You have a server running on your home network, but how does the outside world reach it? There are two main approaches:\n\n### Option A: Port Forwarding\n\nYour home router sits between the internet and your devices. By default, it blocks all incoming connections from the outside. Port forwarding punches a specific hole in that wall: \"if someone requests port 80 (HTTP) or 443 (HTTPS), send them to this machine.\"\n\nYou configure this in your router's admin interface (usually at `192.168.1.1` or `192.168.0.1`). The process varies by router, but you're looking for \"Port Forwarding\" or \"Virtual Servers\" in the settings.\n\n**Pros:**\n- No third party involved\n- Fully direct connection, lowest latency\n- No dependency on Cloudflare's uptime\n\n**Cons:**\n- Your home IP address is publicly visible\n- If your ISP gives you a dynamic IP (which most residential ISPs do), your address changes periodically — you need a Dynamic DNS (DDNS) service like [DuckDNS](https://www.duckdns.org/) to keep a stable domain pointing at it\n- Some ISPs block incoming connections on port 80/443 on residential plans\n- You are directly exposing your home network to the internet — if your server has a vulnerability, it's reachable\n\n### Option B: Cloudflare Tunnel\n\nNow, [I've criticised Cloudflare in the past](https://brennan.day/the-internets-landlord-problem/), and the problems with their leadership is something to keep in mind.\n\nWith that said, [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/) (formerly Argo Tunnel) works differently from port forwarding. Instead of opening your router, a small daemon called `cloudflared` runs on your server and *reaches out* to Cloudflare's network, establishing a persistent encrypted connection. Cloudflare then proxies requests through that tunnel to your server.\n\nYour home IP is never exposed. You don't touch your router. It works even if your ISP blocks port 80/443. It works behind CGNAT (the thing some ISPs do where multiple households share a single IP address, making traditional port forwarding impossible).\n\n**Pros:**\n- No router configuration\n- Home IP stays private\n- Works with CGNAT and restrictive ISPs\n- Free tier is generous for personal use\n- SSL certificates are handled automatically\n\n**Cons:**\n- Cloudflare sits between you and your visitors (they see your traffic)\n- Dependency on Cloudflare's infrastructure\n- Against Cloudflare's ToS to serve large media files through a tunnel\n\n**My recommendation for beginners: start with Cloudflare Tunnel.** It's more forgiving, requires less networking knowledge, and you can always switch to port forwarding later. The privacy tradeoff is there, but for a personal homelab, I think it's reasonable.\n\nHere's how you set up Cloudflare tunnel:\n\n1. Create a free account at [cloudflare.com](https://www.cloudflare.com/) and add your domain\n2. Install `cloudflared`:\n```bash\n# Add Cloudflare's apt repo\ncurl -L --output cloudflared.deb https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb\nsudo dpkg -i cloudflared.deb\n```\n3. Authenticate and create a tunnel:\n```bash\ncloudflared tunnel login\ncloudflared tunnel create my-homelab\n```\n4. Configure your tunnel in `~/.cloudflared/config.yml`:\n```yaml\ntunnel: YOUR-TUNNEL-ID\ncredentials-file: /home/youruser/.cloudflared/YOUR-TUNNEL-ID.json\n\ningress:\n  - hostname: files.yourdomain.com\n    service: http://localhost:8080\n  - hostname: blog.yourdomain.com\n    service: http://localhost:2368\n  - service: http_status:404\n```\n5. Route DNS and start the tunnel:\n```bash\ncloudflared tunnel route dns my-homelab files.yourdomain.com\nsudo cloudflared service install\nsudo systemctl start cloudflared\n```\n\n## Step 6: Docker and Caddy\n\n[Docker](https://www.docker.com/) is what makes running a dozen services on one machine practical. Instead of installing each piece of software directly on your OS (where they'd fight over dependencies and configurations), Docker packages each service in its own isolated container. Each container has everything it needs. They run side by side without interfering with each other. When you want to remove a service, you remove the container. The host machine stays clean.\n\nInstall Docker:\n```bash\ncurl -fsSL https://get.docker.com -o get-docker.sh\nsudo sh get-docker.sh\nsudo usermod -aG docker $USER\n```\n\nLog out and back in. Now you can run Docker commands without `sudo`.\n\n[Caddy](https://caddyserver.com/) is a web server and reverse proxy. A reverse proxy sits in front of all your services and routes incoming requests to the right container. When someone visits `files.brennan.cafe`, Caddy looks at the domain name and forwards the request to whatever container is serving FileBrowser on port 8080.\n\nCaddy's killer feature is automatic HTTPS: it provisions and renews SSL certificates from Let's Encrypt automatically, with zero configuration. You don't think about it. It just works.\n\nA `Caddyfile` looks like this:\n\n```\nfiles.yourdomain.com {\n    reverse_proxy localhost:8080\n}\n\nwiki.yourdomain.com {\n    reverse_proxy localhost:8090\n}\n```\n\nInstall Caddy:\n```bash\nsudo apt install -y debian-keyring debian-archive-keyring apt-transport-https\ncurl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg\ncurl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list\nsudo apt update\nsudo apt install caddy\n```\n\nEdit `/etc/caddy/Caddyfile` with your subdomains and service ports, then:\n\n```bash\nsudo systemctl reload caddy\n```\n\n## Step 7: Setting Up Monitoring\n\nBefore you deploy a bunch of services, set up monitoring so you can actually see what's happening on your server. You can't manage what you can't measure. This is also a great way to understand how Docker works.\n\n**Beszel**: Internal server monitoring (CPU, RAM, disk, network, per-container stats)\n\nInstall Beszel with Docker:\n```bash\ndocker run -d \\\n  --name beszel \\\n  --restart unless-stopped \\\n  -p 3000:3000 \\\n  -v /beszel_data:/beszel_data \\\n  henrygd/beszel:latest # This is the entire service!\n```\n\nAccess the dashboard at `http://your-server-ip:3000` and follow the setup wizard to add your server as an agent.\n\n**Uptime Kuma**: External uptime monitoring (checks if services are up from the outside)\n\nInstall Uptime Kuma with Docker:\n```bash\ndocker run -d \\\n  --name uptime-kuma \\\n  --restart unless-stopped \\\n  -p 3001:3001 \\\n  -v uptime-kuma:/app/data \\\n  louislam/uptime-kuma:1\n```\n\nAccess at `http://your-server-ip:3001` and add monitors for your services.\n\n**Dozzle**: Real-time Docker log viewer\n\nInstall Dozzle with Docker:\n```bash\ndocker run -d \\\n  --name dozzle \\\n  --restart unless-stopped \\\n  -p 8080:8080 \\\n  -v /var/run/docker.sock:/var/run/docker.sock \\\n  amir20/dozzle:latest\n```\n\nAccess at `http://your-server-ip:8080` to view logs from all your containers in real-time.\n\n## Step 8: Setting Up Backups\n\nBefore you add more services, set up a backup strategy. Duplicati is a solid choice, as it supports multiple destinations (Backblaze B2, S3, SFTP, Google Drive, OneDrive) and handles encryption, scheduling, and deduplication automatically.\n\nInstall Duplicati with Docker:\n```bash\ndocker run -d \\\n  --name duplicati \\\n  --restart unless-stopped \\\n  -p 8200:8200 \\\n  -v duplicati_config:/data \\\n  -v /home/brennan:/source \\\n  duplicati/duplicati:latest\n```\n\nAccess at `http://your-server-ip:8200` and configure:\n1. Add a backup destination (Backblaze B2 is affordable and reliable)\n2. Select the directories to back up (`/home/brennan/cafe`, `/data/coolify`, Docker volumes)\n3. Set a schedule (daily at 3 AM is reasonable)\n4. Enable encryption with a strong passphrase\n\n> **Important:** Test your backup by performing a restore. A backup you can't restore is not a backup.\n\n## Step 9: Deploying Services with Coolify\n\n[Coolify](https://coolify.io/) is, as the name implies, really cool. It's a self-hosted alternative to Heroku, Netlify, or Vercel. A web dashboard where you connect a git repository, configure environment variables, and click Deploy. It handles the Docker build, the container orchestration, the reverse proxy config, and the SSL certificate.\n\nFor beginners who don't yet want to write `docker-compose.yml` files by hand, Coolify is a great on-ramp. It comes with one-click installers for Nextcloud, Ghost, WordPress, n8n, Gitea, Plausible Analytics, and dozens of other services.\n\nInstall Coolify with one command:\n```bash\ncurl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash\n```\n\nThen access the dashboard at `http://your-server-ip:8000` and follow the setup wizard. You'll configure your domain, set up SSH key access to the server (Coolify uses this to manage containers), and you're off.\n\n**A note on resource use:** Coolify itself is more resource-intensive than running containers manually, I've found it uses 300–500 MB of RAM at rest. On an 8 GB machine, that's fine. On a 4 GB machine, you might prefer managing Docker Compose files directly.\n\n### Deployment Order\n\nIf you're following this guide from start to finish, here's a recommended order for deploying services. This builds incrementally and gives you useful tools early:\n\n1. **Dozzle**: Fastest to deploy, immediately useful for debugging\n2. **Beszel + Agent**: Get visibility into your server ASAP\n3. **Uptime Kuma**: Monitor all your existing services\n4. **Duplicati**: Set up backups before you add more services\n5. **Vaultwarden**: Move passwords off commercial providers\n6. **Coolify**: Set up your deployment platform\n7. **FreshRSS or Miniflux**: Needs PostgreSQL if using Miniflux\n8. **Linkding**: Quick single-container deploy\n9. **Shlink**: Quick single-container deploy\n10. **Pi-hole**: Requires network-level DNS config change on your router\n\n## Step 10: Good Ol' Fashion Blogging\n\n[Hugo](https://gohugo.io/) is a fantastic option for a homelab blog. Generates a static site from plain Markdown files. There's no database, no PHP, no runtime. Just a folder of `.md` files turned into folder of `.html` files.\n\nI specifically created the bash tool [`writer-cli`](https://writer.brennan.day) for this use-case! I also created the Hugo blog theme [IndiePaper](https://github.com/brennanbrown/indiepaper) for people that want a template that has full IndieWeb functionality built-in. The workflow is:\n\n1. Write a post in Markdown with my `writer-cli` script\n2. Hugo rebuilds the site (takes about 200ms for a large site)\n3. Caddy serves the static output\n\nTo run Hugo in Docker:\n\n```dockerfile\nFROM klakegg/hugo:ext-alpine AS builder\nCOPY . /src\nWORKDIR /src\nRUN hugo --minify\n\nFROM caddy:alpine\nCOPY --from=builder /src/public /usr/share/caddy\n```\n\nOr just install Hugo directly:\n```bash\n# Download the latest release\nwget https://github.com/gohugoio/hugo/releases/download/v0.128.0/hugo_extended_0.128.0_linux-amd64.deb\nsudo dpkg -i hugo_extended_0.128.0_linux-amd64.deb\n```\n\nAnd serve the site:\n```bash\nhugo server --bind 0.0.0.0 --baseURL https://blog.yourdomain.com\n```\n\n## Step 11: The Wiki (Document As You Go)\n\nA great project to have on your homelab is a wiki for the homelab itself. The more you work on it, the more you'll learn. It's a virtuous cycle! Document everything and keep notes as you go.\n\n[DokuWiki](https://www.dokuwiki.org/) is my choice because it's flat-file (no database), and the search works great. But [Wiki.js](https://js.wiki/), or even a plain [Obsidian](https://obsidian.md/) vault synced to your server would work fine.\n\nWhat goes in the wiki:\n\n- Every command you run that you had to look up\n- Every config file you edited and what you changed\n- Every error you encountered and how you fixed it\n- Port assignments for all your services (so you don't accidentally give two things the same port)\n- Your Docker Compose files, in full\n- Notes on what broke and why\n\nSix months from now, when something stops working and you can't remember how you set it up, you'll thank yourself.\n\n## Step 12: Security Beyond SSH\n\nSSH hardening is a good start, but there are a few more security basics worth implementing.\n\n**UFW (Uncomplicated Firewall)**: A simple firewall management tool\n\n```bash\nsudo apt install ufw\nsudo ufw default deny incoming\nsudo ufw default allow outgoing\nsudo ufw allow ssh\nsudo ufw allow 80/tcp\nsudo ufw allow 443/tcp\nsudo ufw enable\n```\n\nThis blocks all incoming traffic except SSH, HTTP, and HTTPS — which is all you need for a web server.\n\n**Fail2ban**: Ban brute-force attackers\n\n```bash\nsudo apt install fail2ban\nsudo systemctl enable fail2ban\nsudo systemctl start fail2ban\n```\n\nFail2ban monitors log files and bans IPs that show malicious signs (too many failed SSH login attempts, etc.).\n\n**Automatic Security Updates**\n\n```bash\nsudo apt install unattended-upgrades\nsudo dpkg-reconfigure -plow unattended-upgrades\n```\n\nThis will automatically install security updates on your system, reducing the window of vulnerability.\n\n## Appendix: Power Consumption and Cost\n\nRunning a server 24/7 has an ongoing cost in electricity. The AMD FX-4130 in my own tower has a 125W TDP (Thermal Design Power). In practice, at idle with light services running, it draws about 40–60 watts from the wall. Under load, it might spike to 80–100 watts.\n\n**Monthly cost calculation:**\n- Average draw: 50 watts\n- Hours per day: 24\n- Days per month: 30\n- Total kWh: 50W × 24h × 30d ÷ 1000 = 36 kWh\n- Cost at $0.12/kWh: 36 × $0.12 = $4.32/month\n\nSo you're looking at roughly $4–$6 per month in electricity costs for a machine like this. That's not nothing, but it's significantly less than the monthly cost of cloud services.\n\nIf you're concerned about power use, consider:\n- Using a more efficient CPU (Intel NUC, Raspberry Pi, or modern low-power desktop)\n- Aggressively power-managing the machine (CPU frequency scaling, aggressive sleep settings on unused services)\n- Running the server on a schedule (only on when you need it)\n\n## A Final Note\n\nWow, that was a lot of steps! Let me tell you, like anything related to programming, you will have bugs. You will have errors. You will be searching and trying to find solutions, and sometimes things will stay broken for a long time.\n\nBecause I've primarily been a front-end webdev for over a decade, I've always run into trouble with devOps. But I just kept returning, I kept figuring out better practices. Better fundamentals. And now my homelab has [better uptimes than GitHub](https://mrshu.github.io/github-statuses/):\n\n<figure>\n<img src=\"/assets/images/blog/server-status.jpg\" alt=\"An Uptime Kuma monitoring dashboard on a dark background listing eleven services with their uptime percentages and green bar history indicators: Archive (99.31%), Backup (99.38%), Blog (100%), Café (99.65%), Deploy (97.57%), Files (99.44%), Logs (99.65%), Monitor (99.72%), RSS (99.74%), Social (99.84%), and Wiki (99.79%). All bars are fully green, indicating no recent downtime.\" style=\"max-width: 600px; width: 100%;\">\n<figcaption>The uptime statuses of all the services running on <a href=\"https://brennan.cafe\">brennan.cafe</a>, at <a href=\"https://status.brennan.cafe\">status.brennan.cafe</a> using <a href=\"https://uptimekuma.org/\">Uptime Kuma</a></figcaption>\n</figure>\n\nThis isn't about the easiest, fastest solution. This isn't about splurging on powerful hardware to replace your entire digital life. Start where you are. Use what you have. Do what you can. \n\nThis is about envisioning a web that's affordable, accessible, and focused on *learning*. My God, how are we supposed to learn anything if everything works the first time or we offload troubleshooting to someone else? (or worse, an error-prone genAI bot?)\n\nHomelabbing is a reclamation project. To reclaim the *understanding* of what the Internet is, and how we can create and build it ourselves. \n",
      "date_published": "2026-05-28T20:00:00.000Z",
      "tags": [
        "Self-hosting",
        "technical",
        "homelab",
        "IndieWeb",
        "Linux",
        "Docker"
      ],
      "author": {
        "name": "Brennan Kenneth Brown",
        "url": "https://brennanbrown.ca",
        "email": "mail@brennanbrown.ca"
      }
    },
    {
      "id": "https://brennan.day/gemini-gophers-and-fingers-oh-my-alternative-internets-beyond-https/",
      "url": "https://brennan.day/gemini-gophers-and-fingers-oh-my-alternative-internets-beyond-https/",
      "title": "Gemini, Gophers, and Fingers. Oh My! Alternative Internets Beyond HTTPS",
      "summary": "Finger from 1971, Gopher from 1991, and Gemini from 2019. These protocols offer decentralized, terminal-based alternatives to the modern web. The small web's is in a renaissance. On the solarpunk philosophy of intentional technology, and how these protocols meet you where you are, whether you're on a machine from 2005 or just tired of Chrome's monoculture.",
      "content_html": "\nIn my last post, [I announced that I created a bash tool](https://brennan.day/introducing-writer-cli-a-bash-tool-i-built-from-scratch-to-blog-in-the-terminal/) for easier blogging in the terminal, inspired by [the tildeverse](https://tildeverse.org/). Today, I want to continue my discussion on visions of alternative Internets that are already being created. \n\nI want to talk about Uniform Resource Identifier (URI) schemes.\n\nSounds boring, right? Or at least complicated, but it really isn't. URIs are just the protocols set for browsing the Internet. There are many, some official (as per the Internet Assigned Numbers Authority) and some unofficial.\n\nOne of the biggest draws of the IndieWeb for me is the decentralization of the Internet. The entire point is to stop the erosion of the Internet from being a handful of bad-faith, extractive corporate social media platforms.\n\nBut at the end of the day, we're still *all* using the same Internet, aren't we? The same handful of browsers, the same frameworks and engines. We can take this a step further, and we can interface with the Internet in ways that don't involve going to websites that start with `https://`\n\n## The Colour of What We Call the Internet\n\n[Chrome alone controls roughly 73% of global desktop browser market share](https://undetectable.io/blog/chromium-based-browsers/). If you add in Edge, Brave, Opera, Vivaldi, which all are built on Google's Chromium engine, that accounts for [over 80% of desktop browsing worldwide](https://undetectable.io/blog/chromium-based-browsers/). Mozilla, which still maintains one of the only independent rendering engines (Gecko), is the only viable competitor. Everything else is Blink and Google.\n\nMore and more, the webdevs of the world test and develop for Chrome only. Agriculture teaches us how dangerous and fragile monocultures like this are.\n\nIt doesn't need to be this way. `https://` is not the only way to connect and interface with the Internet. Some that you may know are `ftp://` for file transfers, `mailto:` for email composition, `ssh://` for secure shell access, `irc://` for Internet Relay Chat, or `magnet:` for peer-to-peer downloads.  The majority of Internet browsers do not play nicely even with these protocols, handing them off to other applications.\n\nBut what I want to write about today are three protocols that have their own ecosystems, their own communities, and their own aesthetics. `finger://`, `gopher://`, and `gemini://`. Two predate the World Wide Web entirely, but one was created in 2019, the same year the first black hole photograph circled the planet. None of them require a GUI. None of them require JavaScript. All three of them run in a terminal. \n\n## Finger (1971)\n\nLet me start with the deep past, when the ARPANET was less than two years old. In 1971, users wanted to know who else was logged into their small networks, and where they were. The existing tool, called `WHO`, gave a list of user IDs and terminal line numbers which was cryptic, technical, readable only if you already knew what you were looking at. Researcher Les Earnest at the Stanford Artificial Intelligence Laboratory watched people literally run their fingers down the WHO printout, scanning for recognizable names. [He named his new program after that gesture](https://handwiki.org/wiki/Finger_protocol).\n\nThe finger daemon runs on TCP port 79, serving a small, human-readable file about you. Your name. Your email. Whether you're logged in. And the contents of two files: `.plan` and `.project`.\n\n[The `.plan` file was originally meant to contain a user's current and future plans](https://gunkies.org/wiki/Finger), a professional status update before status updates existed. But as the informal culture of the early Internet evolved, `.plan` files became random musings, personal manifestos, and links to things you were thinking about. A broadcast of who you were to anyone who cared to ask. In ways, it was the first social media profile.\n\nI have a `.plan` file in my tilde home directory right now. I'm not going to tell you what it says, for the point is you have to go looking. `finger brennan@omg.lol` and you'll find out what I'm working on right now. And yes, of course the verb \"to finger someone,\" is designed to make you snicker.\n\nIt's opt-in, low-infrastructure presence. A plain text file and a TCP connection.\n\n[Bombadillo](https://bombadillo.colorfield.space/), the terminal-based non-web browser I'll mention more below, supports Finger natively alongside Gopher and Gemini. You can run your own finger server on any Linux machine. The protocol is so simple it fits in your head.\n\n## Gopher (1991)\n\nNow let's move forward twenty years, to another problem at another university.\n\nIn 1991, the University of Minnesota wanted a campus-wide information system. The project became, as these things do, [a design-by-committee monstrosity](https://mncomputinghistory.com/gopher-protocol/). A group of programmers, Mark McCahill, Farhad Anklesaria, Paul Lindner, Daniel Torrey, and Bob Alberti, decided to go around the committee entirely and built something themselves on personal computers rather than a mainframe, and see if they could have a working prototype done before the next meeting. [They released the code without official approval](https://mncomputinghistory.com/gopher-protocol/). The committee initially rejected it, and then the rest of the Internet found it.\n\n[Paul Lindner, dubbed the Gopher Dude for his evangelism, long metal-head hair and all—signed his emails with Babes in Toyland lyrics](https://www.minnpost.com/business/2016/08/rise-and-fall-gopher-protocol/). Programmer Robert Alberti later recalled that \"[Gopher] was the first viral software. All these people started calling the University and pestering the president and other administrators, saying, 'This Gopher thing is great, when are you going to release a new version?' And the administrators said, 'What are you talking about?'\" The administration unsurprisingly reversed their decision and gave the project their blessing shortly after.\n\nThe name is a triple pun. [The University of Minnesota's mascot is the Golden Gopher; \"gopher\" evokes the act of burrowing; and it's a play on \"go-fer,\" an errand-runner who fetches things on request](https://hackaday.com/2021/09/28/gopher-the-competing-standard-to-www-in-the-90s-is-still-worth-checking-out/). The protocol is a hierarchical menu system, you navigate a tree of directories and documents. It's faster and more simple than FTP. For a moment in 1991 and 1992, [Gopher and the World Wide Web competed as genuine equals](https://thehistoryoftheweb.com/what-the-web-could-have-been/). Two totally different visions of how to organize human knowledge on a global network.\n\nGopher lost. [In 1993, the University of Minnesota announced it would start charging a licensing fee to commercial users](https://www.howwegettonext.com/gone-gone-gopher-the-other-world-wide-web-that-almost-was/). Tim Berners-Lee had declared HTTP and HTML completely free and open, with no licensing attached, ever. [The press started describing Gopher as an obsolete predecessor rather than a living alternative](https://www.ils.unc.edu/callee/gopherpaper.htm). Within a couple of years, the race was over because of one institutional decision about money.\n\nBut, Gopher isn't actually dead. It got turned into a newt, but then got better! Here are the stats over the past twenty years, as per [Veronica2 Gopher search index](https://gopherproxy.meulie.net/gopher.floodgap.com/1/v2):\n\n| Index Date | Gopher Servers | Unique Selectors |\n|---|---|---|\n| 19 March 2007 | 86 | 740,000 |\n| 3 January 2008 | 148 | 1,220,665 |\n| 2012 | approx. 160 | approx. 2,500,000 |\n| November 2014 | 144 | approx. 3,000,000 |\n| 15 October 2015 | 144 | 3,314,158 |\n| 25 April 2016 | 137 | 4,396,061 |\n| 15 August 2017 | 146 | 5,176,602 |\n| May 2018 | 260 | approx. 3,700,000 |\n| 10 December 2018 | 297 | 3,946,750 |\n| May 2019 | 320 | approx. 4,200,000 |\n| January 2020 | 395 | approx. 4,500,000 |\n| 18 November 2020 | 358 | 5,973,552 |\n| 18 October 2021 | 343 | 5,294,599 |\n| 11 October 2022 | 333 | 5,098,733 |\n| 17 February 2024 | 323 | 5,113,957 |\n| 19 June 2025 | 296 | 5,113,382 |\n| 29 August 2025 | 432 | 5,254,158 |\n| 28 January 2026 | 411 | 5,856,111 |\n\nIn January 2026, there were 411 active Gopher servers serving nearly six million unique selectors. Gopher is maintained by people who choose it, not being propped up by corporate interest backing whatsoever. \n\nI maintain my own gopherhole manually with a shell script, `gopher-build.sh`, that lives in my `bin/` directory. Navigating it in a terminal feels like handling a card catalogue.\n\n## Gemini (2019)\n\n[Project Gemini was started in June 2019](https://geminiprotocol.net/) by a pseudonymous developer known as Solderpunk. The name is a [reference to NASA's Project Gemini, the human spaceflight program conducted between 1964 and 1966](https://www.nicfab.eu/en/posts/gemini-protocol/), and the protocol runs on port 1965 to honour that. \n\nIt has nothing to do with Google's AI, or the cryptocurrency exchange. It's named after part of the space program between Mercury and Apollo, the middle step, the bridge. What made the moon landing possible.\n\n[Solderpunk designed Gemini as a direct response to watching more and more people rediscover Gopher](https://techrights.org/n/2025/10/07/How_Solderpunk_and_Sean_Conner_Started_Gemini_Protocol_and_Coll.shtml), finding a refuge from what the web had become. But Gopher, with its age, has a significant problem: no encryption. Particularly after [Edward Snowden's 2013 revelations about mass surveillance](https://blog.cryptographyengineering.com/2019/09/24/looking-back-at-the-snowden-revelations/), running an unencrypted protocol started to feel more and more like bad practice. [Gemini's answer is to make TLS encryption mandatory](https://www.glukhov.org/post/2025/10/gemini-protocol/) for all Gemini capsules.\n\n[The Gemini specification fits in a few pages](https://dev.to/rosgluk/gemini-protocol-a-minimalist-alternative-to-the-web-mb5). Requests are a single URL terminated by a line break. Responses include a two-digit status code, a content type, and the data. That's it. There are [no cookies, no tracking pixels, no third-party resources, no behavioral analytics](https://grokipedia.com/page/Gemini_(protocol)). A Gemini capsule cannot phone home and surveil you. There's no JavaScript or cookies or tracking pixels or 3rd-party resources or any other bullshit.\n\n[Gemtext](https://geminiprotocol.net/docs/gemtext-specification.gmi), Gemini's native document format, is line-oriented. The first three characters of a line determine its type: a heading, a link, a list item, a quote, a preformatted block, or body text. There's no nesting, inline formatting or images.\n\nYou can't use bold for emphasis or italicize a word for tone. Writing is stripped down to its skeleton, and I think that forces you to be a better writer.\n\nI've been using Gemini for a while through [Smol Pub](https://smol.pub), a brutally simple blogging platform which publishes your posts at both `https://` and `gemini://` simultaneously. For only $5, you have a lifetime license to the platform, which I think is an amazing deal! The math of the small web is different from the math of the attention economy.\n\nBecause I work primarily in Markdown, I built a [Markdown to Gemtext converter](https://gemtext.brennan.day), which is a great way to get started. You can read my write-up about the project [on my smol pub](https://brennan.smol.pub/markdown2gemtext).\n\n## Blogging? More Like Gemlogs and Phlogs!\n\nAs I wrote about in my previous post, `ttbp`, [the tilde.town blogging platform, nicknamed FEELS](https://git.tilde.town/endorphant/ttbp) is one of my favourite ways to blog. You run it in the terminal, opening your text editor of choice to a plain text file. You write, then save and quit. The entry propagates automatically to a global feels list, and publishes to both HTML and Gopher simultaneously. \n\nI have a `public_gopher/feels` directory right now that's synced to my gopherhole. I think the naming is important, as this isn't content or articles, they're called *feels*. It's people writing mundane journal entries, poetry, and reflections. Emotional and human. Electric intimacy of strangers sharing inner lives with anyone patient enough to look.\n\nA *phlog* (a portmanteau of \"Gopher\" and \"blog\") is a blog maintained in Gopherspace, updated via a gophermap. A *gemlog* is the same thing for Gemini. My `gemlogs/` directory has its own feed and indexor.\n\nGemlogs follow the Gemini subscription convention, which means it's designed to be subscribable without needing RSS or Atom. Each entry is formatted as:\n\n```gemini\n=> /posts/YYYY-MM-DD-title.gmi YYYY-MM-DD Post title\n```\n\nThe date format (YYYY-MM-DD) at the start of the link label allows Gemini clients to automatically detect and subscribe to new posts. The simple, human-readable format works great for this kind of small-scale personal publishing. \n\n## A Gift to Old Hardware\n\nSomething important about these protocols that I think is underlooked is that, due to their simplicity, all you need is the terminal to access and create on them, no GUI needed at all. This vastly lowers the hardware requirements compared to the mainstream Internet browser.\n\nLoading a modern website built with React (or any of its cousins) requires your browser to download a JavaScript bundle, parse it, execute it, render a virtual DOM, reconcile that DOM with the real one, and then do it all again whenever state changes. \n\nA modern Chromium-based browser uses ~2 GB of RAM in normal operation. NASA's Gemini Guidance Computer had 20kb. The machines required to run these browsers have only been getting more expensive and more energy-intensive to manufacture every year.\n\nOn the other hand, a Gemini capsule in [Bombadillo](https://bombadillo.colorfield.space/) requires a terminal emulator, a network connection, and a TLS library. The entire browser is a few megabytes. This will run on a machine from 2005. \n\nThis is important for the mountain of electronics we have landfilled. A laptop from 2008 no longer able to run Chrome can run Bombadillo, accessing the six million documents in Gopherspace and browsing thousands of Gemini capsules. \n\nThese protocols can run on virtually anything, they meet you where you are.\n\nWho gets to participate in an Internet that requires an increasingly expensive, frequently-replaced device to use in any meaningful way? You still need a network connection and terminal, sure, but the hardware threshold drops dramatically.\n\n## The Small Web and Solarpunk\n\nSolderpunk's pseudonym instantly reminded me of [Solarpunk](https://aeon.co/essays/in-solarpunk-cities-of-the-future-tech-follows-natures-lead), a speculative fiction genre and a real-world political and aesthetic movement. Cyberpunk imagines a future of neon-soaked corporate dystopia and steampunk looks backward to industrial romanticism, but solarpunk imagines forward—toward decentralized communities, renewable energy, mutual aid, technology that serves life rather than exploiting. [The symbol is a half-gear for technology compatible with nature, and a sun for the infinite potential of the open imagination](https://aeon.co/essays/in-solarpunk-cities-of-the-future-tech-follows-natures-lead). The movement began in sci-fi and migrated into architecture, gardening, political organizing, and Internet culture.\n\nSolarpunk doesn't worship technology, nor demonize it. [Rather, solarpunk asks how we can use technology to improve humanity](https://www.goodgoodgood.co/articles/solar-punk-green-architecture-futuristic-design). It's interested in [decentralized infrastructure, community engagement, and a DIY attitude](https://www.pbs.org/wnet/peril-and-promise/2018/11/what-you-can-learn-from-the-solarpunk-movement). It distrusts monocultures, suspicious of scale for scale's sake, asking: who benefits from technology, and at what expense?\n\nThis is what the small web asks. Gemini was created by someone who named themselves after the act of soldering—the work of connection with heat and metal. Bombadillo was developed by [sloum on tildegit](https://tildegit.org/sloum/bombadillo/), a fellow tildeverse resident. The tildeverse itself runs on the philosophy that public-access Unix servers are a commons you can have a home on the Internet without paying a corporation. Without surrendering your data or being the product.\n\nI have a `.botany/` directory on tilde.town, [a terminal plant-growing game](https://github.com/jifunks/botany). A small, shared, pixelated garden where tilde.town residents tend to ASCII plants, growing when you're logged in and paying attention. \n\nIt's stuff like that, you know?\n\nThe alternative Internet is not separate from the struggle for a better world. We learn to build intentionally, creating for people. Not for social currency or scale or profit. For care. There's no way to have a pipeline for data harvesting or intrusive advertising on these alternative protocols.\n\nThe only way any of these projects continue being maintained and grow is by us using them and contributing to their developers. I believe that now more than ever we need to be imaginative and play with the Internet. There are so many different ways to use our connection to the entire world we haven't even thought about yet.\n\n**Want to get started?** For a catalog of Gemini clients, servers, and tools across every programming language, the [awesome-gemini list on GitHub](https://github.com/kr1sp1n/awesome-gemini) is great.\n\nFor accessing these protocols, [Bombadillo](https://bombadillo.colorfield.space/) is a versatile terminal option, handling Gopher, Gemini, and Finger in a single interface with Vim-style keybindings. \n\n[Offpunk](https://offpunk.net) is another excellent, offline-first command-line browser worth knowing about. It handles the Web, Gemini, Gopher, and RSS feeds all from your terminal, with a focus on working offline and syncing content for later reading. Thanks to [Candy](https://candyether.space/) for the tip on that one! \n\nFor a GUI browser, [Lagrange](https://github.com/skyjake/lagrange) is my personal favourite. \n\nIf you want to browse Gemini from a web browser first, proxies at [portal.mozz.us](https://portal.mozz.us) and [proxy.vulpes.one](https://proxy.vulpes.one) will translate Gemini capsules into HTTP. My own [Markdown to Gemtext converter](https://gemtext.brennan.day) is free to use if you want to bring existing writing into Geminispace easily.\n",
      "date_published": "2026-05-26T18:00:00.000Z",
      "tags": [
        "Indieweb",
        "Small Web",
        "technical",
        "Digital Culture",
        "history",
        "decentralization"
      ],
      "author": {
        "name": "Brennan Kenneth Brown",
        "url": "https://brennanbrown.ca",
        "email": "mail@brennanbrown.ca"
      }
    },
    {
      "id": "https://brennan.day/introducing-writer-cli-a-bash-tool-i-built-from-scratch-to-blog-in-the-terminal/",
      "url": "https://brennan.day/introducing-writer-cli-a-bash-tool-i-built-from-scratch-to-blog-in-the-terminal/",
      "title": "Introducing writer-cli: a bash tool I built from scratch to blog in the terminal!",
      "summary": "After finding the tildeverse and the Tilde.town feels engine, I decided to build my own simple command-line tool for blogging that handles the full lifecycle of a blog post (creation, editing, building, and git push). A walkthrough of the design decisions, the modular architecture, and the tradeoffs of writing 700 lines of plain bash.",
      "content_html": "\nWhen I first began exploring the IndieWeb several months ago, I stumbled upon the [tildeverse](https://tildeverse.org/), which describes itself as \"a loose association of like-minded tilde communities\" for those \"interested in learning about *nix (linux, unix, bsd, etc)*.\"\n\nIt's important I tell you about these communities, because [Wikipedia deleted the article on it](https://en.wikipedia.org/wiki/Tildeverse), justifying the decision by saying there was \"no coverage available in reliable sources, provided sources are non-independent\".\n\nA \"tilde community\" is, essentially, a shared, public-access computer. And you know how much [I love public access](https://brennan.day/announcing-my-new-radio-show-a-love-letter-to-public-access-television/), right? The name comes from the Unix shorthand symbol (~), denoting a user's home directory (e.g., server.org/~username), because these communities exist on Unix/Linux servers (often called a \"pubnix\") run with love by hobbyists.\n\n## The Heartbreak of Copy Fail\n\nSadly, right now, many tilde communities are shut down due to the [CopyFail](https://xint.io/blog/copy-fail-linux-distributions) and [Dirty Frag](https://www.microsoft.com/en-us/security/blog/2026/05/08/active-attack-dirty-frag-linux-vulnerability-expands-post-compromise-risk/) vulnerabilities.\n\nCopy Fail is a local privilege escalation flaw in the Linux kernel's `algif_aead` cryptographic module. It chains the AF_ALG crypto API socket interface with the `splice()`` system call to perform a 4-byte write to the page cache, allowing an unprivileged local user to escalate their privileges to full root access.\n\nThe exploit requires only local authenticated access, and that access can come from compromised SSH credentials, an exposed service, or a malicious container image.\n\nTilde servers are explicitly multi-user SSH environments where untrusted strangers have shell accounts. That's the whole model, and so Copy Fail turns any local user account into a path to root, which means a tilde admin's only real option is to take the server offline right now.\n\nSo, regrettably, my essay on the tildeverse is put on hold until these vulnerabilities can be properly patched and the communities return.\n\n## The Feels Engine\n\nBut in the meantime, I made my own terminal-based tool for writing. You see, one of my favourite programs of the tildeverse is the [TTBP](https://github.com/modgethanc/ttbp), short for the tilde.town feels engine. It is [a blogging tool](https://tilde.club/wiki/ttbp.html) that allows you to easily write an entry, publish it to the web, and browse other entries by other users of the tilde community.\n\nI thought about the steps required to make a blog post on my own server: You need to SSH into the server, navigate to the right folder, manually create a file with the right frontmatter (YAML or TOML), remember the exact date format your SSG wants, open an editor, write, save, run the build, check for errors. Then, if you use git, you need to run `git add`, `git commit` (with proper message hygiene), `git push`.\n\nSo I built [`writer-cli`](https://github.com/brennanbrown/writer-cli), inspired by the feels engine. A command-line tool for bloggers who just want to open a terminal, write something, and have it live on the Internet. It's a single bash command:\n\n```bash\nwriter my-post-slug\n```\n\nThat's it, everything else is prompts and automation.\n\nThis post is a technical walkthrough of how it works, the design decisions made, and what I'd do differently.\n\nI'd like to give a shoutout to [Cris](https://mastodon.social/@crisverstraeten)! He gave me really helpful pointers and sent me the [Google Shell Style Guide](https://google.github.io/styleguide/shellguide.html), which taught me a lot and influenced a lot of the code of this project.\n\nNow, this seems like such a simple concept, right? But in wanting to do a good job, the codebase is now around 1,800 lines in total.\n\nI can't really tell you exactly why I always treat these little software projects I do as sprints. I've been wanting to make a project like this forever but I only began planning it a week ago. And then regarding the actual coding part, I've been up doing ten-hour daily coding sessions for the past three days during this self-imposed hackathon at this point.\n\n<small>Honestly? I think I'm actually lazy and I don't want to continually work on projects with maintence. :^)</small>\n\n## What `writer-cli` Does\n\nThe premise of my little tool is simple, I wanted to wrap the full lifecycle of a Hugo (or Eleventy, or Jekyll) blog post into one shell command. When you run `writer my-slug`, the following happens:\n\n1. You're asked for a title and optional tags\n2. Your editor opens with the cursor below the frontmatter, ready to write\n3. You close the editor, optionally add a one-line description\n4. You confirm, and writer builds the site and pushes to git\n\nAnd, voilà, the post is live! The tool takes care of everything else. \n\n## Why Bash?\n\nBecause bash is always there! The intended use case is a remote server over SSH. You can post from anywhere you can open a terminal: your laptop, a library computer, even your phone if you're tech-savvy enough.\n\nMy philosophy is that you should not be required to have dependencies installed just to publish a blog post, such as Python, Node, etc. But bash has been on every Linux server before I was born, and will continue to be there long after every JavaScript framework in my `node_modules` folder has been deprecated.\n\nI wanted to make a blogging tool that, itself was just a text file. There's no binaries, build steps, or compilation. You can read every line from source.\n\nOf course, there is trade-off. bash 4 had a GPL license change, and so [macOS ships with the outdated bash 3.2](https://news.ycombinator.com/item?id=38132066). This means no associative arrays, no `${var,,}` lowercase operator, no `mapfile`. \n\nObviously, having that functionality would have been nice, and I needed to find workarounds: \n\n```bash\n# What I wanted to write:\nslug=\"${input,,}\"\n\n# What I had to write instead (bash 3.2 compatible):\nslug=\"$(printf '%s' \"$input\" | tr '[:upper:]' '[:lower:]')\"\n```\n\nIt's more verbose and clunky, but it works on every machine.\n\n## Modular Architecture\n\nYou'd think a script for something like this would be tiny, but as I accounted for edge cases and different static-site generators, the single `writer.sh` script became 700 lines. \n\nIt worked, but I decided to modularize the way I did for [my site's 11ty config a week ago](https://brennan.day/cleaning-house-refactoring-my-eleventy-config-into-modules/):\n\n```\nlib/\n├── defaults.sh      ← global variables and output helpers\n├── config.sh        ← INI config file parser\n├── args.sh          ← CLI flag parsing\n├── setup.sh         ← interactive setup wizard\n├── validate.sh      ← slug validation, ISO 8601 dates\n├── frontmatter.sh   ← YAML and TOML builders\n├── deps.sh          ← dependency pre-flight checks\n└── post.sh          ← main workflow orchestration\n```\n\nThe entry point `writer.sh` is now only 30 lines, it resolves its own directory (so symlinks work), sources all eight modules in order, and calls `main \"$@\"`.\n\n```bash\n_writer_source=\"${BASH_SOURCE[0]}\"\nwhile [[ -L \"$_writer_source\" ]]; do\n    _writer_dir=\"$(cd \"$(dirname \"$_writer_source\")\" && pwd)\"\n    _writer_source=\"$(readlink \"$_writer_source\")\"\n    [[ \"$_writer_source\" != /* ]] && _writer_source=\"${_writer_dir}/${_writer_source}\"\ndone\nWRITER_DIR=\"$(cd \"$(dirname \"$_writer_source\")\" && pwd)\"\n\nsource \"${WRITER_DIR}/lib/defaults.sh\"\nsource \"${WRITER_DIR}/lib/config.sh\"\n# ... and so on\nmain \"$@\"\n```\n\nUsing `${BASH_SOURCE[0]}` rather than `$0` is important, `$0` can be rewritten by the shell, while `${BASH_SOURCE[0]}` always points to the file being sourced or executed. The `while` loop then follows any chain of symlinks to the real file, handling the case where BSD `readlink` returns relative paths (unlike GNU `readlink -f`).\n\nAll modules are sourced into the same shell, not run as subshells. This means they share global state without needing `export` everywhere. It also means each lib file has no shebang and doesn't set its own `set -e` and instead inherits the caller's environment.\n\n## Config Layering\n\nOne thing I wanted from the start was a sane configuration system. Writer has ten configurable settings: your SSG, build command, content directory, editor, timezone, etc. and I wanted them to be overridable at multiple levels without confusion.\n\nThe loading order is:\n\n1. Hardcoded defaults (in `lib/defaults.sh`)\n2. Global config (`~/.config/writer/config`)\n3. `cd` to `SITE_DIR` if set\n4. Project-local `.writerrc`\n5. CLI flags — highest priority\n\n```bash\nload_global_config        # reads ~/.config/writer/config\nif [[ -n \"$SITE_DIR\" ]]; then\n    cd \"$SITE_DIR\"\nfi\nload_local_config         # reads .writerrc in current directory\n# then CLI flag overrides are applied\n```\n\nThe config format is plain INI. `KEY=value`, one per line, `#` for comments. I wrote a small parser for it to continue not using an external library:\n\n```bash\n_parse_config_file() {\n    local config_file=\"$1\"\n    local line key value\n    while IFS= read -r line || [[ -n \"$line\" ]]; do\n        line=\"${line%%#*}\"           # strip inline comments\n        line=\"${line#\"${line%%[![:space:]]*}\"}\"  # trim leading whitespace\n        line=\"${line%\"${line##*[![:space:]]}\"}\"  # trim trailing whitespace\n        if [[ -z \"$line\" ]]; then continue; fi\n\n        key=\"${line%%=*}\"\n        value=\"${line#*=}\"\n        # ... trim whitespace from each, then assign to global\n\n        case \"$key\" in\n            SSG)          SSG=\"$value\" ;;\n            BUILD_CMD)    BUILD_CMD=\"$value\" ;;\n            # ... etc\n            *)\n                err \"Unknown config key: '$key'\"\n                exit 5\n                ;;\n        esac\n    done < \"$config_file\"\n}\n```\n\nThe `|| [[ -n \"$line\" ]]` on the `while read` is important, the last line of a file is silently dropped if it doesn't end with a newline, a common mistake in hand-edited config files.\n\nUnknown keys exit with code 5 and print all valid keys. It's strict to ensure typos aren't silently ignored.\n\n## Frontmatter Generation\n\nBoth YAML and TOML are supported, and the frontmatter needs to be generated twice: once before the editor opens (without a description, because you haven't written the post yet) and once after (optionally inserting a description you provide post-edit).\n\nFor YAML:\n\n```bash\nbuild_yaml_frontmatter() {\n    local title=\"$1\" slug=\"$2\" date=\"$3\"\n    local tags=\"$4\" description=\"$5\" draft=\"$6\"\n\n    local fm=\"---\\n\"\n    fm+=\"title: \\\"${title}\\\"\\n\"\n    fm+=\"date: ${date}\\n\"\n    fm+=\"slug: \\\"${slug}\\\"\\n\"\n\n    if [[ -n \"$tags\" ]]; then\n        fm+=\"tags:\\n\"\n        IFS=',' read -ra tag_array <<< \"$tags\"\n        for tag in \"${tag_array[@]}\"; do\n            # trim whitespace from each tag\n            tag=\"${tag#\"${tag%%[![:space:]]*}\"}\"\n            tag=\"${tag%\"${tag##*[![:space:]]}\"}\"\n            if [[ -z \"$tag\" ]]; then continue; fi\n            fm+=\"  - ${tag}\\n\"\n        done\n    fi\n\n    if [[ -n \"$description\" ]]; then\n        fm+=\"description: \\\"${description}\\\"\\n\"\n    fi\n\n    fm+=\"draft: ${draft}\\n---\\n\"\n    printf \"%b\" \"$fm\"\n}\n```\n\nI needed to trim the tags, because if a user types `life, coffee , writing` the commas split into `life`, ` coffee `, ` writing`. The whitespace needs to be stripped from each element. Bash doesn't have a trim function, so I use parameter expansion: `${var#\"${var%%[![:space:]]*}\"}` strips leading whitespace by removing the longest prefix that consists only of spaces, and `${var%\"${var##*[![:space:]]}\"}\"` does the same for trailing. It's a little ugly, but it works without spawning a subshell.\n\nAfter the editor closes, if the user provides a description, the tool only needs to rewrite only the frontmatter section of the already-written file, preserving the post body. The closing deliminter is found (`---` for YAML, `+++` for TOML) and `tail` is used to extract the body:\n\n```bash\nlocal delim_count=0\nlocal body_start=0\nlocal lineno=0\nwhile IFS= read -r line; do\n    lineno=$(( lineno + 1 ))\n    if [[ \"$line\" == \"$delimiter\" ]]; then\n        delim_count=$(( delim_count + 1 ))\n        if [[ $delim_count -eq 2 ]]; then\n            body_start=$lineno\n            break\n        fi\n    fi\ndone < \"$file_path\"\n\nbody=\"$(tail -n +\"$((body_start + 1))\" \"$file_path\")\"\nprintf \"%s\\n\" \"$frontmatter\" > \"$file_path\"\nif [[ -n \"$body\" ]]; then\n    printf \"%s\\n\" \"$body\" >> \"$file_path\"\nfi\n```\n\n## The Date Problem\n\nGetting a timezone-aware ISO 8601 date string in bash is annoying. GNU `date` (Linux) and BSD `date` (macOS) have completely different flag syntax:\n\n```bash\n# GNU date (Linux):\ndate --iso-8601=seconds\n# Output: 2026-05-23T12:00:00-06:00\n\n# BSD date (macOS):\ndate +\"%Y-%m-%dT%H:%M:%S%z\"\n# Output: 2026-05-23T12:00:00-0600  ← missing colon in offset\n```\n\nHugo, for example, requires the colon. So `get_iso_date()` tries GNU `date` first, and if that fails, falls back to BSD `date` with a `sed` pass to insert the colon:\n\n```bash\nprintf '%s' \"$result\" | sed 's/\\([+-][0-9]\\{2\\}\\)\\([0-9]\\{2\\}\\)$/\\1:\\2/'\n```\n\nFor timezones, I wanted to avoid the error-prone approach of manually computing offsets, so the tool uses a plain string variable and a conditional `TZ=` prefix:\n\n```bash\nlocal custom_tz=\"\"\nif [[ \"$TIMEZONE\" != \"auto\" && -n \"$TIMEZONE\" ]]; then\n    custom_tz=\"$TIMEZONE\"\nfi\n\nif [[ -n \"$custom_tz\" ]]; then\n    TZ=\"$custom_tz\" date --iso-8601=seconds 2>/dev/null\nelse\n    date --iso-8601=seconds 2>/dev/null\nfi\n```\n\nAn earlier version used a bash array (`local -a tz_prefix=()`) to build an optional `env TZ=...` prefix, which looked cleaner. But under `set -u` in bash 3.2, expanding an empty array with `${tz_prefix[@]}` throws `unbound variable`, a well-known bash 3.2 gotcha that surfaces when the array is empty. Once again, the conditional string approach is more clunky but works correctly everywhere.\n\n## The Setup Wizard\n\nI wanted first-run setup to be completely non-frightening for less technical users. Running `writer` with no config fires an interactive wizard. There are prompts, and each shows the current default in green so you can just press Enter through everything.\n\n```bash\n_prompt() {\n    local key=\"$1\" description=\"$2\" current=\"$3\"\n    printf \"\\n${CYAN}%s${RESET}\\n\" \"$key\"\n    printf \"  %s\\n\" \"$description\"\n    printf \"  Current: ${GREEN}%s${RESET}\\n\" \"$current\"\n    printf \"  Press Enter to keep, or type a new value: \"\n    read -r REPLY_VAL </dev/tty || true\n    REPLY_VAL=\"${REPLY_VAL#\"${REPLY_VAL%%[![:space:]]*}\"}\"\n    REPLY_VAL=\"${REPLY_VAL%\"${REPLY_VAL##*[![:space:]]}\"}\" \n    if [[ -z \"$REPLY_VAL\" ]]; then REPLY_VAL=\"$current\"; fi\n}\n```\n\nThe `</dev/tty` redirect is needed when the installer is run via `curl | bash`, because stdin is the pipe carrying the script itself. Without redirecting reads to `/dev/tty`, `read` would consume lines of the script as user input, silently corrupting the saved config. The whitespace trimming strips spaces a user might accidentally type before pressing Enter.\n\nThe result is saved to `~/.config/writer/config` with a date-stamped comment header. It can be re-run anytime with `writer --setup` and every value is shown with whatever you set last time.\n\n## The Test Suite\n\nTest-driven development is smart, right? So I created a test suite to ensure all edge-cases are caught and errors are handled gracefully and give verbose output so we can understand what's going wrong, and why.\n\n```bash\nbash tests/test_writer.sh\n```\n\nThe harness is split into a thin runner (`tests/test_writer.sh`) that sources six focused modules from `tests/lib/`, mirroring the same structure as the main `lib/`. The runner creates an isolated `$HOME` via `mktemp -d` for every test so the real config is never touched. All tests use `--dry-run` or temp directories, there's no real editor, build, or git operations ever run. It exits non-zero if anything fails, so it can be used in CI.\n\nRight now? All the tests I've created are passing, yay!\n\n## What I'd Do Differently\n\n**The `eval` for `BUILD_CMD`**: Originally I used `eval \"$BUILD_CMD\"` to run the user's build command. This is discouraged by the [Google Shell Style Guide](https://google.github.io/styleguide/shellguide.html#s6.6-eval) because `eval` on user-controlled strings is a correctness and security risk. I've replaced it with `bash -c \"$BUILD_CMD\"`, which still handles multi-word commands like `hugo --minify` correctly but is safer.\n\n**Test coverage of the full flow**: While the test suite has many assertions covering every function: all flag combinations, frontmatter formats, and config parsing, etc. The actual editor-open-save-close flow is not automatically tested because it needs an interactive terminal. I did a lot of manual testing myself on four different machines (I'm the kind of computer nerds that collects ThinkPads like they're candy) and I hope that was robust enough to catch issues.\n\n## Install and Give It a Try!\n\nI wanted to make things as simple as possible, and so the command below takes care of everything, you just copy-paste it into your terminal.\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/brennanbrown/writer-cli/main/INSTALL.sh | bash\n```\n\nAfter the installer finishes, reload your shell profile so the new `~/.local/bin/` PATH entry takes effect and `writer` is available as a command:\n\n```bash\nsource ~/.bashrc   # or ~/.zshrc if you're using Zsh, etc.\n```\n\nThen run `writer --setup` to configure your site directory, SSG, and editor.\n\n> **NOTE:** Now, of course you shouldn't blindly copy-paste commands from the Internet into your terminal, so only do that if you trust me! You can visit that URL and the repo and read everything that goes into the scripts I've made. Again, there's no building or compiling or dependencies, so WYSIWYG!\n\nThe installer clones the repo to `~/.local/share/writer-cli`, symlinks `writer` to `~/.local/bin/`, and adds that to your PATH if needed. Everything in your home directory, nothing system-wide. \n\nTo uninstall: `rm -rf ~/.local/share/writer-cli ~/.local/bin/writer`.\n\nRead the [docs site](https://writer.brennan.day) for the full guide, including the SSH remote workflow and `.writerrc` project-local config.\n\nIf you do try it out, and you find a bug (which I'm sure you will), please [open an issue](https://github.com/brennanbrown/writer-cli/issues) or submit a pull request! All tests should pass before submitting (unless you find bugs in the test suite, then God help me). Run `shellcheck writer.sh lib/*.sh tests/lib/*.sh` to lint your changes.\n\nHave questions, feedback, or your own CLI workflow tips? Drop a comment below or [email me](mailto:mail@brennanbrown.ca), I'd love to hear how you're using `writer-cli` or what features you'd like to see added!\n\n---\n\n## BONUS: Making a Homebrew Tap\n\nAfter getting the curl installer working, I realized I wanted more options for installing. Anybody in security will tell you the `curl | bash` pattern is [a security anti-pattern](https://sandstorm.io/news/2015-09-24-is-curl-bash-insecure-pgp-verified-install). \n\nI added support for [Basher](https://www.basher.it), a lightweight package manager for shell scripts. Where Homebrew is a full package manager that handles binaries and dependencies, Basher is much simpler: it clones a GitHub repo and links the main script into your PATH. All it needs is a `package.sh` manifest in the repo declaring the entry point:\n\n```sh\nBASHER_PACKAGE_NAME=writer\nBASHER_MAIN=writer.sh\n```\n\nThen anyone with Basher can install `writer` with:\n\n```sh\nbasher install brennanbrown/writer-cli\n```\n\nI also then decided to make a Homebrew tap to support `brew install`, as that's the first thing a lot of macOS users reach for, though it's a little more complicated.\n\nHomebrew supports third-party \"taps\", which are just GitHub repos named `homebrew-<something>` that contain a `Formula/` directory.\n\nSo I created [`brennanbrown/homebrew-writer`](https://github.com/brennanbrown/homebrew-writer). The repo is one file:\n\n```\nhomebrew-writer/\n└── Formula/\n    └── writer.rb\n```\n\nThe formula itself is Ruby:\n\n```ruby\nclass Writer < Formula\n  desc \"CLI post creation tool for static site generator blogs\"\n  homepage \"https://github.com/brennanbrown/writer-cli\"\n  url \"https://github.com/brennanbrown/writer-cli/archive/refs/tags/v1.1.2.tar.gz\"\n  sha256 \"845e16dbf3c438196754d9a6956db265e5f371b5eb061531ca9b54670f2a5096\"\n  license \"AGPL-3.0-only\"\n\n  depends_on \"bash\"\n  depends_on \"git\"\n\n  def install\n    libexec.install \"writer.sh\", \"lib\"\n    bin.install_symlink libexec/\"writer.sh\" => \"writer\"\n  end\n\n  def caveats\n    <<~EOS\n      Run the setup wizard before first use:\n        writer --setup\n    EOS\n  end\n\n  test do\n    assert_match \"Usage:\", shell_output(\"#{bin}/writer --help\")\n  end\nend\n```\n\nThe symlink-resolution loop in `writer.sh` needs to handle relative paths. When Homebrew creates `bin/writer → ../libexec/writer.sh`, BSD `readlink` returns that relative path as-is, not an absolute one. The loop resolves it against the symlink's own directory:\n\n```bash\n[[ \"$_writer_source\" != /* ]] && _writer_source=\"${_writer_dir}/${_writer_source}\"\n```\n\nWithout that line, `cd \"$(dirname relative/path)\"` would resolve relative to whatever directory the user happened to be in when they ran `writer`.\n\nOnce the tap is in place, installing is:\n\n```sh\nbrew tap brennanbrown/writer\nbrew install writer\n```\n\nAnd updating is just `brew upgrade writer`, so you don't need to manually pull from the git repository.",
      "date_published": "2026-05-24T18:00:00.000Z",
      "tags": [
        "bash",
        "technical",
        "tools",
        "blogging",
        "indieweb"
      ],
      "author": {
        "name": "Brennan Kenneth Brown",
        "url": "https://brennanbrown.ca",
        "email": "mail@brennanbrown.ca"
      }
    },
    {
      "id": "https://brennan.day/groundhog-day-groundhog-day-and-variations-on-a-theme/",
      "url": "https://brennan.day/groundhog-day-groundhog-day-and-variations-on-a-theme/",
      "title": "Groundhog Day, Groundhog Day, and Variations on a Theme",
      "summary": "I love time loops in media—from Groundhog Day to...hey, wait a minute. Does anybody else feel a weird sense of déjà vu? It can't just be me. Do you ever get up in the morning and feel as though you've already lived the same day?",
      "content_html": "\nOne of my favourite tropes (or maybe it's a genre at this point) in media is the Groundhog Day time loop. Most people know this well—the classic 1993 film starring Bill Murray where he finds himself waking up to the exact same day—\n\nOkay, jokes aside, I did actually find myself thinking more about the topics of yesterday's essay, and continued pulling on the thread. I really couldn't help myself.\n\n## Ferb, I Know What We're Going to Do Today\n\nLet me start with one of the best animated television shows ever. Phineas and Ferb's plot pattern is extremely structured and formulaic, a narrative system where each episode is always split into two interconnected stories. It revolves around the boys' wildly ambitious invention, Candace's attempts to \"bust\" them, and Perry the Platypus fighting Dr. Doofenshmirtz, culminating in the automatic destruction of all evidence.\n\nThe formula is a contract. Every episode makes the same promises. It's [because the audience knows the formula so well](https://criticallytouched.wordpress.com/2017/08/17/phineas-and-ferb-was-formula-storytelling-at-its-finest/) that the writers can play it like an instrument. \n\nThe formula becomes increasingly subverted over time. Some beats are rushed, some are reversed, some intersect. In one episode, Ferb glances at the camera and deadpans, [\"that usually takes us an entire montage\"](https://screenrant.com/phineas-and-ferb-meta-moments-reddit/), the joke works after you've sat through dozens of montages. The lampshade hangs only after the lamp.\n\n[The show is self-aware about this.](https://tvtropes.org/pmwiki/pmwiki.php/LampshadeHanging/PhineasAndFerb) In \"Leave the Busting to Us,\" Candace looks around at her own life—the same thing happening, again, every single day of summer vacation. She exclaims, *\"my life is like a bad sitcom!\"* She knows she is trapped inside a loop she cannot break. Her inability to win is an inevitability, not a predictability.\n\nThe show ran for 222 episodes across four seasons. People kept watching, as [familiarity is a form of pleasure](https://www.theswaddle.com/why-we-derive-comfort-from-rewatching-familiar-things). \n\n## We Are Repeated Things\n\nAlmost everything we do, we will do tens of thousands of times. We find ourselves trying to go to sleep each night. Throughout the day we eat, and most often eat the same meals frequently. We will go on the same commutes, see the same landmarks until our brains tune them out. \n\nThe repeated becomes safe becomes invisible. This is how life is for nearly every being on earth, not just us. To find food, shelter, and of course, companionship. It gets existential quickly.\n\nWhy do we crave the same thing, over and over again? \n\nIn 1968, psychologist Robert Zajonc demonstrated what he called [the \"mere exposure effect\"](https://aeon.co/essays/why-repetition-can-turn-almost-anything-into-music). People prefer things they've encountered before—people, words, melodies—without remembering the prior exposure. We misattribute our increased fluency with quality. Instead of thinking *I've seen this before*, we think *I like this*. \n\nCognitive scientist [Elizabeth Margulis, in *On Repeat: How Music Plays the Mind*](https://www.themarginalian.org/2014/09/18/on-repeat-margulis/), traces mere exposure through music. Repetition, she argues, invites us in as *active participants* rather than passive listeners. Your brain procedurally encodes the music, until the next note can be anticipated without effort. I know the words to the theme songs of the cartoons I watched as a child, even if I haven't encountered them in twenty years.\n\nAnd when I find a new song or album that I absolutely love, I'll listen to it on repeat, sometimes for hours until there's semantic satiation. When I go to Village Ice Cream, I have the go-to flavour I always order. There are a handful of films and books I'd happily rewatch or reread despite having an impossibly long list of other media I still need to get to.\n\nThis isn't static or fixed—people get bored of the same thing and move on, maybe to a more intense version, a different variation, or something else entirely. There is a spectrum. People live in the dichotomy between the comfort and safety of the known and the excitement of the novel and different. But for the most part, we will always orbit the same few things.\n\nWe find ourselves talking to the same classmates and coworkers on a daily basis, sometimes for years. Our romantic partners for even longer, what else is there to say?\n\nThe rollercoaster will always press G-force into us and flutter our stomach with butterflies. Alcohol will always metabolize in our liver the same way. My page will always have the same 26 English letters rearranged in various different ways. There will never be a new colour to witness, never a new planet to live on. [You know the greatest films of all time were never made.](https://brennan.day/how-a-taylor-swift-lyric-gave-me-an-existential-crisis/) I previously wrote about how [there is more than one way to skin a cat](https://brennan.day/more-than-one-way-on-ritual-morality-and-the-darkness-beyond-knowing/), but really, there are only so many ways to.\n\n[The unfamiliar trail might have had a predator](https://www.nitthin.com/p/why-we-crave-more-of-the-same-the). An unfamiliar fruit might be poison. Novelty is risky. The known food and face and path, they all mean survival.\n\n[Familiar environments demand less cognitive processing](https://pmc.ncbi.nlm.nih.gov/articles/PMC11885360/). The brain runs on autopilot, conserving resources for new threats and novel problems. In times of acute stress, [people don't explore new behaviors](https://medium.com/@srinjana818/why-we-repeat-certain-behaviors-the-science-behind-it-bbdf7393e19a), but instead retreat to the deeply-grooved ones, even harmful ones, the behaviours they've been trying to quit. The brain under pressure defaults to the known. \n\nMary Oliver, writing about what makes great poetry, said that [\"rhythm is one of the most powerful of pleasures, and when we feel a pleasurable rhythm we hope it will continue.\"](https://www.themarginalian.org/2014/09/18/on-repeat-margulis/) Murakami said something similar about his running routine: \"The repetition itself becomes the important thing; it's a form of mesmerism.\" The known rhythm carries you somewhere outside the noise of having to decide anything.\n\n[Overexposure leads to satiation, and then boredom](https://arxiv.org/pdf/2210.16226). We drift. We find something new and the cycle resets. The trick is that the new thing, once we've lived with it long enough, becomes the familiar thing we can't imagine living without.\n\n## Not Safe for Working Minds\n\nThere are only so many ways to have sex—despite the seemingly endless creative kink and fetish. In 2019 alone, [13 videos were uploaded to PornHub per minute. Meaning each minute, almost three hours of content were uploaded.](https://news.ycombinator.com/item?id=22529425). And if you take a step back, you have to ask why?\n\n[The Coolidge Effect](https://pubmed.ncbi.nlm.nih.gov/35790609/), named after an apocryphal joke about President Calvin Coolidge, describes a phenomenon observed across mammalian species: sexual interest dampens with a familiar partner, and reliably revives at the introduction of a new one. The dopamine spike that novelty produces is amplified in the context of sexuality in ways that dwarf almost every other stimulus.\n\nThe internet gave this [infinite fuel and removed all friction](https://journals.sagepub.com/doi/10.1177/26318318221116042). The primitive brain wired for novel mates now has access to an endless scroll, each new image producing a dopamine hit, none becoming familiar enough to lose charge. [There's always another](https://pmc.ncbi.nlm.nih.gov/articles/PMC9259837/). \n\nThe seeking becomes the thing. The next video is identical to the last in structure. Novelty is cosmetic.\n\n## The Refrain, The Reframe\n\nLet me be blasphemous and quote Ecclesiastes 1:9 right after that section,\n\n> <small>9</small> That which has been is what will be,  \n> That which is done is what will be done,  \n> And there is nothing new under the sun. —NKJV\n\nFor creative endeavours, there is good argument to be made that you should always create, no matter how similar or repetitive or stale you think your creation is. That is one thing that is so contradictory and paradoxical here. [Any two humans are 99.9% identical in their genetic makeup](https://www.genome.gov/about-genomics/fact-sheets/Genetics-vs-Genomics), and yet each and every one of us holds an entirely unique mind and life.\n\nThe German choreographer Pina Bausch, whose dance-theatre pieces built entire worlds out of repeated gestures, said:\n\n> [\"Repetition is not repetition. The same action makes you feel something completely different by the end.\"](https://www.azquotes.com/quote/698273) \n\nEven if you return to the same river bank, the same bend, the same cold shallows where the reeds catch the light, [the water is different](https://tiedupsdotcom.wordpress.com/2022/08/30/repetition-backwards-and-repetition-forwards/). You are different.\n\nGilles Deleuze argued in [*Difference and Repetition*](https://philopedia.org/works/difference-and-repetition/) that each instance of a repeated act carries uniqueness, producing something new through returning. Repetition, for Deleuze, is [the process by which creativity becomes possible](https://www.thenandnow.co/2023/04/25/introduction-to-deleuze-difference-and-repetition/). \n\nThe musician practicing the same melody for the thousandth time has different neural pathways. Her hands are different. The weight of the emotion in the phrasing shifts. Think of Bach's Goldberg Variations, Beethoven's Diabelli Variations, the passacaglia and the fugue. In the repetition you find everything the idea contained that wasn't there the first time. The fugue returns to its subject again and again, until there's revelation. Jazz does the same thing with 12-bar blues progression. The chord structure doesn't change, the player does. [The night does](https://human.libretexts.org/Bookshelves/Music/Book:_Music_Appreciation_I_(Lumen)/04:_Classical_Forms/4.05:_Theme_and_Variations).\n\nThis is what Ecclesiastes actually means. It is not a eulogy for novelty, it's a permission slip. The pressure to invent something unprecedented, something that has never existed in the history of the world? It's bullshit. The invitation is to do what Kyoto Animation did with *Endless Eight*. Take the same plot, the same beats, the same dialogue, and change the camera angle. Change the outfit. Change what the character is eating. Do it again. Do it again. Find what the next iteration holds that the first one couldn't.\n\nA sunset will never look as good in a photograph as it does in real life. And yet a sunset will never stop being photographed by people, until it stops setting.\n\nI guess that's kind of how I go about [writing love poetry](https://bkpoetry.com/post/670686478532263936/impossibility-of-this). Hm.\n",
      "date_published": "2026-05-23T20:00:00.000Z",
      "tags": [
        "philosophy",
        "psychology",
        "Media Analysis",
        "Creative Writing"
      ],
      "author": {
        "name": "Brennan Kenneth Brown",
        "url": "https://brennanbrown.ca",
        "email": "mail@brennanbrown.ca"
      }
    },
    {
      "id": "https://brennan.day/groundhog-day-savescumming-and-our-endless-numbered-days/",
      "url": "https://brennan.day/groundhog-day-savescumming-and-our-endless-numbered-days/",
      "title": "Groundhog Day, Savescumming, and Our Endless Numbered Days",
      "summary": "I love time loops in media—from Groundhog Day to Haruhi's Endless Eight. What do they reveal about mortality, memory, and the human desire to escape consequence through Nietzsche's eternal recurrence?",
      "content_html": "\nOne of my favourite tropes (or maybe it's a genre at this point) in media is the Groundhog Day time loop. Most people know this well—the classic 1993 film starring Bill Murray where he finds himself waking up to the exact same day, frozen in a repeating 24-hours. In each loop he becomes more knowledgeable, more aware of the machinations of every person at every hour.\n\nOnly by following the hero's journey, and by undergoing a profound moral transformation, does Murray's character break the cycle. He abandons his selfish, cynical ways, and his final loop is a perfect, selfless day dedicated to helping others.\n\nThis film wasn't the first story to have a timeloop, that would arguably be the 1905 Russian novel *the Strange Life of Ivan Osokin* by P.D. Ouspensky. It features the protagonist, Osokin, who is granted the ability to live his life over again but struggles to change his fate the second time.\n\nWhat might surprise you though, is how many pieces of media actually follow the Groundhog Day timeloop. There's [over 100 films](https://letterboxd.com/bungtoad/list/135-time-loop-movies/) alone. Some of my favourite examples include *All You Need Is Kill* (2004), *Before I Fall* (2017), *The Map of Tiny Perfect Things* (2021), and *Puella Magi Madoka Magica* (2011), and of course the ur-text itself.\n\nBut why are we drawn to time loops in media? Fiction in general enjoys playing with time—flashbacks, foreshadowing, time travel. But these one-day time loops are a specific, particular flavour.\n\nWestern culture has made death taboo. The idea of getting old, or getting sick, or kicking the bucket are all swept under the rug. People live with the reckless shortsightedness as though they'll live forever exactly as they are. As a result, nearly everyone is shocked and unprepared for when the inevitable arrives.\n\nAnd I think that's the allure of Groundhog Day timeloops. People want to live forever, but they don't want to be 200-years-old, no way. People want to permanently stay at wherever they consider the peak of their life. We want the comfortable, predictable day where there's no sudden huge change. No eviction notice, no medical emergency, no impending apocalypse.\n\nPhilosopher Ernest Becker argued in [*The Denial of Death*](https://www.templeton.org/wp-content/uploads/2021/02/JTF_Immortality_fnl.pdf) that the central organizing project of humanity has always been the management of mortality terror. We create culture, religion, children, and legacy. We create so we do not not have to instead look at what waits at the end. \n\nPsychologists Pyszczynski, Solomon, and Greenberg built this into Terror Management Theory: mortality awareness doesn't make us live more deliberately, rather, it makes us build monuments. Makes us write books. Do anything that might outlast the body. Isn't that what I'm doing here, with this blog?\n\nBut time loop, hm, that's the monument that doesn't have to outlast anything.\n\nOn the flip side, you might already feel as though you're living through a Groundhog Day time loop. The monotony and exhaustion of the job we need to survive can organically paint each day the same. The time loop, stil, is an escape. If we knew we didn't have to worry about the next day, would we perform our job in every loop? Of course not. We would be free and liberated by the means of being trapped.\n\n[Matt Bennett, writing for the Institute of Art and Ideas,](https://iai.tv/articles/groundhog-day-vs-nietzsche-reliving-your-life-auid-2040) writes that the Groundhog Day loop is \"a challenge but also an opportunity—to imagine what the best versions of ourselves could be, even if the world around us remained the same.\" I think that's an optimistic reading. \n\nThere's something more anxious underneath, isn't there? The loop isn't an invitation to self-improvement, but a fantasy of consequence-removal. Of waking up and the eviction notice is still not yet slid under the door, the test results are not yet in, the person you love is still asleep in the next room and hasn't yet decided to leave.\n\nYou don't have to die. Instead you wake up and everything is just the same—thank god, the morning you already know. Same time on the clock, same breakfast, same body. Your suffering is predictable in the loop. Fully known with no surprises.\n\n## Endless Eight\n\nMy most favourite example of the loop is one of the most controversial and critically-panned, [*Endless Eight*](https://haruhi.fandom.com/wiki/Endless_Eight_I) from the anime series *The Melancholy of Haruhi Suzumiya*. While all other examples of time loop media only show the most interesting, plot-relevant loops to the audience, Endless Eight does the opposite. In the light novel, the \"eight\" means August, marking the eternal summer, but the showrunners decided to take the name in a different direction. There are instead eight episodes in the story arc, and all eight episodes are nearly identical. You have to endure watching the same plot, the same beats, the same dialogue, eight times in a row.\n\nIn Nagaru Tanigawa's source novel, the Endless Eight is barely thirty pages and only covers the final loop.\n\nThe reason the show stretched so long is that [*The Disappearance of Haruhi Suzumiya* had been shifted from a TV arc to a theatrical film mid-production](https://www.animeherald.com/2019/04/26/endless-eight-ten-years-on-an-anime-origin-story/), leaving a gap that couldn't be filled with any other novel material without spoiling the film.\n\nThere isn't repeated footage, either. [The studio, Kyoto Animation, completely re-animated and re-voiced every single episode from scratch](https://www.cbr.com/haruhi-suzumiya-endless-eight-arc-genius/). Each episode had different storyboard directors, animators, music cues. Different camera angles, character outfits, background scenery, food, and staging of scenes.\n\nThis is not lazy television. This is obviously obsessive, meticulous, and expensive. Yet the production team's own senior staff publicly opposed it and later apologized for it. Yutaka Yamamoto, a longtime KyoAni animator, argued against the eight-episode run during planning and offered his regrets after. The English dubbers, [frustrated by the decision](https://www.cbr.com/haruhi-suzumiya-endless-eight-arc-legacy/), pitched turning the arc into a gag dub—something like the notorious *Ghost Stories* localization—as a way to leaven the repetition. The pitch was rejected, but man, imagine if it wasn't.\n\nCan you imagine the fan reaction during the original airing? Week by week, from June through August of 2009. It was [collective grief](https://chikorita157.com/2009/07/23/the-fiasco-of-suzumiya-haruhi-endless-eight-continues-and-fan-reactions/). Viewers checked in every Friday hoping that, this time, the loop would finally break. Only to instead watch yet another intact loop. By episode seven, when it *still* hadn't resolved, the forums became volcanic. \n\nYou can see the performance art in retrospect, right? The audience, unwittingly, enacted the loop. Eight weeks of tuning in expecting a different outcome and getting the same one.\n\nIt is painful to get through, and that's the entire point. Time loop media romanticizes and glosses over how painfully repetitive being trapped in the loop would actually be. With *Endless Eight*, you're exhausted just watching the same loop happen eight times. It is impossible to fathom experiencing the 15,532 loops that occur for the characters in Endless Eight.\n\nOne of the characters is [Nagato Yuki](https://haruhi.fandom.com/wiki/Yuki_Nagato), a quiet android linked to a data entity that transcends time. Because of this, she remembers every loop. Every summer festival, every firework, every cicada, every cup of shaved ice melting in the heat. [594 years](https://en.namu.wiki/w/%EC%97%94%EB%93%A4%EB%A6%AC%EC%8A%A4%20%EC%97%90%EC%9D%B4%ED%8A%B8) of the same two weeks of August, alone in her memory while everyone else resets. \n\nThe 594-year weight is [what breaks Nagato in the sequel film, *The Disappearance of Haruhi Suzumiya*](https://neigoseipokgai.home.blog/2020/02/27/what-is-the-point-of-endless-eight/), the film KyoAni released six months later and widely understood as their act of contrition. For Nagato's decision to remake the world in *Disappearance* is inscrutable without *Endless Eight*. She is not malfunctioning, she is just exhausted. She has been watching the same summer end and reset for six centuries, unable to intervene, unable to forget, unable to do anything but observe and she has finally had enough.\n\n*The Disappearance of Haruhi Suzumiya* went on to become one of the highest-grossing anime films of its year.\n\n## Savescumming\n\nVideo games as a medium inherently have a time loop mechanic without meaning to. [What is any video game if not a time loop?](https://www.gamesradar.com/from-deathloop-to-returnal-how-2021-became-the-year-of-the-video-game-time-loop/) If you die, you restart at a checkpoint or beginning. The video game \"lives\" mechanic originated directly from pinball, where players had a limited number of balls per game. When arcades exploded in the late 1970s and 1980s, developers (starting with Taito’s 1978 hit Space Invaders) adopted this finite-life system.\n\nThe primary goal was monetization: losing a life forced players to insert more quarters to continue playing. The mechanic was grandfathered into console gaming even though by that point there was no monetization incentive. It took until [Super Mario Odyssey](https://nintendoeverything.com/nintendo-explains-why-super-mario-odyssey-ditches-the-lives-system/) for Nintendo to remove the lives mechanic from the game series, though you still die and restart all the same.\n\nBut beyond the enforced live-die-repeat mechanic of video games, there is something far more interesting. Save scumming is the practice of repeatedly saving and reloading a video game to ensure a specific, favorable outcome. Players typically use this to undo mistakes, bypass bad luck, or guarantee a successful dice roll.\n\n*Undertale* is a game aware of this. Sans accurately guesses how many times you have died and reloaded simply by reading the subtle look of defeat or boredom on Frisk's face, and if you reload your save to get a different ending (like going from Neutral back to Pacifist), Sans will recall your past actions. Flowey has \"ripple-effect proof memory\" who remembers past saves, reloads, and resets.\n\nConsent is the moral distinction between savescumming and the Groundhog Day loop. In the loop, you cannot choose not to know what you know, and memory accumulates against your will, building a terrible sediment loop after loop. Savescumming, on the other hand, is a choice. You reach back and cancel what happened.\n\n[The gaming community loves arguing about savescumming.](https://dissectinggamedesign.substack.com/p/xcom-enemy-within-why-do-we-save) [Some players feel](https://malvasiabianca.org/archives/2009/08/saving-ethics-and-the-slog/) that reloading evacuates the moral weight from decisions that were supposed to matter. The pang of having chosen wrong is supposed to be there.\n\n[Critic Elvie Mae Parian argued](https://sidequest.zone/2021/11/22/death-is-only-the-beginning-mortality-in-the-roguelike/) that the game *Hades* presents death as \"not something to be feared or reviled—but a natural part of progression.\" Zagreus's deaths are not failures, they're needed for the story to unfold. The gods keep talking. The garden keeps growing. Each attempt accretes into relationship, into warmth, into a world that wants you to succeed.\n\n*Returnal* asks \"What does the cycle do to someone?\" Selene crash-lands on an alien planet and finds her own corpses scattered across the terrain. Ruins of every version of herself that didn't make it.\n\nIn [*Outer Wilds*](https://francismurillo.github.io/2020-03-22-Outer-Wilds-On-Acceptance/), every twenty-two minutes, the sun goes supernova. Everything dies. The solar system resets. You carry nothing forward except knowledge. No items. No saves to reload. No stat increases. The loop in *Outer Wilds* cannot be gamed. [You have \"become a master of this space,\"](http://www.pressplaygaming.net/articles/2019/10/8/witnessing-the-end-messages-amp-meaning-from-outer-wilds) and you can \"continue in this loop, comfortable in the knowledge that things will be the same tomorrow—or you can risk it all, dive into the unknown.\" The game ends when you let the loop stop. To die a final, real, unresettable death.\n\n## Nietzsche Returns\n\nI think it's incredibly fitting that the first-ever time loop media, Strange Life of Ivan Osokin by P.D. Ouspensky, was a narrative platform about Nietzsche's concept of eternal recurrence, something [I've already written about](https://brennan.day/the-blogging-uebermensch-or-being-the-luckiest-person-on-earth/#joy-and-amor-fati).\n\nThe Groundhog Day timeloop asks whether the self is a pattern that will keep asserting itself. Ouspensky's Ivan Osokin gets his wish of a second run at his life—and squanders it. Same mistakes. Same woman. Same wreckage. \n\n[Writing in *Philosophy Now*](https://philosophynow.org/issues/93/Groundhog_Day), David Larocca writes that *Groundhog Day* realizes Nietzsche's eternal recurrence so brilliantly that it even solves the contradiction between Nietzsche and Deleuze's conflicting readings of that idea. Where Nietzsche's version is terrifying, with every single detail of your life recurring identically, forever, the same traffic jams and bad haircuts and cruelty you regret—the Groundhog Day version instead is merciful. You can do it differently in the same life. You can learn piano, and you can catch the boy who falls from the tree.\n\nNietzsche's eternal recurrence was always a test, not a theory. If a demon appeared and told you that you would live this life—this exact life—over and over for eternity, would you despair or say yes? The time loop genre [almost unanimously answers](https://studenttheses.universiteitleiden.nl/access/item:3192814/view): *yes, but...* But only once you've become someone worth saying yes about. But only when you earn the exit. For the day ends only when you're ready to let it go.\n\nYou can change, but only if you stop trying to win. Bill Murray's character Phil Connors breaks the loop not by memorizing schedules or learning ice sculpture, no. He woke up to the next day only by trying and caring. Caring about the old man who dies in the alley every single night no matter what Phil does. Endless Eight breaks because Kyon finally just does his homework. Zagreus reaches the surface not because his attack damage increased, but because the people in the underworld want him to make it. \n\nThe loop is a mirror, showing you who you are by showing you who you keep being.\n    \nOh, that reminds me! One of my favourite tropes (or maybe it's a genre at this point) in media is the Groundhog Day time loop. Most people know this well—the classic 1993 film starring Bill Murray where he finds himself waking up to the exact same day, frozen in a repeating 24-hours...\n\n\n",
      "date_published": "2026-05-22T20:00:00.000Z",
      "tags": [
        "philosophy",
        "Media Analysis",
        "Video Games",
        "Anime",
        "psychology"
      ],
      "author": {
        "name": "Brennan Kenneth Brown",
        "url": "https://brennanbrown.ca",
        "email": "mail@brennanbrown.ca"
      }
    },
    {
      "id": "https://brennan.day/spice-our-antifragile-biology/",
      "url": "https://brennan.day/spice-our-antifragile-biology/",
      "title": "SPICE: Our Antifragile Biology",
      "summary": "Spicy food and capsaicin demonstrate hormesis and antifragility in human biology. The science of pain, TRPV1 receptors, and how controlled exposure to stressors makes our bodies stronger rather than weaker.",
      "content_html": "\nIt's come to my attention that, even though I was a cook for years, I've never actually written a post here yet about food. How absurd!\n\nOver the past few months, I've been adding more spice to my meals. Learning the recipes has been so enjoyable—cracking Sichuan peppercorns into a dry, hot wok, filling the air with scents of citrus peel and electricity. Then, sizzling the *doubanjiang* (fermented broad bean paste) in toasted sesame oil. Silken tofu slides in as pale moons, poaching as the oil starts to blush red. You finish with hand-crinkled chili threads and a glug of chili oil infused with star anise and cinnamon.\n\nThe heat of Mapo Tofu hits twice. The upfront hit of fried chiles, and then the numbing buzz-buzz tingle dancing on your lips long after the bowl is empty. A kiss you can't stop remembering.\n\nThere are a lot of recipes I could describe like this I've been trying out. Like Jalapeño & Habanero Corn Chowder, Misir Wot (Berbere-Spiced Red Lentil Stew), or Volcán al Pastor.\n\nBut no, this isn't going to be a blog post about recipes or cooking. What I actually want to write about is the aftermath. The red-faced sniffles and unquenchable fire that stays well after the meal. The science of the pain that cultures around the world have celebrated, ritualized, and passed down.\n\n## The Accident\n\nWhat exactly is spicy food? The answer is [capsaicin](https://www.uchuspice.com/blog/blog/capsaicin-the-science-of-spice), a chemical which binds to the [TRPV1 receptors](https://en.wikipedia.org/wiki/TRPV1) in our mouths. Those receptors evolved to detect actual physical burning, to stop us from eating things hot enough to damage tissue, and so capsaicin tricks us into thinking there's pain.\n\n[Plants evolved high concentrations of capsaicin to stop mammals from eating them](https://www.azolifesciences.com/article/Science-of-Spicy-Foods.aspx), so their seeds could instead be carried by birds, since birds lack the relevant receptor entirely and [feel nothing at all](https://npic.orst.edu/factsheets/archive/Capsaicintech.html). The chili pepper is bird-delivery with mammal-proof packaging.\n\nDidn't really work out that way.\n\n## The Chase\n\nWhat's the response our body has to being on fire? [Blood vessels dilate; we flush, sweat, drool](https://www.healthdigest.com/306112/the-real-reason-spicy-food-makes-your-nose-run/). The trigeminal nerve in both mouth and nasal cavity sets off mucus production [even when nothing has gone near your nose](https://www.iflscience.com/why-does-spicy-food-make-your-nose-run-76832). We hiccup. [We vomit if it's severe enough](https://www.powershealth.org/about-us/newsroom/health-library/2022/07/08/hot-stuff-spicy-foods-cant-harm-you-can-they). \n\nEvery symptom is a purge response. Cry, sweat, drool, flush, expel.\n\n[Endorphins then rush in to provide relief, creating euphoria; dopamine adds pleasure and reward; adrenaline surges, heightening senses](https://neurolaunch.com/why-do-i-feel-high-after-eating-spicy-food/). These endorphins reduce stress and sedate us.\n\nLeigh Cowart, in her book *Hurts So Good*, writes how [people who seek out deliberate pain, like spice, always talk about what comes after. The dominion over self, the endorphin rush, the homebrew morphine](https://www.popsci.com/science/why-do-people-like-spicy-food/). This is what we're drawn to, not the pain itself.\n\nPsychologist Paul Rozin calls this [\"benign masochism,\"](https://www.austinchronicle.com/food/the-psychology-of-why-were-drawn-to-spicy-food-and-other-dalliances-with-pain-13284112/) the enjoyment of negative sensations which are harmless. When eating spicy food, you know the discomfort is short-lived and not a real threat; a thrill rather than something to flee.\n\nCapsaicin is also a neurotoxin; it causes selective degeneration of a particular population of pain-sensing neurons in mammals, producing irreversible functional impairments. But the amount you'd need to consume for that to happen is kilograms of the hottest peppers that exist, don't worry.\n\n## After the Fire\n\nAfter the initial excitation, [capsaicin produces a lasting refractory state where neurons become unresponsive, not just to capsaicin, but to a variety of other stimuli including noxious heat](https://pubmed.ncbi.nlm.nih.gov/20932251/). \n\nThis is why [high-concentration capsaicin patches are used to treat chronic nerve pain](https://www.frontiersin.org/journals/allergy/articles/10.3389/falgy.2022.898494/full). Our body is a forest, the controlled burn repairs and heals.\n\nThe calcium influx through the TRPV1 channel desensitizes the channel. The stressor triggers its own antidote.\n\nInterestingly, the same logic extends to the gut. [IBS involves TRPV1 receptors that are overactive and hypersensitive](https://redbloom.co/blogs/research/capsaicin-therapy-how-spicy-can-heal-your-gut-not-hurt-it). Repeated, controlled exposure to capsaicin causes those nerves to become less reactive, improving visceral pain thresholds, calming overactive gut signals. In clinical trials, [patients initially reported more discomfort in the first two weeks, and then the symptoms faded](https://redbloom.co/blogs/research/capsaicin-therapy-how-spicy-can-heal-your-gut-not-hurt-it). You endure the flame, you become fire resistant.\n\n## The Bacteria Were Always There\n\nIt used to be thought that drinking large quantities of milk to treat or cure lactose intolerance was folk wisdom—wrong. [Like nearly all folk wisdom, though, there was truth here as well. It works.](https://www.youtube.com/watch?v=h90rEkbx95w)\n\n[Consuming lactose does not cause your body to produce more lactase](https://pmc.ncbi.nlm.nih.gov/articles/PMC11013211/). The enzyme needed is absent, regardless. However, [repeated daily consumption of lactose alters the gut microbiome and improves lactose tolerance](https://www.milkgenomics.org/?splash=gut-microbes-boost-dairy-tolerance-in-adults-lacking-lactase). [Lactic acid bacteria eat the lactose but produce lactic acid instead of gas](https://biology.indiana.edu/news-events/news/2019/foster-lactose-intolerance.html). You still can't digest lactose yourself, but the bacteria kindly digest it for you before any symptoms begin.\n\n[Bifidobacterium multiply in response to a signal you sent by eating something that hurt you](https://www.sciencedirect.com/science/article/pii/S000291652366349X). The microbiome reorganizes and the gut homes a different ecology. You are changed by choosing discomfort consistently over time.\n\n## Weight-lifting, Allergies, Fasting, and Childhood Dirt\n\nWhen you lift weights, [microscopic tears occur in your muscle fibers](https://alloypersonaltraining.com/science-of-muscle-recovery-enhance-your-fitness-regimen/). [The pain you feel a day later is your body's inflammatory response to the structural injury](https://www.oreateai.com/blog/that-twoday-ache-unpacking-the-mystery-of-doms/d62540e5076902c016c9f229b53c1b2d). [After a rigorous workout, the nuclei of muscle cells migrate toward the tears to help patch them up](https://www.livescience.com/muscle-repair-by-roaming-nuclei), issuing commands for new proteins to be built. The muscle that heals is denser than the one that tore.\n\n[Allergen immunotherapy works by introducing small, gradually increasing doses of the thing that makes you sick](https://allergyasthmanetwork.org/health-a-z/immunotherapy/). Pollen, peanut, bee venom. The immune system, which is confused and overreactive, is healed through controlled exposure. The short-term phase involves mast cell desensitization; the long-term phase produces regulatory T-cells that suppress the allergic response entirely. \n\nWhen you fast, your cells experience mild metabolic stress, [activating autophagy. Damaged proteins and worn-out organelles are broken down and recycled](https://www.qualialife.com/fasting-autophagy-and-senolytics-what-you-need-to-know) in this state. The cell eats its own debris. There's increased long-term stress resistance as a result.\n\n[The hygiene hypothesis states that early childhood exposure to particular microorganisms—gut flora, environmental bacteria, even parasites—protects against allergies by properly tuning the immune system](https://en.wikipedia.org/wiki/Hygiene_hypothesis). Children who grow up on farms, who play in the mud, who are exposed to animals, [consistently show lower rates of asthma, allergic disease, and autoimmune conditions](https://www.sciencedaily.com/releases/2012/03/120322142157.htm). [Raise children in sterile environments and the system turns its aggression inward](https://www.britannica.com/video/Research-exposure-child-life-germs-immune-system/-169130), attacking pollen, peanuts, and the body's own tissue instead.\n\n## There's A Word For It\n\nThis is the biological concept [hormesis](https://pmc.ncbi.nlm.nih.gov/articles/PMC2248601/). The phenomenon in which a low or moderate dose of a stressor produces a beneficial response, though high dose remains harmful. \n\n[Intermittent fasting, exercise, cold exposure, and plant compounds like capsaicin all operate through hormetic mechanisms](https://www.mindbodygreen.com/articles/hormesis). The poison makes the medicine.\n\n[It's \"an adaptive response of cells and organisms to a moderate, usually intermittent stress\"](https://pure.johnshopkins.edu/en/publications/hormesis-what-it-is-and-why-it-matters-4/). Cells increase production of cytoprotective proteins, antioxidant enzymes, and growth factors.\n\n## What Needs the Storm\n\nIn 2012, Nassim Nicholas Taleb published [*Antifragile: Things That Gain from Disorder*](https://www.goodreads.com/book/show/13530973-antifragile). Encountering this concept significantly shifted things for me. Antifragility is not resilience or robustness. Antifragile systems don't merely withstand shocks, the antifragile thrive and grow stronger in response. The Hydra grows two heads if you cut one off. The system *needs* to be attacked to become more than it was.\n\nTaleb built this argument through finance and systems theory. But life and our biology have been antifragile for millions of years before finance existed.\n\nOur receptors react less after exposure, muscle fibers heal thicker than the tears, and immunity cells learn from invasions. The TRPV1 channel closes. The Bifidobacterium multiply. The nuclei migrate toward the wound.\n\n## You Must Continue\n\nOf course, there's a catch to all of this: None of it is permanent.\n\n[TRPV1 receptors resensitize if capsaicin exposure stops](https://onlinelibrary.wiley.com/doi/10.1155/2016/1512457). The Bifidobacterium population in the gut reverts when lactose consumption ends, as continuous exposure is a prerequisite to maintain tolerance. Allergen tolerance after immunotherapy, while longer-lasting, also fades without maintenance. What stops being challenged stops being strong.\n\nAntifragility is a dynamic equilibrium sustained by ongoing exposure. The gains are rented, not owned. Stop applying the stressor and the system softens back to baseline.\n\nThere's no endpoint, no achievement of toughness. You are trying to maintain a practice. The exposure is not a treatment you complete, it is a relationship you sustain.\n\nEvery generation of children playing in the mud, every culture eating fermented foods, everyone choosing discomfort in small doses? None are banking gains for later. We are keeping something alive that will die without us. The antibody, the receptor, the microbiome. None of these persist without the stressor. We are not the beneficiaries of our ancestors' hardships, no, we have to do our own.\n\n## The Hard Part\n\nWhich brings me to *BoJack Horseman*. The scene near the end of the first season where BoJack asks a runner how he does it:\n\n> *It gets easier. Every day it gets a little easier. But you gotta do it every day, that's the hard part. But it does get easier.*\n\nHonestly, the hard part isn't the pain. It's the consistency. Like everything else important, you have to show up and do the work. In order to stay adapted, you need to keep showing up to the thing that hurt you in the first place.\n\nEvery time you sit with the burn instead of reaching for the water, you are telling your nervous system something about what kind of person you are becoming.\n\nI think this partially answers why I find it easier to [write every day now](https://brennan.day/a-thousand-cranes-why-i-write-every-day/), half a year in, than I did when I started in November. Spiritual traditions around the world have held that endurance, when chosen deliberately, transforms those who endure. This is hormesis. This is antifragility.",
      "date_published": "2026-05-21T20:00:00.000Z",
      "tags": [
        "Food",
        "Biology",
        "Science",
        "Health"
      ],
      "author": {
        "name": "Brennan Kenneth Brown",
        "url": "https://brennanbrown.ca",
        "email": "mail@brennanbrown.ca"
      }
    },
    {
      "id": "https://brennan.day/manifestation-the-law-of-attraction-cancer-and-abuse/",
      "url": "https://brennan.day/manifestation-the-law-of-attraction-cancer-and-abuse/",
      "title": "Manifestation, the Law of Attraction, Cancer and Abuse",
      "summary": "Examining the dark side of manifestation and Law of Attraction movement: its New Thought origins, cultural appropriation of Eastern and Indigenous practices, gender dynamics, and the hidden cruelty of victim blaming cancer survivors and abuse victims.",
      "content_html": "\nPicture a softly lit bedroom, white linen, diffuser trailing lavender mist into the late afternoon. A woman is speaking into her phone in a low, confiding voice. Behind her, a corkboard studded with magazine cutouts. Range Rover, beachfront villa, stacks of cash fanned out beside a crystal water bottle. She's writing the same sentence fifty-five times in a gold-leafed journal—the [55x5 method](https://www.oprahmag.com/life/a30244004/how-to-manifest-anything/) burns your desires into the subconscious and the universe, she explains. She's reciting [affirmations](https://www.cnet.com/health/mental/lucky-girl-syndrome-the-science-behind-this-new-tiktok-trend/) over and over. *I'm so lucky. Everything always works out for me. I don't chase, I attract.* The comments are full of emojis and angel numbers. Hundreds of thousands of people are watching. Millions, depending on the day.\n\n[This is ✨ `#MANIFESTATION` ✨ on TikTok and Instagram Reels](https://www.thecrimson.com/article/2023/3/30/manifestation-tiktok/). Gorgeous, warm, aspirational, cozy. There are tarot readers in fairy-lit rooms pulling cards just for you. Psychics explaining what your energy is currently attracting and how the universe rearranges on your behalf. Life coaches walking you through vision board tutorials and the [369 method](https://www.vox.com/the-goods/21524975/manifesting-does-it-really-work-meme) and pillow techniques. \n\nThe aesthetic is soft, golden, and feminine. The promise is total: *think the right thoughts, and reality will bend.* And there is scientific literature about how this could possibly be [a psychological disorder](https://www.sciencedirect.com/science/article/abs/pii/S187620182400248X).\n\nLet's back up and start from the beginning.\n\n## Where Did All This Come From?\n\nManifesting is not new. Most of its believers understand these practices as ancient Eastern wisdom, exotic and timeless (a problematic framing I'll come back to). \n\nThe actual origin is much more recent and American. [New Thought](https://theconversation.com/why-you-should-know-about-the-new-thought-movement-72256) began in the United States in the early 19th century, rooted in the work of a Maine clockmaker-turned-healer named Phineas Quimby, who believed that illness originated in the mind through erroneous belief. A mind \"open to God's wisdom\" could overcome any disease. There was the Transcendentalism of Ralph Waldo Emerson, the \"Mental Science\" of Swedenborgian minister Warren Felt Evans, and eventually an entire ecosystem of churches, Unity denominations and self-help philosophies. \n\nBy the 20th century, these ideas would mutate into *The Secret*, the Oprah industrial complex, and the TikTok wellness feed.\n\nManifesting mostly comes from Neville Goddard, a Barbadian-born dancer and mystic who moved to New York in the 1920s and studied esoteric philosophy under a mysterious Harlem teacher named Abdullah. Goddard spent the next four decades lecturing in Los Angeles on what he called the [\"Law of Assumption.\"](https://coolwisdombooks.com/neville/neville-goddard-radio-lectures-6-the-law-of-assumption/) Enter a drowsy, hypnagogic state and inhabit your desired reality as though it is already true. The subconscious doesn't distinguish between what you vividly imagine and what actually happens. \"An assumption,\" he wrote, \"though false, if persisted in, will harden into fact.\" Goddard interpreted the entire Bible as psychological allegory, Christ as the human imagination, the Crucifixion as the spirit buried in matter. He preached to overflow crowds and television audiences of 300,000 until his death in 1972. His books, which had been out of print for decades, are now ubiquitous in the manifestation corners of TikTok and Reddit.\n\n## Spiritual, Not Religious\n\nIf manifestation was simply about positive thinking and optimism, I'd absolutely have no problem with it. I myself believe in the good of many things and others, and have an astounding amount of faith in uncertain things.\n\nThe appeal of [new age, \"spiritual but not religious\" eclecticism](https://www.elle.com/culture/books/a64275190/new-age-spirituality-riot-grrrl-tarot-cards-essay/) is not irrational. [Organized religion has historically been a mechanism for women's subordination and oppression](https://progressivechristianity.org/resource/women-religions-traditional-victims/). The Abrahamic traditions use the story of Eve to justify everything from denying women education to withholding pain relief during childbirth. When women began leaving those traditions, they didn't leave the hunger for the sacred, finding it elsewhere, in a holistic milieu that centred them. That impulse is understandable.\n\nBut as a tragic result, there's now a billion-dollar industry built on cherry-picking practices from marginalized cultures, stripping them of meaning, and selling them back as lifestyle accessories. [The chakra system](https://nchschant.com/19480/investigative/spirituality-or-cultural-appropriation/) derives from Hindu scripture written between 1200 and 1500 BCE. Smudging with sage is sacred ceremony in many Indigenous North American traditions. The 369 manifestation method is rooted in a Hindi philosophical concept. \n\nThe bastardization of these practices has resulted in people [charging $80 for a charged crystal water bottle](https://www.thewayward.co/wellbeing/2018/10/13/what-is-crystal-activated-water), or $300 for a manifestation course, while the cultures whose knowledge made those products possible receive nothing. \n\nThis is [orientalism](https://www.fairobserver.com/blog/the-truth-about-western-cultural-appropriation-of-eastern-spirituality/) dressed in linen and rose quartz. The East (and Indigeous Peoples) as a source of exotic spiritual raw material to be refined into Western wellness content.\n\nI want to be clear that some of these practices are good, such as meditation and gratitude, some are harmless such as believing crystals emit vibrational energy that interacts with the body's energy fields or moon rituals, but some are not only extractive but extremely harmful. \n\n## The Gendering of Spirituality\n\nManifestation culture skews heavily toward women. The [TikTok aesthetic is almost entirely feminine](https://dailyfreepress.com/04/16/20/203943/lucky-girl-syndrome-the-gentrification-of-manifestation-mad-women/). Beige and blush tones, the \"lucky girl\" framing, vision boards plastered with luxury handbags and dream bodies. \n\nThose who downplay and dismiss new age spirituality as a \"white woman thing\" are practicing misogyny and hiding it under criticism of race. When society oppresses women, when systemic change is impossible, when the structures of oppression feel immovable, an individualized framework of spiritual empowerment has obvious appeal. For then you don't need to change the entire system, you just need to change your own frequency. \n\nI understand why that's seductive and feels like power. But a movement telling women the reason their material conditions haven't improved is that their thoughts aren't positive enough is not empowering at all.\n\nWhen you look at [the dominant faces of \"Lucky Girl Syndrome,\"](https://hungermag.com/editorial/why-lucky-girl-syndrome-is-tiktoks-newest-toxic-manifestation-trend) they *are* uniformly white, straight, conventionally attractive, and affluent. Their \"manifestation wins\" are the casino jackpot, the brand trip, the Cartier bracelet. All predictable outcomes of existing privilege, just merely rebranded. \n\n## The True Believers\n\nMost believers of manifestation have some relationship with this spectrum of harmless to extractive. But true believers of manifestation take the idea to its logical conclusion, believing they can literally alter reality and that every action that happens to someone, good and bad, is due to their thinking and manifesting of it. This is the hidden cruelty of the law of attraction and manifesting.\n\nFor me, this is where the buck stops. For if your thoughts create your reality—all of it, not just the good parts—then what happens when something terrible occurs? [Cancer survivors did not manifest their cancer](https://www.psychotherapy.net/perspectives/articles/cancer-and-the-secret/), abuse victims are not responsible for the abuse that came into their lives. People in car accidents were not consecrating themselves toward collision.\n\nI worked in a children's hospice. I've sat with children who were dying and with the families who were holding them. The idea that anyone could believe a child manifested their own terminal illness, whether through insufficient positivity, or a karmic contract their soul signed before birth, or through the wrong thought—is repugnant. Nearly everyone has lost a loved one to terminal illness, [including myself](https://brennan.day/loss-and-loss-and-loss-a-eulogy/). Manifestation hands the most vulnerable people in the room a mirror and says, \"this is your fault.\" I cannot think of anything more cruel and less spiritual.\n\nI am someone that believes in God, and I completely understand the frustration and outrage somebody could have thinking a God would allow something so cruel and evil as childhood cancer, and that the \"mystery\" is bullshit. But there is a wide, oceanic distance between wrestling with a universe that allows childhood cancer, and simply believing the child themselves are responsible through manifestation.\n\nThe first is honest. The second is [a spiritual bypass](https://www.psychologytoday.com/us/blog/mindfully-present-fully-alive/201812/manifestation-the-real-deal), a way of immunizing yourself against the full horror of other people's pain by converting their tragedy into a lesson about their own failure of consciousness. The belief system \"simply doesn't give people the space to just be with our genuine and authentic human emotions when life's inevitable and uncontrollable struggles hit.\" Devoted practitioners become terrified that feeling grief or fear or rage will manifest more of the same, instead pushing the feelings down. This toxic positivity is, funnily enough, [physiologically worse for the nervous system](https://theryo.ai/blog/the-psychology-behind-toxic-positivity/) than simply allowing the feelings to move through.\n\nFrom true believers, you will hear sentiments such as \"your souls contracted for this experience\" or \"there’s an energy exchange between abuser and the abused, and if the abused wasn't putting out that kind of energy they wouldn't attract this experience.\" Or that \"your thoughts create your reality, therefore, your victim mentality created this situation.\" It is literally victim blaming.\n\n## An Actual Answer\n\nIf you are somebody in the throes of manifestation, if you're somebody who is desperately trying to conjure a better life for yourself and it isn't working, then I am going to be the person to tell you that it isn't actually your fault. You are trying, and you're trying hard. There are real systematic barriers and harms that we all endure. While we all have the ability to cultivate resiliency and grit—and that's incredibly important to do—but this certainly does not mean we're anywhere close to being on an even playing field.\n\n[The psychology behind manifestation](https://thecampanile.org/2020/10/24/the-psychology-behind-manifestation/) is real, there is research and evidence on how goal visualization can focus attention and prime behaviour. But *directed attention toward your goals* and *your thoughts are the only reason you don't have what you want* is the difference between a tool and an ideology. And ideologies that locate the cause of systemic suffering entirely within individual consciousness are ideologies that protect the system.\n\nYou can cultivate joy and still be structurally disadvantaged. You can practice gratitude and still be owed something by the world. You can hold faith and still be furious. We are full of contradictions and that's perfectly okay.\n\nThe prosperity gospel is manifestation in a megachurch, and it tells the poor that their poverty is a moral and spiritual failing. It is no surprise most believers in manifestation attempt to conjure personal wealth and prosperity instead of bettering others and the world or healing the many systemic horrors—this is the rugged individualism of the American dream where New Thought originated from, after all.\n\nBut the billionaires of our world did not manifest their abhorrent fortunes. They were obtained through exploitation of the working class, full stop. A cursory search into [the Epstein files](https://www.bbc.com/news/articles/cevnmxyy4wjo) demonstrates how unjust and cruel our world can be and continues to be. To put it bluntly and bleakly, no amount of manifesting has stopped human trafficking, indentured servitude, or the widespread abuse known and documented. \n\nDo not add to this cruelty by blaming victims of suffering and horrors, please.\n\nThe universe, if it's anything, is something we're in together. Not alone. Not just vibing toward individual escape from a system none of us designed. We can try, not manifest, to fix the system instead.\n",
      "date_published": "2026-05-19T20:00:00.000Z",
      "tags": [
        "Social Commentary",
        "Spirituality",
        "Gender",
        "New Age",
        "Cultural Appropriation",
        "Health"
      ],
      "author": {
        "name": "Brennan Kenneth Brown",
        "url": "https://brennanbrown.ca",
        "email": "mail@brennanbrown.ca"
      }
    },
    {
      "id": "https://brennan.day/rslopcorecirclejerk-and-the-men-who-are-pro-ai/",
      "url": "https://brennan.day/rslopcorecirclejerk-and-the-men-who-are-pro-ai/",
      "title": "/r/SlopcoreCirclejerk and the Men who are pro-AI",
      "summary": "With the AI bubble finally deflating, what can we learn from the gender gap in genAI enthusiasm? Looking at /r/SlopcoreCirclejerk's culture of contempt, historical Luddite parallels, crypto bro demographics, and why men are drawn to extractive technologies.",
      "content_html": "\nThankfully, [the generative-AI bubble is finally deflating](https://www.theglobeandmail.com/investing/markets/inside-the-market/article-ai-bubble-artificial-intelligence-markets-investing-tech/). [Massive infrastructure spend with dismal returns](https://www.gartner.com/en/newsroom/press-releases/2026-05-05-gartner-says-autonomous-business-and-artificial-intelligence-layoffs-may-create-budget-room-but-do-not-deliver-returns). [Performative layoffs backfiring](https://www.thestateofbrand.com/news/ai-job-cuts-not-improving-returns). The slow dawning that the emperor has very expensive GPUs and nothing much else.\n\nBut the business side of things is just that—business. Bubbles inflate and burst. What interests me is the culture that has grown alongside the market—the believers.\n\nOver the years, a culture has developed on the individual (consumer) level in regards to genAI. [/r/SlopcoreCirclejerk](https://reddit.com/r/slopcorecirclejerk) is one of many examples of this. \n\n## A Subculture of Contempt\n\nThe subreddit is a mocking imitation of anti-AI communities and their language and their grief. When scrolling subreddits like this, I witness a disdain towards those who are against the erosion of humanity. The contempt is evident in posts such as \"[Luddites prove they're fools once again...](https://www.reddit.com/r/SlopcoreCirclejerk/comments/1td9dwy/luddites_prove_theyre_fools_once_again/)\" and \"[AI took away luddie’s hobbies. How sad getting mogged by AI so hard that you need to quit 😭](https://www.reddit.com/r/SlopcoreCirclejerk/comments/1tbzekp/ai_took_away_luddies_hobbies_how_sad_getting/)\". There's a post titled \"[Ragebaiting luddites into karma is easy as fck](https://www.reddit.com/r/SlopcoreCirclejerk/comments/1t9zfaz/ragebaiting_luddites_into_karma_is_easy_as_fck/)\" where users discuss how to provoke anti-AI sentiment, and comments like \"[Luddites are idiots. It's hilarious to falseflag as one of them with a bait AI image and watch them defend it and claim that AI couldn't recreate it.](https://www.reddit.com/r/SlopcoreCirclejerk/comments/1t9zfaz/comment/ol5tgmw/)\". The sentiment extends to personal attacks, as seen in a comment on a post titled \"[\\\"I am speaking from the view of a 15yr old\\\"](https://www.reddit.com/r/SlopcoreCirclejerk/comments/1shwedd/i_am_speaking_from_the_view_of_a_15yr_old/)\" writing, \"[you're not anti AI lil bro, you're a child, go do your homework](https://www.reddit.com/r/SlopcoreCirclejerk/comments/1shwedd/comment/ofg6bvl/)\".\n\n## The Gendering of genAI\n\nWhen I look at any pro-genAI spaces, I have this intuition they are predominantly men. \n\n[A 2026 survey from Data for Progress](https://www.dataforprogress.org/blog/2026/2/27/public-opinion-on-artificial-intelligence-varies-widely-by-age-gender-race-and-frequency-of-use) found that men view genAI favorably by a +16-point margin. Women view it unfavorably by -10 points, a 26-point gap between genders. A [Federal Reserve study published in *Economics Letters*](https://www.sciencedirect.com/science/article/abs/pii/S0165176524002982) found 50% of men have used generative AI compared to 37% of women. [CNBC's 2026 Women at Work survey](https://www.cnbc.com/2026/03/06/gender-gap-in-ai-revealed-in-cnbc-surveymonkey-women-at-work-survey.html) found 69% of men call AI a \"valuable collaborator,\" against 61% of women and found that half of women view genAI use at work as cheating, compared to 43% of men. [Lean In's research](https://leanin.org/research/ai-women-gender-gap-data) found women are 38% more likely than men to have ethical reservations about genAI.\n\nThe [Young Men's Research Project](https://youngmenresearchinitiative.substack.com/p/young-men-and-women-use-ai-differently) asked young people how they feel about AI. \n\nThe most common response among young men: excited.\n\nAmong young women: anxious.\n\n## Luddites\n\nThere is a proactive, hostile aggression towards those who have an emotional, empathetic repulsion towards genAI. People who spend their time making fun of and lambasting those who are against genAI, labelling them \"Luddites\".\n\nUsing that term in a derogatory fashion is amusing. It's supposed to conjure a figure hunched in technophobic darkness, waving a fist at the machine, afraid. A fearful primitive, right? Someone who doesn't understand progress. Someone who belongs in the past.\n\nAnd there are definitely parallels, as [the 19th-century English textile workers and artisans did protest against automated machinery during the Industrial Revolution](https://www.history.com/articles/industrial-revolution-luddites-workers). But while they are stereotyped today as being mindlessly afraid of progress, their original movement was a desperate labour rights fight against factory owners using technology to bypass fair wages and safe working conditions.\n\nIn response, the British government deployed more troops to suppress the Luddites than Napoleon had facing him in the Peninsula. \n\nLuddites were willing to accept mechanization if they shared in its gains. They watched instead as the productivity of their craft, the value of decades of embodied skill, was extracted and redirected upward—always upward—to the merchant class. \n\nWho would be against that?\n\n## Crypto Bros and Conservatism\n\nJust a few years ago, with NFTs and Web3. [Globally, 74% of cryptocurrency investors are men](https://coinlaw.io/men-vs-women-in-crypto-adoption-statistics/). Men are three times more likely than women to collect NFTs. [Only 16% of NFT creators identify as women](https://cointelegraph.com/news/nfts-liberate-imagination-the-gender-gap-that-needs-to-be-addressed). [Only 13% of Web3 founding teams include a woman](https://sifted.eu/articles/web3-gender-gap-brnd). The technology has changed but the demographic hasn't.\n\nObviously, it is also political and partisan. [Republicans hold a net +11 favorable view of AI](https://www.dataforprogress.org/blog/2026/2/27/public-opinion-on-artificial-intelligence-varies-widely-by-age-gender-race-and-frequency-of-use), while Democrats and Independents trend unfavorable. Research from Stony Brook University tracking daily surveys found [Republicans increasing their support for AI at a measurably faster rate than Democrats](https://arxiv.org/pdf/2412.05163), the polarization increasing. [Men are 12 percentage points more likely than women to affiliate with the Republican Party](https://www.pewresearch.org/politics/fact-sheet/party-affiliation-fact-sheet-npors/), according to Pew. \n\nEnthusiasm for genAI, conservative political identity, and maleness are not three separate variables, they're woven deeply together.\n\nThe gender gap of participation can be seen in the culture, the slang (*wen lambo*, *wagmi*, *have fun staying poor*) that characterized crypto's peak has a clear cousin in the hostility of pro-genAI spaces toward skeptics. The in-group treating the technology as identity, and treating those outside as losers who don't get it. As marks. As Luddites.\n\n## Why Are Men Like This?\n\nThe question here, for me, is why? I've written about the [shortcomings of men](https://brennan.day/we-as-men-must-do-more-and-we-must-do-better/), including myself, so my guess is this: men are much more used to, and comfortable with, extracting labour from others and claiming credit for it. Men are more often uncritical or apathetic towards being extractive, focusing more on the personal benefits and upsides being more important than the systemic disadvantages and harm.\n\n[In academic teams, women make up nearly half the workforce but receive authorship credit on only 35% of the papers their teams produce](https://www.ncbi.nlm.nlm.nih.gov/pmc/articles/PMC9352587/). Men self-cite [70% more than women](https://arxiv.org/pdf/1607.00376) and have for 50 years, unchanged. [University of Delaware research found that men are given more credit than women for saying the exact same thing in a meeting](https://www.sciencedaily.com/releases/2017/12/171213130252.htm). In collaborative work, when performance information is ambiguous—when the team succeeded but it's not clear *who* did what—women are consistently rated less competent, less influential, and less leaderly than men who did equivalent work. The ambiguity fills with assumption, and the assumption is always the same.\n\nGenerative AI is, at its core, a machine for manufacturing exactly that ambiguity. You prompt it; it produces. The question of where the value came from—from the billions of images, poems, essays, voices training the model without consent or compensation; from the cultural labour of centuries of human creativity—then becomes officially unanswerable. And in that ambiguity, the credit flows toward the one holding the prompt. Who is holding the prompt? Look at the data.\n\n[Marc Andreessen and Elon Musk have both gone on record saying they practice 'zero' introspection.](https://www.businessinsider.com/marc-andreessen-zero-introspection-debate-2026-3)\n\n> Reinforcing negative neural pathways via therapy or introspection is a recipe for misery. Don’t cut a rut in the road.  \n> — [Elon Musk](https://x.com/elonmusk/status/2035225277085909248?lang=en)\n\nTwo of the most powerful individual actors in the technology industry, together worth trillions of dollars, publicly advertising the fact that they do not examine themselves. That self-knowledge, for them, is a liability.\n\nIt is, thus, unsurprising to see those who are in support of an economy and culture that produces billionaire men who advocate against introspection would lack introspection themselves. Fish cannot see the water.\n\nThe contempt for artistic labour running through pro-genAI spaces is load-bearing. The idea that prompting a model is meaningfully similar to making art—or that the output carries real aesthetic weight—requires a flattening of what art actually is. It requires you to believe that the *product* is what matters, not the centuries of accumulated human struggle, failure, revision, and attention that produced the cultural substrate the model was trained on. The loaf is just flour, and flour is just wheat, and wheat is just a commodity.\n\nThe hand-waving dismissal of the complexity of art, of the centuries of work done in the name of creativity, is imbued here. And the idea that prompting genAI to make art is at all similar to creating art yourself, or that genAI art has aesthetic appeal, fits squarely with my previous thesis on why [conservatives cannot make good art](https://brennan.day/right-wing-conservatives-cannot-make-good-art/)\n\nSo yes, there is the explicit, obvious propaganda of the manosphere and rise of violent misogyny, particularly in younger men and boys of today. But it is an over-simplification to only look at that.\n\nWe have been inundated with centuries of harmful rhetoric and propaganda, of being socialized towards being drawn to power and compartmentalizing in order to blunt the natural emotional response towards being extractive. We are downstream of that. Men have been carefully taught not to examine.\n\n## A Lack of Conclusion\n\nWhile I have pointed out the most egregious examples here, I see generative-AI being used without any disclaimer in many other spaces. I see people who claim to be \"neutral\" or \"thoughtful\" about genAI usage who then go on to vibecode their entire website, or put genAI art on display, or write out entire blog posts dense with genAI tells. As though the reliance and over-usage of these tools has become invisible to these people.\n\nAnd I am someone that does want nuance, that wants productive conversation and dialogue where people can understand the real problems and harms associated with even casual genAI usage. I certainly do not think anyone who has ever used a genAI tool is a bad person or a lost cause.\n\nIf only changing minds were so easy.\n",
      "date_published": "2026-05-18T20:00:00.000Z",
      "tags": [
        "Digital Culture",
        "Social Commentary",
        "AI",
        "technical",
        "political",
        "Gender"
      ],
      "author": {
        "name": "Brennan Kenneth Brown",
        "url": "https://brennanbrown.ca",
        "email": "mail@brennanbrown.ca"
      }
    },
    {
      "id": "https://brennan.day/a-love-letter-to-everything/",
      "url": "https://brennan.day/a-love-letter-to-everything/",
      "title": "A Love Letter to Everything",
      "summary": "My first IndieWeb Carnival entry—the theme is love letters, and I couldn't pick just one thing. A letter to the infrastructure that holds my corner of the internet together, to the strangers who maintain the open-source tools I depend on every day, and to the IndieWeb friends I've met over the past few months. And finally, to curiosity: the embarrassing willingness to fall in love with a static-site generator or a transit system or a protocol nobody's heard of, which I've come to believe is what kept me alive.",
      "content_html": "\nWell, here's my first ever participation in the [IndieWeb Carnival](https://indieweb.org/IndieWeb_Carnival), which is ridiculous since I've had several months to participate by now and I write, like, nearly every day (this is what I mean by bad executive functioning). This month's topic is [love letters](https://hamatti.org/posts/indieweb-carnival-write-a-love-letter/) hosted by [Juha-Matti Santala](https://mastodon.world/@hamatti), which is a wonderful theme.\n\nSo, what am I writing a love letter to? [Rasagy Sharma](https://rasagy.in/sketchnotes/love-letter-to-indiewebclub/) already did a wonderful post on the IndieWeb Club (yet another community participation I haven't gotten around to!) A few months ago, I wrote [a love letter to public transit](https://brennan.day/a-love-letter-to-public-transit/).\n\nI guess I should start with an interesting fact and a confession. There's a construct in psychology called [emophilia](https://www.sciencedirect.com/science/article/abs/pii/S0191886924000114), which is described as falling in love fast and easily. I resonate deeply with this—I feel as though I fall in love with everyone I meet. Not just that, though, when I'm introduced to a new, really good piece of software or service or website, I feel the same! There is so much in the world to care for and deeply appreciate.\n\nMaybe I should lean into that—why only pick one particular thing, anyways?!\n\nSo here's what I've decided: everything. Or at least everything I've been grateful for while I write. Which turns out to be a lot. This essay is going to meander, the way love does. I'm going to name names, thank strangers, gush at infrastructure. A love letter to the invisible labour that holds my little corner of the Internet together, to tools that are extensions of thought, and to the people who reached out across the void and made a neighbourhood.\n\n## My Hosting\n\nLet me start with the most dry, nerdy thing possible: infrastructure. Hurray! Despite all of its flaws, I'm deeply appreciative of [Netlify](https://netlify.com), where I'm currently hosting 60 projects (I can host 500 in total simultaneously, holy smokes), using around 100GB of bandwidth monthly, along with millions of web requests, dozens of forms, and hours of build time. All for free.\n\nAnybody in tech (or elsewhere, really) will tell you nothing is free, and that you are the product, etc., but I am certainly not looking a gift horse in the mouth. I'm sure the day will come when my legacy plan will be null and void, and I'll have to migrate dozens of my projects and pay a pretty penny in the process. But today is not that day!\n\n## Unix-like Operating Systems Maintainers\n\nI began using [**CrunchBang #!**](https://crunchbang.org/) over fifteen years ago when the desktop [I bought off of Kijiji for $35 mysteriously could no longer boot up Windows](https://blog.brennanbrown.ca/my-coding-journey-ea2463c7856f) in any capacity. I am so grateful for that.\n\nI love the terminal, the cursor slow-blinking at you like a cat. I was a teenager when I first booted Linux off a USB drive into a world more mine. The desktop was spare and dark. A panel at the top. Conky stats glowing in the corner, a vital-signs readout for the machine itself. The fan hummed.\n\nWhat I've only come to understand slowly, over fifteen years of troubleshooting and mailing lists and forum rabbit holes is that this world is maintained by only a handful of humans. The Linux kernel has thousands of contributors in its git history, but the critical path runs through a much smaller number of people. Subsystem maintainers who review patches, catch regressions, and shepherd code. Greg Kroah-Hartman, for example, maintains the stable kernel branch that most of the world's production servers actually run alone.\n\nThe same is true of the BSD family—FreeBSD, OpenBSD, NetBSD, each stewarded by volunteer teams who move with care. The unglamorous work that everything else depends on.\n\nI am so grateful for the hours and days of troubleshooting I've struggled through all these years. I have learned so many valuable skills, both technical and non-technical. Patience, the importance of free and open sharing, coming to realize expertise isn't a credential but a practice. \n\nCountless tonnes of e-waste are saved by the ability to boot a USB of a lightweight distro onto an otherwise abandoned machine. Every time I `ssh` into a server, every time a hospital runs its imaging software, every time a spacecraft sends telemetry across the solar system—it's all running on this gift. A decades-long gift from strangers who decided the commons mattered. You build for the community, not for yourself. The work is the offering. Miigwech.\n\n## Independent Project Maintainers\n\nIf an operating system is the land, software is the shelter people build on it. And shelter, it turns out, is also largely held together by volunteers. People who decided that a thing should exist and kept deciding that year after year.\n\nI'm grateful that my IDE of choice, [**Sublime Text**](https://www.sublimetext.com/), still exists as it has for the past decade. No genAI features in sight. Every tool is racing to stuff a chatbot into its sidebar, and the restraint of Sublime Text is wonderful. It opens instantly. It stays out of your way. It trusts you to know what you're doing. \n\nAlthough I've never used the Zed IDE, I'm also grateful for [**Gram**](https://gram-editor.com/), as an example of a no-genAI fork that was created when Zed introduced genAI features. There are those who care enough to fork the project, strip out the parts they found objectionable, and maintain the alternative. You can view many [other examples here](https://codeberg.org/small-hack/open-slopware). \n\n[**omg.lol**](https://home.omg.lol/) is something in particular I'm incredibly grateful for. [Adam Newbold](https://neatnik.net/) is single-handedly responsible for creating the infrastructure for a smaller, human, kind web. My [original article](https://blog.brennanbrown.ca/omg-lol-is-the-internet-we-need-right-now-3538199d5dea?sk=e3121e980391c9fa04ba7f77ae6a011c) covering the platform is my most popular post on Medium ever.\n\nIf it wasn't for omg.lol, I wouldn't be here writing to you right now, because I only began my [brennan.day](https://brennan.day) project because I started a blog on [weblog.lol](https://weblog.lol/), omg.lol's blogging service, and found it didn't have enough functionality for me. And so I moved to building my own website from scratch instead. In the past, I had always been far too intimidated to start a site like this because there are so many moving parts. But it's really come together after months of tinkering.\n\nOf course, that leads me to [**Eleventy**](https://www.11ty.dev/), which is the static-site generator powering this blog. What I love about it is that every piece of this site is something I built. On the homepage, a `postGraph` shortcode renders a heatmap of every post by day—a filled square for each one—the shape of years of writing made visible at a glance. A `lastModified` filter reads the git history at build time to show when each page was actually last edited, not just published. `EleventyFetch` reaches out to the omg.lol API on every build, pulls down my latest status updates, and caches them for an hour—live data added in at compile time, no database required (never databases!). At the bottom of every post, a `relatedPosts` filter finds others that share tags, building a map of connection across my writing. \n\nNext, I'm grateful for [**GitLab**](https://gitlab.com/) for [hosting the code repository](https://gitlab.com/brennankbrown/brennan.day) of this blog. Now, the platform does have a [permissive genAI policy](https://gitlab.com/rluna-gitlab/gitlab-ce/-/blob/master/.ai/) and there are far more ethical alternatives, such as [**Codeberg**](https://codeberg.org/) or [**Forgejo**](https://codeberg.org/forgejo/forgejo), but compared to [GitHub](https://github.com/brennanbrown/brennanbrown#%EF%B8%8F-choose-a-better-developer-platform)? It is certainly the lesser of two evils, and I'm all about [software harm reduction](https://brennan.day/software-harm-reduction/), not radical absolutism (but I support you if you are!)\n\nUsing Netlify, Eleventy, and GitLab in conjunction with one another is what allows me [functionality like comments](https://brennan.day/building-an-indieauth-comment-system-for-your-static-site/)! Which I think is really cool.\n\nI'm also deeply grateful for [**Mastodon**](https://joinmastodon.org). I've never used a microblogging platform before, avoiding Twitter for its entire existence (thankfully). But fedi has been such a delight, from the cat photos to the photography and art to the interesting articles I wouldn't have otherwise known about. Of course, I am using omg.lol's [social.lol](https://social.lol/@brennan) instance!\n\nMastodon and the broader fediverse are federated at the *protocol* level. There is no central company holding a relay that all traffic passes through. Compare this to Bluesky's AT Protocol, where a central relay operated by Bluesky PBC is required for content discovery. The infrastructure dependency remains. With ActivityPub, if Mastodon the company vanished tomorrow, every server would keep federating with every other server. The protocol is the commons. The network is the commons. \n\nFinally, of course, I need to thank [Buster Benson](https://busterbenson.com/) and [Kellianne](https://www.instagram.com/kellianne/) for making and maintaining [**750words.com**](https://750words.com), where I wrote the first draft of this blog post and every other blog post on this site. If I didn't find this website all the way back in 2011, I absolutely would not be writing, and I would not have over a million words written. It's no exaggeration to say I owe this little journal site my entire life.\n\n## Friends\n\nOver the past few months of my IndieWeb journey, I've encountered [so many wonderful people](https://brennan.day/blogroll/)! I want to give a few specific people a shout-out here.\n\nTo start, [**Coyote**](https://osteophage.neocities.org/) introduced me to the [32-bit Café forum](https://discourse.32bit.cafe/), which is a wonderful community of creatives and webweavers. Coyote writes really interesting, smart essays on the IndieWeb along with many other topics. Please go have a read!\n\n[**Melo**](https://eunoia.sayitditto.net/) is a young, talented sysadmin and programmer responsible for [superlove](https://superlove.sayitditto.net/), one of the only forks of AO3 in existence, along with a multitude of equally impressive projects.\n\n[**Brendan**](https://theonlyblogever.com/) is a blogger (with the best domain ever) who has encouraged me to [write in French more](https://theonlyblogever.com/blog/2026/blogue3.html), and vice versa! Chu ben reconnaissant d'avoir un chum blogueur français.\n\n[**P.J.M. / HisVirusness**](https://hisvirusness.com/) is a multimedia artist who has an extremely interesting \"rolling-release neuro-zine\" that I love reading.\n\n[**Mike**](https://shellsharks.com) is a security researcher who runs the newsletter [Scrolls](https://shellsharks.com/scrolls/), which is always chock full of interesting links and people, and one of the most useful nexus points for the IndieWeb I've found so far.\n\n[**Adam**](https://www.adamdjbrett.com/) is an academic doing work I find really interesting and important in both religion and Indigenous law, and is also an 11ty developer. That last part is a total understatement — I am pretty sure Adam has created and maintained [more 11ty websites](https://www.11ty.dev/authors/) than any other person on Earth. (38 and counting!)\n\n[**Alvan**](https://rahim.li/) is a programmer and FOSS enthusiast who, impressively, created [his own blogging engine](https://git.sr.ht/%7Ealvanrahimli/tanager). Like me, he's trying his hand at his [own radio show](https://latetopartyfm.omg.lol/) which you should check out!\n\n[**Candy**](https://candyether.space) is a CompSci student and artist that draws an adorable [comic about slimes, toasters, and bugs](https://candyether.space/comic/) and also works on various Balatro mods and artwork. I very much enjoy the aesthetic of his site!\n\n[**Vick**](https://backyardtinker.bearblog.dev/) is a tinkerer and pixel artist who has made [various 88x31 badges](https://backyardtinker.bearblog.dev/cataminated/) that I adore (and some I use on my site!). They're the first person who reached out and asked if they could put me on their [neighbourhood/friends page](https://backyardtinker.bearblog.dev/neighbours-friends/) which I was really touched by.\n\n[**James**](https://jamesg.blog/) is someone I consider very knowledgeable on the IndieWeb — his list of [website ideas](https://jamesg.blog/2024/02/19/personal-website-ideas) being one of the first resources I stumbled upon and started implementing. He was also one of the first people who reached out to respond to my article [How a Taylor Swift Lyric Gave Me an Existential Crisis](https://brennan.day/how-a-taylor-swift-lyric-gave-me-an-existential-crisis/), being a Swiftie himself ♡ He has an IndieWeb podcast called [Wonders of Webweaving](https://web-weaving.jamesg.blog/) that I absolutely recommend!\n\nI am so grateful for those who have reached out and made me feel like I'm part of a community. I am bad at being proactively social myself, and I really hope to get to know more of you better!\n\n## The Life I've Been Able to Live\n\nI have written about [the Moon](https://brennan.day/the-moon/) and what it means that we went back to her, about [twelve thousand generations](https://brennan.day/12-000-generations-on-deep-time-grief-and-the-body/) of homo sapiens who did not know I was coming and made room for me anyway. I have written about [Long COVID](https://brennan.day/clean-air-long-covid-is-a-catastrophic-public-policy-failure/) and the bureaucratic wall of disability denial, about [the three times the world nearly ended](https://brennan.day/the-three-times-the-world-nearly-ended/) and the ordinary people who chose correctly in the dark. I have written about [Sadako Sasaki folding 1,450 paper cranes](https://brennan.day/a-thousand-cranes-why-i-write-every-day/) in a hospital ward, about [Bon Iver retiring](https://brennan.day/i-started-listening-to-justin-vernon-in-grade-school-now-he-s-retiring-as-i-turn-30/) as I turned thirty, about [Japanese writers named Banana](https://brennan.day/the-banana-mystery/). About [God](https://brennan.day/how-and-why-i-believe-in-god-the-ballad-of-tragic-theism/), who I believe is infinite and makes creative mistakes and grieves them. About my [Métis ancestors](https://brennan.day/where-is-the-indigenous-cultural-revolution/) who carried a language born from Cree verbs and French nouns. About what it means to [inherit a chain with links already missing](https://brennan.day/what-we-lose-with-cultural-extinction-the-red-thread-cut/).\n\nI have written about the [prairie](https://brennan.day/grain-elevator-country/) unrolling through a car window at ninety kilometers an hour, grain elevators like punctuation marks between nothing and nothing. I've been interviewed about [chess and journal writing and strawberries](https://lazybea.rs/ovr-058/). I've written about [boredom](https://brennan.day/fermenting-boredom/) as fermenting agent, about [schizoid personality disorder](https://brennan.day/being-a-21st-century-schizoid-man/) and a rich interior life mistaken for coldness, about [depression as preparation](https://brennan.day/30-finding-my-footing/) rather than delay. I have written about [what men must do differently](https://brennan.day/we-as-men-must-do-more-and-we-must-do-better/) and admitted, clearly, that I have not always done it. About [grief that has no clean end](https://brennan.day/loss-and-loss-and-loss-a-eulogy/). About the names I write down so they don't disappear.\n\nI snuck off school grounds to write in a back alley. [I shoplifted Ginsberg and Neruda from Chapters](https://brennan.day/poetry-saved-my-life/). I am alive and writing today and there were years when I was not sure that would be true.\n\nWhat I keep trying to say in every essay and every poem and every [technical walkthrough that turns out to also be about something else](https://brennan.day/downgrading-to-macos-catalina-a-sermon-on-obsolescence/)—is that curiosity saved my life. \n\nNot intelligence. Not discipline. Not talent. Curiosity. The embarrassing willingness to discover and be wrong, to fall in love with a static site generator or a transit system or a protocol nobody's heard of. To stay up until three in the morning reading about copyleft licensing or Elinor Ostrom's Nobel Prize or the water cycle on Mars or the neuroscience of narrative. To care about things that don't care back.\n\nThe commons are real. The [mycorrhizal network](https://brennan.day/wont-you-be-my-neighbour/) is real. The underground exchange of resources between organisms that have no reason to cooperate but do. The [tragedy of the commons was never inevitable](https://brennan.day/good-standard-work-creating-the-commons/); Hardin was wrong, Ostrom proved it, the IndieWeb is proving it every day. The [Long Web](https://brennan.day/how-are-we-preparing-for-the-long-web/) is possible. People can build things that outlast the platforms that birth them. We are doing it right now.\n\nGratitude is not the same as acceptance. You can be [deeply, wrenchingly grateful](https://brennan.day/the-blogging-uebermensch-or-being-the-luckiest-person-on-earth/) for the life you have and still insist the world should be different and better.\n\n[Writing is medicine](https://brennan.day/what-can-i-offer-the-shell/). Neuroscience is catching up. Poetry activates the dopaminergic reward system. Story creates brain synchrony between teller and listener. When I write to you across this distance—you who I may never meet, who found this page through a search engine or a blogroll or a Mastodon boost—something real passes between us. Something that did not exist before. \n\nI am so grateful. I am so grateful for every stranger who read something I wrote and sent a reply into the void. For you, reading this, right now. Whoever you are. Wherever this finds you.\n\nThe world is on fire and the fediverse is full of cat photos. Somewhere a grain elevator is standing in Saskatchewan in the late-afternoon light and nobody is looking at it and it doesn't care and it's beautiful. I have been given—I don't know by what, by whom exactly—I have been given a mind to notice all this. Hands to write it down. A corner of the internet to put it in. I know how lucky that is. I hope I use it well enough to deserve it.\n",
      "date_published": "2026-05-17T20:00:00.000Z",
      "tags": [
        "personal essay",
        "IndieWeb",
        "community",
        "writing",
        "blogging",
        "internet",
        "open source"
      ],
      "author": {
        "name": "Brennan Kenneth Brown",
        "url": "https://brennanbrown.ca",
        "email": "mail@brennanbrown.ca"
      }
    },
    {
      "id": "https://brennan.day/cleaning-house-refactoring-my-eleventy-config-into-modules/",
      "url": "https://brennan.day/cleaning-house-refactoring-my-eleventy-config-into-modules/",
      "title": "Cleaning House: Refactoring My Eleventy Config Into Modules",
      "summary": "How I decomposed an 866-line .eleventy.js monolith into four focused modules, fixed some lurking bugs, and eliminated dead CSS and dead dependencies along the way",
      "content_html": "\nAfter I began tinkering with [DX (developer experience)](https://brennan.day/i-made-my-eleventy-build-5-faster-with-five-changes/) a few days ago, I knew that was only the beginning. As you can see in my [changelog](https://brennan.day/changelog), I add new functionality to my site often. A lot of that functionality lives in the titular `.eleventy.js`. This script had become more monsterous than bloated, sitting at 866 lines in the single file. Any time I wanted to touch a filter or tweak a collection, I was scrolling through a wall of code to find the right spot. \n\nSo, I finally did what I should have done months ago: It's refactoring-into-modules time!\n\nThis post is a walkthrough of how I broke things apart, what bugs I found lurking in the process, and cleanups that were long overdue. The goal was to improve the structure without changing any behaviour or the site for the end-user.\n\n## The Before State\n\nHere's a rough sketch of what `.eleventy.js` looked like before:\n\n```javascript\n// .eleventy.js was 866 lines, with everything in one place\nconst pluginRss = require(\"@11ty/eleventy-plugin-rss\");\n// ... 15 more require()s\n\nmodule.exports = async function(eleventyConfig) {\n  // Plugins\n  eleventyConfig.addPlugin(pluginRss);\n  // ...blah blah blah\n\n  // ~30 filters, each defined inline\n  eleventyConfig.addFilter(\"assetHash\", (assetPath) => { /* 20 lines */ });\n  eleventyConfig.addFilter(\"readableDate\", (dateObj) => { /* ... */ });\n  eleventyConfig.addFilter(\"getWebmentionsForUrl\", (webmentions, url) => { /* 30 lines */ });\n  // ...\n\n  // Async shortcodes\n  eleventyConfig.addAsyncShortcode(\"thumbnail\", async function(...) { /* 40 lines */ });\n  eleventyConfig.addShortcode(\"postGraph\", (postsCollection) => { /* 80 lines + 110 lines of inline CSS */ });\n\n  // Collections\n  eleventyConfig.addCollection(\"posts\", function(collectionApi) { /* ... */ });\n  // ...\n\n  // markdown-it setup with 6 plugins + custom link rewriting\n  const markdownLibrary = markdownIt({ /* ... */ })\n    .use(markdownItAnchor, { /* ... */ })\n    // ...\n  eleventyConfig.setLibrary(\"md\", markdownLibrary);\n\n  return { /* config */ };\n};\n```\n\nIt worked great! Which was the problem, it was \"good enough\" for long enough that it just kept growing and growing.\n\n## The Plan: a `config/` Directory\n\nThe split was straightforward. Everything in `.eleventy.js` fell naturally into four groups:\n\n- **Filters** — 30 custom Nunjucks filters for dates, content, webmentions, etc.\n- **Shortcodes** — `year`, `thumbnail`, and `postGraph`\n- **Collections** — `posts`, `notes`, `pages`, and `tagList`\n- **Markdown** — markdown-it with all its plugins and the custom link-rewriting rule\n\nEach group becomes its own file that exports a single function accepting `eleventyConfig`. The main file would just call the config scripts in order.\n\n## `config/filters.js`\n\nThe filters module is the biggest one. It starts with all its own `require()` statements and a local cache map, then exports one function:\n\n```javascript\n// config/filters.js\nconst { DateTime } = require(\"luxon\");\nconst path = require(\"path\");\nconst crypto = require(\"crypto\");\nconst fs = require(\"fs\");\nconst { execSync } = require(\"child_process\");\nconst commentsData = require(\"../src/_data/comments.js\");\n\nconst ROOT_DIR = path.join(__dirname, \"..\");\n\nconst _assetHashCache = new Map();\n\nmodule.exports = function(eleventyConfig) {\n  eleventyConfig.addFilter(\"assetHash\", (assetPath) => {\n    if (_assetHashCache.has(assetPath)) {\n      return _assetHashCache.get(assetPath);\n    }\n    // ... hash computation\n  });\n\n  eleventyConfig.addFilter(\"readableDate\", (dateObj) => {\n    return DateTime.fromJSDate(dateObj, { zone: \"utc\" })\n      .toFormat(\"dd LLLL yyyy\");\n  });\n\n  // ... all 30 filters\n};\n```\n\nOne important detail: the filters in `.eleventy.js` must be registered *after* the plugins, because some of them override defaults set by the RSS plugin (the date filters in particular). The module call order in the orchestrator preserves this.\n\n## `config/shortcodes.js`\n\nThe shortcodes module had a pre-existing problem I fixed while moving things, it turned out I never moved the embedded 110 lines of CSS from the `postGraph` shortcode to my stylesheets. Whoops!\n\n```javascript\n// Before: CSS string injected into every page render\neleventyConfig.addShortcode(\"postGraph\", (postsCollection) => {\n  const styleSheet = `<style>\n    .epg { color: var(--text); margin: 20px 0; }\n    .epg__squares { display: grid; grid-template-rows: repeat(7, 1fr); ... }\n    .epg__squares > :nth-child(7n + 1) .epg__hasPost { background: var(--nav-red); }\n    /* ... 100 more lines ... */\n  </style>`;\n\n  return styleSheet + buildGraphHTML(postsCollection);\n});\n```\n\nThe fix was to move all of that into `08-features.css` and have the shortcode return only HTML:\n\n```javascript\n// After: shortcode only builds HTML, CSS lives in the stylesheet\nmodule.exports = function(eleventyConfig) {\n  eleventyConfig.addShortcode(\"postGraph\", (postsCollection) => {\n    // HTML-only output, no inline <style>\n    return buildGraphHTML(postsCollection);\n  });\n\n  eleventyConfig.addAsyncShortcode(\"thumbnail\", async function(\n    imagePath, alt, width = 400, height = 225, loading = \"lazy\", fetchpriority = \"\"\n  ) {\n    // @11ty/eleventy-img handles WebP conversion and srcset generation\n    const metadata = await Image(fullPath, {\n      widths: [width],\n      formats: [\"webp\", \"jpeg\"],\n      outputDir: path.join(ROOT_DIR, \"_site/assets/thumbnails/\"),\n      urlPath: \"/assets/thumbnails/\"\n    });\n    // ...\n  });\n};\n```\n\nThe EPG styles now live where they belong, next to the other feature CSS.\n\n## `config/collections.js`\n\nCollections were the simplest to extract, just four definitions:\n\n```javascript\n// config/collections.js\nmodule.exports = function(eleventyConfig) {\n  eleventyConfig.addCollection(\"posts\", function(collectionApi) {\n    return collectionApi.getFilteredByGlob(\"src/posts/**/*.md\")\n      .sort((a, b) => {\n        const dateA = a.data.date || a.date;\n        const dateB = b.data.date || b.date;\n        return new Date(dateB) - new Date(dateA);\n      });\n  });\n\n  eleventyConfig.addCollection(\"tagList\", function(collection) {\n    const tagSet = new Set();\n    collection.getAll().forEach(item => {\n      (item.data.tags || []).forEach(tag => tagSet.add(tag));\n    });\n    return [...tagSet].filter(tag =>\n      ![\"posts\", \"notes\", \"pages\", \"all\"].includes(tag)\n    ).sort();\n  });\n\n  // notes and pages collections follow the same pattern\n};\n```\n\n## `config/markdown.js`\n\nThe markdown module configures markdown-it with all its plugins, plus a custom rule that rewrites `.md` links to clean URL slugs (so internal wikilinks work in both the editor and the browser):\n\n```javascript\n// config/markdown.js\nconst markdownIt = require(\"markdown-it\");\nconst markdownItAnchor = require(\"markdown-it-anchor\");\n// ... other plugin requires\n\nfunction rewriteMarkdownLinks(md) {\n  const defaultRender = md.renderer.rules.link_open ||\n    function(tokens, idx, options, env, self) {\n      return self.renderToken(tokens, idx, options);\n    };\n\n  md.renderer.rules.link_open = function(tokens, idx, options, env, self) {\n    const hrefIndex = tokens[idx].attrIndex(\"href\");\n    if (hrefIndex >= 0) {\n      const href = tokens[idx].attrs[hrefIndex][1];\n      if (href.endsWith(\".md\")) {\n        // /posts/2026-01-10-some-post.md → /some-post/\n        const slug = path.basename(href, \".md\")\n          .replace(/^\\d{4}-\\d{2}-\\d{2}-/, \"\")\n          .toLowerCase().replace(/\\s+/g, \"-\");\n        tokens[idx].attrs[hrefIndex][1] = `/${slug}/`;\n      }\n    }\n    return defaultRender(tokens, idx, options, env, self);\n  };\n}\n\nmodule.exports = function(eleventyConfig) {\n  const markdownLibrary = markdownIt({ html: true, linkify: true, typographer: true })\n    .use(markdownItAnchor, { permalink: markdownItAnchor.permalink.ariaHidden({ placement: \"after\" }) })\n    .use(emoji)\n    .use(markdownItKatex)\n    .use(markdownItFootnote)\n    .use(markdownItTaskLists, { label: true })\n    .use(markdownItDeflist);\n\n  rewriteMarkdownLinks(markdownLibrary);\n  eleventyConfig.setLibrary(\"md\", markdownLibrary);\n\n  eleventyConfig.addFilter(\"markdown\", (string) =>\n    markdownLibrary.render(string || \"\")\n  );\n};\n```\n\n## The Slim Orchestrator\n\nAfter all four modules were extracted, `.eleventy.js` collapsed from 866 lines down to 117. Hurray!\n\n```javascript\nrequire(\"dotenv\").config();\nconst EleventyFetch = require(\"@11ty/eleventy-fetch\");\nconst pluginRss = require(\"@11ty/eleventy-plugin-rss\");\nconst syntaxHighlight = require(\"@11ty/eleventy-plugin-syntaxhighlight\");\n\nmodule.exports = async function(eleventyConfig) {\n  const faModule = await import(\"@11ty/font-awesome/plugin.js\");\n  const pluginFontAwesome = faModule.default || faModule;\n\n  eleventyConfig.addPlugin(pluginRss);\n  eleventyConfig.addPlugin(syntaxHighlight);\n  eleventyConfig.addPlugin(pluginFontAwesome);\n\n  eleventyConfig.addGlobalData(\"statuslog\", async () => { /* omg.lol fetch */ });\n\n  eleventyConfig.addPassthroughCopy(\"src/assets/css\");\n  // ... other passthroughs and watch targets\n\n  // Filters must come after plugins (some override RSS plugin defaults)\n  require(\"./config/filters.js\")(eleventyConfig);\n  require(\"./config/markdown.js\")(eleventyConfig);\n  require(\"./config/shortcodes.js\")(eleventyConfig);\n  require(\"./config/collections.js\")(eleventyConfig);\n\n  eleventyConfig.ignores.add(\"src/drafts/**\");\n\n  return {\n    templateFormats: [\"md\", \"njk\", \"html\", \"liquid\"],\n    markdownTemplateEngine: \"njk\",\n    htmlTemplateEngine: \"njk\",\n    dir: { input: \"src\", includes: \"_includes\", layouts: \"_includes/layouts\",\n           data: \"_data\", output: \"_site\" }\n  };\n};\n```\n\nI love looking at this now. The FontAwesome plugin uses a dynamic `import()` because it's an ES module, while everything else is CommonJS, a quirk of Eleventy v3's transition period. The `require()` calls for the config modules are synchronous, which is fine since they just call registration functions.\n\n## Bugs Found Along the Way\n\nThe best part of a refactor is what crawls out from under the furniture, of course. The true refactoring is the bugs we found along the way.\n\n### The April Fools Flag That Never Turned Off\n\nWhile reading through `base.njk` I spotted:\n\n```javascript\n// Before: this ran on every page visit\nconst isAprilFools = new Date().getMonth() === 3 && new Date().getDate() === 1;\nconst isDebug = true; // Temporary debug flag\nif (isAprilFools || isDebug) {\n  loadAprilFoolsScript();\n}\n```\n\nThe `isDebug = true` flag was clearly meant to be temporary. Fixed it by simply removing the `isDebug` line and letting `isAprilFools` do its job alone.\n\n### `require()` Inside a Hot Loop\n\nThe `commentCount` filter was doing something expensive on every call:\n\n```javascript\n// Before: require() called thousands of times during a build\neleventyConfig.addFilter(\"commentCount\", (postUrl) => {\n  const commentsData = require(\"./src/_data/comments.js\"); // ← inside the filter!\n  return (commentsData[postUrl] || []).length;\n});\n```\n\nNode.js does cache `require()` calls, but the cache lookup still happens on every invocation, and it's sloppy. The fix is to hoist the `require()` to the top of the file so it runs exactly once:\n\n```javascript\n// After: loaded once, referenced many times\nconst commentsData = require(\"../src/_data/comments.js\");\n\nmodule.exports = function(eleventyConfig) {\n  eleventyConfig.addFilter(\"commentCount\", (postUrl) => {\n    return (commentsData[postUrl] || []).length;\n  });\n};\n```\n\n### A CSS Variable That Disagreed With Itself\n\nI found that `--panel` had two different values in the codebase:\n\n```css\n/* 01-variables.css — what the stylesheet said */\n:root {\n  --panel: #f9f5d7;\n}\n\n/* base.njk critical inline CSS — what loaded first */\n:root {\n  --panel: #f2e5bc;\n}\n```\n\nSince the external stylesheet loads *after* the inline critical CSS, `#f9f5d7` was winning at render time. But during initial paint, `#f2e5bc` was used. Every page had a brief flash on the header and panel backgrounds before the stylesheet loaded. `#f2e5bc` is the correct Gruvbox `bg0_s` panel colour, so I updated `01-variables.css` to match.\n\nThis is more of a fix in principle, since both colours are just, uh, white.\n\n### A 329-Line Dead File\n\nI also found that I still had `src/assets/css/critical.css`, which was the original source for the inline critical CSS block in `base.njk`, but the two diverged over time and only the inline version is used. Deleted it.\n\n## Extracting More Inline `<style>` Blocks\n\nWhile I was in the zone after fixing `postGraph`, I noticed `comments.njk` had the same problem: 261 lines of `<style>` injected into every post page that had comments.\n\nShortcodes/partials outputting CSS alongside its HTML work. But it means every page using that component carries the full CSS payload inline rather than getting it from a cached, shared stylesheet.\n\nAll the comment-specific classes (`.comments-section`, `.comment-header`, `.btn-reply`, `.reply-form-container`, etc.) went into `08-features.css`. The classes that were already covered by `10-utilities.css` (`.btn`, `.btn-primary`) and `06-forms.css` (`.form-group`) were dropped from the extracted CSS.\n\n## Dependency Cleanup\n\nTwo npm packages had been dead for a while:\n\n**`@fortawesome/fontawesome-free`** wasn't needed, as I migrated to `@11ty/font-awesome` (the SVG plugin) back in January. The old package stuck around, along with its `fontawesome.css` and `fontawesome-all.css` files sitting in `src/assets/css/`. Those files were still being passthrough-copied to `_site` on every build. Removed the package (`npm uninstall`), deleted the two CSS files, and freed up 54 packages and ~200KB of font data from the output. Yay space-saving!\n\n**`chart.js`** was listed in `dependencies`, but the charts page loads it from a CDN:\n\n{% raw %}\n```html\n<!-- src/pages/charts.md -->\n<script src=\"https://cdn.jsdelivr.net/npm/chart.js\"></script>\n<script>\n  window.blogStats = {{ charts.generate(collections) | dump | safe }};\n</script>\n```\n{% endraw %}\n\nThe npm package was never `require()`d anywhere in the build. Removed it.\n\n## The Result\n\nThe project structure now looks like this:\n\n```\nbrennan.day/\n├── .eleventy.js           # 117 lines, plugins, global data, passthrough\n├── config/\n│   ├── filters.js         # All 30 custom Nunjucks filters\n│   ├── shortcodes.js      # year, thumbnail, postGraph\n│   ├── collections.js     # posts, notes, pages, tagList\n│   └── markdown.js        # markdown-it + plugins + link rewriting\n└── src/\n    └── ...\n```\n\nI made sure my local dev server rebuilt at each step. 421 files and no errors. \n\n## What I Learned\n\n1. **Follow the shape of the data.** There's no need to reinvent the wheel, or in this case, the model structure. Filters, shortcodes, collections, and markdown are the four things Eleventy actually has. The natural groupings were already there, I just needed to honour them with separate files.\n2. **Refactoring is a great time to audit.** When you're reading every line carefully to move it, you actually *read* it. I found the April Fools bug, the `require()` in a hot loop, the dead CSS file, and the colour variable mismatch. The refactoring forced me to look at my code instead of scrolling past it, which is what I typically do for my own sanity.\n3. **Small self-contained modules are easier to reason about.** When I want to add a new filter now, I open `config/filters.js`. I don't have a monolith file with markdown configuration and collection definitions, scrolling to find where I want to add something. The file I need is obvious from the name.\n4. **Inline CSS in shortcodes and partials is an anti-pattern.** It feels convenient, but inline CSS conjures dark demons (I think this is what anti-pattern means), and also means the same CSS is embedded in every page that uses the component, it bypasses the browser's stylesheet cache, plus it's invisible to anyone reading the stylesheet files. The CSS belongs in the stylesheet. Always. To stave off the demons.\n\nThe site works as it did before. It's just a little easier for me to work with now.\n\n## Postscript: A Gotcha That Bit Me While Writing This Post\n\nAfter writing the post above, the dev server threw a build error:\n\n```\n[11ty] ./src/pages/charts.md contains a circular reference\n       (using collections) to its own templateContent.\n```\n\nThis is an issue I've had before: the culprit turned out to be a code example inside this very post! Since `markdownTemplateEngine: \"njk\"` is set in the Eleventy config, Nunjucks processes every `.md` file **before** the markdown renderer runs. Nunjucks expressions inside backtick code blocks are still executed, not protected by markdown fencing at all.\n\nThe code block example was the Nunjucks expression that called `charts.generate(collections)`. Nunjucks actually ran it. That call accessed `collections`, which needed `charts.md`'s `templateContent`, which needed `charts.md` to finish building first. Circular!\n\n{% raw %}The fix was wrapping the offending code block in `{% raw %}` and `{% endraw %}` tags. Those tell Nunjucks to pass the content through as literal text without evaluating it, so the expression appears in the rendered post as code rather than being executed.\n\nIf you write technical posts about Eleventy, wrap every code example containing `{{ }}` or `{% %}` in raw tags. The backticks (like the goggles) do nothing to stop the template engine.{% endraw %}\n",
      "date_published": "2026-05-15T20:00:00.000Z",
      "tags": [
        "eleventy",
        "javascript",
        "technical",
        "web development"
      ],
      "author": {
        "name": "Brennan Kenneth Brown",
        "url": "https://brennanbrown.ca",
        "email": "mail@brennanbrown.ca"
      }
    },
    {
      "id": "https://brennan.day/on-being-a-river/",
      "url": "https://brennan.day/on-being-a-river/",
      "title": "On Being a River",
      "summary": "Sixty thousand miles of blood vessels run inside each of us, more than twice around the Earth. 330 billion cells are replaced every single day. Humanity has always built civilization beside rivers because we are rivers. Always in motion, never stepping into the same current twice, carrying cells that live only days alongside neurons that will last precisely as long as we do.",
      "content_html": "\nHumanity has always existed by the river. The Nile gave Egyptian civilization life, annual flooding depositing rich black silt across the delta as a calendar of abundance. [Mesopotamia](https://www.britannica.com/place/Tigris-Euphrates-river-system) translates to *the land between rivers* in Greek, rising from the Tigris and Euphrates, two bodies of water running parallel through the heart of what would become Iraq and Syria and Turkey, feeding the civilization that gave us writing and the wheel and the city.\n\nThe [Indus River Valley](https://courses.lumenlearning.com/suny-hccc-worldcivilization/chapter/river-valley-civilizations/) nourished people in what is now modern-day Pakistan and India. Grid-planned cities with sewer systems and running water thousands of years ago, more sophisticated than anything in Europe for millennia. The Yellow River, the Huang He, turned the plains of northern China gold. \n\nHumanity has always been something the river built around us.\n\nFresh, running water gives us life. Drinking, fishing, irrigation, the turning of grain mills, hydroelectric power, trade routes before roads. It gives us borders and it gives us bridges. Running water gives us the spiritual cleansing of mikveh, baptism, the sacred bath. I have written much about the Red River and the Assiniboine River, converging at my birthplace in the heart of the continent—the Forks where Winnipeg now stands—and of the Bow River in Mohkínstsis where I lived for twenty years, running clear and cold off the Rockies through the centre of the prairie city.\n\nPerhaps we are drawn to rivers because we, too, are rivers. Think of all the veins and arteries and capillaries within you right now. If you pulled every blood vessel from your body and laid them end to end, they would [stretch approximately 60,000 miles](https://www.texasvascular.com/blog/how-long-are-your-blood-vessels), more than twice around the circumference of the Earth. [Sixty thousand miles of river inside you](https://my.clevelandclinic.org/health/body/21640-blood-vessels), always running, never in the same spot twice.\n\nThere's recirculation, of course—five litres of blood making the full circuit every minute, the heart a fist-sized pump never once resting. But recirculation is no different than water vapourizing into clouds and returning to the Earth as rain. The river goes and returns. It is never truly the same.\n\nThis is what I was getting at with my English thesis on [bloodwriting](https://www.researchgate.net/publication/388769322_HOW_THE_ENGLISH_DEGREE_WILL_SAVE_THE_WORLD_Queering_Decolonizing_and_Democratizing_Literary_Studies_for_Generation_Z). The blood is us, mixed with the ochre in the first cave paintings of humanity, but it is also finite, temporary, streaming and coursing. I cannot think of a calmer, more relaxing sound than the soft noise of running waters. I have held my hand in glacial streams until my fingers went white and numb, reluctant to pull my hand out. To feel the cold is to be real, to be here in the now. \n\nOur own anatomy has a precipitation system. A living body has an entire ecology, for [we are far less singular than we imagine](https://pmc.ncbi.nlm.nih.gov/articles/PMC4991899/). We are [38 trillion bacteria cells, and 30 trillion human cells](https://www.scientificamerican.com/article/scientists-bust-myth-that-our-bodies-have-more-bacteria-than-human-cells/). 1.3:1. We are more other than human. We are the safe harbour and cradle for a civilization naked to the human eye. You are not one. You are a watershed.\n\nWe are always in a state of ebbing and flowing. Always turning into something new, transforming. Every cell within your body has an expiry date, and nearly every second, millions of new ones are born. The human body replaces [330 billion cells per day](https://www.scientificamerican.com/article/our-bodies-replace-billions-of-cells-every-day/). [3.8 million new cells every single second](https://www.sciencealert.com/your-body-makes-4-million-cells-a-second-and-most-of-them-are-blood). 86% of those are blood cells—river cells. You shed yourself daily.\n\nColon cells die after three to five days. Skin cells have a life of two to four weeks. The lining of the small intestine replaces itself [every few days](https://science.howstuffworks.com/life/cellular-microscopic/does-body-really-replace-seven-years.htm). Skeletal muscle cells take up to fifteen years. And [neuron cells are never replaced at all](https://askanaturalist.com/do-we-replace-our-cells-every-7-or-10-years/) in the cerebral cortex. Memory, language, and consciousness all live exactly as long as you do. Likewise, the cells behind your eyes, in the lens, are embryonic, they formed before you were born and will be there when you die.\n\nIn your skull are cells that have been with you from your beginning. Carrying, inside itself, the shape of every river you will ever be.\n\nAfter enough time, the same man cannot step into the same river twice, for he is a new man. But not entirely. Something of the first man remains.\n\nGood health of the system depends on the shedding, the moulting, the old making way for the new. We are baptized in the waters. Our ashes are spread in the waters.\n\nI remember stumbling onto a Twitter bio years ago that said *constantly recalibrating* and that's deeply stuck with me. I cannot think of a better self-descriptor. Life is far too long to not reinvent yourself, to not question and realign the base principles of operation. Life is far too short and fragile for this as well. The tension between holding on and letting the current take you, between the cells that live forever and the cells that die in days.\n\nAnd I wonder to myself what my new phase will be. What direction is the river of my blood oriented towards? Is this true animal magnetism? The way the Canada Geese know which way to fly, spending countless hours in formation across the sky, crossing provinces, finding refuge in the warmth of the Floridian peninsula. Ancestral instinct running through the body. Something older than thought, older than memory, older than the cells that carry it.\n\nThe river, though, is impossible. The fresh, current now is always just a moment. All we ever experience will, inherently, be a memory for 99% of our life. There is peace and solace in this—for this too shall pass. But there is also a bittersweet yearning. For as soon as the river is witnessed, is felt, that water is stale and elsewhere, no longer the current cold river we’re pressing our fingertips into.\n\nThe past and the future are handy constructs—intricate illusions to help us not live a life constantly disoriented and impulsive and without focus. But the now is now is now.\n\nA man cannot step into the same river twice. The river cannot be stepped into by the same man twice.\n\nI sit at my desk and I want to list out all of my future plans, all of the big projects I was to thrust myself into ambitiously. I want to retire the old, abandon the past, and only look into the future.\n\n## The Dark River\n\nThe Greeks understood the river. Their underworld—the realm of the dead, the place beyond—was navigated entirely by a dark river. To die was to arrive at the water.\n\nThe [underworld held five rivers](https://www.greeklegendsandmyths.com/rivers-of-the-underworld.html): Styx, the river of hate, which formed the boundary between the living world and the dead. Charon ferried you across for the price of a coin. Acheron, the river of woe. Phlegethon, the river of fire. Cocytus, the river of lamentation. And Lethe. [The river of forgetting.](https://en.wikipedia.org/wiki/Lethe) The river whose water washed every memory clean when you drank.\n\nWhen a soul was ready to be reincarnated—to return to the river of the living—they drank from the Lethe, and forgot. Everything. Who they had been. Who they had loved. The shape of their hands, the sound of their mother's voice, the cold of every river they had ever crossed. To drink oblivion and become new again.\n\nTo shed what was and arrive again at the source, unencumbered, as pure water. The question is never whether you will change. The river never asks. The question is whether you will drink willingly—or whether you will be the man who keeps looking back.\n\nOrpheus, a legendary musician in Greek mythology, traveled to the underworld to bring back his wife, Eurydice, who died from a snake bite on their wedding day. He crossed the Styx. He charmed Cerberus to sleep with the sound of his lyre. He stood before Hades and Persephone and played music so beautiful that gods, who do not weep for nothing, wept. Hades allowed her to return on one condition: Orpheus must walk ahead of her and not turn to look back at her until they were completely out of the darkness.\n\n<span class=\"sc\">With so much to look forward to, Orpheus looked back.</span>\n\nWhat do we call the pull that is stronger than survival, stronger than reason, stronger than the thing you want most? The Lethe flows through the underworld for a reason. You cannot bring back what was without losing what is. Orpheus wanted both. He wanted the past and the future and no present. No darkness, no uncertainty, no walk through the cave where you cannot see who is behind you. He wanted to look, just once, just to be sure.\n\n## What Remained\n\nI want to end with this, another well-known tale from Greek mythology: When Pandora lifted the lid and out poured everything that had no name before. Plague, grief, envy, war, the slow rot of time. The world, which had known only warmth, learned frigid cold. Loss. What it meant to witness the beautiful end.\n\nGods did not give her curiosity by accident.\n\nEvery evil scattered to the four winds, finding the cracks in every heart, the fault lines in every kingdom. Humanity bent, then bent further. Invisible fractures running through trust, joy, the ability to believe in tomorrow.\n\nAnd then the jar went quiet.\n\nShe must have felt the sudden stillness after. She pressed the lid back down from instinct, the way you cover your mouth after saying the wrong thing, too late, knowing it already.\n\nOne thing remained at the bottom. The only thing that could live after everything else had already won.\n\nHer name was Elpis. She had been sealed in with the rest of them, felt the weight of the lid, breathed the same dark air as plague and war and grief. She was hope. She was not separate from suffering. She was its unlikely survivor. While everything else tore itself into the world with hunger, she stayed. She waited at the bottom of the ruined thing like someone who has decided, for no good reason, not to leave.\n\nHope does not arrive before suffering, it is what suffering leaves behind. Not a promise. Not a cure. Stubborn, unreasonable insistence. The story is not yet finished.\n\n<span class=\"sc\">Pandora opened the jar, and the world fell until there was nothing left but hope.</span>\n",
      "date_published": "2026-05-14T07:00:00.000Z",
      "tags": [
        "personal essay",
        "mythology",
        "philosophy",
        "biology",
        "history",
        "identity"
      ],
      "author": {
        "name": "Brennan Kenneth Brown",
        "url": "https://brennanbrown.ca",
        "email": "mail@brennanbrown.ca"
      }
    },
    {
      "id": "https://brennan.day/what-we-lose-with-cultural-extinction-the-red-thread-cut/",
      "url": "https://brennan.day/what-we-lose-with-cultural-extinction-the-red-thread-cut/",
      "title": "What We Lose with Cultural Extinction: The Red Thread Cut",
      "summary": "In 1995, China abducted six-year-old Gedhun Choekyi Nyima—the recognized 11th Panchen Lama—severing the chain of mutual recognition at the heart of Tibetan Buddhist succession. Meanwhile, Michif, a language born from Cree verbs and French nouns that belonged to no one but the Métis People, has nearly vanished within living memory. Both losses are the same act: colonialism's weaponization of continuity. On the extinction of languages, the cutting of red threads, and what it means to inherit a chain with links already missing.",
      "content_html": "\nOn May 14, 1995, the 14th Dalai Lama recognized six-year-old Gedhun Choekyi Nyima as the 11th Panchen Lama, the reincarnation of the second-highest authority in Tibetan Buddhism. Three days later, Chinese authorities abducted the boy Nyima and his family, replacing him with their own appointee, Gyaincain Norbu.\n\nThe Dalai Lama and Panchen Lama have [historically identified each other's reincarnations](https://www.rfa.org/english/news/tibet/dalai-lama-succession-reincarnation-09202024101512.html) since the 1300's. A mutual legitimation relationship, where each was the witness to the other's continuation. Two hands needed to pass a single flame. The Panchen Lama is meant to recognize the next Dalai Lama after he passes. With Nyima disappeared, the chain of mutual recognition is forever broken.\n\nChina knows spiritual authority is political sovereignty. The Gelug school of Tibetan Buddhism works with the practice of reincarnation recognition; the system is predicated on continuity and the unbroken thread of one realized soul finding the next. Break the thread and you kill the succession, yes, but you also inherit the loom. Beijing's state-selected Panchen Lama, Gyaincain Norbu, has spent thirty years being positioned to recognize China's version of the 15th Dalai Lama when the current Tenzin Gyatso passes away. The 14th Dalai Lama has already warned that no candidate chosen for political ends should be recognized or accepted. But warning isn't prevention.\n\n[Gedhun Choekyi Nyima would have turned thirty-six this April](https://www.rfa.org/english/news/tibet/buddhism-04262024121905.html). If the legitimate Panchen Lama is alive—and we don't know if he is—he's spent his adult life invisible. His birthday is marked by exile, with children in Dharamsala holding portraits of a face that hasn't been seen in public for three decades. [The Tibetan Centre for Human Rights and Democracy marked the 30th anniversary of his disappearance in May 2025](https://tchrd.org/2025/05/17/30th-anniversary-of-the-enforced-disappearance-of-gedhun-choekyi-nyima/). His whereabouts remain unknown, as does the fate of Tibetan Buddhism. The government of the People's Republic of China continues to deny access to him. His enforced disappearance constitutes a serious violation of the Convention on the Rights of the Child, to which China is a signatory. China insists he is living as a private citizen, contentedly. Hm.\n\nThese are the extinctions I think about, the permanent severance of culture.\n\n## My Own Cultural Extinction\n\nI spoke to my Dad the other day about how I want to learn Michif but the resources to do so are so few and far between. For I am of the Michif People, a distinct Métis nation in Canada and the United States, originating from 18th-century unions between Cree, Nakota, and Ojibwe women and French-Canadian fur trade workers.\n\nHe told me how his Mémère—my great-grandmother—spoke the language all the time. He understood Michif as \"low\" French compared to \"high\" Quebecois French. He recounted, too, how his Uncle would try to fill his childhood head with important lessons and histories of our People, and the atrocities committed at Residential Schools, being a survivor himself. But my Dad was so young at the time, and had no idea how important that knowledge and storytelling and storykeeping would be as time passed.\n\nThere's grief in retrospect, in understanding only after too much time has passed. My Dad heard Michif as a child. He didn't know he was witnessing the language of his people, an entire epistemology, really. The way of naming the world existing nowhere else on earth. Michif is [Plains Cree verbs married to French nouns](https://bild-lida.ca/educationalsociolinguistics/uncategorized/michif-a-dying-language/), the grammar of the fur trade, a linguistic record and a new tongue. Linguist Peter Bakker, in *A Language of Our Own*, wrote that the bilingual Métis were no longer accepted as Indians or French, and so they formulated their own ethnic identity, and a mixed language was part of that. Something that belonged to nobody else. Something that was entirely and irreducibly ours.\n\nIt's thought there were [never more than a thousand speakers of Michif](https://bild-lida.ca/educationalsociolinguistics/uncategorized/michif-a-dying-language/). By the 2011 census, 640 Métis reported it as a mother tongue; 940 said they could hold a conversation. A fragile language that perhaps never numbered more than a thousand, and now scraped down to the hundreds, concentrated in Elders, scattered across the Prairies and North Dakota.\n\nNobody in the family speaks Michif as their mother tongue anymore. That is what was lost, what was taken through the systemic erasure of our culture and history. Through the wreckage of settler-colonialism.\n\nThis is [language attrition](https://languageattrition.org/) at the individual level, the gradual erosion of a first language due to the cultural pressures of the dominant one. At the community level, this is \"intergenerational language shift.\" The language stops being transmitted between parents and children. Not with violence, necessarily, but with silence. The quiet decision to not pass something on, a decision that isn't even fully a decision. More like a capitulation to a world that has made speaking your mother tongue expensive. \n\nIn early twentieth-century Manitoba, [instruction in public schools was required to be in English only](https://thecanadianencyclopedia.ca/en/article/manitoba-schools-question). The law didn't relax for Francophones until 1967. But for Michif speakers, the accommodation never came. \n\nBy the time the laws changed, there was a generation of children who grew up in kitchens where Noohkooms and Mémères switched to something foreign and low when nobody was listening. The language wasn't passed on. Why would it be? The world had made very clear what the cost of being visibly Indigenous looked like.\n\nI can try my best to learn Michif mechanically, through the scant resources available to me. The [Gabriel Dumont Institute's Michif Tools](https://gdins.org/metis-culture/publishing/michif-resources/) has been banking the language for decades. There's also the [Rupertsland Institute's language program](https://www.rupertsland.org/teaching-learning/michif-language/) here in Alberta, the [BC Métis Federation's Michif Language Project](https://www.michif.ca/), and a Michif studies guide at [the University of Calgary library](https://libguides.ucalgary.ca/c.php?g=702954&p=4997984). Dictionaries, lesson plans, and oral histories are compiled. \n\nThese are all resources that didn't exist when my Dad was young, or if they did, nobody thought to tell him. \n\nBut I cannot learn it through my own family anymore.\n\n---\n\nThe name \"Winnipeg\" originates from the [Western Cree words *winipīhk* (or *win-nipi*), meaning \"muddy water\" or \"murky water.\"](https://www.mcislanguages.com/mcis-blog/under-indigenous-language-influence-canadian-location-names/) It was adopted from the local Indigenous name for nearby Lake Winnipeg, 65 kilometres north of the city.\n\nFor years living in Alberta, I felt so disconnected from my culture and people of Winnipeg and Treaty One. There was a certitude in reconnection, in repairing the loss I've accumulated. But in truth, some loss is permanently excavated. The water stays murky.\n\n## The Many Others\n\nMichif is not alone in this, of course. The world is so impossibly full of languages dying within living memory. You cannot even attempt to hold them all at once.\n\nIn 2008, [Chief Marie Smith Jones of Alaska died, and with her died the language of Eyak](https://www.npr.org/2008/01/24/18391658/last-fluent-speaker-of-eyak-language-dies), unique to the Pacific Northwest coast that had already outlasted most predictions. Chief Smith Jones spent years documenting Eyak, trying to find others who still held pieces. She said\n\n> \"It's horrible to be alone. I have a lot of friends. I have all kinds of children—yet I have no one to speak to.\" \n\nNot in Eyak. Not in the language that made her who she was. The Eyak language isn't gone from the archive, as the linguists recorded it. French linguist Guillaume Leduey has dedicated himself to its study, but its natural transmission, the kind that happens across a kitchen table, is finished.\n\nThere is Manchu. Once [the ruling language of China's Qing dynasty](https://theworld.org/stories/2013/12/03/manchus-ruled-china-20th-century-their-language-almost-extinct), spoken by the people who governed a fifth of the world's population for nearly three centuries, Manchu is now down to fewer than a hundred native speakers, mostly elders in Sanjiazi village in Manchuria. A young Manchu man who had started learning his ancestors' tongue told a reporter: \"If Manchu dies out, so much will be lost. Language is the soul of a culture. People would never truly understand Manchu culture and history.\" The same state that disappeared the Panchen Lama is the same regime now tightening instruction in minority languages across its \"autonomous\" regions, where Manchu is dying but yet its speakers are told their language is officially protected. Protection and extinction are not opposites. Often they're the same policy wearing different names.\n\nThere are also, thankfully, counterexamples. Welsh, Hawaiian, Māori—the languages that returned from the edge through sustained, community-driven effort. Cornish, once declared extinct, is now being taught to children in Cornwall. Hebrew was resurrected from a purely liturgical language into a living mother tongue. \n\nRevival requires continuous community, resources, political will, and above all, the uninterrupted chain of people who remember and share. All of which colonialism violently targeted. Once enough links in that chain are missing, revitalization becomes archaeology. You can dig up the bones. You cannot make them walk.\n\n## My Relations\n\nThere is, though, at least a silver lining. I've done the genealogy research as best I could independently on my own, and cross-referenced it with the family tree my father and half-brother have created—and luckily I was accurate. These names are the links in the chain that survived. Let me tell you who I am, and what my relations are. \n\n> I am Red River Métis, a member of the Manitoba Métis Federation. My ancestry traces directly to the Red River Settlement through several documented family lines. On my father's side, I descend from Alexis Lamirande (b. 1839, St. Norbert, Manitoba) and his mother Marguerite Danis (b. 1805, Red River), whose father Louis Lamirande (b. 1793) made the journey from St-François-du-Lac, Québec to the Red River Settlement, where he died in 1873. Further back, the line reaches Jacques Lamirande (b. 1755, Louiseville, Québec), among the earliest documented ancestors in this branch. Parallel lines include the Charron dit Ducharme family, rooted in St. Boniface and St. Vital across multiple generations, and the Pilon family — Antoine William Pilon (b. 1785, Pointe-Claire, QC, d. 1869, St. Norbert) and his daughter Marie Pilon (b. 1840, St. Norbert). All of which were central to the francophone Métis parishes of the Red River. These are the families who built the community that became Manitoba.  \n>  \n> Marguerite La Montagnaise (described as Chippewa/Ojibwe, b. 1776, St. Norbert, Red River Settlement; d. 1853, Winnipeg, Manitoba) is among the most directly named Indigenous ancestors. Philomène Larivière (Cree, b. 1750, Red River) and Joséphte Maskégonne (b. 1765, Red River Settlement) are further documented. These ancestors reflect the historical reality of Métis identity: the children and grandchildren of French-Canadian and Scottish fur trade men who formed families with Cree, Ojibwe, and other First Nations women in the Red River basin.\n\nWhen I say these names, I am practicing both genealogy and ceremony. The record survived. The chain of transmission was not fully severed. My ancestors lived in the St. Norbert corridor, in the parishes along the Red and the Assiniboine, in a world smelling of pemmican, woodsmoke, and river mud. They witnessed Louis Riel be called a traitor by the same government that called their children's French \"low.\" They spoke Michif.\n\nWhat the Panchen Lama's disappearance and the death of Michif as a mother tongue share is colonialism. The weaponization of continuity. When you break the chain of succession, recognition, and transmission, you get to steal and recreate culture at your will and peril.\n\nYou get to name what comes next. You get to appoint the boy who will identify the next God-king. You get to call the children's English fluency progress, not loss.\n\nThe water stays murky, yes. But murky does not mean gone. Murky is not invisible. Murky water is still water. Murky means something happened upstream, and the river remembers it. The river always remembers, even when we've forgotten the name.\n",
      "date_published": "2026-05-12T07:00:00.000Z",
      "tags": [
        "personal essay",
        "history",
        "politics",
        "culture",
        "language",
        "indigenous",
        "colonialism",
        "identity"
      ],
      "author": {
        "name": "Brennan Kenneth Brown",
        "url": "https://brennanbrown.ca",
        "email": "mail@brennanbrown.ca"
      }
    },
    {
      "id": "https://brennan.day/i-made-my-eleventy-build-5-faster-with-five-changes/",
      "url": "https://brennan.day/i-made-my-eleventy-build-5-faster-with-five-changes/",
      "title": "I Made My Eleventy Build 5× Faster with Five Changes",
      "summary": "A walkthrough of how I audited my 11ty build benchmarks and cut cold-start time from 14 seconds down to 2.6 seconds by caching two custom filters and swapping out a bare network fetch.",
      "content_html": "\nA few months ago, I worked on [improving the performance of my website](https://brennan.day/from-65-to-83-attempts-at-performance-optimization/) for end-users and visitors. But I've also come to realize I needed to look at the build and rendering of the site, as the initial boot of my dev server (and production server) has become absurdly sluggish. I'd run `npm start`, brew coffee in my Chemex, come back, and it'd *just* be finishing. I told myself it's no big deal, nobody sees it except me and it's only the startup. With my blog already at over 180 posts, I figured it was just something I'd need to accept. Incremental builds are fast so I just suffered through it.\n\nThe thing is though, the fixes were embarrassingly simple once I actually looked at what was happening. Come explore my novice computer science skills with me! :D\n\nEleventy prints benchmark data at the end of every build if anything is slow enough to measure. I'd often just skim past it. This time I paid attention:\n\n```\n[11ty] Benchmark   8937ms  64%   222× (Configuration) \"lastModified\" Nunjucks Filter\n[11ty] Copied 286 Wrote 413 files in 13.99 seconds\n```\n\nEight and a half seconds on a single filter! Out of fourteen total.\n\n## The Culprit: `lastModified`\n\nI have a filter that displays \"last modified\" dates on posts and pages, using `git log` to pull the most recent commit timestamp for each source file. I think it's important to inform readers when content was  updated, not just published.\n\nThe problem is how it was implemented:\n\n```javascript\n// Before: spawns a git subprocess for every single page\neleventyConfig.addFilter(\"lastModified\", (filePath) => {\n  const result = execSync(`git log -1 --format=%at \"${filePath}\"`).toString().trim();\n  if (result) {\n    const timestamp = parseInt(result, 10);\n    return DateTime.fromSeconds(timestamp, { zone: \"America/Edmonton\" })\n      .toFormat(\"MMMM d, yyyy\");\n  }\n});\n```\n\nAt 222 pages, this spawns **222 separate `git` processes**, each with its own startup overhead. Process spawning in Node.js is not free. It adds up fast.\n\nThe fix: run `git log` *once* at startup with `--name-only` to get all file timestamps in a single pass, store the results in a `Map`, and just do a lookup in the filter.\n\n```javascript\n// After: one git process at startup w/ 222 Map lookups\nlet _gitTimestampCache = null;\nfunction getGitTimestampCache() {\n  if (_gitTimestampCache !== null) return _gitTimestampCache;\n  _gitTimestampCache = new Map();\n  const output = execSync(\n    'git log --format=\"%at\" --name-only',\n    { encoding: 'utf8', maxBuffer: 20 * 1024 * 1024 }\n  );\n  let currentTimestamp = null;\n  for (const line of output.split('\\n')) {\n    const trimmed = line.trim();\n    if (!trimmed) continue;\n    if (/^\\d{9,11}$/.test(trimmed)) {\n      currentTimestamp = parseInt(trimmed, 10);\n    } else if (currentTimestamp !== null && !_gitTimestampCache.has(trimmed)) {\n      // git log is newest-first, so first occurrence = most recent commit\n      _gitTimestampCache.set(trimmed, currentTimestamp);\n    }\n  }\n  return _gitTimestampCache;\n}\n\nconst _lastModifiedResultCache = new Map();\neleventyConfig.addFilter(\"lastModified\", (filePath) => {\n  if (_lastModifiedResultCache.has(filePath)) return _lastModifiedResultCache.get(filePath);\n  const normalizedPath = filePath.replace(/^\\.?\\//, '');\n  const cache = getGitTimestampCache();\n  let result = null;\n  if (cache.has(normalizedPath)) {\n    const timestamp = cache.get(normalizedPath);\n    result = DateTime.fromSeconds(timestamp, { zone: \"America/Edmonton\" })\n      .toFormat(\"MMMM d, yyyy\");\n  } else {\n    const stats = fs.statSync(filePath);\n    result = DateTime.fromJSDate(stats.mtime, { zone: \"America/Edmonton\" })\n      .toFormat(\"MMMM d, yyyy\");\n  }\n  _lastModifiedResultCache.set(filePath, result);\n  return result;\n});\n```\n\n`git log --name-only` streams every commit with all the files it touched. Since git outputs commits newest-first, the very first time a file path appears in that stream is its most recent modification date. The `Map.has()` check ensures we don't overwrite it with an older timestamp.\n\nAfter this change: **13.99s → 4.35s**.\n\n## Second Pass: `assetHash`\n\nWith `lastModified` out of the way, the next benchmark that appeared was:\n\n```\n[11ty] Benchmark    439ms  10% 11891× (Configuration) \"assetHash\" Nunjucks Filter\n```\n\nEleven thousand, eight hundred and ninety-one calls. For a filter that reads a file from disk and computes an MD5 hash. I have maybe ten asset files.\n\nThe filter is used for cache-busting, appending a `?v=<hash>` query string to CSS and JS paths. It's called from `base.njk` which renders for *every* page, and base.njk references the same five or six asset paths every time. So the same files were being read and hashed ~28 times per page.\n\n```javascript\n// Before: reads from disk on every call\neleventyConfig.addFilter(\"assetHash\", (assetPath) => {\n  const fullPath = path.join(__dirname, 'src', assetPath);\n  if (fs.existsSync(fullPath)) {\n    const fileContents = fs.readFileSync(fullPath, 'utf8');\n    const hash = crypto.createHash('md5').update(fileContents).digest('hex').substring(0, 8);\n    return `${assetPath}?v=${hash}`;\n  }\n  return assetPath;\n});\n```\n\n```javascript\n// After: one read per unique path\nconst _assetHashCache = new Map();\neleventyConfig.addFilter(\"assetHash\", (assetPath) => {\n  if (_assetHashCache.has(assetPath)) return _assetHashCache.get(assetPath);\n  const fullPath = path.join(__dirname, 'src', assetPath);\n  if (fs.existsSync(fullPath)) {\n    const fileContents = fs.readFileSync(fullPath, 'utf8');\n    const hash = crypto.createHash('md5').update(fileContents).digest('hex').substring(0, 8);\n    const result = `${assetPath}?v=${hash}`;\n    _assetHashCache.set(assetPath, result);\n    return result;\n  }\n  return assetPath;\n});\n```\n\nTwo lines added. `assetHash` disappeared from the benchmarks entirely after this.\n\n## Third Pass: Uncached Network Fetch\n\nThe third issue was less obvious. After the first two fixes, this appeared:\n\n```\n[11ty] Benchmark    523ms  13%     1× (Data) `./src/_data/guestbook.js`\n```\n\nOnly called once, but still 523ms—a live HTTP round-trip to the Netlify API on every build. My `guestbook.js` data file was using raw `node-fetch` with no caching, no retry, and no persistence between builds.\n\nMy `webmentions.js` already does this correctly with [`@11ty/eleventy-fetch`](https://www.11ty.dev/docs/plugins/fetch/), which caches responses to disk for a configurable duration. I just hadn't applied the same pattern to guestbook data.\n\n```javascript\n// Before: raw fetch, live request every build\nconst fetch = require(\"node-fetch\");\n\nconst formsResponse = await fetch(formsUrl, { headers: { \"Authorization\": `Bearer ${token}` } });\nconst forms = await formsResponse.json();\n\nconst submissionsResponse = await fetch(submissionsUrl, { headers: { \"Authorization\": `Bearer ${token}` } });\nconst submissions = await submissionsResponse.json();\n```\n\n```javascript\n// After: EleventyFetch with 1h disk cache\nconst EleventyFetch = require(\"@11ty/eleventy-fetch\");\n\nconst fetchOptions = { headers: { \"Authorization\": `Bearer ${token}`, \"User-Agent\": \"curl/7.79.1\" } };\n\nconst forms = await EleventyFetch(formsUrl, { duration: \"1h\", type: \"json\", fetchOptions });\nconst submissions = await EleventyFetch(submissionsUrl, { duration: \"1h\", type: \"json\", fetchOptions });\n```\n\nThe result is cached to `.cache/` for an hour. Subsequent builds within that window skip the network.\n\n## Fourth Pass: A Disk Cache for `git log`\n\nAfter running the benchmarks again, `lastModified` was still showing at ~450ms per cold start. The single-process fix cut spawning from 222 to 1, but that one `git log --name-only` call still runs on every fresh Node.js process — every `npm start`, every CI build.\n\n```\n[11ty] Benchmark    449ms  11%   223× (Configuration) \"lastModified\" Nunjucks Filter\n```\n\nThe fix was to persist the timestamp map to `.cache/git-timestamps.json`, keyed by `git rev-parse HEAD`. If HEAD matches, then the git log is skipped entirely and just the JSON is read.\n\n```javascript\n// Before: in-memory only, runs git log on every cold start\nlet _gitTimestampCache = null;\nfunction getGitTimestampCache() {\n  if (_gitTimestampCache !== null) return _gitTimestampCache;\n  _gitTimestampCache = new Map();\n  const output = execSync(\n    'git log --format=\"%at\" --name-only',\n    { encoding: 'utf8', maxBuffer: 20 * 1024 * 1024 }\n  );\n  // ...parse output into map\n  return _gitTimestampCache;\n}\n```\n\n```javascript\n// After: disk-cached, keyed by HEAD SHA\nconst cacheFile = path.join(__dirname, '.cache', 'git-timestamps.json');\nconst currentHead = execSync('git rev-parse HEAD', { encoding: 'utf8' }).trim();\n\nif (fs.existsSync(cacheFile)) {\n  const cached = JSON.parse(fs.readFileSync(cacheFile, 'utf8'));\n  if (cached.head === currentHead) {\n    for (const [k, v] of Object.entries(cached.timestamps)) {\n      _gitTimestampCache.set(k, v);\n    }\n    return _gitTimestampCache; // no subprocess at all\n  }\n}\n\n// ...run git log as before, then persist:\nfs.mkdirSync(path.join(__dirname, '.cache'), { recursive: true });\nfs.writeFileSync(cacheFile, JSON.stringify({\n  head: currentHead,\n  timestamps: Object.fromEntries(_gitTimestampCache)\n}));\n```\n\n`lastModified` dropped off the benchmarks entirely on the next build. The `.cache/` directory is already used by `@11ty/eleventy-fetch`, so no extra gitignore entry needed.\n\n## Fifth Pass: 54 Warnings From Old Medium Posts\n\nRunning the dry-run build was also flooding the console:\n\n```\nImage not found: /Users/brennan/.../src/https:/cdn-images-1.medium.com/max/1200/1*...png\n```\n\nOld posts imported from Medium have absolute CDN URLs in their frontmatter. These were being passed to my `thumbnail` shortcode, which calls `fs.existsSync` on a nonsense path like `src/https:/...` before bailing.\n\n```javascript\n// Before: passes external URLs straight to fs.existsSync\nconst fullPath = path.join(__dirname, 'src', imagePath);\nif (!fs.existsSync(fullPath)) {\n  console.warn(`Image not found: ${fullPath}`);\n  return `<img src=\"${imagePath}\" alt=\"${alt}\" ...>`;\n}\n```\n\nTwo lines ahead of that check fixes it:\n\n```javascript\n// After: bail before touching the filesystem for external URLs\nif (imagePath.startsWith('http://') || imagePath.startsWith('https://')) {\n  const fetchpriorityAttr = fetchpriority ? ` fetchpriority=\"${fetchpriority}\"` : '';\n  return `<img src=\"${imagePath}\" alt=\"${alt}\" width=\"${width}\" height=\"${height}\" loading=\"${loading}\"${fetchpriorityAttr}>`;\n}\n```\n\nZero warnings. As a bonus, external images now correctly receive the `fetchpriority` attribute instead of silently stripping it.\n\n## What Didn't Help: `slugify` Memoization\n\n`slugify` was sitting at ~638ms for 1,851 calls, another candidate for memoization:\n\n```javascript\nconst _slugifyCache = new Map();\nconst _origSlugify = eleventyConfig.getFilter(\"slugify\");\neleventyConfig.addFilter(\"slugify\", (str, opts) => {\n  const key = str + (opts ? JSON.stringify(opts) : '');\n  if (_slugifyCache.has(key)) return _slugifyCache.get(key);\n  const result = _origSlugify(str, opts);\n  _slugifyCache.set(key, result);\n  return result;\n});\n```\n\nBefore: 638ms. After: 645ms. The 1,851 calls are almost entirely unique strings of post titles, heading anchors, and tag names computed fresh per page. The hit rate is near zero. The wrapper stays since it costs nothing, but it isn't a meaningful win today.\n\n## One More Line Each: Longer Cache Durations\n\n`webmentions.js` and `guestbook.js` were both using `\"1h\"` EleventyFetch durations. Neither service updates hourly. Bumped to `\"6h\"`.\n\n## Final Numbers\n\n| Build | Time | Notes |\n|---|---|---|\n| Before | 13.99s | `lastModified` consuming 64% of build |\n| Fix 1 | 4.35s | Single `git log` + Map cache |\n| Fix 2 | 4.13s | `assetHash` memoized |\n| Fix 3 | 4.00s  | `guestbook` on EleventyFetch |\n| Fix 4 (cold) | 3.28s | git-timestamps.json written to disk |\n| Fix 4 (warm) | **2.63s** | `lastModified` off benchmarks; site has grown since Fix 3 |\n\n**81% faster cold-start. 5.3× overall speedup.** The remaining time on the warm build is `html-transformer` (~580ms) and `slugify` (~640ms) which are both built-in. The `lastModified` git log cost is now effectively free on repeated cold starts once the disk cache is populated.\n\n## Bonus: `netlify dev`\n\nWhile I was at it, I added a `[dev]` section to `netlify.toml` to make the Netlify CLI actually useful for local prod-like testing. Without it, `netlify dev` tries to auto-detect the framework and usually guesses wrong.\n\n```toml\n[dev]\n  command = \"npm start\"\n  targetPort = 8081\n  port = 8888\n  autoLaunch = false\n```\n\nNow `npm run start:netlify` spins up a local server at `http://localhost:8888` with all the Netlify Functions, redirects, and custom headers from `netlify.toml` active — so you can test things like the micropub endpoint and comment function without deploying first.\n\n## On Developer Experience (DX)\n\nI've often tried to optimize and add accessibility for end-users.  I've concerned myself with Lighthouse scores, asset compression, etc. But what I've been describing in this post is  something I hadn't thought to name before I started digging into it.\n\nIt's called [developer experience](https://getdx.com/blog/developer-experience/), or DX! Not UX for users, but UX for the developer themselves. Everything that shapes the building. Tools, feedback loops, the environment you code in, and certainly how long you wait during build times. I came through this through my benchmarks without really knowing that's what I was doing.\n\nDeveloper experiencedeals with [three interconnected dimensions](https://queue.acm.org/detail.cfm?id=3595878): **feedback loops**, **cognitive load**, and **flow state**. \n\n- **Feedback loops** are the speed at which your environment responds to what you do. Write a line, see the result. Change a filter, rebuild the page. Every development session is a chain of micro-cycles. When the loop is less than a second, you stay in the work. When it drags, you [lose the thread](https://microservices.io/post/architecture/2025/02/23/the-importance-of-flow.html). The 14-second cold start I've accumulated had trained me to physically leave my desk during startup to make coffee! The loop broke and I ritualized the breakage.\n* **Cognitive load** is the mental overhead of your environment, which is everything your brain is spending cycles on besides the actual problem. The 54 console warnings from those Medium import URLs were a great example. I'd been skimming past them for months. Every build gad a scroll noise, and that noise pulled at my attention. The fix was two lines. A clean terminal is a lower-overhead terminal.\n* **Flow state** is what becomes possible when the other two are healthy. The Csikszentmihalyi's term, the absorbed, frictionless attention. Tools disappears and the work is all there is. For a personal site, on a solo project, flow is the entire point, isn't it? I'm not shipping to stakeholders. Nobody is waiting on a PR. The reason I maintain this or any of my other projects is just the pleasure of the craft, and a poor DX is antithetical to that.\n\nBuild speed, for a personal site, the one I use as for my daily writing practice, is important to be mindful of. The optimizations I made didn't change anything visible to a reader. \n\nThe `netlify dev` configuration also helps in a similar way, allowing me to test micropub endpoints and edge functions before deploying. The doubt is gone.\n\nDX, like UX, is something I'll be tinkering with indefinitely. My benchmarks will become slower again as I write more posts and add more functionality. New filters, new data sources, new complexity. I'm so excited to learn more about this \n\n---\n\nLike the rest of my code, all of these changes are available to see in my [site's source on GitLab](https://gitlab.com/brennankbrown/brennan.day). The pattern is **measure first, then cache aggressively**. Eleventy's built-in benchmarks tell you exactly where to look — and when you think you've found everything, run them again. RTFM! :D\n",
      "date_published": "2026-05-11T07:00:00.000Z",
      "tags": [
        "eleventy",
        "javascript",
        "technical",
        "tutorial",
        "IndieWeb",
        "personal site"
      ],
      "author": {
        "name": "Brennan Kenneth Brown",
        "url": "https://brennanbrown.ca",
        "email": "mail@brennanbrown.ca"
      }
    },
    {
      "id": "https://brennan.day/last-online-620-weeks-ago-why-im-loyal-to-the-indieweb/",
      "url": "https://brennan.day/last-online-620-weeks-ago-why-im-loyal-to-the-indieweb/",
      "title": "Last Online 620 Weeks Ago: Why I'm Loyal to the IndieWeb",
      "summary": "You visit your parent's house and find your white Xbox 360 in your childhood bedroom. A friends list full of gamertags that haven't booted up their own console in hundreds of weeks. On the heartbreak of digital disappearance, and why I'm committed to staying findable.",
      "content_html": "\nYou visit your parent's house and find your white Xbox 360 in your childhood bedroom. \n\nThe tri-coloured composite cables are still stuffed behind the nightstand where you left them, tangled the way you left them, and when you plug them in you hear the ambient glow of the logo as the system boots up—you hear the fan pitch and wait patiently at the boot screen. You're presented with a vibrant, extinct design language and a friends list full of gamertags that haven't booted up their own console in hundreds of weeks. You hover the cursor over a name and the tooltip reads: *Last Online: 640 Weeks Ago.* Twelve years and you hadn't thought of him in eleven.\n\nYou read an article in a physical, ink-printed newspaper in 2012 discussing how Microsoft is announcing the shutdown of MSN Messenger next year. You hurry home and try to remember the password to the Hotmail account you had in middle school. You look through a plastic binder full of polynomials and chemistry-balancing exercises and find the credentials written on a pink sticky note, your twelve-year-old handwriting still round, the looping letters you don't recognize as yours anymore. Once again, you're presented with an already-aging design language and two lists of people you used to love: \"Not Online (52)\" and \"Online (0)\".\n\nIt's only a couple years ago, and instead of sleeping you are replaying the most embarrassing moments from high school in your head. You decide to keep yourself up for a few more hours by looking up the usernames you remember on Instagram. You find accounts, and some are even public and full of posts. But then you look at the most recent photos posted. The metadata at the bottom reads \"July 2nd, 2020.\" You look at the posts before that, and there's nearly one per day before the silence of the past six years. What happened? You search their full name with \"obituary\" added as a rueful suffix. Nothing comes up. It's just a ghost town mystery.\n\nIt's sometime in 2019, and you're reading a short news item about MySpace. Oh, that still exists? Yes, but they just admitted to losing everything uploaded to the platform between 2003 and 2015. Not misplacing. Not taking offline temporarily. Gone forever. Fifty million songs from fourteen million artists. A server migration the company described as an inconvenience, with an apology statement already half-buried. The music was the point of MySpace, you know? Bedroom recordings that no label ever touched, local bands that found their first fifty listeners through a blue-and-white grid of blinking GIFs and Top 8s. The audio of the Internet at the time. The developer and blogger Andy Baio was openly skeptical it was an accident, noting that flagrant incompetence might make for worse press than admitting they simply couldn't be bothered to migrate 50 million old files. You think about those songs, suspended in no air.\n\n[Oxford University's Internet Institute](https://www.eurekalert.org/news-releases/698549) projects that dead Facebook users will outnumber the living by 2070. By 2100, up to 4.9 billion accounts will belong to people no longer able to log in. Right now, 8,000 Facebook users die every single day. There are already 107 million deceased users across social platforms. Profiles frozen mid-sentence, birthday notifications still firing into the feeds of people who don't know what to feel when they arrive, tagged memories resurfacing in timelines like letters returned to sender. Twitter deleted fifteen million inactive accounts in December 2025. The platforms maintain these presences reluctantly, and then delete them erratically. Logic shifts with each new executive and earnings call. \n\nAn account stopped in time feels different from a deleted one, different again from a memorialized one, and different still from accounts belonging to people who are alive somewhere and simply stopped, for reasons you aren't sure of.\n\n---\n\nExamples like the ones I've shared above are why I have found myself with a deep, irrational loyalty to the [IndieWeb](https://brennan.day/indieweb). I know as well as anybody the heartbreak of losing total contact with someone, whether they were an online friend or someone in real life. Even if you only had a couple of back-and-forth correspondences, it sticks in your mind with the roots of a blooming flower. We remember the kind and the considerate, regardless of whether they were schoolmates or anonymous screen names and cartoon avatars. We are not often enough kind and considerate to one another. We are not often enough brave enough to reach out spontaneously.\n\nNearly everyone in your life will be a season. There are undefined start dates and end dates, and the seasons don't announce themselves. You only recognize, in retrospect, who was summer and who was the long grey middle of February. Who you were present for and who you slept through. \n\nAnd I also need to confess that throughout my life, I've been flaky and unreliable. I've gone dark. I've been impossible to contact for months at a time during the worst periods. This has been detrimental, obviously, because relationships are built on a foundation of trust and faith. Ghosting is pouring accelerant on the end-date—the opposite of fertilizer for the blooming flowers. Often in-person, there is an established social contract. But online, unless you specifically ask, nobody is obligated to continue a sustained connection. Netizens come and go with a far more ephemeral, transient nature than people you see face-to-face. The seasons end faster. The silences are easier to maintain.\n\nBut I don't want that for myself, anymore. I want to be someone reliable and easy to contact, both in-person and online.[^1] This is in conjunction with my commitment to [building for the long web](https://brennan.day/how-are-we-preparing-for-the-long-web/). My domain [https://brennan.day](https://brennan.day) is owned by me for the next decade, which means you'll be able to comment on my posts and write in my guestbook and email me for the next decade, minimum. And I'll get back to you.\n\nI don't want to be yet another ship passing through the night. I don't want to be a perpendicular line intersecting once and significantly with other perpendicular lines. I want to consistently comment on the same other active blogs for as long as they're active. I don't want anybody wondering what happened to me.\n\nI think this is a promise to be more proactive about checking in. To sustain a continued and legible presence. These are important principles for the future of the human web. There are thousands of inactive corporate social media accounts, thousands of blogs that haven't had a post in years, and fifty million songs that are simply gone. I don't want to contribute to the accumulation of started things and the dusty shelves of interrupted selves. The best parts of the Internet you love are made by people who kept showing up. I want to be someone who keeps showing up.\n\n[^1]: Which isn't to say I'll respond immediately—I want to return to an [internet that is a place](https://www.intersectmagazine.com/post/the-internet-used-to-be-a-place-now-we-just-live-here) we visit periodically instead of where we're permanently stuck in.\n",
      "date_published": "2026-05-10T07:00:00.000Z",
      "tags": [
        "personal essay",
        "indieweb",
        "internet",
        "community"
      ],
      "author": {
        "name": "Brennan Kenneth Brown",
        "url": "https://brennanbrown.ca",
        "email": "mail@brennanbrown.ca"
      }
    },
    {
      "id": "https://brennan.day/the-hondius-pneumonia-low-risk-assessment/",
      "url": "https://brennan.day/the-hondius-pneumonia-low-risk-assessment/",
      "title": "The Hondius Pneumonia (Low Risk Assessment)",
      "summary": "A hantavirus outbreak aboard the MV Hondius in the South Atlantic has sent thirty passengers home across twenty-three countries before a single test was run. What does the WHO's 'low risk' framing mean? The institutional failure of January 2020, and what honest communication about uncertainty actually requires. The incubation window is open. We are watching.",
      "content_html": "\n## I.\n\nBlue-black water, cold getting into the bone even through a cabin window. The *MV Hondius* somewhere in the South Atlantic. Somewhere below deck, a 70-year-old Dutch man has a fever. Headache. Abdominal pain. The ship's doctor sees him. He dies on April 11. His body stays on board for thirteen more days.\n\nBy the time [anyone calls the WHO](https://www.who.int/emergencies/disease-outbreak-news/item/2026-DON599), it is May 2. The ship has been at sea for a month. Thirty passengers have already disembarked at Saint Helena. They are home in the Netherlands, in Singapore, in Texas, or in Ontario. Sleeping in their beds, taking the bus, sitting in waiting rooms.\n\n[The risk to the global population is stated to be low](https://www.cdc.gov/hantavirus/situation-summary/index.html).\n\n## II.\n\nOn December 30th, 2019, a global infectious disease surveillance network, staffed largely by volunteers, called [ProMED](https://promedmail.org) flagged a cluster of pneumonia cases in Wuhan, China with an unknown cause. An ophthalmologist named [Li Wenliang](https://en.wikipedia.org/wiki/Li_Wenliang) sent a message to colleagues that same week warning them to wear protective equipment. He was summoned by police and forced to sign a statement admitting to \"making false comments.\" He contracted the virus from a patient. He died on February 7, 2020.\n\nOn January 14, 2020, the WHO [tweeted](https://twitter.com/WHO/status/1217043229427761152) that preliminary investigations found \"no clear evidence of human-to-human transmission.\"\n\nOn January 30, they declared a Public Health Emergency of International Concern. On March 11, they finally used the word *pandemic*. By then, it was [already everywhere](https://www.who.int/director-general/speeches/detail/who-director-general-s-opening-remarks-at-the-media-briefing-on-covid-19---11-march-2020). Many were already going to die for want of action taken earlier\n\nWho was right in January 2020? A handful of epidemiologists on Twitter. A science journalist named [Helen Branswell at STAT News](https://www.statnews.com/2020/01/04/as-china-reports-second-death-from-new-virus-nearly-two-dozen-new-cases-are-identified/), who had been covering it carefully since the first week of January. A sociologist named [Zeynep Tufekci](https://www.scientificamerican.com/article/preparing-for-coronavirus-to-strike-the-u-s/), who wrote in February that we needed to prepare *now*. An epidemiologist named Eric Feigl-Ding who tweeted \"HOLY MOTHER OF GOD\" on January 24 after seeing the first reproduction number estimates. He was mocked for it.\n\n## III.\n\nI won't lie by omission. [The Andes virus does not drift through the air](https://www.npr.org/2026/05/07/nx-s1-5814761/hantavirus-likely-not-the-next-covid). Not through subway cars or church basements. It spreads through close, sustained contact—shared breath, shared saliva, the intimacy of caring for someone who is dying. A 2018–19 Argentine outbreak began at a birthday party and deepened at a funeral wake. Not a grocery store and not a school. The transmission coefficient is different from a respiratory pathogen.\n\nThe [WHO's current assessment](https://www.cnn.com/2026/05/07/world/hantavirus-ship-tenerife-outbreak-intl) that human-to-human spread requires close, prolonged contact is thankfully based on decades of outbreak data this time, not wishful thinking.\n\n## IV.\n\nThe incubation window for Andes hantavirus is [four to forty-two days](https://www.cdc.gov/hantavirus/situation-summary/index.html). Someone exposed on April 15 may not know until late May. The thirty passengers who disembarked at Saint Helena left before a single test had been run. They came from [twenty-three countries](https://www.today.com/health/news/hantavirus-cruise-ship-pandemic-risk-covid-2026-rcna343854). Every case so far has a traceable link to the ship. The moment that stops being true, the low-risk framing collapses like a lung under fluid.\n\nThe worst-case scenario here is not another pandemic. It's slower and messier—dispersed household clusters, healthcare workers exposed, contact chains that can't be reconstructed. It's the 2014 Ebola model, not the COVID model. Ebola in 2014 killed eleven thousand people and overwhelmed entire health systems.\n\n## V.\n\nThe right answer in January 2020 was to say that we don't know yet, and that is the emergency.\n\nNot \"the risk is low\" and not \"there is no evidence of widespread transmission.\" Honesty would be declaring that there is an unknown pathogen spreading among humans, and we are lagging behind on it, and we need to move as if it is worse than we hope.\n\nThat's the sentence I want to hear now. Not panic. Not the grinding, ambient dread of another March 2020. Just honesty about the gap between what officials know and what is actually true—and the diligence that gap demands from all of us while we wait for the incubation window to close.\n\nThe *Hondius* is docking in Tenerife. The passengers are going home. The rodents along a road-trip route in Argentina are being tested. Somewhere in a lab in Johannesburg, a PCR machine is running.\n\nWe are watching. That, at least, we have learned.\n",
      "date_published": "2026-05-08T07:00:00.000Z",
      "tags": [
        "personal essay",
        "science",
        "politics",
        "health",
        "pandemic"
      ],
      "author": {
        "name": "Brennan Kenneth Brown",
        "url": "https://brennanbrown.ca",
        "email": "mail@brennanbrown.ca"
      }
    },
    {
      "id": "https://brennan.day/where-is-the-indigenous-cultural-revolution/",
      "url": "https://brennan.day/where-is-the-indigenous-cultural-revolution/",
      "title": "Where is the Indigenous Cultural Revolution?",
      "summary": "Fred Moten and Stefano Harney's 'The Undercommons' describes a space of collective refusal beneath the institutions of the master. On why Black American cultural revolution was possible, why Indigenous cultural revolution is structurally different, and where the Indigenous undercommons already is. The potlatch went underground for sixty-six years. The drum broke out in a shopping mall. The land is the undercommons. We were always already here.",
      "content_html": "\nFred Moten and Stefano Harney's [*The Undercommons: Fugitive Planning & Black Study*](https://www.minorcompositions.info/wp-content/uploads/2013/04/undercommons-web.pdf) describes a space of collective refusal and radical study existing beneath the institutions of the master. In the hold of the ship, in the field, in the church hidden behind the plantation, in the block party at the end of the dead-end Bronx street. The undercommons is a practice, a gathering of the refused, refusing back. Black culture, Moten and Harney argue, found its undercommons in the very conditions of its oppression. Stolen people, crammed into ships, pressed into fields. From that horror blossomed the rhythm and call and response, a musical theology that the captors could never extinguish. \n\nMoten and Harney were not writing about Turtle Island. And yet there is something in the concept that keeps arriving at the treeline, keeps turning up at the edges of rez, keeps sounding like a drum in a shopping mall. Something saying *this was already here.*\n\n## PART ONE: The Beautiful Success of Black America\n\nIn 2001, [Robert L. Johnson became the first Black billionaire in America](https://www.cnbc.com/2018/02/26/what-to-know-about-robert-johnson-americas-first-black-billionaire.html) after selling BET, Black Entertainment Television, to Viacom for three billion dollars. He had built a cable empire and a *cultural* empire. This business was a signal. Black people had successfully carved out a frequency in the electromagnetic spectrum. \n\nIn 2020, nearly two decades later, [Tom Love of the Chickasaw Nation](https://hof.chickasaw.net/Members/2019/Tom-Love.aspx) entered [the Forbes billionaire list](https://www.forbes.com/profile/tom-love/) through Love's Travel Stops & Country Stores, a chain of truck-stop convenience stores. The comparison is not made to diminish either man. One sold a television network that beamed Black culture back to Black people across a continent. The other sold coffee, sandwiches, and diesel. I am trying to understand what this gap means.\n\nI am trying to understand why two groups of people, both systematically destroyed over centuries by the same European colonial project, arrived at such different places of cultural power, and what the mechanics of those differences are.\n\nUnderstand that these situations cannot be flattened to easy comparison whatsoever. [Tuck and Yang](https://clas.osu.edu/sites/clas.osu.edu/files/Tuck%20and%20Yang%202012%20Decolonization%20is%20not%20a%20metaphor.pdf) caution us, writing that [\"solidarity is an uneasy, reserved, and unsettled matter.\"](https://www.pantograph-punch.com/posts/ode-to-the-aunties) Settler colonialism operates through elimination, through the seizure of land for permanent occupation, in a logic distinct from (if entangled with) the logic of chattel slavery. To flatten these is a \"settler move to innocence,\" a way of making the conversation easier than it should be.\n\nAn answer begins with the body. \n\n### Where the Body was Placed\n\nThe Transatlantic slave trade, more accurately called [the Transatlantic human trafficking rings](https://theexodusroad.com/history-of-human-trafficking/), took approximately 12.5 million people from the African continent and deposited them into a shared geography of oppression over four centuries. Stripped of their languages, nations, and cosmologies. In a terrible and brutal act of colonial reduction, they were homogenized. \n\nNot fully and not willingly, and certainly not without enormous loss. But the shared condition of American chattel slavery created the conditions for a shared culture. A new people. *African American*. The blues is born in Mississippi. Gospel is born in the terror of the plantation. [Hip hop emerges in 1973 in the South Bronx](https://www.theeagleonline.com/article/2023/04/a-deep-dive-into-the-origins-and-future-of-hip-hop), at a block party at 1520 Sedgwick Avenue, where DJ Kool Herc isolates the percussion break of a funk record and creates, from two turntables and a crowd of people with nowhere else to go. An entirely new art form. When you concentrate suffering and compress pain, there's something that sustainably burns.\n\n[The Great Migration](https://www.archives.gov/research/african-americans/migrations/great-migration)—six million Black Americans moving from the rural South to the urban North between roughly 1910 and 1970—is essential here. Chicago, Detroit, Harlem, the Bronx. Density. Proximity. Shared language. A concentrated, critically massed population with a shared enemy. The record labels follow. The radio stations follow. The money—eventually, partially, extractively—follows.\n\nThere are approximately [476 million Indigenous people](https://www.un.org/development/desa/indigenouspeoples/about-us.html) worldwide. Roughly 6% of the global population spread across more than 90 countries and speaking an estimated 4,000 languages, most greatly endangered. In Canada, there are [1.8 million Indigenous people](https://www150.statcan.gc.ca/n1/pub/71-607-x/2018004/cov-couv-eng.htm), about 5% of the total population. In the United States, roughly 3.7 million. \n\nWe are not a diaspora. We are a dispossession. The difference between what has occurred between Black people and Indigenous Peoples is of direction. Enslaved Africans were removed from their land and concentrated. We were removed from our land and *scattered*. Isolated, contained, fenced. The reserve system, the reservation system. None were communities, but rather administrative units. Quarantine zones. The geography of elimination.\n\nThe cultural revolution of Hip hop required density. The block party, the apartment hallway, the shared wall between too many people with too much pain and genius. The South Bronx of 1973 was economically abandoned, deliberately starved by Robert Moses's freeway policies, but God, it was *full*. Hundreds of thousands of people in a few square miles. Fullness is the condition of possibility. Rez has always been designed to prevent that fullness.\n\n### The Impossible Mosaic of Language\n\nBlues became jazz, jazz became soul, soul became hip hop. When the African American cultural revolution happened, it always happened in English. One language. The language of the colonizer remade and reclaimed and bent back until it cracked open into something new. African American Vernacular English is a linguistic achievement, a creole forged in captivity and successfully becoming the mainstream that white teenagers worldwide speak its idioms. Shared language is required to propagate.\n\nWe have no equivalent. There are [over 70 Indigenous languages still spoken in Canada](https://www.canada.ca/en/canadian-heritage/services/indigenous-cultural-initiatives/indigenous-languages.html), from Cree to Anishinaabemowin to Inuktitut to Michif. Michif is my language, the Métis creole of French and Cree, a beautiful linguistics of the border-crossing creating me. \n\nEach Indigenous language carries a worldview, a cosmology, a way of organizing experience that is irreducible to any other. None are interchangeable. These are not the building blocks of a shared pan-Indigenous culture in the way that shared English was the building block of a shared Black American culture. And many are nearly gone or already extinct.\n\n### Our Culture\n\nNone of which is to say we have built nothing, for the evidence against that is loud and beautiful. [The Halluci Nation](https://thehallucination.com/), formerly A Tribe Called Red, emerged from Ottawa's Electric Pow Wow parties in 2008 and became a sonic argument that Indigenous culture was present and alive, not preserved under glass but beating under bass. Their powwow step is traditional First Nations drumming and vocal chanting pressed against dubstep, hip hop, moombahton. [In 2025, they became the first independent Indigenous artists from North America to surpass 100 million streams on Spotify](https://open.spotify.com/artist/2jlWF9ltd8UtoaqW0PxY4z). The [2016 album *We Are the Halluci Nation*](https://ices.library.ubc.ca/index.php/workplace/article/view/186405/185482), named for a concept given to them by Santee Sioux activist and poet John Trudell, was described by *Pitchfork* as [\"politically thrilling and immediate.\"](https://pitchfork.com/reviews/albums/22384-we-are-the-halluci-nation/) Manitoba's Premier, Wab Kinew, called what ATCR represented an \"[Indigenous Music Renaissance](https://exclaim.ca/music/article/a_tribe_called_red-the_halluci_nation_is_real).\"\n\n[Tanya Tagaq](https://www.newyorker.com/culture/listening-booth/tanya-tagaqs-experimental-inuit-throat-singing), Inuk from Nunavut, practices throat singing. [Cherie Dimaline](https://www.cheriedimaline.com/), Métis, writes *The Marrow Thieves*, a dystopia in which Indigenous peoples are hunted for their bone marrow—the one thing settlers cannot take, until they do—and wins the Governor General's Award and reaches the school curriculum. [Lido Pimienta screams in Spanish and Kogi](https://www.kexp.org/read/2023/6/30/lido-pimienta-chronicles-of-the-sublime/). This is the cultural reclamation I am asking about, and they are happening.\n\nBut a singular band crossing 100 million Spotify streams is not the same as the entire genre of hip hop. The Halluci Nation is, as Bear Witness himself has said, carrying a weight of representation, of being one of the only Indigenous acts visible at this scale. [The Globe and Mail reported that their position \"at the forefront of an explosion of Indigenous music... placed a lot of weight on the group's collective shoulders.\"](https://www.theglobeandmail.com/arts/music/article-a-tribe-called-red-calls-it-quits-allowing-the-halluci-nation-to-rise/) No singular Black artist carries the entire Black culture on her back. There is one Halluci Nation.\n\n[APTN](https://www.aptn.org/about/our-story/), the Aboriginal Peoples Television Network, is the world's first national Indigenous broadcaster, launched in 1999 in Winnipeg. APTN's annual budget is $47 million. BET, when Robert Johnson sold it, was valued at three billion.\n\n### The Conditions for Cultural Production\n\nBlack cultural revolution was possible because the conditions of anti-Black oppression accidentally created the conditions for cultural production: Concentration, shared language, a single enemy legible from a single geography. The undercommons could form because the undercommons had critical mass, demographic mass, the mass of shared suffering in shared space.\n\nWhat was done to Indigenous peoples on this continent was designed to prevent exactly that. Scatter. Fragment. Contain. Define legally out of existence. Destroy the language. Take the children. \"Indigenous\" means many different, specific, irreducible things. Métis, Cree, Anishinaabe, Haudenosaunee, Tlingit, Wet'suwet'en. A unified cultural identity can never fully cohere the way \"Black American\" cohered under pressure. Slavery destroyed people and created community by accident. Settler colonialism on this continent destroyed community *on purpose*. It was the community—the web of our relations, our language, our children—that it was designed to eliminate.\n\nPatrick Wolfe, the Australian settler colonial theorist, wrote that settler colonialism is [\"a structure, not an event.\"](https://www.tandfonline.com/doi/full/10.1080/14623520601056240) It doesn't end and it is operating, now. In the ongoing [second-generation cut-off](https://cklbradio.com/2025/11/19/elimination-of-first-nations-blood-quantum-now-in-sight/) stripping status from the children of status women who marry out. It continues in the reserve geography that prevents the density hip hop required. It continues in the loss of languages, each one a universe of meaning that does not translate into English, that carries no commercial value in the streaming economy, that dies one elder at a time.\n\nThere are [27 Black billionaires in the world as of 2026](https://www.forbes.com/sites/jabariyoung/2026/03/13/the-worlds-black-billionaires/), managing a combined $121 billion. There is one Indigenous billionaire. Tom Love and his fortune built on truckers needing coffee. I do not begrudge him his coffee empire. I am asking what the gap means, and I think I have arrived at an answer, or the beginning of one.\n\nThe gap is what you get when you take Peoples and try to make them disappear not by concentrating them but by dispersing them, not by forcing them together but by keeping them apart, not by making them forget their homeland, but by making them forget each other. \n\nI am Métis. I carry Michif in my ancestry and English in my mouth and a growing fury in my chest about what was taken and a growing tenderness about what remains. I do not know what our revolution will look like. I know it will not come from a billionaire selling a cable network. I know the revolution will not be televised. It will come from the throat. From the drum. From our continued, enduring presence and existence despite everything. \n\nWe are the tribe they cannot see. We are still here. We are learning, slowly and with enormous difficulty, to see each other.\n\n---\n\n## PART TWO: \"In the Bush, We Were Always Already There\" // Notes Toward an Indigenous Undercommons\n\n### The Logistics\n\n[Blood quantum](https://nativegov.org/resources/blood-quantum-and-sovereignty-a-guide/) is a concept with no Indigenous origin. It was invented by white settlers, a pseudoscientific calculation of \"Indian blood\" as a fraction of a person's lineage, and imposed beginning in the late 19th century as a mechanism of elimination. The more Indigenous people intermarried, the smaller the fractions became, and the fewer people met the threshold, and the fewer people remained legally, bureaucratically *Indigenous*. The federal government used it to strip land and limit treaty obligations. The [Dawes Act of 1887](https://en.wikipedia.org/wiki/Dawes_Act) required a quarter-blood minimum to receive land allotments. Over ninety million acres were transferred from Indigenous to predominantly white settler hands through this mechanism alone.\n\nIn Canada, [the Indian Act](https://indigenousfoundations.arts.ubc.ca/the_indian_act/) operated similarly and still does. Existing for 149 years and counting. Legislation determining who could be \"Indian,\" who could leave the reserve without a pass, who could vote, who could practice ceremony, who could hold land, who could educate their children, who could be a person in the eyes of the state.\n\nIndigenous women who married non-Indigenous men lost their status for decades; their children lost their status; the contraction deliberate and legal. Scholar Pamela Palmater has argued the Act's descent-based rules [will eventually lead to the extinguishment of First Nations as legal and constitutional entities](https://openpolar.no/Record/ftunicalfberklaw:oai:lawcat.berkeley.edu:1287246), unless changed. The blood quantum system is a slow-motion administrative genocide.\n\nCompare this to the so-called \"one-drop rule\" in the United States, which operated in the opposite direction—anyone with any African ancestry was classified as Black. This was a tool of oppression too, of course, designed to ensure that the children of slaveholders and enslaved women remained enslaved. But as a demographic mechanism, it *expanded* the community. It created a larger, more unified group with shared political interests and shared cultural experiences. The architecture of anti-Blackness built community by accident. The architecture of anti-Indigeneity was designed to fragment.\n\nI know what it means to sit at the edge of the question *are you really?*, to have your fraction of belonging interrogated by bureaucrats and, sometimes, by other Indigenous people. Lateral violence. Blood quantum is not only government policy. It is a psychic wound we have inherited, and in some cases inflicted on each other. How can you build cultural renaissance on foundations actively dissolving beneath you?\n\nMoten and Harney call it \"logistics.\" The management of movement, of bodies, of populations through administrative space. [Canadian colonial governance](https://cedarvia.ca/resources/our-common-laws/indian-act-of-1876) did not only dispossess land, it organized bodies. Assigned them to parcels. Timed their movement. \"Our object is to continue,\" said Duncan Campbell Scott of the Department of Indian Affairs, \"until there is not a single Indian in Canada that has not been absorbed.\" Logistics. [A plan](https://www.facinghistory.org/en-ca/resource-library/historical-background-indian-act-indian-residential-schools).\n\nAnd credit. The reserve system held land \"in trust,\" which is to say, [First Nations people did not legally own the land they lived on](https://www.siyamconsulting.com/stories/the-indian-act-a-tool-of-colonial-oppression-against-first-peoples-in-canada), even as it was their ancestral territory. They were in perpetual debt to a Crown that had stolen the collateral. Harney and Moten say that debt cannot be paid off. Debt is a structure of ongoing capture, not a ledger awaiting resolution. The numbered treaties were debt instruments. The land \"cessions\" were credit agreements. The unpayable debt is the point.\n\n### Study in the Hold\n\n[Residential schools](https://indigenousfoundations.arts.ubc.ca/the_residential_school_system/) were explicitly designed to destroy cultures. Children were taken—stolen—from loving families and placed in brutal, racist institutions built on the motto \"kill the Indian, save the child.\" Tiny bodies beaten for speaking their languages. Beautiful hair destroyed. Separated from loving siblings. Assigned numbers and stripped of names. The last residential school in Canada did not close until 1996, the year I was born. There are grandparents alive today who lost their grandchildren to these schools. \n\n[One hundred and fifty thousand children](https://indigenouspeoplesatlasofcanada.ca/article/history-of-residential-schools/) passed through the residential school system over more than a century. \n\nThis trauma isn't far-off, black-and-white, or historical. [The wound is open, current and active. Intergenerational](https://www.kqed.org/education/535528/the-lasting-impact-of-native-american-residential-schools). What was targeted for erasure and elimination? Language, story, and ceremony, the knowledge held in the body of the elder and passed to the child—what Moten and Harney would call the undercommons. The fields holler. The break beats. What was taken from us was not just culture but the capacity of transmission.\n\nThis is what the state called \"education.\" [Schooling, not study](https://autonomedia.org/product/the-undercommons/). The management of persons toward administered outcomes. The production of subjects who would surrender their relationship to land, kin, ceremony—who would become legible to the state, taxable, settleable, absorbed. \n\nWhen you take the children away from the elders for a hundred years, you sever the cord. The body has no one to learn from. The knowledge dies with the last speaker, the last ceremonial practitioner, the last storyteller. The hold is not only a site of capture. The hold is also where the social is made, fugitively, in the darkness, from what the captors could not see or did not think to forbid.\n\nBut children whispered Anishinaabemowin under the covers, passing songs between dormitory walls. But the children taught each other what had been taught to them by their grandmothers before the Indian Agent came. The school newspapers \"carefully created an English-only fantasy for readers, but may also attest to the success of students' secrecy: perhaps official school documents did not report that students still knew Indigenous languages because schools were unaware of this.\"\n\nThe school called it failure. [Government reports, read contrapuntally](https://utppublishing.com/doi/10.3138/9781487521554.004), were \"more forthcoming in how students continued to speak their language, though they framed such resistance as failure.\"  We call it study.\n\nFugitive study. No curriculum, no grade, no recognized institution. Studying that happens in the break, in the undercommons, in the surplus of social life that governance cannot fully account for or contain. Children [running away toward home](https://parks.canada.ca/culture/designation/evenement-event/sys-pensionnats-residential-school-sys). The running was also study, a testimony to what is known about where home is, even when the state has tried to make you forget.\n\n### Gift Against the Credit\n\n[Robin Wall Kimmerer](https://milkweed.org/book/braiding-sweetgrass) writes of the gift economy, older than any word for economy, rooted in Potawatomi relationship to plants, to land, to the non-human persons who give without accounting. \"The awakening of a wider ecological consciousness requires the acknowledgment and celebration of our reciprocal relationship with the rest of the living world.\" This is botany and ceremony insomuch as political theory. She is also, without naming it, writing the undercommons.\n\nBecause the undercommons is what happens when communities refuse the logic of exchange. Refuse to convert everything into a transaction, a credit, a debt to be repaid on colonial terms. Moten and Harney's concept of debt is not Kimmerer's gift, but they share a refusal. The gift economy does not owe, and instead circulates. Feeding without a ledger.\n\n[The Potlatch](https://www.cbc.ca/news/indigenous/150-years-indian-act-9.7152147) was [banned under the Indian Act from 1885 to 1951.](https://umistapotlatch.ca/potlatch_interdire-potlatch_ban-eng.php) Why? Because Potlatch is a ceremony of redistribution—of giving, of building relationship across communities through gift rather than accumulation. The living enactment of gift economy. Nothing to tax or mortgage.\n\nAfter being banned, the practice went underground and continued in secret. The legislation against Aboriginal peoples \"did not stop Aboriginal practices but in most cases drove them underground, or caused Aboriginal peoples to create new ways of continuing them without facing persecution.\" *Drove them underground.* The undercommons is the underground. The potlatch continued in the undercommons for sixty-six years. The gift survived the credit.\n\n### The Surround\n\nImagine [22,000 square kilometres of unceded territory](https://stand.earth/resources/coastal-gaslink-dangerous-project-violates-indigenous-rights/). The size of the state of New Jersey, or the countries Belize or El Salvador. Imagine this land while the RCMP deploys snipers, helicopters, and dogs to remove you. Imagine your sacred headwaters running beneath you and a pipeline drilling toward them from the far side of an injunction. Imagine the legal system of the occupier announcing, as a British Columbia Supreme Court judge did, that though you may \"believe in your rights under Indigenous law to prevent the plaintiff from entering,\" but the law does not recognize this.\n\nMoten and Harney call it the surround. The condition of being encircled by power while refusing absorption into it. The reserve is the surround made spatial. The injunction is the surround made legal. The RCMP raid on [Wet'suwet'en territory](https://thenarwhal.ca/wetsuweten-coastal-gaslink-rcmp-overview/), with snipers aiming at a cabin, an axe and a chainsaw at the door, is the surround made violent.\n\nThe Wet'suwet'en Hereditary Chiefs did not consent. [They issued an eviction notice](https://www.theindigenousfoundation.org/articles/wetsuweten-explained). They declared that Coastal GasLink and the RCMP were trespassers on their Yintah. They rebuilt the camps. Sleydo' (Molly Wickham) said, of defending Wedzin Kwa:\n\n> \"They will not drill under our sacred headwaters because we're going to defend this space until the end. We're not going anywhere.\"\n\nThis is fugitive planning, a declaration rooted in a law far older than the Canadian state, a law grounded in the land. [Glen Coulthard](https://thenewinquiry.com/fires-of-resistance/) calls this \"grounded normativity,\" the ethical framework that emerges from long-standing place-based relationships, from what the land teaches about responsibility. The Wet'suwet'en do not need the Canadian state to recognize their law in order to practice it. They practice it, and that practice is the undercommons.\n\n### The Fugitive University\n\nIn the Northwest Territories, near Yellowknife, on the Chief Drygeese Territory of the Yellowknives Dene First Nation, there is [a university that can only be reached by bush plane, snowmobile, or dog team](https://www.localfutures.org/programs/global-to-local/planet-local/place-based-education/dechinta-centre-for-research-and-learning/). It is called *Dechinta*, the Wiìliìdeh Yatì word for \"bush.\" It is the only fully land-based accredited post-secondary program in the world.\n\nAt Dechinta, students tan moose hides, fish, gather medicines, learn governance by living. Elders are faculty. The land is the curriculum. As Leanne Betasamosake Simpson—writer, activist, faculty at Dechinta—has said: \n\n> \"Indigenous education is not Indigenous or education from within our intellectual traditions unless it comes through the land, unless it occurs in an Indigenous context using Indigenous processes.\"\n\nMoten and Harney distinguish between schooling (the production of administered subjects) and study, which is \"a mode of life\" that escapes and exceeds institutional management. [Dechinta](https://en.ccunesco.ca/initiatives/education-for-sustainable-development/case-study-dechinta) is study. And it is also accredited by the University of Alberta. It holds both. It works from within the institution while refusing to become it. The undercommons do not flee the institution but occupy it, working the institution against its own grain, while \"always being in but never of\" the university's administrative logic.\n\n### Drum as Fugitive Technology\n\nIn December 2012, in shopping malls across Canada, [something strange began to happen](https://www.cbc.ca/radio/unreserved/idle-no-more-reconciliation-1.6663310). People gathered. A drum started. A round dance spread from the food court outward, drawing in shoppers, children, elders, strangers. Idle No More. \n\n> \"When you hear the drum, holy heck, you can't get away from it. You're propelled towards it.\"\n\nInexplicable, joyful, disruptive, ungovernable. The mall is the space of commerce, the space of credit, the space of colonial consumption. The round dance interrupted this, however briefly. Not a protest in the registered, permitted, recognized sense. Not a demand addressed to power. [A direct act of resurgence](https://www.tandfonline.com/doi/abs/10.1080/14747731.2014.971531), as one scholar called it. A direct act of sovereignty.\n\nBetasamosake Simpson, in [*As We Have Always Done*](https://www.upress.umn.edu/9781517903879/as-we-have-always-done/), argues Indigenous resistance \"is a radical rejection of contemporary colonialism focused around the refusal of the dispossession of both Indigenous bodies and land.\" The goal \"can no longer be cultural resurgence as a mechanism for inclusion in a multicultural mosaic.\" The round dance is not asking to be recognized, not for a multicultural display case. It is practicing sovereignty in the space of the surround. The drum does not need an audience. The drum is not performing. The drum is meeting.\n\n### Land is the Undercommons\n\nThe undercommons is the land. [Coulthard and Simpson](https://www.cambridge.org/core/books/democratic-multiplicity/cracking-the-settler-colonial-concrete/46475D137E44E68F50C0FC3C3F4C6BA9) write that \"grounded normativity teaches us how to be in respectful diplomatic relationships with other Indigenous and non-Indigenous nations with whom we might share territorial responsibilities or common political or economic interests.\" The ethical framework is inseparable from the land that generates it. Remove the land and you remove the conditions of possibility for the undercommons itself.\n\nThis is what makes Indigenous undercommons distinct from, and irreducible to, the Black radical tradition Moten and Harney draw from. [Wynter](https://read.dukeupress.edu/books/book/199/Sylvia-WynterOn-Being-Human-as-Praxis) asks us to reconceptualize being human as praxis—as a making, a doing, a refusal of the colonial category of Man. Indigenous resurgence adds that this praxis must be place-based. [The land is not backdrop](https://www.theindigenousfoundation.org/articles/wetsuweten-explained). \"Our people's belief is that we are part of the land. The land is not separate from us. The land sustains us.\" The undercommons here is not an abstract social space. It is the specific boreal forest, the specific river, the specific ceremony, the specific Nishnaabeg constellation.\n\n[Kimmerer](https://guides.libraries.psu.edu/c.php?g=1395558&p=10322140) teaches that \"paying attention is a form of reciprocity with the living world.\" Attention given freely, as a gift, to the world that gives back. The undercommons as the structure of reciprocal attention.\n\n### The Incommensurable and the Shared\n\n[Decolonization is not a metaphor](https://clas.osu.edu/sites/clas.osu.edu/files/Tuck%20and%20Yang%202012%20Decolonization%20is%20not%20a%20metaphor.pdf), as Tuck and Yang have written. Decolonization \"is not an 'and'.\" It is not simply another social justice project to be added to a progressive coalition. It demands the return of land. It has \"a different perspective to human and civil rights based approaches to justice, an unsettling one, rather than a complementary one.\"\n\nMoten and Harney's undercommons is, in the end, a framework developed from and for Black life under anti-Black racial capitalism. [A scholar working in Aotearoa](https://www.academia.edu/84751389/Black_Study_and_Communist_Affect) writes that Moten and Harney's later work is \"important to think with and through, especially in a settler colonial context,\" while acknowledging that \"fugitive here signal[s] the opposite of settling.\" The fugitivity of Blackness and the rootedness of Indigenous sovereignty pull in different directions. The hold of the ship and the dispossession from the land are different violations of different relationships to place.\n\n[The Antipode essay](https://onlinelibrary.wiley.com/doi/abs/10.1111/anti.12615) that responds critically to Tuck and Yang argues that their critique risks collapsing the Black-Indigenous-settler triad into a dyad—that preserving incommensurability must not mean severing the conversation between Black and Indigenous freedom projects. \n\nThe hold, the surround, study, fugitive planning, the shipped, debt—all resonate with Indigenous experience in Canada without being identical. The resonance is not fusion. The resonance is the beginning of a conversation between freedom projects that have different origins, different stakes, and therefore, different gifts to offer each other.\n\nThe potlatch, carried underground for sixty-six years in the mouths and hands of the people the state called wards of the Crown. The children whispering languages into dormitory darkness, framing their resistance as failure so the school would not see it. The Wet'suwet'en Hereditary Chiefs, on unceded land, issuing eviction notices to the RCMP. The round dance breaking out in a mall in Saskatoon, propelled by a drum that could not be permitted or denied. The Nishnaabeg constellation, the Dene knowledge passed on the land at Dechinta, the sweetgrass braided to remember what the university forgot.\n\nMoten and Harney write that the undercommons is not built. Rather, it is found. It is what was already organized [\"every day and every night amid the general antagonism.\"](https://redefineschool.com/the-undercommons/) It is the surplus of social life that administration, logistics, governance, and credit cannot fully contain.\n\nOn Turtle Island, that surplus has a name in countless languages. In every ceremony continued. In every river that is also a legal order, a kinship, a body, a prayer. The undercommons was never a new idea, it was the condition of survival. The undercommons is always our land.\n",
      "date_published": "2026-05-07T07:00:00.000Z",
      "tags": [
        "personal essay",
        "politics",
        "Indigenous",
        "Social Justice"
      ],
      "author": {
        "name": "Brennan Kenneth Brown",
        "url": "https://brennanbrown.ca",
        "email": "mail@brennanbrown.ca"
      }
    }
  ]
}