{
	"version": "https://jsonfeed.org/version/1.1",
	"title": "Adam DJ Brett",
	"language": "en-US",
	"home_page_url": "https://www.adamdjbrett.com/",
	"feed_url": "https://www.adamdjbrett.com/feed/feed.json",
	"description": "Adam DJ Brett Web Developer",
	"author": {
		"name": "Adam DJ Brett",
		"url": "https://www.adamdjbrett.com"
	},
	"items": [
		{
			"id": "https://www.adamdjbrett.com/blog/2026-08-13-tidel/",
			"url": "https://www.adamdjbrett.com/blog/2026-08-13-tidel/",
			"title": "TIDEL Conference: Racial Justice in the Digital Public Square Presentation",
			"content_html": "<p>I'm honored to be presenting alongside Dean Teresa Smallwood at the <strong>Technology, Innovation &amp; Digital Engagement Lab (TIDEL) Symposium</strong> in New York City on <strong>October 1, 2026</strong>.</p>\n<p><img src=\"https://cdn.some.pics/adjb/6a7e17b9c09b3.png\" alt=\"event poster\"></p>\n<p>Here's why this gathering matters to me. Most of us feel it — the sense that technology is moving faster than our ability to think clearly about it. We adopt tools before we've asked what they're for. We watch innovation set the pace and scramble to keep up. TIDEL was created as a space to slow down and ask better questions: How do we make good decisions about our tech use? What does responsible engagement look like when the ground keeps shifting?</p>\n<p>I'll be leading the <strong>Racial Justice in the Digital Public Square</strong> track — a conversation about who gets heard, who gets harmed, and what justice requires of the platforms where so much of our public life now happens. It's work I care deeply about, and I can't think of a better setting for it.</p>\n<p><strong>Two things you can do:</strong></p>\n<p>If you're a scholar or practitioner with something to say, the <strong>call for papers is open through September 15</strong>. I'd love to see your work in the mix — especially in the racial justice track.</p>\n<p>And whether or not you're presenting, <strong>registration is open now at <a href=\"https://www.tidelconference.org\">www.tidelconference.org</a></strong>. Use the code <code>TIDEL20</code> for 20% off.</p>\n<p>New York. October 1. If you're planning to be there, hit reply and let me know — I'd love to connect in person.</p>\n<h2 id=\"event-details\" tabindex=\"-1\">Event Details <a class=\"header-anchor\" href=\"#event-details\">#</a></h2>\n<ul>\n<li><strong>Event:</strong> Technology, Innovation &amp; Digital Engagement Lab (TIDEL) Symposium</li>\n<li><strong>Date:</strong> October 1, 2026 · New York City</li>\n<li><strong>Adam's role:</strong> Presenting alongside Dean Teresa Smallwood; leading the <em>Racial Justice in the Digital Public Square</em> track</li>\n<li><strong>CFP deadline:</strong> September 15 · <strong>Registration:</strong> <a href=\"https://www.tidelconference.org\">www.tidelconference.org</a> · <strong>Code:</strong> <code>TIDEL20</code> (20% off)</li>\n</ul>\n",
			"date_published": "2026-08-13T14:10:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2026-08-13-haudenosaunee-wooden-stick-festival-weekend-2026/",
			"url": "https://www.adamdjbrett.com/blog/2026-08-13-haudenosaunee-wooden-stick-festival-weekend-2026/",
			"title": "The 11th Annual Haudenosaunee Wooden Stick Festival Weekend: A Dinner, a Run, and the Creator&#39;s Game at Onondaga Lake",
			"content_html": "<p>Before lacrosse was a varsity sport, before it was an Olympic event, before it was anything you could buy tickets to, it was a gift. The Haudenosaunee call it Deyhontsigwa'ehs — &quot;They Bump Hips&quot; — and they have played it for over a thousand years as the Creator's Game, a medicine game played for healing and thanksgiving. The game is older than the Haudenosaunee Confederacy itself, and the Confederacy was founded on the shores of Onondaga Lake, where the Peacemaker brought five warring nations together under the Great Law of Peace.</p>\n<p>Which is why what happens at Onondaga Lake every September matters. On September 11–13, 2026, the American Indian Law Alliance hosts the 11th Annual Haudenosaunee Wooden Stick Festival weekend: three days that braid together sport, ceremony, remembrance, and restoration. The festival is free, family-friendly, and open to all. Here is what the weekend holds.</p>\n<h2 id=\"an-evening-for-alfie-the-ambassador-award-dinner\" tabindex=\"-1\">An Evening for Alfie: The Ambassador Award Dinner <a class=\"header-anchor\" href=\"#an-evening-for-alfie-the-ambassador-award-dinner\">#</a></h2>\n<p><strong>Friday, September 11 · 5:00 PM · Bellevue Country Club, Syracuse · <a href=\"https://alfieaward.com\">alfieaward.com</a></strong></p>\n<p><img src=\"https://cdn.some.pics/adjb/6a7caa4e68612.png\" alt=\"alfie in his workshop making a wooden stick\"></p>\n<p>For more than fifty years, Alfie Jacques of the Onondaga Nation made wooden lacrosse sticks by hand — tens of thousands of them, each one bent, carved, and strung the traditional way, and each one an occasion to teach someone about where the game comes from. When Alfie passed, the lacrosse world lost its greatest stickmaker and one of its most beloved teachers.</p>\n<p>The Alfie Jacques Ambassador Award keeps that teaching alive. It honors leaders who grow the game with the same selfless dedication and the same reverence for its Indigenous heritage that defined Alfie's life. The 2026 honorees are Dom Starsia, the championship college coach; Michael Kennedy, a leader in international lacrosse; and Mike Kanatakeron Mitchell, a Haudenosaunee ambassador for the game. The award itself is carved by Ryan Sandy of Six Nations, and proceeds from the evening fund a college scholarship for Native American youth.</p>\n<h2 id=\"the-restore-our-sacred-lake-5k\" tabindex=\"-1\">The Restore Our Sacred Lake 5K <a class=\"header-anchor\" href=\"#the-restore-our-sacred-lake-5k\">#</a></h2>\n<p><strong>Onondaga Lake · Register at <a href=\"https://aila.li/run\">aila.li/run</a></strong>\n<img src=\"https://cdn.some.pics/adjb/6a7ca9dbd0fde.png\" alt=\"The top of flyer shows traditional wooden stick players raising their sticks high in the air along with the text above repeated.\"></p>\n<p>Onondaga Lake holds a double identity. It is the birthplace of the Haudenosaunee Confederacy — among the most sacred places in Haudenosaunee territory — and it spent the twentieth century becoming one of the most polluted lakes in America. The Restore Our Sacred Lake 5K exists in the space between those two facts.</p>\n<p>The run brings the community onto the lake's shoreline in support of its ongoing restoration. It is welcoming by design: runners chasing a personal best, families walking with strollers, first-timers, and shoreline cheering sections all belong. Registration is open now at <a href=\"https://aila.li/run\">aila.li/run</a>.</p>\n<h2 id=\"the-wooden-stick-festival-and-randy-hall-memorial-tournament\" tabindex=\"-1\">The Wooden Stick Festival and Randy Hall Memorial Tournament <a class=\"header-anchor\" href=\"#the-wooden-stick-festival-and-randy-hall-memorial-tournament\">#</a></h2>\n<p><strong>Saturday &amp; Sunday, September 12 &amp; 13 · Onondaga Lake · Free admission</strong></p>\n<p>The heart of the weekend is the festival itself: two days of wooden stick lacrosse played the way it has been played for centuries. The Randy Hall Memorial Tournament runs throughout the weekend, honoring Randy Hall of Akwesasne, the coach and player who in 2013 set the game back on the shores of Onondaga Lake and started the tradition the festival continues today.</p>\n<p>Around the tournament, the park fills with the rest of the celebration: Smoke Dancing, traditional stick-making demonstrations, Haudenosaunee singers and dancers, Indigenous food, and craft artisans. It is equal parts sporting event, cultural teaching, and family reunion — and everyone is invited to all three parts.</p>\n<h2 id=\"plan-your-weekend\" tabindex=\"-1\">Plan Your Weekend <a class=\"header-anchor\" href=\"#plan-your-weekend\">#</a></h2>\n<p>The festival weekend runs September 11–13, 2026. The Alfie Jacques Ambassador Award Dinner opens the weekend Friday evening at Bellevue Country Club (<a href=\"https://alfieaward.com\">alfieaward.com</a>); the festival, tournament, Smoke Dancing, and 5K fill Saturday and Sunday at Onondaga Lake. Festival admission is free.</p>\n<p><strong>Register for the run: <a href=\"https://aila.li/run\">aila.li/run</a></strong>\n<strong>Learn more about the weekend: <a href=\"https://aila.li/wsf\">aila.li/wsf</a></strong></p>\n<p>Come to the lake. The game began here — and every September, it comes home.</p>\n",
			"date_published": "2026-08-13T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/two-domains-one-build-eleventy-xmit/",
			"url": "https://www.adamdjbrett.com/blog/two-domains-one-build-eleventy-xmit/",
			"title": "Two Domains, One Build: Hosting .ngo and .ong Together with Eleventy and xmit",
			"content_html": "<p>There is a very particular kind of joy that comes from solving a web problem whose final answer is smaller than the problem felt.</p>\n<p>I wanted the American Indian Law Alliance website to live at both <a href=\"https://aila.ngo/\">aila.ngo</a> and <code>aila.ong</code>. The pairing matters: <code>.ngo</code> is the primary address, while <code>.ong</code> is its parallel form. I did not want the second domain to bounce visitors to the first. If somebody requests <code>/give/</code>, a blog post, an image, a PDF, or any other site resource from either hostname, that hostname should serve the resource itself.</p>\n<p>This sounds ordinary until the requirements are stated precisely. It is not a redirect rule. It is not an alias that only works for the homepage. It is the entire generated site—hundreds of pages and a large document archive—available under two fully qualified domains.</p>\n<p>When I finally had it working, I felt euphoric. Not because the solution was elaborate, but because it was not.</p>\n<h2 id=\"one-canonical-build\" tabindex=\"-1\">One canonical build <a class=\"header-anchor\" href=\"#one-canonical-build\">#</a></h2>\n<p>The site is built with Eleventy. Eleventy writes the finished static site to <code>dist</code>, so there is no application server and no runtime routing layer to duplicate. The first important decision was to build only once.</p>\n<p>I set the production URL to the primary domain:</p>\n<pre class=\"language-yaml\" tabindex=\"0\"><code class=\"language-yaml\"><span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Build Eleventy site\n  <span class=\"token key atrule\">run</span><span class=\"token punctuation\">:</span> npm run build\n  <span class=\"token key atrule\">env</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">URL</span><span class=\"token punctuation\">:</span> https<span class=\"token punctuation\">:</span>//aila.ngo</code></pre>\n<p>That keeps canonical links, Open Graph URLs, feeds, and the sitemap anchored to <code>aila.ngo</code>. Search engines get one authoritative address even though human beings can use either domain. The parallel domain serves the same HTML, but the metadata continues to identify the primary.</p>\n<p>This distinction cleared up much of my confusion: “available at two domains” does not have to mean “build two versions.”</p>\n<h2 id=\"let-xmit-launch-the-same-bundle-twice\" tabindex=\"-1\">Let xmit launch the same bundle twice <a class=\"header-anchor\" href=\"#let-xmit-launch-the-same-bundle-twice\">#</a></h2>\n<p><a href=\"https://xmit.co/\">xmit</a> is unusually well suited to this because it treats a static deployment as a content-addressed bundle. It hashes the files and uploads only content it does not already have. My site includes a substantial collection of PDFs, images, fonts, Pagefind indexes, and ordinary HTML. Uploading the same unchanged bytes twice would be absurd. xmit recognizes that they are the same bytes.</p>\n<p>The domain-to-team syntax is also wonderfully small. Team 389 is written after the hostname:</p>\n<pre class=\"language-sh\" tabindex=\"0\"><code class=\"language-sh\">xmit <span class=\"token string\">\"aila.ngo@389\"</span> dist\nxmit <span class=\"token string\">\"aila.ong@389\"</span> dist</code></pre>\n<p>That is the heart of the solution. Both commands launch the complete <code>dist</code> directory. Neither command contains a path list because none is needed. <code>/give/</code> was my first test, but it is not a special case. Every post, page, image, stylesheet, font, feed, search index, and document goes along with it.</p>\n<p>The production workflow adds retries because an 800-plus-megabyte site should not fail permanently over one transient network error:</p>\n<pre class=\"language-yaml\" tabindex=\"0\"><code class=\"language-yaml\"><span class=\"token key atrule\">env</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">XMIT_PRIMARY_SITE</span><span class=\"token punctuation\">:</span> aila.ngo\n  <span class=\"token key atrule\">XMIT_PARALLEL_SITE</span><span class=\"token punctuation\">:</span> aila.ong\n\n<span class=\"token key atrule\">steps</span><span class=\"token punctuation\">:</span>\n  <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Deploy to xmit\n    <span class=\"token key atrule\">env</span><span class=\"token punctuation\">:</span>\n      <span class=\"token key atrule\">XMIT_KEY</span><span class=\"token punctuation\">:</span> $<span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> secrets.XMIT_KEY <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span>\n    <span class=\"token key atrule\">run</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">|</span><span class=\"token scalar string\">\n      for site in \"$XMIT_PRIMARY_SITE\" \"$XMIT_PARALLEL_SITE\"; do\n        deployed=false\n        for attempt in 1 2 3; do\n          if ./node_modules/.bin/xmit \"$site@389\" dist; then\n            deployed=true\n            break\n          fi\n          sleep $((attempt * 15))\n        done\n        [ \"$deployed\" = true ] || exit 1\n      done</span></code></pre>\n<p>The DNS records for both domains point to xmit, and xmit serves each requested hostname directly. A request to <code>https://aila.ong/give/</code> stays on <code>aila.ong</code>; it is not sent to <code>aila.ngo</code>. Yet both responses come from one Eleventy build.</p>\n<h2 id=\"the-speed-came-from-doing-less\" tabindex=\"-1\">The speed came from doing less <a class=\"header-anchor\" href=\"#the-speed-came-from-doing-less\">#</a></h2>\n<p>The other satisfying part was making repeat deployments faster without inventing a new build system. Eleventy’s image pipeline already maintains a cache, so GitHub Actions only needed to preserve it:</p>\n<pre class=\"language-yaml\" tabindex=\"0\"><code class=\"language-yaml\"><span class=\"token punctuation\">-</span> <span class=\"token key atrule\">uses</span><span class=\"token punctuation\">:</span> actions/cache@v6\n  <span class=\"token key atrule\">with</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">path</span><span class=\"token punctuation\">:</span> .cache/@11ty/img\n    <span class=\"token key atrule\">key</span><span class=\"token punctuation\">:</span> eleventy<span class=\"token punctuation\">-</span>images<span class=\"token punctuation\">-</span>$<span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> runner.os <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">-</span>$<span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> hashFiles('package<span class=\"token punctuation\">-</span>lock.json') <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span>\n    <span class=\"token key atrule\">restore-keys</span><span class=\"token punctuation\">:</span> eleventy<span class=\"token punctuation\">-</span>images<span class=\"token punctuation\">-</span>$<span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> runner.os <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">-</span></code></pre>\n<p>That cache is about 53 MB. Restoring it avoids regenerating responsive images on every clean runner. Pagefind takes less than a second; it was never the bottleneck. Dependency installation was already cached by <code>setup-node</code>. xmit already avoids resending unchanged content. The fast solution was to let each tool do the job it already knew how to do.</p>\n<p>There are more sophisticated architectures for multi-domain publishing. I do not need one. I need a single canonical Eleventy build, two real hostnames, one xmit team, and a workflow boring enough that I will understand it six months from now.</p>\n<p>That is what produced the joy: not merely seeing both domains resolve, but realizing that the correct model had been sitting in front of me all along. Build the site once. Name the primary. Launch the same artifact wherever it belongs.</p>\n",
			"date_published": "2026-07-30T16:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/writing-support-resources/",
			"url": "https://www.adamdjbrett.com/blog/writing-support-resources/",
			"title": "Writing Support Resources",
			"content_html": "<h2 id=\"writing-support-resources\" tabindex=\"-1\">Writing Support Resources <a class=\"header-anchor\" href=\"#writing-support-resources\">#</a></h2>\n<p>These resources support the writing process itself: the language you use, the community that holds you accountable, and the institutional tools already available to you at no extra cost.</p>\n<h3 id=\"coaching-and-community\" tabindex=\"-1\">Coaching and community <a class=\"header-anchor\" href=\"#coaching-and-community\">#</a></h3>\n<p><a href=\"https://eileencampbellreed.org/writing-table-and-freewrite-fridays/\">Eileen Campbell-Reed's Writing Table</a> is a weekly virtual writing session for academic and ministry-related writers, built on Robert Boice's research showing that writing briefly and daily builds a more lasting habit than writing in long, infrequent bursts. The Friday session remains free to attend, and it welcomes professors, pastors, students, and anyone else working on a long writing project.</p>\n<p>The Grafton Line is a private Facebook group for peer support and accountability during the writing process.</p>\n<h3 id=\"reference-language-and-templates\" tabindex=\"-1\">Reference language and templates <a class=\"header-anchor\" href=\"#reference-language-and-templates\">#</a></h3>\n<p>The <a href=\"https://www.phrasebank.manchester.ac.uk/\">Academic Phrasebank</a>, developed by the University of Manchester, is a free bank of example academic phrasing for introductions, methods, results, and other common sections. Use it when you know what you want to say but not how academic prose usually says it.</p>\n<h3 id=\"through-your-library\" tabindex=\"-1\">Through your library <a class=\"header-anchor\" href=\"#through-your-library\">#</a></h3>\n<p>Your university's writing center and library often provide free or discounted access to tools you would otherwise pay for yourself, including Grammarly, EndNote, and NVivo for qualitative analysis. Check with your library before purchasing any of these on your own.</p>\n<h3 id=\"staying-current\" tabindex=\"-1\">Staying current <a class=\"header-anchor\" href=\"#staying-current\">#</a></h3>\n<p>Set up citation alerts through <a href=\"https://scholar.google.com/\">Google Scholar</a> for your key authors and search terms, so you are notified as soon as new work appears in your niche rather than having to remember to check.</p>\n",
			"date_published": "2026-07-21T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/scholarly-apps-and-tools/",
			"url": "https://www.adamdjbrett.com/blog/scholarly-apps-and-tools/",
			"title": "Apps and Tools for Research and Writing",
			"content_html": "<h2 id=\"apps-and-tools-for-research-and-writing\" tabindex=\"-1\">Apps and Tools for Research and Writing <a class=\"header-anchor\" href=\"#apps-and-tools-for-research-and-writing\">#</a></h2>\n<p>These tools cover the three jobs your writing workflow needs done: keeping track of sources, giving you a quiet place to write, and holding your notes and outlines together as your project grows.</p>\n<h3 id=\"reference-managers\" tabindex=\"-1\">Reference managers <a class=\"header-anchor\" href=\"#reference-managers\">#</a></h3>\n<p><a href=\"https://www.zotero.org/\">Zotero</a> is a free, open source reference manager that saves citations directly from your browser, organizes PDFs by project, and formats citations and bibliographies in whatever style your target journal requires. It is the reference manager most widely recommended in academic writing guides because it has no cost barrier and works the same way across Mac, Windows, and Linux.</p>\n<p><a href=\"https://www.mendeley.com/\">Mendeley</a> is a reference manager owned by Elsevier. It offers similar citation and PDF organization features to Zotero, plus a built-in academic social network for finding related papers and authors. Check whether your university library already has an institutional Mendeley license before you choose between the two.</p>\n<p><a href=\"https://www.notabene.com/\">Nota Bene</a> is an integrated word processor and bibliographic manager built specifically for humanities scholars. Its Ibidem bibliographic database and multilingual support make it a strong choice if your project draws on primary sources in ancient or modern languages beyond English.</p>\n<h3 id=\"distraction-free-writing\" tabindex=\"-1\">Distraction-free writing <a class=\"header-anchor\" href=\"#distraction-free-writing\">#</a></h3>\n<p><a href=\"https://bywordapp.com/\">Byword</a> is a lightweight Markdown editor for Mac, iPhone, and iPad. It syncs drafts through iCloud or Dropbox, so you can start a section on your laptop and keep writing on your phone, and it is a one-time purchase rather than a subscription.</p>\n<h3 id=\"morning-pages-and-daily-writing\" tabindex=\"-1\">Morning pages and daily writing <a class=\"header-anchor\" href=\"#morning-pages-and-daily-writing\">#</a></h3>\n<p><a href=\"https://750words.com/\">750 Words</a> gives you a private, browser-based space to write roughly three pages every morning, following the &quot;morning pages&quot; practice popularized by Julia Cameron's The Artist's Way. Many writers use it to clear their head before turning to the dissertation itself.</p>\n<p><a href=\"https://simplenote.com/\">Simplenote</a> is a free, minimal, cross-platform note app. Its instant sync and full version history make it a good home for quick daily writing or journal-style reflections you want to keep separate from your formal drafts.</p>\n<h3 id=\"structured-research-and-writing-platforms\" tabindex=\"-1\">Structured research and writing platforms <a class=\"header-anchor\" href=\"#structured-research-and-writing-platforms\">#</a></h3>\n<p><a href=\"https://www.overleaf.com/\">Overleaf</a> is a browser-based LaTeX editor. It matters if your target journal expects a LaTeX submission, or if you are co-writing with collaborators who prefer LaTeX to Word.</p>\n<p><a href=\"https://www.notion.so/\">Notion</a> is a flexible workspace that can hold your reading notes, dissertation outline, and weekly task list in one connected system, which helps if you would rather manage the whole project in one place than juggle several separate apps.</p>\n<p><a href=\"https://obsidian.md/\">Obsidian</a> is a local-first, Markdown-based note app built around linking ideas together. It is popular for literature notes, since it lets you connect a quote or concept from one source directly to related ideas from other sources as your reading grows.</p>\n<p><a href=\"https://notesnook.com/\">Notesnook</a> is a free, open source, end-to-end encrypted note app. It is a strong private alternative if you want your research notes stored with zero-knowledge encryption, meaning even the app's own developers cannot read them.</p>\n<p><a href=\"https://miro.com/\">Miro</a> is an online collaborative whiteboard built around sticky notes, arrows, and text boxes. It is especially useful for a literature review, since you can write a short summary of each source on its own note and physically drag related sources into the same cluster until your themes emerge visually instead of staying buried in a spreadsheet.</p>\n<h3 id=\"time-management\" tabindex=\"-1\">Time management <a class=\"header-anchor\" href=\"#time-management\">#</a></h3>\n<p><a href=\"https://tomato-timer.com/\">Tomato Timer</a> is a free, no-signup online Pomodoro timer. Set it to 25 minutes, work until it rings, then take a short break. It is the simplest possible way to try time-boxing before committing to a heavier app.</p>\n<h3 id=\"digital-storytelling-and-visualization-tools\" tabindex=\"-1\">Digital storytelling and visualization tools <a class=\"header-anchor\" href=\"#digital-storytelling-and-visualization-tools\">#</a></h3>\n<p>Northwestern University's <a href=\"https://knightlab.northwestern.edu/\">Knight Lab</a> publishes a suite of free, open source tools built for telling stories with data. <a href=\"https://timeline.knightlab.com/\">TimelineJS</a> turns a spreadsheet into an interactive timeline, which is useful for laying out the history behind a research question or the sequence of events in a case study. <a href=\"https://storymap.knightlab.com/\">StoryMapJS</a> does the same for geography, mapping a professional practice or field site across locations. Both are free and require no coding experience.</p>\n<h3 id=\"further-reading\" tabindex=\"-1\">Further reading <a class=\"header-anchor\" href=\"#further-reading\">#</a></h3>\n<p><a href=\"https://medium.com/@sharonashferguson/streamline-grad-school-with-these-8-tools-a92a52e80518\">Streamline Grad School with These 8 Tools (Sharon Ferguson, Medium)</a> walks through one PhD student's everyday toolkit, including several tools already listed above plus cloud storage and meeting-note habits worth adapting to your own workflow.</p>\n",
			"date_published": "2026-07-21T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/kanban-for-dissertation-and-article-writing/",
			"url": "https://www.adamdjbrett.com/blog/kanban-for-dissertation-and-article-writing/",
			"title": "The Kanban Method for Dissertation and Journal Article Writing",
			"content_html": "<h2 id=\"the-kanban-method-for-dissertation-and-journal-article-writing\" tabindex=\"-1\">The Kanban Method for Dissertation and Journal Article Writing <a class=\"header-anchor\" href=\"#the-kanban-method-for-dissertation-and-journal-article-writing\">#</a></h2>\n<p>Kanban is a visual work-management method that started on Toyota's factory floor in the 1940s, where cards, kanban in Japanese, signaled when a workstation needed more material. Software teams adapted it decades later, and individual writers now borrow the same logic to manage a project too large to hold in their head all at once, whether that project is a dissertation, a journal article, or a full season of writing across both.</p>\n<p>The method comes down to one idea. Take a board with a small number of columns, commonly something like Not Started, Drafting, Revising, and Done, and represent each unit of your work as a card that moves left to right as it progresses. Chunking, breaking a large project into visible units, is the whole discipline behind it. An 80,000-word dissertation is not a task you can act on directly. A board holding forty specific cards, each one a subsection, a data chapter, or a round of feedback, is something you can actually work through one card at a time.</p>\n<p>For dissertation writing, cards work best when they represent chapter sections rather than whole chapters. A whole chapter can sit on a board for months without moving and stop telling you anything useful. Sharper cards look like &quot;Chapter 3: code the interview transcripts,&quot; &quot;Chapter 3: draft the findings narrative,&quot; or &quot;Chapter 2: revise after advisor comments.&quot; Each card advances on its own timeline, so a glance at the board shows which chapters are stalled in revision and which have barely started, instead of leaving you with only a vague sense that &quot;the dissertation is coming along.&quot;</p>\n<p>For journal article writing, the columns map naturally onto the submission pipeline: Drafting, Internal Review, Submitted, Under Peer Review, Revise and Resubmit, Published. One card per article in progress lets you track several submissions at once without losing track of which one is waiting on you and which is waiting on an editor. Keeping a target journal in view from early in the writing process matters, rather than treating submission as an afterthought once a draft is finished.</p>\n<p>Kanban's second core practice, alongside chunking, is limiting work in progress. The method caps how many cards can sit in an &quot;in progress&quot; column at once, often just one or two. The constraint is deliberate. Writers who let five sections sit half-finished at the same time tend to finish none of them quickly, while writers who complete one card before pulling the next tend to accumulate finished work steadily. A work-in-progress limit turns &quot;I am working on my dissertation&quot; into &quot;I am finishing this one section, right now,&quot; which is a much easier sentence to act on.</p>\n<p>You do not need special software to run this. Index cards on a wall or a whiteboard divided into columns work exactly as well as an app. If you would rather keep it digital, Notion and Miro include built-in kanban board views, and dedicated tools such as Trello follow the same model. The board itself matters less than the habit it enforces: name the next small piece of work, finish it, and move the card.</p>\n",
			"date_published": "2026-07-21T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/in-praise-of-zotero/",
			"url": "https://www.adamdjbrett.com/blog/in-praise-of-zotero/",
			"title": "In Praise of Zotero",
			"content_html": "<h2 id=\"in-praise-of-zotero\" tabindex=\"-1\">In Praise of Zotero <a class=\"header-anchor\" href=\"#in-praise-of-zotero\">#</a></h2>\n<p>Every writer's toolkit has to pick one hill to die on. This is mine: use Zotero.</p>\n<p>Zotero solves the one problem that quietly derails more dissertations than bad theory ever does, which is losing track of what you read and where you read it. Click the browser extension on a journal article, a library catalog page, or even a well-formed website, and Zotero pulls the full citation, the PDF, and often the abstract into your library without you typing a single field by hand. Do that consistently from the first week of your literature review, and by the time you are drafting, your bibliography already exists. You are not reconstructing it from memory the night before a deadline, hunting for a DOI you half-remember, or discovering that a crucial source is a library-loan PDF you can no longer find on your laptop.</p>\n<p>The case for Zotero over its competitors is mostly a case for what it does not do. It does not charge you to use it. The desktop application, browser extension, and word processor plugins are entirely free, and the only cost that ever shows up is optional cloud storage for PDFs beyond a generous free allowance, which most doctoral projects never hit. It does not lock your library into one vendor's ecosystem either. Your citation data lives in an open format you can export at any time, which matters if a subscription-based competitor changes its pricing or its terms partway through your program.</p>\n<p>Inside a manuscript, Zotero's word processor plugin inserts and reformats citations and full bibliographies automatically, in whatever style your target journal specifies. Switching a completed draft from APA to Chicago, something that happens more often than any writer would like, becomes one menu selection instead of an afternoon of manual reformatting. That single feature is worth adopting the tool for on its own.</p>\n<p>None of this requires Zotero to be perfect. Its interface is plain rather than polished, and Mendeley's built-in social network for discovering related authors is a real feature Zotero does not try to match. But polish is not the job a reference manager is hired to do. The job is to make sure that six months from now, every claim in your article traces cleanly back to a source you can still find, cited in the format your journal requires, without you having to remember how you found it. Zotero does that job as well as anything available, and it does it for free.</p>\n<p>If you take nothing else from this post, adopt this: install Zotero before you read your next source, not after you've read fifty more without it.</p>\n",
			"date_published": "2026-07-21T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/frame-analysis-critical-theory-and-english-language-teaching-review/",
			"url": "https://www.adamdjbrett.com/blog/frame-analysis-critical-theory-and-english-language-teaching-review/",
			"title": "Review: Frame Analysis, Critical Theory, and English Language Teaching",
			"content_html": "<h2 id=\"frame-analysis-critical-theory-and-english-language-teaching\" tabindex=\"-1\">Frame Analysis, Critical Theory, and English Language Teaching <a class=\"header-anchor\" href=\"#frame-analysis-critical-theory-and-english-language-teaching\">#</a></h2>\n<p><strong>By Robert J. Lowe</strong>\n<em>Routledge, 2026</em></p>\n<blockquote>\n<p>Lowe, Robert J. 2026. <em>Frame Analysis, Critical Theory, and English Language Teaching</em>. Abingdon: Routledge. ISBN 978-1-032-54469-4 (hardback), 978-1-032-53280-6 (paperback), 978-1-003-42505-2 (ebook).</p>\n</blockquote>\n<p>Robert J. Lowe opens with a confession common to critical scholars but rarely examined this carefully: he had been calling his research &quot;critical&quot; for years without being able to say precisely what the word committed him to. Applied linguistics and English language teaching research host at least two incompatible traditions under that label, Lowe notes, a neo-Marxist, structural strand focused on redistribution and a poststructuralist strand focused on identity and discourse, and moving between them without a stated theoretical home left his own native-speakerism research, he came to feel, undertheorized. His solution is to build a research method, which he calls frame analysis, directly out of Max Horkheimer's early critical theory, particularly the concept of immanent critique, and then to test that method on a real classroom of Japanese university students studying English. The book is simultaneously a work of intellectual history, a methodological manual, and a research report, and it is unusually honest about the seams between those three functions.</p>\n<h3 id=\"a-genuinely-useful-synthesis\" tabindex=\"-1\">A genuinely useful synthesis <a class=\"header-anchor\" href=\"#a-genuinely-useful-synthesis\">#</a></h3>\n<p>The theoretical achievement here deserves to be taken seriously by qualitative researchers well outside applied linguistics. Lowe's frame analysis borrows &quot;master framing&quot; and &quot;counter-framing&quot; from social movement theory (Snow and Benford) and from Joe Feagin's work on the white racial frame, then fuses that vocabulary with Horkheimer's immanent critique: rather than importing an external ideology critique and applying it to participants from outside, the researcher identifies the internally held, consciously expressed beliefs that make up a participant's &quot;master frame,&quot; then surfaces the participant's own tacit awareness of contradictions between that frame and their lived social reality. When the technique works, it produces a specific, observable outcome, &quot;counter-framing,&quot; in which participants themselves generate new understandings that resolve the contradiction, rather than the researcher simply asserting that the participants are falsely conscious. This is a real methodological contribution: most ideology-critique research either stops at diagnosis (participants are shown to be mistaken) or smuggles the researcher's political conclusions in as the participants' own discoveries. Lowe's design, in principle, makes the participants' own reasoning the site of the finding, and the book's case study bears this out in a genuinely interesting way. His students began the course endorsing standard liberal-pluralist claims about English as a &quot;common resource&quot; that &quot;all Englishes&quot; access equally; through the frame analysis intervention they came to recognize the tension between that pluralism and the material reality that certain &quot;inner circle&quot; varieties of English carry more institutional and economic weight, and produced a more structurally aware, if still individualist, revised framing centered on expanded choice rather than enforced standardization.</p>\n<h3 id=\"the-candor-is-the-strongest-chapter\" tabindex=\"-1\">The candor is the strongest chapter <a class=\"header-anchor\" href=\"#the-candor-is-the-strongest-chapter\">#</a></h3>\n<p>What sets this book apart from typical methods guides is Lowe's conclusion, which reads less like triumphant validation and more like a research diary of everything that could go wrong. He flags, unprompted, that his students' revised framing &quot;does not fully transcend the essentially liberal values they began the course with,&quot; and cites Marxist critics of just this kind of individualist resolution to make the point against his own findings. He admits that frame analysis as demonstrated here falls short of Horkheimer's original standard, that critique requires &quot;a fully developed material theory of society,&quot; conceding that his own &quot;bricolage&quot; leans more on reflexive qualitative data collection than on the historical-materialist grounding Horkheimer's method presupposes, and calls this, bluntly, &quot;perhaps practising sleight of hand.&quot; He is equally direct about a structural problem in his research design that many qualitative studies would bury in a footnote: he was simultaneously the students' teacher and their researcher, which gave him extraordinary latitude to raise ideological contradictions in class time but also meant his authority over the participants' grades and standing could easily have produced compliant rather than genuine counter-framing. Few methods books volunteer this level of self-implicating detail, and it makes the book considerably more trustworthy than one that presented frame analysis as a clean, generalizable tool.</p>\n<h3 id=\"where-the-candor-doesnt-go-far-enough\" tabindex=\"-1\">Where the candor doesn't go far enough <a class=\"header-anchor\" href=\"#where-the-candor-doesnt-go-far-enough\">#</a></h3>\n<p>That said, Lowe's own diagnosis of the teacher-researcher power imbalance resolves too quickly into reassurance. His ethical defense, that participants &quot;already given their consent for things in the setting to be documented&quot; simply by allowing him into the classroom, treats institutional access as equivalent to informed consent to have one's political views actively challenged and revised by the person grading your coursework, which is a considerably higher bar than consenting to be observed. Lowe's own comparison of frame analysis to the &quot;observer's paradox,&quot; the idea that all research inevitably influences its subjects, is true but does real work to flatten a difference in degree that matters here: there is a meaningful gap between a researcher's presence subtly altering behavior and a researcher-instructor deliberately engineering contradictions for students to resolve as part of a graded final project. The book would be stronger if it treated this asymmetry as a genuine limitation on the method's ethical portability, rather than folding it into the general, unavoidable messiness of qualitative fieldwork.</p>\n<p>The single-classroom scope is the other real constraint, one Lowe names but doesn't fully reckon with. The study draws on a small, mixed group of students from two countries with no shared prior training pathway, which Lowe himself notes makes it impossible to identify where their initial ideological framing actually came from, textbooks, teacher training, popular discourse, or some combination he cannot disentangle. He proposes, reasonably, that future researchers study a more homogeneous cohort, teachers who completed the same training program, to isolate a specific transmission mechanism. But this means the book's central case study functions more as a proof of concept for the method's mechanics than as a demonstration of what frame analysis can actually reveal about how ELT ideology is produced and circulated at scale, the larger claim the book's opening chapters gesture toward.</p>\n<h3 id=\"a-genuinely-rare-intellectual-historical-contribution\" tabindex=\"-1\">A genuinely rare intellectual-historical contribution <a class=\"header-anchor\" href=\"#a-genuinely-rare-intellectual-historical-contribution\">#</a></h3>\n<p>One quieter virtue of the book is its literature review of how Frankfurt School theory has actually been used, and misused, in applied linguistics. Lowe is sharp and specific in noting that critical ELT scholarship has drawn heavily on Habermas and occasionally Honneth while almost entirely skipping Horkheimer's founding formulation of critical theory, and he singles out Bernard Spolsky's recent work for flattening the difference between 1930s Horkheimer and 1960s Marcuse into an undifferentiated &quot;identity politics&quot; ancestor, a criticism that lands because Lowe has done the historical homework to back it up. This kind of returning-to-the-source move is exactly what a field drowning in loosely defined &quot;critical&quot; research needs, and it is a genuine service independent of whether frame analysis itself catches on as a method.</p>\n<h3 id=\"verdict\" tabindex=\"-1\">Verdict <a class=\"header-anchor\" href=\"#verdict\">#</a></h3>\n<p><em>Frame Analysis, Critical Theory, and English Language Teaching</em> is a rigorous, unusually self-aware attempt to give critical ELT research an actual theoretical spine, and researchers in applied linguistics and adjacent qualitative fields will find frame analysis a genuinely portable technique, not just an English-teaching curiosity. Lowe's willingness to name his method's shortfalls, from its incomplete fidelity to Horkheimer's materialism to its small sample size, is the book's most valuable feature and sets a standard other methods books should be held to. But that same candor stops just short of the place it most needs to go: the ethical weight of a teacher using classroom authority to engineer students' ideological transformation as part of their coursework. Lowe has built a genuinely interesting tool. Whether it can be responsibly used by anyone who is not, like him, both the students' evaluator and their critic remains the book's most important unanswered question.</p>\n",
			"date_published": "2026-07-20T06:14:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/kant-machine-review/",
			"url": "https://www.adamdjbrett.com/blog/kant-machine-review/",
			"title": "Review: Kant Machine: Critical Philosophy after AI",
			"content_html": "<h2 id=\"kant-machine-critical-philosophy-after-ai\" tabindex=\"-1\">Kant Machine: Critical Philosophy after AI <a class=\"header-anchor\" href=\"#kant-machine-critical-philosophy-after-ai\">#</a></h2>\n<p><strong>By Yuk Hui</strong>\n<em>Bloomsbury Academic, 2026 (Political Theory and Contemporary Philosophy series)</em></p>\n<blockquote>\n<p>Hui, Yuk. 2026. <em>Kant Machine: Critical Philosophy after AI</em>. London: Bloomsbury Academic. ISBN 978-1-3505-6320-9 (hardback), 978-1-3506-0250-2 (paperback), 978-1-3505-6321-6 (ePDF).</p>\n</blockquote>\n<p>The book opens with an epigraph from Turing's 1950 paper: &quot;Can a machine be made to be super-critical?&quot; Turing meant the term in the nuclear sense, a machine whose ideas set off chain reactions of further ideas. Yuk Hui hears the pun that Turing did not intend. Can a machine be critical in Kant's sense, aware of its own limits, legislating for itself, capable of judgment rather than mere execution? The whole book lives inside that pun, and the surprising thing is how much philosophical work it turns out to do.</p>\n<p>Hui's wager is stated plainly in the preface. Kant's philosophy can be read as a reflection on two ways of constructing machines, represented by rationalism and empiricism, and these two eighteenth-century schools still govern how we understand machines today, in the debate between symbolic AI and connectionism. The Cartesian machine follows innate rules. The Humean machine learns from experience. GOFAI and deep learning, in other words, were fighting Kant's war two centuries late, and Kant's critical philosophy, which was built precisely to overcome the dogmatism of the first and the scepticism of the second, might therefore have something to say about where both projects run aground. This is the kind of framing that sounds obvious once stated and was stated by nobody before. It gives the current AI debates a philosophical genealogy deeper than the usual references to Dreyfus and Searle, and it explains why those debates feel so stuck: they are repetitions, Hui argues, of the very impasse that made critical philosophy necessary in the first place.</p>\n<p>The book is short, three chapters over roughly 117 pages, and organized with a symmetry that is itself a Kantian joke. Kant's three questions, what can I know, what must I do, what may I hope for, become three questions about machines: What kinds of machines are intelligent? Are machines capable of being moral? Does an algorithm of perpetual peace exist? The latent question, Hui notes, shifts accordingly from &quot;what is the human?&quot; to &quot;what is the machine?&quot; He is candid that the book concludes a long engagement, extending threads from <em>Recursivity and Contingency</em> (2019), <em>Art and Cosmotechnics</em> (2021), and <em>Machine and Sovereignty</em> (2024), and that he has deliberately refrained from developing the implications already explored in that trilogy. That candor names the book's character precisely, in ways I will return to.</p>\n<h3 id=\"the-intelligent-machine-and-the-epigenesis-of-reason\" tabindex=\"-1\">The intelligent machine and the epigenesis of reason <a class=\"header-anchor\" href=\"#the-intelligent-machine-and-the-epigenesis-of-reason\">#</a></h3>\n<p>Chapter 1 is the strongest and the most durable. Hui reads Turing's post-war lectures carefully, noting that Turing's intelligent machine is an empirical machine, one that learns rather than merely executes, and that Turing's real answer to Lovelace's objection was a bet on experience over innate instruction. From there the chapter runs backward into the eighteenth century, setting up Descartes's animal-machine and Hume's habit-driven mind as the two poles between which Kant's transcendental philosophy emerges, then forward again into cybernetics. The pivot is a remark of Simondon's from 1953 that Hui rightly flags as extraordinary: &quot;Kant could only have dealt with cybernetics by situating it in the <em>Critique of Judgment</em>.&quot; The third Critique, with its reflective judgment, its organisms that are causes and effects of themselves, and its &quot;technics of nature,&quot; turns out to be where the modern machine question was already latent. Hui traces this through the concept of epigenesis, which recent scholarship (Zammito, Mensch, Huneman, Lenoir) has placed at the center of Kant's account of reason itself. Reason is not preformed but self-organizing, and the three Critiques elaborate what Hui calls an organic, recursive structure, technical unity versus architectonic unity, aggregate versus system. The suggestion that Kant's philosophy is simultaneously an antidote to the machines of his time and, paradoxically, a theory for future machines, since cybernetics is precisely the mechanization of the organic and recursive, is the book's deepest claim, and chapter 1 earns it. Hui also recovers Gerhard Lehmann's neglected reading of Kant's Nachlass as a &quot;critique of technological reason&quot; and engages Franziska Aigner's recent <em>Kant and Technics</em>, arguing that the technics of nature only becomes concretely comprehensible once we have the cybernetic machine in view. This is genuine scholarship, not vibes, and the footnote apparatus, which Hui explicitly designs as a parallel text dialoguing with Kant's commentators while the main text stays with Kant, makes the chapter usable as a map of an entire literature.</p>\n<h3 id=\"the-moral-machine-and-the-kant-test\" tabindex=\"-1\">The moral machine and the Kant test <a class=\"header-anchor\" href=\"#the-moral-machine-and-the-kant-test\">#</a></h3>\n<p>Chapter 2 proposes what may become the book's most quoted idea: after the Turing test, the Kant test. A machine that passes the Turing test is only a knowing machine, not a moral one, and the &quot;Moral Turing Test&quot; proposed in the machine-ethics literature fails for a reason Kant would have appreciated: a moral act is an act in the world, not a language game, and a beautiful speech about morality is no evidence of a moral will. Hui's taxonomy is again elegant. Current artificial moral agents are at best partial Humean moral machines, deriving norms from conventions and data while lacking the sentiments and sympathy on which Hume actually grounded morals. A Kantian moral machine would require autonomy in the strict sense, self-legislation, and the chapter turns on Kant's own observation about Vaucanson's automaton, in which the question of freedom is unthinkable. The antagonism between autonomy and automation is the chapter's real subject, and Hui handles it without the sentimentality that mars most writing on machine ethics.</p>\n<p>The chapter's critical passages are more uneven. The reading of AI alignment through Asimov's three laws and the figure of the slave is historically suggestive, Hui connects the robot to the vacated symbolic position of the slave via Aristotle and Agamben, and his observation that the alignment problem never specifies whose goals count (individuals, clans, the species?) is a fair hit. The pages on Yudkowsky's shutdown proposal and the Hinton-LeCun quarrel are lively. But this is engagement with AI ethics at the level of its public spokesmen and its op-eds, not its technical literature. The alignment research programme has more sophisticated formulations than &quot;AI systems' goals may not align with those of humans,&quot; and a book proposing a Kant test owes the reader more specificity about what taking it would involve. What would count as evidence of machine self-legislation rather than a very good simulation of it? Hui's own Turing material contains the objection, the solipsism problem he cites approvingly against Searle, and the book never quite explains why that objection would not devour the Kant test too. The best moment in the chapter is the Greenspan aside: the 2008 testimony blaming the crisis on models fed only two decades of euphoric data becomes a parable of the Humean machine's incurable vulnerability to contingency, and it does more argumentative work than the Yudkowsky pages combined.</p>\n<h3 id=\"the-peace-machine-and-the-buggy-algorithm\" tabindex=\"-1\">The peace machine and the buggy algorithm <a class=\"header-anchor\" href=\"#the-peace-machine-and-the-buggy-algorithm\">#</a></h3>\n<p>Chapter 3 is the boldest and the most Hui. Reading Kant's late political writings, composed as censorship closed in on a philosopher who had considered abandoning Königsberg over it, Hui proposes that &quot;Toward Perpetual Peace&quot; describes an algorithm: a recursive procedure that presupposes conflict, resolves it through reciprocal operations and communal structure, and generates new conflicts at each iteration, avoiding war not by eliminating antagonism but by metabolizing it. International trade is the algorithm's key parameter. The conceit could easily be cute. It becomes productive when Hui introduces the bug report: Hume's &quot;jealousy of trade,&quot; Fichte's <em>Closed Commercial State</em> as a rival implementation that swaps the trade parameter for <em>Wissenschaft</em>, and then the devastating historical test cases, Perry's black ships forcing open Japan, the Opium Wars forcing open China, in which the &quot;spirit of trade&quot; arrived as war rather than preventing it. Hui, writing from within the East Asian experience of that history, poses the question with real force: can we refuse Kant's perpetual peace on the evidence of the nineteenth century? His answer is carefully double. A true Kantian would say the algorithm was sound and the technical element failed, and the regulative principle concerning whole and parts might still hold even if trade no longer serves. The closing section on DeepSeek, &quot;sovereign AI,&quot; hypersonic missiles, and prediction as itself a source of war is vivid, and the Caygill-inspired reading of Clausewitz's <em>On War</em> as an intensification of Kantian reflective judgment, purposiveness without purpose applied to the strategy of attack, is a chilling and memorable demonstration that the organic paradigm serves war as readily as peace.</p>\n<p>Yet this chapter also exposes the method's limit. &quot;Algorithm&quot; is doing metaphorical work throughout, and Hui never fully confronts the disanalogy: Kant's perpetual peace is a regulative idea, an infinite task, while an algorithm is a finite effective procedure, and collapsing the two risks precisely the confusion of reflective with determinative judgment that the book elsewhere polices so carefully. Hui clearly knows this, his refusal of the planetary &quot;superintelligence&quot; as guarantor of peace depends on the distinction, but the chapter's rhetoric repeatedly borrows precision from the computational vocabulary that its argument then withdraws. The topical references, DeepSeek &quot;at the moment of this writing,&quot; the Oreshnik launch of November 2024, ground the book in its moment at the price of dating it within a few years, a trade-off Hui accepts with open eyes but that sits oddly in a book about a philosopher whose examples have lasted 230 years.</p>\n<h3 id=\"a-coda-that-knows-it-is-a-coda\" tabindex=\"-1\">A coda that knows it is a coda <a class=\"header-anchor\" href=\"#a-coda-that-knows-it-is-a-coda\">#</a></h3>\n<p>The deliberate restraint announced in the preface, elucidating Kant without developing the implications already treated in the trilogy, gives the book its discipline and its thinness at once. Readers arriving fresh will find the cleanest introduction to Hui's whole project yet written, and at this length that is a real service, given how demanding <em>Recursivity and Contingency</em> is. Readers who know the trilogy will notice that the conceptual heavy lifting, recursivity, contingency, cosmotechnics, technodiversity, happens offstage, and that the book's final gesture, philosophy must set off again from Kant's island into the fog-bound ocean, seeking a new condition of philosophizing &quot;after the organic,&quot; points directly back at Hui's other books rather than resolving anything here. The ending is nonetheless beautifully judged: Kästner's epigram about perpetual peace among all men, &quot;all but the philosophers,&quot; lets Kant's own account of philosophy's constitutive &quot;itch&quot; to quarrel have the last word, war avoided everywhere except in the seminar room, which for Kant was exactly how it should be.</p>\n<h3 id=\"verdict\" tabindex=\"-1\">Verdict <a class=\"header-anchor\" href=\"#verdict\">#</a></h3>\n<p><em>Kant Machine</em> is the rare AI book by a continental philosopher that neither denounces the technology from a safe distance nor capitulates to its hype. Its central historical claim, that the symbolic-connectionist debate replays the rationalist-empiricist impasse and that Kant's third Critique is where cybernetics was philosophically anticipated, is illuminating and, I think, correct, and chapter 1 will be cited for years. The Kant test is a genuinely useful provocation even in its underspecified state, and the peace chapter's East Asian rereading of Kantian cosmopolitanism is something no other book on Kant and technology attempts. Its weaknesses are the mirror of its economy: engagement with machine learning at the level of its publicists rather than its practice, analogies that occasionally outrun their arguments, and a self-imposed dependence on a trilogy it declines to summarize. Read it as the keystone of Hui's arch rather than a freestanding structure and it holds. Anyone teaching philosophy of AI should assign it alongside the analytic literature it pointedly brackets, because the questions it asks, not whether machines can think but what kind of machines our thinking has already made us, are the ones that literature cannot formulate.</p>\n",
			"date_published": "2026-07-20T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/big-data-in-the-arts-and-humanities-review/",
			"url": "https://www.adamdjbrett.com/blog/big-data-in-the-arts-and-humanities-review/",
			"title": "Review: Big Data in the Arts and Humanities—Theory and Practice",
			"content_html": "<h2 id=\"big-data-in-the-arts-and-humanities-theory-and-practice\" tabindex=\"-1\">Big Data in the Arts and Humanities: Theory and Practice <a class=\"header-anchor\" href=\"#big-data-in-the-arts-and-humanities-theory-and-practice\">#</a></h2>\n<p><strong>Edited by Giovanni Schiuma and Daniela Carlucci</strong>\n<em>CRC Press / Taylor &amp; Francis, 2018 (Data Analytics Applications series)</em></p>\n<blockquote>\n<p>Schiuma, Giovanni, and Daniela Carlucci, eds. 2018. <em>Big Data in the Arts and Humanities: Theory and Practice</em>. Boca Raton, FL: CRC Press. ISBN 978-1-4987-6585-5.</p>\n</blockquote>\n<p>It matters where a book comes from. <em>Big Data in the Arts and Humanities</em> sits in CRC Press's &quot;Data Analytics Applications&quot; series, alongside titles like <em>Big Data Analytics in Cybersecurity</em>, <em>Sport Business Analytics</em>, and <em>Actionable Intelligence for Healthcare</em>. That placement is not incidental. The volume treats arts and humanities as one more industry vertical waiting to be brought into the big-data fold, the same way the series treats hospitals, governments, and sports franchises, and the framing chapters read exactly like what that pedigree would predict: a business-consulting register applied to museums and literature departments. The surprise is that buried in the middle of the book is a chapter that has nothing to do with that register at all, and it is good enough to make the surrounding material look worse by comparison.</p>\n<h3 id=\"three-parts-two-registers\" tabindex=\"-1\">Three parts, two registers <a class=\"header-anchor\" href=\"#three-parts-two-registers\">#</a></h3>\n<p>The book collects fifteen chapters into three sections: understanding big data in arts and humanities, digital humanities proper, and managing big data with and for the sector. The first and third sections are dominated by what can fairly be called cultural-management consultancy: chapters on &quot;Culture Metrics&quot; as a quality-assessment tool for arts organizations, a case study of Arts Council England's data practices, museum provenance databases, &quot;data culture&quot; in the creative industries, and smart-city art initiatives. These chapters are competent as institutional reporting—the Arts Council England chapter, for instance, is a genuinely useful account of how one major funding body tried to operationalize data-driven decision-making—but they rarely rise above description of programs and tools. The introduction sets the tone early with language like &quot;the datification of human life&quot; and repeated insistence that arts and humanities need to build a &quot;big data culture,&quot; phrases that get restated across several chapters without much argumentative work being done between restatements.</p>\n<p>The middle section, &quot;Digital Humanities,&quot; is a different book. Ian Milligan and Robert Warren's chapter on historians moving &quot;from black boxes to models&quot; takes seriously the methodological stakes of computational history—not just that historians can now use big data, but what habits of mind they need to develop to use it responsibly, rather than trusting opaque tools they don't understand. It is the first chapter in the volume that treats its subject as an intellectual problem rather than an adoption curve.</p>\n<h3 id=\"the-chapter-that-justifies-the-book\" tabindex=\"-1\">The chapter that justifies the book <a class=\"header-anchor\" href=\"#the-chapter-that-justifies-the-book\">#</a></h3>\n<p>The standout, though, is Federica Perazzini's &quot;The English Gothic Novel: Theories and Praxis of Computer-Based Macroanalysis in Literary Studies.&quot; Working in the tradition of Franco Moretti's distant reading and Matthew Jockers's computational macroanalysis, Perazzini builds a large corpus of digitized Gothic novels and runs it through stylometric analysis—most-frequent-word comparisons, type-token ratio for vocabulary richness, and motif mining—to trace how the genre's &quot;genome&quot; evolved across decades. What makes the chapter work is that Perazzini treats her quantitative results as data to be interpreted rather than conclusions that speak for themselves: the chapter closes with a section of &quot;epistemological considerations&quot; that asks directly what it means to have discovered a pattern in word frequencies, and what interpretive work still has to happen before a pattern becomes a literary-historical claim. This is exactly the question the framing chapters never ask about their own material. Culture Metrics and audience-development dashboards are presented as though the hard part is generating the data; Perazzini's chapter understands that generating the data is the easy part.</p>\n<h3 id=\"an-uneven-case-for-the-thesis\" tabindex=\"-1\">An uneven case for the thesis <a class=\"header-anchor\" href=\"#an-uneven-case-for-the-thesis\">#</a></h3>\n<p>The book's implicit thesis is that arts and humanities can benefit from big data approaches while also having something distinctive to contribute back to those approaches—qualitative depth, narrative sense-making, what Paul Moore's chapter calls &quot;thick data.&quot; That is a defensible and interesting claim. But the volume makes its case unevenly: the chapters that actually demonstrate humanistic method enriching computational analysis (Perazzini, and to a lesser extent Milligan and Warren) are outnumbered by chapters that gesture at the idea of &quot;data culture&quot; without showing what a genuinely humanistic engagement with data analysis looks like in practice. A reader who wants to see the thesis proven has to do some of that comparative work themselves, chapter by chapter, rather than being handed a synthesis by the editors.</p>\n<p>The book also shows its age in a way that is hard to avoid noting from 2026. Published in 2018, its touchstones are Amazon, Facebook, and Google as the paradigm big-data companies, and its framing questions—should museums adopt big data? what does a data culture look like?—belong to a moment before generative AI reorganized the entire conversation about computation and the humanities. None of this is the editors' fault, but it means the book now reads less as a live intervention than as a snapshot of a specific, already-superseded stage of the digital humanities conversation, useful mainly for readers doing the history of that conversation rather than looking for a current one.</p>\n<h3 id=\"verdict\" tabindex=\"-1\">Verdict <a class=\"header-anchor\" href=\"#verdict\">#</a></h3>\n<p>This is a mixed book whose value is concentrated rather than distributed. Read it for Perazzini's Gothic novel chapter, which is a small, well-executed model of what computational literary analysis owes to interpretive judgment, and for Milligan and Warren's argument against black-box historical method. Read the surrounding chapters on data culture and cultural-sector metrics for institutional context if you need it, but don't expect them to meet the same bar. As a series entry in business-analytics publishing applied to a new vertical, it does what that genre does. As a sustained argument about what big data means for arts and humanities specifically, it is a partial success carried by a couple of chapters that clearly belong to a more demanding tradition than the one the book was packaged in.</p>\n",
			"date_published": "2026-07-19T06:39:28Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/another-universalism-seyla-benhabib-review/",
			"url": "https://www.adamdjbrett.com/blog/another-universalism-seyla-benhabib-review/",
			"title": "Review: Another Universalism—Seyla Benhabib and the Future of Critical Theory",
			"content_html": "<h2 id=\"another-universalism-seyla-benhabib-and-the-future-of-critical-theory\" tabindex=\"-1\">Another Universalism: Seyla Benhabib and the Future of Critical Theory <a class=\"header-anchor\" href=\"#another-universalism-seyla-benhabib-and-the-future-of-critical-theory\">#</a></h2>\n<p><strong>Edited by Stefan Eich, Anna Jurkevics, and Nishin Nathwani</strong>\n<em>Columbia University Press, 2023 (New Directions in Critical Theory)</em></p>\n<blockquote>\n<p>Eich, Stefan, Anna Jurkevics, and Nishin Nathwani, eds. 2023. <em>Another Universalism: Seyla Benhabib and the Future of Critical Theory</em>. New York: Columbia University Press. ISBN 978-0-231-21278-6.</p>\n</blockquote>\n<p>Festschrifts have a reputation problem, and it is mostly deserved. Too often they are collections of loosely related essays held together by nothing more than shared affection for the honoree, padded with tributes that read more like toasts than arguments. <em>Another Universalism</em>, gathered from a 2020 conference honoring Seyla Benhabib and published the year after, avoids that trap almost entirely, and it does so through a specific editorial choice worth naming: rather than organizing the volume by discipline, chronology, or contributor prominence, editors Stefan Eich, Anna Jurkevics, and Nishin Nathwani organize it around Benhabib's own conceptual vocabulary—the concrete universal, democratic iteration, jurisgenerativity, deprovincialization. The result is a book that reads less like a tribute and more like a coordinated stress test of one scholar's theoretical apparatus, conducted by twenty-two people who know it from the inside.</p>\n<h3 id=\"an-organizing-principle-that-actually-organizes\" tabindex=\"-1\">An organizing principle that actually organizes <a class=\"header-anchor\" href=\"#an-organizing-principle-that-actually-organizes\">#</a></h3>\n<p>The volume's six parts track the arc of Benhabib's career in a way that gives each section real argumentative unity rather than the alphabetical or topical grab-bag structure that afflicts so many edited collections in this space. Part I, &quot;Critique, Norm, and Utopia,&quot; returns to Benhabib's 1986 book of the same name and interrogates her founding move: mediating Habermasian communicative ethics with Arendtian contingency to produce norms that emerge from concrete struggle rather than abstract reason. Thomas McCarthy's opening chapter presses the hardest version of the obvious objection—does contextualizing universal norms this much eventually dissolve them into relativism?—and the volume is stronger for opening on that note of genuine challenge rather than celebration.</p>\n<p>Part II turns to Arendt, whom Benhabib brought into critical theory's canon despite Arendt's own anti-Marxist commitments; Part III to democratic iterations and cosmopolitanism; Part IV to jurisgenerativity and the vexed question of law's emancipatory potential within a tradition descended from Marx; Part V to what the editors and contributors call &quot;deprovincializing&quot; critical theory—pushing a body of thought built by European men in the 1930s and 40s to reckon with decolonization, indigenous rights, and race in ways its first two generations never did. The final part, &quot;Philosophy and Friendship,&quot; closes with Benhabib's own intellectual autobiography and Carolin Emcke's essay &quot;Swimming,&quot; an unusually personal register for an academic volume, and one that lands harder than it might otherwise given that Drucilla Cornell, whose chapter on transnational decolonization appears in Part V, died before the book went to press.</p>\n<h3 id=\"where-the-volume-earns-its-stakes\" tabindex=\"-1\">Where the volume earns its stakes <a class=\"header-anchor\" href=\"#where-the-volume-earns-its-stakes\">#</a></h3>\n<p>The strongest material sits in Parts IV and V, where contributors take Benhabib's frameworks somewhere she did not fully go herself. Matthew Longo's chapter applies jurisgenerativity to state surveillance and big data, arguing that mass data collection replaces the legal presumption of innocence with a logic of &quot;risky until proven safe&quot; that forecloses exactly the kind of contestation democratic iteration depends on—a genuinely contemporary problem addressed with Benhabib's own tools rather than imported ones. Angélica María Bernal's chapter on Pachamama and the Rights of Nature asks directly whether a cosmopolitanism built from European sources can support indigenous movements against extractivism, and answers carefully rather than either dismissing or over-claiming the fit. Ayten Gündoğdu's treatment of border deaths as a form of forced disappearance, read through Fanon rather than only Arendt, does something similar: it uses Benhabib's apparatus to reach a conclusion—that border violence must be understood through the history of colonialism and race, not territorial sovereignty alone—that pushes past where the framework's original architecture was built to go.</p>\n<p>Max Pensky's chapter on genocide and jurisgenesis deserves particular mention for using new archival evidence about Raphael Lemkin to complicate Benhabib's own reading of him, showing Lemkin as concerned less with protecting essentialized group identities than with criminalizing state violence against socially designated targets—a case of a Benhabib student correcting Benhabib's history rather than simply extending her theory.</p>\n<h3 id=\"the-limits-of-thinking-from-inside-a-framework\" tabindex=\"-1\">The limits of thinking from inside a framework <a class=\"header-anchor\" href=\"#the-limits-of-thinking-from-inside-a-framework\">#</a></h3>\n<p>The volume's coherence, though, is bought at a price the editors do not fully address. Because every essay is written in explicit relation to Benhabib's own concepts, the book is better at extending and applying her framework than at testing whether the framework is the right one to begin with. Rainer Forst's chapter comes closest to an external challenge, offering a starker, more power-centered account of politics as &quot;a power struggle—as a struggle for justification,&quot; but even this reads as a friendly amendment rather than a rival paradigm. A reader who wonders whether &quot;democratic iteration&quot; and &quot;jurisgenerativity&quot; are doing real theoretical work, as opposed to giving existing normative commitments new names, will not find that question posed directly anywhere in the book. The essays that come closest to independent argument—Longo on data, Bernal on decolonial cosmopolitanism, Threadcraft and Terry's reading of Martin Luther King through Benhabib's &quot;thinking with and against&quot; method—succeed because they put the framework under real strain rather than because anyone in the volume steps outside it to ask if it should hold.</p>\n<p>This is, in fairness, close to unavoidable for what the book is: a volume built to honor a living scholar by demonstrating what her ideas can still do, not a symposium designed to adjudicate her place in the tradition. Judged by that standard, it succeeds, and unusually well for the genre.</p>\n<h3 id=\"verdict\" tabindex=\"-1\">Verdict <a class=\"header-anchor\" href=\"#verdict\">#</a></h3>\n<p><em>Another Universalism</em> is a rare festschrift that functions as a genuine contribution to critical theory rather than a monument to one. Its structural decision to organize around Benhabib's own conceptual vocabulary gives the volume an argumentative spine that most multi-author theory anthologies lack, and the strongest chapters—Longo, Bernal, Gündoğdu, Pensky—use that vocabulary to reach genuinely new places, on data surveillance, indigenous rights, border violence, and the history of genocide law. What it does not offer, and does not claim to, is a hostile cross-examination of whether democratic iteration and jurisgenerativity are the right conceptual tools for the crises the book addresses. For readers already convinced that Benhabib's third-generation critical theory is the right starting point, this is an essential and often moving map of where that theory can still go. For readers looking to be convinced of that starting point in the first place, the case has to be found elsewhere.</p>\n",
			"date_published": "2026-07-19T06:36:26Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/critical-theory-and-the-authoritarian-personality-review/",
			"url": "https://www.adamdjbrett.com/blog/critical-theory-and-the-authoritarian-personality-review/",
			"title": "Review: Critical Theory and the Authoritarian Personality",
			"content_html": "<h2 id=\"critical-theory-and-the-authoritarian-personality\" tabindex=\"-1\">Critical Theory and the Authoritarian Personality <a class=\"header-anchor\" href=\"#critical-theory-and-the-authoritarian-personality\">#</a></h2>\n<p><strong>By Geoff M. Boucher</strong>\n<em>Edinburgh University Press, 2025</em></p>\n<blockquote>\n<p>Boucher, Geoff M. 2025. <em>Critical Theory and the Authoritarian Personality</em>. Edinburgh: Edinburgh University Press. ISBN 978-1-3995-1945-8.</p>\n</blockquote>\n<p>Geoff Boucher's preface tells you exactly what kind of book this is before the argument even starts. Researching a study of rightwing narrative fiction, he bought a copy of William Luther Pierce's <em>The Turner Diaries</em>, the 1978 novel that inspired Timothy McVeigh, and Amazon's recommendation algorithm did the rest. Within weeks his shopping suggestions &quot;looked like a neo-Nazi bookstore.&quot; Working with collaborators, Boucher and Rachel Fetherston eventually catalogued close to a hundred self-published rightwing authoritarian novels, most of them genre fiction about a coming second American civil war, written largely by veterans who understand insurgency tactics and write, in Boucher's phrase, &quot;as patient and precise as a sniper.&quot; That archive, more than any single theoretical claim, is what makes this book worth reading. It is Frankfurt School critical theory applied to primary source material that almost no one in the field has actually sat down and read.</p>\n<h3 id=\"updating-adorno-for-the-age-of-qanon\" tabindex=\"-1\">Updating Adorno for the age of QAnon <a class=\"header-anchor\" href=\"#updating-adorno-for-the-age-of-qanon\">#</a></h3>\n<p>The book's stated task is to revive and revise the Frankfurt School's theory of the authoritarian personality, first developed in Adorno and Horkheimer's <em>Studies in Prejudice</em> (1950), for a political moment defined by QAnon, January 6, and the global resurgence of rightwing populism. Boucher accepts the classical theory's core claim, that a measurable minority of the population (11 to 16 percent, he reports, citing Karen Stenner's cross-cultural survey data) carries a durable cluster of authoritarian social attitudes that ideological propaganda can activate and radicalize. But he argues the classical Freudian apparatus built around the Oedipus complex, castration anxiety, and identification with a strict-father leader figure has not aged well, and turns to Lacan, by way of Slavoj Žižek's concept of &quot;totalitarian subjectivity,&quot; to rebuild the theory's psychoanalytic foundation. The seven chapters move outward from that reformulation into a sequence of case studies: QAnon as collective fantasy, the classical theory's balance sheet, the Lacanian reworking itself, Jean Raspail's <em>The Camp of the Saints</em>, the survivalist genre, &quot;neofascist&quot; terrorist-manual novels like <em>The Turner Diaries</em>, and finally the neoconfederate second-civil-war fiction that closes the book.</p>\n<h3 id=\"where-the-theory-earns-its-keep\" tabindex=\"-1\">Where the theory earns its keep <a class=\"header-anchor\" href=\"#where-the-theory-earns-its-keep\">#</a></h3>\n<p>The strongest theoretical move in the book comes early, in chapter 2's treatment of Adolf Eichmann. Boucher uses Eichmann's own psychiatric profile, drawn from Bettina Stangneth's biography and courtroom testimony, to test the classical theory against a case it should fit perfectly and doesn't. Eichmann's aggression was not organized around sexual fantasy or paternal identification in the way Adorno's Oedipal framework predicts; it was organized around identification with the abstract authority of the German nation and a self-image of &quot;punctuality, lifeless chilliness, cynicism.&quot; Rather than force the case into the classical mold, Boucher lets the misfit stand and uses it to argue that the sadomasochistic character structure (following Fromm and the psychoanalyst Otto Fenichel) is the deeper substrate, of which the &quot;authoritarian personality&quot; is only the surface symptom under stress. This is real theoretical work: a classical concept tested against evidence, found wanting in a specific, documented way, and revised rather than simply reasserted.</p>\n<p>The payoff of the Lacanian retooling shows up most clearly in the book's closing reading of neoconfederate insurgency fiction. Boucher argues that the genre's recurring villain, the &quot;citizen-traitor,&quot; a grotesque, subhuman composite of every demographic the authors resent, functions as a psychoanalytic screen: virtually every trait projected onto this figure (craving domination, craving submission, obsessing over violence) actually describes the authoritarian subject's own disavowed desire. That is a genuinely illuminating way to read pages of ugly caricature without simply reproducing the caricature's own terms, and it is the kind of interpretive payoff that justifies close reading of material this unpleasant in the first place.</p>\n<h3 id=\"the-interpretive-technique-is-also-the-books-weak-point\" tabindex=\"-1\">The interpretive technique is also the book's weak point <a class=\"header-anchor\" href=\"#the-interpretive-technique-is-also-the-books-weak-point\">#</a></h3>\n<p>The trouble is that a reading strategy built on projection and disavowal is difficult to falsify, and Boucher does not spend much time asking what a piece of authoritarian propaganda would have to look like for the Lacanian frame not to apply. Once a critic is committed to reading a villain as the return of the propagandist's repressed desire, that move is available for almost any hostile caricature in any political tradition, not just the rightwing insurgency genre. The Eichmann chapter shows Boucher is capable of subjecting a classical Frankfurt School claim to a real test; the neoconfederate chapter, by contrast, applies the Žižekian apparatus and reports what it finds, without asking what evidence would have counted against the reading. The book would be stronger if it had turned the same adversarial instinct on its own updated theory that it turned on Adorno's original one.</p>\n<p>There is also a genre question the book raises but doesn't fully resolve. Boucher frames this as a contribution to critical theory's account of authoritarian <em>psychology</em>, but a large share of the actual analytical labor, in the QAnon, Camp of the Saints, survivalist, and neoconfederate chapters alike, is close reading of specific narrative texts: their plot mechanics, their use of pseudonymous digital publishing, their marketing niches on Amazon and Goodreads. That is valuable literary-critical and sociological work in its own right, and Boucher's dual training (he has also written on Habermas and literature) shows. But the book sometimes oversells itself as a revision to critical theory's theoretical architecture when what it more reliably delivers is an unusually well-documented literary sociology of a propaganda genre, read through a theoretical lens rather than substantially altering that lens.</p>\n<p>Boucher's categorical distinction between &quot;rightwing populism&quot; (illiberal but pro-democratic parties like the AfD or Rassemblement National) and &quot;rightwing authoritarianism&quot; (explicitly anti-democratic movements like the Proud Boys or Oathkeepers), borrowed from Cas Mudde, is doing a great deal of load-bearing work in the introduction, keeping the book's claims from sprawling into an indictment of the entire populist right. It is a sensible distinction to draw. But Boucher's own examples complicate it: he notes that Trump represents exactly the case where an &quot;influential incumbent, together with a wing of their party,&quot; crosses from one category into the other. If the boundary is that permeable in the book's own headline case, the tidy typology may be doing more analytical reassurance than the messy political reality actually supports.</p>\n<h3 id=\"how-it-reads\" tabindex=\"-1\">How it reads <a class=\"header-anchor\" href=\"#how-it-reads\">#</a></h3>\n<p>The prose is clear and occasionally gripping, especially in the preface's account of the Amazon rabbit hole and in the extended close readings of specific novels, which quote enough of the source material (redacted slurs and all) to make the genre's rhetorical machinery visible without requiring the reader to go find these books themselves. Boucher writes as a critical theorist genuinely alarmed by what he found in the course of research rather than as a detached cataloguer, and that urgency is mostly an asset. The book is heavily footnoted and clearly the product of years of prior journal articles (several chapters began life as standalone pieces in <em>Thesis Eleven</em>, <em>Religions</em>, and elsewhere), which occasionally shows in some repetition of framing material across chapters.</p>\n<h3 id=\"verdict\" tabindex=\"-1\">Verdict <a class=\"header-anchor\" href=\"#verdict\">#</a></h3>\n<p>This is a genuinely useful piece of applied critical theory precisely because it is willing to get its hands dirty with material most Frankfurt School scholarship never touches: a documented corpus of self-published rightwing insurgency fiction that Boucher and his collaborators appear to be the first academics to catalogue systematically. The Eichmann chapter shows the classical theory being tested and revised rather than merely cited, and the closing reading of neoconfederate fiction's &quot;citizen-traitor&quot; is a real interpretive achievement. But the Lacanian apparatus that generates that achievement is under-interrogated as a method, and the book's framing as a theoretical intervention in critical theory oversells work that is, chapter for chapter, more securely a contribution to the sociology and literary criticism of rightwing propaganda. Read it for the archive and for the Eichmann chapter's methodological honesty; treat the psychoanalytic readings of individual novels as suggestive rather than demonstrated.</p>\n",
			"date_published": "2026-07-17T04:36:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/critical-theory-ai/",
			"url": "https://www.adamdjbrett.com/blog/critical-theory-ai/",
			"title": "What Is Critical Theory, and Why Do We Need It in the Age of AI?",
			"content_html": "<p>Artificial intelligence is often introduced as a technical problem. We are told to ask whether the model is accurate, whether the system is safe, whether the interface is useful, and whether the company has followed the right risk-management checklist. These questions matter. They are not enough.</p>\n<p>Critical theory begins where technical description becomes socially inadequate. It asks how a technology is made, whose interests it serves, whose labor and data it depends on, what forms of power it extends, what harms it normalizes, and what futures it quietly makes harder to imagine. In the age of AI, those questions are not optional. They are part of the basic literacy required for democratic life.</p>\n<p>This post explains what critical theory is, how it differs from ordinary criticism, and why AI makes its methods more urgent.</p>\n<h2 id=\"critical-theory-in-one-sentence\" tabindex=\"-1\">Critical theory in one sentence <a class=\"header-anchor\" href=\"#critical-theory-in-one-sentence\">#</a></h2>\n<p>Critical theory is a tradition of social thought that studies how domination works and how people might become freer from it.</p>\n<p>That definition is simple, but it needs care. Critical theory is more than a habit of saying that every new technology is bad. It is a method of connecting ideas, institutions, economic systems, culture, knowledge, and everyday life. It asks why arrangements that harm people can still appear natural, neutral, efficient, or inevitable.</p>\n<p>The Stanford Encyclopedia of Philosophy describes Frankfurt School critical theory as a tradition that combines philosophical reflection and social-scientific analysis with an emancipatory aim. It is self-reflexive, interdisciplinary, materialist, and oriented toward freedom from domination. In Max Horkheimer's classic formulation, critical theory differs from &quot;traditional theory&quot; because it does not treat society as a neutral object to be described from the outside. It asks how knowledge itself is shaped by social conditions, and how theory might help transform those conditions rather than merely explain them.</p>\n<p>That distinction matters for AI. A traditional technical account might ask whether a model produces a correct answer. A critical account also asks why this model exists, why this task is being automated, who owns the infrastructure, who supplied the training data, who labels or moderates the outputs, who is monitored by the system, who can contest its decisions, and who benefits if the system becomes normal.</p>\n<h2 id=\"the-frankfurt-school-critique-after-catastrophe\" tabindex=\"-1\">The Frankfurt School: critique after catastrophe <a class=\"header-anchor\" href=\"#the-frankfurt-school-critique-after-catastrophe\">#</a></h2>\n<p>Critical theory is often associated with the Frankfurt School, a group of philosophers and social theorists linked to the Institute for Social Research in Frankfurt, founded in 1923. Its best-known first-generation figures include Max Horkheimer, Theodor W. Adorno, Herbert Marcuse, Walter Benjamin, Erich Fromm, Friedrich Pollock, Leo Löwenthal, Franz Neumann, and Otto Kirchheimer. Later generations include Jürgen Habermas, Axel Honneth, Seyla Benhabib, Nancy Fraser, Rainer Forst, Rahel Jaeggi, and Amy Allen.</p>\n<p>The first generation wrote in response to crises that still sound familiar: authoritarianism, mass propaganda, economic instability, antisemitism, racism, bureaucratic control, consumer culture, and the political failures of liberal democracy. They wanted to understand why modern societies could produce scientific progress and administrative efficiency while also producing domination and fascism.</p>\n<p>Horkheimer and Adorno's <em>Dialectic of Enlightenment</em> argued that reason can turn against itself when it becomes only instrumental reason: the calculation of means without reflection on ends. Marcuse's <em>One-Dimensional Man</em> analyzed how advanced industrial societies absorb dissent and train people to experience domination as comfort. Habermas later shifted the tradition toward communication, public reason, and the conditions of democratic deliberation. Fraser, Benhabib, Allen, and others pushed the tradition to engage more seriously with feminism, race, colonialism, capitalism, and the limits of Eurocentric narratives of progress.</p>\n<p>The tradition is not unified. It contains disagreements about reason, normativity, social movements, capitalism, identity, colonialism, and democracy. That is a strength. Critical theory is less a fixed doctrine than a set of questions about power, knowledge, domination, and emancipation.</p>\n<h2 id=\"what-critical-theory-actually-does\" tabindex=\"-1\">What critical theory actually does <a class=\"header-anchor\" href=\"#what-critical-theory-actually-does\">#</a></h2>\n<p>Critical theory is useful because it gives names to patterns that otherwise remain hidden. Four concepts are especially important for AI.</p>\n<h3 id=\"1-ideology\" tabindex=\"-1\">1. Ideology <a class=\"header-anchor\" href=\"#1-ideology\">#</a></h3>\n<p>Ideology is broader than propaganda. In critical theory, ideology refers to forms of belief, practice, and common sense that make domination appear natural or unavoidable. A social order is most powerful when people stop seeing it as a social order at all.</p>\n<p>In AI discourse, ideology appears when prediction is treated as objectivity, automation as progress, scale as public benefit, and efficiency as an unquestioned good. A hiring algorithm may be described as neutral because it uses data. A welfare algorithm may be described as efficient because it reduces administrative cost. A generative AI system may be described as creative because it produces fluent text or images. Critical theory asks what those descriptions hide.</p>\n<h3 id=\"2-reification\" tabindex=\"-1\">2. Reification <a class=\"header-anchor\" href=\"#2-reification\">#</a></h3>\n<p>Reification means treating social relations as things. People, histories, judgments, and conflicts are made to appear as objects, scores, rankings, categories, or data points.</p>\n<p>AI systems intensify this problem because they work by translating human life into machine-readable form. Students become risk scores. Workers become productivity traces. Patients become prediction profiles. Writers, artists, and users become training data. The issue is not only that categories can be wrong. It is that the act of categorization can change how institutions see people and how people are allowed to appear before institutions.</p>\n<h3 id=\"3-instrumental-reason\" tabindex=\"-1\">3. Instrumental reason <a class=\"header-anchor\" href=\"#3-instrumental-reason\">#</a></h3>\n<p>Instrumental reason asks how to optimize means. It does not ask whether the goal should be pursued. A system can be technically effective and socially destructive.</p>\n<p>Critical theory is useful here because much AI governance is tempted to focus on technical mitigation: reduce bias, improve explainability, add a human in the loop, publish a model card. These steps can help. But they do not answer the prior question: should this system exist in this setting at all?</p>\n<p>UNESCO's Recommendation on the Ethics of Artificial Intelligence makes a similar point in policy language. It says AI methods should be appropriate and proportional to a legitimate aim, should not violate human rights, and should be assessed across the AI life cycle. It also states that AI should not be used for social scoring or mass surveillance purposes. Critical theory gives a philosophical vocabulary for why proportionality and legitimacy cannot be reduced to engineering performance.</p>\n<h3 id=\"4-emancipation\" tabindex=\"-1\">4. Emancipation <a class=\"header-anchor\" href=\"#4-emancipation\">#</a></h3>\n<p>Critical theory is not only diagnosis. Its central question is how people can become less dominated by systems they themselves sustain. Emancipation does not mean that every social problem has a simple solution. It means that people should be able to understand, contest, and reshape the institutions that govern their lives.</p>\n<p>This is the point at which critical theory becomes democratic. AI systems are increasingly used in education, employment, policing, welfare, finance, media, health care, and government administration. If people cannot understand or contest those systems, then decisions that affect public life move away from public reason and into proprietary infrastructure.</p>\n<h2 id=\"why-ai-makes-critical-theory-urgent\" tabindex=\"-1\">Why AI makes critical theory urgent <a class=\"header-anchor\" href=\"#why-ai-makes-critical-theory-urgent\">#</a></h2>\n<p>AI did not create capitalism, racism, patriarchy, coloniality, surveillance, or bureaucratic domination. It can, however, automate and extend them. That is why critical theory matters now.</p>\n<h3 id=\"ai-turns-social-judgment-into-infrastructure\" tabindex=\"-1\">AI turns social judgment into infrastructure <a class=\"header-anchor\" href=\"#ai-turns-social-judgment-into-infrastructure\">#</a></h3>\n<p>The EU AI Act classifies AI systems by risk. It bans certain unacceptable-risk systems and imposes obligations on high-risk systems. The European Commission lists high-risk areas such as critical infrastructure, education, employment, essential services, law enforcement, migration, justice, and democratic processes. These are not marginal use cases. They are domains where people receive rights, opportunities, care, punishment, mobility, credit, and political voice.</p>\n<p>When AI enters these domains, it does more than assist decision-making. It can reshape what counts as evidence, which explanations institutions accept, and how people are sorted before they are heard. Critical theory helps us ask whether procedural safeguards are sufficient, or whether some uses turn public judgment into administrative automation.</p>\n<h3 id=\"ai-makes-power-look-like-prediction\" tabindex=\"-1\">AI makes power look like prediction <a class=\"header-anchor\" href=\"#ai-makes-power-look-like-prediction\">#</a></h3>\n<p>Prediction carries authority. A predicted risk can become a reason to deny bail, flag a student, reject an applicant, discipline a worker, prioritize a patient, or target a neighborhood. The danger is not only inaccurate prediction. The danger is that prediction can become a way to govern people through probabilities they cannot inspect or contest.</p>\n<p>Virginia Eubanks's <em>Automating Inequality</em> examined automated decision systems in social services and welfare administration. Safiya Umoja Noble's <em>Algorithms of Oppression</em> showed how search systems can reproduce racist and sexist hierarchies while presenting results as neutral information retrieval. Ruha Benjamin's <em>Race After Technology</em> argues that discriminatory systems can appear objective or benevolent because they are coded into technical form. These works extend the critical-theory question: how does domination persist when it no longer announces itself as domination?</p>\n<h3 id=\"ai-depends-on-extraction\" tabindex=\"-1\">AI depends on extraction <a class=\"header-anchor\" href=\"#ai-depends-on-extraction\">#</a></h3>\n<p>AI systems require data, computation, energy, minerals, labor, infrastructure, and capital. Kate Crawford's <em>Atlas of AI</em> frames AI through its material and planetary costs: natural resources, labor, privacy, equality, and freedom. Nick Couldry and Ulises Mejias describe &quot;data colonialism&quot; as a process through which human life is appropriated as data for capitalism. Shoshana Zuboff's theory of surveillance capitalism describes how human experience can become raw material for prediction products.</p>\n<p>These arguments differ, but together they challenge the idea that AI is immaterial. AI is not a cloud. It is an industrial system. It draws on mines, data centers, underpaid labeling work, copyrighted and uncopyrighted cultural production, user traces, and concentrated corporate control. Critical theory helps connect the polished interface to the social and material chain that makes it possible.</p>\n<h3 id=\"ai-changes-the-public-sphere\" tabindex=\"-1\">AI changes the public sphere <a class=\"header-anchor\" href=\"#ai-changes-the-public-sphere\">#</a></h3>\n<p>Habermas's work on the public sphere remains useful because democracy depends on more than voting. It depends on shared conditions for public reasoning: access to information, the ability to contest claims, and institutions that can be held accountable.</p>\n<p>Generative AI complicates those conditions. It can produce persuasive text at scale, generate synthetic images and audio, automate spam and propaganda, personalize persuasion, and flood information channels with low-cost content. These capacities do not automatically destroy democracy. But they put pressure on the institutions and habits that public reason requires.</p>\n<p>UNESCO's AI recommendation explicitly links AI governance to communication and information. It calls for media and information literacy, transparency in automated content generation and moderation, access to diverse viewpoints, and mechanisms for redress. This is critical theory in policy form: the health of a democracy depends on the conditions under which people can know, speak, disagree, and organize.</p>\n<h3 id=\"ai-governance-needs-critique-not-only-compliance\" tabindex=\"-1\">AI governance needs critique, not only compliance <a class=\"header-anchor\" href=\"#ai-governance-needs-critique-not-only-compliance\">#</a></h3>\n<p>NIST's AI Risk Management Framework is a serious governance tool. It is voluntary, use-case agnostic, and designed to help organizations manage risks to individuals, organizations, and society. Its core functions are commonly summarized as govern, map, measure, and manage. NIST has also released a generative AI profile to help organizations identify risks specific to generative AI.</p>\n<p>The EU AI Act is more legal and binding. It uses a risk-based approach, including prohibited practices, high-risk obligations, transparency duties, and rules for general-purpose AI models.</p>\n<p>These frameworks are important. Critical theory does not replace them. It asks what they may miss.</p>\n<p>A compliance framework can ask whether a high-risk system has documentation, logging, human oversight, and risk mitigation. Critical theory asks whether the institution should be using that system, whether affected communities had power in the decision, whether the system shifts responsibility away from accountable humans, whether it deepens existing inequality, and whether its benefits depend on harms displaced elsewhere.</p>\n<p>Good governance asks, &quot;Is this system safe and compliant?&quot; Critical theory adds, &quot;Safe for whom, compliant with whose interests, and necessary for what kind of society?&quot;</p>\n<h2 id=\"critical-ai-studies-beyond-one-off-takedowns\" tabindex=\"-1\">Critical AI studies: beyond one-off takedowns <a class=\"header-anchor\" href=\"#critical-ai-studies-beyond-one-off-takedowns\">#</a></h2>\n<p>A newer field, critical AI studies, is trying to build methods adequate to contemporary AI. One recent methodological intervention, Fabian Offert and Ranjodh Singh Dhaliwal's &quot;The Method of Critical AI Studies, A Propaedeutic&quot; (2024), argues that criticism of generative AI should not rely too heavily on single examples of bad outputs. Probabilistic systems require methods that can handle variation, interfaces, pipelines, data histories, deployment contexts, and institutional uses.</p>\n<p>This is an important correction. It is easy to critique AI by showing a hallucination, a biased image, or an absurd chatbot answer. Those examples can be revealing, but they do not always prove a general claim. A stronger critique asks how the system behaves across cases, how it changes over time, what pipeline produced it, what institution deploys it, and what social function it performs.</p>\n<p>That is also the spirit of the academic humanizer discipline used in this post: do not overclaim, do not let rhetoric outrun evidence, and do not replace analysis with slogans. Critical theory is strongest when it is specific.</p>\n<h2 id=\"what-critical-theory-can-teach-ai-builders-and-users\" tabindex=\"-1\">What critical theory can teach AI builders and users <a class=\"header-anchor\" href=\"#what-critical-theory-can-teach-ai-builders-and-users\">#</a></h2>\n<p>Critical theory is often treated as external opposition to technology. That is a mistake. It can improve how AI is designed, governed, adopted, and resisted.</p>\n<h3 id=\"1-ask-the-prior-question\" tabindex=\"-1\">1. Ask the prior question <a class=\"header-anchor\" href=\"#1-ask-the-prior-question\">#</a></h3>\n<p>Before asking how to build the system, ask whether the task should be automated. Some tasks require care, judgment, trust, responsibility, or democratic legitimacy. Automation may support those tasks, but it can also hollow them out.</p>\n<h3 id=\"2-follow-the-whole-life-cycle\" tabindex=\"-1\">2. Follow the whole life cycle <a class=\"header-anchor\" href=\"#2-follow-the-whole-life-cycle\">#</a></h3>\n<p>UNESCO emphasizes the AI system life cycle: research, design, development, deployment, use, maintenance, monitoring, and termination. Critical theory adds that we should also follow labor, data, energy, ownership, and institutional incentives.</p>\n<h3 id=\"3-treat-neutrality-claims-as-hypotheses\" tabindex=\"-1\">3. Treat neutrality claims as hypotheses <a class=\"header-anchor\" href=\"#3-treat-neutrality-claims-as-hypotheses\">#</a></h3>\n<p>When a system is called neutral, objective, or data-driven, treat that as a claim to be tested. What data was used? Which categories were chosen? Which histories are encoded? Which groups are overexposed to error? Who can appeal?</p>\n<h3 id=\"4-keep-humans-accountable\" tabindex=\"-1\">4. Keep humans accountable <a class=\"header-anchor\" href=\"#4-keep-humans-accountable\">#</a></h3>\n<p>Human oversight should not become a ritual phrase. A person who rubber-stamps algorithmic output is not meaningful oversight. Accountability requires authority, time, information, contestability, and consequences.</p>\n<h3 id=\"5-protect-the-public-sphere\" tabindex=\"-1\">5. Protect the public sphere <a class=\"header-anchor\" href=\"#5-protect-the-public-sphere\">#</a></h3>\n<p>AI literacy cannot mean prompt tips alone. It should include knowledge of data extraction, model limits, synthetic media, recommender systems, labor impacts, privacy, bias, and the political economy of platforms.</p>\n<h3 id=\"6-include-affected-communities\" tabindex=\"-1\">6. Include affected communities <a class=\"header-anchor\" href=\"#6-include-affected-communities\">#</a></h3>\n<p>People affected by AI systems should not appear only as data subjects or end users. They should have a role in deciding whether systems are adopted, how harms are measured, and what remedies are available.</p>\n<h2 id=\"why-we-need-it-now\" tabindex=\"-1\">Why we need it now <a class=\"header-anchor\" href=\"#why-we-need-it-now\">#</a></h2>\n<p>We need critical theory now because AI is becoming a general layer of social mediation. It is entering search, writing, education, health care, work, government, policing, warfare, culture, and intimate life. It changes not only what institutions can do, but what they can imagine doing.</p>\n<p>Without critical theory, AI will be judged mainly by convenience, productivity, market value, and technical performance. Those measures are partial. A society can become more efficient and less free. It can become more automated and less accountable. It can become more personalized and less public. It can generate more content and less understanding.</p>\n<p>Critical theory does not tell us to reject every AI system. It tells us to refuse the false choice between technological enthusiasm and technological panic. The real question is political: under what conditions, governed by whom, for whose benefit, with what rights, at what cost, and toward what forms of life?</p>\n<p>That question is difficult because AI is not one thing. It is a family of technologies, business models, infrastructures, narratives, and institutional practices. Some uses may help people. Some may be trivial. Some may be dangerous. Some may be unacceptable even if they work.</p>\n<p>Critical theory gives us a way to make those distinctions. It asks us to look past the demo and examine the system. It asks us to hear the people who are usually treated as edge cases. It asks us to connect bias to history, automation to labor, prediction to power, and innovation to ownership. It asks whether we are building tools that expand democratic agency or systems that make domination harder to see.</p>\n<p>That is why we need critical theory in the age of AI. Not because it has all the answers, but because it keeps the right questions alive.</p>\n<h2 id=\"sources\" tabindex=\"-1\">Sources <a class=\"header-anchor\" href=\"#sources\">#</a></h2>\n<ul>\n<li>Stanford Encyclopedia of Philosophy, &quot;Critical Theory (Frankfurt School),&quot; Fall 2025 archive: https://plato.stanford.edu/archives/fall2025/entries/critical-theory/</li>\n<li>UNESCO, &quot;Recommendation on the Ethics of Artificial Intelligence&quot; (2021): https://www.unesco.org/en/legal-affairs/recommendation-ethics-artificial-intelligence?hub=1063</li>\n<li>NIST, &quot;AI Risk Management Framework&quot;: https://www.nist.gov/itl/ai-risk-management-framework</li>\n<li>European Commission, &quot;AI Act&quot;: https://digital-strategy.ec.europa.eu/en/policies/regulatory-framework-ai</li>\n<li>Safiya Umoja Noble, <em>Algorithms of Oppression: How Search Engines Reinforce Racism</em> (NYU Press, 2018): https://nyupress.org/9781479837243/algorithms-of-oppression/</li>\n<li>Ruha Benjamin, <em>Race After Technology</em> (2019): https://www.ruhabenjamin.com/race-after-technology</li>\n<li>Kate Crawford, <em>Atlas of AI: Power, Politics, and the Planetary Costs of Artificial Intelligence</em> (Yale University Press, 2021): https://yalebooks.yale.edu/book/9780300252392/atlas-of-ai/</li>\n<li>Virginia Eubanks, <em>Automating Inequality</em> (2018): https://academic.macmillan.com/academictrade/9781250215789/automatinginequality/</li>\n<li>Nick Couldry and Ulises A. Mejias, <em>The Costs of Connection: How Data Is Colonizing Human Life and Appropriating It for Capitalism</em> (Stanford University Press, 2019): https://www.sup.org/books/title/?id=28816</li>\n<li>Shoshana Zuboff, <em>The Age of Surveillance Capitalism</em> (PublicAffairs, 2019): https://www.hachettebookgroup.com/titles/shoshana-zuboff/the-age-of-surveillance-capitalism/9781610395700/?lens=publicaffairs</li>\n<li>Fabian Offert and Ranjodh Singh Dhaliwal, &quot;The Method of Critical AI Studies, A Propaedeutic&quot; (arXiv, 2024): https://arxiv.org/html/2411.18833v1</li>\n<li>Stephen Cave and Kanta Dihal, &quot;The Whiteness of AI&quot; (Philosophy &amp; Technology, 2020): https://link.springer.com/article/10.1007/s13347-020-00415-6</li>\n</ul>\n",
			"date_published": "2026-07-17T04:30:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/american-philosophy-and-the-intellectual-migration-review/",
			"url": "https://www.adamdjbrett.com/blog/american-philosophy-and-the-intellectual-migration-review/",
			"title": "Review: American Philosophy and the Intellectual Migration",
			"content_html": "<h2 id=\"american-philosophy-and-the-intellectual-migration-pragmatism-logical-empiricism-phenomenology-critical-theory\" tabindex=\"-1\">American Philosophy and the Intellectual Migration: Pragmatism, Logical Empiricism, Phenomenology, Critical Theory <a class=\"header-anchor\" href=\"#american-philosophy-and-the-intellectual-migration-pragmatism-logical-empiricism-phenomenology-critical-theory\">#</a></h2>\n<p><strong>Edited by Sander Verhaegh</strong>\n<em>De Gruyter, 2025 (De Gruyter History of Philosophy and Science, vol. 1)</em></p>\n<blockquote>\n<p>Verhaegh, Sander, ed. 2025. <em>American Philosophy and the Intellectual Migration: Pragmatism, Logical Empiricism, Phenomenology, Critical Theory</em>. Berlin: De Gruyter. ISBN 978-3-11-133498-1. Open access.</p>\n</blockquote>\n<p>The intellectual migration of the 1930s and 1940s is one of those subjects everyone in philosophy knows in outline and almost no one has studied in full. Carnap fled to Chicago, Arendt to the New School, Adorno and Horkheimer to Columbia and then back to Frankfurt: the canonical stories get told and retold. <em>American Philosophy and the Intellectual Migration</em>, collecting papers from a 2022 Tilburg conference that launched an ERC/NWO research project on &quot;Exiled Empiricists,&quot; sets out to do something more ambitious than retell those stories. It wants to correct the record on how many people were actually involved, and it wants to show that the migration's effects ran through logical empiricism, phenomenology, and critical theory alike, not just through the handful of émigrés who became famous. It partly succeeds at both goals, and the ways it falls short are instructive.</p>\n<h3 id=\"the-database-is-the-real-contribution\" tabindex=\"-1\">The database is the real contribution <a class=\"header-anchor\" href=\"#the-database-is-the-real-contribution\">#</a></h3>\n<p>Sander Verhaegh's introduction does something no chapter that follows quite matches: it builds a table. Working through the Emergency Committee in Aid of Displaced Foreign Scholars' records, the 1942 APA inventory of exiled philosophers, Laura Fermi's 1968 study, Bat-Ami Zucker's visa-category analysis, and the University of Jena's Digitale Datenbank Exilphilosophie, Verhaegh assembles a list of 178 displaced philosophers who spent time in the United States between 1931 and 1945, broadly defined to include physicists, classicists, and sociologists who trained in philosophy or worked closely with philosophical movements. Every prior estimate, he shows, undercounts for a specific reason: Fermi only tracked the successful, the 1942 APA inventory only covered people still looking for work, the 1947 immigration report used a definition of &quot;philosopher&quot; narrow enough to exclude Alfred Tarski and Erich Fromm.</p>\n<p>The payoff of this work is not just a bigger number. It is a corrective to the shape of the historical narrative. Standard accounts of the migration foreground success stories, which means they foreground people like Carnap, who got a tenured chair at Chicago, over people like Janina Hosiasson-Lindenbaum, a Polish-Jewish logician working on probability whom Nagel, Quine, Hempel, and Tarski all tried and failed to place at an American institution. She was shot by the Gestapo in 1942. Verhaegh's table makes room for that story alongside the more comfortable ones, and it does so with real methodological care about who counts and why. This is exactly the kind of infrastructural scholarship that will outlast the volume built on top of it; future historians of the migration will be citing Table 1 long after they've stopped citing the chapters.</p>\n<h3 id=\"twelve-case-studies-four-uneven-parts\" tabindex=\"-1\">Twelve case studies, four uneven parts <a class=\"header-anchor\" href=\"#twelve-case-studies-four-uneven-parts\">#</a></h3>\n<p>The book's other half is a set of twelve chapters sorted into four sections: American Philosophy (pragmatism and naturalism), Phenomenology, Logical Empiricism, and Critical Theory and Political Philosophy. Each chapter is a genuine archival contribution. Cheryl Misak traces C.I. Lewis's engagement with the exiled empiricists; George Reisch and Adam Tamas Tuboly reconstruct Philipp Frank's campaign to revive the Unity of Science movement from Harvard; Fons Dewulf explains why voluntarism, a live option in Vienna, found no takers among American logical empiricists.</p>\n<p>The strongest chapter I sampled is Thomas Wheatland's &quot;Philosophical Flaschenpost,&quot; on Max Horkheimer's attempts to win over Sidney Hook and Ernest Nagel. Wheatland's argument is genuinely dialectical: Horkheimer was right that Critical Theory and Hook's Marxian pragmatism shared real philosophical ground, both trying to rescue Marxism as a social-scientific method rather than a doctrine, both working through the same Hegelian inheritance. But Horkheimer pursued that shared ground by way of immanent critique aimed at demolishing his interlocutors' positions rather than building on the overlap, and the strategy backfired into permanent animosity. Wheatland's twist is that this diagnosis of failure at the center comes paired with a story of success at the margins: Marcuse, Franz Neumann, and Fromm, working with less confrontational tactics, did the quiet work that let Critical Theory take root in American thought by the 1960s. It is a chapter that uses close archival reading (unpublished letters to Salka Viertel and Erich Fromm, in one case) to complicate a settled story rather than just confirm it.</p>\n<p>The trouble is structural rather than chapter-by-chapter. Twelve case studies drawn from the attendees of a single conference is not the same thing as a systematic account of the migration's philosophical effects, and the volume doesn't quite claim it is one, but it also doesn't fully own the gap. Some sections carry four chapters, others three; genuinely central figures in the standard story of the migration—Arendt above all, but also Cassirer and Strauss beyond the single chapter each gets folded into—appear only as supporting cast in essays organized around someone else. The four-part division itself repeats a problem visible in comparable reference works on adjacent territory: &quot;American Philosophy,&quot; &quot;Phenomenology,&quot; &quot;Logical Empiricism,&quot; and &quot;Critical Theory and Political Philosophy&quot; mix a period label, a method label, and two school labels, so the parts don't sit at a consistent level of description even though they read as parallel. A reader who wants Critical Theory's full American reception, rather than the slice Wheatland, Schliesser, and Dyzenhaus happened to write about, has to look elsewhere.</p>\n<h3 id=\"a-first-installment-not-a-synthesis\" tabindex=\"-1\">A first installment, not a synthesis <a class=\"header-anchor\" href=\"#a-first-installment-not-a-synthesis\">#</a></h3>\n<p>None of this is really a complaint about quality; it is a reminder of what kind of book this is. The conference that generated it marked the <em>start</em> of a five-year research project (2022–27), and the volume reads accordingly, as a promissory note backed by unusually strong collateral. The database in the introduction is the collateral. The chapters demonstrate, convincingly, that the migration's American story runs well beyond the logical empiricists who usually get credit for it, into phenomenology's reception through Alfred Schutz's influence on the feminist sociology of Dorothy Smith and Patricia Hill Collins, and into a critical-theory story where failure at the top made room for success elsewhere. What the book does not yet offer is a synthesis that would let a reader place Wheatland's Horkheimer alongside Ierna's phenomenologists and Katzav's philosophers of science within one coherent account of how the migration remade American philosophy. That synthesis may be exactly what the remaining years of the Exiled Empiricists project are meant to produce.</p>\n<h3 id=\"verdict\" tabindex=\"-1\">Verdict <a class=\"header-anchor\" href=\"#verdict\">#</a></h3>\n<p>This is a useful, honest, and open-access book for anyone working on twentieth-century philosophy's institutional history, and the introduction alone justifies a place in any research library on the subject: 178 names, carefully sourced, is not a small thing to hand the field. Read as a set of case studies rather than a synthetic history, the twelve chapters that follow deliver real archival payoff, Wheatland's chapter especially. Read as the definitive account of how the migration reshaped American philosophy, the book is not there yet, and it does not pretend otherwise. It is the first, well-documented installment of a project still in progress.</p>\n",
			"date_published": "2026-07-16T23:26:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/dh-part-6-minimal-computing-and-go-dh/",
			"url": "https://www.adamdjbrett.com/blog/dh-part-6-minimal-computing-and-go-dh/",
			"title": "Digital Humanities Part 6: Preservation through Minimal Computing and GO::DH",
			"content_html": "<p>This is the sixth and final essay in a series on the digital humanities. Part 1 asked what the digital humanities are. Part 2 surveyed tools for dissertations. Part 3 brought the conversation home to theology and religious studies. Part 4 made the case for why we need this work at all. Part 5 faced the uncomfortable truth that most digital projects die, and argued that preserving them is itself a form of knowledge-making. This essay is the constructive answer to Part 5's diagnosis. If digital projects die because we build them too big, too fragile, and too dependent on money and machines that will not last, then the cure is to build small, plain, and durable from the start. Two communities have spent the last decade working out what that looks like in practice: Global Outlook::Digital Humanities and the minimal computing working group that grew out of it.</p>\n<p>I want to make the argument plainly before I make it at length. Preservation is not a chore you perform at the end of a project. It is a set of decisions you make at the beginning, and the communities best positioned to teach us those decisions are not the best-funded labs in North America and Europe. They are the scholars who never had the luxury of assuming fast networks, new hardware, stable power, and permanent staff. Constraint taught them what is necessary. The rest of us, flush or not, should listen.</p>\n<h2 id=\"where-part-5-left-us\" tabindex=\"-1\">Where Part 5 Left Us <a class=\"header-anchor\" href=\"#where-part-5-left-us\">#</a></h2>\n<p>Part 5 ended with a list of failure modes, and it is worth restating them because everything in this essay answers one or more of them. Digital projects die when their databases rot and no one is left who knows the schema. They die when the content management system needs a security patch that never comes, and the hosting institution quietly takes the site down rather than risk a breach. They die when the grant ends and the server bill comes due. They die when the one graduate student who understood the custom code graduates. They die when a platform company pivots, gets acquired, or shuts off an API. And they die in a quieter way when web archives try to capture them and cannot, because the content lives behind JavaScript queries and login walls that a crawler cannot follow.</p>\n<p>Notice what all of these have in common. None of them is a failure of scholarship. The research was sound. The editions were careful. The maps were accurate. What failed was the stack, the pile of software and services and salaries that the scholarship was balanced on top of. Every layer in that pile is a promise someone has to keep, and promises lapse. A database is a promise that someone will keep migrating it. A CMS is a promise that someone will keep patching it. A server is a promise that someone will keep paying for it. Part 5 argued that we should treat preservation as knowledge-making, as real intellectual work rather than janitorial afterthought. This essay argues something more specific. The most reliable way to keep a promise is to need fewer of them. Choose the smallest adequate toolchain, and the pile gets short enough that one scholar, or one small department, can actually hold it up for decades.</p>\n<p>That phrase, the smallest adequate toolchain, is doing real work. Small alone is not the goal. A project that cannot do what the scholarship requires has failed differently but just as surely. The discipline is in the word adequate. You figure out what the work actually needs, you meet that need, and you stop. It sounds obvious. Almost no one does it. And the people who have thought hardest about how to do it came to the problem not from preservation anxiety but from a question about global equity.</p>\n<h2 id=\"global-outlook-digital-humanities\" tabindex=\"-1\">Global Outlook::Digital Humanities <a class=\"header-anchor\" href=\"#global-outlook-digital-humanities\">#</a></h2>\n<p>In January 2013, the Alliance of Digital Humanities Organizations announced the creation of its first Special Interest Group, Global Outlook::Digital Humanities, usually shortened to GO::DH.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1\">[1]</a></sup> ADHO describes it as &quot;a Community of Interest whose purpose is to help break down barriers that hinder communication and collaboration among researchers and students of the Digital Arts, Humanities, and Cultural Heritage sectors in High, Mid, and Low Income Economies.&quot;<sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2\">[2]</a></sup> Read that sentence again and notice what it does not say. It does not say GO::DH exists to help poor countries do digital humanities. The founding announcement made the point explicitly: &quot;It is not an aid programme. Instead it recognises that work is being done in many countries and regions and that we all have much to learn from each other.&quot;<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:1\">[1:1]</a></sup></p>\n<p>That sentence is the ethos of the whole enterprise. Every member has something to offer and something to learn, whatever the GDP of the country they work in. Daniel Paul O'Donnell, the founding chair, told an interviewer in 2013 how the group came together out of three experiences: conversations at the DH2012 conference in Hamburg about collaboration with scholars in China and Taiwan, his encounter with Alex Gil's project mapping digital humanities work around the world, and a December 2012 meeting with researchers in Havana. What struck him in Cuba was not deficit but kinship. The experiences were symbiotic, he recalled: &quot;we shared many problems and approaches, and, where our experiences and opportunities differed, we were richer for the discovery.&quot;<sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3\">[3]</a></sup> The group ran on volunteer labor and a few thousand dollars from the University of Lethbridge, which is itself a small lesson in adequacy.</p>\n<p>O'Donnell and his collaborators, including Gil, Katherine Walter, and Neil Fraistat, laid out the intellectual case in a chapter called &quot;Only Connect: The Globalization of the Digital Humanities.&quot;<sup class=\"footnote-ref\"><a href=\"#fn4\" id=\"fnref4\">[4]</a></sup> The argument, compressed, is that digital humanities as institutionalized in North America and Europe had mistaken itself for the whole field, when in fact digital scholarship was happening everywhere, under different names, in different languages, and under different constraints. The field's centers of gravity had mistaken their local conditions for universal ones, treating fast networks, grant economies, and English as givens.</p>\n<p>GO::DH set out to correct that by doing things rather than issuing statements. Gil's project Around DH in 80 Days, launched in 2014, published a new digital humanities project from somewhere in the world every day for eighty days, a simple, cheerful, and quietly devastating demonstration that the field was already global.<sup class=\"footnote-ref\"><a href=\"#fn5\" id=\"fnref5\">[5]</a></sup> The group ran an essay prize in its first year and received 53 entries in seven languages, with first prizes going to scholars in France, Australia, the United States, and India.<sup class=\"footnote-ref\"><a href=\"#fn6\" id=\"fnref6\">[6]</a></sup> At the DH2014 conference in Lausanne, volunteers wearing badges offered live whispered translation for attendees, an experiment the community called DH Whisperers, and the enthusiasm it revealed grew into the GO::DH Translation Toolkit, a catalog of tools and practices for multilingual conferences, journals, and projects.<sup class=\"footnote-ref\"><a href=\"#fn7\" id=\"fnref7\">[7]</a></sup> The toolkit's authors insist that &quot;the labor of translation in DH cannot be delegated to a group,&quot; meaning it is everyone's job, not a service performed by the margins for the center.<sup class=\"footnote-ref\"><a href=\"#fn7\" id=\"fnref7:1\">[7:1]</a></sup></p>\n<p>You might reasonably ask what any of this has to do with preservation. Here is the connection, and it is the hinge of this essay. When GO::DH members compared notes across high, mid, and low income economies, the differences that mattered most were infrastructural. Bandwidth. Hardware. Power. Server money. Institutional support. A scholar in Lethbridge and a scholar in Havana could share methods and questions, but they could not share assumptions about what a computer could be counted on to do. So GO::DH chartered a working group to think about exactly that problem, computing under constraint. They called it minimal computing. And it turned out that designing for scholars with little produced exactly the durability that scholars with much had been failing to achieve.</p>\n<h2 id=\"minimal-computing-what-do-we-need\" tabindex=\"-1\">Minimal Computing: What Do We Need? <a class=\"header-anchor\" href=\"#minimal-computing-what-do-we-need\">#</a></h2>\n<p>The minimal computing working group maintains a wiki, originally published under GO::DH's own domain and now at minicomp.github.io/wiki, that serves as the community's commonplace book.<sup class=\"footnote-ref\"><a href=\"#fn8\" id=\"fnref8\">[8]</a></sup> Its self-description is careful. &quot;We use 'minimal computing' to refer to computing done under some set of significant constraints of hardware, software, education, network capacity, power, or other factors.&quot;<sup class=\"footnote-ref\"><a href=\"#fn8\" id=\"fnref8:1\">[8:1]</a></sup> The definition is deliberately broad because the group noticed early that minimalism means different things depending on who is being minimal and why. The wiki notes that minimal computing covers both &quot;the maintenance, refurbishing, and use of machines to do DH work out of necessity along with the use of new streamlined computing hardware like the Raspberry Pi or the Arduino micro controller to do DH work by choice.&quot;<sup class=\"footnote-ref\"><a href=\"#fn8\" id=\"fnref8:2\">[8:2]</a></sup> Necessity and choice, the Havana case and the Lethbridge case, gathered under one tent.</p>\n<p>The founding provocation came from Alex Gil, then at Columbia University Libraries and a co-chair of GO::DH, in a short 2015 essay called &quot;The User, the Learner and the Machines We Make.&quot;<sup class=\"footnote-ref\"><a href=\"#fn9\" id=\"fnref9\">[9]</a></sup> Gil's move was to shift the conversation away from features and toward sufficiency. &quot;I prefer to approach minimal computing around the question 'What do we need?'&quot; he wrote, and he was explicit about who the we is: &quot;When I ask 'what do we need?' I'm asking scholars around the world—librarians, professors, students, cultural workers, independent: What is enough?&quot;<sup class=\"footnote-ref\"><a href=\"#fn9\" id=\"fnref9:1\">[9:1]</a></sup> He refused to let the question harden into doctrine. Minimal computing, he wrote, &quot;does not stand in as a universal call, but rather as a space for new questions and practices, an injunction to constantly repeat the question, 'what do we need?'&quot;<sup class=\"footnote-ref\"><a href=\"#fn9\" id=\"fnref9:2\">[9:2]</a></sup></p>\n<p>The question sounds humble. It is actually radical, because almost nothing in academic technology is built by asking it. Projects get built by asking what would be impressive, what the grant reviewers will reward, what the vendor is selling, what the lab down the hall just launched. &quot;What do we need?&quot; cuts through all of that. Ask it plainly about a digital scholarly edition and the answers are short. Readable text. Stable addresses. Notes and apparatus. A way for readers to find it. Nothing in that list requires a database, an application server, or a subscription.</p>\n<p>Jentery Sayers, who co-chaired the working group with John Simpson, complicated the picture productively in a 2016 essay called &quot;Minimal Definitions.&quot;<sup class=\"footnote-ref\"><a href=\"#fn10\" id=\"fnref10\">[10]</a></sup> Sayers showed that &quot;minimal&quot; fans out into many distinct commitments that do not always agree with each other. &quot;To me, minimal computing immediately suggests minimal design, especially as it pertains to workflow and communication,&quot; he begins, and then keeps going: minimal use, minimal consumption, minimal maintenance, minimal internet, minimal externals, minimal automation, minimal technical language, and more.<sup class=\"footnote-ref\"><a href=\"#fn10\" id=\"fnref10:1\">[10:1]</a></sup> On maintenance, the concern closest to this series, he observes that &quot;we might say that minimal computing simply decreases the maintenance of machines and related configurations/formats.&quot;<sup class=\"footnote-ref\"><a href=\"#fn10\" id=\"fnref10:2\">[10:2]</a></sup> The essay's real lesson is that you cannot minimize everything at once. Minimizing your own labor might mean maximizing a dependency on someone else's platform. Minimizing bandwidth might mean minimizing images your argument needs. Minimal computing is not a checklist. It is a habit of asking which constraints matter for this project, in this place, for these readers.</p>\n<p>The most mature statement of the field came in 2022, when Digital Humanities Quarterly published a special issue, volume 16 number 2, called &quot;The Questions of Minimal Computing,&quot; edited by Roopika Risam and Alex Gil.<sup class=\"footnote-ref\"><a href=\"#fn11\" id=\"fnref11\">[11]</a></sup> Their introduction distills a decade of practice into a compact framework. &quot;Minimal computing connotes digital humanities work undertaken in the context of some set of constraints,&quot; they write, and they name the stakes without flinching: &quot;In environments in which we are contending with limitations, whether of infrastructure, finances, labor, and/or technical knowledge, among other factors, we simply cannot have it all.&quot;<sup class=\"footnote-ref\"><a href=\"#fn11\" id=\"fnref11:1\">[11:1]</a></sup> Gil's founding question anchors the whole issue. &quot;'What do we need?' is a question that echoes throughout essays and case studies in this special issue,&quot; the editors note, and they sharpen it against its opposite. The minimal in minimal computing &quot;stands in stark contrast to an implied 'maximal,' where 'maximal' connotes design choices that are made without putting the question of what is necessary and sufficient at the heart of decision-making.&quot;<sup class=\"footnote-ref\"><a href=\"#fn11\" id=\"fnref11:2\">[11:2]</a></sup></p>\n<p>Maximal computing, in other words, is not a strawman. It is the default. It is what happens when nobody asks the question. And the special issue is honest about minimal computing's own tradeoffs. Quinn Dombrowski's essay in the issue, pointedly titled &quot;Minimizing Computing Maximizes Labor,&quot; argues that stripping away infrastructure does not make work disappear, it moves the work onto people, often the same overextended people the movement means to liberate.<sup class=\"footnote-ref\"><a href=\"#fn12\" id=\"fnref12\">[12]</a></sup> A static site with no CMS has no login screen, but it also has no edit button for the colleague who never learned Git. That critique is worth keeping in view. Minimal computing done thoughtlessly just relocates fragility from machines to humans. Done well, it puts the labor where labor can actually be sustained, in skills that are common, documented, and transferable rather than in systems that are rare, opaque, and rented.</p>\n<h2 id=\"what-this-looks-like-in-practice\" tabindex=\"-1\">What This Looks Like in Practice <a class=\"header-anchor\" href=\"#what-this-looks-like-in-practice\">#</a></h2>\n<p>So far this could sound like theory. It is not. Minimal computing has a mature, working toolkit, and most of it is free in both senses.</p>\n<p>Start with the writing itself. Minimal computing projects almost universally begin with plain text, usually in Markdown, a lightweight markup you can learn in an afternoon and read without any software at all. Plain text is the most durable digital format we have. Files written forty years ago open today on any machine, which is a claim no database export or word processor format can make. Markdown adds just enough structure, headings, links, emphasis, footnotes, to carry scholarly prose, and because the source is human-readable, the format cannot hold your work hostage. If every Markdown renderer on earth vanished tomorrow, your files would still say what they say.</p>\n<p>Then comes the static site generator, the workhorse of the whole movement. A static site generator takes your folder of plain text files, runs once on your own machine, and produces ordinary HTML pages. Jekyll is the elder of the family and the one GitHub Pages runs natively, which means GitHub will rebuild and host a Jekyll site for free every time you push a change.<sup class=\"footnote-ref\"><a href=\"#fn13\" id=\"fnref13\">[13]</a></sup> Eleventy is a newer, lighter option in JavaScript, and Hugo is famously fast and ships as a single executable.<sup class=\"footnote-ref\"><a href=\"#fn14\" id=\"fnref14\">[14]</a></sup> The differences matter less than what they share. The output is plain HTML, CSS, and a little JavaScript. There is no application running on the server, because there does not need to be a server in any meaningful sense at all, just a place that hands files to browsers.</p>\n<p>On top of the generators, the minimal computing community has built scholarly tools with real disciplinary intelligence. Wax, a project led by Marii Nyröp at New York University with Alex Gil, is &quot;an extensible workflow for producing scholarly exhibitions with minimal computing principles.&quot;<sup class=\"footnote-ref\"><a href=\"#fn15\" id=\"fnref15\">[15]</a></sup> It gives you what a digital collections platform gives you, image collections at archival quality served through the IIIF standard, item metadata, search, without the platform. The output is a static site you can host anywhere. Ed., a Jekyll theme Gil built for textual editions, makes the preservation argument right in its documentation. It is &quot;designed for textual editors based on minimal computing principles, and focused on legibility, durability, ease and flexibility,&quot; and it produces &quot;static pages whose rate of decay is substantially lower than database-driven systems.&quot;<sup class=\"footnote-ref\"><a href=\"#fn16\" id=\"fnref16\">[16]</a></sup> Rate of decay is exactly the right metric, and it is telling that a tool for editing poetry is the software that names it honestly.</p>\n<p>It helps to see the whole workflow in miniature, so picture a project many readers of this series might actually build, a digital edition of a nineteenth-century preacher's sermon collection. You transcribe the sermons into Markdown files, one per sermon, with a few lines of metadata at the top of each, date, place, scripture text, source archive. The folder of transcriptions goes into a Git repository, which from that moment is the project's permanent record. You drop the Ed. theme into the folder, run Jekyll once, and you have a readable, searchable, citable edition with a table of contents and stable URLs for every sermon. You push it to GitHub Pages and it is published, at no cost, over an encrypted connection, on infrastructure as fast and reliable as anything your library could rent. Total software learned: Markdown, which takes an afternoon, and enough Git to commit and push, which takes another. Total recurring cost: nothing. Total running services you are now responsible for: none. When you add sermon twenty-three next spring, you write it, commit it, and push. That is the entire maintenance story, and it will still be the entire maintenance story in fifteen years.</p>\n<p>Now line this toolkit up against Part 5's failure modes, one by one, because this is the payoff of the whole series.</p>\n<p>The database rots. There is no database. Your content is a folder of text files, and the published site is a folder of HTML files. Both can be copied, moved, and opened anywhere, by anyone, indefinitely.</p>\n<p>The CMS needs patching. Nothing here needs patching, because nothing is running. A static site has almost no attack surface, because there is no login to breach, no plugin to exploit, no admin panel to probe. Nobody takes your site down as a security risk, because it is not one.</p>\n<p>The grant ends and the server bill comes due. Static hosting is free or nearly free, on GitHub Pages and its peers, precisely because serving flat files costs providers almost nothing. A project that costs nothing to keep alive does not need a budget line to survive, which means it does not die when the budget does.</p>\n<p>The one person who understood the system leaves. The system is plain text, a folder structure, and one well-documented generator with an enormous public user base. Any successor who can use a text editor can maintain it, and the version history, if you keep the source in Git, is the documentation of every decision ever made.</p>\n<p>The platform shuts down. There is no platform. If your host disappears, you move the folder. Every internal link still works, every page is still there, and the migration takes an afternoon instead of a funded year.</p>\n<p>The web archive cannot capture it. This one matters more than people realize. Crawlers like the Internet Archive's struggle with content assembled by JavaScript queries against a live backend, which is why so many elaborate digital projects survive in the Wayback Machine only as broken shells. A static site is the easiest possible thing to crawl, because what the crawler sees is the whole site. Build minimally and the world's archives preserve you for free, without being asked.</p>\n<p>None of this is hypothetical. It is how a growing share of careful digital scholarship already works, and it is why the Endings Project at the University of Victoria, which has done the most systematic thinking anywhere about how digital projects should conclude, arrives at the same architecture from the preservation side. The Endings principles are blunt in a way academic guidelines rarely are: &quot;No dependence on server-side software: build a static website with no databases, no PHP, no Python.&quot; And again: &quot;No boutique or fashionable technologies: use only standards with support across all platforms.&quot;<sup class=\"footnote-ref\"><a href=\"#fn17\" id=\"fnref17\">[17]</a></sup> Two communities, one asking what scholars with little can build and the other asking what scholars' work needs to survive, converged on the same answer. That convergence is the strongest evidence I know that the answer is right.</p>\n<h2 id=\"justice-not-austerity\" tabindex=\"-1\">Justice, Not Austerity <a class=\"header-anchor\" href=\"#justice-not-austerity\">#</a></h2>\n<p>Here I want to guard against a misreading. It would be easy to hear all of this as an aesthetic, a sort of digital Shaker furniture, or worse, as austerity dressed up as virtue, telling underfunded scholars to be grateful for less. That gets the movement exactly backwards, and the people who built it have said so from the start.</p>\n<p>Minimal computing came out of GO::DH, which means it came out of the concrete experience of scholars working with low bandwidth, aging hardware, intermittent power, and institutions that could not promise a server would exist next year. For a scholar on a slow connection, a lean static page is not a style choice. It is the difference between a site that loads and a site that does not. For a department whose electricity fails in the afternoon, software that runs on a modest laptop and publishes to free hosting is not minimalism. It is access. Risam and Gil's introduction keeps the ledger honest, naming &quot;infrastructure, finances, labor, and/or technical knowledge&quot; as the constraints in play and refusing the fantasy that any project escapes all of them.<sup class=\"footnote-ref\"><a href=\"#fn11\" id=\"fnref11:3\">[11:3]</a></sup></p>\n<p>The justice argument runs in both directions, and this is the part the well-funded should sit with. When scholars in wealthy institutions build maximally, they do not only endanger their own work. They set the field's default expectations, and those expectations become gatekeeping. If a real digital project is assumed to need a development team, a server budget, and a grant, then most of the world's scholars are defined out of doing real digital projects, and their institutions are defined out of hosting them. Building small is a way of keeping the field's front door wide. A methodology that a graduate student in Colombo can practice on a secondhand laptop, publish for free, and maintain alone is a methodology the whole discipline can share. One that requires a lab is not.</p>\n<p>Language sits inside this argument too. GO::DH's translation work and the multilingual entries in Around DH in 80 Days both insist that a global field must be multilingual in its infrastructure, not just in its sentiments.<sup class=\"footnote-ref\"><a href=\"#fn5\" id=\"fnref5:1\">[5:1]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn7\" id=\"fnref7:2\">[7:2]</a></sup> Plain text helps here in an unglamorous way. Unicode text files handle the world's scripts without a plugin or a locale pack, and a static site serves Tamil or Yoruba or Arabic exactly as cheaply as it serves English. This is also where the critical DH literature this series leaned on in Part 4 connects. The scholars gathered in Global Debates in the Digital Humanities, edited by Domenico Fiormonte, Sukanta Chaudhuri, and Paola Ricaurte, have documented how deeply the field's infrastructure encodes the asymmetries of access, language, and power between its centers and its supposed peripheries.<sup class=\"footnote-ref\"><a href=\"#fn18\" id=\"fnref18\">[18]</a></sup> Minimal computing is one of the few practical programs that answers that critique with a build instruction rather than a lament.</p>\n<p>So the point is not that constraint is good for the soul. The point is that infrastructure choices are ethical choices, and the practices developed by scholars who had no choice about their constraints turn out to be better practices for nearly everyone, including the preservation of the work itself. Necessity was the teacher. Durability is the lesson.</p>\n<h2 id=\"minimal-computing-for-theology-and-religious-studies\" tabindex=\"-1\">Minimal Computing for Theology and Religious Studies <a class=\"header-anchor\" href=\"#minimal-computing-for-theology-and-religious-studies\">#</a></h2>\n<p>Part 3 argued that theology and religious studies are natural homes for digital scholarship. I want to close that loop, because our fields have particular reasons to take this essay's argument personally.</p>\n<p>Start with our materials. Religious studies is multilingual by constitution. The texts we study move among Hebrew, Greek, Arabic, Sanskrit, Pali, Ge'ez, Classical Chinese, and dozens of living vernaculars, often within a single project. Every layer of software you add to a project is another layer that can mishandle a script, mangle a right-to-left passage, or silently normalize a diacritic that carried meaning. Plain Unicode text handles all of it, and a static page serves a Syriac hymn as faithfully and cheaply as an English abstract. The less machinery between your sources and your readers, the fewer places for the languages to break.</p>\n<p>Then consider our colleagues. The study of religion is one of the most globally distributed conversations in the academy, and much of the most important work on lived religion happens exactly where GO::DH's mid and low income members work, in institutions without server budgets or digital humanities centers. A seminary in Nairobi, a Buddhist studies program in Colombo, a scholar of Candomblé in Salvador documenting a terreiro's archive, these are not edge cases for our field. They are the field. Methods that require a funded lab exclude them structurally. Methods built from plain text and free hosting do not. If Part 4's argument was that the digital humanities need critical attention to global asymmetry, this is what acting on that argument looks like for us in particular.</p>\n<p>And consider our time horizons. Scholars of religion think in centuries by professional habit. We work on texts that survived because communities copied them onto durable media and kept the copies moving. It should unsettle us that the scholarly editions we make of those texts are often the most fragile link in their transmission history, dependent on a database license and a hosting contract. A two-thousand-year-old psalm deserves better than a five-year platform. The manuscript cultures we study already teach the minimal computing lesson: simple formats, many copies, low dependence on any single institution, and a bias toward media that degrade slowly. A folder of Markdown files in version control, published statically and deposited in a repository, is the nearest thing our moment has to that tradition of transmission.</p>\n<p>The practical openings are everywhere once you look. A minimal edition of a sermon collection in Ed. A Wax exhibit of devotional objects photographed during fieldwork, with IIIF images that other scholars can cite and reuse. A congregation's records, digitized and published as a static archive a volunteer can maintain after the grant student graduates. A multilingual glossary of liturgical terms that loads instantly on a phone in a place where phones are the internet. None of these needs permission, a committee, or a line item. All of them can outlive their makers, which is, after all, the kind of survival our sources themselves have modeled for millennia.</p>\n<h2 id=\"people-and-places-doing-it-right\" tabindex=\"-1\">People and Places Doing It Right <a class=\"header-anchor\" href=\"#people-and-places-doing-it-right\">#</a></h2>\n<p>Arguments are easier to trust when you can point to people living them, so let me praise three by name.</p>\n<p>Lincoln Mullen, a historian of American religion at George Mason University and executive director of the Roy Rosenzweig Center for History and New Media, has spent his career demonstrating what plain-text computational scholarship in public looks like.<sup class=\"footnote-ref\"><a href=\"#fn19\" id=\"fnref19\">[19]</a></sup> His project America's Public Bible tracks the presence of biblical quotations in millions of pages of historical American newspapers, and it is exemplary twice over. Once as scholarship, an early prototype won the National Endowment for the Humanities' Chronicling America Data Challenge in 2016, and the finished work appeared as a born-digital monograph with Stanford University Press. And once as practice, because the code and data behind it sit in the open on GitHub, where anyone can inspect the methods, rerun the analysis, or learn from the workflow.<sup class=\"footnote-ref\"><a href=\"#fn20\" id=\"fnref20\">[20]</a></sup> For a religious studies scholar wondering what this series' methods look like at full maturity in our own field, Mullen is the standing answer. His GitHub account is a public lab notebook. That transparency is minimal computing's social side, scholarship whose workings are legible because its materials are plain.</p>\n<p>Mullen's institutional home deserves its own praise. The Roy Rosenzweig Center for History and New Media, founded by Roy Rosenzweig at George Mason in 1994, has probably done more than any single institution to give humanists open infrastructure.<sup class=\"footnote-ref\"><a href=\"#fn21\" id=\"fnref21\">[21]</a></sup> Zotero, the citation manager this series recommended back in Part 2, came out of RRCHNM. So did Omeka, the collections publishing platform that powers thousands of library and museum exhibits, and Tropy, which brings order to the photographs every archival researcher hauls home. These tools are free, open source, and built by people who understand scholarly work because they do scholarly work. RRCHNM's whole history is a proof that academic infrastructure can be a public good rather than a leased service.</p>\n<p>And credit where it is due to Northwestern University's Knight Lab, whose TimelineJS, StoryMapJS, and JuxtaposeJS have carried more humanities storytelling onto the web than almost anything else, precisely because they ask so little of their users.<sup class=\"footnote-ref\"><a href=\"#fn22\" id=\"fnref22\">[22]</a></sup> A scholar with a spreadsheet can have a polished interactive timeline in an hour, no code, no budget. That generosity is real and I do not want to undersell it. But Knight Lab's tools are also a good place to practice Part 5's discipline, because the standard embeds depend on Knight Lab's servers continuing to exist and to serve them. The projects are open source, so the escape hatch exists. If your timeline matters to your scholarship, plan its minimal-computing exit, self-host the library or export the underlying data so that the day the service sunsets, your work does not sunset with it. Generous tooling still deserves an exit plan. Nothing in this series is a criticism of these builders. It is a reminder that even the best-run service is a promise, and archives should not run on promises.</p>\n<h2 id=\"a-playbook-for-ending-well\" tabindex=\"-1\">A Playbook for Ending Well <a class=\"header-anchor\" href=\"#a-playbook-for-ending-well\">#</a></h2>\n<p>Everything above condenses into practice you can adopt this week. Consider this the closing playbook of the series, six habits, in roughly the order they enter a project's life.</p>\n<p>First, write in plain text. Markdown for prose, CSV for tabular data, TEI XML if your editing tradition calls for it. The test is always the same. Could a stranger in thirty years open this file with whatever they have and understand it? If the answer requires naming a company, choose differently. Your dissertation notes, your transcriptions, your metadata, all of it can live in formats that no vendor can orphan.</p>\n<p>Second, keep your sources in version control. Git costs nothing and a public or private GitHub repository gives you, for free, the three things projects die without: an off-site copy, a complete history of every change, and a path for collaborators or successors to take over cleanly. Version control is often sold to humanists as a collaboration tool. Think of it instead as continuity insurance. The repository is the project. Everything else is a rendering.</p>\n<p>Third, publish static. Run your Markdown through Jekyll, Eleventy, or Hugo, and put the result on GitHub Pages or any host that serves flat files.<sup class=\"footnote-ref\"><a href=\"#fn13\" id=\"fnref13:1\">[13:1]</a></sup> Resist every feature that requires something to be running on a server, and when a feature seems to demand it, ask Gil's question first. What do we need? Search can be a pre-built index. Comments can be an email address. Maps can be static images with a link to the interactive version. You will be surprised how often the need dissolves under the question.</p>\n<p>Fourth, use persistent identifiers. Link rot is preservation failure at retail scale, and the antidote is boring discipline. Keep your URLs stable and human-readable, never break an address you have published, and when you cite the work of others, prefer DOIs and archived links so your footnotes outlive other people's hosting decisions. The Endings Project's rule that every entity should have &quot;a unique page with a simple URL&quot; is as much about citability as durability.<sup class=\"footnote-ref\"><a href=\"#fn17\" id=\"fnref17:1\">[17:1]</a></sup></p>\n<p>Fifth, deposit your work. A website, even a durable one, should not be the only copy. Knowledge Commons, the scholarly network at hcommons.org that grew out of Humanities Commons, runs CORE, &quot;a library-quality repository for sharing, discovering, retrieving, and archiving digital work.&quot;<sup class=\"footnote-ref\"><a href=\"#fn23\" id=\"fnref23\">[23]</a></sup> Deposit the finished article, the dataset, the site's source, and your work gains a stable, citable home in institutional-grade infrastructure that is not a commercial platform and does not depend on your personal hosting arrangements. For scholars in theology and religious studies, whose societies increasingly maintain a presence there, it is the natural first shelf.</p>\n<p>Sixth, plan the ending from day one. This is the Endings Project's great reframing, and the deepest single idea I know in digital preservation.<sup class=\"footnote-ref\"><a href=\"#fn17\" id=\"fnref17:2\">[17:2]</a></sup> A digital project is not a garden that grows forever. It is a book that takes longer to finish. Write into your project charter, on the first page, what done will look like: a final static release, validated and archived, hosted cheaply, deposited in a repository, citable forever. Projects with defined endings can end well. Projects without them can only be abandoned. The difference between an ending and an abandonment is the difference between a monument and a ruin, and it is decided at the beginning, not the end.</p>\n<p>A seventh habit runs underneath the other six, and Dombrowski's labor critique is the reason to name it. Document as you go, in the same plain text as everything else. A README at the top of the repository that says what the project is, how to build it, and what each folder contains costs an hour and repays it a hundredfold, because minimal computing's real dependency is not software but memory. The system is simple enough for a successor to maintain only if the successor can find out how it works without you in the room. Write the README for a stranger. Eventually, one way or another, a stranger is who will read it, even if that stranger is you in a decade.</p>\n<p>None of these habits requires a grant. None requires a developer. None requires permission. That is the point. Preservation through minimal computing is the rare methodological reform that is more available to the underfunded than its alternative.</p>\n<h2 id=\"practicing-what-this-essay-preaches\" tabindex=\"-1\">Practicing What This Essay Preaches <a class=\"header-anchor\" href=\"#practicing-what-this-essay-preaches\">#</a></h2>\n<p>There is a small recursive pleasure in how you are reading this. This essay was written in Markdown, one plain text file, portable to anywhere, and it is rendered on a static site by markdown-it, with the footnotes you have been clicking generated by markdown-it-footnote. There is no database behind this page and no CMS in front of it. The scholarly apparatus, every citation below, travels inside the text file itself as plain footnote syntax, which means the argument and its evidence cannot be separated by a platform migration. If this site's host vanished tomorrow, this essay would move intact, footnotes and all, in seconds. The form of the essay is the argument of the essay. What do we need? For six essays on the digital humanities, we needed text files and a folder. That was enough, and enough is the whole idea.</p>\n<h2 id=\"closing-the-series\" tabindex=\"-1\">Closing the Series <a class=\"header-anchor\" href=\"#closing-the-series\">#</a></h2>\n<p>Six essays ago, this series began with a definitional question, and it seems right to end by watching how the answers stack. Part 1 argued that the digital humanities are not a gadget collection but a scholarly practice, humanistic questions pursued with computational means. Part 2 got practical, showing how that practice serves the longest project most scholars ever undertake, the dissertation. Part 3 claimed the work for theology and religious studies in particular, fields whose texts, communities, and material cultures reward digital attention as richly as any. Part 4 stepped back to make the case for why the humanities need these methods, and took seriously the critical scholars who warn that the field's infrastructure carries the world's inequities inside it. Part 5 faced the mortality of digital projects and insisted that preserving them is knowledge-making, not maintenance. And this essay has argued that the practices most likely to make our work last, plain text, small tools, static publication, planned endings, are the same practices that make the field most open to the world's scholars, because they were forged by communities, GO::DH and minimal computing, who asked what we need instead of what we can get.</p>\n<p>If you have read all six parts, you have watched an argument assemble itself. If you are arriving here first, the practical upshot fits in a sentence. Start your next project by asking what you need, write the answer in plain text, keep it in version control, publish it statically, deposit a copy, and decide on day one what finished will look like. You can begin this afternoon. The tools are free, the skills are learnable in a weekend, and the communities named in this essay have already written the documentation, which is one more thing to admire about them.</p>\n<p>That convergence is where I want to leave you. Durability and justice turn out to be the same discipline. Build small enough to keep, and you have built open enough to share. Ask what you need, and mean the question, at the start of every project, and the answer will usually be less than you feared and enough for more than you hoped. The digital humanities do not need to be big to matter. They need to last, and they need to belong to everyone. Those two goals, it turns out, have the same architecture.</p>\n<h2 id=\"in-this-series\" tabindex=\"-1\">In This Series <a class=\"header-anchor\" href=\"#in-this-series\">#</a></h2>\n<ol>\n<li>Digital Humanities Part 1: What Are the Digital Humanities?</li>\n<li>Digital Humanities Part 2: Digital Humanities Tools for Dissertations</li>\n<li>Digital Humanities Part 3: Digital Humanities for Theology and Religious Studies</li>\n<li>Digital Humanities Part 4: Why We Need the Digital Humanities</li>\n<li>Digital Humanities Part 5: Preserving Digital Humanities Projects</li>\n<li>Digital Humanities Part 6: Preservation through Minimal Computing and GO::DH</li>\n</ol>\n<hr class=\"footnotes-sep\">\n<section class=\"footnotes\">\n<ol class=\"footnotes-list\">\n<li id=\"fn1\" class=\"footnote-item\"><p>Alliance of Digital Humanities Organizations, &quot;Global Outlook::Digital Humanities (GO::DH) Special Interest Group Created,&quot; ADHO, January 13, 2013, https://adho.org/2013/01/13/global-outlookdigital-humanities-godh-special-interest-group-created/. <a href=\"#fnref1\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn2\" class=\"footnote-item\"><p>Alliance of Digital Humanities Organizations, &quot;Global Outlook::Digital Humanities,&quot; ADHO, https://adho.org/go-dh/. <a href=\"#fnref2\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn3\" class=\"footnote-item\"><p>&quot;Bringing Diversity of Experience Together: An Interview with Daniel O'Donnell,&quot; 4Humanities, May 2013, https://4humanities.org/2013/05/interview-daniel-o-donnell/. <a href=\"#fnref3\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn4\" class=\"footnote-item\"><p>Daniel Paul O'Donnell, Katherine L. Walter, Alex Gil, and Neil Fraistat, &quot;Only Connect: The Globalization of the Digital Humanities,&quot; in A New Companion to Digital Humanities, ed. Susan Schreibman, Ray Siemens, and John Unsworth (Wiley-Blackwell, 2016), https://onlinelibrary.wiley.com/doi/10.1002/9781118680605.ch34. <a href=\"#fnref4\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn5\" class=\"footnote-item\"><p>Alex Gil et al., &quot;About,&quot; Around DH in 80 Days, 2014, https://arounddh.org/about/. <a href=\"#fnref5\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref5:1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn6\" class=\"footnote-item\"><p>Alliance of Digital Humanities Organizations, &quot;Global Outlook::Digital Humanities Announces Essay Prize Winners,&quot; ADHO, December 2013, https://adho.org/announcements/2013/global-outlookdigital-humanities-announces-essay-prize-winners. <a href=\"#fnref6\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn7\" class=\"footnote-item\"><p>Global Outlook::Digital Humanities, &quot;About,&quot; The Translation Toolkit, https://go-dh.github.io/translation-toolkit/about/. <a href=\"#fnref7\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref7:1\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref7:2\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn8\" class=\"footnote-item\"><p>Global Outlook::Digital Humanities Minimal Computing Working Group, &quot;About,&quot; Minimal Computing, https://go-dh.github.io/mincomp/about/. <a href=\"#fnref8\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref8:1\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref8:2\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn9\" class=\"footnote-item\"><p>Alex Gil, &quot;The User, the Learner and the Machines We Make,&quot; Minimal Computing, May 21, 2015, https://go-dh.github.io/mincomp/thoughts/2015/05/21/user-vs-learner/. <a href=\"#fnref9\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref9:1\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref9:2\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn10\" class=\"footnote-item\"><p>Jentery Sayers, &quot;Minimal Definitions,&quot; Minimal Computing, October 2, 2016, https://go-dh.github.io/mincomp/thoughts/2016/10/02/minimal-definitions/. <a href=\"#fnref10\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref10:1\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref10:2\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn11\" class=\"footnote-item\"><p>Roopika Risam and Alex Gil, &quot;Introduction: The Questions of Minimal Computing,&quot; Digital Humanities Quarterly 16, no. 2 (2022), https://digitalhumanities.org/dhq/vol/16/2/000646/000646.html. <a href=\"#fnref11\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref11:1\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref11:2\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref11:3\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn12\" class=\"footnote-item\"><p>Quinn Dombrowski, &quot;Minimizing Computing Maximizes Labor,&quot; Digital Humanities Quarterly 16, no. 2 (2022), https://digitalhumanities.org/dhq/vol/16/2/000594/000594.html. <a href=\"#fnref12\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn13\" class=\"footnote-item\"><p>GitHub, &quot;About GitHub Pages and Jekyll,&quot; GitHub Docs, https://docs.github.com/en/pages/setting-up-a-github-pages-site-with-jekyll/about-github-pages-and-jekyll. <a href=\"#fnref13\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref13:1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn14\" class=\"footnote-item\"><p>Jekyll, https://jekyllrb.com/. Eleventy, https://www.11ty.dev/. Hugo, https://gohugo.io/. <a href=\"#fnref14\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn15\" class=\"footnote-item\"><p>Minimal Computing Working Group, &quot;Wax,&quot; Minimal Computing Wiki, https://minicomp.github.io/wiki/wax/. See also Wax's credits, which name Marii Nyröp as lead and Alex Gil as maintainer, https://github.com/minicomp/wax. <a href=\"#fnref15\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn16\" class=\"footnote-item\"><p>Minimal Computing Working Group, &quot;Ed,&quot; Minimal Computing Wiki, https://minicomp.github.io/wiki/ed/. <a href=\"#fnref16\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn17\" class=\"footnote-item\"><p>The Endings Project, &quot;Endings Principles for Digital Longevity,&quot; version 2.2.1, University of Victoria, March 3, 2023, https://endings.uvic.ca/principles.html. <a href=\"#fnref17\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref17:1\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref17:2\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn18\" class=\"footnote-item\"><p>Domenico Fiormonte, Sukanta Chaudhuri, and Paola Ricaurte, eds., Global Debates in the Digital Humanities (University of Minnesota Press, 2022), https://www.upress.umn.edu/9781517913267/global-debates-in-the-digital-humanities/. <a href=\"#fnref18\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn19\" class=\"footnote-item\"><p>Roy Rosenzweig Center for History and New Media, &quot;Our People,&quot; RRCHNM, https://rrchnm.org/our-people/. See also Lincoln Mullen's site, https://lincolnmullen.com/, and code at https://github.com/lmullen. <a href=\"#fnref19\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn20\" class=\"footnote-item\"><p>Lincoln Mullen, America's Public Bible: A Commentary (Stanford University Press, 2023), https://americaspublicbible.org/. Code and data at https://github.com/public-bible. <a href=\"#fnref20\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn21\" class=\"footnote-item\"><p>Roy Rosenzweig Center for History and New Media, https://rrchnm.org/. <a href=\"#fnref21\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn22\" class=\"footnote-item\"><p>Knight Lab, Northwestern University, https://knightlab.northwestern.edu/. <a href=\"#fnref22\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn23\" class=\"footnote-item\"><p>Modern Language Association, &quot;CORE,&quot; Knowledge Commons support documentation, https://support.mla.hcommons.org/getting-started/core/. Knowledge Commons, formerly Humanities Commons, is at https://hcommons.org/. <a href=\"#fnref23\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n</ol>\n</section>\n",
			"date_published": "2026-07-15T07:35:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/dh-part-5-preserving-digital-humanities-projects/",
			"url": "https://www.adamdjbrett.com/blog/dh-part-5-preserving-digital-humanities-projects/",
			"title": "Digital Humanities Part 5: Preserving Digital Humanities Projects",
			"content_html": "<p>Somewhere right now, a digital humanities project is dying. Nobody decided to kill it. The grant ended three years ago. The postdoc who maintained the server took a job in industry. The library migrated its hosting environment over the summer, and nobody remembered to test the old sites afterward. The project still loads, mostly. The map tiles no longer render, and the search box returns an error that nobody has reported because nobody is checking. Next year the domain registration will lapse. After that, the project will exist only as a line on someone's CV and a scatter of citations pointing at a URL that no longer answers.</p>\n<p>If you have worked in or near the digital humanities for more than a few years, you have watched this happen to something you admired. Maybe it was a database you leaned on in coursework, or an interactive edition a mentor built, or the companion site to a book you still assign. The field has produced brilliant work for three decades, and it has lost a discouraging amount of it. This essay is about why that happens and what you can do about it.</p>\n<p>I want to make one claim up front, because everything else follows from it. What happens to a project when the site is no longer maintained is not an IT question. It is a scholarly question. Preservation is not janitorial work you do after the real thinking is finished. Deciding what deserves to survive, in what form, with what documentation, under whose care — these are acts of scholarly judgment, the same kind you exercise when you choose an edition, weigh a source, or build a bibliography. A field that treats preservation as somebody else's problem is a field that has quietly decided its own work is disposable.</p>\n<p>A note on where we are. This is the fifth essay in a six-part series on the digital humanities. Part 1 asked what the digital humanities are. Part 2 surveyed tools for dissertation writers. Part 3 turned to theology and religious studies in particular. Part 4 made the case for why we need the digital humanities at all. This essay takes up the problem the first four kept circling without landing on: digital scholarship is fragile, and keeping it alive takes deliberate work. Part 6 will look at the most promising response I know, minimal computing.</p>\n<h2 id=\"the-web-forgets-link-rot\" tabindex=\"-1\">The Web Forgets: Link Rot <a class=\"header-anchor\" href=\"#the-web-forgets-link-rot\">#</a></h2>\n<p>Start with the plainest failure, the link that dies. Librarians call it link rot. You click a citation and get a 404 page, a domain squatter, or a server that never answers. Every scholar has met it. Few realize how bad it actually is.</p>\n<p>In 2013, Jonathan Zittrain, Kendra Albert, and Lawrence Lessig measured link rot in the places you would most expect durability, law journals and Supreme Court opinions. Legal citation is famously obsessive about precision, and legal writing is preserved with more institutional care than almost any other kind. It did not matter. They found that more than 70 percent of the URLs cited in the Harvard Law Review and two other Harvard law journals, and 50 percent of the URLs cited in United States Supreme Court opinions, no longer led to the material the authors had originally cited.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1\">[1]</a></sup> Sit with that for a moment. The evidentiary record of the most heavily scrutinized court on earth rests partly on citations that have already failed.</p>\n<p>The rot is not a legal peculiarity. In 2024 the Pew Research Center examined a decade of webpages and found that 38 percent of pages that existed in 2013 were no longer accessible ten years later. A quarter of all webpages that existed at any point between 2013 and 2023 were gone by the time of the study. Fifty-four percent of Wikipedia articles contained at least one link in their references pointing to a page that no longer exists, and roughly a fifth of the government and news pages Pew sampled carried at least one broken link.<sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2\">[2]</a></sup> The numbers from industry are worse. Ahrefs, a company that crawls the web commercially and has no scholarly axe to grind, sampled links pointing to more than two million websites and found that 66.5 percent of the links created since 2013 had rotted.<sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3\">[3]</a></sup></p>\n<p>The digital humanities cannot claim immunity. Zach Coble and Jojo Karlin studied citations in Digital Humanities Quarterly, one of the field's flagship open-access journals, across articles published from its 2007 launch through 2019. Thirty-one percent of the citations containing links no longer worked correctly.<sup class=\"footnote-ref\"><a href=\"#fn4\" id=\"fnref4\">[4]</a></sup> In a journal where digital humanists talk to each other about digital scholarship, nearly a third of the linked evidence has already slipped away. We are not even preserving our own conversation about preservation.</p>\n<p>If you are writing a dissertation right now, this is not an abstract worry. The URLs in your bibliography have already started to rot, and some of them will be dead before your defense. Doctoral timelines run three to seven years, which is plenty of time for a fifth of your web citations to fail at the rates measured above. Your committee may never check, but the scholar in 2040 who wants to build on your third chapter will, and what she finds when she clicks will shape whether your work remains usable evidence or becomes an artifact that must be taken on faith. Later in this essay I will describe the tools that solve this problem at the moment of citation, because it is solvable, cheaply and today.</p>\n<p>For a scholar, link rot is not an inconvenience. It is a hole in the argument. A citation is a promise to your reader: here is my evidence, go and check it. When the link dies, the promise dies with it. Your reader is left to take your word for what the source said, which is exactly the situation scholarly citation was invented to prevent.</p>\n<h2 id=\"content-drift-the-page-that-lies\" tabindex=\"-1\">Content Drift: The Page That Lies <a class=\"header-anchor\" href=\"#content-drift-the-page-that-lies\">#</a></h2>\n<p>Link rot at least has the decency to announce itself. A 404 page tells you something is wrong. The subtler failure is content drift, and it deserves a precise definition because people constantly blur it into link rot. Content drift is what happens when the URL still resolves — the server answers, a page loads, everything looks fine — but the content at that address is no longer what the author cited. The link works. The evidence is gone.</p>\n<p>The definitive study here is by Shawn M. Jones, Herbert Van de Sompel, and their colleagues, published in PLOS ONE in 2016 under a title that gives away the ending: &quot;Scholarly Context Adrift: Three out of Four URI References Lead to Changed Content.&quot; Examining links in scholarly articles, they found that for more than 75 percent of references, the content had drifted away from what it was when the author cited it. As they put it, a reader who follows a link in an article some time after publication &quot;is led to believe that the resource's content is representative of what the author originally referenced,&quot; when very often it is not.<sup class=\"footnote-ref\"><a href=\"#fn5\" id=\"fnref5\">[5]</a></sup></p>\n<p>Drift is more corrosive than rot because it is invisible. Imagine you cite a denomination's statement on marriage from its official website, and three years later the denomination revises the statement after a contentious synod vote. Your citation now points to a text that says something different from the one you analyzed, with no notice to your reader and none to you. Anyone checking your work will conclude that you misread the source, or worse, misrepresented it. The page did not die. It changed underneath your footnote, which is a quieter kind of loss and a more dangerous one.</p>\n<p>Religious studies scholars should feel this problem acutely, because so much of our source material now lives on exactly the kinds of pages that drift: congregational websites, diocesan announcements, statements from religious organizations, online devotional publications. These are working documents for the communities that publish them. They get revised, reorganized, and pruned without any obligation to the scholars who cited them. The web is a living archive maintained by people who never agreed to be an archive at all.</p>\n<h2 id=\"when-the-stack-dies\" tabindex=\"-1\">When the Stack Dies <a class=\"header-anchor\" href=\"#when-the-stack-dies\">#</a></h2>\n<p>Links and pages are only the surface. Underneath every digital project sits a stack of technologies, and stacks die too. Sometimes they die suddenly and publicly, and sometimes they die the slow death of neglect, but either way they take scholarship with them.</p>\n<p>The sudden deaths make the best cautionary tales. On December 31, 2020, Adobe ended support for Flash Player, and starting January 12, 2021, Adobe actively blocked Flash content from running in the player at all.<sup class=\"footnote-ref\"><a href=\"#fn6\" id=\"fnref6\">[6]</a></sup> Flash was not a niche technology. For roughly two decades it was the default medium for interactive work on the web: animated timelines, clickable maps, games, digital art, museum kiosks, language-learning modules, and a whole generation of interactive scholarly projects. When Adobe pulled the plug, all of it stopped working at once. Not gradually. At once. A project built in Flash in 2008 did not degrade gracefully in 2021. It simply would not run.</p>\n<p>The rescue efforts are instructive. In November 2020 the Internet Archive announced it would emulate Flash animations and games in the browser using an emulator called Ruffle, so that &quot;Flash animations, games and toys&quot; could live on without any plugin installed.<sup class=\"footnote-ref\"><a href=\"#fn7\" id=\"fnref7\">[7]</a></sup> Rhizome, the born-digital art organization, did similar work with its web archiving tools, and its preservation director Dragan Espenschied was honest about the limits: Ruffle handles self-contained Flash files &quot;quite splendidly,&quot; but emulation &quot;always introduces an extra step to access,&quot; and none of the available emulators &quot;will be able to reproduce the immediacy of Flash in its heyday.&quot;<sup class=\"footnote-ref\"><a href=\"#fn8\" id=\"fnref8\">[8]</a></sup> That honesty matters. Emulation is a rescue operation, not a preservation strategy. If your plan for your project's afterlife is that someone will heroically emulate it later, you do not have a plan. You have a hope.</p>\n<p>Java applets tell the same story with less drama. If you used the web in the early 2000s, you sat through the gray loading box of an applet embedding some interactive visualization into a page. Browser vendors dropped support for the underlying plugin architecture one by one, the applet API was deprecated in Java 9 in 2017, and by 2021 the OpenJDK project moved to strip it out entirely, noting that the API had become &quot;essentially irrelevant since all web-browser vendors have either removed support for Java browser plug-ins or announced plans to do so.&quot;<sup class=\"footnote-ref\"><a href=\"#fn9\" id=\"fnref9\">[9]</a></sup> Every scholarly project built on applets — every interactive text tool, every early mapping experiment — went down with the plugin. The technology did not fail. It was withdrawn, by companies making reasonable business decisions that had nothing to do with scholarship.</p>\n<p>Then there are the slow deaths, which are more common and less discussed. Most digital humanities projects of the 2005 to 2020 era were built on database-backed content management systems, usually Drupal, WordPress, or Omeka. These platforms are wonderful for building and terrible for lasting. They require constant security patching, and when the patches stop, the site becomes a liability. Drupal 7, which powered an enormous number of library and humanities sites, reached its official end of life on January 5, 2025, fourteen years after its release.<sup class=\"footnote-ref\"><a href=\"#fn10\" id=\"fnref10\">[10]</a></sup> Every unmigrated Drupal 7 site on a university server is now unpatchable, which means every one of them is a security incident waiting to happen. When a campus IT department takes such a site down, it is not being philistine. It is doing its job. The scholarship just happens to be collateral.</p>\n<p>Omeka deserves a special word here, because it is the platform closest to home for humanists, built by digital historians for exactly the exhibit-and-archive work our fields do. Omeka is good software, and an Omeka site is still a PHP application with a MySQL database that someone must patch, upgrade, and eventually migrate. In practice, that someone is usually one dependable person, a librarian or a technically inclined faculty member, and the site's real lifespan is the length of that person's job. The field runs to a remarkable degree on the unbudgeted goodwill of individuals. Goodwill is a lovely thing and a terrible infrastructure.</p>\n<p>Database-backed sites also fail at migration time, and migration time always comes. A dynamic site is a running program, not a document. It needs a specific version of PHP, a specific database, specific server modules, and a specific configuration, and when the library moves to new infrastructure, some of those assumptions break. A plain HTML page written in 1996 still renders perfectly in any modern browser. A dynamic site built in 2016 may already be unservable. That asymmetry tells you most of what you need to know about designing for longevity.</p>\n<p>The librarians who clean up afterward have started publishing their case notes. Kirsta Stapelfeldt and her colleagues at the University of Toronto Scarborough described rescuing a series of stranded projects: a Flash-based educational game, a Drupal mapping project on the history of a local Chinatown, a story map built on a hosted commercial platform. Their blunt assessment is that &quot;the gradual disappearance of digital scholarship projects forms a gap in the scholarly record.&quot;<sup class=\"footnote-ref\"><a href=\"#fn11\" id=\"fnref11\">[11]</a></sup> A gap in the scholarly record. That is the correct frame. When a monograph goes out of print, libraries still hold copies. When a digital project dies, there is often no copy anywhere, because nobody ever decided what a copy of it would even be.</p>\n<p>Behind almost every one of these deaths is the same economic structure. Grants fund launches. Nothing funds maintenance. A project gets three years of money, a triumphant release, a conference paper, and then a cliff. The team disperses, the money is gone, and the site enters what preservationists politely call benign neglect. The problem is not that anyone behaved badly. The problem is that the entire funding system is arranged around beginnings, and preservation is a discipline of endings.</p>\n<h2 id=\"what-stability-looks-like\" tabindex=\"-1\">What Stability Looks Like <a class=\"header-anchor\" href=\"#what-stability-looks-like\">#</a></h2>\n<p>So what actually lasts? The pattern in the wreckage is consistent, and you can state it in three preferences. Static over dynamic. Plain text over binary. Documented data over black-box platforms.</p>\n<p>Static over dynamic means the site your project leaves behind should be a set of files, not a running program. A static site — plain HTML, CSS, and JavaScript, with no database and no server-side code — can be served by any web server ever written, copied with a single command, archived by the Wayback Machine in its entirety, and handed to a library as a folder. It has almost nothing that can break. A dynamic site is a performance that must be re-staged correctly every single day. A static site is a book on a shelf.</p>\n<p>Plain text over binary means your data and your writing should live in open, human-readable formats: TEI or other XML, Markdown, CSV, JSON, plain UTF-8 text. Files like these can be opened by any editor on any machine, inspected without special software, tracked line by line in version control, and read by scholars fifty years from now with no archaeology required. Proprietary binary formats promise convenience today and demand emulation tomorrow. If you have ever tried to open a word-processor file from the early 1990s, you know which side of this bargain you want to be on.</p>\n<p>Documented data over black-box platforms means the intellectual core of your project — the dataset, the transcriptions, the encoding decisions, the categories you built — should exist independently of whatever software currently displays it, and it should be documented well enough that a stranger could pick it up. I argued in Part 4 of this series that metadata is a knowledge-making practice rather than a clerical afterthought, and preservation is where that argument pays off. An undocumented dataset is a ruin without an inscription. The stones are there, but nobody knows what the building was for.</p>\n<p>None of this is my invention. The clearest articulation of these principles comes from the Endings Project at the University of Victoria, a team of digital humanists, programmers, and librarians led by scholars including Martin Holmes and Janelle Jenstad, funded by the Social Sciences and Humanities Research Council to answer one question: how do you actually finish a digital project? Their published principles are bracingly concrete. Data should be &quot;stored only in formats that conform to open standards.&quot; Products should have &quot;no dependence on server-side software: build a static website with no databases, no PHP, no Python.&quot; Every release should be versioned and clearly identified, and pages should keep working even without JavaScript or CSS.<sup class=\"footnote-ref\"><a href=\"#fn12\" id=\"fnref12\">[12]</a></sup> They call this designing for the ending, and they treat the ending not as failure but as a normal part of a project's life, the way a monograph has a final chapter.</p>\n<p>The Endings team also gathered data on how bad the situation is. In a global survey of digital humanities practitioners conducted in 2017 and 2018, covering 127 projects, only about 24 percent of projects were considered complete, and fewer than half had any long-term preservation plan from the outset.<sup class=\"footnote-ref\"><a href=\"#fn13\" id=\"fnref13\">[13]</a></sup> In the special issue of Digital Humanities Quarterly on project resiliency that grew out of this work, the editors offer an observation that ought to be printed on a poster in every DH lab: &quot;The fewer flourishes in software, the longer the project seems to last.&quot;<sup class=\"footnote-ref\"><a href=\"#fn14\" id=\"fnref14\">[14]</a></sup> Simplicity is the preservation strategy, not a compromise you settle for when the budget is small.</p>\n<h2 id=\"a-citation-you-can-keep-permalinks-and-persistent-identifiers\" tabindex=\"-1\">A Citation You Can Keep: Permalinks and Persistent Identifiers <a class=\"header-anchor\" href=\"#a-citation-you-can-keep-permalinks-and-persistent-identifiers\">#</a></h2>\n<p>Stability of projects is half the problem. The other half is stability of reference, how you cite digital things so the citations still work in twenty years. Here the infrastructure already exists, and the failure is one of habit rather than technology.</p>\n<p>The general solution is called a persistent identifier, and the idea is simple indirection. Instead of citing a location, which changes, you cite a name, which does not, and a resolver service maintains the mapping from name to current location. The most familiar persistent identifier is the DOI, the Digital Object Identifier, administered by the DOI Foundation and resolvable through doi.org.<sup class=\"footnote-ref\"><a href=\"#fn15\" id=\"fnref15\">[15]</a></sup> When a journal moves to a new platform, every DOI pointing at its articles keeps working, because the publisher updates one registry instead of hoping every citation in the world updates itself. A DOI is only as durable as the institution behind it, but that is precisely the point. It converts a technical problem, where did the file go, into an institutional commitment, someone is responsible for this name.</p>\n<p>DOIs have siblings worth knowing. The ARK, or Archival Resource Key, was created in 2001 by John Kunze and R. P. Channing Rodgers and stewarded by the California Digital Library, and it is widely used by libraries, archives, and museums, partly because assigning ARKs is free. The ARK specification states its founding principle in a line every digital humanist should memorize: persistence &quot;is purely a matter of service,&quot; neither inherent in an object nor conferred by a naming syntax.<sup class=\"footnote-ref\"><a href=\"#fn16\" id=\"fnref16\">[16]</a></sup> Nothing about a URL, a DOI, or an ARK is magically permanent. Permanence is a promise made by an organization, and identifiers are how organizations sign their promises. PURLs, persistent URLs, have offered similar redirection since 1995, first at OCLC and, since 2016, under the care of the Internet Archive.<sup class=\"footnote-ref\"><a href=\"#fn17\" id=\"fnref17\">[17]</a></sup></p>\n<p>For the ordinary web pages you cite, the news story, the blog post, the denominational statement, there are two tools you should be using today. Perma.cc, built by the Harvard Library Innovation Lab in direct response to the link rot studies discussed above, lets you create an archived snapshot of a page at the moment you cite it, preserved by a network of libraries, with a permanent link you can put in your footnote.<sup class=\"footnote-ref\"><a href=\"#fn18\" id=\"fnref18\">[18]</a></sup> And the Internet Archive's Wayback Machine remains the great safety net under the entire web. Its scale is hard to absorb. In mid-2025 the Internet Archive announced that the Wayback Machine was about to cross one trillion archived web pages, a milestone it marked that October.<sup class=\"footnote-ref\"><a href=\"#fn19\" id=\"fnref19\">[19]</a></sup> You should not only rely on it passively. The Wayback Machine has a save-page feature, and archiving a page at citation time takes seconds. Make it a reflex, the way checking a quotation against the original is a reflex.</p>\n<p>Here is the practice I want to argue for, stated as an obligation rather than a tip. If a DOI or other persistent identifier exists for a source, citing the bare URL instead is a scholarly failure, the same category of failure as citing a book without a page number. If no persistent identifier exists, creating an archived snapshot and citing it alongside the live URL is the minimum standard of care. We hold ourselves to exacting standards about editions and translations because we know texts are unstable and transmission is treacherous. The web is the most unstable textual medium humans have ever built. It deserves at least the rigor we give a medieval manuscript tradition, and for the same reason. The reader who comes after you has to be able to find what you found.</p>\n<h2 id=\"where-projects-go-to-live-preservation-infrastructure\" tabindex=\"-1\">Where Projects Go to Live: Preservation Infrastructure <a class=\"header-anchor\" href=\"#where-projects-go-to-live-preservation-infrastructure\">#</a></h2>\n<p>Suppose you are persuaded. Your project's data is in open formats, your site can be flattened to static files, your documentation exists. Where does it all go? The good news is that the humanities do not have to build this infrastructure from scratch. Most of it already exists, much of it is free, and using it is easier than maintaining a server.</p>\n<p>Zenodo is the general-purpose workhorse. It describes itself as &quot;a free and open digital archive built by CERN and OpenAIRE, enabling researchers to share and preserve research output in any size, format and from all fields of research.&quot;<sup class=\"footnote-ref\"><a href=\"#fn20\" id=\"fnref20\">[20]</a></sup> The physics laboratory that runs the Large Hadron Collider also runs a repository where a religious studies scholar can deposit a dataset, a codebase, a PDF, or a zipped snapshot of an entire website, and every deposit receives a DOI. Zenodo also handles versioning, so your dataset can grow while old citations keep pointing at the exact version a scholar used. If your code lives on GitHub, Zenodo can archive each release automatically. Ten minutes of setup buys your project a form of citability and durability that no departmental server will ever provide.</p>\n<p>Dataverse serves a similar role with deeper roots in research data management. It is &quot;an open source web application to share, preserve, cite, explore, and analyze research data,&quot; developed at Harvard's Institute for Quantitative Social Science, and it powers institutional data repositories at universities around the world.<sup class=\"footnote-ref\"><a href=\"#fn21\" id=\"fnref21\">[21]</a></sup> Your own institution's repository, whatever software it runs, belongs in this list too. Institutional repositories are unglamorous, and they are also staffed by professionals whose actual job description includes keeping your deposit alive after you retire. Librarians have been preserving scholarship for centuries. Handing them a well-documented deposit is not outsourcing your responsibility. It is fulfilling it.</p>\n<p>Underneath the repositories sits a deeper layer most scholars never see. LOCKSS, a system developed at Stanford, operates on the principle in its name, Lots Of Copies Keep Stuff Safe: libraries around the world hold synchronized, mutually auditing copies of published content, so no single failure can destroy the record.<sup class=\"footnote-ref\"><a href=\"#fn22\" id=\"fnref22\">[22]</a></sup> Its sibling CLOCKSS runs a shared dark archive on the same technology, holding publisher content that is unlocked and made freely available if the publisher disappears.<sup class=\"footnote-ref\"><a href=\"#fn23\" id=\"fnref23\">[23]</a></sup> The insight here is old. Redundant copying by distributed communities of custodians is how the classics survived antiquity and how scripture survived everything. Anyone whose work touches the history of religious texts already understands LOCKSS in their bones. Monasteries were a distributed preservation network with a strict replication protocol. We are relearning what scriptoria knew.</p>\n<p>For humanists specifically, there is Knowledge Commons, the scholarly network formerly known as Humanities Commons, founded in 2016 under the Modern Language Association and now hosted at Michigan State University.<sup class=\"footnote-ref\"><a href=\"#fn24\" id=\"fnref24\">[24]</a></sup> Its repository, CORE, gives every deposit a DOI and puts your work in an open, library-grade archive run by and for scholars rather than by a commercial publisher. For the many people in theology and religious studies who work outside big research universities, at seminaries and small colleges without institutional repositories of their own, CORE fills a real gap. Deposit the article preprint, the syllabus, the dataset, the conference paper. It costs nothing, and it means your work has an address that does not depend on your employment status.</p>\n<p>And for the project as a whole, the Endings Project again offers the model: finish the project deliberately. Produce a final, versioned, static release. Archive it in a repository with an identifier. Document what it was, what it did, and what a future scholar can do with the data. A project that ends this way is not dead. It is complete, the way a published book is complete, and completeness is a far better afterlife than the long slow rot of an unmaintained server.</p>\n<h2 id=\"projects-die-of-people-problems\" tabindex=\"-1\">Projects Die of People Problems <a class=\"header-anchor\" href=\"#projects-die-of-people-problems\">#</a></h2>\n<p>Everything so far sounds like a technical story, and I have told it that way deliberately, because the technical failures are visible and datable. But if you talk to the people who actually run long-lived projects, they will tell you that technology is the easy part. Projects die of people problems. They die of funding cliffs, staff turnover, and graduated students. The server outlives the community around it, and then, unattended, the server dies too.</p>\n<p>The evidence here is more than anecdote. In 2014, Ithaka S+R published a study by Nancy L. Maron and Sarah Pickle with a title that names the wound: &quot;Sustaining the Digital Humanities: Host Institution Support Beyond the Start-up Phase.&quot; Drawing on interviews with well over a hundred faculty, librarians, and administrators across four campuses, they found that institutions had built elaborate support for launching digital projects and almost nothing for sustaining them.<sup class=\"footnote-ref\"><a href=\"#fn25\" id=\"fnref25\">[25]</a></sup> Everyone owns the beginning. Nobody owns year six. A university will happily issue a press release about a new digital archive and has no office whose job is to keep that archive alive when its creator takes a job elsewhere.</p>\n<p>The University of Pittsburgh's Visual Media Workshop, led by Alison Langmead, turned this insight into a practical instrument called the Socio-Technical Sustainability Roadmap, built through an NEH-funded project between 2016 and 2018.<sup class=\"footnote-ref\"><a href=\"#fn26\" id=\"fnref26\">[26]</a></sup> The roadmap's central move is in its name. Sustainability is socio-technical. It asks project teams the questions that feel rude at a launch party. How long do you intend this project to live? Who will do the work in year five, and what are they being paid? Which features will you let die first? If those questions have no answers, the project's lifespan is not unknown. It is short.</p>\n<p>The librarian Lisa Goddard, writing in the Endings-adjacent literature, distills the whole argument into one line she borrows from the DOI Foundation: &quot;persistence is a function of organizations, not a function of technology.&quot;<sup class=\"footnote-ref\"><a href=\"#fn27\" id=\"fnref27\">[27]</a></sup> Files do not keep themselves. Institutions keep files, and institutions are made of budgets and job descriptions. Graduate students are the sharpest case of this. An enormous amount of digital humanities labor is performed by doctoral students, who are structurally guaranteed to leave. If a project's continuity plan is a person who will graduate, the plan has a built-in expiration date, and everyone involved knows the date. Building on graduate labor without a succession plan writes the departure into the project's architecture from day one.</p>\n<p>And then there are the cliffs nobody can plan around. In April 2025, the Roy Rosenzweig Center for History and New Media reported that six of its NEH grants, totaling $789,000 in unspent funds, had been terminated in the federal government's mass cancellation of humanities funding. Among the terminated projects was American Religious Ecologies, which was digitizing the 1926 Census of Religious Bodies, a project close to the heart of anyone who works on American religion.<sup class=\"footnote-ref\"><a href=\"#fn28\" id=\"fnref28\">[28]</a></sup> The center's director wrote about it publicly and without self-pity, describing how the center would carry on through donor support. The lesson is grim but clarifying. Even excellent stewardship at a well-run center cannot make a project safe from politics. Which is one more reason the work itself, the data and the code and the documentation, needs to live in places designed to outlast any single funder's mood.</p>\n<h2 id=\"what-doing-it-well-looks-like\" tabindex=\"-1\">What Doing It Well Looks Like <a class=\"header-anchor\" href=\"#what-doing-it-well-looks-like\">#</a></h2>\n<p>It would be easy to end in gloom, so let me spend some time on the people who show what good stewardship looks like in practice. The digital humanities have exemplars, and they deserve to be named and praised.</p>\n<p>Take the Roy Rosenzweig Center for History and New Media at George Mason University, mentioned above in sadder circumstances. Founded in 1994 by the historian Roy Rosenzweig with a mission to use digital media &quot;to democratize history,&quot; RRCHNM is one of the oldest digital history centers in the world, and it has done something almost no one else has managed. It has kept its projects alive for decades.<sup class=\"footnote-ref\"><a href=\"#fn29\" id=\"fnref29\">[29]</a></sup> Its September 11 Digital Archive, launched in January 2002 with the American Social History Project at CUNY, collected first-hand stories, emails, and images of the attacks, more than 150,000 digital items in all. In September 2003 the Library of Congress accessioned the archive, its first major digital acquisition, and the archive is still online and still serving researchers today, more than two decades after the towers fell.<sup class=\"footnote-ref\"><a href=\"#fn30\" id=\"fnref30\">[30]</a></sup> Along the way RRCHNM built and released tools the whole field depends on, including Zotero, Omeka, and Tropy. What makes the center a model is not that it never struggles. It struggles constantly, and it writes about the struggles in public, including the unglamorous work of sustaining old projects on new infrastructure and the scramble that follows lost funding.<sup class=\"footnote-ref\"><a href=\"#fn28\" id=\"fnref28:1\">[28:1]</a></sup> Honesty about maintenance is itself a contribution to the field. Most project websites perform success. RRCHNM documents survival, which is more useful.</p>\n<p>Consider also Lincoln Mullen, professor of history at George Mason and RRCHNM's director, whose everyday practice is a model of preservation-friendly scholarship. His work lives in plain text and version control. His code is open source under permissive licenses on GitHub, his datasets are published openly, and his personal site is a static site generated from files anyone can inspect.<sup class=\"footnote-ref\"><a href=\"#fn31\" id=\"fnref31\">[31]</a></sup> His project America's Public Bible, which tracks biblical quotations across millions of pages of nineteenth-century American newspapers, won first prize in the NEH's Chronicling America Data Challenge in 2016 and grew into a digital monograph published by Stanford University Press in 2023.<sup class=\"footnote-ref\"><a href=\"#fn32\" id=\"fnref32\">[32]</a></sup> Look at how the project is put together. The website's prose is under copyright, the code is MIT licensed, and the underlying data is released into the public domain under CC0, all documented in a public repository with a suggested citation.<sup class=\"footnote-ref\"><a href=\"#fn33\" id=\"fnref33\">[33]</a></sup> Every layer of the project can be inspected, downloaded, forked, and cited independently. If the website vanished tomorrow, the scholarship would survive, because the scholarship was never only the website. For religious studies readers this example is doubly instructive, since it shows that computational work on religion at the highest level and durable open practice are the same project, not competing priorities.</p>\n<p>Then there is Knight Lab at Northwestern University, which I want to discuss with affection precisely because it complicates the story. Knight Lab makes some of the most beloved free tools in the digital humanities: TimelineJS, StoryMapJS, JuxtaposeJS, SoundciteJS. TimelineJS alone has been used by more than 250,000 people, in over sixty languages, to tell stories seen hundreds of millions of times.<sup class=\"footnote-ref\"><a href=\"#fn34\" id=\"fnref34\">[34]</a></sup> If you have taught a DH-inflected course, you have probably assigned one of these tools, and your students probably loved it. The tools are open source, and the lab has been a generous citizen of the field.</p>\n<p>Here is the complication, and it is not a criticism of Knight Lab. It is a lesson about dependency. These tools are hosted services. A TimelineJS timeline is typically driven by a published Google Sheet, which means your elegant class project depends on Google's continued support for that publishing feature and on Knight Lab's continued hosting of the rendering code. StoryMapJS projects are authored through and stored on Knight Lab's servers. Knight Lab is a university lab, staffed substantially by students, and university labs reorganize, lose funding, and change direction. None of this makes the tools bad. It makes them dependencies, and dependencies demand an exit strategy. If you build scholarship on a hosted tool, keep your own copy of the source data, export or snapshot the rendered result, and document what the tool did well enough that the work could be reconstructed. Enjoy the free infrastructure. Just do not confuse it with an archive, because its makers never promised you one.</p>\n<h2 id=\"start-with-the-ending\" tabindex=\"-1\">Start With the Ending <a class=\"header-anchor\" href=\"#start-with-the-ending\">#</a></h2>\n<p>What should you actually do, especially if you are a graduate student or early-career scholar with a project in hand and no budget line for preservation? The advice compresses well, and none of it requires permission or money.</p>\n<p>Plan the ending at the beginning. Before you build anything, write down how long the project should live, what its final form will be, and where that final form will be deposited. The Endings Project's principles are free, short, and battle-tested, and they are the assigned reading I would give any dissertation writer with a digital component.<sup class=\"footnote-ref\"><a href=\"#fn12\" id=\"fnref12:1\">[12:1]</a></sup> Choose boring, open, plain-text formats for anything you cannot afford to lose, and let the flashy presentation layer be the disposable part. Keep the project under version control from the first day, because a Git repository is a complete, portable, self-documenting history of the work that can be archived anywhere. Write the README you would want to inherit, explaining what the data is, where it came from, what the fields mean, and what a stranger may do with it.</p>\n<p>Cite digital things the way you would want your own work cited. When you cite a dataset, a code repository, a digital edition, or a website in your dissertation, cite it as scholarship, with a creator, a title, a version, a date, and a persistent identifier wherever one exists. I made this argument in Part 2 of this series in the context of dissertation tools, and it bears repeating here because citation is where preservation becomes contagious. Proper citation is how digital work gets counted in tenure files and grant reports, and work that counts is work someone will eventually pay to maintain. Every time you cite a dataset by its DOI instead of waving at a homepage, you make the scholarly record slightly more durable, and you cast a small vote for a field in which digital work is real work.</p>\n<p>Then use the infrastructure that already wants to help you. Deposit versions of your data and code in Zenodo or your institutional repository and put the resulting DOIs in your dissertation, so that what you cite is what your readers can still find. Put your papers and preprints in Knowledge Commons CORE. Archive every important web page you cite with the Wayback Machine or Perma.cc at the moment of citation. When the project is done, flatten it. Produce a static final release, deposit it, give it an identifier, and write the short note that tells the future what it was. And in every grant application and project charter you ever write, include the afterlife as a line item, because a budget that funds only the launch is a plan for a beautiful ruin.</p>\n<p>I said at the start that preservation is a scholarly question, and I will end with the reason I believe that so firmly, which is that religious studies taught it to me. Every tradition we study survived because someone treated transmission as sacred work. Texts endured through copying, glossing, cataloging, and care by communities who understood that keeping a thing alive is a form of honoring it, and that the copyist's labor was never lesser than the author's. The humanities' digital record deserves custodians with the same conviction. Preservation is not what happens after scholarship. It is scholarship, extended to the reader who has not been born yet.</p>\n<p>That conviction raises an obvious question. If projects last longest when they are simple, static, and plain, why not design them that way from the very first line of code? That is exactly the wager of minimal computing, a movement within the digital humanities that treats constraint as a scholarly virtue, and it is where this series goes next. Part 6 will look at minimal computing and the work of Global Outlook::Digital Humanities, and at what it would mean to build projects that are born preservable.</p>\n<h2 id=\"in-this-series\" tabindex=\"-1\">In this series <a class=\"header-anchor\" href=\"#in-this-series\">#</a></h2>\n<ol>\n<li>Digital Humanities Part 1: What Are the Digital Humanities?</li>\n<li>Digital Humanities Part 2: Digital Humanities Tools for Dissertations</li>\n<li>Digital Humanities Part 3: Digital Humanities for Theology and Religious Studies</li>\n<li>Digital Humanities Part 4: Why We Need the Digital Humanities</li>\n<li>Digital Humanities Part 5: Preserving Digital Humanities Projects</li>\n<li>Digital Humanities Part 6: Preservation through Minimal Computing and GO::DH</li>\n</ol>\n<hr class=\"footnotes-sep\">\n<section class=\"footnotes\">\n<ol class=\"footnotes-list\">\n<li id=\"fn1\" class=\"footnote-item\"><p>Jonathan Zittrain, Kendra Albert, and Lawrence Lessig, &quot;Perma: Scoping and Addressing the Problem of Link and Reference Rot in Legal Citations,&quot; Harvard Law Review Forum 127, no. 4 (February 2014), https://harvardlawreview.org/forum/vol-127/perma-scoping-and-addressing-the-problem-of-link-and-reference-rot-in-legal-citations/ <a href=\"#fnref1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn2\" class=\"footnote-item\"><p>Athena Chapekis, Samuel Bestvater, Emma Remy, and Gonzalo Rivero, &quot;When Online Content Disappears,&quot; Pew Research Center, May 17, 2024, https://www.pewresearch.org/data-labs/2024/05/17/when-online-content-disappears/ <a href=\"#fnref2\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn3\" class=\"footnote-item\"><p>Patrick Stox, &quot;At Least 66.5% of Links to Sites in the Last 9 Years Are Dead (Ahrefs Study on Link Rot),&quot; Ahrefs Blog, April 29, 2022, https://ahrefs.com/blog/link-rot-study/ <a href=\"#fnref3\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn4\" class=\"footnote-item\"><p>Zach Coble and Jojo Karlin, &quot;Reference Rot in the Digital Humanities Literature: An Analysis of Citations Containing Website Links in DHQ,&quot; Digital Humanities Quarterly 17, no. 1 (2023), https://dhq.digitalhumanities.org/vol/17/1/000662/000662.html <a href=\"#fnref4\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn5\" class=\"footnote-item\"><p>Shawn M. Jones, Herbert Van de Sompel, Harihar Shankar, Martin Klein, Richard Tobin, and Claire Grover, &quot;Scholarly Context Adrift: Three out of Four URI References Lead to Changed Content,&quot; PLOS ONE 11, no. 12 (December 2, 2016), https://doi.org/10.1371/journal.pone.0167475 <a href=\"#fnref5\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn6\" class=\"footnote-item\"><p>Adobe Inc., &quot;Adobe Flash Player End of Life,&quot; January 13, 2021, https://www.adobe.com/products/flashplayer/end-of-life-alternative.html <a href=\"#fnref6\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn7\" class=\"footnote-item\"><p>Jason Scott, &quot;Flash Animations Live Forever at the Internet Archive,&quot; Internet Archive Blogs, November 19, 2020, https://blog.archive.org/2020/11/19/flash-animations-live-forever-at-the-internet-archive/ <a href=\"#fnref7\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn8\" class=\"footnote-item\"><p>Dragan Espenschied, &quot;Emulation or it Didn't Happen,&quot; Rhizome, December 21, 2020, https://rhizome.org/editorial/2020/dec/21/flash-preservation/ <a href=\"#fnref8\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn9\" class=\"footnote-item\"><p>&quot;JEP 398: Deprecate the Applet API for Removal,&quot; OpenJDK, 2021, https://openjdk.org/jeps/398 <a href=\"#fnref9\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn10\" class=\"footnote-item\"><p>Drupal Association, &quot;Drupal 7 End of Life Officially Announced for 5 January 2025,&quot; Drupal.org, August 14, 2023, https://www.drupal.org/association/blog/drupal-7-end-of-life-officially-announced-for-5-january-2025 <a href=\"#fnref10\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn11\" class=\"footnote-item\"><p>Kirsta Stapelfeldt, Sukhvir Khera, Natkeeran Ledchumykanthan, Lara Gomez, Erin Liu, and Sonia Dhaliwal, &quot;Strategies for Preserving Digital Scholarship / Humanities Projects,&quot; Code4Lib Journal, no. 53 (May 2022), https://journal.code4lib.org/articles/16370 <a href=\"#fnref11\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn12\" class=\"footnote-item\"><p>The Endings Project, &quot;Endings Principles for Digital Longevity,&quot; University of Victoria, https://endings.uvic.ca/principles.html <a href=\"#fnref12\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref12:1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn13\" class=\"footnote-item\"><p>The Endings Project, &quot;Endings Project Survey Results,&quot; University of Victoria, https://endings.uvic.ca/survey.html <a href=\"#fnref13\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn14\" class=\"footnote-item\"><p>Martin Holmes, Janelle Jenstad, and J. Matthew Huculak, &quot;Introduction to Special Issue: Project Resiliency in the Digital Humanities,&quot; Digital Humanities Quarterly 17, no. 1 (2023), https://dhq.digitalhumanities.org/vol/17/1/000671/000671.html <a href=\"#fnref14\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn15\" class=\"footnote-item\"><p>DOI Foundation, &quot;The DOI System,&quot; https://www.doi.org/ <a href=\"#fnref15\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn16\" class=\"footnote-item\"><p>John A. Kunze and R. P. C. Rodgers, &quot;The ARK Identifier Scheme,&quot; IETF Internet-Draft, https://www.ietf.org/archive/id/draft-kunze-ark-34.html and ARK Alliance, &quot;The ARK Origin Story,&quot; https://arks.cdlib.org/about/the-ark-origin-story/ <a href=\"#fnref16\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn17\" class=\"footnote-item\"><p>Mark Graham, &quot;Persistent URL Service, purl.org, Now Run by the Internet Archive,&quot; Internet Archive Blogs, September 27, 2016, https://blog.archive.org/2016/09/27/persistent-url-service-purl-org-now-run-by-the-internet-archive/ <a href=\"#fnref17\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn18\" class=\"footnote-item\"><p>Harvard Library Innovation Lab, &quot;Perma.cc,&quot; https://lil.law.harvard.edu/our-work/perma-cc/ <a href=\"#fnref18\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn19\" class=\"footnote-item\"><p>Chris Freeland, &quot;Wayback Machine to Hit 'Once-in-a-Generation Milestone' this October: One Trillion Web Pages Archived,&quot; Internet Archive Blogs, July 1, 2025, https://blog.archive.org/2025/07/01/wayback-machine-to-hit-once-in-a-generation-milestone-this-october-one-trillion-web-pages-archived/ <a href=\"#fnref19\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn20\" class=\"footnote-item\"><p>Zenodo, &quot;About Zenodo,&quot; CERN, https://about.zenodo.org/ <a href=\"#fnref20\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn21\" class=\"footnote-item\"><p>The Dataverse Project, &quot;About the Project,&quot; Institute for Quantitative Social Science, Harvard University, https://dataverse.org/about <a href=\"#fnref21\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn22\" class=\"footnote-item\"><p>LOCKSS Program, &quot;About LOCKSS,&quot; Stanford University Libraries, https://www.lockss.org/about <a href=\"#fnref22\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn23\" class=\"footnote-item\"><p>CLOCKSS, &quot;Frequently Asked Questions,&quot; https://clockss.org/faq/ <a href=\"#fnref23\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn24\" class=\"footnote-item\"><p>Knowledge Commons, https://hcommons.org/ <a href=\"#fnref24\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn25\" class=\"footnote-item\"><p>Nancy L. Maron and Sarah Pickle, &quot;Sustaining the Digital Humanities: Host Institution Support Beyond the Start-up Phase,&quot; Ithaka S+R, June 18, 2014, https://sr.ithaka.org/publications/sustaining-the-digital-humanities/ <a href=\"#fnref25\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn26\" class=\"footnote-item\"><p>Visual Media Workshop, &quot;The Socio-Technical Sustainability Roadmap,&quot; University of Pittsburgh, https://sites.haa.pitt.edu/sustainabilityroadmap/about/ <a href=\"#fnref26\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn27\" class=\"footnote-item\"><p>Lisa Goddard, &quot;What's Left When It's Over: Libraries and Digital Humanities Project Preservation,&quot; IDEAH 3, no. 5, July 18, 2023, https://ideah.pubpub.org/pub/mfid9ero/release/1 <a href=\"#fnref27\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn28\" class=\"footnote-item\"><p>Lincoln Mullen, &quot;Carrying On When the Grants Go Away,&quot; Roy Rosenzweig Center for History and New Media, April 11, 2025, https://rrchnm.org/blog/carrying-on-when-the-grants-go-away/ <a href=\"#fnref28\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref28:1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn29\" class=\"footnote-item\"><p>Roy Rosenzweig Center for History and New Media, &quot;Our Story,&quot; George Mason University, https://rrchnm.org/our-story/ <a href=\"#fnref29\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn30\" class=\"footnote-item\"><p>&quot;September 11 as History,&quot; Library of Congress Information Bulletin, October 2003, https://www.loc.gov/loc/lcib/0310/911.html and The September 11 Digital Archive, https://911digitalarchive.org/ <a href=\"#fnref30\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn31\" class=\"footnote-item\"><p>Lincoln Mullen, personal website and code repositories, https://lincolnmullen.com/ and https://github.com/lmullen <a href=\"#fnref31\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn32\" class=\"footnote-item\"><p>National Endowment for the Humanities, &quot;NEH Announces Winners of Chronicling America Data Challenge,&quot; July 25, 2016, https://www.neh.gov/news/press-release/2016-07-25 <a href=\"#fnref32\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn33\" class=\"footnote-item\"><p>Lincoln A. Mullen, America's Public Bible: A Commentary (Stanford, CA: Stanford University Press, 2023), code and data repository at https://github.com/lmullen/americas-public-bible <a href=\"#fnref33\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn34\" class=\"footnote-item\"><p>Knight Lab, Northwestern University, https://knightlab.northwestern.edu/ <a href=\"#fnref34\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n</ol>\n</section>\n",
			"date_published": "2026-07-15T05:44:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/dh-part-4-why-we-need-the-digital-humanities/",
			"url": "https://www.adamdjbrett.com/blog/dh-part-4-why-we-need-the-digital-humanities/",
			"title": "Digital Humanities Part 4: Why We Need the Digital Humanities",
			"content_html": "<p><em>This is Part 4 of a six-part series on the digital humanities. Part 1 asked what the digital humanities are. Part 2 surveyed tools for dissertation writers. Part 3 turned to theology and religious studies. This part makes the argument the earlier parts have been building toward. The full list of posts appears at the end.</em></p>\n<p>For three posts now I have been describing the digital humanities. I have defined them, cataloged their tools, and traced what they offer scholars of religion. In this post I want to do something different. I want to persuade you.</p>\n<p>Here is the claim. The humanities, the universities that house them, and the publics they serve need the digital humanities. Not as a garnish on real scholarship. Not as a grant-friendly buzzword. As a necessary part of how humanistic knowledge gets made, taught, shared, and defended in this century. I will make that case on five fronts: the state of the cultural record, the publics our scholarship should reach, the way we teach, the institutions we build, and the AI moment we are living through. Then I will take the strongest critics seriously, because a case that only works against strawmen is not a case.</p>\n<p>One note on terms before we start. In Part 1 I offered a working definition: digital humanities are a contested ensemble of methods, infrastructures, pedagogies, institutions, and critical practices through which humanists create, preserve, model, analyze, publish, and critique cultural evidence in digital forms. Keep that definition in view. The argument below is not that every humanist should learn to code. It is that the humanities as a whole need people, projects, and institutions doing this work, and need them badly enough that the rest of us should care whether they thrive.</p>\n<h2 id=\"the-record-has-already-moved\" tabindex=\"-1\">The Record Has Already Moved <a class=\"header-anchor\" href=\"#the-record-has-already-moved\">#</a></h2>\n<p>Start with the evidence itself, because everything else follows from it. The cultural record that humanists study has moved. Much of it has been digitized, and an enormous and growing share of it was born digital and has never existed anywhere else.</p>\n<p>The numbers are hard to take in. Google has scanned more than 40 million books since its library project began.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1\">[1]</a></sup> HathiTrust, the academic digital library assembled by research universities, holds over 18 million digitized volumes.<sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2\">[2]</a></sup> The Digital Public Library of America aggregates more than 54 million images, texts, videos, and sounds from American libraries, archives, and museums.<sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3\">[3]</a></sup> And the Internet Archive's Wayback Machine reached a milestone in late 2025 that would have sounded like science fiction a generation ago: one trillion archived web pages.<sup class=\"footnote-ref\"><a href=\"#fn4\" id=\"fnref4\">[4]</a></sup></p>\n<p>Roy Rosenzweig saw this coming before most of his colleagues did. In 2003 he warned in the <em>American Historical Review</em> that historians &quot;may be facing a fundamental paradigm shift from a culture of scarcity to a culture of abundance.&quot;<sup class=\"footnote-ref\"><a href=\"#fn5\" id=\"fnref5\">[5]</a></sup> The traditional training of a humanist assumes scarcity. You learn to squeeze meaning from the few sources that survive. Abundance breaks that training. When the sources number in the millions, close reading alone cannot even tell you what is there. You need methods for searching, sampling, modeling, and visualizing at scale, and you need the critical judgment to know what those methods hide. That combination, method plus judgment, is exactly what the digital humanities cultivate.</p>\n<p>The born-digital record raises the stakes further. The correspondence of this century is email and chat logs. Its pamphlets are blog posts and social media threads. Its congregational newsletters, sermon archives, and denominational debates live on websites and platforms that can vanish overnight. The Library of Congress spent seven years attempting to archive the full public Twitter firehose before concluding at the end of 2017 that it could only collect selectively going forward.<sup class=\"footnote-ref\"><a href=\"#fn6\" id=\"fnref6\">[6]</a></sup> Think about what that decision means. One of the best-funded memory institutions on earth looked at a single platform's output and blinked. The record of contemporary life is being created faster than any archive can keep it, on infrastructure that scholars do not control.</p>\n<p>If you study religion, this is not an abstract problem. The religious life of the last thirty years happened substantially online. Prayer requests, fatwa databases, papal tweets, deconversion testimonies on YouTube, pandemic-era streamed liturgies. A historian of American religion writing in 2080 about the 2020s will need digital archives the way historians of the Reformation need printed pamphlets. Whether those archives exist, and whether anyone knows how to interrogate them, depends on choices being made right now, mostly by people who are not humanists.</p>\n<p>And digitized does not mean transparent. Every digital archive you search is an interface hiding a thousand decisions. What got scanned first and what still waits. How the OCR handled blackletter type, or Arabic script, or a water-stained page. What the metadata calls a &quot;sermon&quot; and what it calls a &quot;speech.&quot; When you type a term into a database and get four hundred hits, you are not seeing the past. You are seeing the residue of digitization budgets, cataloging choices, and search algorithms, and unless you know how to ask what the interface conceals, you will mistake the residue for the record. Training scholars to ask exactly that is a core competency of the digital humanities. It is source criticism, the oldest humanistic skill there is, extended to the infrastructure our sources now live in.</p>\n<p>That is the first front of the argument. The record has moved, and scholars who cannot work with digital archives, platforms, and datasets are increasingly cut off from the evidence of their own fields. This is not about fashion. It is about access to sources, which has always been the beginning of humanistic work.</p>\n<h2 id=\"what-we-cede-if-we-look-away\" tabindex=\"-1\">What We Cede If We Look Away <a class=\"header-anchor\" href=\"#what-we-cede-if-we-look-away\">#</a></h2>\n<p>Suppose the humanities collectively decided the digital turn was someone else's business. What would happen? Nothing dramatic at first. Monographs would keep appearing. Seminars would keep meeting. But ground would be ceded, quietly and steadily, on three sides.</p>\n<p>First, the interpretation of the digitized record would fall to people without humanistic training. Search engineers, platform designers, and data scientists already make consequential decisions about what parts of the cultural record are findable, how texts are classified, and which materials get prioritized for digitization. Those are interpretive acts. Every metadata schema embeds a theory of what matters. Every search ranking is an argument about relevance. When humanists are absent from that work, the theories embedded in our infrastructure go unexamined, and the record gets shaped by commercial logic alone.</p>\n<p>Second, the tools of cultural analysis would be built without us. Text mining, network analysis, and machine learning are being applied to literature, scripture, and historical archives whether or not humanists participate. The question is only whether the people applying them understand the materials. A model trained on digitized newspapers will happily produce findings about the nineteenth century. Whether those findings survive contact with what historians actually know about newspaper reprinting, OCR error, and archival gaps depends on having scholars in the room who know both the math and the archive.</p>\n<p>Third, and this one stings, the public conversation about culture would continue drifting away from the academy. People are not waiting for us. They research their genealogies, transcribe old letters, build fan wikis, and argue about history on platforms every day. The humanities can meet that energy with open projects and public scholarship, or it can watch from behind the paywall. The digital humanities, more than any other part of the academy, has spent thirty years building the meeting places.</p>\n<p>Which brings me to the strongest evidence I know that this work pays off.</p>\n<h2 id=\"the-proof-at-george-mason\" tabindex=\"-1\">The Proof at George Mason <a class=\"header-anchor\" href=\"#the-proof-at-george-mason\">#</a></h2>\n<p>If you want to see what the digital humanities give the public, look at one center's track record. The Roy Rosenzweig Center for History and New Media at George Mason University was founded in 1994 by Roy Rosenzweig, a labor and social historian with a conviction that has held up remarkably well. The center states its mission plainly: &quot;We use digital media and computer technology to democratize history: to incorporate multiple voices, reach diverse audiences, and encourage popular participation in presenting and preserving the past.&quot;<sup class=\"footnote-ref\"><a href=\"#fn7\" id=\"fnref7\">[7]</a></sup> Rosenzweig died in 2007, and the center was renamed in his honor in 2011. It has now spent more than three decades making good on that sentence.</p>\n<p>Consider what has come out of one center at one public university. Zotero, released in 2006, is free, open source software for collecting, organizing, and citing research sources.<sup class=\"footnote-ref\"><a href=\"#fn8\" id=\"fnref8\">[8]</a></sup> If you have written a dissertation in the last fifteen years, there is a fair chance Zotero managed your footnotes. It did not come from a software company. It came from historians who decided that scholars deserved a research tool they could own, extend, and trust, and it has saved researchers an incalculable amount of money and grief. Omeka, the center's web publishing platform, did the same thing for exhibitions and collections.<sup class=\"footnote-ref\"><a href=\"#fn9\" id=\"fnref9\">[9]</a></sup> Small museums, local historical societies, libraries, and classrooms use Omeka to put their holdings online with real metadata standards behind them, no vendor contract required.</p>\n<p>Then there is the September 11 Digital Archive, which the center built with the American Social History Project at the CUNY Graduate Center in the immediate aftermath of the attacks. The project collected first-person accounts, emails, photographs, and other digital materials from the public, tens of thousands of items from ordinary people, and in August 2003 the Library of Congress formally accepted the archive, describing a collection of more than 130,000 written accounts, emails, recordings, and images.<sup class=\"footnote-ref\"><a href=\"#fn10\" id=\"fnref10\">[10]</a></sup> Read that again. Two years after the event, a university center had gathered a people's archive of a national trauma and placed it in the national library. No commercial platform did that. No traditional archive could have done it at that speed. It took scholars who understood both historical documentation and the web.</p>\n<p>The pattern has continued long past those famous examples. The center also gave rise to Tropy, a desktop application for organizing the thousands of archival photographs researchers now bring home from reading rooms, and PressForward, a tool for curating and publishing scholarship from the open web, both now developed by the center's spinoff, Digital Scholar.<sup class=\"footnote-ref\"><a href=\"#fn7\" id=\"fnref7:1\">[7:1]</a></sup> Notice what unites the whole catalog. Each tool began as a real problem in a working historian's life, got solved in the open, and was given to everyone with the same problem. That is a research agenda disguised as a software shop, and it is the inverse of how commercial academic software gets made, where the problem solved is the vendor's revenue and the scholar is the product's captive.</p>\n<p>Rosenzweig himself named the principle underneath all of this. &quot;Democratized access,&quot; he wrote, &quot;is the real payoff in electronic records and materials.&quot;<sup class=\"footnote-ref\"><a href=\"#fn5\" id=\"fnref5:1\">[5:1]</a></sup> The center he founded is the standing demonstration that the payoff is real. Free tools used by millions. Public archives of national significance. Training for generations of digital historians. When someone asks you what the humanities have done for the public lately, RRCHNM is a very good answer, and it is an answer that exists only because a university invested in the digital humanities early and kept investing.</p>\n<h2 id=\"one-scholar-working-in-the-open\" tabindex=\"-1\">One Scholar, Working in the Open <a class=\"header-anchor\" href=\"#one-scholar-working-in-the-open\">#</a></h2>\n<p>Institutions matter, but so do individual examples, and I want to give you one because it answers a doubt I hear often from graduate students. The doubt goes like this: sure, big centers can do digital work, but I am one person with a dissertation and no budget. What difference can openness make at my scale?</p>\n<p>Lincoln Mullen is a professor of history at George Mason University and now directs the Roy Rosenzweig Center for History and New Media.<sup class=\"footnote-ref\"><a href=\"#fn11\" id=\"fnref11\">[11]</a></sup> Before he held any directorship, though, he was a scholar of American religion doing something that was still unusual: publishing his code, his data, and his methods alongside his arguments, all in the open, from graduate school onward.</p>\n<p>Look at how his two major projects fit together. <em>The Chance of Salvation</em>, his history of religious conversion in America, appeared from Harvard University Press in 2017 and won the American Academy of Religion's award for best first book in the history of religions.<sup class=\"footnote-ref\"><a href=\"#fn12\" id=\"fnref12\">[12]</a></sup> That is the traditional path, done well. But alongside it he built <em>America's Public Bible</em>, a computational study that tracks biblical quotation across millions of pages of digitized American newspapers, identifying which verses were quoted, when, and in what contexts. Stanford University Press published it in 2023 as an interactive scholarly work, a monograph you read by exploring it.<sup class=\"footnote-ref\"><a href=\"#fn13\" id=\"fnref13\">[13]</a></sup> And the entire apparatus behind it, the code that detects the quotations, the data, the site itself, sits in a public repository for anyone to inspect, reuse, or challenge.<sup class=\"footnote-ref\"><a href=\"#fn14\" id=\"fnref14\">[14]</a></sup></p>\n<p>That last part is the point. Mullen's methodological claims are checkable in a way most humanities arguments are not. If you doubt his quotation detection, the code is right there. If you want to run his methods on Canadian newspapers or on the Quran instead of the Bible, you can start from his repositories rather than from zero. He has also released a string of R packages that other historians now use daily, tools for tokenizing text, detecting text reuse, inferring gender from historical names, and mapping historical boundaries.<sup class=\"footnote-ref\"><a href=\"#fn15\" id=\"fnref15\">[15]</a></sup> Each one is a piece of his own research process, generalized and given away.</p>\n<p>I will not pretend the openness was free. Publishing your code means letting strangers find your bugs. Releasing your data means someone may scoop the article you meant to write from it. Building tools counts unevenly in tenure files that were designed for monographs, a real inequity the field is still fighting to fix. Mullen made those trades anyway, and the return on them is a career's worth of evidence that generosity is a viable scholarly strategy, not a sacrifice of one. His grants, his press contracts, and his directorship all came to a scholar whose defining habit is giving the work away.</p>\n<p>One scholar, working openly, has changed how a field works. Historians of American religion now have a model for computational argument, a toolkit they did not have to build, and a standard of transparency to aspire to. Multiply that example across the disciplines and you begin to see what the humanities forfeit when open computational practice remains rare. This is why we need the digital humanities in the plural, as a community of practice. Openness compounds. Every released dataset lowers the cost of the next project. Every published method teaches the next student. Closed scholarship cannot compound this way, because there is nothing for the next person to build on except the citations.</p>\n<h2 id=\"teaching-in-the-open\" tabindex=\"-1\">Teaching in the Open <a class=\"header-anchor\" href=\"#teaching-in-the-open\">#</a></h2>\n<p>The pedagogical case may be the least glamorous front of this argument and the most important. In Part 1 I argued, following Brian Croxall and Diane Jakacki's collection <em>What We Teach When We Teach DH</em>, that the digital humanities are learned through practice, in classrooms and workshops, through modules and metadata exercises and mapping assignments.<sup class=\"footnote-ref\"><a href=\"#fn16\" id=\"fnref16\">[16]</a></sup> Claire Battershill and Shawna Ross make the same point at book length for working instructors, and Johanna Drucker's <em>Digital Humanities Coursebook</em> turns it into a full curriculum.<sup class=\"footnote-ref\"><a href=\"#fn17\" id=\"fnref17\">[17]</a></sup> Teaching is not what happens after the real DH work is done. Teaching is the work, because a method that cannot be taught dies with its inventor.</p>\n<p>The clearest demonstration of what open digital pedagogy looks like is <em>Digital Pedagogy in the Humanities: Concepts, Models, and Experiments</em>, published by the Modern Language Association in 2020 after years of open development. The project is organized as a set of curated keywords, 59 of them, each introduced by a scholar-curator and supported by concrete pedagogical artifacts. Syllabi, assignment prompts, exercises, lesson plans, student work. More than 500 artifacts in all, and each one is provided in a modifiable, openly licensed format so you can take it, adapt it, and use it in your own classroom this semester.<sup class=\"footnote-ref\"><a href=\"#fn18\" id=\"fnref18\">[18]</a></sup></p>\n<p>Sit with how different that is from the way teaching knowledge usually circulates in the academy, which is to say, barely at all. Most syllabi live and die on a single campus. Most brilliant assignments are never seen by anyone but the students who complete them. <em>Digital Pedagogy in the Humanities</em> treats teaching materials as scholarship, curates them with the seriousness of an edited volume, subjects them to open review, and then gives them away. The project was even reviewed in public before publication, with the draft keywords posted for open commentary.<sup class=\"footnote-ref\"><a href=\"#fn18\" id=\"fnref18:1\">[18:1]</a></sup></p>\n<p>If you teach, you can feel the force of this immediately. A new instructor assigned a digital methods course does not have to invent it alone. A theologian who wants students to build an online exhibit can start from artifacts that worked elsewhere. The commons model does for pedagogy what Mullen's repositories do for research. It compounds.</p>\n<p>Picture the difference in an ordinary classroom. A religious studies seminar spends a unit building a small digital exhibit on local congregations. The students photograph buildings, interview members, write catalog entries, and wrestle with metadata. Is this building a &quot;church&quot; or a &quot;former church&quot;? Whose name goes on an oral history? What does the community get to veto? By the end of the unit they have learned description, provenance, consent, and audience, which is to say they have learned the working ethics of the archive, and they learned it by making something a stranger can visit. Now ask what the same unit teaches as a term paper. The paper is read once, by one person, and filed. I am not against term papers. I assign them. But a pedagogy that never asks students to make public knowledge is training them for a version of the humanities that speaks only to itself, and students can tell.</p>\n<p>And notice what makes it possible. The collection is not open by accident. It is open because the digital humanities community made openness a professional norm, argued for it inside a scholarly society as traditional as the MLA, and built the platform to carry it. Which raises the question of platforms directly.</p>\n<h2 id=\"infrastructure-we-own\" tabindex=\"-1\">Infrastructure We Own <a class=\"header-anchor\" href=\"#infrastructure-we-own\">#</a></h2>\n<p>Where does open scholarship actually live? For too many academics the honest answer is: on venture-funded platforms that exist to monetize them. Academia.edu and ResearchGate present themselves as scholarly commons, but they are for-profit companies, and their business models run on the attention and data of researchers. The paper you upload becomes bait for someone else's subscription prompt.</p>\n<p>The digital humanities community built an alternative. Humanities Commons launched in December 2016 as a project of the Modern Language Association, funded by the Andrew W. Mellon Foundation, offering scholars profiles, group discussion, website hosting, and an open access repository called CORE where work receives a permanent DOI and joins the open scholarly record.<sup class=\"footnote-ref\"><a href=\"#fn19\" id=\"fnref19\">[19]</a></sup> In November 2020 its home moved to Michigan State University, and in 2024 it took the name Knowledge Commons, reflecting a membership that had grown well beyond the humanities.<sup class=\"footnote-ref\"><a href=\"#fn20\" id=\"fnref20\">[20]</a></sup> The network now serves tens of thousands of scholars and practitioners. Kathleen Fitzpatrick, the project's director and one of the most consistent voices for open infrastructure in the academy, describes it as open access, open source, and nonprofit, which is precisely the combination the commercial platforms cannot offer.<sup class=\"footnote-ref\"><a href=\"#fn21\" id=\"fnref21\">[21]</a></sup></p>\n<p>The distinction is not sentimental. It is about governance and survival. A platform owned by its scholarly community answers to that community. A platform owned by investors answers to an exit strategy. When a for-profit network changes its terms, locks features behind payment, or sells, scholars have no recourse and their work is hostage. When Knowledge Commons makes a decision, it does so as academic infrastructure, hosted at a public university, sustained by grants and institutional support, with its code in the open.</p>\n<p>If you are reading this as a working scholar, the practical translation is simple. You probably have work that deserves readers and sits where none can find it. A conference paper, a dissertation chapter, a dataset, a syllabus. Depositing it in an open repository with a permanent identifier takes an afternoon and makes it citable forever, and doing that on community-owned infrastructure rather than a commercial network means your afternoon strengthens the commons instead of somebody's quarterly numbers. Small choices like this are how infrastructure survives. Platforms live on participation the way journals live on submissions, and every scholar who moves their work into the open commons casts a vote for the version of scholarly communication they want to exist.</p>\n<p>Here is why this belongs in an argument about why we need the digital humanities. Infrastructure like this does not emerge from the humanities' traditional ways of working. It takes people who can think like scholars and build like engineers, who understand peer review and metadata schemas and server costs all at once, and who can persuade learned societies and foundations to fund the unglamorous work of keeping a platform alive. Those people are the digital humanities. Without them, open access remains a sermon. With them, it becomes a place you can actually put your work.</p>\n<h2 id=\"building-capacity-inside-a-public-university\" tabindex=\"-1\">Building Capacity Inside a Public University <a class=\"header-anchor\" href=\"#building-capacity-inside-a-public-university\">#</a></h2>\n<p>Arguments about the academy can float free of any actual institution, so let me ground this one. Michigan State University shows what it looks like when a large public university decides to build digital humanities capacity deliberately rather than accidentally.</p>\n<p>DH@MSU, the university's digital humanities program, describes itself as a community of faculty, librarians, staff, and students collaborating across departments and colleges, with a stated goal to &quot;lead at MSU and on the international stage in enhancing arts and humanities research and teaching through digital methods.&quot;<sup class=\"footnote-ref\"><a href=\"#fn22\" id=\"fnref22\">[22]</a></sup> The program offers an undergraduate minor in digital studies and a graduate certificate that requires coursework, pedagogy, and a research portfolio, which means students can leave MSU with digital humanities training credentialed on their transcripts, not just picked up in the hallway.<sup class=\"footnote-ref\"><a href=\"#fn22\" id=\"fnref22:1\">[22:1]</a></sup></p>\n<p>The capacity runs deeper than the degree programs. MATRIX, the university's Center for Digital Humanities and Social Sciences, has been building digital projects since 1997, with a mission that emphasizes collaborative, sustainable, openly accessible work and a longstanding focus on the African diaspora and continent.<sup class=\"footnote-ref\"><a href=\"#fn23\" id=\"fnref23\">[23]</a></sup> LEADR, a lab run between the History and Anthropology departments, puts digital research methods directly into the undergraduate curriculum.<sup class=\"footnote-ref\"><a href=\"#fn24\" id=\"fnref24\">[24]</a></sup> The university hosts Knowledge Commons, as we just saw. And it recruited Fitzpatrick to direct digital humanities there in 2017, a hire that signaled the institution understood this was a field you invest in with people, not just servers.<sup class=\"footnote-ref\"><a href=\"#fn21\" id=\"fnref21:1\">[21:1]</a></sup></p>\n<p>Why does the institutional story matter for my argument? Because critics of the digital humanities often picture it as a fad imposed from above, a shiny object administrators chase. MSU shows the opposite pattern. Decades of patient, cumulative capacity building. Labs that teach methods to sophomores. Certificates that survive leadership changes. Infrastructure adopted from a scholarly society and sustained. Fads do not survive decades of leadership changes, budget cycles, and curriculum committees. This has. It is a public university treating digital scholarship as core academic capacity, the way an earlier generation treated area studies centers or university presses. Other institutions can do the same, and the ones that do will be the places where the next generation of humanists actually wants to train.</p>\n<p>You do not need MSU's scale to act on the lesson. A small college can cross-list one digital methods course and give it a permanent number. A seminary can put a librarian with metadata training on every digital project from day one. A department can decide that a peer-reviewed digital project counts in tenure review and write that into its bylaws, which costs nothing and changes everything for the assistant professor deciding what to build. Capacity is not a budget line first. It is a set of decisions about what counts, who gets hired, and what students are allowed to make, and every one of those decisions is available to your institution this year.</p>\n<h2 id=\"the-argument-the-humanities-need-to-win\" tabindex=\"-1\">The Argument the Humanities Need to Win <a class=\"header-anchor\" href=\"#the-argument-the-humanities-need-to-win\">#</a></h2>\n<p>Step back from the particular examples and notice the larger fight they belong to. The humanities have spent two decades answering the same question from legislators, trustees, parents, and deans: what are you for? The question is often asked in bad faith, and the best answers, that the humanities teach judgment, that a society without them forgets what it is, are true and rarely persuade the people holding the budget. Enrollments have slid. Departments have been merged and closed. You know the litany. I will not rehearse it further, except to point out one thing about every example in this post. Each one is an answer to that question which does not require the asker to already love the humanities.</p>\n<p>A state legislator may not care about historiography, but a free tool used by millions of researchers is legible to them. A parent may not care about archival theory, but a public archive of September 11 that lives in the Library of Congress is legible to them.<sup class=\"footnote-ref\"><a href=\"#fn10\" id=\"fnref10:1\">[10:1]</a></sup> A trustee may not read monographs, but a platform that saves scholars from predatory publishing costs is legible to them. This is not selling out. The work is scholarship all the way down, and I have spent this whole post showing its intellectual seriousness. It is translation. The digital humanities produce public evidence of the humanities' value at a moment when the humanities are being asked for evidence, and no other part of our fields produces it at the same scale or in a form the public can hold in its hands.</p>\n<p>There is a defensive version of this point and an affirmative one, and I want to be clear I am making both. Defensively, yes, digital projects give provosts and deans something to point to, and fields that give their institutions nothing to point to get cut. You do not have to like that logic to plan for it. Affirmatively, and this matters more, public scholarship is what many of us wanted from the humanities all along. Rosenzweig did not build free tools as a budget strategy. He built them because he believed the past belongs to everyone and acted on it.<sup class=\"footnote-ref\"><a href=\"#fn7\" id=\"fnref7:2\">[7:2]</a></sup> The happy fact is that the same work serves both purposes. It keeps the lights on, and it keeps the faith.</p>\n<h2 id=\"the-skeptics-deserve-an-answer\" tabindex=\"-1\">The Skeptics Deserve an Answer <a class=\"header-anchor\" href=\"#the-skeptics-deserve-an-answer\">#</a></h2>\n<p>Now the hard part. In 2016, Daniel Allington, Sarah Brouillette, and David Golumbia published an essay in the <em>Los Angeles Review of Books</em> called &quot;Neoliberal Tools (and Archives): A Political History of Digital Humanities,&quot; and it remains the sharpest attack the field has faced.<sup class=\"footnote-ref\"><a href=\"#fn25\" id=\"fnref25\">[25]</a></sup> If you have absorbed anything from this series so far, you owe it to yourself to read the case against.</p>\n<p>Their argument, compressed: the digital humanities rose not because of intellectual merit but because the field fit the needs of a university being restructured on corporate lines. &quot;By providing a model for humanities teaching and research that appears to overcome these perceived limitations,&quot; they write, &quot;Digital Humanities has played a leading role in the corporatist restructuring of the humanities.&quot;<sup class=\"footnote-ref\"><a href=\"#fn25\" id=\"fnref25:1\">[25:1]</a></sup> The field, they charge, &quot;has often tended to be anti-interpretive,&quot; preferring to &quot;archive materials, produce data, and develop software, while bracketing off the work of interpretation.&quot;<sup class=\"footnote-ref\"><a href=\"#fn25\" id=\"fnref25:2\">[25:2]</a></sup> And they note, pointedly, that &quot;Digital Humanities is pushed far more strongly by university administrators than it is by scholars and students.&quot;<sup class=\"footnote-ref\"><a href=\"#fn25\" id=\"fnref25:3\">[25:3]</a></sup></p>\n<p>I want to resist the reflex to wave this off, because parts of it land. It is true that administrators and funders have sometimes loved DH for bad reasons, as a photogenic answer to the crisis of the humanities that asks nothing of budgets for tenure lines. It is true that grant-driven project work can pull junior scholars into service roles without security or credit. It is true that a lab full of deliverables can crowd out the slow interpretive work that has no demo day. Anyone who has watched a university chase innovation theater knows the pattern the critics are describing. It is real.</p>\n<p>But the argument fails as a description of the field, and it fails in three ways.</p>\n<p>First, it mistakes the vulnerability for the essence. Every part of the university can be bent toward corporate logic, including the traditional humanities, whose adjunctified survey courses are hardly a refuge from neoliberalism. The question is not whether DH can be co-opted. Everything can. The question is what the work itself does, and the record I have laid out in this post, free tools, public archives, open pedagogy, community-owned infrastructure, is mostly a record of decommodification. Zotero replaced software that cost money. Knowledge Commons competes with platforms that harvest scholars' data. The September 11 Digital Archive put a people's history in the Library of Congress. If this is neoliberalism's advance guard, it has a strange way of showing it.</p>\n<p>Second, the anti-interpretive charge does not survive contact with the field's own literature. The most prominent development in digital humanities over the past decade has been precisely the growth of its critical wing. <em>Global Debates in the Digital Humanities</em> confronts the field's Anglophone and Global North defaults.<sup class=\"footnote-ref\"><a href=\"#fn26\" id=\"fnref26\">[26]</a></sup> Elizabeth Losh and Jacqueline Wernimont's <em>Bodies of Information</em> brings intersectional feminist analysis to bear on data and computation.<sup class=\"footnote-ref\"><a href=\"#fn27\" id=\"fnref27\">[27]</a></sup> James Dobson's <em>Critical Digital Humanities</em> subjects computational methods themselves to sustained interpretive scrutiny.<sup class=\"footnote-ref\"><a href=\"#fn28\" id=\"fnref28\">[28]</a></sup> David Berry and Anders Fagerjord argue that the field's task is knowledge and critique in a digital age, not tool building for its own sake.<sup class=\"footnote-ref\"><a href=\"#fn29\" id=\"fnref29\">[29]</a></sup> A field allergic to interpretation could not have produced this shelf. The critics wrote as if DH's center of gravity were the software demo. Its center of gravity is now the argument about what computation does to knowledge, which is an interpretive question if anything is.</p>\n<p>Third, the field answered rather than flinched, and the answers were often more interesting than the attack. Within days of the essay, responses came from across the field, and the exchange is worth reading as a whole.<sup class=\"footnote-ref\"><a href=\"#fn30\" id=\"fnref30\">[30]</a></sup> Andrew Piper, Juliana Spahr, and Richard Jean So replied in the same venue that they were &quot;sympathetic to the observations that provoked this essay&quot; while showing that other disciplines &quot;have benefited greatly from the merging of critical and computational modes of analysis.&quot;<sup class=\"footnote-ref\"><a href=\"#fn31\" id=\"fnref31\">[31]</a></sup> Matthew Kirschenbaum's wry personal essay, &quot;Am I a Digital Humanist? Confessions of a Neoliberal Tool,&quot; took the accusation apart from the inside.<sup class=\"footnote-ref\"><a href=\"#fn32\" id=\"fnref32\">[32]</a></sup> The pattern matters. A healthy field metabolizes its critics. The digital humanities took the hardest punch available and got more self-aware, more global, and more political as a result. That is not what a hollow administrative fad does. It is what a discipline does.</p>\n<p>So keep the skeptics on your shelf. They are the field's conscience, and the labor critique in particular should be tattooed on every project budget. But the conclusion they wanted you to draw, that the humanities would be safer without the digital humanities, gets the situation exactly backward. The forces they fear, austerity, platform capitalism, the reduction of knowledge to product, are advancing on the humanities regardless. The digital humanities are one of the few places in the academy building the countervailing tools, archives, and institutions. Disarming ourselves is not resistance.</p>\n<h2 id=\"the-ai-moment\" tabindex=\"-1\">The AI Moment <a class=\"header-anchor\" href=\"#the-ai-moment\">#</a></h2>\n<p>Everything above was true five years ago. The rise of large language models has made it urgent.</p>\n<p>Machine learning systems are now trained on the digitized cultural record, the same scanned books, archived web pages, and digitized newspapers I described at the start of this post. Companies claim these models understand language, reason about texts, and can stand in for human judgment. Those are claims about culture, meaning, and interpretation. They are, in other words, humanities claims, made at industrial scale by people with no obligation to the evidence, and they demand examination by people trained to give it.</p>\n<p>Who is equipped to do that examination? You need to understand how the training data was assembled and what it omits, which is an archival question. You need to understand what a model actually does with text, which is a methodological question. And you need to understand what is lost when statistical pattern stands in for meaning, which is an interpretive question. That combination is the digital humanities' home territory, and the most influential critiques of the current AI regime have come from exactly this borderland between technical fluency and humanistic judgment. Emily Bender and her colleagues' &quot;stochastic parrots&quot; paper, which forced the phrase into the public debate, is at bottom a linguist's argument about the difference between form and meaning.<sup class=\"footnote-ref\"><a href=\"#fn33\" id=\"fnref33\">[33]</a></sup> Kate Crawford's <em>Atlas of AI</em> reads artificial intelligence the way a historian reads an empire, through its extraction of labor, minerals, and data.<sup class=\"footnote-ref\"><a href=\"#fn34\" id=\"fnref34\">[34]</a></sup> Catherine D'Ignazio and Lauren Klein's <em>Data Feminism</em>, published open access, gives readers a framework for asking whose interests any data regime serves.<sup class=\"footnote-ref\"><a href=\"#fn35\" id=\"fnref35\">[35]</a></sup> None of these interventions could have been written by a pure technologist or a pure critic. They required people fluent in both registers.</p>\n<p>The same borderland produces the careful middle position the public conversation badly needs. Ted Underwood, a literary scholar who has used computational methods for years, greeted language models neither with panic nor with hype but with experiments, testing what the models can and cannot do with fiction and documenting the results in the open.<sup class=\"footnote-ref\"><a href=\"#fn36\" id=\"fnref36\">[36]</a></sup> That is the temperament the moment calls for. Investigate the thing instead of cheering for it or refusing to look at it.</p>\n<p>Religious studies has particular stakes in this examination, so let me name them. Language models are trained on scriptures, sermons, apologetics, and centuries of religious polemic, and they will answer questions about all of it, fluently and with no sense of what they do not know. Ask one about a Bible verse and you get something shaped by exactly the history of quotation and contestation that Mullen's project maps, flattened into a confident paragraph.<sup class=\"footnote-ref\"><a href=\"#fn13\" id=\"fnref13:1\">[13:1]</a></sup> Communities are already using these systems for devotional questions, and pastoral ones. Who will study what the models say about religion, whose theology dominates their training data, and what happens to religious authority when the answer machine speaks? Scholars of religion who understand how the systems work. That is a digital humanities job description, and the posting is open now.</p>\n<p>There is a training argument here too, and it points at your classroom. Students now arrive having used AI systems for years, with no framework for thinking about what these systems are. The instructor who can teach them to interrogate a model, ask what is in the training data, probe where the outputs fail, name who profits, is doing core humanities work, the examination of powerful cultural claims, with the tools of the present. The digital humanities built the pedagogy for this over two decades of teaching students to work critically with data and computation. We need that pedagogy in every humanities department, not because AI is the future of the humanities, but because the humanities are how a society thinks clearly about AI.</p>\n<p>And if the humanities do not claim this ground? Then the interrogation of AI's claims on culture will be left to the industry's own researchers and to whatever regulators can manage. The past decade of platform history tells you how that goes. This is the ceded-ground argument from the top of this post, at higher stakes and on a shorter clock. It is the strongest single reason I know why we need the digital humanities now and not eventually.</p>\n<h2 id=\"none-of-it-survives-by-accident\" tabindex=\"-1\">None of It Survives by Accident <a class=\"header-anchor\" href=\"#none-of-it-survives-by-accident\">#</a></h2>\n<p>Here is the uncomfortable coda to everything I have argued. Suppose you are persuaded. The record has moved, the public projects are real, the pedagogy compounds, the institutions can be built, the AI moment demands us. Every item in that case depends on digital projects continuing to exist, and digital projects are mortal. Grant funding ends. Servers get decommissioned. Software rots. The graduate student who maintained the database graduates. Some of the most celebrated digital humanities projects of the 2000s are already gone, or survive only as screenshots and citations to dead links.</p>\n<p>Rosenzweig, again, saw it first. We have moved from a world where the record decayed slowly on paper to one where it can vanish instantly and completely. &quot;We have never preserved everything,&quot; he wrote, but &quot;we need to start preserving something.&quot;<sup class=\"footnote-ref\"><a href=\"#fn5\" id=\"fnref5:2\">[5:2]</a></sup> An argument for why we need the digital humanities is incomplete without an argument for keeping digital humanities work alive, and that is where this series goes next. Part 5 takes up preservation directly, and Part 6 looks at minimal computing and the Global Outlook::Digital Humanities community as a path toward projects built to last.</p>\n<p>For now, the case stands as follows. The evidence of our fields is digital, and we must be able to interrogate it. The publics we serve are reachable, and RRCHNM proves scholarship can reach them. The teaching commons is open, and it compounds. The infrastructure can be ours, if we build and sustain it. And the machines are making claims about culture that only people with our training, extended by these methods, can properly examine. That is five fronts, one conclusion. We need the digital humanities, and we need them now.</p>\n<h2 id=\"in-this-series\" tabindex=\"-1\">In this series <a class=\"header-anchor\" href=\"#in-this-series\">#</a></h2>\n<ol>\n<li>Digital Humanities Part 1: What Are the Digital Humanities?</li>\n<li>Digital Humanities Part 2: Digital Humanities Tools for Dissertations</li>\n<li>Digital Humanities Part 3: Digital Humanities for Theology and Religious Studies</li>\n<li>Digital Humanities Part 4: Why We Need the Digital Humanities</li>\n<li>Digital Humanities Part 5: Preserving Digital Humanities Projects</li>\n<li>Digital Humanities Part 6: Preservation through Minimal Computing and GO::DH</li>\n</ol>\n<hr class=\"footnotes-sep\">\n<section class=\"footnotes\">\n<ol class=\"footnotes-list\">\n<li id=\"fn1\" class=\"footnote-item\"><p>Google, &quot;15 years of Google Books,&quot; The Keyword (Google blog), October 17, 2019, https://blog.google/products-and-platforms/products/search/15-years-google-books/ <a href=\"#fnref1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn2\" class=\"footnote-item\"><p>HathiTrust Digital Library, homepage, accessed July 2026, https://www.hathitrust.org/ <a href=\"#fnref2\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn3\" class=\"footnote-item\"><p>Digital Public Library of America, homepage, accessed July 2026, https://dp.la/ <a href=\"#fnref3\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn4\" class=\"footnote-item\"><p>Internet Archive, &quot;Wayback Machine to Hit 'Once-in-a-Generation Milestone' this October: One Trillion Web Pages Archived,&quot; Internet Archive Blogs, July 1, 2025, https://blog.archive.org/2025/07/01/wayback-machine-to-hit-once-in-a-generation-milestone-this-october-one-trillion-web-pages-archived/ <a href=\"#fnref4\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn5\" class=\"footnote-item\"><p>Roy Rosenzweig, &quot;Scarcity or Abundance? Preserving the Past in a Digital Era,&quot; American Historical Review 108, no. 3 (June 2003): 735-762, available at https://rrchnm.org/essays/scarcity-or-abundance-preserving-the-past-in-a-digital-era/ <a href=\"#fnref5\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref5:1\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref5:2\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn6\" class=\"footnote-item\"><p>Library of Congress, &quot;Update on the Twitter Archive at the Library of Congress,&quot; Library of Congress Blog, December 26, 2017, https://blogs.loc.gov/loc/2017/12/update-on-the-twitter-archive-at-the-library-of-congress-2/ <a href=\"#fnref6\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn7\" class=\"footnote-item\"><p>Roy Rosenzweig Center for History and New Media, &quot;Our Story,&quot; George Mason University, accessed July 2026, https://rrchnm.org/our-story/ <a href=\"#fnref7\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref7:1\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref7:2\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn8\" class=\"footnote-item\"><p>Zotero, homepage, Corporation for Digital Scholarship, accessed July 2026, https://www.zotero.org/ <a href=\"#fnref8\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn9\" class=\"footnote-item\"><p>Omeka, homepage, accessed July 2026, https://omeka.org/ <a href=\"#fnref9\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn10\" class=\"footnote-item\"><p>Library of Congress, &quot;Library Accepts September 11 Digital Archive, Holds Symposium,&quot; press release, August 14, 2003, https://www.loc.gov/item/prn-03-142/ <a href=\"#fnref10\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref10:1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn11\" class=\"footnote-item\"><p>Lincoln Mullen, &quot;Biography,&quot; lincolnmullen.com, accessed July 2026, https://lincolnmullen.com/bio/ <a href=\"#fnref11\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn12\" class=\"footnote-item\"><p>Lincoln A. Mullen, The Chance of Salvation: A History of Conversion in America (Cambridge: Harvard University Press, 2017). On the American Academy of Religion award, see https://lincolnmullen.com/bio/ <a href=\"#fnref12\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn13\" class=\"footnote-item\"><p>Lincoln A. Mullen, America's Public Bible: A Commentary (Stanford: Stanford University Press, 2023), https://americaspublicbible.org/ <a href=\"#fnref13\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref13:1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn14\" class=\"footnote-item\"><p>Lincoln Mullen, &quot;americas-public-bible&quot; (code, data, and website for America's Public Bible), GitHub, accessed July 2026, https://github.com/lmullen/americas-public-bible <a href=\"#fnref14\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn15\" class=\"footnote-item\"><p>Lincoln Mullen, GitHub profile and repositories, accessed July 2026, https://github.com/lmullen <a href=\"#fnref15\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn16\" class=\"footnote-item\"><p>Brian Croxall and Diane K. Jakacki, eds., What We Teach When We Teach DH: Digital Humanities in the Classroom (Minneapolis: University of Minnesota Press, 2023), https://www.upress.umn.edu/9781517915315/what-we-teach-when-we-teach-dh/ <a href=\"#fnref16\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn17\" class=\"footnote-item\"><p>Claire Battershill and Shawna Ross, Using Digital Humanities in the Classroom: A Practical Introduction for Teachers, Lecturers, and Students, 2nd ed. (London: Bloomsbury Academic, 2022). Johanna Drucker, The Digital Humanities Coursebook: An Introduction to Digital Methods for Research and Scholarship (London: Routledge, 2021). <a href=\"#fnref17\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn18\" class=\"footnote-item\"><p>Rebecca Frost Davis, Matthew K. Gold, Katherine D. Harris, and Jentery Sayers, eds., Digital Pedagogy in the Humanities: Concepts, Models, and Experiments (New York: Modern Language Association, 2020), https://digitalpedagogy.mla.hcommons.org/ See the project description at https://digitalpedagogy.mla.hcommons.org/description/ <a href=\"#fnref18\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref18:1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn19\" class=\"footnote-item\"><p>Knowledge Commons, &quot;Our History,&quot; Sustaining the Commons, accessed July 2026, https://sustaining.hcommons.org/about-this-site/our-history/ <a href=\"#fnref19\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn20\" class=\"footnote-item\"><p>Lauren Collister, &quot;Infra Finder Spotlight: Knowledge Commons,&quot; Invest in Open Infrastructure, August 28, 2024, https://investinopen.org/blog/infra-finder-spotlight-knowledge-commons/ <a href=\"#fnref20\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn21\" class=\"footnote-item\"><p>Michigan State University College of Arts &amp; Letters, &quot;Kathleen Fitzpatrick,&quot; faculty directory, accessed July 2026, https://directory.cal.msu.edu/kfitz <a href=\"#fnref21\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref21:1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn22\" class=\"footnote-item\"><p>DH@MSU, &quot;About,&quot; Michigan State University, accessed July 2026, https://digitalhumanities.msu.edu/about/ On the graduate certificate, see https://digitalhumanities.msu.edu/certificate/ <a href=\"#fnref22\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref22:1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn23\" class=\"footnote-item\"><p>Matrix: Center for Digital Humanities &amp; Social Sciences, &quot;Mission,&quot; Michigan State University, accessed July 2026, https://matrix.msu.edu/mission/ <a href=\"#fnref23\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn24\" class=\"footnote-item\"><p>LEADR (Lab for the Education and Advancement in Digital Research), &quot;About,&quot; Michigan State University, accessed July 2026, https://leadr.msu.edu/about/ <a href=\"#fnref24\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn25\" class=\"footnote-item\"><p>Daniel Allington, Sarah Brouillette, and David Golumbia, &quot;Neoliberal Tools (and Archives): A Political History of Digital Humanities,&quot; Los Angeles Review of Books, May 1, 2016, https://lareviewofbooks.org/article/neoliberal-tools-archives-political-history-digital-humanities/ <a href=\"#fnref25\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref25:1\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref25:2\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref25:3\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn26\" class=\"footnote-item\"><p>Domenico Fiormonte, Sukanta Chaudhuri, and Paola Ricaurte, eds., Global Debates in the Digital Humanities (Minneapolis: University of Minnesota Press, 2022), https://dhdebates.gc.cuny.edu/projects/global-debates-in-the-digital-humanities <a href=\"#fnref26\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn27\" class=\"footnote-item\"><p>Elizabeth Losh and Jacqueline Wernimont, eds., Bodies of Information: Intersectional Feminism and Digital Humanities (Minneapolis: University of Minnesota Press, 2018), https://dhdebates.gc.cuny.edu/projects/bodies-of-information <a href=\"#fnref27\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn28\" class=\"footnote-item\"><p>James E. Dobson, Critical Digital Humanities: The Search for a Methodology (Urbana: University of Illinois Press, 2019). <a href=\"#fnref28\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn29\" class=\"footnote-item\"><p>David M. Berry and Anders Fagerjord, Digital Humanities: Knowledge and Critique in a Digital Age (Cambridge: Polity, 2017). <a href=\"#fnref29\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn30\" class=\"footnote-item\"><p>dh+lib, &quot;Neoliberal Tools (and Archives): A Political History of Digital Humanities,&quot; response roundup, Association of College and Research Libraries, May 5, 2016, https://acrl.ala.org/dh/2016/05/05/neoliberal-tools-and-archives-a-political-history-of-digital-humanities/ <a href=\"#fnref30\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn31\" class=\"footnote-item\"><p>Andrew Piper, Juliana Spahr, and Richard Jean So, &quot;Beyond Resistance: Towards a Future History of Digital Humanities,&quot; Los Angeles Review of Books, May 11, 2016, https://lareviewofbooks.org/article/beyond-resistance-towards-future-history-digital-humanities/ <a href=\"#fnref31\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn32\" class=\"footnote-item\"><p>Matthew Kirschenbaum, &quot;Am I a Digital Humanist? Confessions of a Neoliberal Tool,&quot; Medium, 2016, https://medium.com/@mkirschenbaum/am-i-a-digital-humanist-confessions-of-a-neoliberal-tool-1bc64caaa984 <a href=\"#fnref32\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn33\" class=\"footnote-item\"><p>Emily M. Bender, Timnit Gebru, Angelina McMillan-Major, and Shmargaret Shmitchell, &quot;On the Dangers of Stochastic Parrots: Can Language Models Be Too Big?,&quot; in Proceedings of the 2021 ACM Conference on Fairness, Accountability, and Transparency (FAccT '21), March 2021, https://dl.acm.org/doi/10.1145/3442188.3445922 <a href=\"#fnref33\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn34\" class=\"footnote-item\"><p>Kate Crawford, Atlas of AI: Power, Politics, and the Planetary Costs of Artificial Intelligence (New Haven: Yale University Press, 2021), https://yalebooks.yale.edu/book/9780300264630/atlas-of-ai/ <a href=\"#fnref34\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn35\" class=\"footnote-item\"><p>Catherine D'Ignazio and Lauren F. Klein, Data Feminism (Cambridge: MIT Press, 2020), open access edition at https://data-feminism.mitpress.mit.edu/ <a href=\"#fnref35\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn36\" class=\"footnote-item\"><p>Ted Underwood, &quot;Using GPT-4 to Measure the Passage of Time in Fiction,&quot; The Stone and the Shell, March 19, 2023, https://tedunderwood.com/2023/03/19/using-gpt-4-to-measure-the-passage-of-time-in-fiction/ <a href=\"#fnref36\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n</ol>\n</section>\n",
			"date_published": "2026-07-15T04:05:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/dh-part-3-digital-humanities-for-theology-and-religious-studies/",
			"url": "https://www.adamdjbrett.com/blog/dh-part-3-digital-humanities-for-theology-and-religious-studies/",
			"title": "Digital Humanities Part 3: Digital Humanities for Theology and Religious Studies",
			"content_html": "<p>If you work in theology or religious studies, you already know the problem, even if you have never named it. Your evidence refuses to sit still. A church historian needs sermon manuscripts and denominational yearbooks. A scholar of Tibetan Buddhism needs woodblock prints scattered across three continents. A student of American religion needs to hear a congregation, not just read about one. The sources of religious life come in more forms than almost any other field has to handle, and most of our training prepares us for exactly one of them: the printed text.</p>\n<p>This essay makes the case that the digital humanities matter for theology and religious studies specifically, not as a borrowed toolkit from English departments but as a set of practices that fit the peculiar shape of our evidence. It is the third essay in a six-part series. The first asked what the digital humanities are. The second surveyed tools you can use in a dissertation. This one turns to our own fields and asks what is already built, what it makes possible, what it costs, and how to teach with it.</p>\n<h2 id=\"the-multi-form-evidence-problem\" tabindex=\"-1\">The Multi-Form Evidence Problem <a class=\"header-anchor\" href=\"#the-multi-form-evidence-problem\">#</a></h2>\n<p>Start with an inventory. What counts as evidence in the study of religion? Scriptures, obviously, and the commentaries that accumulate around them like coral. Manuscripts, with their marginalia, corrections, and erasures. But also ritual objects, from prayer beads to processional crosses. Sacred spaces and the pilgrimage routes that connect them. Images, icons, and the visual cultures of devotion. Music and the broader soundscape of worship, which includes creaking pews and kitchen noise as much as choirs. Oral histories from practitioners. Born-digital communities that exist only on Discord servers and WhatsApp threads. Online sermons. Prayer request forms. The institutional archives of denominations, mission boards, and seminaries.</p>\n<p>The inventory also keeps growing at the digital end. Religious life now happens in livestreamed liturgies, prayer apps, meditation platforms, and influencer pulpits, and those materials are evidence too, as surely as a medieval sermon collection. They are also far more fragile than they look. A denominational website redesign can erase twenty years of institutional history in an afternoon. A platform shutdown can take a decade of a community's conversation with it. Scholars who study contemporary religion are already, whether they chose it or not, working in a field where the sources decay faster than parchment ever did.</p>\n<p>No single scholar masters all of this, and no single method handles it. Yet the print-era organization of our fields quietly privileged one form above the others. If it could be edited, translated, and shelved, it was scholarship's proper object. Everything else became context, background, or the province of some adjacent discipline. Ethnomusicologists got the music. Art historians got the icons. Geographers got the pilgrimage routes. The study of religion kept the texts.</p>\n<p>The digital humanities do not dissolve that division of labor, but they loosen it. A database can hold a scanned manuscript, an audio recording, a georeferenced map, and a transcribed census schedule in the same collection, described with the same metadata standards, discoverable through the same search. That technical fact has an intellectual consequence. When a sound recording and a printed sermon can sit side by side as evidence, you can ask questions that neither supports alone. What did this revival sound like, and how did the newspapers describe it? Where were these congregations, and what did they file with the census bureau? The multi-form evidence problem does not go away. It becomes workable.</p>\n<p>One caution before going further. The field's best introductory literature insists that religious-studies DH is methodologically plural, and that plurality is worth defending. The De Gruyter series Introductions to Digital Humanities – Religion, the most sustained effort to map this terrain, treats databases, pedagogy, new media, and digital culture as distinct areas of practice rather than one technique with many names.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1\">[1]</a></sup> Nothing in this essay should be read as saying there is a digital method for religion. There are many, and they disagree with each other in productive ways.</p>\n<h2 id=\"what-digital-methods-actually-offer\" tabindex=\"-1\">What Digital Methods Actually Offer <a class=\"header-anchor\" href=\"#what-digital-methods-actually-offer\">#</a></h2>\n<p>Strip away the conference language and the digital humanities offer religious studies about eight concrete things. They preserve fragile materials before fire, war, or mold takes them. They make dispersed sources discoverable, so that a manuscript in a monastery library and its sister copy in Berlin can be found in one search. They allow comparison across corpora too large for any human reading life. They map sacred space and movement through it. They model networks of teachers, students, correspondents, and converts. They support annotation of manuscripts at a depth print editions cannot match. They build public archives that communities can see themselves in. And they teach, because a student who builds a small digital archive learns things about evidence that no seminar discussion can deliver.</p>\n<p>Take one example of how the pieces combine. Suppose you study a nineteenth-century missionary society. Its letters are in one archive, its photographs in another, its converts' descendants in living congregations on another continent. A digital project can unite the letters and photographs in one collection, map the mission stations, model the correspondence network, and, if built with the descendants rather than merely about them, give the communities a say in how their ancestors appear. Every one of those steps uses infrastructure that already exists.</p>\n<p>Each of these is already happening in the study of religion, at scale, funded, and peer reviewed. That is the part many theologians and religion scholars have not heard. The sections that follow tour that infrastructure, because the case for digital methods in our fields is strongest when it is concrete. You do not have to imagine what a digital library of Jewish texts would look like. You can open one right now.</p>\n<h2 id=\"libraries-of-sacred-texts-rebuilt-for-computation\" tabindex=\"-1\">Libraries of Sacred Texts, Rebuilt for Computation <a class=\"header-anchor\" href=\"#libraries-of-sacred-texts-rebuilt-for-computation\">#</a></h2>\n<p>Sefaria is the example to show a skeptical colleague first. It describes itself as &quot;a free living library of Jewish texts and their interconnections,&quot; and the phrase is precise.<sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2\">[2]</a></sup> The Tanakh, Talmud, midrash, halakhic codes, and centuries of commentary are not just scanned but structured, so that every verse knows which commentaries discuss it and every Talmudic passage links to the biblical text it cites. Founded in the early 2010s by Joshua Foer and Brett Lockspeiser, Sefaria now underpins classroom source sheets, daily study apps, and a growing body of computational research, because the whole library is available through an open API.<sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3\">[3]</a></sup> That last detail matters more than it sounds. An API means the texts are not trapped behind a reading interface. A graduate student who wants to trace how a phrase moves from Torah through Rashi into a nineteenth-century responsum can write a script and ask.</p>\n<p>Islamic studies has the Open Islamicate Texts Initiative, or OpenITI, led by Matthew Thomas Miller, Maxim Romanov, and Sarah Bowen Savant. OpenITI builds machine-actionable corpora of premodern texts in Arabic and Persian, which is slower and harder work than it sounds because Arabic-script optical character recognition lagged behind Latin-script OCR for decades.<sup class=\"footnote-ref\"><a href=\"#fn4\" id=\"fnref4\">[4]</a></sup> The initiative's Arabic-script OCR Catalyst Project, run with the Maryland Institute for Technology in the Humanities, has pushed the recognition technology itself forward, which is a reminder that religious-studies scholars sometimes have to build the road before they can drive on it.<sup class=\"footnote-ref\"><a href=\"#fn5\" id=\"fnref5\">[5]</a></sup></p>\n<p>Buddhist studies may have the most ambitious of these libraries. The Buddhist Digital Resource Center began in 1999, when E. Gene Smith founded what was then the Tibetan Buddhist Resource Center to preserve texts scattered by the Tibetan diaspora. It has since digitized more than twenty-seven million pages of Buddhist literature, and its BUDA platform publishes the catalog as linked open data, so that a text, its author, its printing house, and its lineage of transmission are all machine-readable entities that other projects can build on.<sup class=\"footnote-ref\"><a href=\"#fn6\" id=\"fnref6\">[6]</a></sup></p>\n<p>Smaller fields benefit even more, because digital infrastructure substitutes for the reference works that small fields never had the labor to produce in print. Syriaca.org, the Syriac Reference Portal, publishes linked-data reference works for Syriac studies, including a gazetteer of places and Qadishe, a prosopography of Syriac saints.<sup class=\"footnote-ref\"><a href=\"#fn7\" id=\"fnref7\">[7]</a></sup> For a field whose sources are dispersed across Middle Eastern, European, and American collections, a shared set of stable identifiers for people, places, and works is what lets the field accumulate knowledge at all rather than restart with every scholar.</p>\n<h2 id=\"manuscripts-recovered-and-preserved\" tabindex=\"-1\">Manuscripts, Recovered and Preserved <a class=\"header-anchor\" href=\"#manuscripts-recovered-and-preserved\">#</a></h2>\n<p>Digitization is sometimes dismissed as mere photography. Two projects show how wrong that is.</p>\n<p>At St. Catherine's Monastery in the Sinai, the oldest continually operating Christian monastery in the world, the Sinai Palimpsests Project used multispectral imaging to recover texts that had been scraped away and written over centuries ago. Working with the Early Manuscripts Electronic Library and UCLA, the project imaged seventy-four palimpsest manuscripts and recovered erased undertexts in ten languages, several thousand pages of writing that no eye had been able to read for a millennium.<sup class=\"footnote-ref\"><a href=\"#fn8\" id=\"fnref8\">[8]</a></sup> These are not marginal materials. Palimpsest undertexts from Sinai include some of the earliest witnesses to Christian scripture and liturgy in languages like Syriac, Christian Palestinian Aramaic, and Georgian. No amount of conventional scholarship could have produced this evidence. The imaging did.</p>\n<p>The Hill Museum &amp; Manuscript Library at Saint John's University in Minnesota has been doing the slower, steadier version of this work since 1965, first with microfilm in Austrian monastic libraries and now with digital photography across the Middle East, Africa, and beyond. HMML states its mission plainly, &quot;Preserving and sharing the world's handwritten past to inspire a deeper understanding of our present and future,&quot; and it has photographed manuscripts in partnership with more than 1,500 libraries and collections, prioritizing communities whose heritage is endangered by conflict.<sup class=\"footnote-ref\"><a href=\"#fn9\" id=\"fnref9\">[9]</a></sup> Its online Reading Room lets you search those manuscripts by language, script, genre, and repository from your desk.<sup class=\"footnote-ref\"><a href=\"#fn10\" id=\"fnref10\">[10]</a></sup> Manuscripts HMML photographed in Iraq and Syria before the wars of the last two decades are, in some cases, the only surviving copies. Preservation here is not a preliminary to scholarship but sometimes the only reason any scholarship remains possible.</p>\n<h2 id=\"listening-to-religion\" tabindex=\"-1\">Listening to Religion <a class=\"header-anchor\" href=\"#listening-to-religion\">#</a></h2>\n<p>Religion is heard as much as read. The projects below treat sound as evidence, not atmosphere.</p>\n<p>The American Religious Sounds Project, directed by Isaac Weiner at Ohio State and Amy DeRogatis at Michigan State, built a sonic archive of American religious life between 2014 and 2022. Its recordings include the formal sounds you would expect, chanting and choirs and calls to prayer, but also the incidental ones, pots clattering during a langar meal, the murmur before a service starts.<sup class=\"footnote-ref\"><a href=\"#fn11\" id=\"fnref11\">[11]</a></sup> The project's premise is that attending to sound changes what you know about religious diversity. A city's religious life sounds different than it reads, and communities invisible in print can be loud in the archive of the ear.</p>\n<p>The Gospel Music History Archive at the University of Southern California's Center for Religion and Civic Culture grew out of a loss. When fire destroyed Chicago's Pilgrim Baptist Church in 2006, it took with it original sheet music and papers of Thomas A. Dorsey, the father of gospel music. The archive digitizes interviews, photographs, recordings, and documents of the gospel tradition and makes them searchable for scholars, artists, and church historians alike.<sup class=\"footnote-ref\"><a href=\"#fn12\" id=\"fnref12\">[12]</a></sup> Waiting to digitize is itself a decision, and the fire showed what it can cost.</p>\n<h2 id=\"the-verse-and-the-variant-digital-text-criticism\" tabindex=\"-1\">The Verse and the Variant: Digital Text Criticism <a class=\"header-anchor\" href=\"#the-verse-and-the-variant-digital-text-criticism\">#</a></h2>\n<p>Biblical scholars have a special claim on this story, because New Testament textual criticism went digital before most of the humanities knew the word. The problem was always computational in shape. The New Testament survives in thousands of Greek manuscripts, no two identical, and the discipline's founding question, what did the earliest recoverable text say, requires comparing readings across that whole tradition. For two centuries editors managed the comparison with card files, apparatus sigla, and heroic memory.</p>\n<p>The Institute for New Testament Textual Research in Münster, which produces the critical editions behind nearly every modern Bible translation, now runs that comparison as data.<sup class=\"footnote-ref\"><a href=\"#fn13\" id=\"fnref13\">[13]</a></sup> Its New Testament Virtual Manuscript Room puts images and transcriptions of Greek New Testament manuscripts online, where anyone can examine the witnesses that editors once traveled continents to see.<sup class=\"footnote-ref\"><a href=\"#fn14\" id=\"fnref14\">[14]</a></sup> More consequentially, the institute's Editio Critica Maior is built with the Coherence-Based Genealogical Method, an approach that uses computer-assisted analysis of agreement patterns among witnesses to model how readings flow through the manuscript tradition. You can hold whatever view you like about the method, and text critics hold several, but the debate itself is now a debate about a digital instrument, conducted in the field's most traditional venues. When the Nestle-Aland text your students carry into exegesis class changes a reading, a computational method helped change it.</p>\n<p>The point generalizes past the New Testament. Digital critical editions let an editor encode every witness rather than flattening them into a single reconstructed text with an apparatus at the foot of the page. For traditions that never had critical editions at all, the digital edition is often the first edition. And for theologians the stakes are not merely philological. Doctrines of scripture, arguments about canon, and homiletical habits all rest, at some layer, on claims about what the text is. A generation of tools has quietly changed how those claims get made. Seminary curricula have mostly not caught up, and a course that walks students through the Virtual Manuscript Room would teach them more about the human history of their scriptures than another semester of secondary literature.</p>\n<h2 id=\"maps-networks-and-the-shape-of-religious-worlds\" tabindex=\"-1\">Maps, Networks, and the Shape of Religious Worlds <a class=\"header-anchor\" href=\"#maps-networks-and-the-shape-of-religious-worlds\">#</a></h2>\n<p>Religion happens somewhere, and it moves. Two families of digital method take that seriously in ways print scholarship never quite could.</p>\n<p>Mapping comes first. The gazetteer, a structured index of places with stable identifiers, is the unglamorous foundation. Pleiades, the open gazetteer of the ancient world, gives every attested ancient place a permanent address that projects can link against, which is why a Syriac monastery in one database and the same monastery in another can be recognized as one place.<sup class=\"footnote-ref\"><a href=\"#fn15\" id=\"fnref15\">[15]</a></sup> Syriaca.org built its own gazetteer on the same logic for the Syriac world. On top of such foundations, you can ask spatial questions with real bite. Stanford's ORBIS models travel time and cost across the Roman world, so instead of gesturing at how far Paul traveled, a student can estimate what a winter journey from Antioch to Rome demanded in weeks and denarii.<sup class=\"footnote-ref\"><a href=\"#fn16\" id=\"fnref16\">[16]</a></sup> The American Religious Ecologies maps do something similar for a later world, turning census schedules into a map where you can watch a denomination hug a river valley or an immigrant church trace a railroad line. Sacred space, pilgrimage, mission, migration, and parish geography are all, in part, map problems, and they were waiting for maps that could hold data.</p>\n<p>Networks come second. Religious traditions are transmission systems. Teachers certify students, bishops consecrate bishops, Sufi orders trace silsilas, rabbinic authority moves through ordination, and conversion travels along kinship and friendship. Network analysis treats those relationships as data, and it can make visible what narrative history keeps anecdotal, which figures actually bridge communities, where a lineage bottlenecks through a single teacher, how a heresy spreads through correspondence faster than a council can condemn it. The Buddhist Digital Resource Center's linked-data catalog is, among other things, a network of persons, texts, and lineages that scholars can query. Prosopographies like Syriaca's Qadishe do the same for saints. None of this replaces the archive work of establishing who knew whom. It gives that work somewhere cumulative to live, and it lets the next scholar stand on it rather than redo it.</p>\n<h2 id=\"what-counting-can-teach-lincoln-mullen-and-americas-public-bible\" tabindex=\"-1\">What Counting Can Teach: Lincoln Mullen and America's Public Bible <a class=\"header-anchor\" href=\"#what-counting-can-teach-lincoln-mullen-and-americas-public-bible\">#</a></h2>\n<p>If one scholar's work can stand for what quantitative methods offer the history of religion, it is Lincoln Mullen's. Mullen is a historian of American religion at George Mason University and director of the Roy Rosenzweig Center for History and New Media, and he has spent a career demonstrating that counting, done carefully, is a form of close reading's ally rather than its rival.<sup class=\"footnote-ref\"><a href=\"#fn17\" id=\"fnref17\">[17]</a></sup></p>\n<p>His America's Public Bible is the clearest demonstration. Published by Stanford University Press as an interactive scholarly work, it detects biblical quotations across millions of pages of digitized American newspapers in the Library of Congress's Chronicling America collection and Gale's Nineteenth Century U.S. Newspapers.<sup class=\"footnote-ref\"><a href=\"#fn18\" id=\"fnref18\">[18]</a></sup> The scale is worth pausing on. The project identified roughly 1.8 million biblical quotations and traced quotation trends for nearly three thousand individual verses across a century of print.<sup class=\"footnote-ref\"><a href=\"#fn19\" id=\"fnref19\">[19]</a></sup> No scholar could read fifteen million newspaper pages. A model can, and what it found reshapes how you think about the Bible in American public life. Verses surged and faded with wars, elections, and panics. Editors quoted scripture for jokes and advertisements as readily as for sermons. The Bible in the newspaper was contested common property, quoted constantly and interpreted in mutually exclusive ways, its meaning far more often assumed than explained. The project won first prize in the National Endowment for the Humanities' Chronicling America Data Challenge in 2016, before growing into the Stanford publication.<sup class=\"footnote-ref\"><a href=\"#fn20\" id=\"fnref20\">[20]</a></sup></p>\n<p>The method did something specific there. It did not replace interpretation. It generated a new object for interpretation, a record of quotation practices that had always existed but had never been visible. That is the honest promise of computational methods for theology and religious studies. They will not tell you what a verse means. They can tell you, for the first time, who quoted it, when, where, and alongside what, and then the interpretive work begins. Mullen's earlier book, The Chance of Salvation, a history of conversion in America, shows the same sensibility applied with traditional methods, which is the point.<sup class=\"footnote-ref\"><a href=\"#fn21\" id=\"fnref21\">[21]</a></sup> The computation serves questions a historian of religion already cared about.</p>\n<h2 id=\"rebuilding-a-census-american-religious-ecologies-and-rrchnm\" tabindex=\"-1\">Rebuilding a Census: American Religious Ecologies and RRCHNM <a class=\"header-anchor\" href=\"#rebuilding-a-census-american-religious-ecologies-and-rrchnm\">#</a></h2>\n<p>Mullen also co-directs, with John Turner, a project that shows what patient infrastructure-building looks like in our fields. In 1926 the U.S. Census Bureau conducted a Census of Religious Bodies, collecting a schedule from individual congregations across the country, hundreds of thousands of them, recording membership, buildings, finances, and languages of worship. The tabulated summaries were published. The schedules themselves, the congregation-level records, sat on microfilm, effectively unreadable at scale. The American Religious Ecologies project at the Roy Rosenzweig Center for History and New Media is digitizing and transcribing them, calling the schedules &quot;the single richest historical source of data about American congregations.&quot;<sup class=\"footnote-ref\"><a href=\"#fn22\" id=\"fnref22\">[22]</a></sup></p>\n<p>By late 2020 the team had digitized more than forty thousand schedules and released them publicly, in the public domain, with datasets and an API.<sup class=\"footnote-ref\"><a href=\"#fn23\" id=\"fnref23\">[23]</a></sup> A second National Endowment for the Humanities grant, awarded in 2023, funds the work of digitizing and transcribing the rest.<sup class=\"footnote-ref\"><a href=\"#fn24\" id=\"fnref24\">[24]</a></sup> Instead of denominational totals by state, you get a congregation-by-congregation map of American religion in 1926, the Black Baptist church and the Yiddish-speaking synagogue and the Norwegian Lutheran parish each visible as a point with its own record. Local historians can find their own congregations. Scholars can ask ecological questions, in the project's language, about how religious bodies inhabited neighborhoods, counties, and regions.</p>\n<p>The institution behind this deserves attention as much as the project. The Roy Rosenzweig Center for History and New Media, founded in 1994 by the historian Roy Rosenzweig and renamed in his honor after his death, has spent three decades pursuing a stated mission &quot;to democratize history.&quot;<sup class=\"footnote-ref\"><a href=\"#fn25\" id=\"fnref25\">[25]</a></sup> It built tools you may already use without knowing their origin, including Zotero, the reference manager, and Omeka, the collections-publishing platform that runs thousands of digital archives.<sup class=\"footnote-ref\"><a href=\"#fn26\" id=\"fnref26\">[26]</a></sup> It publishes Current Research in Digital History, an open-access, peer-reviewed journal that insists digital projects should make discipline-specific arguments rather than just showcase technology.<sup class=\"footnote-ref\"><a href=\"#fn27\" id=\"fnref27\">[27]</a></sup> And it runs multiple religion projects at once, from the 1926 census work to Pandemic Religion, an Omeka-based collection documenting American religious life during COVID-19.<sup class=\"footnote-ref\"><a href=\"#fn28\" id=\"fnref28\">[28]</a></sup> For theological schools and religious-studies departments wondering what institutional commitment to digital scholarship looks like, RRCHNM is the working model: shared staff, shared tools, grant funding, student labor treated as training, and projects that outlive any single grant cycle.</p>\n<h2 id=\"between-close-and-distant-reading\" tabindex=\"-1\">Between Close and Distant Reading <a class=\"header-anchor\" href=\"#between-close-and-distant-reading\">#</a></h2>\n<p>A worry runs under every conversation about these methods, and it deserves a direct answer before we go further. The worry is that counting is the opposite of reading, that a field built on the patient interpretation of difficult texts betrays itself when it starts treating scripture as data.</p>\n<p>The strongest digital scholarship in religion answers the worry by refusing the choice. It is built on movement between scales. Mullen's project counts 1.8 million quotations so that it can then read single newspaper columns with new eyes, because now you know this joke about Jonah appeared during an election season when that verse was surging nationally. The census maps show you a pattern, a denomination thick in one county and absent in the next, and the pattern sends you back to the archive asking why, where only close reading of local sources will answer. Distant reading without close reading produces trivia. Close reading without any sense of scale produces confident generalizations from three examples, which our fields have published for decades without embarrassment.</p>\n<p>Theology, of all disciplines, should recognize this rhythm. Exegesis has always moved between the verse and the canon, the word study and the biblical theology. Systematicians move between a doctrine's precise formulation and its place in the whole dogmatic structure. The movement between scales is not foreign to us. What is new is only that one of the scales now runs on software, and that the software's assumptions, like a lexicon's or a concordance's before it, have to be learned and criticized rather than trusted. The tradition of suspicion we bring to every other instrument of interpretation applies here too, and that is an argument for our involvement, not our abstention.</p>\n<h2 id=\"the-ethics-of-digitizing-the-sacred\" tabindex=\"-1\">The Ethics of Digitizing the Sacred <a class=\"header-anchor\" href=\"#the-ethics-of-digitizing-the-sacred\">#</a></h2>\n<p>Everything so far has been the good news. Here is the harder part, and for theologians it may be the most important section of this essay.</p>\n<p>Digitization is not neutral. When a sacred object becomes a digital image, something changes. The image can travel where the object never would, appear in contexts its community never sanctioned, and be seen by people who, within the tradition, have no standing to see it. Some Indigenous communities restrict certain materials by season, by gender, by initiation status, or by family. A database with a public search box overrides all of that by default.</p>\n<p>The scholar who has thought hardest about this is Kimberly Christen, whose work asks directly whether the open-access ideal fits every kind of knowledge. In a widely cited article she argues that the binary logic of open and closed &quot;cannot handle the mire of fine-grained and overlapping types of relationships&quot; that actually govern access to Indigenous knowledge.<sup class=\"footnote-ref\"><a href=\"#fn29\" id=\"fnref29\">[29]</a></sup> Her answer was not to abandon digital archives but to redesign them. Mukurtu, the content management system she helped build, lets communities set cultural protocols that control who sees what, and the Traditional Knowledge Labels developed with Local Contexts let source communities attach their own conditions of access and use to digitized materials, even materials legally in the public domain.<sup class=\"footnote-ref\"><a href=\"#fn30\" id=\"fnref30\">[30]</a></sup> For scholars of religion, this is not someone else's problem. Ritual objects, ceremonial recordings, and esoteric texts raise exactly these questions, whatever the tradition.</p>\n<p>Colonial archives raise a second set. Much of what religious-studies scholars digitize was collected under conditions of grossly unequal power, by missionaries, colonial administrators, and anthropologists whose subjects did not consent to being documented. The art historian Temi Odumosu, writing about digitized images of enslaved people in Danish colonial archives, poses the question that every digitization project involving such materials must answer: what does it mean to provide open digital access to materials representing violated subjects who never agreed to be recorded in the first place?<sup class=\"footnote-ref\"><a href=\"#fn31\" id=\"fnref31\">[31]</a></sup> Making a colonial archive searchable multiplies its reach, for researchers and descendants, but also multiplies the exposure of the people caught inside it. Gerben Zaagsma has argued that digitization choices are themselves political, shaping which pasts become visible and on whose terms.<sup class=\"footnote-ref\"><a href=\"#fn32\" id=\"fnref32\">[32]</a></sup> And the Santa Barbara Statement on Collections as Data, a widely endorsed set of principles for treating cultural collections computationally, insists that collections as data should be developed with care for the people they represent, not just efficiency for the researchers who query them.<sup class=\"footnote-ref\"><a href=\"#fn33\" id=\"fnref33\">[33]</a></sup></p>\n<p>Then there is born-digital religion, where the ethical questions arrive before the archive does. Online prayer requests, congregational Facebook groups, grief posts, and confession threads are all technically collectable. A prayer request is data to a scraper and a cry of the heart to the person who typed it. If you harvest ten thousand of them for a corpus study, what have you done, and who did you ask? Theologians are, if anything, better equipped than most humanists to take these questions seriously, because our fields have never pretended that texts and objects are inert. A discipline that understands what it means for something to be consecrated should understand what it means for something to be exposed.</p>\n<p>None of this is an argument against digitization. It is an argument that access is a relationship, not a switch, and that religious-studies scholars should be helping to design the relationship rather than inheriting defaults from commercial platforms.</p>\n<h2 id=\"working-with-communities-not-just-about-them\" tabindex=\"-1\">Working with Communities, Not Just About Them <a class=\"header-anchor\" href=\"#working-with-communities-not-just-about-them\">#</a></h2>\n<p>The ethics questions have a constructive corollary. Digital projects change the relationship between scholars and the communities they study, and the best projects treat that change as an opportunity rather than a risk to be managed.</p>\n<p>A print monograph about a congregation is written for other scholars, and the congregation may never see it. A digital archive of the same congregation is visible to its members the day it goes online, and they will have opinions. They will correct your dates, identify the people in your photographs, and tell you which items should never have been public. That friction is the method working as intended. The American Religious Sounds Project recorded in partnership with the communities it documented. Pandemic Religion invited people to contribute their own materials, so the archive of American religious life under COVID-19 is partly self-authored by the people who lived it. Mukurtu goes furthest, handing communities the keys to their own collections. Each of these projects treats the community as a source of authority about its own religious life, not merely a source of data.</p>\n<p>For theologians this should feel familiar rather than radical, because many of us are answerable to communities already. Seminary faculty serve churches. Scholars trained in traditions they study answer to teachers and elders as well as tenure committees. The digital humanities did not invent accountability to living communities. What they did was make it structural, built into permissions systems and contribution forms and takedown policies, instead of leaving it to the individual scholar's conscience. That is worth having, and religious-studies scholars, who navigate these relationships as a matter of professional survival, have expertise the wider digital humanities needs. This is one of the places where our fields should be exporting wisdom, not importing it.</p>\n<h2 id=\"where-the-work-gets-shared-knowledge-commons\" tabindex=\"-1\">Where the Work Gets Shared: Knowledge Commons <a class=\"header-anchor\" href=\"#where-the-work-gets-shared-knowledge-commons\">#</a></h2>\n<p>Digital scholarship needs somewhere to live that is not a publisher's paywall or a personal hard drive. For scholars of religion, the most important address is Knowledge Commons, the open scholarly network at hcommons.org. Launched as Humanities Commons and hosted at Michigan State University, it connects a community of scholars now numbering in the tens of thousands, with Kathleen Fitzpatrick, who has long directed the effort, among the most thoughtful voices in academia on why scholarly infrastructure should be community-owned.<sup class=\"footnote-ref\"><a href=\"#fn34\" id=\"fnref34\">[34]</a></sup></p>\n<p>Two features matter most in practice. First, the network hosts groups and sites, so a research seminar or a scholarly society section can share syllabi, working papers, and discussion in the open. Religion scholars are already there, including groups connected to American Academy of Religion research programs.<sup class=\"footnote-ref\"><a href=\"#fn35\" id=\"fnref35\">[35]</a></sup> Second, and more consequential for your CV, its repository, CORE, now branded KCWorks, gives every deposit a persistent DOI.<sup class=\"footnote-ref\"><a href=\"#fn36\" id=\"fnref36\">[36]</a></sup> That means the conference paper you would otherwise let die in a drawer, the syllabus you spent a summer on, the dataset behind your article, each can become a citable object with a stable address, open to anyone, counted by citation trackers. For fields like theology, where so much intellectual labor circulates informally through guild meetings and never enters the published record, an open repository with DOIs is a real shift in what counts.</p>\n<p>Knowledge Commons also signals something about where this work finds institutional homes. Michigan State's digital humanities program, which offers an undergraduate minor and a graduate certificate and anchors an active DH@MSU community across departments, is the kind of program where a religious-studies student can now get formal methods training without leaving the humanities.<sup class=\"footnote-ref\"><a href=\"#fn37\" id=\"fnref37\">[37]</a></sup> If you advise students who want these skills, programs like MSU's are where to send them looking.</p>\n<h2 id=\"teaching-theology-and-religion-digitally\" tabindex=\"-1\">Teaching Theology and Religion Digitally <a class=\"header-anchor\" href=\"#teaching-theology-and-religion-digitally\">#</a></h2>\n<p>The pedagogical case for digital humanities in theological education is easy to state. Students learn about evidence by handling it, and digital projects force the handling.</p>\n<p>Ask a seminar to write a paper about a local congregation's history and you will get prose about sources. Ask them to build a small public archive of it, and suddenly every decision teaches. What do we photograph? What do we call this object, and in whose vocabulary? Who might be harmed if this photo is public? What metadata does a scholar in fifty years need us to record now? Those are the questions of archival theory, description, and research ethics, and students meet them not as readings but as decisions with consequences. Instructors across the humanities use Omeka, the RRCHNM-built platform, for exactly this kind of student-built collection work, and it fits religious-studies courses naturally because congregations, cemeteries, shrines, and family devotional objects are all nearby and under-documented.</p>\n<p>For narrative and spatial assignments, the free tools from Northwestern University's Knight Lab have become a standard classroom kit, and they deserve their reputation.<sup class=\"footnote-ref\"><a href=\"#fn38\" id=\"fnref38\">[38]</a></sup> TimelineJS builds interactive timelines from a spreadsheet, which makes it a one-class-session tool for visualizing, say, the sequence of the Reformation pamphlet wars or a century of a diocese's bishops. StoryMapJS ties narrative to place, and religious studies is full of journeys that students understand differently once they trace them: Paul's travels, the hajj routes, the Great Migration's remaking of American Black church life. JuxtaposeJS compares two images with a slider, perfect for a church before and after iconoclasm or a neighborhood before and after a mosque was built. SoundciteJS embeds inline audio, so an essay about chant can let the reader hear the chant mid-sentence. Knight Lab reports that TimelineJS alone has been used by more than 250,000 people.<sup class=\"footnote-ref\"><a href=\"#fn39\" id=\"fnref39\">[39]</a></sup> These tools cost nothing, require no code, and produce work students can put in a portfolio.</p>\n<p>Assignment design is where the pedagogy succeeds or fails, and the principles are teachable. Keep the corpus small enough that students can know it whole, a single congregation's newsletters, one missionary's letter book, the gravestones of one cemetery section. Make the technical layer thin at first, a spreadsheet feeding a timeline, so the intellectual work stays in front. Build the ethics conversation into the assignment rather than appending it, by requiring students to justify in writing what they chose not to publish. And end with an audience beyond the instructor, because students who know a congregation's members will see the site behave differently with evidence than students writing for a grade. None of this requires the instructor to be a technologist. It requires the same judgment about scope and sources that any good seminar paper assignment already demands.</p>\n<p>There is also now a scholarly literature on this teaching, so you do not have to improvise alone. The Wabash Center for Teaching and Learning in Theology and Religion, the field's dedicated teaching institute, publishes the open-access Wabash Center Journal on Teaching, where instructors document what digital assignments actually do in religion classrooms.<sup class=\"footnote-ref\"><a href=\"#fn40\" id=\"fnref40\">[40]</a></sup> A representative example is Randall Reed and Alaina Doyle's account of teaching religious-studies majors to work with data, arguing that data-analysis assignments serve both humanistic inquiry and students' employability.<sup class=\"footnote-ref\"><a href=\"#fn41\" id=\"fnref41\">[41]</a></sup> That dual argument matters in theological education, where enrollment pressures are real and students reasonably ask what skills a religion degree carries into the world. A graduate who can build an archive, clean a dataset, and tell a story with a map has an answer.</p>\n<h2 id=\"the-limits-are-interpretive-too\" tabindex=\"-1\">The Limits Are Interpretive Too <a class=\"header-anchor\" href=\"#the-limits-are-interpretive-too\">#</a></h2>\n<p>An honest advocate has to say what these methods cannot do, and the limits are not mainly technical. They are interpretive, which means they belong inside our scholarship rather than in a methods appendix.</p>\n<p>Every corpus has boundaries, and the boundaries are arguments. A study of the Bible in American newspapers is really a study of the Bible in the newspapers that got digitized, which skews toward certain regions, languages, and publishers. Sefaria's library, for all its richness, encodes decisions about which textual traditions and editions represent Judaism. OpenITI's corpus grows fastest where OCR works best. Optical character recognition itself has error rates that vary by script, typeface, and print quality, so the archive is always cleanest for the best-printed, which usually means the best-funded, corners of a tradition. Metadata categories carry assumptions too. A census schedule that asks for a congregation's denomination imposes a Protestant organizational logic on communities it fits badly. A catalog field for author sits awkwardly on texts a tradition regards as revealed.</p>\n<p>None of this is a reason to abstain. It is a reason to treat preservation, encoding, and metadata as knowledge-making practices rather than clerical preliminaries, which is precisely how the strongest projects already treat them. The scholars behind the infrastructures in this essay write about their categories and their error rates in public, and reading those methods essays is now part of reading the scholarship. Your training in hermeneutics is precisely what this work demands. A field that has spent two centuries asking how a canon gets formed is well prepared to ask how a corpus does.</p>\n<h2 id=\"where-to-start\" tabindex=\"-1\">Where to Start <a class=\"header-anchor\" href=\"#where-to-start\">#</a></h2>\n<p>If this essay has worked, you are asking what to do next, so here is a modest sequence. Spend an hour inside one infrastructure near your own specialty, Sefaria or BUDA or the HMML Reading Room or the American Religious Ecologies maps, and pay attention to what its structure lets you ask. Create a Knowledge Commons account and deposit one thing you have already written. If you teach, replace one paper assignment with one Knight Lab assignment and see what your students do with it. And if you are beginning a research project, ask the ethics questions at the design stage, before the first scan, using Christen and Odumosu as your guides.</p>\n<p>When you want training, it exists and much of it is free. The Programming Historian publishes peer-reviewed, novice-friendly lessons on the exact methods this essay has described, from text analysis to mapping, and you can work through one in an afternoon.<sup class=\"footnote-ref\"><a href=\"#fn42\" id=\"fnref42\">[42]</a></sup> Summer institutes and workshops in the digital humanities now run on several continents, and your library likely has a digital scholarship unit whose staff would be delighted to hear from a theologian, because they field the same questions from historians and literary scholars every week. You will not be starting alone, and you will not be starting from zero. The infrastructures in this essay were built to be used, and the communities around them were built to teach.</p>\n<p>The deeper invitation is to stop thinking of the digital humanities as someone else's field that religion scholars borrow from. The projects in this essay were built by scholars of religion, for questions about religion, often against real technical odds. The evidence of religious life is multi-form, dispersed, fragile, and contested, and it always has been. What has changed is that the methods finally match it.</p>\n<p>One more word to the skeptics, because every department has them and they are often right. You do not have to become a programmer. You do not have to believe that data will settle interpretive questions, because it will not. You do not even have to like these methods to benefit from what they preserve, since the manuscript HMML photographed before the war does not care whether its eventual reader admires databases. The claim of this essay is narrower and harder to dismiss. The evidence of religious life is being digitized, structured, and made computable, by scholars of religion among others, and the standards being set now will govern what future scholars can see and ask. The only question is whether people with theological and religious-studies training are in the room while it happens. Our absence would not stop the work. It would just make the work worse.</p>\n<h2 id=\"in-this-series\" tabindex=\"-1\">In this series <a class=\"header-anchor\" href=\"#in-this-series\">#</a></h2>\n<ol>\n<li>Digital Humanities Part 1: What Are the Digital Humanities?</li>\n<li>Digital Humanities Part 2: Digital Humanities Tools for Dissertations</li>\n<li>Digital Humanities Part 3: Digital Humanities for Theology and Religious Studies</li>\n<li>Digital Humanities Part 4: Why We Need the Digital Humanities</li>\n<li>Digital Humanities Part 5: Preserving Digital Humanities Projects</li>\n<li>Digital Humanities Part 6: Preservation through Minimal Computing and GO::DH</li>\n</ol>\n<hr class=\"footnotes-sep\">\n<section class=\"footnotes\">\n<ol class=\"footnotes-list\">\n<li id=\"fn1\" class=\"footnote-item\"><p>Christopher D. Cantwell and Kristian Petersen, eds., <em>Digital Humanities and Research Methods in Religious Studies: An Introduction</em>, Introductions to Digital Humanities – Religion (Berlin: De Gruyter, 2021), https://www.degruyter.com/document/doi/10.1515/9783110573022/html. <a href=\"#fnref1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn2\" class=\"footnote-item\"><p>&quot;About Sefaria,&quot; Sefaria, accessed July 14, 2026, https://www.sefaria.org/about. <a href=\"#fnref2\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn3\" class=\"footnote-item\"><p>Sefaria's developer resources and API documentation, Sefaria, https://developers.sefaria.org/. <a href=\"#fnref3\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn4\" class=\"footnote-item\"><p>Open Islamicate Texts Initiative, accessed July 14, 2026, https://openiti.org/. <a href=\"#fnref4\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn5\" class=\"footnote-item\"><p>&quot;OpenITI AOCP,&quot; Maryland Institute for Technology in the Humanities, accessed July 14, 2026, https://mith.umd.edu/research/openiti-aocp/. <a href=\"#fnref5\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn6\" class=\"footnote-item\"><p>&quot;About Us,&quot; Buddhist Digital Resource Center, accessed July 14, 2026, https://www.bdrc.io/about-us/. The BUDA platform is at https://library.bdrc.io/. <a href=\"#fnref6\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn7\" class=\"footnote-item\"><p>&quot;About Syriaca.org,&quot; Syriaca.org: The Syriac Reference Portal, ed. David A. Michelson et al., accessed July 14, 2026, https://syriaca.org/about-srophe.html. <a href=\"#fnref7\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn8\" class=\"footnote-item\"><p>Sinai Palimpsests Project, St. Catherine's Monastery of the Sinai in collaboration with the Early Manuscripts Electronic Library and the UCLA Library, accessed July 14, 2026, http://sinaipalimpsests.org/. <a href=\"#fnref8\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn9\" class=\"footnote-item\"><p>&quot;About HMML,&quot; Hill Museum &amp; Manuscript Library, accessed July 14, 2026, https://hmml.org/about/. <a href=\"#fnref9\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn10\" class=\"footnote-item\"><p>HMML Reading Room (vHMML), Hill Museum &amp; Manuscript Library, accessed July 14, 2026, https://www.vhmml.org/readingRoom. <a href=\"#fnref10\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn11\" class=\"footnote-item\"><p>American Religious Sounds Project, dir. Amy DeRogatis and Isaac Weiner, The Ohio State University and Michigan State University, 2014–2022, https://religioussounds.osu.edu/. <a href=\"#fnref11\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn12\" class=\"footnote-item\"><p>Gospel Music History Archive, Center for Religion and Civic Culture, University of Southern California, accessed July 14, 2026, https://dornsife.usc.edu/crcc/gospel-music-history-archive. The archive itself is hosted in the USC Digital Library at https://digitallibrary.usc.edu/Archive/Gospel-Music-History-Archive-2A3BF1P0L9. <a href=\"#fnref12\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn13\" class=\"footnote-item\"><p>Institute for New Testament Textual Research (Institut für Neutestamentliche Textforschung), University of Münster, accessed July 14, 2026, https://www.uni-muenster.de/INTF/. <a href=\"#fnref13\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn14\" class=\"footnote-item\"><p>New Testament Virtual Manuscript Room, Institute for New Testament Textual Research, University of Münster, accessed July 14, 2026, https://ntvmr.uni-muenster.de/. <a href=\"#fnref14\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn15\" class=\"footnote-item\"><p>Pleiades: A Gazetteer of Past Places, accessed July 14, 2026, https://pleiades.stoa.org/. <a href=\"#fnref15\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn16\" class=\"footnote-item\"><p>ORBIS: The Stanford Geospatial Network Model of the Roman World, Stanford University, accessed July 14, 2026, https://orbis.stanford.edu/. <a href=\"#fnref16\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn17\" class=\"footnote-item\"><p>Lincoln Mullen, personal website, accessed July 14, 2026, https://lincolnmullen.com/. His code and data are at https://github.com/lmullen. <a href=\"#fnref17\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn18\" class=\"footnote-item\"><p>Lincoln Mullen, <em>America's Public Bible: A Commentary</em> (Stanford: Stanford University Press, 2022), https://americaspublicbible.supdigital.org/. <a href=\"#fnref18\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn19\" class=\"footnote-item\"><p>Lincoln Mullen, &quot;Introduction,&quot; in <em>America's Public Bible: A Commentary</em> (Stanford: Stanford University Press, 2022), https://americaspublicbible.supdigital.org/essay/introduction/. <a href=\"#fnref19\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn20\" class=\"footnote-item\"><p>&quot;NEH Data Challenge Winner: America's Public Bible,&quot; National Endowment for the Humanities, accessed July 14, 2026, https://www.neh.gov/divisions/preservation/featured-project/neh-data-challenge-winner-americas-public-bible. <a href=\"#fnref20\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn21\" class=\"footnote-item\"><p>Lincoln A. Mullen, <em>The Chance of Salvation: A History of Conversion in America</em> (Cambridge, MA: Harvard University Press, 2017), https://www.hup.harvard.edu/books/9780674975620. <a href=\"#fnref21\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn22\" class=\"footnote-item\"><p>&quot;40,000 Documents from Religious Bodies Census Digitized Nearly a Century Later,&quot; American Religious Ecologies, December 14, 2020, https://religiousecologies.org/blog/40000-documents-from-religious-bodies-census-digitized-nearly-a-century-later/. The project overview is at https://religiousecologies.org/about/. <a href=\"#fnref22\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn23\" class=\"footnote-item\"><p>&quot;40,000 Documents from Religious Bodies Census Digitized Nearly a Century Later,&quot; American Religious Ecologies, December 14, 2020, https://religiousecologies.org/blog/40000-documents-from-religious-bodies-census-digitized-nearly-a-century-later/. <a href=\"#fnref23\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn24\" class=\"footnote-item\"><p>&quot;American Religious Ecologies Receives Second NEH Grant to Work with 1926 Census of Religious Bodies,&quot; Roy Rosenzweig Center for History and New Media, April 2023, https://rrchnm.org/blog/american-religious-ecologies-receives-second-neh-grant-to-work-with-1926-census-of-religious-bodies/. <a href=\"#fnref24\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn25\" class=\"footnote-item\"><p>&quot;Our Story,&quot; Roy Rosenzweig Center for History and New Media, accessed July 14, 2026, https://rrchnm.org/our-story/. <a href=\"#fnref25\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn26\" class=\"footnote-item\"><p>Roy Rosenzweig Center for History and New Media, accessed July 14, 2026, https://rrchnm.org/. Zotero is at https://www.zotero.org/ and Omeka at https://omeka.org/. <a href=\"#fnref26\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn27\" class=\"footnote-item\"><p>&quot;About,&quot; <em>Current Research in Digital History</em>, Roy Rosenzweig Center for History and New Media, accessed July 14, 2026, https://crdh.rrchnm.org/about/. <a href=\"#fnref27\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn28\" class=\"footnote-item\"><p>Pandemic Religion: A Digital Archive, Roy Rosenzweig Center for History and New Media, accessed July 14, 2026, https://pandemicreligion.org/. <a href=\"#fnref28\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn29\" class=\"footnote-item\"><p>Kimberly Christen, &quot;Does Information Really Want to Be Free? Indigenous Knowledge Systems and the Question of Openness,&quot; <em>International Journal of Communication</em> 6 (2012): 2870–2893, https://ijoc.org/index.php/ijoc/article/view/1618. <a href=\"#fnref29\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn30\" class=\"footnote-item\"><p>Mukurtu CMS, accessed July 14, 2026, https://mukurtu.org/. Traditional Knowledge Labels are maintained by Local Contexts at https://localcontexts.org/. <a href=\"#fnref30\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn31\" class=\"footnote-item\"><p>Temi Odumosu, &quot;The Crying Child: On Colonial Archives, Digitization, and Ethics of Care in the Cultural Commons,&quot; <em>Current Anthropology</em> 61, no. S22 (2020), https://doi.org/10.1086/710062. <a href=\"#fnref31\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn32\" class=\"footnote-item\"><p>Gerben Zaagsma, &quot;Digital History and the Politics of Digitization,&quot; <em>Digital Scholarship in the Humanities</em> 38, no. 2 (2023): 830–851, https://doi.org/10.1093/llc/fqac050. <a href=\"#fnref32\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn33\" class=\"footnote-item\"><p>&quot;The Santa Barbara Statement on Collections as Data,&quot; Always Already Computational: Collections as Data, accessed July 14, 2026, https://collectionsasdata.github.io/statement/. <a href=\"#fnref33\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn34\" class=\"footnote-item\"><p>Knowledge Commons, accessed July 14, 2026, https://hcommons.org/. On Kathleen Fitzpatrick's role and the network's scale, see &quot;Kathleen Fitzpatrick Named New Associate Dean for Research and Graduate Studies,&quot; Michigan State University, May 27, 2025, https://wrac.msu.edu/2025/05/27/kathleen-fitzpatrick-named-new-associate-dean-for-research-and-graduate-studies/. <a href=\"#fnref34\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn35\" class=\"footnote-item\"><p>For example, the AAR Artificial Intelligence and Religion Research Seminar group, Knowledge Commons, https://hcommons.org/groups/aar-artificial-intelligence-and-religion-research-seminar/. <a href=\"#fnref35\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn36\" class=\"footnote-item\"><p>&quot;CORE,&quot; Knowledge Commons, accessed July 14, 2026, https://hcommons.org/core/. The repository is at https://works.hcommons.org/. <a href=\"#fnref36\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn37\" class=\"footnote-item\"><p>Digital Humanities at Michigan State University, accessed July 14, 2026, https://digitalhumanities.msu.edu/. <a href=\"#fnref37\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn38\" class=\"footnote-item\"><p>Northwestern University Knight Lab, accessed July 14, 2026, https://knightlab.northwestern.edu/. TimelineJS: https://timeline.knightlab.com/. StoryMapJS: https://storymap.knightlab.com/. JuxtaposeJS: https://juxtapose.knightlab.com/. SoundciteJS: https://soundcite.knightlab.com/. <a href=\"#fnref38\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn39\" class=\"footnote-item\"><p>&quot;About,&quot; Northwestern University Knight Lab, accessed July 14, 2026, https://knightlab.northwestern.edu/about/. <a href=\"#fnref39\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn40\" class=\"footnote-item\"><p><em>The Wabash Center Journal on Teaching</em>, Wabash Center for Teaching and Learning in Theology and Religion, published via Atla Open Press, https://serials.atla.com/wabashcenter/. The Wabash Center is at https://wabashcenter.wabash.edu/. <a href=\"#fnref40\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn41\" class=\"footnote-item\"><p>Randall Reed and Alaina Doyle, &quot;Teaching Religion with Data,&quot; <em>The Wabash Center Journal on Teaching</em> 2, no. 2 (2021), https://serials.atla.com/wabashcenter/article/view/563. <a href=\"#fnref41\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn42\" class=\"footnote-item\"><p>The Programming Historian, accessed July 14, 2026, https://programminghistorian.org/. <a href=\"#fnref42\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n</ol>\n</section>\n",
			"date_published": "2026-07-14T12:31:05Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/dh-part-2-digital-humanities-tools-for-dissertations/",
			"url": "https://www.adamdjbrett.com/blog/dh-part-2-digital-humanities-tools-for-dissertations/",
			"title": "Digital Humanities Part 2: Digital Humanities Tools for Dissertations",
			"content_html": "<p>In Part 1 of this series I asked what the digital humanities are. This post gets practical. If you are writing a dissertation right now, or about to start one, this is a guide to the tools that can actually help you, organized around the problems you actually have.</p>\n<p>First, the claim that shapes everything else in this post. A dissertation is not just a long argument. It is a research system. You gather sources, you organize them, you transform them into evidence, you interpret that evidence, and you present the interpretation in a form your committee can examine. Most of that system stays invisible in a traditional dissertation. The footnotes gesture at it. The methods section summarizes it. But the system itself, the actual machinery of files and notes and decisions, lives in a private folder that no one else ever sees.</p>\n<p>The real value of the digital humanities for dissertation writers is that they make the research system explicit. When you build a corpus, you have to decide what belongs in it and write that decision down. When you make a map, you have to confront how much you actually know about where things happened. When you version your drafts, you create a record of how your argument changed. None of this replaces interpretation. All of it disciplines interpretation, and that discipline is precisely what a dissertation is supposed to demonstrate.</p>\n<p>So this is not a listicle of fifty tools. It is an opinionated walk through the research problems every dissertation writer faces, with the smallest set of tools I trust for each one, and with honest warnings about the interpretive risks each tool introduces. Tools are secondary to transformations. The question is never &quot;should I use Voyant or Gephi.&quot; The question is what transformation your argument requires, what interpretive risk that transformation introduces, and how you will document it.</p>\n<h2 id=\"before-you-pick-a-single-tool\" tabindex=\"-1\">Before you pick a single tool <a class=\"header-anchor\" href=\"#before-you-pick-a-single-tool\">#</a></h2>\n<p>Here is the advice I wish someone had given me before I opened my first piece of software. Write a method statement first.</p>\n<p>Before you install anything, write one page answering five questions. What is the humanistic question I am asking? What evidence bears on it? What would a digital method add that reading alone cannot? What is the smallest toolchain adequate to that addition? What are the ethical and permissions issues in my sources, and how will I handle them?</p>\n<p>That one page will save you months. Graduate students lose entire semesters to tools they adopted because a workshop made them look exciting. The workshop was not wrong. The tool was probably excellent. But excellence is not relevance, and a dissertation runs on a clock. Every tool you adopt has a learning curve, a maintenance cost, and a documentation burden. If the tool does not serve a transformation your argument requires, it is not helping you. It is a very sophisticated form of procrastination.</p>\n<p>The method statement also forces you to name your transformations. Every digital method transforms your sources into something else. Optical character recognition transforms page images into text, imperfectly. Corpus construction transforms a tradition into a bounded dataset, selectively. Georeferencing transforms narrative descriptions of place into coordinates, with false precision as a standing risk. Network extraction transforms relationships into nodes and edges, flattening everything the categories cannot hold. None of these transformations is neutral. Each one is an interpretive act, and your committee is entitled to see it documented. Record your corpus boundaries, your cleaning steps, your exclusions, your uncertainty, your tool versions, and your settings. Future you, revising chapter three at two in the morning, will be grateful. So will the scholar who tries to build on your work in ten years.</p>\n<p>With that frame in place, we can talk about tools. I have organized what follows by dissertation problem, not by tool category, because you do not wake up needing &quot;a network analysis package.&quot; You wake up needing to manage two thousand sources, or to read more sermons than any human can read, or to show a committee where something happened.</p>\n<h2 id=\"the-center-that-built-your-toolkit\" tabindex=\"-1\">The center that built your toolkit <a class=\"header-anchor\" href=\"#the-center-that-built-your-toolkit\">#</a></h2>\n<p>Before the problems, though, one piece of context that I find remarkable and that too few graduate students know. A single university center built much of the everyday infrastructure of humanities research.</p>\n<p>The Roy Rosenzweig Center for History and New Media at George Mason University, usually shortened to RRCHNM, was founded by the historian Roy Rosenzweig in 1994. Its mission is to use digital media and technology &quot;to democratize history: to incorporate multiple voices, reach diverse audiences, and encourage popular participation in presenting and preserving the past.&quot;<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1\">[1]</a></sup> Rosenzweig himself died in 2007, at just fifty-seven, and the center was renamed in his honor in 2011.<sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2\">[2]</a></sup> He saw earlier than almost anyone that historians would soon face what he called a shift &quot;from a culture of scarcity to a culture of abundance,&quot; and he argued in a landmark 2003 essay that scholars &quot;need to be thinking simultaneously about how to research, write, and teach in a world of unheard-of historical abundance and how to avoid a future of record scarcity.&quot;<sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3\">[3]</a></sup> That essay repays reading in full, and it frames this whole series. Parts 5 and 6 will return to it.</p>\n<p>The record of software that came out of this one center still astonishes me. Zotero, the reference manager that anchors the research systems of scholars across every humanities discipline, was established at RRCHNM.<sup class=\"footnote-ref\"><a href=\"#fn4\" id=\"fnref4\">[4]</a></sup> Tropy, the tool for organizing archival photographs, was created there.<sup class=\"footnote-ref\"><a href=\"#fn5\" id=\"fnref5\">[5]</a></sup> Omeka, the platform behind thousands of library, museum, and scholarly exhibition websites, launched from the center in 2008.<sup class=\"footnote-ref\"><a href=\"#fn6\" id=\"fnref6\">[6]</a></sup> PressForward, the WordPress plugin that powers curated scholarly publications like Digital Humanities Now, launched there in 2011.<sup class=\"footnote-ref\"><a href=\"#fn7\" id=\"fnref7\">[7]</a></sup> Four tools, one center, and together they cover source management, archival photography, web publishing, and scholarly communication. Well-funded commercial vendors have not matched that record of building things scholars actually use every day. If your dissertation touches the digital humanities at all, you are almost certainly running RRCHNM code, and it is worth knowing where it came from and why it is free.</p>\n<p>The center is now in its fourth decade, its sites draw over two million visitors a year, and it continues to train digital historians and build data-rich histories.<sup class=\"footnote-ref\"><a href=\"#fn8\" id=\"fnref8\">[8]</a></sup> Its current executive director is Lincoln Mullen, about whom more below, because his own work models the learning ethos I want to recommend to you.</p>\n<h2 id=\"managing-the-research-system-zotero\" tabindex=\"-1\">Managing the research system: Zotero <a class=\"header-anchor\" href=\"#managing-the-research-system-zotero\">#</a></h2>\n<p>Every dissertation problem I will discuss sits downstream of one unglamorous task. You have to manage sources, in the hundreds or thousands, over four to eight years, without losing anything. This is the problem to solve first, and Zotero is the answer.</p>\n<p>Zotero describes itself as &quot;a free, open-source research tool that helps you collect, organize, and analyze research and share it in a variety of ways,&quot; and for once the self-description undersells the product.<sup class=\"footnote-ref\"><a href=\"#fn9\" id=\"fnref9\">[9]</a></sup> It has been in continuous development since 2006, it is maintained by the nonprofit Corporation for Digital Scholarship, and it will never charge you for the core product or hold your library hostage.<sup class=\"footnote-ref\"><a href=\"#fn10\" id=\"fnref10\">[10]</a></sup> That last point matters more than it sounds. Your dissertation library is a multi-year asset. Do not build it inside a commercial product whose pricing, ownership, or existence could change before your defense.</p>\n<p>Here is what a Zotero-centered workflow looks like in practice. The browser connector captures full bibliographic metadata from library catalogs, JSTOR, publisher pages, and news sites with one click, usually grabbing the PDF along the way. The built-in PDF reader lets you highlight and annotate, and your annotations live in your library, searchable, right next to the metadata. Tags and collections let you organize the same source into multiple chapters without duplicating it. The word processor plugins format your citations and bibliography in any of the more than 10,000 styles in the Zotero Style Repository, which means switching from Chicago notes to author-date because your committee changed its mind is a five-minute problem instead of a five-day one.<sup class=\"footnote-ref\"><a href=\"#fn11\" id=\"fnref11\">[11]</a></sup> Group libraries let you share sources with your adviser or a writing group.</p>\n<p>Two habits turn Zotero from a citation manager into a research system. First, tag by argument, not just by topic. A tag like &quot;evidence-for-chapter-2-counterargument&quot; is worth ten tags like &quot;ritual.&quot; Second, write a sentence or two of notes on every source when you first read it, in your own words, stating what the source is evidence for. Four years later those sentences are the difference between a literature review that takes a month and one that takes a season.</p>\n<h2 id=\"managing-the-archive-you-photographed-tropy\" tabindex=\"-1\">Managing the archive you photographed: Tropy <a class=\"header-anchor\" href=\"#managing-the-archive-you-photographed-tropy\">#</a></h2>\n<p>If your dissertation involves archival research, you will come home from the archive with thousands of photographs named IMG_4032.jpg, and six months later you will have no idea which box, folder, or archive half of them came from. This failure mode is so universal that RRCHNM built a dedicated tool to prevent it.</p>\n<p>Tropy is &quot;free open-source software that allows you to organize and describe photographs of research material.&quot;<sup class=\"footnote-ref\"><a href=\"#fn12\" id=\"fnref12\">[12]</a></sup> Its central insight is that the photograph is not the unit of research. The document is. A five-page letter is five photos but one item, and Tropy lets you group photos into items, attach metadata about the archive, collection, box, and folder, add tags and lists, and transcribe passages right next to the image. It is now developed jointly by RRCHNM, the Luxembourg Centre for Contemporary and Digital History, and Digital Scholar, with Mellon funding behind it, which is a reasonable proxy for institutional staying power.<sup class=\"footnote-ref\"><a href=\"#fn13\" id=\"fnref13\">[13]</a></sup></p>\n<p>The discipline Tropy enforces is the discipline your footnotes will need anyway. Every archival citation in your dissertation ultimately resolves to repository, collection, box, folder, item. If you enter that metadata the week you visit the archive, your citations write themselves. If you do not, you will be emailing archivists apologetic questions three years later. Tropy also exports to JSON-LD and CSV and integrates directly with Omeka S, so the descriptive work you do now can seed a digital exhibit later.</p>\n<h2 id=\"versioning-the-argument-git-and-github\" tabindex=\"-1\">Versioning the argument: Git and GitHub <a class=\"header-anchor\" href=\"#versioning-the-argument-git-and-github\">#</a></h2>\n<p>Here is the tool recommendation that meets the most resistance from humanities graduate students, and the one I will defend hardest. Put your dissertation under version control.</p>\n<p>Git is a system that records snapshots of your files over time, with a note attached to each snapshot saying what changed and why. GitHub is a service that stores those snapshots remotely. Together they give you three things no cloud drive gives you. A true history of your argument, so you can recover the paragraph you deleted in March. An offsite backup that is a deliberate act rather than a background sync you hope is working. And a log of your own thinking, because commit messages like &quot;cut the Weber section, the argument works without it&quot; are a record of decisions, not just of keystrokes.</p>\n<p>The cost of entry is lower than its reputation suggests. You do not need the command line to start. The Programming Historian ran a widely used lesson on GitHub Desktop, the point-and-click application, framed explicitly for scholars writing articles and dissertations in plain text.<sup class=\"footnote-ref\"><a href=\"#fn14\" id=\"fnref14\">[14]</a></sup> The lesson has since been retired because the software's interface moved on, but the workflow it teaches, edit, commit, push, remains exactly right, and current GitHub Desktop documentation covers the same ground. If you write in Markdown or LaTeX, version control fits your files natively. If you write in Word, it still backs you up faithfully, though the change-by-change comparisons work best with plain text.</p>\n<p>Version control also quietly prepares you for something bigger. If your dissertation involves any code or data at all, versioning is not optional. It is the difference between &quot;the analysis in chapter four&quot; being reproducible and being a rumor. Committees increasingly ask, and future scholars will certainly ask, exactly what you ran and when.</p>\n<h2 id=\"cleaning-what-the-sources-give-you-openrefine\" tabindex=\"-1\">Cleaning what the sources give you: OpenRefine <a class=\"header-anchor\" href=\"#cleaning-what-the-sources-give-you-openrefine\">#</a></h2>\n<p>Somewhere between collecting sources and analyzing them lives the least discussed phase of digital work, and the one where more interpretive decisions hide than anywhere else. Cleaning.</p>\n<p>Suppose you have extracted a spreadsheet of names from a mission society's annual reports. The same missionary appears as &quot;Rev. J. Smith,&quot; &quot;John Smith,&quot; and &quot;Smyth, J.&quot; The same station appears under three spellings and two colonial renamings. Before you can count, map, or graph anything, you have to decide that these are the same person and the same place. Those are historical judgments, not technical chores, and they belong in your documentation.</p>\n<p>OpenRefine is the tool for this work. It calls itself &quot;a powerful free, open source tool for working with messy data,&quot; which it cleans, transforms between formats, and extends with web services and external data.<sup class=\"footnote-ref\"><a href=\"#fn15\" id=\"fnref15\">[15]</a></sup> Its clustering functions find probable variants of the same name and let you approve or reject each merge. Crucially for our purposes, OpenRefine keeps a complete, exportable history of every operation you perform. That history is your methods appendix, generated for free while you work. When a committee member asks how you standardized names, you can show them, step by step. That answer is the difference between data cleaning as silent distortion and data cleaning as documented method.</p>\n<h2 id=\"reading-more-than-you-can-read-corpora-voyant-and-antconc\" tabindex=\"-1\">Reading more than you can read: corpora, Voyant, and AntConc <a class=\"header-anchor\" href=\"#reading-more-than-you-can-read-corpora-voyant-and-antconc\">#</a></h2>\n<p>Now to the transformations that get called &quot;distant reading.&quot; Suppose your dissertation asks how a denomination's language about mission changed across sixty years of periodicals. No one can close-read sixty years of periodicals. A corpus lets you ask the question anyway.</p>\n<p>Begin with the principle that governs everything downstream. A corpus is an argument about inclusion. The moment you decide which periodicals are in, which years, which genres, whether letters to the editor count, whether reprinted material counts, you have made claims about what represents the phenomenon you are studying. Write those claims down before you analyze anything, because every count, trend, and topic you find is conditional on them. A finding that &quot;mission language declines after 1920&quot; means one thing if your corpus includes the denomination's women's auxiliary magazine and another thing entirely if it does not.</p>\n<p>For exploring a corpus, start with Voyant Tools. Voyant is &quot;a web-based text reading and analysis environment&quot; that its creators describe as &quot;a scholarly project that is designed to facilitate reading and interpretive practices.&quot;<sup class=\"footnote-ref\"><a href=\"#fn16\" id=\"fnref16\">[16]</a></sup> Note that word choice. Reading, not results. You paste in or upload your texts and Voyant gives you word frequencies, trends across the corpus, keywords in context, and a dozen other views, all linked, all in the browser, with nothing to install. It was built by Stéfan Sinclair and Geoffrey Rockwell, whose book Hermeneutica argues at length that these tools are instruments for interpretation rather than proof machines.<sup class=\"footnote-ref\"><a href=\"#fn17\" id=\"fnref17\">[17]</a></sup> That framing is exactly right, and it is why Voyant is safe to recommend to beginners. It invites you to look, then look closer.</p>\n<p>When you need more control, AntConc is the next step. Laurence Anthony's freeware corpus analysis toolkit gives you concordances, collocates, keyword lists, and n-grams with precise, adjustable settings.<sup class=\"footnote-ref\"><a href=\"#fn18\" id=\"fnref18\">[18]</a></sup> Where Voyant invites exploration, AntConc supports the focused question. Show me every occurrence of &quot;civilization&quot; within five words of &quot;Christian,&quot; by decade. That is a query a chapter can be built on.</p>\n<p>The method that makes any of this scholarship rather than decoration is the movement between distant and close reading. The corpus view shows you a pattern. You then go read the passages that make up the pattern, in full, in context, the way you were trained to. Half the time the pattern dissolves under close reading, an artifact of OCR errors or a reprinted article counted forty times. That is not failure. That is validation, and you should report it. The other half of the time the pattern survives, and now you have a finding you can defend from two directions at once. Validate every computational output through close reading before it enters your argument. No exceptions, and especially no exceptions for the outputs that confirm what you hoped to find.</p>\n<h2 id=\"showing-where-qgis-and-honest-maps\" tabindex=\"-1\">Showing where: QGIS and honest maps <a class=\"header-anchor\" href=\"#showing-where-qgis-and-honest-maps\">#</a></h2>\n<p>Space is evidence. Where congregations formed, where presses operated, where pilgrims walked, these are facts an argument can rest on, and maps make them visible in ways prose cannot. But maps are also the digital genre most prone to quiet dishonesty, because a map asserts every location with the same confident dot.</p>\n<p>QGIS is the tool I recommend for serious dissertation mapping. It is a full open-source geographic information system, community-owned and free.<sup class=\"footnote-ref\"><a href=\"#fn19\" id=\"fnref19\">[19]</a></sup> The learning curve is real, a few weeks of steady practice rather than an afternoon, but it repays the effort with complete control. You can georeference a scanned historical map, layer your evidence over it, distinguish categories of places by symbol, and export publication-quality figures for the dissertation itself.</p>\n<p>The interpretive discipline matters more than the software. Historical sources rarely give you coordinates. They give you &quot;near the river crossing,&quot; &quot;the old mission station,&quot; &quot;a village three days' walk inland.&quot; Before you map anything, classify every place in your evidence into at least these categories: exact, approximate, contested, remembered, and lost. Then make the map show the difference, with distinct symbols or explicit uncertainty notes. A map that renders a remembered place and a surveyed one with the same dot has erased precisely the thing a humanist should care about, which is how people knew where things were. Your committee may not ask about this. You should do it anyway, because a map must not erase uncertainty, and because a map does not prove an argument. It visualizes evidence for one.</p>\n<h2 id=\"showing-who-knew-whom-gephi-and-palladio\" tabindex=\"-1\">Showing who knew whom: Gephi and Palladio <a class=\"header-anchor\" href=\"#showing-who-knew-whom-gephi-and-palladio\">#</a></h2>\n<p>Networks tempt dissertation writers more than any other method, because humanities evidence is full of relationships. Correspondents, co-authors, teachers and students, lenders and borrowers, patrons and clients. Network analysis makes those relationships computable, and two free tools make it accessible.</p>\n<p>Gephi is the established open-source platform for visual network analysis, powerful enough for large graphs and rich in layout and measurement options.<sup class=\"footnote-ref\"><a href=\"#fn20\" id=\"fnref20\">[20]</a></sup> Palladio, built at Stanford for humanists, is gentler.<sup class=\"footnote-ref\"><a href=\"#fn21\" id=\"fnref21\">[21]</a></sup> You upload a spreadsheet and get networks, maps, and galleries with almost no setup, which makes it ideal for the exploratory phase when you are still deciding whether network structure is even part of your argument.</p>\n<p>The warning here is the same one, wearing different clothes. Node and edge choices are interpretive. When you decide that a &quot;connection&quot; means at least one surviving letter, you have decided that survival equals relationship, and that silence equals absence. Archives preserve some relationships and destroy others, on lines of gender, class, and empire that your dissertation probably cares about. So say what an edge means, say what the archive cannot show, and treat centrality scores as questions to investigate, not conclusions to report. &quot;Why does this minor figure sit at the center of the graph&quot; is a wonderful research question. &quot;This figure was central&quot; is, by itself, an artifact of counting.</p>\n<h2 id=\"working-with-the-sources-themselves-recogito-transkribus-and-escriptorium\" tabindex=\"-1\">Working with the sources themselves: Recogito, Transkribus, and eScriptorium <a class=\"header-anchor\" href=\"#working-with-the-sources-themselves-recogito-transkribus-and-escriptorium\">#</a></h2>\n<p>Three tools serve the slow middle of a source-driven dissertation, where you are annotating and transcribing.</p>\n<p>Recogito, from the Pelagios network, offers what its makers call &quot;Semantic Annotation without the pointy brackets.&quot;<sup class=\"footnote-ref\"><a href=\"#fn22\" id=\"fnref22\">[22]</a></sup> You upload texts or images and mark up places, people, and events by selecting and clicking, no encoding knowledge required. It is particularly strong for place annotation, linking the places you mark to gazetteers, which means your annotations can become a map dataset later. For a dissertation on travel narratives, pilgrimage accounts, or missionary itineraries, Recogito can be the bridge from reading to mapping.</p>\n<p>Transkribus applies machine learning to handwritten text recognition. It is run by a European cooperative of research institutions and describes itself as a platform for turning handwritten documents into searchable text.<sup class=\"footnote-ref\"><a href=\"#fn23\" id=\"fnref23\">[23]</a></sup> If your sources are manuscript letters, diaries, or registers, Transkribus can convert months of squinting into a searchable corpus. Train or select a model, correct its output on sample pages, and the model improves. The transformation is powerful and its risk is obvious. Recognition errors are not randomly distributed. They cluster on unusual names, non-standard spellings, and marginal hands, which may be exactly the voices your dissertation exists to recover. Report error rates, and hand-check every passage you quote. eScriptorium offers an open-source alternative in the same space, worth evaluating if institutional control of your data matters to your project or your archive's permissions.</p>\n<h2 id=\"the-fastest-on-ramp-northwesterns-knight-lab\" tabindex=\"-1\">The fastest on-ramp: Northwestern's Knight Lab <a class=\"header-anchor\" href=\"#the-fastest-on-ramp-northwesterns-knight-lab\">#</a></h2>\n<p>Now for the section I most want overwhelmed graduate students to read. Suppose you need a publication-quality interactive, a timeline for a conference presentation, a map-driven narrative for a digital appendix, a before-and-after image comparison for a chapter on architectural change, and you have no time to learn QGIS and no intention of learning JavaScript. There is a place built for you, and it is Northwestern University's Knight Lab.</p>\n<p>Knight Lab describes itself as &quot;a community of designers, developers, students, and educators working on experiments designed to push journalism into new spaces.&quot;<sup class=\"footnote-ref\"><a href=\"#fn24\" id=\"fnref24\">[24]</a></sup> It sits between Northwestern's Medill School of Journalism and its McCormick School of Engineering, and that location explains everything good about its tools. Journalists have humanists' problems, real stories, real evidence, real deadlines, without the luxury of semester-long tool training. So Knight Lab built storytelling tools that produce professional results in an afternoon, and every one of them is free and open source. Four of them belong in a dissertation writer's kit.</p>\n<p>TimelineJS is &quot;an open-source tool that enables anyone to build visually rich, interactive timelines.&quot;<sup class=\"footnote-ref\"><a href=\"#fn25\" id=\"fnref25\">[25]</a></sup> The mechanism is disarmingly simple. You copy a Google Sheets template, fill in rows with dates, text, and links to media, publish the sheet, and paste its address into the TimelineJS generator. Out comes an embeddable, elegant, interactive timeline. For a dissertation, think of the chronology you are already building for your own reference, the sequence of synods, editions, controversies, or campaigns, and imagine it as a navigable object your committee can explore before the defense. The Google Sheets workflow means updating the timeline is just editing a spreadsheet.</p>\n<p>StoryMapJS is &quot;a free tool to help you tell stories on the web that highlight the locations of a series of events.&quot;<sup class=\"footnote-ref\"><a href=\"#fn26\" id=\"fnref26\">[26]</a></sup> Where QGIS produces analytical maps, StoryMapJS produces narrative ones. A sequence of slides, each pinned to a place, each carrying text and media, walking a reader along a route. A pilgrimage, a preaching tour, a migration, a supply chain. Its gigapixel mode does the same walking across a large image instead of a map, so you can guide a reader across a historic map, a painting, or a manuscript page, stopping at details in order. This is the tool I recommend when someone says they want &quot;something like a documentary, but for my chapter.&quot;</p>\n<p>JuxtaposeJS &quot;helps storytellers compare two pieces of similar media, including photos, and GIFs.&quot;<sup class=\"footnote-ref\"><a href=\"#fn27\" id=\"fnref27\">[27]</a></sup> It puts a slider between two aligned images. Before and after the fire, the renovation, the iconoclasm, the urban renewal. All you supply is two image addresses. For any dissertation arguing visual or material change, a juxtapose slider communicates in two seconds what a page of prose approximates.</p>\n<p>SoundCite solves a problem you may not have named. As Knight Lab puts it, &quot;audio clips force uncomfortable choices: read or listen, but not both.&quot;<sup class=\"footnote-ref\"><a href=\"#fn28\" id=\"fnref28\">[28]</a></sup> SoundCite makes audio play inline, from a highlighted phrase inside your running text, so a reader of your web-published chapter can hear the hymn, the sermon excerpt, or the oral history clip at the exact sentence where you analyze it, without stopping. For scholars of religion working on sound, liturgy, or oral tradition, that changes what a written chapter can do.</p>\n<p>Knight Lab maintains other tools worth a look, including StorylineJS for annotated charts and Scene for VR stories, but the four above are the core. None requires code. All embed anywhere that accepts an iframe, including Omeka and Scalar sites and most university web platforms. If the digital component of your dissertation needs to exist by next month, start here.</p>\n<h2 id=\"learn-by-doing-lincoln-mullen-and-the-programming-historian\" tabindex=\"-1\">Learn by doing: Lincoln Mullen and the Programming Historian <a class=\"header-anchor\" href=\"#learn-by-doing-lincoln-mullen-and-the-programming-historian\">#</a></h2>\n<p>At some point a tool will not quite do what your argument needs, and you will face the question every digitally inclined dissertation writer eventually faces. Should I learn to code? My answer is a qualified yes, and the qualification is about how you learn, and the model I want to point you to is Lincoln Mullen.</p>\n<p>Mullen is a professor of history at George Mason University and now executive director of RRCHNM.<sup class=\"footnote-ref\"><a href=\"#fn29\" id=\"fnref29\">[29]</a></sup> What makes him worth your attention as a dissertation writer is the shape of his work. He is a scholar of American religion whose first book, The Chance of Salvation, is a history of conversion in America published by Harvard University Press.<sup class=\"footnote-ref\"><a href=\"#fn30\" id=\"fnref30\">[30]</a></sup> He is also a builder whose computational projects serve historical arguments rather than replacing them. His America's Public Bible, published by Stanford University Press as an interactive scholarly work, tracks biblical quotation across millions of nineteenth-century American newspaper pages, and it won its arguments by pairing that scale with close reading of individual quotations in context.<sup class=\"footnote-ref\"><a href=\"#fn31\" id=\"fnref31\">[31]</a></sup> He has released R packages for historians, including textreuse for detecting borrowed text between documents and USAboundaries for historical state and county lines, tools built because his own research needed them and shared because someone else's would.<sup class=\"footnote-ref\"><a href=\"#fn32\" id=\"fnref32\">[32]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn33\" id=\"fnref33\">[33]</a></sup></p>\n<p>Two things about his practice transfer directly to yours. First, he teaches computation as historical thinking, not as programming for its own sake. His open, in-progress textbook Computational Historical Thinking states its aim in one sentence: &quot;The aim of this book is to teach you how to think historically with computational methods.&quot;<sup class=\"footnote-ref\"><a href=\"#fn34\" id=\"fnref34\">[34]</a></sup> The book proceeds through miniature research projects, real questions with real data, which is exactly how you should learn, one small project connected to your actual dissertation at a time. Second, he insists that visualizations earn their keep. In an essay answering the common objection that DH charts merely show what we already knew, he describes showing audiences a blank chart first, axes and title only, and asking them to sketch the trend they expect. &quot;The problem,&quot; he writes, &quot;is that often it is not possible to know what a visualization would look like in advance.&quot;<sup class=\"footnote-ref\"><a href=\"#fn35\" id=\"fnref35\">[35]</a></sup> Try this on yourself before every chart you make. If you can draw the result in advance and you are always right, the chart is illustration. When your sketch is wrong, you have learned something, and that is when the method is earning its place in your dissertation.</p>\n<p>The same learn-by-doing ethos has an institutional home at the Programming Historian, an open access, peer reviewed journal of methodology founded in 2008 by William J. Turkel and Alan MacEachern.<sup class=\"footnote-ref\"><a href=\"#fn36\" id=\"fnref36\">[36]</a></sup> Its tutorials walk you through real methods on real data, they are &quot;rigorously peer reviewed,&quot; and every lesson is published under a Creative Commons CC-BY license with no fees of any kind.<sup class=\"footnote-ref\"><a href=\"#fn37\" id=\"fnref37\">[37]</a></sup> It now publishes in English, Spanish, French, and Portuguese. When you decide it is time to learn text analysis in Python, mapping in R, or data cleaning in OpenRefine, do not start with a generic programming course. Start with a Programming Historian lesson that ends with a result a humanist would recognize. Learning by doing, on materials that resemble your own, is the only tool pedagogy I have ever seen stick.</p>\n<h2 id=\"a-worked-example-start-to-finish\" tabindex=\"-1\">A worked example, start to finish <a class=\"header-anchor\" href=\"#a-worked-example-start-to-finish\">#</a></h2>\n<p>Abstractions only carry so far, so let me walk one imaginary dissertation through the whole system. Suppose you are writing on healing practices in early twentieth-century American Pentecostalism, working from denominational periodicals, a founder's correspondence in two archives, and a handful of recorded oral histories from a congregation's centennial project.</p>\n<p>The method statement comes first. The humanistic question is how claims about divine healing changed as the movement institutionalized. The evidence is roughly forty years of periodicals, about nine hundred letters, and eleven interviews. The digital addition, stated in one sentence, is that periodical language about healing can be tracked at a scale no reader can hold in memory, and that the letters' geography can show whether healing testimony traveled along the same routes as personnel. The ethical questions are real. The oral histories involve living people and a worshiping community, so they stay out of every public dataset unless consent, your IRB, and the congregation all say otherwise.</p>\n<p>Now the toolchain, kept small. Zotero holds every secondary source and every periodical issue you cite, tagged by chapter and by argument. Tropy holds the four thousand photographs from both archives, grouped into letters as items, with box and folder metadata entered during the trip because past you read this post. The dissertation itself lives in plain text under Git, committed at the end of every writing day, pushed to a private GitHub repository, which cost you two afternoons to learn.</p>\n<p>The periodical corpus requires decisions, and the decisions get written down. In: the movement's two flagship weeklies, 1906 to 1945, articles and testimonies. Out: reprints from other papers, advertisements, and the children's page, each exclusion noted with a reason. OCR quality gets spot-checked, and the error rate on a fifty-page sample goes in the methods appendix. Voyant gives the first look, and the trend line for healing terms shows a dip in the 1920s you did not expect. Following Mullen's blank-chart practice, you had sketched your prediction beforehand, and you were wrong, which is exactly why the finding might matter. AntConc then shows you every &quot;healing&quot; collocate by decade, and close reading of two hundred passages reveals the dip is partly real and partly an editorial change, testimonies moved to a new column your corpus had excluded. So the corpus gets revised, the exclusion log gets updated, and the finding survives in chastened, defensible form. That embarrassing-sounding correction is not a footnote to the method. It is the method.</p>\n<p>The letters yield a spreadsheet of senders, recipients, and places, cleaned in OpenRefine with its operation history exported. Place names get classified as exact, approximate, or lost, since several healing homes appear in no gazetteer. QGIS maps the defensible ones with distinct symbols for the uncertain ones. For the defense and the department website, StoryMapJS walks viewers along one evangelist's 1913 itinerary in eight slides, built in an evening from work the research system had already done. A TimelineJS chronology of institutional milestones does similar double duty in a conference talk.</p>\n<p>When the dissertation is filed, the corpus metadata, the exclusion log, the cleaned letter tables, and the analysis scripts go to Zenodo and get a DOI, cited in the dissertation's own bibliography. The conference paper goes to CORE with a DOI of its own. The oral histories go nowhere public, and the dissertation says so plainly, because documented restraint is also documentation.</p>\n<p>Total new software learned: seven tools, none requiring code, plus one optional Programming Historian lesson when the text analysis outgrew Voyant. Every transformation named, every risk logged, every output validated by reading. That is what a research system made explicit looks like, and no single step was heroic.</p>\n<h2 id=\"publishing-the-digital-component-omeka-scalar-and-pressforward\" tabindex=\"-1\">Publishing the digital component: Omeka, Scalar, and PressForward <a class=\"header-anchor\" href=\"#publishing-the-digital-component-omeka-scalar-and-pressforward\">#</a></h2>\n<p>Some dissertations end at the PDF. Increasingly, many do not. If your project includes an exhibit, an edition, or a curated collection, two platforms deserve your attention, and both come from the scholarly world rather than the startup world.</p>\n<p>Omeka is &quot;a free, flexible, and open source web-publishing platform for the display of library, museum, archives, and scholarly collections and exhibitions.&quot;<sup class=\"footnote-ref\"><a href=\"#fn38\" id=\"fnref38\">[38]</a></sup> It thinks in items, metadata, collections, and exhibits, which is to say it thinks the way archives think. Omeka Classic, public since 2008, serves individual projects well, and it has been downloaded over half a million times.<sup class=\"footnote-ref\"><a href=\"#fn39\" id=\"fnref39\">[39]</a></sup> Omeka S, the newer sibling, serves institutions running many sites and speaks linked open data natively.<sup class=\"footnote-ref\"><a href=\"#fn39\" id=\"fnref39:1\">[39:1]</a></sup> For a dissertation, Omeka Classic is usually the right size. If you organized your archival photographs in Tropy, you can move them into Omeka with their metadata intact, which turns the private discipline of your research system into a public contribution.</p>\n<p>Scalar, from the Alliance for Networking Visual Culture at the University of Southern California, suits born-digital scholarly argument, long-form writing woven through media, with multiple pathways through the same material.<sup class=\"footnote-ref\"><a href=\"#fn40\" id=\"fnref40\">[40]</a></sup> Where Omeka presents collections, Scalar presents arguments about collections. If your digital component is closer to a media-rich monograph chapter than to an exhibit, Scalar is the better fit.</p>\n<p>And for a different kind of publishing problem, staying current and making your field's gray literature visible, there is PressForward, RRCHNM's WordPress plugin for aggregating, filtering, and disseminating scholarship from across the web.<sup class=\"footnote-ref\"><a href=\"#fn41\" id=\"fnref41\">[41]</a></sup> Its proof of concept is Digital Humanities Now, which has surfaced blog posts, white papers, and conference talks that formal journals would never carry. A dissertation writing group, a graduate program, or a small subfield can run a PressForward publication with an editor rotation and an RSS reader. It is community infrastructure at dissertation-committee scale.</p>\n<h2 id=\"making-it-last-and-making-it-count-zenodo-dataverse-and-core\" tabindex=\"-1\">Making it last and making it count: Zenodo, Dataverse, and CORE <a class=\"header-anchor\" href=\"#making-it-last-and-making-it-count-zenodo-dataverse-and-core\">#</a></h2>\n<p>You will produce more than a dissertation. You will produce a corpus, a dataset, cleaning scripts, maybe an edition or a website. Two questions decide whether that work outlives your defense. Where will it live, and how will people cite it? Part 5 of this series takes up preservation in depth, but the deposit habit belongs in this post because you should start it now, not after you graduate.</p>\n<p>Zenodo is a free and open digital archive built by CERN and OpenAIRE that accepts research outputs &quot;in any size, format and from all fields of research.&quot;<sup class=\"footnote-ref\"><a href=\"#fn42\" id=\"fnref42\">[42]</a></sup> Deposit your dataset or code there and it receives a DOI, a persistent identifier that makes it citable forever, with versioning so corrected datasets keep their history. Harvard Dataverse serves the same deposit-and-cite function with especially strong support for structured data.<sup class=\"footnote-ref\"><a href=\"#fn43\" id=\"fnref43\">[43]</a></sup> Either one transforms &quot;data available from the author on request,&quot; which is where data goes to die, into a citable scholarly object with a permanent address.</p>\n<p>For humanities scholars specifically, I want to flag Knowledge Commons, the scholarly network at hcommons.org, hosted at Michigan State University.<sup class=\"footnote-ref\"><a href=\"#fn44\" id=\"fnref44\">[44]</a></sup> Its repository, CORE, the Commons Open Repository Exchange, is &quot;a library-quality repository for sharing, discovering, retrieving, and archiving digital work,&quot; and it assigns DOIs to deposits, registered with DataCite.<sup class=\"footnote-ref\"><a href=\"#fn45\" id=\"fnref45\">[45]</a></sup> What makes CORE especially useful during the dissertation years is its breadth. It takes conference papers, syllabi, datasets, and works in progress, the dissertation-adjacent outputs that have no other citable home.<sup class=\"footnote-ref\"><a href=\"#fn46\" id=\"fnref46\">[46]</a></sup> The conference paper you gave at AAR does not have to vanish into a program PDF. Deposit it, get a DOI, put it on your CV as a citable object, and let other scholars find it. It costs nothing, and it starts building the public research profile you will want on the job market anyway.</p>\n<p>Whatever repositories you choose, cite your own datasets, code, editions, and websites in the dissertation itself, with their DOIs, exactly as you cite books. This is how the research system becomes visible and creditable, for you and for everyone who builds on you.</p>\n<h2 id=\"a-decision-path-and-a-closing-caution\" tabindex=\"-1\">A decision path, and a closing caution <a class=\"header-anchor\" href=\"#a-decision-path-and-a-closing-caution\">#</a></h2>\n<p>Let me compress this whole post into the sequence I recommend every time someone asks &quot;which tools should I use for my dissertation.&quot;</p>\n<p>Define the humanistic question first, in writing. Identify the evidence that bears on it. State, in a sentence, what a digital method would add that reading alone cannot. If you cannot write that sentence, stop. You have saved yourself a semester, and reading alone is a proud and sufficient method. If you can write it, choose the smallest toolchain adequate to the addition. Zotero almost always. Tropy if there is an archive. Git if there is code or plain text. One analysis tool, not four, matched to the transformation your argument needs. A Knight Lab tool if you need an interactive fast. Then plan ethics and permissions before you build, especially for oral histories, living communities, and religious materials with access restrictions. Document as you go: corpus boundaries, cleaning steps, exclusions, uncertainty, tool versions, settings. Validate every computational output through close reading. Preserve and cite your datasets, code, and sites with DOIs. And keep the argument interpretive from first page to last.</p>\n<p>That last clause is the caution I want to leave you with, and it is the hill this whole series stands on. A map does not prove an argument. A topic model does not interpret a tradition. A network graph does not understand a community, and a timeline does not explain change. You do those things. The tools transform your sources so that your interpretation has more, and more explicit, evidence to work with. Used that way, with the transformations named and the risks documented, digital tools do not make your dissertation less humanistic. They make its humanism easier to examine, which is what a dissertation is for.</p>\n<p>In Part 3, I will turn to what all this looks like in theology and religious studies specifically, where our sources, our communities, and our questions put particular pressure on these methods.</p>\n<h2 id=\"in-this-series\" tabindex=\"-1\">In this series <a class=\"header-anchor\" href=\"#in-this-series\">#</a></h2>\n<ol>\n<li>Digital Humanities Part 1: What Are the Digital Humanities?</li>\n<li>Digital Humanities Part 2: Digital Humanities Tools for Dissertations</li>\n<li>Digital Humanities Part 3: Digital Humanities for Theology and Religious Studies</li>\n<li>Digital Humanities Part 4: Why We Need the Digital Humanities</li>\n<li>Digital Humanities Part 5: Preserving Digital Humanities Projects</li>\n<li>Digital Humanities Part 6: Preservation through Minimal Computing and GO::DH</li>\n</ol>\n<hr class=\"footnotes-sep\">\n<section class=\"footnotes\">\n<ol class=\"footnotes-list\">\n<li id=\"fn1\" class=\"footnote-item\"><p>Roy Rosenzweig Center for History and New Media, &quot;Our Story,&quot; George Mason University, accessed July 14, 2026, https://rrchnm.org/our-story/ <a href=\"#fnref1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn2\" class=\"footnote-item\"><p>Wikipedia, &quot;Roy Rosenzweig,&quot; accessed July 14, 2026, https://en.wikipedia.org/wiki/Roy_Rosenzweig <a href=\"#fnref2\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn3\" class=\"footnote-item\"><p>Roy Rosenzweig, &quot;Scarcity or Abundance? Preserving the Past in a Digital Era,&quot; American Historical Review 108, no. 3 (June 2003): 735–762, https://rrchnm.org/essays/scarcity-or-abundance-preserving-the-past-in-a-digital-era/ <a href=\"#fnref3\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn4\" class=\"footnote-item\"><p>Zotero, &quot;About,&quot; Corporation for Digital Scholarship, accessed July 14, 2026, https://www.zotero.org/about/ <a href=\"#fnref4\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn5\" class=\"footnote-item\"><p>Tropy, homepage, accessed July 14, 2026, https://tropy.org/ <a href=\"#fnref5\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn6\" class=\"footnote-item\"><p>Omeka, &quot;Project,&quot; Digital Scholar, accessed July 14, 2026, https://omeka.org/about/project/ <a href=\"#fnref6\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn7\" class=\"footnote-item\"><p>PressForward, homepage, accessed July 14, 2026, https://pressforward.org/ <a href=\"#fnref7\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn8\" class=\"footnote-item\"><p>Roy Rosenzweig Center for History and New Media, &quot;RRCHNM: Past, Present, and Future,&quot; accessed July 14, 2026, https://rrchnm.org/about-rrchnm/rrchnm-past-present-and-future/ <a href=\"#fnref8\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn9\" class=\"footnote-item\"><p>Zotero, &quot;About,&quot; Corporation for Digital Scholarship, accessed July 14, 2026, https://www.zotero.org/about/ <a href=\"#fnref9\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn10\" class=\"footnote-item\"><p>Wikipedia, &quot;Zotero,&quot; accessed July 14, 2026, https://en.wikipedia.org/wiki/Zotero <a href=\"#fnref10\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn11\" class=\"footnote-item\"><p>Zotero, &quot;Citation Styles,&quot; Zotero Documentation, accessed July 14, 2026, https://www.zotero.org/support/styles <a href=\"#fnref11\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn12\" class=\"footnote-item\"><p>Tropy, homepage, accessed July 14, 2026, https://tropy.org/ <a href=\"#fnref12\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn13\" class=\"footnote-item\"><p>Tropy, homepage, accessed July 14, 2026, https://tropy.org/ <a href=\"#fnref13\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn14\" class=\"footnote-item\"><p>Daniel van Strien, &quot;An Introduction to Version Control Using GitHub Desktop,&quot; The Programming Historian, June 17, 2016 (retired lesson), https://programminghistorian.org/en/lessons/retired/getting-started-with-github-desktop <a href=\"#fnref14\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn15\" class=\"footnote-item\"><p>OpenRefine, homepage, accessed July 14, 2026, https://openrefine.org/ <a href=\"#fnref15\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn16\" class=\"footnote-item\"><p>Voyant Tools, &quot;About,&quot; Stéfan Sinclair and Geoffrey Rockwell, accessed July 14, 2026, https://voyant-tools.org/docs/tutorial-about.html <a href=\"#fnref16\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn17\" class=\"footnote-item\"><p>Geoffrey Rockwell and Stéfan Sinclair, Hermeneutica: Computer-Assisted Interpretation in the Humanities (Cambridge, MA: MIT Press, 2016), https://mitpress.mit.edu/books/hermeneutica <a href=\"#fnref17\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn18\" class=\"footnote-item\"><p>Laurence Anthony, &quot;AntConc,&quot; Laurence Anthony's Website, accessed July 14, 2026, https://www.laurenceanthony.net/software/antconc/ <a href=\"#fnref18\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn19\" class=\"footnote-item\"><p>QGIS, homepage, QGIS.org, accessed July 14, 2026, https://qgis.org/ <a href=\"#fnref19\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn20\" class=\"footnote-item\"><p>Gephi, homepage, accessed July 14, 2026, https://gephi.org/ <a href=\"#fnref20\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn21\" class=\"footnote-item\"><p>Humanities + Design, &quot;Palladio,&quot; Stanford University, accessed July 14, 2026, https://hdlab.stanford.edu/palladio/ <a href=\"#fnref21\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn22\" class=\"footnote-item\"><p>Recogito, homepage, Pelagios Commons, accessed July 14, 2026, https://recogito.pelagios.org/ <a href=\"#fnref22\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn23\" class=\"footnote-item\"><p>Transkribus, homepage, READ-COOP SCE, accessed July 14, 2026, https://www.transkribus.org/ <a href=\"#fnref23\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn24\" class=\"footnote-item\"><p>Knight Lab, &quot;About,&quot; Northwestern University, accessed July 14, 2026, https://knightlab.northwestern.edu/about/ <a href=\"#fnref24\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn25\" class=\"footnote-item\"><p>Knight Lab, &quot;TimelineJS,&quot; Northwestern University, accessed July 14, 2026, https://timeline.knightlab.com/ <a href=\"#fnref25\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn26\" class=\"footnote-item\"><p>Knight Lab, &quot;StoryMapJS,&quot; Northwestern University, accessed July 14, 2026, https://storymap.knightlab.com/ <a href=\"#fnref26\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn27\" class=\"footnote-item\"><p>Knight Lab, &quot;JuxtaposeJS,&quot; Northwestern University, accessed July 14, 2026, https://juxtapose.knightlab.com/ <a href=\"#fnref27\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn28\" class=\"footnote-item\"><p>Knight Lab, &quot;SoundCite,&quot; Northwestern University, accessed July 14, 2026, https://soundcite.knightlab.com/ <a href=\"#fnref28\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn29\" class=\"footnote-item\"><p>Roy Rosenzweig Center for History and New Media, &quot;Our People,&quot; accessed July 14, 2026, https://rrchnm.org/our-people/ and George Mason University Department of History and Art History, &quot;Lincoln Mullen,&quot; accessed July 14, 2026, https://historyarthistory.gmu.edu/people/lmullen <a href=\"#fnref29\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn30\" class=\"footnote-item\"><p>Lincoln A. Mullen, The Chance of Salvation: A History of Conversion in America (Cambridge, MA: Harvard University Press, 2017), https://www.hup.harvard.edu/books/9780674975620 <a href=\"#fnref30\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn31\" class=\"footnote-item\"><p>Lincoln A. Mullen, America's Public Bible: A Commentary (Stanford, CA: Stanford University Press, 2023), https://americaspublicbible.supdigital.org/ <a href=\"#fnref31\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn32\" class=\"footnote-item\"><p>Lincoln Mullen, &quot;textreuse: Detect Text Reuse and Document Similarity,&quot; rOpenSci, accessed July 14, 2026, https://docs.ropensci.org/textreuse/ <a href=\"#fnref32\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn33\" class=\"footnote-item\"><p>Lincoln Mullen, &quot;USAboundaries: Historical and Contemporary Boundaries of the United States of America,&quot; accessed July 14, 2026, https://lincolnmullen.com/software/usaboundaries/ <a href=\"#fnref33\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn34\" class=\"footnote-item\"><p>Lincoln A. Mullen, Computational Historical Thinking: With Applications in R (open web book, 2018–), accessed July 14, 2026, https://dh-r.lincolnmullen.com/introduction.html <a href=\"#fnref34\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn35\" class=\"footnote-item\"><p>Lincoln Mullen, &quot;Isn't It Obvious?,&quot; lincolnmullen.com, January 10, 2018, https://lincolnmullen.com/blog/isnt-it-obvious/ <a href=\"#fnref35\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn36\" class=\"footnote-item\"><p>The Programming Historian, &quot;About,&quot; accessed July 14, 2026, https://programminghistorian.org/en/about <a href=\"#fnref36\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn37\" class=\"footnote-item\"><p>The Programming Historian, &quot;About,&quot; accessed July 14, 2026, https://programminghistorian.org/en/about <a href=\"#fnref37\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn38\" class=\"footnote-item\"><p>Omeka, &quot;Project,&quot; Digital Scholar, accessed July 14, 2026, https://omeka.org/about/project/ <a href=\"#fnref38\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn39\" class=\"footnote-item\"><p>Omeka, &quot;Project,&quot; Digital Scholar, accessed July 14, 2026, https://omeka.org/about/project/ <a href=\"#fnref39\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref39:1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn40\" class=\"footnote-item\"><p>Alliance for Networking Visual Culture, &quot;About Scalar,&quot; University of Southern California, accessed July 14, 2026, https://scalar.me/anvc/ <a href=\"#fnref40\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn41\" class=\"footnote-item\"><p>PressForward, homepage, accessed July 14, 2026, https://pressforward.org/ <a href=\"#fnref41\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn42\" class=\"footnote-item\"><p>Zenodo, &quot;About,&quot; CERN and OpenAIRE, accessed July 14, 2026, https://about.zenodo.org/ <a href=\"#fnref42\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn43\" class=\"footnote-item\"><p>Harvard Dataverse, homepage, accessed July 14, 2026, https://dataverse.harvard.edu/ <a href=\"#fnref43\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn44\" class=\"footnote-item\"><p>Knowledge Commons, &quot;Funding,&quot; About Knowledge Commons, accessed July 14, 2026, https://about.hcommons.org/about-us/funding/ <a href=\"#fnref44\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn45\" class=\"footnote-item\"><p>MLA Commons, &quot;Introduction to CORE,&quot; Help and Support, accessed July 14, 2026, https://support.mla.hcommons.org/getting-started/core/ and Knowledge Commons, &quot;What Is a Repository For?,&quot; About Knowledge Commons, September 26, 2023, https://about.hcommons.org/2023/09/26/what-is-a-repository-for/ <a href=\"#fnref45\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn46\" class=\"footnote-item\"><p>MLA Commons, &quot;Introduction to CORE,&quot; Help and Support, accessed July 14, 2026, https://support.mla.hcommons.org/getting-started/core/ <a href=\"#fnref46\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n</ol>\n</section>\n",
			"date_published": "2026-07-14T08:16:32Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/dh-part-1-what-are-the-digital-humanities/",
			"url": "https://www.adamdjbrett.com/blog/dh-part-1-what-are-the-digital-humanities/",
			"title": "Digital Humanities Part 1: What Are the Digital Humanities?",
			"content_html": "<p>Ask ten digital humanists what the digital humanities are and you will get at least eleven answers. There is even a website that proves it. Jason Heppler's whatisdigitalhumanities.com serves up a different scholar's definition every time you refresh the page, drawn from hundreds of self-descriptions collected during the annual Day of DH project.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1\">[1]</a></sup> Heppler built it partly as a joke and partly as an argument. The definition really is that broad, and as he put it, &quot;time spent on definitions is better spent on moving projects forward.&quot;<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:1\">[1:1]</a></sup></p>\n<p>He has a point, and I will spend most of this series on projects rather than definitions. But if you are a humanities scholar or a graduate student encountering the field for the first time, you deserve a better starting place than a slot machine of quotations. So here is the working definition I will use throughout this series. Digital humanities are a contested ensemble of methods, infrastructures, pedagogies, institutions, and critical practices through which humanists create, preserve, model, analyze, publish, and critique cultural evidence in digital forms.</p>\n<p>Every word in that sentence is doing work, and most of this essay unpacks it. &quot;Contested&quot; because the field has argued about its own boundaries for decades, and those arguments are themselves part of the field. &quot;Ensemble&quot; because no single method or tool defines it. &quot;Cultural evidence&quot; because the objects of humanistic study, whether a medieval manuscript, a nineteenth-century sermon, a bundle of letters, or an archaeological site, are what the whole apparatus exists to serve. And &quot;in digital forms&quot; because the heart of the matter is transformation. A manuscript becomes an image. A sermon becomes machine-readable text. A correspondence becomes a network. A landscape becomes a map layer. Digital humanities is the study of what happens in those transformations, what they make possible, and what they put at risk.</p>\n<p>This is the first essay in a six-part series. In this one I want to answer the title question four ways: through the field's history, through its definition debates, through a fourfold account of what the field is (methods, institutions, pedagogy, and critique), and through concrete projects you can visit right now. By the end you should be able to recognize digital humanities work when you see it, and you should understand why the people who do it keep arguing about what to call it.</p>\n<h2 id=\"a-priest-a-punched-card-machine-and-eleven-million-words\" tabindex=\"-1\">A Priest, a Punched-Card Machine, and Eleven Million Words <a class=\"header-anchor\" href=\"#a-priest-a-punched-card-machine-and-eleven-million-words\">#</a></h2>\n<p>Every field tells itself an origin story, and the digital humanities origin story begins with a Jesuit priest. In 1946 Father Roberto Busa, an Italian scholar of Thomas Aquinas, conceived a project that was plainly impossible by hand: a complete lemmatized concordance of the works of Aquinas and related authors, roughly eleven million words of medieval Latin.<sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2\">[2]</a></sup> A concordance indexes every occurrence of every word. Lemmatization groups those occurrences under their dictionary headwords, so that <em>dicit</em>, <em>dixit</em>, and <em>dicere</em> all resolve to the same verb. Scholars had compiled concordances for centuries, but only for single books, and usually as lifelong labors. Busa wanted one for an entire corpus.</p>\n<p>In 1949 he sailed to New York and talked his way into a meeting with Thomas J. Watson, the head of IBM. Watson was skeptical. Busa persisted, and IBM agreed to sponsor the work.<sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2:1\">[2:1]</a></sup> What followed was one of the longest-running research projects in the history of the humanities. Punched-card machines gave way to magnetic tape and then to mainframe computing. The first printed volume of the <em>Index Thomisticus</em> appeared in 1974, the fifty-sixth and final volume in 1980, a CD-ROM edition in 1992, and a web edition in 2005.<sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3\">[3]</a></sup> The project outlived the technologies it started on, which is a lesson this series will return to more than once.</p>\n<p>Two things about Busa's project matter beyond its scale. The first is that Busa understood what he was doing as more than indexing. He later defined the enterprise that grew from it as &quot;the automation of every possible analysis of human expression.&quot;<sup class=\"footnote-ref\"><a href=\"#fn4\" id=\"fnref4\">[4]</a></sup> That is a startlingly ambitious sentence for a man working with punched cards, and it describes much of what came after, from stylometry to topic modeling to the large language models of our own moment.</p>\n<p>The second is that Busa did not do the work alone, and the people who did most of it were left out of the story for sixty years. Melissa Terras and Julianne Nyhan have reconstructed the history of the young Italian women who keypunched the corpus, trained in a school Busa established, working eight-hour days at machines. By the accounts Terras and Nyhan gathered, Busa chose women who did not know Latin &quot;because the quality of their work was higher.&quot;<sup class=\"footnote-ref\"><a href=\"#fn5\" id=\"fnref5\">[5]</a></sup> Their names went unrecorded. As Terras and Nyhan write, &quot;Busa certainly depended on their input, and our work is to write them back into the historical record.&quot;<sup class=\"footnote-ref\"><a href=\"#fn5\" id=\"fnref5:1\">[5:1]</a></sup> I start with this not to diminish Busa but because it prefigures a theme that runs through the whole field. Digital projects rest on enormous amounts of labor, much of it invisible, much of it done by people who never appear on the title page. A field that studies infrastructure has learned, slowly, to study its own.</p>\n<p>For a fuller account of the field's emergence, Steven E. Jones has written the standard scholarly treatment of Busa's project, and his earlier book <em>The Emergence of the Digital Humanities</em> traces how the field took its present shape in the years around 2004 to 2008, a period he describes through William Gibson's image of cyberspace &quot;everting,&quot; turning inside out and spilling into the physical world.<sup class=\"footnote-ref\"><a href=\"#fn6\" id=\"fnref6\">[6]</a></sup></p>\n<h2 id=\"from-humanities-computing-to-digital-humanities\" tabindex=\"-1\">From Humanities Computing to Digital Humanities <a class=\"header-anchor\" href=\"#from-humanities-computing-to-digital-humanities\">#</a></h2>\n<p>For half a century the field that grew from Busa's project called itself &quot;humanities computing.&quot; It had journals, conferences, and professional societies. The Association for Literary and Linguistic Computing was founded in 1973, and the Association for Computers and the Humanities followed in 1978.<sup class=\"footnote-ref\"><a href=\"#fn7\" id=\"fnref7\">[7]</a></sup> Humanities computing scholars built concordances and critical editions, developed text-encoding standards, and worked out the foundations of computational stylistics. The Text Encoding Initiative, founded in 1987 at a meeting at Vassar College, set out &quot;to develop, maintain, and promulgate hardware- and software-independent methods for encoding humanities data in electronic form,&quot; and TEI encoding remains the backbone of serious digital editions today.<sup class=\"footnote-ref\"><a href=\"#fn8\" id=\"fnref8\">[8]</a></sup></p>\n<p>Then, in the early 2000s, the name changed, and that change mattered more than anyone expected.</p>\n<p>The immediate occasion was a book. Susan Schreibman, Ray Siemens, and John Unsworth were editing a Blackwell anthology surveying the field, and the title they landed on was <em>A Companion to Digital Humanities</em> rather than <em>A Companion to Humanities Computing</em>. Published in 2004, the Companion defined the enterprise as &quot;using information technology to illuminate the human record, and bringing an understanding of the human record to bear on the development and use of information technology.&quot;<sup class=\"footnote-ref\"><a href=\"#fn4\" id=\"fnref4:1\">[4:1]</a></sup> The professional societies followed. When the existing organizations formed an umbrella alliance, approved in 2005, they named it the Alliance of Digital Humanities Organizations, and the 2006 conference was the first formally designated &quot;Digital Humanities.&quot;<sup class=\"footnote-ref\"><a href=\"#fn7\" id=\"fnref7:1\">[7:1]</a></sup> Then the funders followed. In 2008 the National Endowment for the Humanities elevated its digital initiative into a permanent Office of Digital Humanities, with Brett Bobley as its inaugural director. The office funded nearly five hundred projects in its first decade, and Bobley described its purpose plainly: &quot;We're building the digital infrastructure that is necessary for humanities research, preservation, and public programs.&quot;<sup class=\"footnote-ref\"><a href=\"#fn9\" id=\"fnref9\">[9]</a></sup></p>\n<p>Why did a rebranding matter? Patrik Svensson gave the most careful answer in a pair of studies of the field's discourse. The shift from &quot;humanities computing&quot; to &quot;digital humanities&quot; was not just cosmetic, he argued. It carried &quot;a set of epistemic commitments&quot; about what the field could contain.<sup class=\"footnote-ref\"><a href=\"#fn10\" id=\"fnref10\">[10]</a></sup> &quot;Humanities computing&quot; named a methodological specialty, computing applied to humanities materials. &quot;Digital humanities&quot; named something wider and vaguer, and the vagueness was productive. A broadly conceived digital humanities, Svensson wrote, &quot;would necessarily include the instrumental, methodological, textual and digitalized, but also new study objects, multiple modes of engagement, theoretical issues from the humanities disciplines, the non-textual and the born digital.&quot;<sup class=\"footnote-ref\"><a href=\"#fn10\" id=\"fnref10:1\">[10:1]</a></sup> Under the new name, a scholar studying video game narratives, a librarian digitizing plantation records, a historian mapping census data, and a programmer building annotation software could all plausibly claim the same label.</p>\n<p>The label spread fast. By 2011 William Pannapacker could write in the Chronicle of Higher Education that after &quot;generations of relatively quiet progress—going back to the era of punch cards—the digital humanities has exploded into academic consciousness as the Next Big Thing.&quot;<sup class=\"footnote-ref\"><a href=\"#fn11\" id=\"fnref11\">[11]</a></sup> The annual conference that year was literally titled &quot;Big Tent Digital Humanities.&quot; Hype of that kind always invites a backlash, and the backlash duly arrived. But before we get to the arguments, it is worth pausing on why a field would argue about its own name at all.</p>\n<h2 id=\"the-definition-debates-and-why-they-matter\" tabindex=\"-1\">The Definition Debates and Why They Matter <a class=\"header-anchor\" href=\"#the-definition-debates-and-why-they-matter\">#</a></h2>\n<p>You might reasonably suspect that definitional debates are the least interesting thing about any field, the academic equivalent of a committee arguing about its charter. In the digital humanities the opposite is true. The definition debates are one of the best entry points into the field, because each major intervention reveals something real about how the field works. Three deserve your attention, and all three are freely readable online.</p>\n<p>Start with Matthew Kirschenbaum's 2010 essay &quot;What Is Digital Humanities and What's It Doing in English Departments?&quot;, probably the most-cited answer to the title question ever written.<sup class=\"footnote-ref\"><a href=\"#fn12\" id=\"fnref12\">[12]</a></sup> Kirschenbaum's move was to refuse the philosophical question and answer a sociological one instead. Digital humanities, he argued, is not defined by a doctrine but by an infrastructure: journals, conferences, funding programs, degree requirements, hiring lines, and above all a social network of practitioners. &quot;DH is 'here,'&quot; he wrote in the discussion that followed the essay on his blog, &quot;because of people and conversations and a lot of hard work on listservs and over meals at conferences.&quot;<sup class=\"footnote-ref\"><a href=\"#fn12\" id=\"fnref12:1\">[12:1]</a></sup> Two years later he sharpened the point in an essay whose title is its thesis: &quot;Digital Humanities As/Is a Tactical Term.&quot; The term digital humanities, he argued there, is deployed &quot;to get things done,&quot; things like funding a staff position or establishing a curriculum, and attempts at definitive definitions &quot;are often self-defeating, not only because they are sometimes divisive, but also because they risk effacing the material history of the term.&quot;<sup class=\"footnote-ref\"><a href=\"#fn13\" id=\"fnref13\">[13]</a></sup> DH, he concluded, &quot;is a means and not an end.&quot;<sup class=\"footnote-ref\"><a href=\"#fn13\" id=\"fnref13:1\">[13:1]</a></sup></p>\n<p>Rafael Alvarado pushed the sociological reading to its logical conclusion. &quot;There is no definition of digital humanities,&quot; he wrote, &quot;if by definition we mean a consistent set of theoretical concerns and research methods.&quot; The field is &quot;a social category, not an ontological one.&quot; Digital humanists &quot;are simply humanists (or interpretive social scientists) by training who have embraced digital media.&quot; What holds them together, in his account, is not a method but a shared fascination, &quot;the ongoing, playful encounter with digital representation itself.&quot;<sup class=\"footnote-ref\"><a href=\"#fn14\" id=\"fnref14\">[14]</a></sup></p>\n<p>If the field is a social category, then the interesting question becomes who belongs to it, and that question produced the sharpest fight in the field's history. At the 2011 Modern Language Association convention, Stephen Ramsay stood up on a panel and said that digital humanists build things, and that &quot;if you are not making anything, you are not... a digital humanist.&quot;<sup class=\"footnote-ref\"><a href=\"#fn15\" id=\"fnref15\">[15]</a></sup> The room, and then the blogosphere, erupted. Ramsay had drawn a line through the big tent: coders and builders on one side, everyone who merely wrote <em>about</em> the digital on the other. Mark Sample's response gave the counter-position its slogan in its very title: &quot;The digital humanities is not about building, it's about sharing.&quot;<sup class=\"footnote-ref\"><a href=\"#fn15\" id=\"fnref15:1\">[15:1]</a></sup> The argument became known as &quot;hack versus yack,&quot; making versus talking, and versions of it still surface whenever someone asks whether you need to know how to program to be a digital humanist. (For what it is worth, my answer is no, but you need to understand what programming makes possible, which is a different and more reasonable demand.)</p>\n<p>Lisa Spiro offered the most constructive way out. If the field cannot agree on a definition, she argued in &quot;This Is Why We Fight,&quot; it can agree on values. Her proposed list included openness, &quot;a commitment to the open exchange of ideas, the development of open content and software, and transparency,&quot; along with collaboration, collegiality, diversity, and experimentation.<sup class=\"footnote-ref\"><a href=\"#fn16\" id=\"fnref16\">[16]</a></sup> Spiro's essay reads today as remarkably prescient. The parts of the field that have flourished, the open-source tools, the open-access publications, the freely shared datasets and lessons, are precisely the parts her values statement predicted would define it.</p>\n<p>These debates were significant enough that an entire anthology was assembled to document them. <em>Defining Digital Humanities: A Reader</em>, edited by Melissa Terras, Julianne Nyhan, and Edward Vanhoutte, collects the landmark essays, including several I have quoted here, and is the single best place to read the argument whole.<sup class=\"footnote-ref\"><a href=\"#fn17\" id=\"fnref17\">[17]</a></sup> And the <em>Debates in the Digital Humanities</em> series, edited by Matthew K. Gold and Lauren F. Klein, has continued taking the field's temperature every few years, with the 2023 volume examining a field now old enough to have its own institutional midlife questions.<sup class=\"footnote-ref\"><a href=\"#fn18\" id=\"fnref18\">[18]</a></sup></p>\n<p>Why should you care about any of this if you just want to make a map or mine a corpus? Because the definition debates settled, in practice, three things that shape any project you might undertake. They settled that the field would be a big tent, which means you do not need anyone's permission or credential to start. They settled that the field's currency would be openness, which means an extraordinary amount of its infrastructure is free for you to use. And they settled that the term itself is tactical, which means when your dean or your funding agency asks what digital humanities is, the honest answer is that it is the name under which resources flow to this kind of work. That is not cynicism. That is how fields function, and the digital humanities is unusual mainly in being honest about it.</p>\n<h2 id=\"transformations-not-tools\" tabindex=\"-1\">Transformations, Not Tools <a class=\"header-anchor\" href=\"#transformations-not-tools\">#</a></h2>\n<p>Here is the misunderstanding I most want to head off. When people first hear about the digital humanities, they usually assume it is about tools. Learn this software, install that platform, and you are doing DH. Tool lists have their place, and Part 2 of this series is full of them. But defining the field by its tools is like defining history by its filing cabinets. Tools change constantly. What persists is the thing the tools are for.</p>\n<p>What the digital humanities actually study, and actually produce, are transformations of cultural evidence from one form to another. Consider four examples that will recur throughout this series.</p>\n<p>A manuscript becomes an image. That sounds trivial until you think about what is gained and lost. The digital photograph travels anywhere and serves thousands of readers at once, where the vellum served one reader in one room. But the photograph flattens texture, hides watermarks, crops margins, and silently substitutes one lighting condition for the infinite variability of the object. Digitization is interpretation. Every choice about resolution, color calibration, and page sequence is an editorial decision, and scholars who use digitized sources without understanding those decisions are reading an edition while believing they read an original.</p>\n<p>A sermon becomes machine-readable text. Optical character recognition turns a page image into searchable characters, and suddenly you can find every sermon in a million-page newspaper archive that quotes a particular verse. But OCR errs, and it errs unevenly. It reads clean modern print far better than blackletter, damaged pages, or non-Latin scripts, so the searchable archive silently overrepresents some sources and eras. The transformation enables research at a scale no human reading could achieve, while embedding biases no human reader would accept without notice.</p>\n<p>A correspondence becomes a network. Take the letters of an eighteenth-century intellectual, record who wrote to whom, when, and from where, and you can draw the Republic of Letters as a graph, as Stanford's Mapping the Republic of Letters project did for the correspondence of Voltaire, Franklin, and their contemporaries.<sup class=\"footnote-ref\"><a href=\"#fn19\" id=\"fnref19\">[19]</a></sup> The network shows structures no single letter reveals, the brokers and bridges and clusters of an intellectual world. It also reduces friendship, patronage, rivalry, and love to identical edges in a diagram. The model illuminates precisely because it simplifies, and the researcher's job is to keep both halves of that sentence in view.</p>\n<p>A place becomes a map layer. Historical gazetteers, georeferenced census data, and archaeological site records let you ask spatial questions that were previously matters of impression. Which counties had the most congregations per capita in 1926? How far did a circuit rider actually travel? The map answers, and in answering it imposes modern coordinate systems, modern boundaries, and a false precision on sources that were often vague, contradictory, or lost.</p>\n<p>Notice the pattern. In each case the transformation creates new scholarly possibilities and new scholarly obligations at the same moment. That doubled character is, to my mind, the intellectual core of the field. The digital humanities is not the cheerleading squad for digitization. It is the discipline that understands digitization deeply enough to use it and to criticize it in one breath. Johanna Drucker's <em>The Digital Humanities Coursebook</em>, the best single textbook introduction to the field's methods, makes this point on nearly every page: data are not given, they are made, and every stage of making involves decisions a scholar must be able to defend.<sup class=\"footnote-ref\"><a href=\"#fn20\" id=\"fnref20\">[20]</a></sup></p>\n<h2 id=\"what-the-work-actually-looks-like\" tabindex=\"-1\">What the Work Actually Looks Like <a class=\"header-anchor\" href=\"#what-the-work-actually-looks-like\">#</a></h2>\n<p>Definitions only take you so far. The fastest way to understand the digital humanities is to look at actual projects, so let me show you some, starting with the scholar whose work I recommend more often than anyone else's.</p>\n<p>Lincoln Mullen is a historian of American religion at George Mason University and the director of the Roy Rosenzweig Center for History and New Media.<sup class=\"footnote-ref\"><a href=\"#fn21\" id=\"fnref21\">[21]</a></sup> He describes himself as &quot;a historian of American religion and the nineteenth-century United States, often using computational methods for texts and maps,&quot; and that unassuming sentence covers some of the most impressive computational history I know of.<sup class=\"footnote-ref\"><a href=\"#fn21\" id=\"fnref21:1\">[21:1]</a></sup></p>\n<p>His project <em>America's Public Bible</em> is the exemplar I hand to every skeptic. Mullen wrote software to detect biblical quotations in the millions of newspaper pages digitized by the Library of Congress's Chronicling America program, then built an interactive scholarly work that, in its own words, &quot;uncovers the history of the Bible in the nineteenth- and early twentieth-century United States.&quot;<sup class=\"footnote-ref\"><a href=\"#fn22\" id=\"fnref22\">[22]</a></sup> You can watch the rise and fall of individual verses in American public discourse across a century and a half, then click through to read any verse in its original newspaper context. The project won first prize in the NEH's Chronicling America Data Challenge in 2016, and Stanford University Press published the full version in 2023 as a peer-reviewed digital monograph, one of the clearest signals yet that interactive scholarship can carry the same weight as a printed book.<sup class=\"footnote-ref\"><a href=\"#fn23\" id=\"fnref23\">[23]</a></sup> The NEH's own description captures why the method matters: the tracked quotations reveal &quot;trends that are inaccessible to a single scholar's reading of these documents, yet enabling a close reading of the ways in which specific verses were put to use.&quot;<sup class=\"footnote-ref\"><a href=\"#fn23\" id=\"fnref23:1\">[23:1]</a></sup> Distant reading and close reading, in other words, are not opponents. The computation finds the passages worth reading closely.</p>\n<p>Mullen's current large project, <em>American Religious Ecologies</em>, is digitizing the surviving schedules of the 1926 Census of Religious Bodies, the remarkable congregation-by-congregation survey the federal government once conducted. The team has digitized more than 227,000 schedules covering 217 denominations across 3,091 counties, creating a dataset that documents, as the project puts it, the &quot;complex interactions between different faith traditions, institutions, and practices that together form the religious landscape of American places.&quot;<sup class=\"footnote-ref\"><a href=\"#fn24\" id=\"fnref24\">[24]</a></sup> If you study American religion, this is primary-source infrastructure being built for you right now, in public, with the data openly available.</p>\n<p>Two more things about Mullen repay attention. First, he works in the open. His code is on GitHub for anyone to inspect and reuse, including an R package for detecting text reuse that other scholars have applied to entirely different corpora.<sup class=\"footnote-ref\"><a href=\"#fn25\" id=\"fnref25\">[25]</a></sup> Second, he thinks hard about how computational work should be written. His essay &quot;A Braided Narrative for Digital History&quot; argues that digital historians have been better at methods than at prose, that &quot;digital history trades in methods more than most other forms of history,&quot; and that the field needs ways of weaving argument and method together rather than hiding one behind the other.<sup class=\"footnote-ref\"><a href=\"#fn26\" id=\"fnref26\">[26]</a></sup> He is also a first-rate historian by conventional measures. His book <em>The Chance of Salvation</em> argued that nineteenth-century America turned religion into &quot;a system of competing options that created an obligation for more and more Americans to choose their own faith.&quot;<sup class=\"footnote-ref\"><a href=\"#fn27\" id=\"fnref27\">[27]</a></sup> The computational work and the interpretive work reinforce each other, which is exactly the combination this field promises and too rarely delivers.</p>\n<p>The institution Mullen directs deserves its own introduction, because you have almost certainly used its software without knowing it. The Roy Rosenzweig Center for History and New Media, founded at George Mason in 1994 by the historian it is now named for, has spent three decades pursuing Rosenzweig's mission &quot;to use digital media and computer technology to democratize history.&quot;<sup class=\"footnote-ref\"><a href=\"#fn28\" id=\"fnref28\">[28]</a></sup> Democratize is a word that usually makes me reach for my wallet, but RRCHNM has earned it. Consider what the center and the nonprofit that grew from it have shipped. Zotero, the free, open-source reference manager that began at RRCHNM in 2006, may be the single most widely used piece of scholarly software in the humanities, and it remains free with, as the project pointedly notes, &quot;no financial interest in your private information.&quot;<sup class=\"footnote-ref\"><a href=\"#fn29\" id=\"fnref29\">[29]</a></sup> Omeka is &quot;a free, flexible, and open source web-publishing platform for the display of library, museum, archives, and scholarly collections and exhibitions,&quot; and it powers digital exhibits at institutions from small historical societies to major universities.<sup class=\"footnote-ref\"><a href=\"#fn30\" id=\"fnref30\">[30]</a></sup> Tropy solves the unglamorous problem every archival researcher has, the thousands of photographs of documents on your phone, by letting you &quot;organize and describe photographs of research material.&quot;<sup class=\"footnote-ref\"><a href=\"#fn31\" id=\"fnref31\">[31]</a></sup> PressForward turned WordPress into a scholarly publishing pipeline for aggregating and curating gray literature.<sup class=\"footnote-ref\"><a href=\"#fn32\" id=\"fnref32\">[32]</a></sup> And the center's September 11 Digital Archive, which collected tens of thousands of firsthand accounts and digital artifacts of the 2001 attacks, became in 2003 the first major digital acquisition accepted into the Library of Congress's permanent collections.<sup class=\"footnote-ref\"><a href=\"#fn33\" id=\"fnref33\">[33]</a></sup></p>\n<p>Consider what that list is. It is not a list of publications about the digital humanities. It is infrastructure, freely given, that changed how ordinary scholars work. When people ask me why the digital humanities deserves institutional support, RRCHNM is my first answer. Decades of patient, unglamorous, public-spirited building, and every scholar with a Zotero library is a beneficiary.</p>\n<p>Beyond Mason, a handful of canonical projects will give you a feel for the field's range. The Walt Whitman Archive has spent decades making &quot;Whitman's vast work, for the first time, easily and conveniently accessible to scholars, students, and general readers,&quot; including all six editions of <em>Leaves of Grass</em> with manuscripts and correspondence.<sup class=\"footnote-ref\"><a href=\"#fn34\" id=\"fnref34\">[34]</a></sup> The Valley of the Shadow, launched at the University of Virginia in 1993 under Edward Ayers and William G. Thomas III, followed two communities, one Confederate and one Union, through the Civil War via digitized newspapers, letters, and records, and stands as one of the earliest demonstrations that a digital archive could make an argument.<sup class=\"footnote-ref\"><a href=\"#fn35\" id=\"fnref35\">[35]</a></sup> The Old Bailey Online published the proceedings of London's central criminal court from 1674 to 1913, some 197,000 trials and 127 million words, which its creators fairly call &quot;the largest single source of information about non-elite lives and behaviour ever published.&quot;<sup class=\"footnote-ref\"><a href=\"#fn36\" id=\"fnref36\">[36]</a></sup> And Voyant Tools, created by Stéfan Sinclair and Geoffrey Rockwell, lets you paste in any text and explore word frequencies, trends, and contexts in your browser, which makes it the easiest possible first step if you want to try text analysis in the next five minutes.<sup class=\"footnote-ref\"><a href=\"#fn37\" id=\"fnref37\">[37]</a></sup></p>\n<p>If you work in theology or religious studies, as I do, you may have noticed how many of these examples touch our field. A Jesuit priest and the corpus of Aquinas at the origin. The Bible in American newspapers. A federal census of congregations. That is not an accident of my selection. Religious studies works with exactly the kinds of evidence that digital transformation rewards and complicates: vast textual corpora in many languages, long manuscript traditions, institutional records scattered across denominational archives, and communities whose practices leave uneven documentary traces. The field has also been present since before the beginning. Busa's project predates the computer science department. Part 3 of this series will map this territory properly, from digitized scriptural corpora to the ethics of computing on sacred texts. For now the point is simpler. Whatever your subfield, somebody has probably already transformed sources you care about into digital forms, and the quality of your work will partly depend on understanding what that transformation did to them.</p>\n<h2 id=\"four-answers-at-once-methods-institutions-pedagogy-critique\" tabindex=\"-1\">Four Answers at Once: Methods, Institutions, Pedagogy, Critique <a class=\"header-anchor\" href=\"#four-answers-at-once-methods-institutions-pedagogy-critique\">#</a></h2>\n<p>By now you can see why single-sentence definitions fail. The field is at least four things simultaneously, and any honest introduction has to hold all four in view.</p>\n<p>Digital humanities is a set of methods. Text analysis, network analysis, mapping and spatial history, digital editing and scholarly encoding, image analysis, 3D modeling, data visualization, and the curation and management of research data. David M. Berry and Anders Fagerjord's <em>Digital Humanities: Knowledge and Critique in a Digital Age</em> offers a clear survey of this methodological terrain and, importantly, insists on treating knowledge and critique as a single package rather than opposites.<sup class=\"footnote-ref\"><a href=\"#fn38\" id=\"fnref38\">[38]</a></sup> The methods are real and learnable, and Part 2 of this series will walk through the ones most useful for dissertation writers. But methods alone do not make a field. Statistics departments do not own every discipline that uses regression.</p>\n<p>Digital humanities is a set of institutions. Centers like RRCHNM and MATRIX, professional bodies like the Alliance of Digital Humanities Organizations, funders like the NEH's Office of Digital Humanities, journals like <em>Digital Humanities Quarterly</em>, conferences, degree programs, and library units. Kirschenbaum's sociological point stands: the institutions are not an accident of the field, they are a large part of what the field is. When you ask whether your university &quot;has&quot; digital humanities, you are asking an institutional question, about lines, labs, and support, not a philosophical one.</p>\n<p>Digital humanities is a pedagogy. This is the dimension outsiders most often miss. A large fraction of DH energy goes into teaching, and into rethinking what humanities teaching can be when students build projects rather than only writing papers. Brian Croxall and Diane Jakacki's collection <em>What We Teach When We Teach DH</em> gathers the field's hard-won classroom wisdom.<sup class=\"footnote-ref\"><a href=\"#fn39\" id=\"fnref39\">[39]</a></sup> And the field has built open teaching infrastructure with few parallels elsewhere in the academy. The Programming Historian, founded in 2008, publishes rigorously peer-reviewed lessons on computational methods for humanists, free to everyone, now in English, Spanish, French, and Portuguese, on the principle that &quot;everyone should be able to benefit from these tutorials, not just those with large research budgets for expensive proprietary software.&quot;<sup class=\"footnote-ref\"><a href=\"#fn40\" id=\"fnref40\">[40]</a></sup> If you want to learn a method this field uses, someone has probably written you a free, refereed lesson on it.</p>\n<p>And digital humanities is a critique. From early on, a strand of the field has studied the digital rather than simply using it, asking what computation does to knowledge itself. David M. Berry's collection <em>Understanding Digital Humanities</em> framed this agenda over a decade ago, asking how the computational turn changes the conditions under which humanities knowledge gets made.<sup class=\"footnote-ref\"><a href=\"#fn41\" id=\"fnref41\">[41]</a></sup> James E. Dobson's <em>Critical Digital Humanities: The Search for a Methodology</em> pushes further, arguing that computational methods import assumptions from the sciences that humanists must interrogate rather than adopt wholesale, and that no algorithm arrives innocent of theory.<sup class=\"footnote-ref\"><a href=\"#fn42\" id=\"fnref42\">[42]</a></sup> I will have much more to say about this strand shortly, because it has produced some of the field's most important recent work.</p>\n<p>Methods, institutions, pedagogy, critique. Hold those four together and the definition debates make sense. Each famous intervention in those debates was really an argument about which of the four should lead.</p>\n<h2 id=\"living-institutional-homes\" tabindex=\"-1\">Living Institutional Homes <a class=\"header-anchor\" href=\"#living-institutional-homes\">#</a></h2>\n<p>Fields survive when institutions carry them, so let me introduce two institutional homes that show what the field looks like as a going concern in 2026, and that you can join or use today.</p>\n<p>The first is Knowledge Commons, at hcommons.org. It launched in December 2016 as Humanities Commons, a pilot project of the Modern Language Association's scholarly communication office under Kathleen Fitzpatrick, and it set out to be what the corporate academic networks pretend to be: a scholar-governed, nonprofit network for sharing work.<sup class=\"footnote-ref\"><a href=\"#fn43\" id=\"fnref43\">[43]</a></sup> In 2020 it moved to Michigan State University, and in 2024 it rebranded as Knowledge Commons to reflect a membership that had grown well beyond the humanities.<sup class=\"footnote-ref\"><a href=\"#fn44\" id=\"fnref44\">[44]</a></sup> The network now serves tens of thousands of scholars and practitioners. Its open-access repository, KCWorks, launched on new infrastructure in October 2024, hosts more than 30,000 open-access works, assigns DOIs to deposits, and was recently selected as the NEH's designated public-access repository.<sup class=\"footnote-ref\"><a href=\"#fn45\" id=\"fnref45\">[45]</a></sup> In plain terms: you can make a professional profile, deposit your papers, syllabi, and datasets with permanent identifiers, build a scholarly website, and join working groups, all without surrendering your work to a venture-funded platform that will eventually sell it or paywall it. Academia.edu and ResearchGate are companies. Knowledge Commons is infrastructure, and the difference matters more every year.</p>\n<p>The second is Michigan State University's digital humanities program, at digitalhumanities.msu.edu, which I point to as a model of what institutionalized DH looks like when it is done with care. MSU's program spans more than sixty core and affiliated faculty across twenty departments, offers an undergraduate minor in Digital Studies in the Arts and Humanities and a graduate certificate open to students in any discipline, and states its commitments in a tagline I wish more programs would steal: &quot;Focused on Experience. Informed by Ethics. Open to All.&quot;<sup class=\"footnote-ref\"><a href=\"#fn46\" id=\"fnref46\">[46]</a></sup> Around the program sit two research units with real histories. MATRIX, the Center for Digital Humanities and Social Sciences, established in 1997, builds &quot;collaborative and sustainable digital humanities projects, with an emphasis on the African diaspora and continent, that are open and accessible to researchers, students, and the general public.&quot;<sup class=\"footnote-ref\"><a href=\"#fn47\" id=\"fnref47\">[47]</a></sup> LEADR, a joint lab of the History and Anthropology departments, teaches students digital storytelling, data visualization, and digital research methods as part of ordinary coursework.<sup class=\"footnote-ref\"><a href=\"#fn48\" id=\"fnref48\">[48]</a></sup> MSU also hosts Knowledge Commons itself, along with the annual Global Digital Humanities Symposium. None of this is flashy. All of it is durable, and durability, as Parts 5 and 6 of this series will argue, is the hardest problem this field has.</p>\n<h2 id=\"the-critical-turn\" tabindex=\"-1\">The Critical Turn <a class=\"header-anchor\" href=\"#the-critical-turn\">#</a></h2>\n<p>I said the field includes critique, and I want to make good on that claim, because if you stopped reading here you might come away thinking the digital humanities is a success story with some methodological footnotes. The field's own best thinkers would not let you off that easily.</p>\n<p>The opening shot came from inside the house. Alan Liu's 2012 essay &quot;Where Is Cultural Criticism in the Digital Humanities?&quot; observed that cultural criticism, &quot;in both its interpretive and advocacy modes,&quot; had been &quot;noticeably absent&quot; from the field, that digital humanists risked becoming cheerful technicians in the service of institutions they never questioned.<sup class=\"footnote-ref\"><a href=\"#fn49\" id=\"fnref49\">[49]</a></sup> The field could count word frequencies across a million books, Liu argued, but it had little to say about the corporations, funding regimes, and labor arrangements that made those books countable. His challenge stuck, and much of the field's most vital work since has been an answer to it.</p>\n<p>Feminist and intersectional scholars supplied a large part of that answer. <em>Bodies of Information: Intersectional Feminism and Digital Humanities</em>, edited by Elizabeth Losh and Jacqueline Wernimont, examines how gender, race, disability, and embodiment shape digital knowledge production, from whose labor builds the archives to whose bodies the interfaces assume.<sup class=\"footnote-ref\"><a href=\"#fn50\" id=\"fnref50\">[50]</a></sup> Remember Busa's unnamed keypunch operators. This scholarship is the field finally reckoning with the pattern they began.</p>\n<p>Postcolonial and global critics widened the lens. Roopika Risam's <em>New Digital Worlds</em> documents how the digital cultural record reproduces colonial asymmetries, with the Global North's archives lavishly digitized while the Global South appears mostly as the object of someone else's dataset, and it lays out theory, praxis, and pedagogy for building otherwise.<sup class=\"footnote-ref\"><a href=\"#fn51\" id=\"fnref51\">[51]</a></sup> <em>Global Debates in the Digital Humanities</em>, edited by Domenico Fiormonte, Sukanta Chaudhuri, and Paola Ricaurte, gathers scholars writing from and about the Global South, many in translation, and makes uncomfortable reading for anyone who assumed the field's default language, infrastructure, and agenda were neutral.<sup class=\"footnote-ref\"><a href=\"#fn52\" id=\"fnref52\">[52]</a></sup> They are not. Bandwidth, electricity, software licensing, and the dominance of English are scholarly conditions, and the field has learned to treat them as such.</p>\n<p>This critical strand is not a side conversation. The <em>Debates in the Digital Humanities</em> series, which began as a single 2012 volume and became the field's ongoing self-examination, devotes more of every volume to these questions.<sup class=\"footnote-ref\"><a href=\"#fn18\" id=\"fnref18:1\">[18:1]</a></sup> A field that started by asking &quot;what can we compute?&quot; now spends at least as much energy asking &quot;who computes, who is computed, and who pays?&quot; That evolution is the strongest evidence of the field's intellectual health.</p>\n<h2 id=\"what-lasts\" tabindex=\"-1\">What Lasts <a class=\"header-anchor\" href=\"#what-lasts\">#</a></h2>\n<p>One more thread, briefly, because it points where this series ends. Digital projects die. Grant funding stops, servers get decommissioned, software dependencies rot, project directors retire, and the beautiful interactive archive that a team spent a decade building returns a 404. The University of Victoria's Endings Project has studied this problem systematically, asking &quot;How do and how should DH projects conclude?&quot; and developing principles for building digital scholarship that can survive its makers' attention.<sup class=\"footnote-ref\"><a href=\"#fn53\" id=\"fnref53\">[53]</a></sup></p>\n<p>One of the most compelling responses to this problem comes from the field's global wing. Global Outlook::Digital Humanities, a special interest group of ADHO, formed a working group on what it calls minimal computing after a 2014 workshop.<sup class=\"footnote-ref\"><a href=\"#fn54\" id=\"fnref54\">[54]</a></sup> The founding question, in Alex Gil's formulation, is disarmingly simple: &quot;What do we need?&quot;<sup class=\"footnote-ref\"><a href=\"#fn55\" id=\"fnref55\">[55]</a></sup> Roopika Risam and Gil define minimal computing as digital humanities work done under constraint, where the constraint might be &quot;lack of access to hardware or software, network capacity, technical education, or even a reliable power grid,&quot; and as an approach that &quot;advocates for using only the technologies that are necessary and sufficient&quot; for the scholarship at hand.<sup class=\"footnote-ref\"><a href=\"#fn56\" id=\"fnref56\">[56]</a></sup> They pose four questions that I think every digital project should have to answer before it spends a dollar: what do we need, what do we have, what must we prioritize, and what are we willing to give up?<sup class=\"footnote-ref\"><a href=\"#fn56\" id=\"fnref56:1\">[56:1]</a></sup></p>\n<p>Minimal computing began as a response to global inequity, and it remains that. But it turns out that the same choices that make a project buildable in a low-resource setting, plain text, static sites, open formats, few dependencies, also make it preservable everywhere. The sturdiest digital scholarship and the most equitable digital scholarship converge on the same architecture. That convergence is the subject of Part 6, and it is why I wanted you to meet GO::DH now, in the essay about definitions. A field reveals what it is by what it chooses to build with. A field that chooses simplicity, so that more of the world can participate and so that its work outlives its grants, has told you something about its values that no definition could.</p>\n<h2 id=\"where-to-start\" tabindex=\"-1\">Where to Start <a class=\"header-anchor\" href=\"#where-to-start\">#</a></h2>\n<p>If this essay has done its job, you want to see the field for yourself rather than read more prose about it. Here is a short path. Spend ten minutes with America's Public Bible and watch a verse rise and fall across a century of newspapers. Paste a text you know well into Voyant Tools and see what distant reading feels like. Make a free account on Knowledge Commons and look at what other scholars in your field have deposited. Browse two or three Programming Historian lessons, not to complete them but to see what is teachable. Then, if you want the arguments, read Kirschenbaum, Spiro, and Alvarado, all free online, all cited below. You will know more about what the digital humanities are than most people who use the term.</p>\n<p>The definition I offered at the start will carry us through the rest of this series. Digital humanities are a contested ensemble of methods, infrastructures, pedagogies, institutions, and critical practices through which humanists create, preserve, model, analyze, publish, and critique cultural evidence in digital forms. Contested, because the arguments are the field. An ensemble, because no tool defines it. And aimed at cultural evidence in digital forms, because the transformations, manuscript to image, sermon to text, letters to network, place to map, are where the scholarship lives. Next time, tools, and specifically the ones that will help you finish a dissertation.</p>\n<h2 id=\"in-this-series\" tabindex=\"-1\">In This Series <a class=\"header-anchor\" href=\"#in-this-series\">#</a></h2>\n<ol>\n<li>Digital Humanities Part 1: What Are the Digital Humanities? (this essay)</li>\n<li>Digital Humanities Part 2: Digital Humanities Tools for Dissertations</li>\n<li>Digital Humanities Part 3: Digital Humanities for Theology and Religious Studies</li>\n<li>Digital Humanities Part 4: Why We Need the Digital Humanities</li>\n<li>Digital Humanities Part 5: Preserving Digital Humanities Projects</li>\n<li>Digital Humanities Part 6: Preservation through Minimal Computing and GO::DH</li>\n</ol>\n<hr class=\"footnotes-sep\">\n<section class=\"footnotes\">\n<ol class=\"footnotes-list\">\n<li id=\"fn1\" class=\"footnote-item\"><p>Jason Heppler, &quot;Defining Digital Humanities,&quot; jasonheppler.org, January 8, 2013, https://jasonheppler.org/2013/01/08/defining-digital-humanities/. The definition generator itself is at https://whatisdigitalhumanities.com/, drawing on participant statements from the Day of DH projects, 2009-2014. <a href=\"#fnref1\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn2\" class=\"footnote-item\"><p>&quot;Publication of Roberto Busa's Index Thomisticus,&quot; HistoryofInformation.com, Jeremy Norman, n.d., https://www.historyofinformation.com/detail.php?id=3077. <a href=\"#fnref2\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref2:1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn3\" class=\"footnote-item\"><p>&quot;Publication of Roberto Busa's Index Thomisticus: Forty Years of Data Processing in the Humanities,&quot; HistoryofInformation.com, Jeremy Norman, n.d., https://www.historyofinformation.com/detail.php?entryid=3515. <a href=\"#fnref3\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn4\" class=\"footnote-item\"><p>Melissa Terras, review of <em>A Companion to Digital Humanities</em>, ed. Susan Schreibman, Ray Siemens, and John Unsworth, <em>The Classical Review</em> 59, no. 1 (2009): 288-290, https://discovery.ucl.ac.uk/171106/1/Terras_review_companiontoDH.pdf. Both Busa's definition and the Companion editors' definition are quoted in Terras's review. The anthology itself is Susan Schreibman, Ray Siemens, and John Unsworth, eds., <em>A Companion to Digital Humanities</em> (Oxford: Blackwell, 2004). <a href=\"#fnref4\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref4:1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn5\" class=\"footnote-item\"><p>Melissa Terras and Julianne Nyhan, &quot;Father Busa's Female Punch Card Operatives,&quot; in <em>Debates in the Digital Humanities 2016</em>, ed. Matthew K. Gold and Lauren F. Klein (Minneapolis: University of Minnesota Press, 2016), https://dhdebates.gc.cuny.edu/read/untitled/section/1e57217b-f262-4f25-806b-4fcf1548beb5. <a href=\"#fnref5\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref5:1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn6\" class=\"footnote-item\"><p>Steven E. Jones, <em>Roberto Busa, S.J., and the Emergence of Humanities Computing: The Priest and the Punched Cards</em> (New York: Routledge, 2016), https://www.routledge.com/Roberto-Busa-S-J-and-the-Emergence-of-Humanities-Computing-The-Priest-and-the-Punched-Cards/Jones/p/book/9781138587250. And Steven E. Jones, <em>The Emergence of the Digital Humanities</em> (New York: Routledge, 2013), https://www.routledge.com/The-Emergence-of-the-Digital-Humanities/Jones/p/book/9780415635523. <a href=\"#fnref6\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn7\" class=\"footnote-item\"><p>&quot;About,&quot; Alliance of Digital Humanities Organizations, https://adho.org/about/. <a href=\"#fnref7\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref7:1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn8\" class=\"footnote-item\"><p>&quot;History,&quot; Text Encoding Initiative, https://tei-c.org/about/history/. <a href=\"#fnref8\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn9\" class=\"footnote-item\"><p>&quot;The Office of Digital Humanities Turns Ten,&quot; <em>Humanities</em>, National Endowment for the Humanities, Spring 2018, https://www.neh.gov/humanities/2018/spring/feature/the-office-digital-humanities-turns-ten. <a href=\"#fnref9\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn10\" class=\"footnote-item\"><p>Patrik Svensson, &quot;Humanities Computing as Digital Humanities,&quot; <em>Digital Humanities Quarterly</em> 3, no. 3 (2009), http://www.digitalhumanities.org/dhq/vol/3/3/000065/000065.html. <a href=\"#fnref10\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref10:1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn11\" class=\"footnote-item\"><p>William Pannapacker, &quot;'Big Tent Digital Humanities,' a View From the Edge, Part 1,&quot; <em>The Chronicle of Higher Education</em>, July 31, 2011, https://www.chronicle.com/article/big-tent-digital-humanities-a-view-from-the-edge-part-1/. <a href=\"#fnref11\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn12\" class=\"footnote-item\"><p>Matthew Kirschenbaum, &quot;What Is Digital Humanities and What's It Doing in English Departments?,&quot; <em>ADE Bulletin</em>, no. 150 (2010), reprinted in <em>Debates in the Digital Humanities</em>, ed. Matthew K. Gold (Minneapolis: University of Minnesota Press, 2012), https://dhdebates.gc.cuny.edu/read/untitled-88c11800-9446-469b-a3be-3fdb36bfbd1e/section/f5640d43-b8eb-4d49-bc4b-eb31a16f3d06. The quoted sentence comes from Kirschenbaum's reply in the comment thread on the blog version of the essay, &quot;What is Digital Humanities?,&quot; January 22, 2011, https://mkirschenbaum.wordpress.com/2011/01/22/what-is-digital-humanities/. <a href=\"#fnref12\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref12:1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn13\" class=\"footnote-item\"><p>Matthew Kirschenbaum, &quot;Digital Humanities As/Is a Tactical Term,&quot; in <em>Debates in the Digital Humanities</em>, ed. Matthew K. Gold (Minneapolis: University of Minnesota Press, 2012), https://dhdebates.gc.cuny.edu/read/untitled-88c11800-9446-469b-a3be-3fdb36bfbd1e/section/c0b0a8ee-95f0-4a9c-9451-e8ad168e3db5. <a href=\"#fnref13\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref13:1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn14\" class=\"footnote-item\"><p>Rafael C. Alvarado, &quot;The Digital Humanities Situation,&quot; in <em>Debates in the Digital Humanities</em>, ed. Matthew K. Gold (Minneapolis: University of Minnesota Press, 2012), https://dhdebates.gc.cuny.edu/read/untitled-88c11800-9446-469b-a3be-3fdb36bfbd1e/section/c513af64-8f99-4e02-9869-babc1cecc451. <a href=\"#fnref14\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn15\" class=\"footnote-item\"><p>Stephen Ramsay, &quot;Who's In and Who's Out,&quot; remarks at the Modern Language Association convention, Los Angeles, January 2011, as quoted in Mark Sample, &quot;The digital humanities is not about building, it's about sharing,&quot; samplereality, May 25, 2011, https://samplereality.com/2011/05/25/the-digital-humanities-is-not-about-building-its-about-sharing/. <a href=\"#fnref15\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref15:1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn16\" class=\"footnote-item\"><p>Lisa Spiro, &quot;'This Is Why We Fight': Defining the Values of the Digital Humanities,&quot; in <em>Debates in the Digital Humanities</em>, ed. Matthew K. Gold (Minneapolis: University of Minnesota Press, 2012), https://dhdebates.gc.cuny.edu/read/untitled-88c11800-9446-469b-a3be-3fdb36bfbd1e/section/9e014167-c688-43ab-8b12-0f6746095335. <a href=\"#fnref16\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn17\" class=\"footnote-item\"><p>Melissa Terras, Julianne Nyhan, and Edward Vanhoutte, eds., <em>Defining Digital Humanities: A Reader</em> (Farnham: Ashgate, 2013), https://www.routledge.com/Defining-Digital-Humanities-A-Reader/Terras-Nyhan-Vanhoutte/p/book/9781409469636. <a href=\"#fnref17\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn18\" class=\"footnote-item\"><p>Matthew K. Gold and Lauren F. Klein, eds., <em>Debates in the Digital Humanities 2023</em> (Minneapolis: University of Minnesota Press, 2023), https://dhdebates.gc.cuny.edu/projects/debates-in-the-digital-humanities-2023. <a href=\"#fnref18\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref18:1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn19\" class=\"footnote-item\"><p><em>Mapping the Republic of Letters</em>, Stanford University, dir. Dan Edelstein and Paula Findlen, https://republicofletters.stanford.edu/. See also &quot;Mapping the Republic of Letters,&quot; <em>Humanities</em>, National Endowment for the Humanities, November/December 2013, https://www.neh.gov/humanities/2013/novemberdecember/feature/mapping-the-republic-letters. <a href=\"#fnref19\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn20\" class=\"footnote-item\"><p>Johanna Drucker, <em>The Digital Humanities Coursebook: An Introduction to Digital Methods for Research and Scholarship</em> (Abingdon: Routledge, 2021), https://www.routledge.com/The-Digital-Humanities-Coursebook-An-Introduction-to-Digital-Methods-for-Research-and-Scholarship/Drucker/p/book/9780367565756. <a href=\"#fnref20\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn21\" class=\"footnote-item\"><p>Lincoln Mullen, personal site, https://lincolnmullen.com/. His title is given on the RRCHNM staff page, &quot;Our People,&quot; Roy Rosenzweig Center for History and New Media, https://rrchnm.org/people/. <a href=\"#fnref21\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref21:1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn22\" class=\"footnote-item\"><p>Lincoln A. Mullen, <em>America's Public Bible: A Commentary</em> (Stanford, CA: Stanford University Press, 2023), https://americaspublicbible.org/. <a href=\"#fnref22\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn23\" class=\"footnote-item\"><p>&quot;NEH Data Challenge Winner: America's Public Bible,&quot; National Endowment for the Humanities, 2016, https://www.neh.gov/divisions/preservation/featured-project/neh-data-challenge-winner-americas-public-bible. <a href=\"#fnref23\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref23:1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn24\" class=\"footnote-item\"><p><em>American Religious Ecologies</em>, Roy Rosenzweig Center for History and New Media, George Mason University, https://religiousecologies.org/. <a href=\"#fnref24\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn25\" class=\"footnote-item\"><p>Lincoln Mullen, GitHub profile, https://github.com/lmullen. <a href=\"#fnref25\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn26\" class=\"footnote-item\"><p>Lincoln Mullen, &quot;A Braided Narrative for Digital History,&quot; in <em>Debates in the Digital Humanities 2019</em>, ed. Matthew K. Gold and Lauren F. Klein (Minneapolis: University of Minnesota Press, 2019), https://dhdebates.gc.cuny.edu/read/untitled-f2acf72c-a469-49d8-be35-67f9ac1e3a60/section/e5496dc6-dcc1-42e7-8609-9377d05812c5. <a href=\"#fnref26\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn27\" class=\"footnote-item\"><p>Lincoln A. Mullen, <em>The Chance of Salvation: A History of Conversion in America</em> (Cambridge, MA: Harvard University Press, 2017), https://www.hup.harvard.edu/books/9780674975620. <a href=\"#fnref27\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn28\" class=\"footnote-item\"><p>Roy Rosenzweig Center for History and New Media, George Mason University, https://rrchnm.org/. <a href=\"#fnref28\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn29\" class=\"footnote-item\"><p>Zotero, Digital Scholar, https://www.zotero.org/. <a href=\"#fnref29\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn30\" class=\"footnote-item\"><p>Omeka, Digital Scholar, https://omeka.org/. <a href=\"#fnref30\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn31\" class=\"footnote-item\"><p>Tropy, Roy Rosenzweig Center for History and New Media, C2DH, and Digital Scholar, https://tropy.org/. <a href=\"#fnref31\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn32\" class=\"footnote-item\"><p>PressForward, Digital Scholar, https://pressforward.org/. <a href=\"#fnref32\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn33\" class=\"footnote-item\"><p>&quot;About,&quot; The September 11 Digital Archive, American Social History Project and Roy Rosenzweig Center for History and New Media, https://911digitalarchive.org/about. <a href=\"#fnref33\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn34\" class=\"footnote-item\"><p>&quot;About the Archive,&quot; The Walt Whitman Archive, ed. Matt Cohen, Ed Folsom, and Kenneth M. Price, https://whitmanarchive.org/about/overview. <a href=\"#fnref34\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn35\" class=\"footnote-item\"><p><em>The Valley of the Shadow: Two Communities in the American Civil War</em>, University of Virginia Library, dir. Edward L. Ayers and William G. Thomas III, https://valley.lib.virginia.edu/. <a href=\"#fnref35\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn36\" class=\"footnote-item\"><p>&quot;The Proceedings of the Old Bailey Online,&quot; The Digital Humanities Institute, University of Sheffield, dir. Tim Hitchcock and Robert Shoemaker, https://www.dhi.ac.uk/projects/old-bailey/. The project itself is at https://www.oldbaileyonline.org/. <a href=\"#fnref36\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn37\" class=\"footnote-item\"><p>Voyant Tools, Stéfan Sinclair and Geoffrey Rockwell, https://voyant-tools.org/. <a href=\"#fnref37\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn38\" class=\"footnote-item\"><p>David M. Berry and Anders Fagerjord, <em>Digital Humanities: Knowledge and Critique in a Digital Age</em> (Cambridge: Polity, 2017), https://www.politybooks.com/bookdetail?book_slug=digital-humanities-knowledge-and-critique-in-a-digital-age--9780745697659. <a href=\"#fnref38\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn39\" class=\"footnote-item\"><p>Brian Croxall and Diane K. Jakacki, eds., <em>What We Teach When We Teach DH: Digital Humanities in the Classroom</em> (Minneapolis: University of Minnesota Press, 2023), https://upress.umn.edu/book-division/books/what-we-teach-when-we-teach-dh. <a href=\"#fnref39\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn40\" class=\"footnote-item\"><p>&quot;About the Programming Historian,&quot; The Programming Historian, https://programminghistorian.org/en/about. <a href=\"#fnref40\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn41\" class=\"footnote-item\"><p>David M. Berry, ed., <em>Understanding Digital Humanities</em> (Basingstoke: Palgrave Macmillan, 2012), https://link.springer.com/book/10.1057/9780230371934. <a href=\"#fnref41\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn42\" class=\"footnote-item\"><p>James E. Dobson, <em>Critical Digital Humanities: The Search for a Methodology</em> (Urbana: University of Illinois Press, 2019), https://www.press.uillinois.edu/books/catalog/48xfp2zp9780252042270.html. <a href=\"#fnref42\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn43\" class=\"footnote-item\"><p>&quot;Our History,&quot; Knowledge Commons, https://sustaining.hcommons.org/about-this-site/our-history/. The network itself is at https://hcommons.org/. <a href=\"#fnref43\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn44\" class=\"footnote-item\"><p>&quot;Humanities Commons is Moving to Michigan State University,&quot; MSUToday, Michigan State University, 2020, https://msutoday.msu.edu/news/2020/humanities-commons-is-moving-to-michigan-state-university. On the 2024 rebrand, see &quot;Infra Finder Spotlight: Knowledge Commons,&quot; Invest in Open Infrastructure, https://investinopen.org/blog/infra-finder-spotlight-knowledge-commons/. <a href=\"#fnref44\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn45\" class=\"footnote-item\"><p>&quot;Introducing KCWorks,&quot; James Madison University Libraries, https://www.lib.jmu.edu/kcworks-announcement/. <a href=\"#fnref45\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn46\" class=\"footnote-item\"><p>DH@MSU, Michigan State University, https://digitalhumanities.msu.edu/. On the minor, see https://digitalhumanities.msu.edu/minor/. On the graduate certificate, see https://digitalhumanities.msu.edu/graduate-certificate/. <a href=\"#fnref46\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn47\" class=\"footnote-item\"><p>&quot;Mission,&quot; MATRIX: Center for Digital Humanities and Social Sciences, Michigan State University, https://matrix.msu.edu/mission/. <a href=\"#fnref47\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn48\" class=\"footnote-item\"><p>LEADR: Lab for the Education and Advancement in Digital Research, Michigan State University, https://leadr.msu.edu/. <a href=\"#fnref48\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn49\" class=\"footnote-item\"><p>Alan Liu, &quot;Where Is Cultural Criticism in the Digital Humanities?,&quot; in <em>Debates in the Digital Humanities</em>, ed. Matthew K. Gold (Minneapolis: University of Minnesota Press, 2012), full text on Liu's site at https://liu.english.ucsb.edu/where-is-cultural-criticism-in-the-digital-humanities/. <a href=\"#fnref49\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn50\" class=\"footnote-item\"><p>Elizabeth Losh and Jacqueline Wernimont, eds., <em>Bodies of Information: Intersectional Feminism and Digital Humanities</em> (Minneapolis: University of Minnesota Press, 2018), https://dhdebates.gc.cuny.edu/projects/bodies-of-information. <a href=\"#fnref50\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn51\" class=\"footnote-item\"><p>Roopika Risam, <em>New Digital Worlds: Postcolonial Digital Humanities in Theory, Praxis, and Pedagogy</em> (Evanston, IL: Northwestern University Press, 2018), https://nupress.northwestern.edu/9780810138858/new-digital-worlds/. <a href=\"#fnref51\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn52\" class=\"footnote-item\"><p>Domenico Fiormonte, Sukanta Chaudhuri, and Paola Ricaurte, eds., <em>Global Debates in the Digital Humanities</em> (Minneapolis: University of Minnesota Press, 2022), https://dhdebates.gc.cuny.edu/projects/global-debates-in-the-digital-humanities. <a href=\"#fnref52\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn53\" class=\"footnote-item\"><p>The Endings Project, Humanities Computing and Media Centre, University of Victoria, https://endings.uvic.ca/index.html. <a href=\"#fnref53\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn54\" class=\"footnote-item\"><p>Minimal Computing, a working group of Global Outlook::Digital Humanities (GO::DH), Alliance of Digital Humanities Organizations, https://go-dh.github.io/mincomp/. <a href=\"#fnref54\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn55\" class=\"footnote-item\"><p>Alex Gil, &quot;The User, the Learner and the Machines We Make,&quot; Minimal Computing, May 21, 2015, https://go-dh.github.io/mincomp/thoughts/2015/05/21/user-vs-learner/. <a href=\"#fnref55\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn56\" class=\"footnote-item\"><p>Roopika Risam and Alex Gil, &quot;Introduction: The Questions of Minimal Computing,&quot; <em>Digital Humanities Quarterly</em> 16, no. 2 (2022), https://digitalhumanities.org/dhq/vol/16/2/000646/000646.html. <a href=\"#fnref56\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref56:1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n</ol>\n</section>\n",
			"date_published": "2026-07-14T07:44:04Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/habermas-and-the-transformations-of-critical-theory-review/",
			"url": "https://www.adamdjbrett.com/blog/habermas-and-the-transformations-of-critical-theory-review/",
			"title": "Review: Habermas and the Transformations of Critical Theory",
			"content_html": "<h2 id=\"habermas-and-the-transformations-of-critical-theory-faces-of-critique\" tabindex=\"-1\">Habermas and the Transformations of Critical Theory: Faces of Critique <a class=\"header-anchor\" href=\"#habermas-and-the-transformations-of-critical-theory-faces-of-critique\">#</a></h2>\n<p><strong>Edited by Amirhosein Khandizaji and James J. Chriss</strong>\n<em>Palgrave Macmillan, 2025</em></p>\n<blockquote>\n<p>Khandizaji, Amirhosein, and James J. Chriss, eds. 2025. <em>Habermas and the Transformations of Critical Theory: Faces of Critique</em>. Cham: Palgrave Macmillan / Springer Nature Switzerland. ISBN 978-3-031-98025-1 (hardback), 978-3-031-98026-8 (eBook).</p>\n</blockquote>\n<p>Jürgen Habermas has now been publishing for close to seventy years, and Amirhosein Khandizaji and James Chriss organize their editors' introduction around a genuinely useful periodization, borrowed from Kire Sharlamanov, that divides that career into four phases: the early public-sphere and knowledge-interests work of the 1960s, the Starnberg-era groundwork for communicative action in the 1970s, the mature theory of communicative action and discourse ethics of the 1980s and 1990s, and a fourth phase since 2000 turning toward religion, international law, and, most recently, the three-volume <em>Also a History of Philosophy</em>. Against that map, the editors assemble eight substantive chapters from a genuinely distinguished set of contributors, Stefano Petrucciani, Alessandro Ferrara, Darrow Schecter, Simon Susen, Hans-Herbert Kögler, among others, each taking up a different facet of Habermas's system: discourse ethics and religion, the postmetaphysical turn, Marxian emancipation, democratic statehood, the Mead and Husserl lineage, the Rawls debate, and the digital public sphere. The subtitle, &quot;Faces of Critique,&quot; promises a volume organized around genuine confrontation with Habermas's positions. What it delivers is more mixed, some chapters critique, several primarily explain, and the difference matters for how the book should be used.</p>\n<h3 id=\"where-the-volume-earns-its-subtitle\" tabindex=\"-1\">Where the volume earns its subtitle <a class=\"header-anchor\" href=\"#where-the-volume-earns-its-subtitle\">#</a></h3>\n<p>The strongest chapter, and the one that most fully honors the book's title, is Michael J. Thompson's &quot;On the Ontological Content of Morality.&quot; Thompson, who elsewhere has made a career of prosecuting what he calls the &quot;domestication&quot; of critical theory by its second and third generations, here turns that same charge on Habermas's postmetaphysical proceduralism directly. His argument is precise: Habermas's discourse ethics locates moral validity entirely in the conditions under which consensus is reached, whether participants speak freely, whether claims are subject to open contestation, and this leaves the theory unable to say anything about the substantive, ontological conditions, poverty, racism, structural domination, that shape who actually gets to participate in discourse on equal terms in the first place. Thompson's proposed alternative, a &quot;critical social ontology&quot; that grounds normative validity in freedom-enhancing forms of social life rather than in procedural consensus alone, is argued with real philosophical care, engaging Habermas's technical vocabulary of <em>Geltung</em> and <em>Gültigkeit</em> directly rather than gesturing at it. Readers who have encountered Neal Harris's recent case against Axel Honneth's normative reconstruction, which draws on this same Thompson lineage, will recognize the family resemblance: this is the same charge, that Frankfurt School critical theory's second and third generations have replaced immanent critique of existing norms with an uncritical embrace of the proceduralist conditions under which those norms get ratified, now aimed at Habermas himself rather than his student. Darrow Schecter's chapter is nearly as sharp, and considerably more willing to name names: he argues that communicative action's account of democratic statehood, plausible from the 1980s through 2008, has been outpaced by the fusion of political and social crisis since the financial crash, citing Elon Musk's Department of Government Efficiency under the second Trump administration as a live instance of exactly the kind of institutional rupture Habermas's framework struggles to theorize.</p>\n<h3 id=\"where-the-subtitle-overpromises\" tabindex=\"-1\">Where the subtitle overpromises <a class=\"header-anchor\" href=\"#where-the-subtitle-overpromises\">#</a></h3>\n<p>Several of the remaining chapters function more as expository reconstruction than critique, useful for readers new to Habermas, less useful for readers wanting to see his positions genuinely tested. Simon Susen's chapter on &quot;the tasks of contemporary philosophy&quot; is a competent survey of communicative action, discourse ethics, and Habermas's engagement with Foucault and Derrida, but its conclusion, that Habermas's framework &quot;remains highly relevant&quot; to an era of polarization and misinformation, restates the case for Habermas's continued importance rather than interrogating it. James Chriss's own chapter tracing Habermas's use of Mead and Husserl is a genuinely illuminating piece of intellectual history, showing how Habermas found Husserl's phenomenology too transcendental and Mead's social behaviorism insufficiently attentive to the origins of norm-consciousness, and had to import Durkheim's sociology of religion to complete the synthesis, but it is history of ideas rather than critique in any evaluative sense. Alessandro Ferrara's chapter, revisiting the Habermas-Rawls dispute over &quot;the reasonable&quot; through the lens of Habermas's recent <em>Also a History of Philosophy</em>, is a republished 2021 journal article rather than newly commissioned material, a fact the acknowledgments disclose but that readers should know going in: roughly one-ninth of the volume's substantive content is not new to 2025.</p>\n<h3 id=\"the-introductions-most-debatable-choice\" tabindex=\"-1\">The introduction's most debatable choice <a class=\"header-anchor\" href=\"#the-introductions-most-debatable-choice\">#</a></h3>\n<p>The editors' introduction opens with an extended comparison between Habermas and Herbert Spencer, on the grounds that both dedicated multi-decade careers to synthesizing philosophy, science, and social theory into totalizing intellectual systems. It is a genuinely interesting framing device, and the editors use it to set up the four-phase periodization that structures the rest of the introduction usefully. But the comparison is asserted rather than argued for at any length, Spencer's Social Darwinism and his role in legitimating laissez-faire capitalism sit uneasily next to Habermas's discourse ethics and deliberative democracy, and readers may find themselves wanting either a fuller defense of why this particular parallel illuminates Habermas's project or a more conventional framing that doesn't ask them to hold Spencer in mind for the rest of the introduction's fourteen pages.</p>\n<h3 id=\"an-edited-volumes-usual-tension-handled-better-than-most\" tabindex=\"-1\">An edited volume's usual tension, handled better than most <a class=\"header-anchor\" href=\"#an-edited-volumes-usual-tension-handled-better-than-most\">#</a></h3>\n<p>Edited volumes on major theorists routinely struggle with coherence, and this one is more honest about that struggle than most, largely because the editors' introduction does real synthesizing work rather than simply summarizing each chapter in sequence. The decision to organize contributions around Habermas's own periodization gives the collection a spine that many &quot;critical perspectives on X&quot; volumes lack. Where the volume falls short of its own ambition is in delivering a consistent register across contributions: a reader moving from Thompson's sharp ontological challenge to Susen's appreciative survey to Ferrara's technical Rawls exegesis experiences something closer to a very good conference panel, with real variation in how combative individual speakers chose to be, than a unified argument about what &quot;critique&quot; of Habermas should look like in 2025. That is a reasonable thing for an edited volume to be. It is a slightly different thing than what &quot;Faces of Critique&quot; promises on the cover.</p>\n<h3 id=\"verdict\" tabindex=\"-1\">Verdict <a class=\"header-anchor\" href=\"#verdict\">#</a></h3>\n<p><em>Habermas and the Transformations of Critical Theory</em> is a genuinely useful state-of-the-field survey, anchored by a strong periodizing introduction and carried by two exceptional chapters, Thompson's ontological challenge to postmetaphysical proceduralism and Schecter's argument that communicative action has been overtaken by the post-2008 crisis of democratic statehood, both of which do the confrontational work the subtitle promises. Readers wanting a map of Habermas's sixty-year career, with expert guides to its major turns and its engagements with Mead, Husserl, Rawls, and religion, will find this volume genuinely useful, particularly given how current some of the material is, Schecter's chapter reaches into 2025 political events directly. Readers expecting every chapter to challenge Habermas as forcefully as its title suggests should adjust expectations: this is a volume with real faces of critique in it, alongside a good deal of sympathetic exposition wearing critique's name.</p>\n",
			"date_published": "2026-07-13T05:16:32Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/critical-theory-of-communication-review/",
			"url": "https://www.adamdjbrett.com/blog/critical-theory-of-communication-review/",
			"title": "Review: Critical Theory of Communication",
			"content_html": "<h2 id=\"critical-theory-of-communication-new-readings-of-lukacs-adorno-marcuse-honneth-and-habermas-in-the-age-of-the-internet\" tabindex=\"-1\">Critical Theory of Communication: New Readings of Lukács, Adorno, Marcuse, Honneth and Habermas in the Age of the Internet <a class=\"header-anchor\" href=\"#critical-theory-of-communication-new-readings-of-lukacs-adorno-marcuse-honneth-and-habermas-in-the-age-of-the-internet\">#</a></h2>\n<p><strong>By Christian Fuchs</strong>\n<em>University of Westminster Press, 2016 (Critical, Digital and Social Media Studies series)</em></p>\n<blockquote>\n<p>Fuchs, Christian. 2016. <em>Critical Theory of Communication: New Readings of Lukács, Adorno, Marcuse, Honneth and Habermas in the Age of the Internet</em>. London: University of Westminster Press. ISBN 978-1-911534-04-4. Open access, DOI: 10.16997/book1.</p>\n</blockquote>\n<p>Christian Fuchs has spent a career arguing that digital and social media theory needs to take Marx seriously again, and this open-access book is his attempt to route that argument through the Frankfurt School specifically. The structure is five stand-alone essays, each pairing one critical theorist with the analysis of digital communication: Lukács's late <em>Ontology of Social Being</em> read against cultural and digital labor, Adorno's theory of knowledge read against claims that he was a &quot;media pessimist,&quot; Marcuse's dialectics read against social media, Honneth's recognition-based theory of alienation read against Facebook, and a closing chapter that surveys several rivals to Habermas's communication theory. Fuchs is explicit that the book does not attempt to deliver a finished &quot;dialectical critical theory of communication,&quot; only to lay foundations for one. That modesty, stated plainly in both the introduction and conclusion, turns out to be the most reliable guide to what the book actually accomplishes.</p>\n<h3 id=\"the-strongest-material-is-where-theory-meets-platform\" tabindex=\"-1\">The strongest material is where theory meets platform <a class=\"header-anchor\" href=\"#the-strongest-material-is-where-theory-meets-platform\">#</a></h3>\n<p>Chapter 4, on Marcuse and social media, is the book's high point, and it earns that status by doing real interpretive synthesis rather than paraphrase. Fuchs takes Marcuse's account of play, labor, and the reality principle from <em>Eros and Civilization</em> and combines it with Boltanski and Chiapello's account of the &quot;new spirit of capitalism,&quot; Mario Tronti's concept of the &quot;social factory,&quot; and Deleuze's &quot;society of control&quot; to build a concept Fuchs calls &quot;playbour&quot;: Facebook use as an activity that has the phenomenological texture of play (irregular, self-directed, pleasurable) while functioning economically as unpaid, surplus-value-generating labor. The chapter includes a table mapping Marcuse's stages, from societies of scarcity through classical capitalism to &quot;capitalism in the age of Facebook,&quot; showing how leisure time and work time collapse into each other under platform capitalism. Whatever one makes of the underlying political economy, this is a genuinely original piece of theoretical bricolage, and it is the concept for which this book is most often cited elsewhere.</p>\n<p>Chapter 5's treatment of Honneth is nearly as strong. Fuchs stages a real disagreement in the secondary literature, between Mark Andrejevic, who argues Facebook produces &quot;algorithmic alienation,&quot; and Eran Fisher, who argues Facebook use can feel de-alienating because it lets users express themselves, and uses Honneth's three-way distinction between subjective, intersubjective, and objective alienation to show the two aren't actually incompatible: Andrejevic is describing the objective dimension (data as an object beyond the user's control) while Fisher is describing the subjective dimension (how alienation feels from the inside). The resulting nine-cell table crossing three spheres (economic, political, cultural) against three dimensions (subjective, intersubjective, objective) is a genuinely useful piece of conceptual infrastructure, the kind of table a reader could productively borrow for other platforms Fuchs never discusses.</p>\n<h3 id=\"an-uneven-allocation-of-critical-attention\" tabindex=\"-1\">An uneven allocation of critical attention <a class=\"header-anchor\" href=\"#an-uneven-allocation-of-critical-attention\">#</a></h3>\n<p>The chapter titled &quot;Beyond Habermas,&quot; which closes the book, is where the project's ambitions outrun its execution. Habermas is one of the five thinkers named in the book's own subtitle, and arguably the Frankfurt School figure most identified with communication as a topic in its own right, yet he receives roughly five pages of direct engagement inside a chapter that also has to cover Alfred Sohn-Rethel, Jean Baudrillard, and then, as the positive alternative, Vygotsky, Vološinov, Rossi-Landi, and Raymond Williams. Lukács, Adorno, Marcuse, and Honneth each get an entire dedicated chapter built around one or two of their books. Habermas gets treated mainly as an obstacle: the chapter's job is to state his labor/communication dualism, note that it separates instrumental action from communicative action too cleanly, and move past him toward a dialectical alternative built out of other people's work. For a book whose title puts Habermas on equal footing with the other four names, the actual space and analytical care devoted to him is the least of the five, and the chapter reads less like a considered response to Habermas's theory of communicative action than a rapid survey of everyone Fuchs would rather build on instead.</p>\n<h3 id=\"the-introduction-is-a-literature-review-wearing-an-arguments-clothes\" tabindex=\"-1\">The introduction is a literature review wearing an argument's clothes <a class=\"header-anchor\" href=\"#the-introduction-is-a-literature-review-wearing-an-arguments-clothes\">#</a></h3>\n<p>Before reaching any of the five thinkers, the book spends nearly forty pages cataloguing definitions: Lash's distinction between dialectical and aporetic critique, Tyson's list of critical-theory schools, Tallack's list, Agger's list, two competing Marxist encyclopedia entries on the German term <em>Kritische Theorie</em>. This is not wrong, exactly, and some readers will find the genealogical care useful as reference material. But it reads as throat-clearing rather than argument, and it delays the book's actual payoff, the applied readings in chapters 2 through 5, for a stretch that would be more at home in a companion or handbook than in the introduction to a five-essay monograph. The repetition compounds across chapters too: because each essay began life able to stand alone (Fuchs says so explicitly), several chapters re-introduce their thinker's basic biography and canonical texts from scratch, producing a mild but noticeable amount of redundancy for anyone reading the book cover to cover rather than dipping into a single chapter.</p>\n<h3 id=\"how-it-holds-up\" tabindex=\"-1\">How it holds up <a class=\"header-anchor\" href=\"#how-it-holds-up\">#</a></h3>\n<p>This is the sharpest limitation, and it is not really Fuchs's fault so much as a function of when the book was written. Published in 2016, every applied example runs through Facebook: Facebook exploitation, Facebook alienation, Facebook playbour. A decade later, after the platform consolidation, algorithmic feed redesigns, TikTok's rise, X's transformation under different ownership, and the arrival of generative AI as a communication medium in its own right, a book subtitled &quot;in the Age of the Internet&quot; reads as a book about one specific and no-longer-dominant moment in that age. The theoretical machinery Fuchs builds, particularly playbour and the nine-dimension alienation grid, is portable to newer platforms, and an alert reader can make that translation. But the book itself doesn't, and its examples now require a small act of historical translation before they land.</p>\n<h3 id=\"verdict\" tabindex=\"-1\">Verdict <a class=\"header-anchor\" href=\"#verdict\">#</a></h3>\n<p>Read chapters 4 and 5 for what they actually are: two of the more inventive attempts in the critical theory literature to make Marcuse's and Honneth's categories do real work on a specific communication platform, rather than staying at the level of gestural citation. The Lukács and Adorno chapters are competent scholarly reconstructions that will be useful to readers who want an accessible route into <em>Ontology of Social Being</em> and Adorno's less-cited epistemological writing. But the book's own subtitle promises equal treatment of five thinkers and delivers four chapters plus an appendix-like treatment of the fifth, and its introduction spends real estate on definitional cataloguing that the applied chapters don't need. Ten years on, its Facebook-bound empirical horizon is the thing most likely to send a reader looking for Fuchs's more recent work instead of this one, even though the concepts built here, playbour above all, are still doing work in that later scholarship.</p>\n",
			"date_published": "2026-07-13T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/critical-theory-and-social-pathology-review/",
			"url": "https://www.adamdjbrett.com/blog/critical-theory-and-social-pathology-review/",
			"title": "Review: Critical Theory and Social Pathology",
			"content_html": "<h2 id=\"critical-theory-and-social-pathology-the-frankfurt-school-beyond-recognition\" tabindex=\"-1\">Critical Theory and Social Pathology: The Frankfurt School Beyond Recognition <a class=\"header-anchor\" href=\"#critical-theory-and-social-pathology-the-frankfurt-school-beyond-recognition\">#</a></h2>\n<p><strong>By Neal Harris</strong>\n<em>Manchester University Press, 2022 (Critical Theory and Contemporary Society series)</em></p>\n<blockquote>\n<p>Harris, Neal. 2022. <em>Critical Theory and Social Pathology: The Frankfurt School Beyond Recognition</em>. Manchester: Manchester University Press. ISBN 978-1-5261-5473-6.</p>\n</blockquote>\n<p>Neal Harris opens his preface by calling the present social order &quot;bonkers,&quot; and he means the word both colloquially and technically. That double register runs through the whole book: a polemical, sometimes chatty voice attached to an unusually disciplined piece of social theory. Harris's target is Axel Honneth, for two decades the closest thing critical theory has had to an official successor to Habermas, and the argument is that Honneth's turn to &quot;recognition&quot; as the master concept of Frankfurt School critique has hollowed the tradition out from the inside. The book's proposed remedy is a return to Erich Fromm and Herbert Marcuse, read together as offering a sturdier foundation for what Harris calls &quot;pathology diagnosing&quot; social research. The diagnosis is considerably more convincing than the cure.</p>\n<h3 id=\"what-social-pathology-is-doing-here\" tabindex=\"-1\">What &quot;social pathology&quot; is doing here <a class=\"header-anchor\" href=\"#what-social-pathology-is-doing-here\">#</a></h3>\n<p>Harris's opening move is definitional, and it matters more than it looks. He argues that critical theory has always been distinguished from liberal social criticism by refusing to reduce social wrongs to injustice or illegitimacy. Where liberal theory (he takes Rawls as the paradigm case) asks whether a distribution of goods is fair, critical theory asks whether the whole &quot;form of life&quot; producing that distribution is rational. The word for the latter kind of wrong, in the Frankfurt School's own vocabulary, is pathology, and Harris's claim is that the concept has quietly narrowed. First-generation theorists like Fromm and Marcuse used pathology in a thick sense, covering distorted needs, self-perpetuating &quot;vicious circles,&quot; psychoanalytically inflected accounts of ideology, and the constitutive power of the mode of production. Contemporary theory, following Honneth and his student Christopher Zurn, has shrunk pathology down to a single mechanism: failures of intersubjective recognition, understood as &quot;second-order disconnects&quot; between a subject and norms that are, on Honneth's account, already latent within existing institutions. That narrowing is what Harris means by the &quot;domestication of critical theory,&quot; a phrase he borrows explicitly from Michael J. Thompson and credits as the book's founding provocation.</p>\n<p>The three-part structure follows from this diagnosis cleanly. Part I builds the case against Honneth's recognition monism. Part II goes back to Rousseau, Hegel, and Marx to extract four features Harris thinks any adequate pathology-diagnosing theory needs: attention to distorted needs, impeded consciousness, self-perpetuating social logics, and historical materialism's account of constitutive power. Part III argues that Fromm's concept of &quot;pathological normalcy,&quot; complemented by Marcuse's account of the &quot;technical a priori&quot; and repressive desublimation, satisfies all four where Honneth's recognition theory satisfies none.</p>\n<h3 id=\"the-strongest-chapter-is-the-demolition-not-the-reconstruction\" tabindex=\"-1\">The strongest chapter is the demolition, not the reconstruction <a class=\"header-anchor\" href=\"#the-strongest-chapter-is-the-demolition-not-the-reconstruction\">#</a></h3>\n<p>Chapter 2, &quot;Distorted by recognition,&quot; is the book's best material, and it earns that status through concreteness rather than abstraction. Harris doesn't just assert that Honneth's anthropology of universal recognition needs is too thin; he tests it against cases designed to break it. Children and adults with profound cognitive impairment don't participate in the &quot;love, respect, esteem&quot; triad Honneth's theory requires, yet plainly have rich intersubjective lives that a genuinely universal theory ought to capture. Fanon's colonial subject, locked by Harris's reading into &quot;crushing object-hood,&quot; has no access to the reciprocal recognition Honneth's framework presupposes as available to any subject whatsoever. Most pointed of all is Harris's thought experiment about a husband and wife with radically unequal, and one abusive, claims to recognition within their own household: if recognition alone is the normative currency, what adjudicates between a misogynist's demand for deference and a housewife's demand that her unpaid labor be acknowledged, and what happens when the abused partner has been socialized to experience coercion as love? Harris's answer, that &quot;one's feeling of recognition is not evidence of a justifiable normative grammar,&quot; is a genuinely damaging point against a theory that grounds its normativity in exactly that feeling. This is critical theory doing what it claims to do best: using a hard case to expose what a seemingly universal category quietly excludes.</p>\n<h3 id=\"where-the-positive-program-thins-out\" tabindex=\"-1\">Where the positive program thins out <a class=\"header-anchor\" href=\"#where-the-positive-program-thins-out\">#</a></h3>\n<p>The trouble is that Part III, which is supposed to deliver the alternative, argues by exposition more than by argument. The chapters on Fromm are largely careful, sympathetic paraphrase of <em>The Sane Society</em> and <em>To Have or To Be</em>, establishing that Fromm held capitalism to be objectively pathological because it produces alienation, and that this &quot;pathological normalcy&quot; is reproduced through what Fromm called consensual validation. That's a fair reconstruction of Fromm, but it does not do to Fromm what chapter 2 did to Honneth. Harris never subjects Fromm's own universalizing claims, the appeal to a fixed &quot;normative humanism&quot; and to &quot;laws which govern mental and emotional functioning,&quot; to anything like the same adversarial pressure. A theory that grounds pathology in a trans-historical human nature is at least as vulnerable to the post-structuralist and decolonial objections Harris raises against Honneth, and the book gestures at this (&quot;such an account was submitted before the rise of post-modernism&quot;) without following through.</p>\n<p>Harris is candid about a second limitation, and to his credit states it plainly in the conclusion: he is &quot;not a psychoanalyst,&quot; and the Freudian machinery that made Fromm's account cohere in the first place is imported rather than defended. He also concedes the Fromm-Marcuse synthesis is offered as &quot;a sketch,&quot; &quot;one possible avenue,&quot; not a completed research program. That candor is appreciated, but it means the book's title promise, an account of critical theory beyond recognition, is redeemed mostly in its negative half. The positive half is closer to an annotated reading list for where such a program might go.</p>\n<h3 id=\"the-polemical-register-cuts-both-ways\" tabindex=\"-1\">The polemical register cuts both ways <a class=\"header-anchor\" href=\"#the-polemical-register-cuts-both-ways\">#</a></h3>\n<p>Harris writes with real energy, and the book is more readable than most social theory in this vein. But the preface's asides about Partygate, pizza-restaurant conspiracy theories, and Boris Johnson, along with the recurring &quot;bonkers&quot; framing, sit oddly next to the philosophical precision of chapter 2. The tone is calibrated for an activist readership Harris explicitly wants to win back to the Frankfurt School, and it succeeds at signaling where his sympathies lie. It is less successful as argument: calling Honneth's work &quot;quiescent&quot; and folding him in with Rawls as institutionally irrelevant to &quot;XR activists&quot; is rhetorically satisfying but does not by itself show the theory is wrong, and Harris sometimes lets the rhetorical move stand in for the philosophical one. The cast of interlocutors is also narrower than the book's ambitions suggest. Nancy Fraser, Michael J. Thompson, and Gerard Delanty (Harris's doctoral supervisor, thanked at length in the preface) supply most of the critical vocabulary, and the book reads at points like an extended elaboration of Thompson's <em>The Domestication of Critical Theory</em> rather than an independent intervention.</p>\n<h3 id=\"how-it-holds-up\" tabindex=\"-1\">How it holds up <a class=\"header-anchor\" href=\"#how-it-holds-up\">#</a></h3>\n<p>Written during the pandemic and explicitly responding to it, the book's political urgency, the sense that critical theory needs to catch up to Andreas Malm and climate-emergency Marxism, has aged into a period piece faster than its theoretical content has. That's not a serious mark against it; social theory written in real time about a live crisis usually reads this way a few years on. More durable is the conceptual apparatus itself: the four-feature reconstruction of Rousseau-Hegel-Marx pathology diagnosis in Part II is a genuinely useful piece of intellectual history, independent of whether one buys the Fromm-Marcuse payoff, and would be worth assigning on its own in a graduate seminar on the Frankfurt School's philosophical foundations.</p>\n<h3 id=\"verdict\" tabindex=\"-1\">Verdict <a class=\"header-anchor\" href=\"#verdict\">#</a></h3>\n<p>Read chapter 2 for the argument, read Part II for the intellectual history, and treat Part III as a promissory note rather than a finished theory. Harris is at his best when he is dismantling a rival position with a well-chosen hard case, and <em>Critical Theory and Social Pathology</em> contains one of the more effective takedowns of Honneth's recognition paradigm currently in print. It is considerably less persuasive when it needs to do constructive work, and the gap between the book's polemical confidence and the modesty of its actual proposal, a modesty Harris himself acknowledges in the final pages, is the honest measure of what this book accomplishes and what it leaves for someone else to finish.</p>\n",
			"date_published": "2026-07-13T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/review-riley-mindful-design/",
			"url": "https://www.adamdjbrett.com/blog/review-riley-mindful-design/",
			"title": "Review: *Mindful Design: A Survival Guide for Responsible Product Designers*",
			"content_html": "<blockquote>\n<p>Riley, Scott. 2024. <em>Mindful Design: A Survival Guide for Responsible Product Designers</em>. 2nd ed. New York: Apress. ISBN 979-8-8688-0142-6.</p>\n</blockquote>\n<p>Scott Riley's <em>Mindful Design</em>, now in a substantially revised second edition, positions itself at the intersection of cognitive psychology, neuroscience, and interaction design, arguing that the discipline's vocabulary of &quot;conversion,&quot; &quot;activation,&quot; and &quot;engagement&quot; has quietly imported the logic of behaviorist manipulation into everyday digital life. Riley, an independent UX designer and frequent conference speaker, writes not as an academic but as a practitioner attempting to smuggle empirical rigor into a field he regards as too often driven by persuasive-design orthodoxy and growth-hacking incentives. The book's animating claim is that design is &quot;emotional manipulation&quot; in the most literal sense—a mechanism for eliciting changes in the brain—and that this fact obliges designers to accept responsibility for the psychological costs, as well as the benefits, of their decisions.</p>\n<p>The book is organized in two parts that mirror the classic theory-to-practice arc of design pedagogy. Part I, &quot;The Theory,&quot; surveys attention and distraction, the default mode network, heuristics and cognitive miserliness, learning and mental models, schema violation and surprise, and—in its most polemical stretch—reward, dopamine, and Self-Determination Theory (SDT). Here Riley's chief target is the popular but, in his telling, scientifically threadbare notion that dopamine functions as a &quot;pleasure chemical&quot; that variable-ratio reward schedules can be engineered to exploit. Drawing on Deci and Ryan's SDT, he argues that autonomy, competence, and relatedness—not slot-machine-style intermittent reinforcement—are the legitimate levers of intrinsic motivation, and that behaviorist &quot;hooks&quot; are not merely ethically dubious but empirically misapplied. Part II, &quot;The Project,&quot; pivots to an extended, worked case study—the design of a journaling application—through which Riley demonstrates how the theoretical material cashes out in principles, workshops, prototyping decisions, and a running commentary on process frameworks such as the Double Diamond.</p>\n<p>Riley's synthesis of secondary literature is genuinely useful. He moves fluently between Kahneman and Tversky's heuristics-and-biases program, Fiske and Taylor's cognitive miser theory, Mason et al.'s work on the default mode network, and the self-determination literature, translating each into design-actionable language without excessive oversimplification. The chapter on &quot;purposeful pessimism&quot;—a repurposing of Edward de Bono's &quot;black hat&quot; thinking as a structured antidote to designer hubris—is a genuine practical contribution, and the case studies of failure (Facebook's &quot;Year in Review&quot; surfacing photographs of deceased relatives, Twitter's slow capitulation to platformed extremism) are well chosen and argued with more precision than the book's looser rhetorical passages. The decision to build the second half around a single sustained project, rather than a scattershot of vignettes, gives the practice section a coherence that many design-methodology books lack.</p>\n<p>The book's weaknesses are, however, bound up with its greatest strength: its voice. Riley writes in a register that is deliberately profane, autobiographical, and politically pointed, folding commentary on capitalism, venture capital, Elon Musk's acquisition of Twitter, and the demographic homogeneity of the tech industry into what is nominally a cognitive-science primer. Readers sympathetic to this framing will find it energizing and honest about design's complicity in surveillance capitalism; readers seeking a more measured, theory-first treatment may find the polemical asides—however well-taken—dilute the empirical argument and date the text to a specific cultural moment. More substantively, the scientific claims, while generally sound, are conveyed almost entirely through popular secondary sources and journalistic framing rather than direct engagement with primary literature, and the book does not always distinguish between well-replicated findings (attentional switching costs, the reality of the default mode network) and more contested territory (the causal role of dopamine in motivation, the generalizability of SDT across product contexts). As a work of applied psychology, it is stronger as provocation and synthesis than as a rigorously sourced literature review, and specialists in cognitive science may wish for more caveats around the studies it cites.</p>\n<p>Within its own genre—the practitioner monograph aimed at working designers—<em>Mindful Design</em> succeeds. It offers a coherent ethical vocabulary for resisting &quot;dark pattern&quot; and addiction-by-design logics, grounds that vocabulary in legitimate psychological research, and demonstrates its application through a sustained, plausible case study rather than isolated maxims. It will be of most value to UX and product designers, design educators building curricula around ethics and cognition, and researchers interested in how psychological science is popularized and operationalized within the tech industry. It is less suited to readers wanting a dispassionate academic treatment of attention, motivation, or persuasion, who would do better to consult the primary literature Riley draws upon directly. As an argument for reorienting design away from behaviorist manipulation and toward genuine human flourishing, however, it is a lucid, if unapologetically opinionated, contribution.</p>\n",
			"date_published": "2026-07-11T17:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/remote-development-with-blit-and-moo/",
			"url": "https://www.adamdjbrett.com/blog/remote-development-with-blit-and-moo/",
			"title": "Remote Development from Any Browser with blit.sh and moo",
			"content_html": "<p><em>I wrote this for a good friend of mine to explain how I have started using two new tools made by <a href=\"https://pcarrier.com\">pcarrier.com</a></em></p>\n<hr>\n<p>For years, remote development has meant one of two things: a bare SSH session in a terminal emulator, or a heavyweight solution like VS Code Remote or a cloud IDE that drags an entire editor stack across the wire. Two newer tools — <a href=\"https://blit.sh\">blit</a> and <a href=\"https://moo.pcarrier.com/\">moo</a> — suggest a third path. Run your tools on the remote machine, and reach all of them through a browser tab.</p>\n<p>The pairing works because the two tools solve complementary halves of the problem. Blit streams terminals (and, experimentally, GUI apps) to any browser with low latency. Moo gives you a browser-based workbench for coding agents — chat, diffs, tool traces, and persistent memory — running against the repositories on whatever machine it's installed on. Put both on a remote box and you have a complete development environment: an AI agent doing the heavy lifting in moo, and real terminals in blit for everything else.</p>\n<h2 id=\"what-blit-is\" tabindex=\"-1\">What blit is <a class=\"header-anchor\" href=\"#what-blit-is\">#</a></h2>\n<p><a href=\"https://github.com/indent-com/blit\">Blit</a> describes itself as a terminal multiplexer and experimental Wayland compositor for browsers and AI agents. It's a single binary with no required dependencies. The core trick: it runs your PTYs on the host and streams delta-compressed updates to a WebGL renderer in the browser, so a terminal in a browser tab feels close to native.</p>\n<p>Three features matter for remote development.</p>\n<p>First, <strong>sharing over WebRTC</strong>. <code>blit share</code> prints a URL you can open from anywhere — or hand to a teammate for real-time access to the same terminal. Because it's WebRTC, it punches through NAT without SSH keys or port forwarding.</p>\n<p>Second, <strong>named SSH remotes with auto-install</strong>. You register a remote once, and blit installs itself on the far end the first time you connect. The remote machine only needs curl or wget and CA certificates.</p>\n<p>Third, <strong>terminals as an API</strong>. Scripts — or AI agents — can start processes, send keystrokes, wait for output patterns, and read screen contents as text. This is what makes blit more than a fancy SSH client; it's a programmable surface for automation.</p>\n<h2 id=\"what-moo-is\" tabindex=\"-1\">What moo is <a class=\"header-anchor\" href=\"#what-moo-is\">#</a></h2>\n<p><a href=\"https://github.com/pcarrier/moo\">Moo</a>, by Pierre Carrier, is a local-first agent harness you drive from a browser UI and inspect while it works. Under the hood it's a Rust host embedding a V8 runtime for TypeScript tools, with SQLite for durable state. On top, a Solid-based web shell shows chat, timelines, diffs, tool calls, and memory side by side.</p>\n<p>The design choices that stand out:</p>\n<ul>\n<li><strong>Scratch worktrees.</strong> Each chat gets an isolated worktree with git or jj context, so agent changes stay quarantined from your main checkout until you decide to keep them.</li>\n<li><strong>Inspectable everything.</strong> Tool calls, memory snapshots, and source views are all first-class in the UI. You watch the agent work rather than trusting a summary.</li>\n<li><strong>Durable memory.</strong> Moo stores RDF-based facts you can assert, retract, patch, and query — globally or per project — so context survives across sessions.</li>\n<li><strong>Provider-agnostic.</strong> It coordinates credentials for OpenAI, Anthropic, Qwen, GLM, xAI, DeepSeek, and Kimi.</li>\n</ul>\n<p>Moo is explicitly <em>not</em> a hosted service. It's built for local agents, on the theory that local privileges matter: the agent works with direct filesystem and process access inside workspaces you configure. That sounds like the opposite of remote development — until you realize &quot;local&quot; just means local to wherever moo runs.</p>\n<h2 id=\"the-recipe-local-first-tools-on-a-remote-machine\" tabindex=\"-1\">The recipe: local-first tools on a remote machine <a class=\"header-anchor\" href=\"#the-recipe-local-first-tools-on-a-remote-machine\">#</a></h2>\n<p>The pattern is simple: install both tools on the remote machine (a VPS, a homelab box, a beefy workstation at the office), then reach their browser UIs from wherever you are.</p>\n<h3 id=\"1-install-on-the-remote-host\" tabindex=\"-1\">1. Install on the remote host <a class=\"header-anchor\" href=\"#1-install-on-the-remote-host\">#</a></h3>\n<p>SSH in once, then:</p>\n<pre class=\"language-sh\" tabindex=\"0\"><code class=\"language-sh\"><span class=\"token function\">curl</span> <span class=\"token parameter variable\">-sf</span> https://install.blit.sh <span class=\"token operator\">|</span> <span class=\"token function\">sh</span>\n<span class=\"token function\">curl</span> <span class=\"token parameter variable\">-sf</span> https://moo.pcarrier.com/install <span class=\"token operator\">|</span> <span class=\"token function\">sh</span></code></pre>\n<p>Both installers drop a single binary. (On Windows, the PowerShell equivalents are <code>irm https://install.blit.sh/install.ps1 | iex</code> and <code>irm https://moo.pcarrier.com/install.ps1 | iex</code>.) Note that blit's full feature set — including the Wayland compositor for GUI streaming — is Linux-only; macOS and Windows get PTY multiplexing.</p>\n<h3 id=\"2-register-the-remote-with-blit-on-your-laptop\" tabindex=\"-1\">2. Register the remote with blit on your laptop <a class=\"header-anchor\" href=\"#2-register-the-remote-with-blit-on-your-laptop\">#</a></h3>\n<p>Install blit locally too, then teach it about your server:</p>\n<pre class=\"language-sh\" tabindex=\"0\"><code class=\"language-sh\">blit remote <span class=\"token function\">add</span> dev ssh:you@dev.example.com\nblit remote set-default dev</code></pre>\n<p>From now on, <code>blit --on dev terminal list</code> shows what's running on the server, and <code>blit open</code> gives you a browser interface to it. Blit auto-installs on the remote on first connect, so if you skipped step 1 for blit, this handles it.</p>\n<h3 id=\"3-start-moo-on-the-remote\" tabindex=\"-1\">3. Start moo on the remote <a class=\"header-anchor\" href=\"#3-start-moo-on-the-remote\">#</a></h3>\n<p>On the server:</p>\n<pre class=\"language-sh\" tabindex=\"0\"><code class=\"language-sh\">moo serve</code></pre>\n<p>This starts the workbench UI. Since moo binds locally by design, tunnel the port over SSH from your laptop:</p>\n<pre class=\"language-sh\" tabindex=\"0\"><code class=\"language-sh\"><span class=\"token function\">ssh</span> <span class=\"token parameter variable\">-L</span> <span class=\"token number\">8080</span>:localhost:8080 you@dev.example.com</code></pre>\n<p>(Substitute whatever port <code>moo serve</code> reports.) Open the forwarded port in your browser and you're in the workbench — chat, diffs, and tool traces for agents running against the repos on your server, with all the privileges of a local process there.</p>\n<h3 id=\"4-work\" tabindex=\"-1\">4. Work <a class=\"header-anchor\" href=\"#4-work\">#</a></h3>\n<p>A concrete session looks like this. In one tab, moo's workbench: you start a chat from a project directory, moo creates a scratch worktree, and the agent begins making changes you can watch as diffs and tool calls. In another tab, blit: real terminals on the same machine for running tests, tailing logs, or poking at anything the agent shouldn't touch.</p>\n<p>Blit's scripting surface even lets you close the loop between the two. Kick off a long build and block on the result:</p>\n<pre class=\"language-sh\" tabindex=\"0\"><code class=\"language-sh\">blit terminal start <span class=\"token parameter variable\">-t</span> build <span class=\"token function\">make</span> <span class=\"token parameter variable\">-j8</span>\nblit terminal <span class=\"token function\">wait</span> <span class=\"token number\">1</span> <span class=\"token parameter variable\">--pattern</span> <span class=\"token string\">'BUILD OK'</span>\nblit terminal show <span class=\"token number\">1</span></code></pre>\n<p>An agent — moo's or anyone else's — can drive that same interface: start a process, wait for a pattern, read the screen. Your terminals become tools the agent can use, with you watching over its shoulder in the same browser.</p>\n<h3 id=\"5-share-when-you-need-another-pair-of-eyes\" tabindex=\"-1\">5. Share when you need another pair of eyes <a class=\"header-anchor\" href=\"#5-share-when-you-need-another-pair-of-eyes\">#</a></h3>\n<p>When you want a colleague to look at something, don't screen-share a video of a terminal:</p>\n<pre class=\"language-sh\" tabindex=\"0\"><code class=\"language-sh\">blit share</code></pre>\n<p>Send the URL. They get the actual terminal, live, in their browser — no accounts, no SSH keys, no VPN.</p>\n<h2 id=\"using-moo-for-local-web-development-with-11ty\" tabindex=\"-1\">Using moo for local web development with 11ty <a class=\"header-anchor\" href=\"#using-moo-for-local-web-development-with-11ty\">#</a></h2>\n<p>The recipe above treats moo as a remote tool, but its home turf is your own laptop — and static site work is a perfect fit. My site runs on <a href=\"https://www.11ty.dev/\">Eleventy</a>, and an 11ty project is exactly the kind of codebase an agent workbench shines on: lots of small, legible files (Nunjucks templates, Markdown content, a config file), fast builds, and instant visual feedback.</p>\n<p>The workflow: run <code>moo serve</code> on your laptop, open the workbench, and start a chat from the site's project directory. Moo creates a scratch worktree, so the agent's experiments never touch your working checkout. Then hand it the kind of tasks that eat an afternoon when done by hand — porting a theme's layouts to Nunjucks (I've been converting Ghost's Headline theme this way), wiring up <code>@11ty/eleventy-img</code> for responsive images, restructuring front matter across dozens of posts, or writing a collection filter you've been putting off.</p>\n<p>Because moo's tools include process access, the agent can run the build itself:</p>\n<pre class=\"language-sh\" tabindex=\"0\"><code class=\"language-sh\">npx @11ty/eleventy <span class=\"token parameter variable\">--serve</span></code></pre>\n<p>You watch the tool calls and diffs in one pane while the dev server output streams in another. When the changes look right in the diff view — and in the live preview at <code>localhost:8080</code> — you merge the worktree. When they don't, you throw the worktree away and nothing happened.</p>\n<p>The durable memory is the underrated part for site work. Assert facts like &quot;layouts live in <code>_includes</code>,&quot; &quot;posts use the <code>post</code> tag,&quot; or &quot;image shortcodes go through eleventy-img&quot; once, and every future chat starts already knowing your site's conventions instead of rediscovering them.</p>\n<h2 id=\"using-blit-for-remote-web-development-with-11ty\" tabindex=\"-1\">Using blit for remote web development with 11ty <a class=\"header-anchor\" href=\"#using-blit-for-remote-web-development-with-11ty\">#</a></h2>\n<p>The same 11ty project works from the other direction too: keep the site building on a remote machine and drive it through blit. This is handy when your laptop is underpowered, when the site's asset pipeline is heavy, or when you just want a build that keeps running after you close the lid.</p>\n<p>Start the dev server in a named blit terminal on your remote:</p>\n<pre class=\"language-sh\" tabindex=\"0\"><code class=\"language-sh\">blit <span class=\"token parameter variable\">--on</span> dev terminal start <span class=\"token parameter variable\">-t</span> site npx @11ty/eleventy <span class=\"token parameter variable\">--serve</span>\nblit <span class=\"token parameter variable\">--on</span> dev terminal <span class=\"token function\">wait</span> <span class=\"token number\">1</span> <span class=\"token parameter variable\">--pattern</span> <span class=\"token string\">'Server at'</span></code></pre>\n<p>The <code>wait</code> command blocks until Eleventy prints its &quot;Server at&quot; line, which makes this scriptable — a deploy script or an agent can start the server and know exactly when it's ready. <code>blit open</code> gives you the terminal in a browser tab from anywhere.</p>\n<p>One clarification worth being explicit about: blit streams <em>terminals</em>, not HTTP. To see the rendered site, tunnel Eleventy's port alongside your session:</p>\n<pre class=\"language-sh\" tabindex=\"0\"><code class=\"language-sh\"><span class=\"token function\">ssh</span> <span class=\"token parameter variable\">-L</span> <span class=\"token number\">8080</span>:localhost:8080 you@dev.example.com</code></pre>\n<p>Now the terminal lives in a blit tab and the live preview lives at <code>localhost:8080</code>, both fed by the remote machine. And when you want a second opinion on a template bug, <code>blit share</code> hands a collaborator the actual terminal — they can scroll your build errors themselves instead of squinting at a screenshot.</p>\n<h2 id=\"using-moo-for-local-document-and-transcript-conversion\" tabindex=\"-1\">Using moo for local document and transcript conversion <a class=\"header-anchor\" href=\"#using-moo-for-local-document-and-transcript-conversion\">#</a></h2>\n<p>The third use case has nothing to do with web servers: moo as a harness for the document-conversion toolchain I use to make teaching materials and podcasts accessible.</p>\n<p>The underlying tools are the usual command-line suspects. On a Mac:</p>\n<pre class=\"language-sh\" tabindex=\"0\"><code class=\"language-sh\">brew <span class=\"token function\">install</span> ocrmypdf tesseract poppler exiftool pandoc</code></pre>\n<p>plus OpenAI's Whisper for transcription. Over time these have accreted into a small set of scripts (mine live in <code>~/github/personal/scripts</code>):</p>\n<ul>\n<li><strong><code>ocr-a11y-pdf.py</code></strong> — runs scanned PDFs through OCRmyPDF and Tesseract so they carry a real text layer. A scanned reading that a screen reader sees as blank images becomes a searchable, readable document.</li>\n<li><strong><code>pdf-to-html.py</code></strong> — converts PDFs to HTML (via Poppler and pandoc), because for many students HTML is simply a better format than PDF: reflowable on a phone, zoomable without horizontal scrolling, friendlier to assistive technology.</li>\n<li><strong><code>pdf_markdown_conversion_script</code></strong> — the same idea aimed at Markdown, which makes course readings easy to excerpt, annotate, and republish on an 11ty site.</li>\n<li><strong><code>apple-m1-transcribe.py</code></strong> — runs Whisper transcription locally on Apple Silicon, so every podcast episode and recorded lecture gets a transcript without shipping audio to a cloud service.</li>\n</ul>\n<p>Each script is simple on its own. The tedium is in the batches: a semester's worth of scanned readings, a back catalog of podcast episodes. This is where moo earns its place. Point a chat at the scripts directory, and the agent can run the tools as processes — OCR this folder of PDFs, transcribe these twelve episodes, convert the results to HTML, fix the metadata with exiftool — while every invocation and its output stays inspectable in the timeline. When a file fails (and one always fails), you can see exactly which command choked and why, rather than excavating a log file.</p>\n<p>The accessibility framing is the point, not a bonus. A course reading that exists only as a crooked scan excludes students who use screen readers; a podcast without a transcript excludes Deaf and hard-of-hearing listeners, and everyone who'd rather skim than listen. Transcripts and true-text documents also make material searchable, quotable, and translatable. These conversions are exactly the kind of work that gets skipped because it's tedious — and exactly the kind of work an inspectable local agent, with private access to your files and no cloud upload, is suited to grind through.</p>\n<h2 id=\"why-this-combination-works\" tabindex=\"-1\">Why this combination works <a class=\"header-anchor\" href=\"#why-this-combination-works\">#</a></h2>\n<p>The deeper appeal here is architectural. Both tools reject the model where your development environment lives inside someone else's cloud. Blit is a single dependency-free binary; moo requires no hosted backend. Everything — code, agent memory, terminal state — stays on hardware you control. The browser is just a viewport.</p>\n<p>That inverts the usual trade-off of remote development. Traditionally you gave up locality (and often privacy) to get access-from-anywhere. With blit and moo, the machine doing the work keeps full local privileges — moo's whole premise — while you keep access from any device with a browser. The &quot;remote&quot; in remote development stops meaning &quot;diminished.&quot;</p>\n<p>A few caveats. Blit's Wayland/GUI streaming is explicitly experimental, and its full feature set assumes Linux on the server. Moo is young and moving fast (<code>moo upgrade</code> will be a regular habit). And because moo grants agents real filesystem and process access, treat the machine it runs on accordingly — a dedicated dev box or VM, not your production server.</p>\n<p>But as a sketch of where remote development is heading — agents in one tab, terminals in another, everything running on your own machine, reachable from anywhere — this pairing is the most convincing one I've tried.</p>\n<h2 id=\"links\" tabindex=\"-1\">Links <a class=\"header-anchor\" href=\"#links\">#</a></h2>\n<ul>\n<li>blit: <a href=\"https://blit.sh\">https://blit.sh</a> · <a href=\"https://github.com/indent-com/blit\">https://github.com/indent-com/blit</a></li>\n<li>moo: <a href=\"https://moo.pcarrier.com/\">https://moo.pcarrier.com/</a> · <a href=\"https://github.com/pcarrier/moo\">https://github.com/pcarrier/moo</a></li>\n</ul>\n",
			"date_published": "2026-07-11T14:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/whitestone-v3-reprise-metasearch-fleet/",
			"url": "https://www.adamdjbrett.com/blog/whitestone-v3-reprise-metasearch-fleet/",
			"title": "11tyx5, Reprise: Build Awesome Alpha, a Whitestone Metasearch, and the Quest for Four 100s",
			"content_html": "<p>Eleventy days ago (literally) I wrote about launching five <a href=\"https://thewhitestonefoundation.org\">Whitestone Foundation</a> sites at once and called it <a href=\"/blog/11tyx5\">11tyx5</a>. I ended that post with a small tease: a Version 3 redesign of the flagship site was &quot;in active development,&quot; and the network would keep moving. I did not expect the next chapter to arrive as one overnight sprint, but that is more or less what happened. Between the evening of July 8th and the morning of July 9th, <a href=\"https://thewhitestonefoundation.org\">thewhitestonefoundation.org</a> shipped its v3 rebuild, the whole fleet got a shared search overhaul, <a href=\"https://jcrt.org\">jcrt.org</a>'s search quietly broke and got rebuilt on a sturdier foundation, and I learned a genuinely new lesson about Cloudflare's edge cache that I am still a little annoyed I didn't know already.</p>\n<p>This post is the field report. It covers the Build Awesome alpha upgrade, why I tore out the old cross-site search pipeline, how the new [<code>/metadata/search/</code>(https://thewhitestonefoundation.org/metadata/search/)] page merges five independent Pagefind indexes in the browser with no server involved, what it took to get all five sites onto one build pipeline and one Netlify setup, where the build-time savings actually came from this time, the still-unfinished chase for four 100s in PageSpeed Insights, and the Cloudflare caching bug that made a fixed problem look unfixed for the better part of a day.</p>\n<h2 id=\"upgrading-to-build-awesome-v4-0-0-alpha-10\" tabindex=\"-1\">Upgrading to Build Awesome v4.0.0-alpha.10 <a class=\"header-anchor\" href=\"#upgrading-to-build-awesome-v4-0-0-alpha-10\">#</a></h2>\n<p>I wrote a whole post <a href=\"/blog/2026-07-05-build-awesome-cloudflare-optimization/\">on July 5th</a> about moving a smaller podcast site onto <a href=\"https://www.11ty.dev/\">Build Awesome</a> — the new package identity for Eleventy — and I won't repeat that here except to say the pattern held: <code>npm install @awesome.me/buildawesome --save-dev</code>, pin the alpha exactly in <code>package.json</code>, swap the build script from <code>eleventy</code> to <code>buildawesome</code>, and let Build Awesome carry its own matching Eleventy alpha instead of listing <code>@11ty/eleventy</code> as a direct dependency yourself.</p>\n<p>The <a href=\"https://thewhitestonefoundation.org\">Whitestone v3</a> rebuild went a step further and adopted <a href=\"https://github.com/11ty/buildawesome/releases/tag/v4.0.0-alpha.10\"><code>v4.0.0-alpha.10</code></a> specifically. I went and read the actual release notes before writing this, because &quot;alpha.10&quot; as Bob noted in the <a href=\"https://11tybundle.dev\">11tybundle.dev</a> is not where the exciting new changes happened that is actually in <code>alpha.09.</code> Reading the realse notes for <code>alpha.09</code> helped me realize i need to keep my output file the same and not be a mad man and switch it to dist, so I am trying to aspire to Zach's levels of consistency in my code. The Whitestone config keeps the same explicit <code>dir</code> block it always has.</p>\n<h2 id=\"from-allsites-json-to-metasearch-what-i-tore-out-first\" tabindex=\"-1\">From <code>allsites.json</code> to metasearch: what I tore out first <a class=\"header-anchor\" href=\"#from-allsites-json-to-metasearch-what-i-tore-out-first\">#</a></h2>\n<p>As previously mentioned in  <a href=\"/blog/11tyx5/\"><code>11tyx5</code></a> I tried to use a shared data patterns like <code>allsites.json</code>, an append-only canonical record, and an intentionally opinionated cross-site ranking where <a href=\"https://jcrt.org/archives/\">JCRT's archive</a> outranked the magazine site, which outranked the org page. That system worked, in the sense that it produced ranked results. But it worked the way a lot of first systems work: by being the most obvious thing to build, not the thing you'd choose if you started over.</p>\n<p>Under the hood it was a scheduled ingestion job — <code>ingest-allsites.yml</code> — that crawled the other four Whitestone sites on a cron, ran an embedding model over what it found, and committed the resulting JSON straight into the flagship repo. That bought semantic-ish ranking, at the cost of a genuinely awkward set of tradeoffs: a cron job that could silently stop working, a growing pile of committed JSON that had nothing to do with the site's own content, an embedding step that had to run somewhere, and search results that were only ever as fresh as whenever the job last succeeded. If JCRT published a new archive issue on Tuesday, the org-wide search wouldn't know about it until the next scheduled crawl.</p>\n<p>The v3 rebuild deleted the whole pipeline — the workflow file, the ingestion script, the committed JSON — in the same pass that removed the old semantic-vector search. That's a strange thing to be proud of, ripping out a feature you built on purpose a year earlier, but it's the right kind of strange. The replacement needed to answer the same question — &quot;search everything Whitestone publishes, from one box&quot; — without a cron job, without an embedding model, and without ever being staler than the last time each individual site deployed. That's the metasite work below.</p>\n<h2 id=\"building-a-metasite-metadata-as-infrastructure-pagefind-as-an-api\" tabindex=\"-1\">Building a metasite: metadata as infrastructure, Pagefind as an API <a class=\"header-anchor\" href=\"#building-a-metasite-metadata-as-infrastructure-pagefind-as-an-api\">#</a></h2>\n<p>What replaced the deleted ingestion pipeline is smaller than what it replaced, which is generally the sign you did something right. Here's the architecture, in the order I'd explain it to someone rebuilding this from scratch.</p>\n<h3 id=\"metadata-as-the-control-plane\" tabindex=\"-1\">Metadata as the control plane <a class=\"header-anchor\" href=\"#metadata-as-the-control-plane\">#</a></h3>\n<p>The rebuild's actual thesis is that most of what makes a multi-site network annoying isn't content, it's <em>facts about the sites</em> — titles, taglines, canonical URLs, OG images, footer links — repeated with slight drift across templates until nobody trusts any of them. So v3 puts all of that in one file, <code>src/_data/metadata.yaml</code>, per site:</p>\n<pre class=\"language-yaml\" tabindex=\"0\"><code class=\"language-yaml\"><span class=\"token key atrule\">site_title</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"The Whitestone Foundation\"</span>\n<span class=\"token key atrule\">tagline</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"Fostering critical thought for the public interest.\"</span>\n<span class=\"token key atrule\">url</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"https://thewhitestonefoundation.org\"</span>\n<span class=\"token key atrule\">routes</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">contact</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"/contact/\"</span>\n  <span class=\"token key atrule\">news</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"/news/\"</span>\n<span class=\"token key atrule\">seo</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">ogImage</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">url</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"/images/whitestone-logo.webp\"</span>\n    <span class=\"token key atrule\">width</span><span class=\"token punctuation\">:</span> <span class=\"token number\">1200</span>\n    <span class=\"token key atrule\">height</span><span class=\"token punctuation\">:</span> <span class=\"token number\">630</span>\n  <span class=\"token key atrule\">openGraph</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">type</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"website\"</span>\n  <span class=\"token key atrule\">twitter</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">card</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"summary_large_image\"</span></code></pre>\n<p>A handful of Nunjucks filters — <code>headTitle</code>, <code>headDescription</code>, <code>headImage</code>, <code>canonicalUrl</code>, <code>absUrl</code> — read from this at build time and populate the <code>&lt;head&gt;</code> of every template. Per-post pages get <code>BlogPosting</code> JSON-LD, and a no-JS breadcrumb component emits its own <code>BreadcrumbList</code> JSON-LD alongside the visible trail. None of this involves a runtime; it's Eleventy resolving data into HTML once, at build time, the same way it's always worked. The point isn't novelty, it's that &quot;site metadata&quot; became a data problem instead of a templating-discipline problem. Once you frame it that way, the search feature falls out almost naturally, because a Pagefind index is really just another artifact built from the same finished HTML.</p>\n<h3 id=\"pagefind-as-an-api-not-a-widget\" tabindex=\"-1\">Pagefind as an API, not a widget <a class=\"header-anchor\" href=\"#pagefind-as-an-api-not-a-widget\">#</a></h3>\n<p>Each site's build ends the same way: <code>eleventy</code> builds <code>_site/</code>, esbuild minifies CSS/JS, and then <code>pagefind --site _site --output-subdir pagefind</code> runs last, crawling the <em>already-rendered</em> production HTML and writing a WASM search engine plus index chunks under <code>/pagefind/</code>. There's no server component — a visitor's browser downloads the WASM module and runs the query locally against static files, which is either delightfully retro or the logical endpoint of &quot;static site,&quot; depending on your mood.</p>\n<p>Locally, each site uses Pagefind's newer Component UI rather than the older <code>PagefindUI</code> bundle, lazy-loaded off the critical path:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>pagefind-modal-trigger</span> <span class=\"token attr-name\">role</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>search<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">aria-label</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>Open search<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">compact</span> <span class=\"token attr-name\">hide-shortcut</span><span class=\"token punctuation\">></span></span>...<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>pagefind-modal-trigger</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>pagefind-modal</span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>pagefind-modal</span><span class=\"token punctuation\">></span></span></code></pre>\n<p>The script only loads on idle, on first hover/focus of the trigger, or on Cmd/Ctrl-K — nobody pays the WASM tax until they've expressed intent to search.</p>\n<p>The interesting part, though, isn't the per-site widget. It's that Pagefind's index is <em>addressable and mergeable across origins</em>, which means you can treat it less like a search plugin and more like a read API.</p>\n<p><strong>A Pagefind bundle is a public, versioned, cacheable, CORS-enabled read API for &quot;what does this site contain&quot; — it just happens to be made of static files instead of JSON endpoints.</strong></p>\n<h3 id=\"the-metasearch-page\" tabindex=\"-1\">The metasearch page <a class=\"header-anchor\" href=\"#the-metasearch-page\">#</a></h3>\n<p><code>/metadata/search/</code> on thewhitestonefoundation.org is the site that actually exercises that idea. It's a plain Eleventy template — no special backend, no aggregation job — that uses Pagefind's documented multisite API to merge four other sites' indexes into its own, live, in the visitor's browser:</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\"><span class=\"token keyword\">await</span> <span class=\"token keyword\">import</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/pagefind/pagefind-component-ui.js'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> configureInstance <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> window<span class=\"token punctuation\">.</span>PagefindComponents<span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> remotes <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n  <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">bundlePath</span><span class=\"token operator\">:</span> <span class=\"token string\">'https://jcrt.org/pagefind/'</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">mergeFilter</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">Site</span><span class=\"token operator\">:</span> <span class=\"token string\">'JCRT'</span> <span class=\"token punctuation\">}</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">bundlePath</span><span class=\"token operator\">:</span> <span class=\"token string\">'https://thenewpolis.com/pagefind/'</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">mergeFilter</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">Site</span><span class=\"token operator\">:</span> <span class=\"token string\">'The New Polis'</span> <span class=\"token punctuation\">}</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">bundlePath</span><span class=\"token operator\">:</span> <span class=\"token string\">'https://journal.thenewpolis.com/pagefind/'</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">mergeFilter</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">Site</span><span class=\"token operator\">:</span> <span class=\"token string\">'The New Polis Journal'</span> <span class=\"token punctuation\">}</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">bundlePath</span><span class=\"token operator\">:</span> <span class=\"token string\">'https://esthesis.org/pagefind/'</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">mergeFilter</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">Site</span><span class=\"token operator\">:</span> <span class=\"token string\">'Esthesis'</span> <span class=\"token punctuation\">}</span> <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> probes <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> Promise<span class=\"token punctuation\">.</span><span class=\"token function\">allSettled</span><span class=\"token punctuation\">(</span>\n  remotes<span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">r</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>r<span class=\"token punctuation\">.</span>bundlePath<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">pagefind-entry.json</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">method</span><span class=\"token operator\">:</span> <span class=\"token string\">'HEAD'</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">mode</span><span class=\"token operator\">:</span> <span class=\"token string\">'cors'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> reachable <span class=\"token operator\">=</span> remotes<span class=\"token punctuation\">.</span><span class=\"token function\">filter</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">r<span class=\"token punctuation\">,</span> i</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> probes<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>status <span class=\"token operator\">===</span> <span class=\"token string\">'fulfilled'</span> <span class=\"token operator\">&amp;&amp;</span> probes<span class=\"token punctuation\">[</span>i<span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>value<span class=\"token punctuation\">.</span>ok<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> unreachable <span class=\"token operator\">=</span> remotes<span class=\"token punctuation\">.</span><span class=\"token function\">filter</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">r</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token operator\">!</span>reachable<span class=\"token punctuation\">.</span><span class=\"token function\">includes</span><span class=\"token punctuation\">(</span>r<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>unreachable<span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  console<span class=\"token punctuation\">.</span><span class=\"token function\">warn</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Metasearch: skipping unreachable indexes:'</span><span class=\"token punctuation\">,</span> unreachable<span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">r</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> r<span class=\"token punctuation\">.</span>bundlePath<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token function\">configureInstance</span><span class=\"token punctuation\">(</span><span class=\"token string\">'allsites'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">bundlePath</span><span class=\"token operator\">:</span> <span class=\"token string\">'/pagefind/'</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">mergeFilter</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">Site</span><span class=\"token operator\">:</span> <span class=\"token string\">'Whitestone Foundation'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">mergeIndex</span><span class=\"token operator\">:</span> reachable\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\ndocument<span class=\"token punctuation\">.</span><span class=\"token function\">getElementById</span><span class=\"token punctuation\">(</span><span class=\"token string\">'allsites-search'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>innerHTML <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">\n  &lt;pagefind-input instance=\"allsites\" placeholder=\"Search all Whitestone sites\">&lt;/pagefind-input>\n  &lt;pagefind-filter-dropdown instance=\"allsites\" filter=\"Site\">&lt;/pagefind-filter-dropdown>\n  &lt;pagefind-summary instance=\"allsites\">&lt;/pagefind-summary>\n  &lt;pagefind-results instance=\"allsites\">&lt;/pagefind-results>\n</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span></code></pre>\n<p><code>configureInstance</code> creates a named search instance; <code>mergeIndex</code> tells it to pull in other Pagefind bundles alongside its own local one; <code>mergeFilter</code> tags results from each merged index with a <code>Site</code> value so a <code>pagefind-filter-dropdown</code> can let visitors narrow to one publication after the fact — without needing to tag every individual page on every individual site. For any of this to work, each remote's <code>/pagefind/*</code> path needs <code>Access-Control-Allow-Origin: *</code>, since the browser is fetching another origin's index files directly.</p>\n<p>The <code>Promise.allSettled</code> probe block exists because of a failure mode I hit almost immediately: if one remote site is down, misconfigured, or its CORS headers are wrong, <code>mergeIndex</code> doesn't fail cleanly — the whole merged instance can just hang, and the visitor sees a permanent &quot;Connecting to all Whitestone sites…&quot; with nothing ever resolving. Probing each remote's <code>pagefind-entry.json</code> with a <code>HEAD</code> request before merging means one publication having a bad day degrades gracefully — its results are silently absent — instead of taking down search for the other four. There's also a <code>&lt;noscript&gt;</code> fallback linking to each site's own <code>/search/</code> page, since the entire mechanism is inert without JavaScript.</p>\n<h3 id=\"the-gotcha-version-skew-is-a-silent-failure-not-a-loud-one\" tabindex=\"-1\">The gotcha: version skew is a silent failure, not a loud one <a class=\"header-anchor\" href=\"#the-gotcha-version-skew-is-a-silent-failure-not-a-loud-one\">#</a></h3>\n<p>Once this was wired up, I noticed <a href=\"https://jcrt.org\">JCRT results</a> in the merged search were thin — a couple of weak matches where there should have been dozens. The cause wasn't CORS, and it wasn't the filter logic. It was that <a href=\"https://jcrt.org\">jcrt.org</a>'s Pagefind index had been built with Pagefind 1.4.0, while the metasearch page and every other site were on 1.5.x. A 1.5 engine merging an index built by 1.4 doesn't error — it just quietly returns partial or degraded results. No exception, no console warning, just a search box that seemed to work while being wrong.</p>\n<p>The fix was to bump jcrt-v2's <code>pagefind</code> devDependency to <code>^1.5.2</code>, and, more importantly, to fold the installed Pagefind version into the build's cache-invalidation signature — so a future version bump anywhere in the network can't silently reuse an index built by a stale binary. After the fix, a search for &quot;Christian Discovery&quot; went from 1 result to 132, with the JCRT 25.1 archive article landing at #3, right where it belonged.</p>\n<p>The lesson generalizes past Pagefind: treating static files as an API doesn't exempt you from API compatibility contracts. If five independently-deployed sites are going to have their indexes merged by a shared client, those indexes need to come from compatible versions of the same tool — and because the failure mode is silent degradation rather than a thrown error, you need to go looking for it rather than wait for it to announce itself.</p>\n<p>What I like about the end state is how small the integration surface is. Each site stays independently deployable and owns its own index; the flagship site is just the client that composes them. Adding a sixth Whitestone publication later means: publish its Pagefind bundle with CORS enabled, add one object to the <code>remotes</code> array. That's the whole contract — which is a nice place to be after ripping out a whole embeddings pipeline, and sets up the next problem, which is keeping five separately-deployed repos honest about the shared metadata and build conventions that make this composability possible in the first place.</p>\n<h2 id=\"getting-five-sites-to-share-one-build-one-11ty-config-shape-and-one-netlify-setup\" tabindex=\"-1\">Getting five sites to share one build, one 11ty config shape, and one Netlify setup <a class=\"header-anchor\" href=\"#getting-five-sites-to-share-one-build-one-11ty-config-shape-and-one-netlify-setup\">#</a></h2>\n<p>None of the metasearch work above means anything if the other four sites can't produce a Pagefind bundle that's reachable, current, and CORS-friendly. So the second half of the July 8–9 sprint was fleet work: bringing <a href=\"https://jcrt.org\">jcrt.org</a>, <a href=\"https://thenewpolis.com\">thenewpolis.com</a>, <a href=\"https://journal.thenewpolis.com\">journal.thenewpolis.com</a>, and <a href=\"https://esthesis.org\">esthesis.org</a> up to a shared baseline, one site at a time, mostly by spawning one subagent per repository and giving each the same short brief: adopt Pagefind's Component UI, add the CORS headers the org search needs, and make sure the local search on that site actually works while you're in there.</p>\n<p>The rollout looked like this across the fleet:</p>\n<ul>\n<li><a href=\"https://github.com/The-Whitestone-Foundation/thenewpolis.com\"><strong>thenewpolis.com</strong> on github</a> — <code>/search/</code> converted from the legacy <code>PagefindUI</code> widget to Component UI (the rest of the site's search plumbing was already there). The site indexes 1,914 pages.</li>\n<li><a href=\"https://github.com/The-Whitestone-Foundation/journal.thenewpolis.com\"><strong>journal.thenewpolis.com</strong> on github</a> — legacy <code>/search/</code> converted the same way, and a leftover hack that had excluded Component UI assets from the search page (to stop two search widgets from colliding) got deleted now that only one widget exists. <code>data-pagefind-body</code> was added to <code>&lt;main&gt;</code> so indexing scopes to actual content instead of the whole page shell.</li>\n<li><a href=\"https://github.com/The-Whitestone-Foundation/thewhitestonefoundation.org\"><strong>thewhitestonefoundation.org</strong> on github</a> — Pagefind bumped <code>1.4.0 → 1.5.2</code>, <code>/search/</code> converted, a dead <code>processResult</code> handler removed.</li>\n<li><a href=\"https://github.com/The-Whitestone-Foundation/esthesis-v2\"><strong>esthesis-v2</strong> on github</a> — bumped to Pagefind 1.5 and a stale <code>pagefind-ui</code> passthrough copy removed. A user report (&quot;results just show the site title and 'skip to main'&quot;) turned into a real quality pass: <code>data-pagefind-body</code> on <code>&lt;main&gt;</code>, <code>data-pagefind-ignore=&quot;all&quot;</code> on the hero, nav, sidebar, and listing grids, a broken tag-page <code>&lt;h1&gt;</code> fixed, explicit title <code>&lt;meta&gt;</code> tags added, the <code>/search/?q=</code> deep link preserved, and Pagefind's <code>--pf-*</code> CSS custom properties mapped onto the site's dark mode. Verified live afterward: searching &quot;beauty&quot; returned 42 real, correctly-titled results instead of noise.</li>\n<li><a href=\"https://github.com/The-Whitestone-Foundation/jcrt-v2/\"><strong>jcrt-v2</strong> on github</a></li>\n</ul>\n<p>Each of those is a small diff on its own. Together they're the thing that actually matters here: every site in the network now emits a Pagefind bundle built the same way, scoped to <code>&lt;main&gt;</code> the same way, versioned the same way, and CORS-enabled the same way. That consistency is what makes the merged metasearch page trustworthy instead of a demo that happens to work for two of the five sites on a good day.</p>\n<p>I got stuck several times late at night and as the repositories will show I did use Claude and Github Co-pilot for assistance in troubleshooting. I did check, verify, and modify their code. They did not ship any code, I made many of the changes they recommended and gave credit to them for clarity. Github Co-pilot and Claude really do not like the <code>11ty/nunjucks</code> fork but I do so I'm keeping it.</p>\n<p>The Netlify side of this stayed almost boring by comparison, which is the goal. Each repo's <code>public/_headers</code> file grew the same shape of rule:</p>\n<pre class=\"language-txt\" tabindex=\"0\"><code class=\"language-txt\">/pagefind/*\n  Access-Control-Allow-Origin: *\n  Access-Control-Allow-Methods: GET, HEAD, OPTIONS</code></pre>\n<p>with jcrt-v2 carrying a slightly richer version to satisfy Range-request preflights (more on why in the Cloudflare section below):</p>\n<pre class=\"language-txt\" tabindex=\"0\"><code class=\"language-txt\">/pagefind/*\n  Cache-Control: public, max-age=172800, stale-while-revalidate=604800\n  Access-Control-Allow-Origin: *\n  Access-Control-Allow-Methods: GET, HEAD, OPTIONS\n  Access-Control-Allow-Headers: Content-Type, Accept, Range\n  Access-Control-Expose-Headers: Content-Length, Content-Range, ETag</code></pre>\n<p>Each site still deploys independently, on its own Netlify project, on its own schedule. Nothing about the metasearch work required a shared deploy pipeline or a monorepo. It required a shared <em>contract</em>: build Pagefind the same way, expose it the same way, and let the flagship site do the composing. That's the &quot;one build pipeline&quot; in the section title — not one repo, one pipeline shape, repeated five times.</p>\n<p>While I had the fleet open, I also spent a morning on the boring-but-necessary chore of auditing pull requests across all six repositories under the-Whitestone-Foundation organization on GitHub. Five had zero open PRs. journal.thenewpolis.com had five open Dependabot PRs, all conflicting against main because of the same session's work. Two (a Pagefind bump and an Eleventy bump) were superseded by changes already on <code>main</code> and got closed. Three more — an <code>eleventy-plugin-rss</code> major version bump, a <code>markdown-it-table-of-contents</code> bump, and a <code>slugify</code> bump — got rebased, conflict-resolved, built, and diffed against baseline feed output to confirm nothing broke, then left pushed and mergeable for me to click through by hand. Merging dependency bumps without a human actually looking at the diff is exactly the kind of thing I don't want automated away, even when the automation could technically do it.</p>\n<h2 id=\"reducing-build-times-again-purgecss-dead-bootstrap-js-and-lighter-thumbnails\" tabindex=\"-1\">Reducing build times, again: PurgeCSS, dead Bootstrap JS, and lighter thumbnails <a class=\"header-anchor\" href=\"#reducing-build-times-again-purgecss-dead-bootstrap-js-and-lighter-thumbnails\">#</a></h2>\n<p>I have written about build times on this blog before, and not because I've solved the problem once and for all. The <a href=\"/blog/2025-12-16-eleventy-build-times/\">December post</a> about a seven-minute build turning into 1.6 seconds locally taught me the first round of lessons: cache RSS fetches with Eleventy Fetch, persist <code>.cache/</code> across Netlify deploys, and get purgeCSS and Pagefind running in the right order relative to each other. That post ended with a &quot;next steps&quot; line admitting I wasn't sure I had purgeCSS and Pagefind sequenced correctly, and that I'd need to explore running them in parallel once heavy builds were re-enabled. The July 9th sprint is where some of that debt came due, on jcrt.org specifically.</p>\n<p><a href=\"https://jcrt.org\">jcrt.org</a> was shipping all of Bootstrap 5.3.8 as its only render-blocking stylesheet — 263 KB raw, for a site that, once you actually measured it, was using roughly 8% of Bootstrap's selectors. A PurgeCSS pass now runs after Eleventy in every build:</p>\n<pre class=\"language-json\" tabindex=\"0\"><code class=\"language-json\"><span class=\"token property\">\"css:purge\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"purgecss --css _site/css/bs.css --content \\\"_site/**/*.html\\\" --output _site/css/\"</span></code></pre>\n<p>That shrinks the served <code>bs.css</code> from 263 KB raw to 38 KB raw — about 7.6 KB compressed — while the full, unpurged Bootstrap build stays in source control so nothing about the underlying framework choice is lost, just the dead weight that was being shipped to every visitor. I deliberately did <em>not</em> defer that stylesheet even at 7.6 KB compressed; deferring layout CSS risks a flash of unstyled content, and at that size there wasn't enough left to defer to make the risk worth it.</p>\n<p>The JavaScript side had an even sillier discovery waiting in it. <code>public/js/bs.js</code> was the entire 81 KB Bootstrap JS bundle, shipped for exactly thirty lines of custom sidebar-toggle code appended to the end of it. A search for <code>data-bs-</code> attributes across the built site turned up zero matches. The Bootstrap JS bundle was doing nothing — every interactive behavior it powers requires those data attributes, and the site had none. The 30 live lines moved into a new 1 KB <code>js/menu.js</code>, and the 81 KB bundle (plus its sourcemap, plus an orphaned <code>pagefind-ui.css</code> nobody was linking to anymore) got deleted outright. This friends is why you dont import the whole framework. Lesson learned.</p>\n<p>The last piece was images, not code. The homepage's &quot;Recent Journal Issues&quot; section was loading full-size cover scans — roughly 380 KB of images above the fold, on a homepage, for thumbnails. Each recent issue (25.1, 24.2, 24.1, 23.2) now carries a proper <code>thumbnail:</code> field in its front matter — a 480px-wide <code>*_tn.webp</code> render, generated at twice the actual 240px display size for crisp high-DPI screens — sourced from the <a href=\"https://github.com/The-Whitestone-Foundation/jcrt-files\">jcrt-files</a> CDN repo that already exists for exactly this kind of asset. The homepage template now prefers <code>issue.data.thumbnail</code>, falling back to the full image if a thumbnail isn't set. Homepage cover payload: roughly 380 KB down to roughly 87 KB.</p>\n<p>The one change major change I made that changed pagefind for that better was refining jcrt-v2's custom Pagefind index cache wrapper in <code>_config/run-pagefind.js</code> — 199 lines down to 75. The deleted half implemented a signature-based cache that could restore a previously-built Pagefind index from <code>.cache/pagefind-index</code>, persisted across Netlify builds, rather than re-indexing from scratch every time. It sounded like a reasonable optimization when I wrote it but it was overly complicated. It is also, per Pagefind's own docs (I had a Claude Sonnet 5 read through <code>pagefind.app</code>'s <code>llms.txt</code> to confirm this rather than trust my memory), not a supported mode — there is no ideal way to restore an index and have it guaranteed to match freshly-built HTML from a different Eleventy run. A restored index can drift from the site it's supposedly indexing. Indexing jcrt.org's roughly 4,900 pages from scratch takes seconds, not minutes. The staleness risk of the cache wrapper was never worth the seconds it saved. I deleted my own cleverness and the site got both simpler and more correct at the same time, which is a good trade whenever you can get it.</p>\n<h2 id=\"the-quest-for-four-100s-in-pagespeed-insights\" tabindex=\"-1\">The quest for four 100s in PageSpeed Insights <a class=\"header-anchor\" href=\"#the-quest-for-four-100s-in-pagespeed-insights\">#</a></h2>\n<p>I have not gotten there yet but I will. The clean, headless Lighthouse run against the v3 production build of <a href=\"https://thewhitestonefoundation.org\">thewhitestonefoundation.org</a> currently looks like this:</p>\n<table>\n<thead>\n<tr>\n<th>Page</th>\n<th style=\"text-align:right\">Performance</th>\n<th style=\"text-align:right\">Accessibility</th>\n<th style=\"text-align:right\">Best Practices</th>\n<th style=\"text-align:right\">SEO</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Home</td>\n<td style=\"text-align:right\">79</td>\n<td style=\"text-align:right\">100</td>\n<td style=\"text-align:right\">100</td>\n<td style=\"text-align:right\">100</td>\n</tr>\n<tr>\n<td><code>/ai/</code></td>\n<td style=\"text-align:right\">100</td>\n<td style=\"text-align:right\">96</td>\n<td style=\"text-align:right\">100</td>\n<td style=\"text-align:right\">100</td>\n</tr>\n<tr>\n<td><code>/panelists/</code></td>\n<td style=\"text-align:right\">100</td>\n<td style=\"text-align:right\">94</td>\n<td style=\"text-align:right\">100</td>\n<td style=\"text-align:right\">92</td>\n</tr>\n</tbody>\n</table>\n<p>Every page is three-for-four. None of them is four-for-four.</p>\n<p>The Home page's Performance score is the most legible gap, and most of this post has already explained what's chasing it down: preloading the hero image explicitly (since it's a CSS <code>background-image</code>, and browsers can't discover the priority of an image they can't see in the markup) —</p>\n<pre class=\"language-njk\" tabindex=\"0\"><code class=\"language-njk\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token tag keyword\">if</span> <span class=\"token variable\">hero</span> <span class=\"token keyword\">and</span> <span class=\"token variable\">hero</span><span class=\"token punctuation\">.</span><span class=\"token variable\">image</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span># <span class=\"token variable\">Hero</span> <span class=\"token keyword\">is</span> <span class=\"token test function\">a</span> <span class=\"token variable\">CSS</span> <span class=\"token variable\">background</span><span class=\"token operator\">-</span><span class=\"token variable\">image</span><span class=\"token punctuation\">,</span> <span class=\"token variable\">so</span> <span class=\"token variable\">the</span> <span class=\"token variable\">browser</span> <span class=\"token variable\">can</span><span class=\"token string\">'t discover its own priority; hint it explicitly since it'</span><span class=\"token variable\">s</span> <span class=\"token variable\">the</span> <span class=\"token variable\">page</span>'<span class=\"token variable\">s</span> <span class=\"token variable\">LCP</span> <span class=\"token variable\">element</span><span class=\"token punctuation\">.</span> #<span class=\"token punctuation\">}</span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">link</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"preload\"</span> <span class=\"token keyword\">as</span><span class=\"token operator\">=</span><span class=\"token string\">\"image\"</span> <span class=\"token variable\">href</span><span class=\"token operator\">=</span><span class=\"token string\">\"{{ hero.image }}\"</span> <span class=\"token variable\">fetchpriority</span><span class=\"token operator\">=</span><span class=\"token string\">\"high\"</span><span class=\"token operator\">></span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endif</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span></code></pre>\n<p>— minifying CSS and JS at build time with esbuild, converting panelist photos to WebP and sweeping roughly 8 MB of unused PNGs out of the repo, and adopting a hard rule going forward: non-favicon images are SVG or WebP, no exceptions. The <code>/ai/</code> and <code>/panelists/</code> pages are closer, and their gap sits in Accessibility rather than Performance — which is a different kind of debt, usually contrast ratios, missing labels, or heading order, and one I'd rather fix by reading the Lighthouse audit line by line than by guessing.</p>\n<p>What's already paying off, even without four green 100s yet: the native <code>popover</code> mobile menu (no custom JS, no layout-shift risk) —</p>\n<pre class=\"language-njk\" tabindex=\"0\"><code class=\"language-njk\"><span class=\"token operator\">&lt;</span><span class=\"token variable\">button</span> <span class=\"token variable\">class</span><span class=\"token operator\">=</span><span class=\"token string\">\"nav-toggle\"</span> <span class=\"token variable\">type</span><span class=\"token operator\">=</span><span class=\"token string\">\"button\"</span> <span class=\"token variable\">popovertarget</span><span class=\"token operator\">=</span><span class=\"token string\">\"nav-menu\"</span> <span class=\"token variable\">data</span><span class=\"token operator\">-</span><span class=\"token variable\">nav</span><span class=\"token operator\">-</span><span class=\"token variable\">toggle</span><span class=\"token operator\">></span>\n  <span class=\"token operator\">&lt;</span><span class=\"token variable\">span</span> <span class=\"token variable\">class</span><span class=\"token operator\">=</span><span class=\"token string\">\"nav-toggle__open\"</span><span class=\"token operator\">></span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">icons</span><span class=\"token punctuation\">.</span><span class=\"token function\">icon</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"menu\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span><span class=\"token variable\">span</span><span class=\"token operator\">></span>\n  <span class=\"token operator\">&lt;</span><span class=\"token variable\">span</span> <span class=\"token variable\">class</span><span class=\"token operator\">=</span><span class=\"token string\">\"nav-toggle__close\"</span> <span class=\"token variable\">hidden</span><span class=\"token operator\">></span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">icons</span><span class=\"token punctuation\">.</span><span class=\"token function\">icon</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"x\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span><span class=\"token variable\">span</span><span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span><span class=\"token variable\">button</span><span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">div</span> <span class=\"token variable\">id</span><span class=\"token operator\">=</span><span class=\"token string\">\"nav-menu\"</span> <span class=\"token variable\">class</span><span class=\"token operator\">=</span><span class=\"token string\">\"nav-popover\"</span> <span class=\"token variable\">popover</span> <span class=\"token variable\">data</span><span class=\"token operator\">-</span><span class=\"token variable\">nav</span><span class=\"token operator\">-</span><span class=\"token variable\">popover</span><span class=\"token operator\">></span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token punctuation\">.</span><span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span><span class=\"token variable\">div</span><span class=\"token operator\">></span></code></pre>\n<p>— the no-JS breadcrumb component emitting <code>BreadcrumbList</code> JSON-LD alongside visible navigation, button contrast brought up to AA in both filled and outline states, explicit <code>width</code>/<code>height</code> on every image so nothing shifts while loading, and the lazy-loaded Pagefind search bundle staying entirely off the critical path until someone actually wants to search. Every one of those is a page not fighting the visitor for their own bandwidth and attention. I'd still like the fourth 100. I'm not going to pretend three isn't real progress in the meantime.</p>\n<h2 id=\"when-cloudflare-cached-the-outage-three-layers-one-poisoned-404-and-a-versioned-url\" tabindex=\"-1\">When Cloudflare cached the outage: three layers, one poisoned 404, and a versioned URL <a class=\"header-anchor\" href=\"#when-cloudflare-cached-the-outage-three-layers-one-poisoned-404-and-a-versioned-url\">#</a></h2>\n<p>This is the section I'd have written differently if you'd asked me on the morning of July 9th, because at the time I was fairly sure something was wrong with Pagefind itself.</p>\n<p>It started with the simplest possible bug report: search on jcrt.org had stopped working, every query hanging forever on &quot;Searching…&quot;. The browser console said <code>Pagefind JS: 1.4.0. Pagefind index: 1.5.2 … you likely have a cached pagefind.js file</code>, alongside a WASM instantiation failure. That message is more honest than most error messages get to be — it was telling me exactly what was wrong on the first try — and I still spent an embarrassing amount of time looking elsewhere first.</p>\n<p><a href=\"https://jcrt.org\">jcrt.org</a> is hosted on Netlify, but the domain is proxied through Cloudflare, which also runs a small WAF worker in front of it. That means every request actually passes through three caches, not one: the visitor's own browser HTTP cache, Cloudflare's edge cache, and Netlify's own origin. Only the third one resets when you deploy. The first two keep whatever they cached for as long as the response's headers said to, and — this is the part that actually got me — Cloudflare caches by file <em>extension</em>, independent of what your own <code>Cache-Control</code> headers say the file's actual freshness policy should be. <code>pagefind.js</code> has a stable filename and a long default TTL from the repo's <code>_headers</code> file, so Cloudflare happily served the old cached copy on every request. <code>pagefind-entry.json</code>, sitting right next to it, isn't in Cloudflare's cache-by-extension list, so it was always fetched fresh from origin. The index (fresh, 1.5.2) and the engine loading it (stale, 1.4.0) had drifted apart from two files sitting in the same folder, deployed at the same time, purely because one had a <code>.js</code> extension and the other had <code>.json</code>. Redeploying didn't fix it, because redeploying only purges Netlify — layer three — and does nothing to layers one or two. There was no Cloudflare purge access from inside the repo to reach for.</p>\n<p>It got one layer weirder. A Cloudflare zone-level dashboard setting called &quot;Browser Cache TTL&quot; was silently rewriting every cacheable response's <code>max-age</code> to 691200 seconds — eight days — regardless of what the origin's own headers said. So even a correct, intentional <code>Cache-Control</code> header from the repo was getting overridden in flight, at the edge, by a setting nobody on the engineering side of this project could see or change from GitHub.</p>\n<p>The fix that actually worked was not &quot;set better cache headers&quot; — headers are policy for <em>future</em> responses; they cannot evict what a cache already has sitting at an old URL under an old policy. The fix was to stop fighting the cache and change the address instead. <code>pagefindVersion</code> is now real global data pulled from <code>node_modules/pagefind/package.json</code> at build time, and every template loads the bundle from a versioned path:</p>\n<pre class=\"language-njk\" tabindex=\"0\"><code class=\"language-njk\"><span class=\"token operator\">&lt;</span><span class=\"token variable\">pagefind</span><span class=\"token operator\">-</span><span class=\"token variable\">config</span> <span class=\"token variable\">bundle</span><span class=\"token operator\">-</span><span class=\"token variable\">path</span><span class=\"token operator\">=</span><span class=\"token string\">\"/pagefind/v/{{ pagefindVersion }}/\"</span><span class=\"token operator\">></span></code></pre>\n<p>with a Netlify rewrite mapping the versioned path back to the real, unversioned bundle on disk (<code>/pagefind/v/:version/* /pagefind/:splat 200</code>), and <code>_headers</code> split by actual file semantics instead of one blanket rule for everything under <code>/pagefind/</code>:</p>\n<pre class=\"language-txt\" tabindex=\"0\"><code class=\"language-txt\">Cache-Control: public, max-age=0, must-revalidate   # unversioned entry points — always revalidate\nCache-Control: public, max-age=31536000, immutable   # content-hashed index/fragment chunks — cache forever</code></pre>\n<p>A brand-new URL has never been cached anywhere, by definition — not in a visitor's browser, not at Cloudflare's edge, not anywhere. Bumping Pagefind's version now rotates the URL automatically, which means this class of bug can't recur silently the next time the site upgrades.</p>\n<p>Two footnotes, because both bit me in the same 24 hours. First, while deploying this fix, a pre-deploy probe request hit the new versioned URL <em>before</em> that deploy was live, got a 404, and Cloudflare cached that 404 under its usual long-TTL rules — a poisoned negative cache, at a URL that was correct three minutes later. The fix there was to salt the path once (<code>1.5.2-1</code>) to sidestep the poisoned address, then remove the salt after I asked to have Cloudflare's cache purged manually. Lesson recorded plainly for future-me: never probe a URL before the deploy that creates it is actually live. Second, jcrt.org's Cloudflare zone doesn't live under my personal account — it's a separate login — so anything requiring dashboard access (the cache purges, the Browser Cache TTL change to &quot;Respect Existing Headers&quot;) had to go through me directly rather than through whatever automation was doing the code-side work. That's a small organizational fact about who owns what, but it mattered a lot for how quickly this got resolved.</p>\n<p>The whole episode is now saved to memory under one name — <code>jcrt-pagefind-cdn-caching</code> — because I do not trust myself to remember it unprompted the next time a stable-filename asset starts feeling haunted. The short version, if you only take one thing from this section: cache lifetime should mirror the identity contract of the URL. A stable name whose content changes needs to revalidate. A name that changes whenever its content changes can be cached forever. Mixing those two contracts on two files in the same folder is exactly how you get a search engine that's stuck talking to yesterday's index.</p>\n<h2 id=\"where-this-leaves-the-network\" tabindex=\"-1\">Where this leaves the network <a class=\"header-anchor\" href=\"#where-this-leaves-the-network\">#</a></h2>\n<p>Zoom back out and the shape of the last eleven days is fairly simple, even if the individual bugs weren't. <a href=\"/blog/11tyx5/\">11tyx5</a> was about proving that five sites could share an architecture without losing their individual identities. This sprint was about proving that shared architecture could also mean shared <em>infrastructure</em> — one metadata model, one search technology, one CORS contract, one Netlify header policy — without turning five independently-edited publications into a single fragile monorepo pretending to be five sites.</p>\n<p>The metasearch page is live. The fleet is on a consistent Pagefind Component UI baseline. jcrt.org's search is not just fixed but rebuilt on URLs that can't silently go stale the same way again. Build times keep coming down, for genuinely different reasons each time I write about them, which I think means I'm still finding real waste rather than repeating the same fix. PageSpeed is not four green 100s yet, on any page, and I'd rather tell you that honestly than round up.</p>\n<p>There's a smaller, quieter line item buried in the middle of all this that I want to name before closing: <code>jcrt-v2</code>'s <code>public/_redirects</code> file has a duplicated block of five rules, repeated at two different line ranges, and it's been failing Netlify's &quot;Redirect rules&quot; check on unrelated pull requests ever since. It's flagged, it's spawned as its own task, and it is exactly the kind of small, unglamorous thing that piles up around an archive this old if nobody goes looking for it on purpose. Consider this me going looking for it on purpose, in public, so it's harder to quietly forget.</p>\n<p>The DOI work with <a href=\"https://kcommons.org/\">KC Commons</a> that I mentioned at the end of <code>11tyx5</code> is still the next big milestone, and it's still coming. Everything in this post — the metadata layer, the shared search contract, the version-pinned build tools — is the kind of infrastructure that a persistent-identifier rollout is going to need underneath it anyway. I'd rather have the plumbing sorted out before I ask five sites to also start minting DOIs. One overnight sprint at a time.</p>\n",
			"date_published": "2026-07-09T22:07:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/easier-11ty-font-awesome-svg/",
			"url": "https://www.adamdjbrett.com/blog/easier-11ty-font-awesome-svg/",
			"title": "Easier Font Awesome SVGs in 11ty",
			"content_html": "<p>Inspired by so many <a href=\"#\">#webdevs</a> on the #indieweb I am continuing to work on posting what I am doing and #buildinpublic. It is a little scary but here we go.</p>\n<p>I need to hurry up and convert all my Jekyll sites to 11ty at the same time because I feel like I keep relearning the same lessons. Hopefully, this post will help me remember what to do when moving old Jekyll sites into <a href=\"https://11ty.dev/\">11ty</a> and <a href=\"https://www.11ty.dev/\">Build Awesome</a>: the hard part is rarely the new tool. The hard part is the history around the old site.</p>\n<p>To make the move easier and quicker, I kept the site in liquid. The major issue that I had was that the minimal mistakes Jekyll theme had very old class names and Font Awesome web font implementation.</p>\n<p>As I was working on the <a href=\"https://www.wocati.org/\">WOCATI</a> <a href=\"https://github.com/adamdjbrett/wocati-new\">repo</a>, I sstruggled to recall how to fix this based on previous experience. The site started as Jekyll plus Minimal Mistakes. Minimal Mistakes uses Font Awesome in many places, and the old site expected Font Awesome CSS and font files to load in the browser. I wanted the Build Awesome version to use inline SVGs instead. Finally I found the guide I used last time thanks to <a href=\"https://11tybundle.dev\">11ty Bundle</a>. In the bundle I found\n<a href=\"https://equk.co.uk/2025/03/23/11ty-font-awesome-svg-plugin/\">equk's guide to the 11ty Font Awesome SVG plugin</a> gave me the path.  Following this guide, I used the <code>@11ty/font-awesome</code> plugin to turn <code>&lt;i class=&quot;...&quot;&gt;</code> Font Awesome markup into SVG during the Eleventy build. No client-side Font Awesome JavaScript. No full icon font for a page that only needs a few icons.</p>\n<p>The basic setup is small:</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\"><span class=\"token keyword\">import</span> fontAwesomePlugin <span class=\"token keyword\">from</span> <span class=\"token string\">\"@11ty/font-awesome\"</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> <span class=\"token keyword\">function</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">eleventyConfig</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  eleventyConfig<span class=\"token punctuation\">.</span><span class=\"token function\">addPlugin</span><span class=\"token punctuation\">(</span>fontAwesomePlugin<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">transform</span><span class=\"token operator\">:</span> <span class=\"token string\">\"i[class]\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">shortcode</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">defaultAttributes</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">class</span><span class=\"token operator\">:</span> <span class=\"token string\">\"icon-svg\"</span><span class=\"token punctuation\">,</span>\n      <span class=\"token string-property property\">\"aria-hidden\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"true\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>That part worked. The real work was making the old theme markup and old theme CSS agree with the new SVG output.</p>\n<h2 id=\"what-the-plugin-changes\" tabindex=\"-1\">What the plugin changes <a class=\"header-anchor\" href=\"#what-the-plugin-changes\">#</a></h2>\n<p>In a traditional Font Awesome setup, a template might include:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>i</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>fas fa-fw fa-rss-square<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">aria-hidden</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>true<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>i</span><span class=\"token punctuation\">></span></span></code></pre>\n<p>The browser loads Font Awesome CSS. The CSS maps those classes to a glyph in a web font. The icon appears. The <code>&lt;i&gt;</code> element is a marker that says, &quot;put the right font glyph here.&quot;</p>\n<p>With <code>@11ty/font-awesome</code>, the build sees that same <code>&lt;i&gt;</code> element and replaces it with SVG. This fits static sites well. The page gets only the SVGs it needs, and the browser does less work.</p>\n<p>That mattered for WOCATI because icons were scattered throughout the Minimal Mistakes templates:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>i</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>fas fa-fw fa-tags<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">aria-hidden</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>true<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>i</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>i</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>fab fa-fw fa-facebook<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">aria-hidden</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>true<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>i</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>i</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>fas fa-fw fa-rss-square<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">aria-hidden</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>true<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>i</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>i</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>fas fa-search<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>i</span><span class=\"token punctuation\">></span></span></code></pre>\n<p>I did not need to rewrite those templates into hand-authored SVG. The plugin let the migration keep the old template vocabulary and change the build output.</p>\n<h2 id=\"the-first-problem-old-icon-classes\" tabindex=\"-1\">The first problem: old icon classes <a class=\"header-anchor\" href=\"#the-first-problem-old-icon-classes\">#</a></h2>\n<p>Here is where [equk's guide](https://equk.co.uk/2025/03/23/11ty-font-awesome-svg-plugin/ came in clutch for me.  The guide notes a common problem. Older sites often use old Font Awesome class patterns:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>i</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>fa fa-github<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>i</span><span class=\"token punctuation\">></span></span></code></pre>\n<p>Modern Font Awesome needs the icon family too:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>i</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>fab fa-github<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>i</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>i</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>fas fa-code<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>i</span><span class=\"token punctuation\">></span></span></code></pre>\n<p>The build plugin needs to know which icon set to use. Is this a brand icon? A solid icon? A regular icon?</p>\n<p>WOCATI already had a mix of older and newer class names because Minimal Mistakes had moved in that direction and the site had been in <code>archve</code> mode using a remote theme hence the blending of old and new. Thankfully, <code>fas</code>, <code>fab</code>, <code>far</code>, and <code>fa-fw</code> were already present in most places. But this is still the first thing to check on an older site. If the plugin runs but icons disappear, do not start with SVG debugging. Search templates and Markdown for plain <code>fa</code> classes that do not name a family.</p>\n<p>Useful searches:</p>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\">rg <span class=\"token string\">'&lt;i class=\"fa '</span> <span class=\"token builtin class-name\">.</span>\nrg <span class=\"token string\">'class=\"[^\"]*\\bfa-[a-z0-9-]+'</span> _includes content src</code></pre>\n<p>The fix is inventory work. It makes the rest of the migration easier.</p>\n<h2 id=\"the-second-problem-svgs-are-not-font-glyphs\" tabindex=\"-1\">The second problem: SVGs are not font glyphs <a class=\"header-anchor\" href=\"#the-second-problem-svgs-are-not-font-glyphs\">#</a></h2>\n<p>After using equk's method, the svgs were <strong>MASSIVE.</strong> This is where the guide helped most and the part I kept forgetting. <a href=\"https://equk.co.uk/2025/03/23/11ty-font-awesome-svg-plugin/\">equk</a> added a default SVG class through <code>defaultAttributes</code>, then styled that class in CSS.</p>\n<p>I used the same pattern:</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\">eleventyConfig<span class=\"token punctuation\">.</span><span class=\"token function\">addPlugin</span><span class=\"token punctuation\">(</span>fontAwesomePlugin<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">transform</span><span class=\"token operator\">:</span> <span class=\"token string\">\"i[class]\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">shortcode</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">defaultAttributes</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">class</span><span class=\"token operator\">:</span> <span class=\"token string\">\"icon-svg\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string-property property\">\"aria-hidden\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"true\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre>\n<p>Then in CSS:</p>\n<pre class=\"language-css\" tabindex=\"0\"><code class=\"language-css\"><span class=\"token selector\">.icon-svg</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token property\">display</span><span class=\"token punctuation\">:</span> inline-block<span class=\"token punctuation\">;</span>\n  <span class=\"token property\">width</span><span class=\"token punctuation\">:</span> 1em<span class=\"token punctuation\">;</span>\n  <span class=\"token property\">height</span><span class=\"token punctuation\">:</span> 1em<span class=\"token punctuation\">;</span>\n  <span class=\"token property\">vertical-align</span><span class=\"token punctuation\">:</span> -0.125em<span class=\"token punctuation\">;</span>\n  <span class=\"token property\">overflow</span><span class=\"token punctuation\">:</span> visible<span class=\"token punctuation\">;</span>\n  <span class=\"token property\">fill</span><span class=\"token punctuation\">:</span> currentColor<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token selector\">.icon-svg.fa-fw</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token property\">width</span><span class=\"token punctuation\">:</span> 1.25em<span class=\"token punctuation\">;</span>\n  <span class=\"token property\">text-align</span><span class=\"token punctuation\">:</span> center<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token selector\">.search__toggle .icon-svg</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token property\">display</span><span class=\"token punctuation\">:</span> block<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>The key idea is not only <code>width: 1em</code> or <code>height: 1em</code>. The SVG needs to behave like the font glyph it replaced. Font icons inherit text color and scale with surrounding text. If the replacement SVG does not do that, every icon becomes a layout problem.</p>\n<p>In WOCATI, <code>fill: currentColor</code> made the SVG inherit the text color. <code>1em</code> kept it sized like text. The <code>.fa-fw</code> rule preserved the fixed-width rhythm expected by the old theme. The search button needed one extra rule because its icon sits inside a button instead of flowing inline with text.</p>\n<h2 id=\"is-1em-too-big\" tabindex=\"-1\">Is <code>1em</code> too big? <a class=\"header-anchor\" href=\"#is-1em-too-big\">#</a></h2>\n<p>At one point, I asked my newfound rubber ducky desktop friend this directly: Is <code>1em</code> too big? (<em>the duck did not answer</em>)</p>\n<p>My answer: not as a default. <code>1em</code> is the right starting point because the SVG replaces a font glyph. If an icon sits next to text, it should usually match the text size.</p>\n<p>But <code>1em</code> is not a rule for every context. It is a baseline and for many of the sites I manage its too large. Smaller icons work better in some places:</p>\n<ul>\n<li>dense metadata rows</li>\n<li>tiny footer links</li>\n<li>compact nav controls</li>\n<li>buttons where the icon is decorative rather than the main affordance</li>\n</ul>\n<p>For those cases, use context-specific CSS instead of changing the global icon size:</p>\n<pre class=\"language-css\" tabindex=\"0\"><code class=\"language-css\"><span class=\"token selector\">.page__meta .icon-svg</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token property\">width</span><span class=\"token punctuation\">:</span> 0.9em<span class=\"token punctuation\">;</span>\n  <span class=\"token property\">height</span><span class=\"token punctuation\">:</span> 0.9em<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>The global rule should make most icons ordinary. Then each interface context can tune from there.</p>\n<h2 id=\"why-this-is-better-than-shipping-old-font-awesome-css\" tabindex=\"-1\">Why this is better than shipping old Font Awesome CSS <a class=\"header-anchor\" href=\"#why-this-is-better-than-shipping-old-font-awesome-css\">#</a></h2>\n<p>The old Font Awesome setup is easy to understand, but it has a cost. You ship CSS and font files for a broad icon system even when a page only needs a few icons. The browser also has to resolve the visual result.</p>\n<p>The plugin moves that work into the build. In the WOCATI migration, this fit the larger project pattern:</p>\n<ul>\n<li>preserve the existing template language where possible</li>\n<li>make the build explicit</li>\n<li>remove old runtime assumptions</li>\n<li>keep public URLs and visual behavior stable</li>\n<li>clean out Jekyll-era cruft after the Build Awesome version works</li>\n</ul>\n<p>Font Awesome SVGs are a small example of that larger migration principle. We did not rewrite every footer, author card, and social link. We made the build smarter, then added the CSS needed to make the new output behave like the old UI.</p>\n<h2 id=\"the-recipe-i-would-use-next-time\" tabindex=\"-1\">The recipe I would use next time <a class=\"header-anchor\" href=\"#the-recipe-i-would-use-next-time\">#</a></h2>\n<p><em>this section is for future Adam</em></p>\n<p>For the next 11ty or Build Awesome site, I would handle Font Awesome SVGs this way:</p>\n<ol>\n<li>Install the plugin.</li>\n</ol>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\"><span class=\"token function\">npm</span> <span class=\"token function\">install</span> @11ty/font-awesome</code></pre>\n<ol start=\"2\">\n<li>Add it to the Eleventy config.</li>\n</ol>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\"><span class=\"token keyword\">import</span> fontAwesomePlugin <span class=\"token keyword\">from</span> <span class=\"token string\">\"@11ty/font-awesome\"</span><span class=\"token punctuation\">;</span>\n\neleventyConfig<span class=\"token punctuation\">.</span><span class=\"token function\">addPlugin</span><span class=\"token punctuation\">(</span>fontAwesomePlugin<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">transform</span><span class=\"token operator\">:</span> <span class=\"token string\">\"i[class]\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">shortcode</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">defaultAttributes</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">class</span><span class=\"token operator\">:</span> <span class=\"token string\">\"icon-svg\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string-property property\">\"aria-hidden\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"true\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre>\n<ol start=\"3\">\n<li>Search for old class names.</li>\n</ol>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\">rg <span class=\"token string\">'&lt;i class=\"fa '</span> <span class=\"token builtin class-name\">.</span></code></pre>\n<ol start=\"4\">\n<li>Replace old generic classes with modern icon families.</li>\n</ol>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>i</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>fab fa-github<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>i</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>i</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>fas fa-link<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>i</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>i</span> <span class=\"token attr-name\">class</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>far fa-calendar-alt<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>i</span><span class=\"token punctuation\">></span></span></code></pre>\n<ol start=\"5\">\n<li>Add the baseline SVG CSS.</li>\n</ol>\n<pre class=\"language-css\" tabindex=\"0\"><code class=\"language-css\"><span class=\"token selector\">.icon-svg</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token property\">display</span><span class=\"token punctuation\">:</span> inline-block<span class=\"token punctuation\">;</span>\n  <span class=\"token property\">width</span><span class=\"token punctuation\">:</span> 1em<span class=\"token punctuation\">;</span>\n  <span class=\"token property\">height</span><span class=\"token punctuation\">:</span> 1em<span class=\"token punctuation\">;</span>\n  <span class=\"token property\">vertical-align</span><span class=\"token punctuation\">:</span> -0.125em<span class=\"token punctuation\">;</span>\n  <span class=\"token property\">overflow</span><span class=\"token punctuation\">:</span> visible<span class=\"token punctuation\">;</span>\n  <span class=\"token property\">fill</span><span class=\"token punctuation\">:</span> currentColor<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token selector\">.icon-svg.fa-fw</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token property\">width</span><span class=\"token punctuation\">:</span> 1.25em<span class=\"token punctuation\">;</span>\n  <span class=\"token property\">text-align</span><span class=\"token punctuation\">:</span> center<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<ol start=\"6\">\n<li>Fix individual UI contexts only when needed.</li>\n</ol>\n<pre class=\"language-css\" tabindex=\"0\"><code class=\"language-css\"><span class=\"token selector\">.search__toggle .icon-svg</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token property\">display</span><span class=\"token punctuation\">:</span> block<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<ol start=\"7\">\n<li>Remove old Font Awesome font imports and font files after checking the build output.\nClean your code, keep it all neat and tidy, especially for a site in archival mode. Otherwise, you will later wonder whether an icon comes from a font, an SVG transform, an old theme stylesheet, or a client-side script.</li>\n</ol>\n<h2 id=\"the-migration-lesson\" tabindex=\"-1\">The migration lesson <a class=\"header-anchor\" href=\"#the-migration-lesson\">#</a></h2>\n<p>This made the WOCATI migration feel less like a full rewrite. The site had old Jekyll templates, Minimal Mistakes conventions, WordPress-era assets, and a lot of history. The Font Awesome piece could have become another reason to rewrite everything. Instead, <code>@11ty/font-awesome</code> lets the site keep familiar markup and get better output.</p>\n<p>That is the kind of 11ty migration I like. The tool does not force a dramatic break with the past. It lets you remove the parts that no longer need to be there.</p>\n<p>Thanks to <a href=\"https://equk.co.uk/2025/03/23/11ty-font-awesome-svg-plugin/\">equk's post</a> for making the path clear. The implementation was only a few lines of config. The real lesson was knowing where to look when the icons appeared, worked, and still looked wrong.</p>\n",
			"date_published": "2026-07-08T00:35:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/speculative-realism-epitome/",
			"url": "https://www.adamdjbrett.com/blog/speculative-realism-epitome/",
			"title": "Review of Leon Niemoczynski&#39;s *Speculative Realism: An Epitome*",
			"content_html": "<h1 id=\"speculative-realism-an-epitome-literature-review\" tabindex=\"-1\">Speculative Realism: An Epitome — Literature Review <a class=\"header-anchor\" href=\"#speculative-realism-an-epitome-literature-review\">#</a></h1>\n<p>Niemoczynski, Leon J. 2017. <em>Speculative Realism: An Epitome</em>. Kismet Press. 9780995671751.</p>\n<hr>\n<p>Leon Niemoczynski’s <a href=\"https://archive.org/details/speculative-realism-an-epitome-kismet-press\"><em>Speculative Realism: An Epitome</em></a> is best read as an introduction to the afterlife of a movement that the book says never became a real school.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1\">[1]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2\">[2]</a></sup> Its central claim is simple: “speculative realism” was useful as a name for a moment, but it does not name a stable doctrine, method, or group.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:1\">[1:1]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3\">[3]</a></sup> What survives is not the brand. What survives is a renewed interest in realism, materialism, metaphysics, nature, science, and the absolute in Continental philosophy.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:2\">[1:2]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3:1\">[3:1]</a></sup></p>\n<p>The book starts from the 2007 Goldsmiths workshop on speculative realism.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:3\">[1:3]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn4\" id=\"fnref4\">[4]</a></sup> That event brought together Ray Brassier, Iain Hamilton Grant, Graham Harman, and Quentin Meillassoux to discuss new approaches to realism after the post-Kantian focus on subjectivity and access.<sup class=\"footnote-ref\"><a href=\"#fn4\" id=\"fnref4:1\">[4:1]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3:2\">[3:2]</a></sup> Niemoczynski accepts the workshop as the naming event, but he does not treat it as the birth of a unified movement.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:4\">[1:4]</a></sup> He follows Brassier’s hard line: speculative realism, as a movement, was “dead on arrival.”<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:5\">[1:5]</a></sup> The label became tied to blogs, factional claims, and arguments over ownership.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:6\">[1:6]</a></sup> For Niemoczynski, that history matters because it shows why the label became less useful than the questions it opened.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:7\">[1:7]</a></sup></p>\n<p>The strongest part of the book is this source-backed distinction between a failed name and a real shift in problems.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:8\">[1:8]</a></sup> Niemoczynski argues that Continental philosophy had spent much of the twentieth century inside the limits of finitude, phenomenology, hermeneutics, deconstruction, and critique.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:9\">[1:9]</a></sup> Speculative realist thinkers try to reopen questions about what exists apart from human access.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:10\">[1:10]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3:3\">[3:3]</a></sup> This means they return to metaphysics without simply restoring older dogmatism.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:11\">[1:11]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3:4\">[3:4]</a></sup> The shared target is often “correlationism,” Meillassoux’s term for the view that thought and being can only be considered together.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:12\">[1:12]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3:5\">[3:5]</a></sup> But the book is careful: not every realist or materialist thinker rejects correlationism in the same way, and this weakens any attempt to turn speculative realism into one doctrine.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:13\">[1:13]</a></sup></p>\n<p>Niemoczynski’s selection of figures is also telling. Standard accounts often name Brassier, Grant, Harman, and Meillassoux.<sup class=\"footnote-ref\"><a href=\"#fn4\" id=\"fnref4:2\">[4:2]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3:6\">[3:6]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn5\" id=\"fnref5\">[5]</a></sup> This book focuses on Meillassoux, Brassier, and Grant.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:14\">[1:14]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2:1\">[2:1]</a></sup> Harman appears in the field history, but he does not carry the main argument.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:15\">[1:15]</a></sup> That choice gives the review a clear line: Meillassoux reopens the absolute through contingency and the critique of correlationism; Brassier connects realism to nihilism, science, Sellarsian naturalism, and rational agency; Grant develops a Schellingian philosophy of nature where nature is not a set of objects but productive activity.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:16\">[1:16]</a></sup> Together, these figures let Niemoczynski frame speculative realism less as object-oriented ontology and more as Continental realism and materialism after Kant.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:17\">[1:17]</a></sup></p>\n<p>The book’s account of Meillassoux is the entry point.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:18\">[1:18]</a></sup> <em>After Finitude</em> matters because it asks whether thought can reach what exists without thought.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:19\">[1:19]</a></sup> Niemoczynski explains the “arche-fossil,” ancestral reality, and the claim that contingency, not necessity, is absolute.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:20\">[1:20]</a></sup> This section works well as pedagogy. It gives readers a usable map of why Meillassoux mattered and why the attack on correlationism became a rallying point.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:21\">[1:21]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3:7\">[3:7]</a></sup></p>\n<p>The later chapters broaden the map.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:22\">[1:22]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2:2\">[2:2]</a></sup> Brassier becomes important because he links realism to extinction, science, negativity, and rational agency.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:23\">[1:23]</a></sup> Niemoczynski stresses that Brassier is not just a crude reductionist.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:24\">[1:24]</a></sup> Grant, by contrast, shifts the focus to nature as activity.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:25\">[1:25]</a></sup> His Schellingian line lets Niemoczynski show that realism after Kant can also look like a philosophy of nature, not only a philosophy of scientific objectivity.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:26\">[1:26]</a></sup></p>\n<p>The book’s main limit follows from its strength. Because it aims to be accessible, it often summarizes rather than tests the arguments.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:27\">[1:27]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2:3\">[2:3]</a></sup> It gives readers a clear route into the field, but it does not fully adjudicate between Meillassoux’s mathematics, Brassier’s rationalism, Grant’s naturephilosophy, or Harman’s object-oriented alternative.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:28\">[1:28]</a></sup> It also accepts Brassier’s rejection of speculative realism as a movement more strongly than some readers will.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:29\">[1:29]</a></sup> Harman, for example, defended the value of the label as a useful umbrella even while admitting the projects differ.<sup class=\"footnote-ref\"><a href=\"#fn5\" id=\"fnref5:1\">[5:1]</a></sup></p>\n<p>Still, Niemoczynski’s review of the field is useful because it stops readers from mistaking a brand for a problem-space.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:30\">[1:30]</a></sup> The implied lesson is direct: do not ask whether speculative realism “won.” Ask what its brief life made thinkable.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:31\">[1:31]</a></sup> On that standard, its contribution is clear. It gives students a plain guide to why realism returned, why Kantian finitude became a target, and why the future of Continental metaphysics moved through several paths rather than one school.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:32\">[1:32]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2:4\">[2:4]</a></sup></p>\n<h2 id=\"open-questions-and-next-reading\" tabindex=\"-1\">Open questions and next reading <a class=\"header-anchor\" href=\"#open-questions-and-next-reading\">#</a></h2>\n<p>Readers should next compare Niemoczynski with the 2007 <em>Collapse</em> transcript, Meillassoux’s <em>After Finitude</em>, Brassier’s <em>Nihil Unbound</em>, Grant’s <em>Philosophies of Nature after Schelling</em>, and Bryant, Srnicek, and Harman’s <em>The Speculative Turn</em>.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:33\">[1:33]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3:8\">[3:8]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn5\" id=\"fnref5:2\">[5:2]</a></sup> That comparison would test whether Niemoczynski’s three-figure map clarifies the field or narrows it too much.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:34\">[1:34]</a></sup></p>\n<h2 id=\"footnotes\" tabindex=\"-1\">Footnotes <a class=\"header-anchor\" href=\"#footnotes\">#</a></h2>\n<hr class=\"footnotes-sep\">\n<section class=\"footnotes\">\n<ol class=\"footnotes-list\">\n<li id=\"fn1\" class=\"footnote-item\"><p>Leon Niemoczynski, <em>Speculative Realism: An Epitome</em> (local source), <code>inputs/critical-theory/speculative-realism-epitome-leon.md</code>. <a href=\"#fnref1\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:1\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:2\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:3\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:4\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:5\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:6\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:7\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:8\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:9\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:10\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:11\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:12\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:13\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:14\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:15\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:16\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:17\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:18\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:19\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:20\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:21\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:22\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:23\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:24\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:25\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:26\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:27\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:28\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:29\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:30\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:31\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:32\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:33\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:34\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn2\" class=\"footnote-item\"><p>Kısmet Press, “Speculative Realism: An Epitome,” https://kismet.press/portfolio/speculative-realism/. <a href=\"#fnref2\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref2:1\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref2:2\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref2:3\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref2:4\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn3\" class=\"footnote-item\"><p>Urbanomic, “Ray Brassier, Iain Hamilton Grant, Graham Harman, Quentin Meillassoux, Speculative Realism,” <em>Collapse III</em> transcript page, https://www.urbanomic.com/chapter/collapse-iii-ray-brassier-iain-hamilton-grant-graham-harman-quentin-meillassoux-speculative-realism/. <a href=\"#fnref3\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref3:1\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref3:2\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref3:3\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref3:4\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref3:5\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref3:6\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref3:7\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref3:8\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn4\" class=\"footnote-item\"><p>Urbanomic, “Speculative Realism: A One Day Workshop,” https://www.urbanomic.com/event/speculative-realism-a-one-day-workshop/. <a href=\"#fnref4\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref4:1\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref4:2\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn5\" class=\"footnote-item\"><p>Levi R. Bryant, Nick Srnicek, and Graham Harman, eds., <em>The Speculative Turn: Continental Realism and Materialism</em> (re.press, 2011), local source <code>inputs/the-speculative-turn-continental-realism-and-materialism.md</code>; publisher PDF: https://re-press.org/book-files/OA_Version_Speculative_Turn_9780980668346.pdf. <a href=\"#fnref5\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref5:1\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref5:2\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n</ol>\n</section>\n",
			"date_published": "2026-07-07T05:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/how-to-implement-status-lol-on-11ty/",
			"url": "https://www.adamdjbrett.com/blog/how-to-implement-status-lol-on-11ty/",
			"title": "How to Implement status.lol on BuildAwesome",
			"content_html": "<p>I wanted a small thing: when I publish a <a href=\"https://adamdjbrett.com/blog/\">new post here</a>, a short status shows up on <a href=\"https://adjb.status.lol/\">adjb.status.lol</a> with a link back to the real post. Not a syndication system, not another social bridge to babysit. My <a href=\"https://echofeed.app/\">EchoFeed</a> is too busy for all that. I just a note that says &quot;new post&quot; on <a href=\"https://adjb.status.lol\">adjb.status.lol</a> and points <a href=\"/\">home</a> because there is no place like <code>127.0.01</code>.</p>\n<p>The <a href=\"https://api.omg.lol/\">OMG API</a> made me say OMG with no LOL, it was <strong>way too much information</strong> Here's what I ended up with: a GitHub Actions workflow that finds new posts in <code>content/blog</code>, posts them to <code>https://adjb.status.lol/</code>, and remembers what it already posted so it doesn't spam the same six posts every night.</p>\n<p><a href=\"https://rknight.me/\">Robb Knight</a>'s <a href=\"https://github.com/rknightuk/alfred-workflows/tree/main/workflows/statuspost\">Alfred workflow, StatusPost</a>, is what actually got me moving. His script is small and plain, and it's exactly the kind of thing that makes an API make sense to me:</p>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\"><span class=\"token function\">curl</span> <span class=\"token parameter variable\">--location</span> <span class=\"token parameter variable\">--request</span> POST <span class=\"token punctuation\">\\</span>\n  <span class=\"token parameter variable\">--header</span> <span class=\"token string\">\"Authorization: Bearer <span class=\"token variable\">$API_KEY</span>\"</span> <span class=\"token punctuation\">\\</span>\n  <span class=\"token string\">\"https://api.omg.lol/address/<span class=\"token variable\">$USERNAME</span>/statuses/\"</span> <span class=\"token punctuation\">\\</span>\n  <span class=\"token parameter variable\">--data</span> <span class=\"token string\">'{\"emoji\": \"📝\", \"content\": \"Hello status.lol\"}'</span></code></pre>\n<p>The endpoint is <code>POST https://api.omg.lol/address/{address}/statuses/</code>, the token is a bearer token in the header, and the body just needs <code>emoji</code> and <code>content</code>. Once I had that, the question became how to I automate this via github workflows so I can make this safe to run automatically, every day, without me thinking about it.</p>\n<h2 id=\"the-setup\" tabindex=\"-1\">The setup <a class=\"header-anchor\" href=\"#the-setup\">#</a></h2>\n<p>(again thanks to Robb Knight)</p>\n<p>This site runs on <s>Eleventy</s> <a href=\"https://11ty.dev\">BuildAwesome</a>. Posts are Markdown files in <code>content/blog</code> with front matter like:</p>\n<pre class=\"language-yaml\" tabindex=\"0\"><code class=\"language-yaml\"><span class=\"token punctuation\">---</span>\n<span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> Making Static Sites FAIR with metadata.json<span class=\"token punctuation\">,</span> Zotero<span class=\"token punctuation\">,</span> Eleventy<span class=\"token punctuation\">,</span> and Jekyll\n<span class=\"token key atrule\">date</span><span class=\"token punctuation\">:</span> <span class=\"token datetime number\">2026-07-05T00:00:00.000Z</span>\n<span class=\"token key atrule\">tags</span><span class=\"token punctuation\">:</span>\n  <span class=\"token punctuation\">-</span> eleventy\n  <span class=\"token punctuation\">-</span> metadata\n  <span class=\"token punctuation\">-</span> zotero\n<span class=\"token punctuation\">---</span></code></pre>\n<p>Eleventy turns those into pages like <code>https://www.adamdjbrett.com/blog/fair-signposting-metadata-json-eleventy/</code>. status.lol is part of the omg.lol ecosystem — my address is <code>adjb</code>, so my status page lives at <code>https://adjb.status.lol/</code>.</p>\n<p>I already had a workflow refreshing feeds and webmentions on a schedule. I just needed to bolt on a publishing step without turning it into a machine that reposts my whole archive every night (thanks revert).</p>\n<h2 id=\"the-workflow-needs-a-memory\" tabindex=\"-1\">The workflow needs a memory <a class=\"header-anchor\" href=\"#the-workflow-needs-a-memory\">#</a></h2>\n<p>This is the part that actually took thought. If the script scans <code>content/blog</code> and posts everything it finds, it reposts the archive. If it only ever looks at the last seven days, it'll miss backdated posts or posts I edit later. If it just checks the latest git commit, it gets fragile the moment I move or restore a file.</p>\n<p>So instead there's a small state file, <code>_data/statuslog-published.json</code>, tracking two things:</p>\n<ul>\n<li><code>publishedUrls</code> — URLs actually posted to status.lol</li>\n<li><code>knownUrls</code> — URLs that existed the last time the workflow ran</li>\n</ul>\n<p>The first run backfills the last seven days. After that, it stops thinking in terms of &quot;recent&quot; and just asks whether a URL is new compared to what it already knew about. The seven-day window is fine for a first run, but it's a bad permanent definition of &quot;new&quot; — the state file is what gives the whole thing memory across runs.</p>\n<h2 id=\"building-the-request\" tabindex=\"-1\">Building the request <a class=\"header-anchor\" href=\"#building-the-request\">#</a></h2>\n<p>Robb's script showed me the shape. The payload is just:</p>\n<pre class=\"language-json\" tabindex=\"0\"><code class=\"language-json\"><span class=\"token punctuation\">{</span>\n  <span class=\"token property\">\"emoji\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"📝\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"content\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"New blog post: [Title](https://example.com/blog/post/)\"</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>I build that as a plain JS object and let <code>JSON.stringify</code> handle the escaping:</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\"><span class=\"token keyword\">const</span> payload <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">emoji</span><span class=\"token operator\">:</span> <span class=\"token constant\">DEFAULT_EMOJI</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">content</span><span class=\"token operator\">:</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">New blog post: [</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span><span class=\"token function\">markdownEscape</span><span class=\"token punctuation\">(</span>post<span class=\"token punctuation\">.</span>title<span class=\"token punctuation\">)</span><span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">](</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>post<span class=\"token punctuation\">.</span>url<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">)</span><span class=\"token template-punctuation string\">`</span></span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre>\n<p>That's safer than building a raw curl string by hand — post titles have quotes, apostrophes, and parentheses, all the characters that make shell escaping miserable. Let JS build the data as data and serialize it correctly.</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\"><span class=\"token keyword\">const</span> response <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> <span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span>apiUrl<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">method</span><span class=\"token operator\">:</span> <span class=\"token string\">\"POST\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">headers</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token string-property property\">\"Content-Type\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"application/json\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">Authorization</span><span class=\"token operator\">:</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">Bearer </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span><span class=\"token constant\">OMGLOL_KEY</span><span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">body</span><span class=\"token operator\">:</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">stringify</span><span class=\"token punctuation\">(</span>payload<span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre>\n<p>The URL comes from the omg.lol address: <code>https://api.omg.lol/address/${OMGLOL_USERNAME}/statuses/</code>. In GitHub Actions, <code>OMGLOL_USERNAME</code> is a secret — for this site, it's <code>adjb</code>.</p>\n<h2 id=\"the-script\" tabindex=\"-1\">The script <a class=\"header-anchor\" href=\"#the-script\">#</a></h2>\n<p>The publishing script lives at <code>scripts/publish-statuslog-posts.mjs</code>. Up top it reads:</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token constant\">OMGLOL_USERNAME</span> <span class=\"token operator\">=</span> process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">OMGLOL_USERNAME</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> <span class=\"token constant\">OMGLOL_KEY</span> <span class=\"token operator\">=</span> process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">OMGLOL_KEY</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> <span class=\"token constant\">STATUSLOG_DRY_RUN</span> <span class=\"token operator\">=</span> process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">STATUSLOG_DRY_RUN</span> <span class=\"token operator\">===</span> <span class=\"token string\">\"true\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> <span class=\"token constant\">STATUSLOG_BACKFILL_DAYS</span> <span class=\"token operator\">=</span> Number<span class=\"token punctuation\">.</span><span class=\"token function\">parseInt</span><span class=\"token punctuation\">(</span>\n  process<span class=\"token punctuation\">.</span>env<span class=\"token punctuation\">.</span><span class=\"token constant\">STATUSLOG_BACKFILL_DAYS</span> <span class=\"token operator\">||</span> <span class=\"token string\">\"7\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token number\">10</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre>\n<p>The GitHub secrets are <code>OMGLOL_USERNAME</code> and <code>OMG_KEY</code>. The workflow maps <code>OMG_KEY</code> to <code>OMGLOL_KEY</code> inside the script:</p>\n<pre class=\"language-yaml\" tabindex=\"0\"><code class=\"language-yaml\"><span class=\"token key atrule\">env</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">OMGLOL_USERNAME</span><span class=\"token punctuation\">:</span> $\n  <span class=\"token key atrule\">OMGLOL_KEY</span><span class=\"token punctuation\">:</span> $</code></pre>\n<p>A little annoying to have two names for the same secret, but it works — the repo keeps its short name, the script gets a clearer one.</p>\n<p>The script reads the Markdown files, pulls front matter, and skips anything that shouldn't go public:</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\"><span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>draft <span class=\"token operator\">===</span> <span class=\"token boolean\">true</span> <span class=\"token operator\">||</span> published <span class=\"token operator\">===</span> <span class=\"token boolean\">false</span> <span class=\"token operator\">||</span> frontMatter<span class=\"token punctuation\">.</span>permalink <span class=\"token operator\">===</span> <span class=\"token string\">\"false\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">continue</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>then builds a plain post object:</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\">posts<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n  file<span class=\"token punctuation\">,</span>\n  title<span class=\"token punctuation\">,</span>\n  url<span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">date</span><span class=\"token operator\">:</span> date<span class=\"token punctuation\">.</span><span class=\"token function\">toISOString</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre>\n<p>Normal dated posts get their URL from the file slug:</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\"><span class=\"token keyword\">const</span> slug <span class=\"token operator\">=</span> file<span class=\"token punctuation\">.</span><span class=\"token function\">replace</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">\\.md$</span><span class=\"token regex-delimiter\">/</span><span class=\"token regex-flags\">i</span></span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">return</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">URL</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">/blog/</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>slug<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">/</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">,</span> siteUrl<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toString</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre>\n<p>and posts with an explicit permalink keep it:</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\"><span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>permalink <span class=\"token operator\">&amp;&amp;</span> permalink <span class=\"token operator\">!==</span> <span class=\"token string\">\"false\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">return</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">URL</span><span class=\"token punctuation\">(</span>permalink<span class=\"token punctuation\">,</span> siteUrl<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toString</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>That matters more than it sounds like it should — not every page on an older Eleventy site follows the same URL pattern, and mine definitely doesn't.</p>\n<h2 id=\"where-i-actually-got-it-wrong\" tabindex=\"-1\">Where I actually got it wrong <a class=\"header-anchor\" href=\"#where-i-actually-got-it-wrong\">#</a></h2>\n<p>The key function is <code>selectPostsToPublish</code>. On the first run it publishes unpublished posts inside the backfill window:</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\"><span class=\"token keyword\">const</span> cutoff <span class=\"token operator\">=</span> Date<span class=\"token punctuation\">.</span><span class=\"token function\">now</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">-</span> backfillDays <span class=\"token operator\">*</span> <span class=\"token number\">24</span> <span class=\"token operator\">*</span> <span class=\"token number\">60</span> <span class=\"token operator\">*</span> <span class=\"token number\">60</span> <span class=\"token operator\">*</span> <span class=\"token number\">1000</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">return</span> unpublished<span class=\"token punctuation\">.</span><span class=\"token function\">filter</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">post</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Date</span><span class=\"token punctuation\">(</span>post<span class=\"token punctuation\">.</span>date<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">getTime</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">>=</span> cutoff<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre>\n<p>After that it switches to <code>knownUrls</code>:</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\"><span class=\"token keyword\">return</span> posts<span class=\"token punctuation\">.</span><span class=\"token function\">filter</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">post</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token operator\">!</span>knownUrls<span class=\"token punctuation\">.</span><span class=\"token function\">has</span><span class=\"token punctuation\">(</span>post<span class=\"token punctuation\">.</span>url<span class=\"token punctuation\">)</span> <span class=\"token operator\">&amp;&amp;</span> <span class=\"token operator\">!</span>publishedUrls<span class=\"token punctuation\">.</span><span class=\"token function\">has</span><span class=\"token punctuation\">(</span>post<span class=\"token punctuation\">.</span>url<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre>\n<p>My first pass recorded the six posts I backfilled but never recorded the rest of the archive as &quot;known.&quot; So the next run looked at dozens of old posts, saw they'd never been published, and got ready to blast all of them to status.lol. Not great.</p>\n<p>The fix was recording a baseline of every known URL, not just the ones I'd posted:</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\"><span class=\"token literal-property property\">knownUrls</span><span class=\"token operator\">:</span> posts<span class=\"token punctuation\">.</span><span class=\"token function\">map</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">post</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> post<span class=\"token punctuation\">.</span>url<span class=\"token punctuation\">)</span></code></pre>\n<p>Now the workflow can tell the difference between old posts that were never meant to go to status.lol, recent posts from the backfill, and posts that are genuinely new.</p>\n<h2 id=\"the-github-actions-side\" tabindex=\"-1\">The GitHub Actions side <a class=\"header-anchor\" href=\"#the-github-actions-side\">#</a></h2>\n<p>The workflow lives at <code>.github/workflows/update-feeds.yml</code> and runs on a schedule, on demand, and whenever blog posts or the script itself change:</p>\n<pre class=\"language-yaml\" tabindex=\"0\"><code class=\"language-yaml\"><span class=\"token key atrule\">on</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">schedule</span><span class=\"token punctuation\">:</span>\n    <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">cron</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"0 23 * * *\"</span>\n  <span class=\"token key atrule\">push</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">branches</span><span class=\"token punctuation\">:</span>\n      <span class=\"token punctuation\">-</span> main\n    <span class=\"token key atrule\">paths</span><span class=\"token punctuation\">:</span>\n      <span class=\"token punctuation\">-</span> <span class=\"token string\">\"content/blog/**\"</span>\n      <span class=\"token punctuation\">-</span> <span class=\"token string\">\"scripts/publish-statuslog-posts.mjs\"</span>\n      <span class=\"token punctuation\">-</span> <span class=\"token string\">\".github/workflows/update-feeds.yml\"</span>\n  <span class=\"token key atrule\">workflow_dispatch</span><span class=\"token punctuation\">:</span></code></pre>\n<p>I got the path filter wrong at first — only <code>content/blog/**</code> triggered it, so a commit fixing the workflow itself never actually ran the workflow. Adding the script and workflow paths means changes to the integration test themselves.</p>\n<p>The publish step:</p>\n<pre class=\"language-yaml\" tabindex=\"0\"><code class=\"language-yaml\"><span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Publish new blog posts to status.lol\n  <span class=\"token key atrule\">env</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">OMGLOL_USERNAME</span><span class=\"token punctuation\">:</span> $\n    <span class=\"token key atrule\">OMGLOL_KEY</span><span class=\"token punctuation\">:</span> $\n    <span class=\"token key atrule\">STATUSLOG_SKIP_MASTODON_POST</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"true\"</span>\n  <span class=\"token key atrule\">run</span><span class=\"token punctuation\">:</span> npm run statuslog<span class=\"token punctuation\">:</span>publish</code></pre>\n<p>Then it refreshes the local status.lol data:</p>\n<pre class=\"language-yaml\" tabindex=\"0\"><code class=\"language-yaml\"><span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Refresh status.lol data after publishing\n  <span class=\"token key atrule\">run</span><span class=\"token punctuation\">:</span> curl <span class=\"token punctuation\">-</span><span class=\"token punctuation\">-</span>fail <span class=\"token punctuation\">-</span><span class=\"token punctuation\">-</span>location <span class=\"token punctuation\">-</span><span class=\"token punctuation\">-</span>retry 3 <span class=\"token punctuation\">-</span><span class=\"token punctuation\">-</span>retry<span class=\"token punctuation\">-</span>delay 5 <span class=\"token punctuation\">-</span><span class=\"token punctuation\">-</span>max<span class=\"token punctuation\">-</span>time 30 \"https<span class=\"token punctuation\">:</span>//api.omg.lol/address/$/statuses/\" <span class=\"token punctuation\">></span> _data/status.lol.json</code></pre>\n<p>I originally had this backwards, fetching before publishing, which meant the committed data file was always one status behind. Publish first, then refresh.</p>\n<p>One of the habits I'm trying to get into is dry runs and once again I'm reminded at how helpful dry runs are instead of just full sending it (no matter how tempting it is).</p>\n<h2 id=\"dry-runs-saved-me\" tabindex=\"-1\">Dry runs saved me <a class=\"header-anchor\" href=\"#dry-runs-saved-me\">#</a></h2>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\"><span class=\"token assign-left variable\">STATUSLOG_DRY_RUN</span><span class=\"token operator\">=</span>true <span class=\"token function\">npm</span> run statuslog:publish</code></pre>\n<p>Before I fixed the baseline, this is what it told me:</p>\n<pre class=\"language-text\" tabindex=\"0\"><code class=\"language-text\">DRY RUN: 48 blog post(s) ready for Statuslog.</code></pre>\n<p>Forty-eight! That's when I knew something was wrong — those weren't new posts, that was my entire back catalog getting queued up. After adding <code>knownUrls</code>, the same command reports:</p>\n<pre class=\"language-text\" tabindex=\"0\"><code class=\"language-text\">DRY RUN: 0 blog post(s) ready for Statuslog.</code></pre>\n<p>which is exactly what it should say right after a clean run.</p>\n<h2 id=\"what-the-state-file-looks-like\" tabindex=\"-1\">What the state file looks like <a class=\"header-anchor\" href=\"#what-the-state-file-looks-like\">#</a></h2>\n<pre class=\"language-json\" tabindex=\"0\"><code class=\"language-json\"><span class=\"token punctuation\">{</span>\n  <span class=\"token property\">\"knownUrls\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n    <span class=\"token string\">\"https://www.adamdjbrett.com/blog/example-old-post/\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"https://www.adamdjbrett.com/blog/example-new-post/\"</span>\n  <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"publishedUrls\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n    <span class=\"token string\">\"https://www.adamdjbrett.com/blog/example-new-post/\"</span>\n  <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"statuses\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n    <span class=\"token punctuation\">{</span>\n      <span class=\"token property\">\"blogUrl\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"https://www.adamdjbrett.com/blog/example-new-post/\"</span><span class=\"token punctuation\">,</span>\n      <span class=\"token property\">\"title\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"Example New Post\"</span><span class=\"token punctuation\">,</span>\n      <span class=\"token property\">\"statusId\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"6a4b2efa69ec9\"</span><span class=\"token punctuation\">,</span>\n      <span class=\"token property\">\"statusUrl\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"https://status.lol/adjb/6a4b2efa69ec9\"</span><span class=\"token punctuation\">,</span>\n      <span class=\"token property\">\"publishedAt\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"2026-07-06T04:28:42.515Z\"</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">]</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>GitHub Actions commits this file itself, which is what makes the memory durable — the runner is temporary, the repo isn't.</p>\n<h2 id=\"what-i-d-tell-myself-before-starting\" tabindex=\"-1\">What I'd tell myself before starting <a class=\"header-anchor\" href=\"#what-i-d-tell-myself-before-starting\">#</a></h2>\n<p>Start with the smallest working request. Robb Knight's StatusPost showed me the essence of the call without any extra architecture around it — it's just a bearer-token POST to <code>/address/{address}/statuses/</code>.</p>\n<p>Don't confuse &quot;not posted yet&quot; with &quot;new.&quot; A post can be old and still unposted. Treat every unposted URL as new and you'll eventually flood your status log with your entire archive, which is exactly what almost happened to me.</p>\n<p>Refresh anything API-backed after you write to the API, not before. I had this backwards for longer than I'd like to admit.</p>\n<p>And let the workflow trigger on its own files. If it only runs when content changes, a broken workflow can sit broken until the next time you happen to publish — too slow when you're touching a live API on a schedule.</p>\n<h2 id=\"thanks\" tabindex=\"-1\">Thanks <a class=\"header-anchor\" href=\"#thanks\">#</a></h2>\n<p>Thanks to <a href=\"https://rknight.me/\">Robb Knight</a> for [StatusPost(https://rknight.me/alfred-workflows/)] — the small, plain script that made this whole thing click and gave me my epiphany.</p>\n<p>Now every new post here shows up on <a href=\"https://adjb.status.lol\">adjb.status.lol</a> within a day of publishing, without me having to touch anything.</p>\n<p><em>After all what is ci if not the friends and mistakes we make along the way.</em></p>\n",
			"date_published": "2026-07-06T00:10:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/xmit-vs-netlify-vercel-render/",
			"url": "https://www.adamdjbrett.com/blog/xmit-vs-netlify-vercel-render/",
			"title": "Xmit Might Be My New Favorite Static Site Host",
			"content_html": "<h1 id=\"xmit-co-might-be-my-new-favorite-static-site-host\" tabindex=\"-1\"><a href=\"https://xmit.co\">🛰️ xmit.co</a> Might Be My New Favorite Static Site Host <a class=\"header-anchor\" href=\"#xmit-co-might-be-my-new-favorite-static-site-host\">#</a></h1>\n<p>I have a new favorite static host: <a href=\"https://xmit.co\">🛰️ xmit.co</a>.\nOver the years I've used Netlify, Vercel, Render, GitHub Pages, Cloudflare Pages, and a few homemade VPS (on Digital Ocean &amp; Vultr) setups held together with Nginx, rsync, GitHub Actions, and hope. They all have their place. But <a href=\"https://xmit.co\">🛰️ xmit.co</a> has been quietly winning me over, mostly because it does the thing I actually want: publish static files, fast, without asking me to reorganize my whole workflow around it.</p>\n<p><a href=\"https://xmit.co\">🛰️ xmit's</a> own pitch is direct — fast, free static hosting, updates in seconds, a system that doesn't resend files it already has, and login through WebAuthn passkeys instead of one more password. It isn't trying to be an app platform or a serverless everything-cloud. It's trying to put static sites online quickly and get out of the way. That's exactly what I want from a host. If thats not easy enough for you there is a GUI <a href=\"https://onclebob.com\">OncleBob.com</a> also by <a href=\"https://xmit.co\">🛰️ xmit.co</a>.</p>\n<h2 id=\"boring-infrastructure-on-purpose\" tabindex=\"-1\">Boring infrastructure, on purpose <a class=\"header-anchor\" href=\"#boring-infrastructure-on-purpose\">#</a></h2>\n<p>You build your site, point Xmit at the output folder, and ship it. The <a href=\"https://github.com/xmit-co/xmit\">CLI</a> is plain: set a key, run something like <code>xmit example.com dist/</code>, done. For anyone running <a href=\"https://11ty.dev\">Build Awesome</a> <s>Eleventy</s>, Astro, Hugo, Vite, Jekyll, Zola, or SvelteKit's static output, that's the whole dream — build locally or in CI, deploy the final files, move on with your day.</p>\n<p><a href=\"https://pcarrier.com/\">Pierre Carrier</a>, who builds Xmit, wrote once about the joy of using your own software to solve your own problems, then called Xmit &quot;a rather boring piece of infrastructure.&quot; That's the good kind of boring — the kind where the site is live and you don't have to think about it again until you want to publish something new. Not exactly a <a href=\"https://hcommons.social/@pc@rrier.fr/116869362980516591\">rousing sales pitch</a> but accurate and appealing (at least to me).</p>\n<h3 id=\"xmit-co-workflow\" tabindex=\"-1\"><a href=\"https://xmit.co\">🛰️ xmit.co</a> workflow <a class=\"header-anchor\" href=\"#xmit-co-workflow\">#</a></h3>\n<p><em>My actual workflow: let GitHub Actions build the site, then let <a href=\"https://xmit.co\">🛰️ xmit.co</a> host the result.</em></p>\n<ol>\n<li>Push source to GitHub.</li>\n<li>GitHub Actions installs dependencies.</li>\n<li>GitHub Actions runs the static site generator's build.</li>\n<li>Upload the output folder — <code>_site</code> for Eleventy, <code>dist</code> for most Vite-based tools — to Xmit.</li>\n</ol>\n<p>That split works well. GitHub owns the build, Xmit owns the hosting, my repo stays the source of truth. <a href=\"https://xmit.dev/guides/end-to-end/\">Xmit's own end-to-end guide</a> walks through basically the same pattern: create an <code>XMIT_KEY</code> secret, run the deploy command from Actions, publish on push to <code>main</code>.</p>\n<h2 id=\"compared-to-what-i-was-using-before\" tabindex=\"-1\">Compared to what I was using before <a class=\"header-anchor\" href=\"#compared-to-what-i-was-using-before\">#</a></h2>\n<p>Netlify is still great, and it more or less defined what static hosting should feel like for a lot of us. Redirects, deploy previews, serverless functions, and Netlify Forms — which can parse a plain HTML form at deploy time with no JavaScript — are all genuinely convenient, and Netlify supports redirects through either a <code>_redirects</code> file or <code>netlify.toml</code>.</p>\n<p>Vercel is excellent if your project is a real frontend application, especially anything Next.js. It's built around <a href=\"https://vercel.com/docs/git\">Git-connected deployments</a>, preview URLs, and scaling actual app workloads. It'll host a static site fine, but that's not really its center of gravity.</p>\n<p>Render is solid too, particularly if you want static sites sitting next to backend services, databases, and workers. It <a href=\"https://render.com/docs/static-sites\">connects to a Git repo</a>, deploys automatically on push, and gives you dashboard redirects and automatic HTTPS.</p>\n<p>None of those are bad tools — I've shipped real projects on all three. Xmit just feels smaller in the right way. It doesn't ask to become the center of your stack. It asks &quot;do you have static files, and do you want them online quickly,&quot; and that's it.</p>\n<table>\n<thead>\n<tr>\n<th></th>\n<th>Xmit</th>\n<th>Netlify</th>\n<th>Vercel</th>\n<th>Render</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Best for</td>\n<td>Static output, indie sites</td>\n<td>Jamstack sites, forms, functions</td>\n<td>Next.js and frontend apps</td>\n<td>Static + backend together</td>\n</tr>\n<tr>\n<td>Deploys via</td>\n<td>CLI, usually from GitHub Actions</td>\n<td>Git-connected build &amp; deploy</td>\n<td>Git-connected build &amp; deploy</td>\n<td>Git-connected build &amp; deploy</td>\n</tr>\n<tr>\n<td>Redirects</td>\n<td><code>xmit.toml</code></td>\n<td><code>_redirects</code> / <code>netlify.toml</code></td>\n<td><code>vercel.json</code></td>\n<td>Dashboard</td>\n</tr>\n<tr>\n<td>Forms</td>\n<td>Form-to-email, lightly documented</td>\n<td>Netlify Forms, mature</td>\n<td>Needs functions/integrations</td>\n<td>Needs a backend</td>\n</tr>\n<tr>\n<td>Vibe</td>\n<td>Small, one developer, focused</td>\n<td>Mature commercial platform</td>\n<td>Polished app platform</td>\n<td>App-platform shaped</td>\n</tr>\n</tbody>\n</table>\n<h2 id=\"redirects-that-dont-make-me-want-to-quit\" tabindex=\"-1\">Redirects that don't make me want to quit <a class=\"header-anchor\" href=\"#redirects-that-dont-make-me-want-to-quit\">#</a></h2>\n<p>I've migrated enough blogs, renamed enough categories, and moved enough domains to know redirects are the thing that seems minor right up until you need them. Xmit handles them through <code>xmit.toml</code>. Pierre <a href=\"https://xmit.dev/posts/pcarrier-com/\">wrote about moving his own site</a> with over a gigabyte of files and, in his words, &quot;a zoo of domain redirects.&quot; The config is plain: <code>[[redirects]]</code>, a <code>from</code>, a <code>to</code>, <code>permanent = true</code>. That's genuinely all it takes.</p>\n<p>One thing that tripped me up: if you're deploying through GitHub Actions like I recommend above, don't forget to copy <code>xmit.toml</code> into your output directory before it uploads, or the redirects just silently won't do anything.</p>\n<p>I have always found netlify's way of doing redirects super simple, Cloudflare's frustrating and xmit's is the closest I have found to netlify's <code>_redirects</code>. It works great.</p>\n<h2 id=\"forms-work-spam-is-still-spam\" tabindex=\"-1\">Forms work, spam is still spam <a class=\"header-anchor\" href=\"#forms-work-spam-is-still-spam\">#</a></h2>\n<p>Xmit has <a href=\"https://xmit.dev/posts/form2mail/\">form-to-email support</a>, though as of the docs I read it's still a little thin on documentation. It's a small feature, but it makes a static site much more useful for the kind of work I do — course sites, project pages, small nonprofits, contact forms for scholars who don't want to run a whole CMS just to receive email.</p>\n<p>The catch is the same catch every static form service has: if a form can email you, bots will eventually find it. Netlify Forms, Formspree, hand-rolled serverless forms — none of them are immune. Add a honeypot, don't publish a high-value inbox if you can avoid it, and check your spam folder regardless of how much SPF and DKIM you set up, because Gmail will bury the notification emails anyway.</p>\n<p><em>If anyone knows of a good recaptcha alt for our present moment that is free/low/no-cost. I'm listening...</em></p>\n<h2 id=\"why-i-m-sticking-with-it\" tabindex=\"-1\">Why I'm sticking with it <a class=\"header-anchor\" href=\"#why-i-m-sticking-with-it\">#</a></h2>\n<p>I do a lot of static site work for teaching, religious studies scholarship, and small nonprofit projects, and most of those sites need to be fast, cheap, and easy to leave alone for months at a time. Xmit fits that better than anything else I've tried lately — it's simple, it plays well with GitHub Actions, redirects don't require a config seminar, and forms are useful enough even with the spam caveat.</p>\n<p>Netlify, Vercel, and Render are all still good tools, and I'll probably keep projects running on all three. But for a plain static site, Xmit is what I reach for first now.</p>\n",
			"date_published": "2026-07-05T00:13:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/fair-signposting-metadata-json-eleventy/",
			"url": "https://www.adamdjbrett.com/blog/fair-signposting-metadata-json-eleventy/",
			"title": "Making Static Sites FAIR with metadata.json, Zotero, Eleventy, and Jekyll",
			"content_html": "<p>I have been thinking a lot about what it means for independent scholarly websites to be readable by more than humans. A good static site should be fast, durable, and readable in the browser. But if the site is publishing scholarly writing, reviews, podcast episodes, transcripts, or resources that people may cite later, it also needs to be readable by Zotero, search engines, archives, citation managers, and whatever discovery systems come next.</p>\n<p>That is the larger reason I started adding FAIR Signposting and per-page <code>metadata.json</code> files to my Eleventy sites.</p>\n<p>The immediate spark was Martin Paul Eve's post, <a href=\"https://eve.gd/2026/06/27/fair-and-square-making-a-static-site-support-fair-signposting/\">&quot;FAIR and Square: making a static site support FAIR signposting&quot;</a>. Martin shows how his static site emits a <code>metadata.json</code> file beside each post and advertises it through HTTP <code>Link</code> headers. The pattern is small, but powerful:</p>\n<ul>\n<li>each page has a stable JSON-LD description;</li>\n<li>the page says where that JSON-LD lives;</li>\n<li>the server can advertise the same metadata before a machine agent even downloads the HTML;</li>\n<li>cited sources can be represented as structured <code>citation</code> objects.</li>\n</ul>\n<p>I started by implementing that pattern in three related but different Eleventy sites:</p>\n<ul>\n<li><code>adamdjbrett.com</code>, where the main unit is a blog post;</li>\n<li><code>dominationchronicles.com</code>, where the main unit is a podcast episode;</li>\n<li><code>outcome.doctrineofdiscovery.org</code>, where the archive mixes blog-style essays, scholarly articles, and podcast episodes.</li>\n</ul>\n<p>Then I pushed the same pattern across a wider set of sites: personal blogs, organizational sites, Then and Now project sites, older Jekyll installations, Minimal Mistakes sites, publication archives, and small Eleventy sites. That second pass taught a different lesson. The pattern transfers cleanly, but the implementation should respect the generator and the content model. A blog post should emit <code>BlogPosting</code>. A podcast episode should emit <code>PodcastEpisode</code>. A journal article should emit <code>ScholarlyArticle</code>. A book-series page should probably emit <code>Book</code>. The shape of the metadata should follow the content, not force everything into one generic object.</p>\n<h2 id=\"what-fair-signposting-adds\" tabindex=\"-1\">What FAIR Signposting Adds <a class=\"header-anchor\" href=\"#what-fair-signposting-adds\">#</a></h2>\n<p>FAIR stands for Findable, Accessible, Interoperable, and Reusable. On the web, one practical way to move toward FAIR is to make explicit links between a human-facing resource and its machine-readable metadata.</p>\n<p>For a post or episode, I want the page to say:</p>\n<ul>\n<li>who authored it;</li>\n<li>how it should be cited;</li>\n<li>what kind of thing it is;</li>\n<li>where its structured metadata lives;</li>\n<li>what license applies, if a license has been explicitly set.</li>\n</ul>\n<p>In HTML, that means links like this:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>author<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://orcid.org/0009-0004-6725-8425<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>cite-as<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://www.adamdjbrett.com/blog/example-post/<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>type<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://schema.org/BlogPosting<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>license<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://creativecommons.org/licenses/by-nc/4.0/deed.en<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span>\n  <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>describedby<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">type</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>application/ld+json<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">profile</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://schema.org/<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>/blog/example-post/metadata.json<span class=\"token punctuation\">\"</span></span>\n<span class=\"token punctuation\">></span></span></code></pre>\n<p>For a podcast episode, the same pattern becomes:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>author<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://stevennewcomb.com/#person<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>author<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://peterderrico.substack.com/#person<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>cite-as<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://dominationchronicles.com/episodes/e008-words-meanings/<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>type<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://schema.org/PodcastEpisode<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span>\n  <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>describedby<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">type</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>application/ld+json<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">profile</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://schema.org/<span class=\"token punctuation\">\"</span></span>\n  <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>/episodes/e008-words-meanings/metadata.json<span class=\"token punctuation\">\"</span></span>\n<span class=\"token punctuation\">></span></span></code></pre>\n<p>Notice the absence of a license link in the podcast example. That is intentional. I do not want a template making rights claims that the site has not explicitly made. On <code>adamdjbrett.com</code>, the blog metadata already has a Creative Commons license configured. On <code>dominationchronicles.com</code>, I am holding that field back until the content license is explicit.</p>\n<h2 id=\"the-blog-version-blogposting\" tabindex=\"-1\">The Blog Version: <code>BlogPosting</code> <a class=\"header-anchor\" href=\"#the-blog-version-blogposting\">#</a></h2>\n<p>On <code>adamdjbrett.com</code>, the existing site already had strong blog metadata. The head template emitted Zotero tags, Dublin Core fields, and inline Schema.org <code>BlogPosting</code> JSON-LD. The problem was duplication. If I created a separate <code>metadata.json</code> template by copying the inline JSON-LD, the two versions would drift.</p>\n<p>So I made the JSON-LD a shared Nunjucks partial.</p>\n<pre class=\"language-njk\" tabindex=\"0\"><code class=\"language-njk\"><span class=\"token punctuation\">{</span>\n  <span class=\"token string\">\"@context\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"https://schema.org\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"@type\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"BlogPosting\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"@id\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token punctuation\">(</span><span class=\"token variable\">jsonld_url</span> <span class=\"token operator\">~</span> <span class=\"token string\">\"#article\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"name\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">jsonld_title</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"headline\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">jsonld_title</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"description\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">jsonld_description</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"url\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">jsonld_url</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"inLanguage\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token punctuation\">(</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">blog</span><span class=\"token punctuation\">.</span><span class=\"token variable\">inLanguage</span> <span class=\"token keyword\">or</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">blog</span><span class=\"token punctuation\">.</span><span class=\"token variable\">inlanguage</span> <span class=\"token keyword\">or</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">language</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"identifier\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">jsonld_identifier</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"license\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token punctuation\">(</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">blog</span><span class=\"token punctuation\">.</span><span class=\"token variable\">license</span> <span class=\"token keyword\">or</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">footer</span><span class=\"token punctuation\">.</span><span class=\"token variable\">text1_link</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"author\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token string\">\"@type\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"Person\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"@id\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token punctuation\">(</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">~</span> <span class=\"token string\">\"#person\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"name\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">author</span><span class=\"token punctuation\">.</span><span class=\"token variable\">name</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"url\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">author</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"identifier\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">blog</span><span class=\"token punctuation\">.</span><span class=\"token variable\">author</span><span class=\"token punctuation\">.</span><span class=\"token variable\">identifier</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"isPartOf\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token string\">\"@type\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"Blog\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"@id\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">blog</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"name\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">blog</span><span class=\"token punctuation\">.</span><span class=\"token variable\">name</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"url\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">blog</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token keyword\">if</span> <span class=\"token variable\">jsonld_citations</span> <span class=\"token keyword\">and</span> <span class=\"token variable\">jsonld_citations</span><span class=\"token punctuation\">.</span><span class=\"token variable\">length</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"citation\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">jsonld_citations</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endif</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>The <code>@id</code> for the blog itself is the clean blog URL:</p>\n<pre class=\"language-json\" tabindex=\"0\"><code class=\"language-json\"><span class=\"token property\">\"@id\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"https://www.adamdjbrett.com/blog/\"</span></code></pre>\n<p>I originally used <code>https://www.adamdjbrett.com/blog/#blog</code>, which works as a JSON-LD identifier, but looks awkward in the generated metadata. It was not necessary. The clean URL is easier to read and remains a stable identifier for the blog collection.</p>\n<p>Then I created a Nunjucks template that paginates over <code>collections.posts</code> and writes one <code>metadata.json</code> file beside every post:</p>\n<pre class=\"language-njk\" tabindex=\"0\"><code class=\"language-njk\"><span class=\"token operator\">-</span><span class=\"token operator\">-</span><span class=\"token operator\">-</span>\n<span class=\"token variable\">pagination</span><span class=\"token punctuation\">:</span>\n  <span class=\"token variable\">data</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">collections</span><span class=\"token punctuation\">.</span><span class=\"token variable\">posts</span>\n  <span class=\"token variable\">size</span><span class=\"token punctuation\">:</span> <span class=\"token number\">1</span>\n  <span class=\"token variable\">alias</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">post</span>\n<span class=\"token variable\">permalink</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"{{ post.url }}metadata.json\"</span>\n<span class=\"token variable\">layout</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">null</span>\n<span class=\"token variable\">eleventyExcludeFromCollections</span><span class=\"token punctuation\">:</span> <span class=\"token boolean\">true</span>\n<span class=\"token operator\">-</span><span class=\"token operator\">-</span><span class=\"token operator\">-</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">postData</span> <span class=\"token operator\">=</span> <span class=\"token variable\">post</span><span class=\"token punctuation\">.</span><span class=\"token variable\">data</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">jsonld_title</span> <span class=\"token operator\">=</span> <span class=\"token variable\">postData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">title</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">jsonld_description</span> <span class=\"token operator\">=</span> <span class=\"token variable\">postData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">description</span> <span class=\"token operator\">|</span> <span class=\"token function\">metaDescription</span><span class=\"token punctuation\">(</span><span class=\"token variable\">postData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">title</span> <span class=\"token keyword\">or</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">title</span><span class=\"token punctuation\">,</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">title</span><span class=\"token punctuation\">,</span> <span class=\"token variable\">post</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">jsonld_url</span> <span class=\"token operator\">=</span> <span class=\"token variable\">postData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">canonical_url</span> <span class=\"token function\">or</span> <span class=\"token punctuation\">(</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">~</span> <span class=\"token variable\">post</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">jsonld_identifier</span> <span class=\"token operator\">=</span> <span class=\"token variable\">postData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">doi</span> <span class=\"token keyword\">or</span> <span class=\"token variable\">postData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">canonical_url</span> <span class=\"token function\">or</span> <span class=\"token punctuation\">(</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">~</span> <span class=\"token variable\">post</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">jsonld_image</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token variable\">postData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">image</span> <span class=\"token keyword\">or</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">image</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">|</span> <span class=\"token variable\">url</span> <span class=\"token operator\">|</span> <span class=\"token function\">absoluteUrl</span><span class=\"token punctuation\">(</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">jsonld_date_published</span> <span class=\"token operator\">=</span> <span class=\"token variable\">post</span><span class=\"token punctuation\">.</span><span class=\"token variable\">date</span> <span class=\"token operator\">|</span> <span class=\"token variable\">htmlDateString</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">jsonld_date_modified</span> <span class=\"token operator\">=</span> <span class=\"token variable\">post</span><span class=\"token punctuation\">.</span><span class=\"token variable\">date</span> <span class=\"token operator\">|</span> <span class=\"token variable\">htmlDateString</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">jsonld_citations</span> <span class=\"token operator\">=</span> <span class=\"token variable\">postData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">citations</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">include</span> <span class=\"token string\">\"widget/blog-post-jsonld.njk\"</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span></code></pre>\n<p>That produces URLs like:</p>\n<pre class=\"language-text\" tabindex=\"0\"><code class=\"language-text\">/blog/zotero-harvestable-blog-posts/metadata.json\n/blog/2026-06-29-on-being-in-the-middle/metadata.json</code></pre>\n<p>The same shared partial is also included inside the existing blog page head:</p>\n<pre class=\"language-njk\" tabindex=\"0\"><code class=\"language-njk\"><span class=\"token operator\">&lt;</span><span class=\"token variable\">script</span> <span class=\"token variable\">type</span><span class=\"token operator\">=</span><span class=\"token string\">\"application/ld+json\"</span><span class=\"token operator\">></span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">jsonld_title</span> <span class=\"token operator\">=</span> <span class=\"token variable\">title</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">jsonld_description</span> <span class=\"token operator\">=</span> <span class=\"token variable\">meta_description</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">jsonld_url</span> <span class=\"token operator\">=</span> <span class=\"token variable\">page_url</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">jsonld_identifier</span> <span class=\"token operator\">=</span> <span class=\"token variable\">doi</span> <span class=\"token keyword\">or</span> <span class=\"token variable\">canonical_url</span> <span class=\"token function\">or</span> <span class=\"token punctuation\">(</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">~</span> <span class=\"token variable\">page</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">jsonld_image</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token variable\">image</span> <span class=\"token keyword\">or</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">image</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">|</span> <span class=\"token variable\">url</span> <span class=\"token operator\">|</span> <span class=\"token function\">absoluteUrl</span><span class=\"token punctuation\">(</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">jsonld_date_published</span> <span class=\"token operator\">=</span> <span class=\"token variable\">page</span><span class=\"token punctuation\">.</span><span class=\"token variable\">date</span> <span class=\"token operator\">|</span> <span class=\"token variable\">htmlDateString</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">jsonld_date_modified</span> <span class=\"token operator\">=</span> <span class=\"token variable\">page</span><span class=\"token punctuation\">.</span><span class=\"token variable\">date</span> <span class=\"token operator\">|</span> <span class=\"token variable\">htmlDateString</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">jsonld_citations</span> <span class=\"token operator\">=</span> <span class=\"token variable\">citations</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">include</span> <span class=\"token string\">\"widget/blog-post-jsonld.njk\"</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span><span class=\"token variable\">script</span><span class=\"token operator\">></span></code></pre>\n<p>That keeps the inline JSON-LD and the external <code>metadata.json</code> synchronized.</p>\n<h2 id=\"the-podcast-version-podcastepisode\" tabindex=\"-1\">The Podcast Version: <code>PodcastEpisode</code> <a class=\"header-anchor\" href=\"#the-podcast-version-podcastepisode\">#</a></h2>\n<p><code>dominationchronicles.com</code> needed the same infrastructure, but not the same Schema.org type.</p>\n<p>The site already had a <code>PodcastSeries</code> in its JSON-LD:</p>\n<pre class=\"language-json\" tabindex=\"0\"><code class=\"language-json\"><span class=\"token punctuation\">{</span>\n  <span class=\"token property\">\"@type\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"PodcastSeries\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"@id\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"https://dominationchronicles.com/#podcast\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"name\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"The Domination Chronicles\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"url\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"https://dominationchronicles.com/\"</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>That is the correct parent object for episode metadata. Each episode should point back to that series with <code>partOfSeries</code>.</p>\n<p>The episode JSON-LD partial looks like this:</p>\n<pre class=\"language-njk\" tabindex=\"0\"><code class=\"language-njk\"><span class=\"token punctuation\">{</span>\n  <span class=\"token string\">\"@context\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"https://schema.org\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"@type\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"PodcastEpisode\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"@id\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">episode_jsonld_url</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"name\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">episode_jsonld_title</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"headline\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">episode_jsonld_title</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"description\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">episode_jsonld_description</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"url\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">episode_jsonld_url</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"inLanguage\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token punctuation\">(</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">language</span> <span class=\"token keyword\">or</span> <span class=\"token string\">\"en\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"datePublished\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">episode_jsonld_date</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"duration\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">episode_jsonld_duration</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"image\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">episode_jsonld_image</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"author\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">[</span>\n    <span class=\"token punctuation\">{</span>\n      <span class=\"token string\">\"@type\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"Person\"</span><span class=\"token punctuation\">,</span>\n      <span class=\"token string\">\"@id\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"https://stevennewcomb.com/#person\"</span><span class=\"token punctuation\">,</span>\n      <span class=\"token string\">\"name\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"Steven T. Newcomb\"</span><span class=\"token punctuation\">,</span>\n      <span class=\"token string\">\"url\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"https://stevennewcomb.com/\"</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">{</span>\n      <span class=\"token string\">\"@type\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"Person\"</span><span class=\"token punctuation\">,</span>\n      <span class=\"token string\">\"@id\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"https://peterderrico.substack.com/#person\"</span><span class=\"token punctuation\">,</span>\n      <span class=\"token string\">\"name\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"Peter d'Errico\"</span><span class=\"token punctuation\">,</span>\n      <span class=\"token string\">\"url\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"https://peterderrico.substack.com/\"</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"publisher\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token string\">\"@type\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"Organization\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"@id\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token keyword\">or</span> <span class=\"token string\">\"https://dominationchronicles.com\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">~</span> <span class=\"token string\">\"/#org\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"name\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"The Domination Chronicles\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"url\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token keyword\">or</span> <span class=\"token string\">\"https://dominationchronicles.com\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">~</span> <span class=\"token string\">\"/\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"partOfSeries\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token string\">\"@type\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"PodcastSeries\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"@id\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token keyword\">or</span> <span class=\"token string\">\"https://dominationchronicles.com\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">~</span> <span class=\"token string\">\"/#podcast\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"name\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"The Domination Chronicles\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"url\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token keyword\">or</span> <span class=\"token string\">\"https://dominationchronicles.com\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">~</span> <span class=\"token string\">\"/\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token keyword\">if</span> <span class=\"token variable\">episode_jsonld_citations</span> <span class=\"token keyword\">and</span> <span class=\"token variable\">episode_jsonld_citations</span><span class=\"token punctuation\">.</span><span class=\"token variable\">length</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"citation\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">episode_jsonld_citations</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endif</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>Then a template paginates over <code>collections.episodes</code>:</p>\n<pre class=\"language-njk\" tabindex=\"0\"><code class=\"language-njk\"><span class=\"token operator\">-</span><span class=\"token operator\">-</span><span class=\"token operator\">-</span>\n<span class=\"token variable\">pagination</span><span class=\"token punctuation\">:</span>\n  <span class=\"token variable\">data</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">collections</span><span class=\"token punctuation\">.</span><span class=\"token variable\">episodes</span>\n  <span class=\"token variable\">size</span><span class=\"token punctuation\">:</span> <span class=\"token number\">1</span>\n  <span class=\"token variable\">alias</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">episodePost</span>\n<span class=\"token variable\">permalink</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"{{ episodePost.url }}metadata.json\"</span>\n<span class=\"token variable\">layout</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">null</span>\n<span class=\"token variable\">eleventyExcludeFromCollections</span><span class=\"token punctuation\">:</span> <span class=\"token boolean\">true</span>\n<span class=\"token operator\">-</span><span class=\"token operator\">-</span><span class=\"token operator\">-</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">episodeData</span> <span class=\"token operator\">=</span> <span class=\"token variable\">episodePost</span><span class=\"token punctuation\">.</span><span class=\"token variable\">data</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">episode_jsonld_title</span> <span class=\"token operator\">=</span> <span class=\"token variable\">episodeData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">title</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">episode_jsonld_description</span> <span class=\"token operator\">=</span> <span class=\"token variable\">episodeData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">description</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">episode_jsonld_url</span> <span class=\"token operator\">=</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">~</span> <span class=\"token variable\">episodePost</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">episode_jsonld_date</span> <span class=\"token operator\">=</span> <span class=\"token variable\">episodeData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">publishDate</span> <span class=\"token operator\">|</span> <span class=\"token variable\">xmlDate</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">episode_jsonld_duration</span> <span class=\"token operator\">=</span> <span class=\"token variable\">episodeData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">duration</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">episode_jsonld_image</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token variable\">episodeData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">image</span> <span class=\"token keyword\">or</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">image</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">|</span> <span class=\"token function\">absoluteUrl</span><span class=\"token punctuation\">(</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">episode_jsonld_audio</span> <span class=\"token operator\">=</span> <span class=\"token variable\">episodeData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">audioUrl</span> <span class=\"token keyword\">or</span> <span class=\"token variable\">episodeData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">audio</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">episode_jsonld_video</span> <span class=\"token operator\">=</span> <span class=\"token variable\">episodeData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">videoUrl</span> <span class=\"token function\">or</span> <span class=\"token punctuation\">(</span><span class=\"token variable\">episodeData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">videoId</span> <span class=\"token function\">and</span> <span class=\"token punctuation\">(</span><span class=\"token string\">\"https://www.youtube.com/watch?v=\"</span> <span class=\"token operator\">~</span> <span class=\"token variable\">episodeData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">videoId</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">episode_jsonld_transcript</span> <span class=\"token operator\">=</span> <span class=\"token variable\">episodeData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">transcriptUrl</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">episode_jsonld_citations</span> <span class=\"token operator\">=</span> <span class=\"token variable\">episodeData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">citations</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">include</span> <span class=\"token string\">\"partials/episode-jsonld.njk\"</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span></code></pre>\n<p>That produces:</p>\n<pre class=\"language-text\" tabindex=\"0\"><code class=\"language-text\">/episodes/e008-words-meanings/metadata.json\n/episodes/e017-bruce-mcivor-legalized-lawlessness/metadata.json</code></pre>\n<p>Those files describe episodes as episodes. That distinction matters. If everything is <code>CreativeWork</code>, machines can still read it, but the metadata is less precise. If an episode is a podcast episode, say so.</p>\n<h2 id=\"the-archive-version-mixed-schema-org-types\" tabindex=\"-1\">The Archive Version: Mixed Schema.org Types <a class=\"header-anchor\" href=\"#the-archive-version-mixed-schema-org-types\">#</a></h2>\n<p><code>outcome.doctrineofdiscovery.org</code> needed the same basic pattern, but it could not be described by one Schema.org type. It is an archive site with several kinds of publication:</p>\n<ul>\n<li>JCRT, JCREOR, IJR, CrossCurrents, Compass, and Ecozoic pieces that should usually be <code>ScholarlyArticle</code>;</li>\n<li>podcast pages that should be <code>PodcastEpisode</code>;</li>\n<li>Canopy, Featured, and other web-native pieces that can be <code>BlogPosting</code>.</li>\n</ul>\n<p>The first implementation used the site's existing <code>posting</code> collection. That worked for many pages, but it missed older podcast entries whose tags came from a different taxonomy. The fix was to create a collection whose membership is based on the source path and URL, not a legacy tag.</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\"><span class=\"token keyword\">const</span> fairEntryPrefixes <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n  <span class=\"token string\">\"/canopy/\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"/compass/\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"/crosscurrents/\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"/ecozoic/\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"/featured/\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"/ijr/\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"/jcreor/\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"/jcrt/\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"/podcast/\"</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> excludedFairEntryBasenames <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Set</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"abstract\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"index\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"toc\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">isFairEntry</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">item</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> url <span class=\"token operator\">=</span> <span class=\"token function\">String</span><span class=\"token punctuation\">(</span>item<span class=\"token operator\">?.</span>url <span class=\"token operator\">||</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">const</span> inputPath <span class=\"token operator\">=</span> <span class=\"token function\">String</span><span class=\"token punctuation\">(</span>item<span class=\"token operator\">?.</span>inputPath <span class=\"token operator\">||</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">const</span> basename <span class=\"token operator\">=</span> path<span class=\"token punctuation\">.</span><span class=\"token function\">basename</span><span class=\"token punctuation\">(</span>inputPath<span class=\"token punctuation\">,</span> path<span class=\"token punctuation\">.</span><span class=\"token function\">extname</span><span class=\"token punctuation\">(</span>inputPath<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">return</span> <span class=\"token function\">Boolean</span><span class=\"token punctuation\">(</span>\n    url <span class=\"token operator\">&amp;&amp;</span>\n    inputPath<span class=\"token punctuation\">.</span><span class=\"token function\">endsWith</span><span class=\"token punctuation\">(</span><span class=\"token string\">\".md\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&amp;&amp;</span>\n    <span class=\"token operator\">!</span>excludedFairEntryBasenames<span class=\"token punctuation\">.</span><span class=\"token function\">has</span><span class=\"token punctuation\">(</span>basename<span class=\"token punctuation\">)</span> <span class=\"token operator\">&amp;&amp;</span>\n    fairEntryPrefixes<span class=\"token punctuation\">.</span><span class=\"token function\">some</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">prefix</span> <span class=\"token operator\">=></span> url<span class=\"token punctuation\">.</span><span class=\"token function\">startsWith</span><span class=\"token punctuation\">(</span>prefix<span class=\"token punctuation\">)</span> <span class=\"token operator\">&amp;&amp;</span> url <span class=\"token operator\">!==</span> prefix<span class=\"token punctuation\">)</span>\n  <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\neleventyConfig<span class=\"token punctuation\">.</span><span class=\"token function\">addCollection</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"fairEntries\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">collectionApi</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span>\n  <span class=\"token function\">sortPostingRecentItems</span><span class=\"token punctuation\">(</span>collectionApi<span class=\"token punctuation\">.</span><span class=\"token function\">getAll</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">filter</span><span class=\"token punctuation\">(</span>isFairEntry<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre>\n<p>The generated <code>metadata.json</code> template paginates over that collection and maps URL families to Schema.org types:</p>\n<pre class=\"language-njk\" tabindex=\"0\"><code class=\"language-njk\"><span class=\"token operator\">-</span><span class=\"token operator\">-</span><span class=\"token operator\">-</span>\n<span class=\"token variable\">pagination</span><span class=\"token punctuation\">:</span>\n  <span class=\"token variable\">data</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">collections</span><span class=\"token punctuation\">.</span><span class=\"token variable\">fairEntries</span>\n  <span class=\"token variable\">size</span><span class=\"token punctuation\">:</span> <span class=\"token number\">1</span>\n  <span class=\"token variable\">alias</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">entryPost</span>\n<span class=\"token variable\">permalink</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"{{ entryPost.url }}metadata.json\"</span>\n<span class=\"token variable\">layout</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">null</span>\n<span class=\"token variable\">eleventyExcludeFromCollections</span><span class=\"token punctuation\">:</span> <span class=\"token boolean\">true</span>\n<span class=\"token operator\">-</span><span class=\"token operator\">-</span><span class=\"token operator\">-</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">entryData</span> <span class=\"token operator\">=</span> <span class=\"token variable\">entryPost</span><span class=\"token punctuation\">.</span><span class=\"token variable\">data</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">academicFolders</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'/compass/'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'/crosscurrents/'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'/ecozoic/'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'/ijr/'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'/jcrt/'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'/jcreor/'</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">entry_jsonld_type</span> <span class=\"token operator\">=</span> <span class=\"token string\">\"BlogPosting\"</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token keyword\">for</span> <span class=\"token variable\">f</span> <span class=\"token keyword\">in</span> <span class=\"token variable\">academicFolders</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token keyword\">if</span> <span class=\"token variable\">entryPost</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span><span class=\"token punctuation\">.</span><span class=\"token function\">startsWith</span><span class=\"token punctuation\">(</span><span class=\"token variable\">f</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">and</span> <span class=\"token variable\">entryPost</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">!=</span> <span class=\"token variable\">f</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">entry_jsonld_type</span> <span class=\"token operator\">=</span> <span class=\"token string\">\"ScholarlyArticle\"</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endif</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endfor</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token keyword\">if</span> <span class=\"token variable\">entryPost</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span><span class=\"token punctuation\">.</span><span class=\"token function\">startsWith</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/podcast/'</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">and</span> <span class=\"token variable\">entryPost</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">!=</span> <span class=\"token string\">'/podcast/'</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">entry_jsonld_type</span> <span class=\"token operator\">=</span> <span class=\"token string\">\"PodcastEpisode\"</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endif</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">entry_jsonld_url</span> <span class=\"token operator\">=</span> <span class=\"token variable\">entryData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">canonical</span> <span class=\"token keyword\">or</span> <span class=\"token variable\">entryData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">canoncial</span> <span class=\"token keyword\">or</span> <span class=\"token variable\">entryData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">doi</span> <span class=\"token function\">or</span> <span class=\"token punctuation\">(</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">~</span> <span class=\"token variable\">entryPost</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">entry_jsonld_title</span> <span class=\"token operator\">=</span> <span class=\"token variable\">entryData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">title</span> <span class=\"token keyword\">or</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">title</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">entry_jsonld_description</span> <span class=\"token operator\">=</span> <span class=\"token variable\">entryData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">description</span> <span class=\"token keyword\">or</span> <span class=\"token variable\">entryData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">abstract</span> <span class=\"token keyword\">or</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">description</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">entry_jsonld_citations</span> <span class=\"token operator\">=</span> <span class=\"token variable\">entryData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">citations</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">include</span> <span class=\"token string\">\"widgets/entry-jsonld.njk\"</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span></code></pre>\n<p>The shared <code>entry-jsonld.njk</code> partial then conditionally adds the parent relationship that fits the type:</p>\n<pre class=\"language-njk\" tabindex=\"0\"><code class=\"language-njk\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token tag keyword\">if</span> <span class=\"token variable\">entry_jsonld_type</span> <span class=\"token operator\">==</span> <span class=\"token string\">\"PodcastEpisode\"</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token string\">\"partOfSeries\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token string\">\"@type\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"PodcastSeries\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"@id\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token punctuation\">(</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">~</span> <span class=\"token string\">\"/podcast/\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"name\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"Mapping the Doctrine of Discovery\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"url\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token punctuation\">(</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">~</span> <span class=\"token string\">\"/podcast/\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">elseif</span> <span class=\"token variable\">entry_jsonld_type</span> <span class=\"token operator\">==</span> <span class=\"token string\">\"BlogPosting\"</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token string\">\"isPartOf\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token string\">\"@type\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"Blog\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"@id\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"name\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">title</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"url\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">|</span> <span class=\"token variable\">jsonify</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endif</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span></code></pre>\n<p>That gives Outcome adjacent files such as:</p>\n<pre class=\"language-text\" tabindex=\"0\"><code class=\"language-text\">/jcrt/issue2/conclusion/metadata.json\n/featured/essay2/documenting/metadata.json\n/podcast/essay1/s2e6/metadata.json</code></pre>\n<p>The important difference is that this site has one FAIR infrastructure but several publication identities. The code decides the type from the archive structure, then the shared partial emits the right shape.</p>\n<h2 id=\"the-11ty-pattern-at-scale\" tabindex=\"-1\">The 11ty Pattern at Scale <a class=\"header-anchor\" href=\"#the-11ty-pattern-at-scale\">#</a></h2>\n<p>Once the first three sites worked, the useful question became: how much of this can be repeated across ordinary 11ty sites without turning every repo into a custom metadata project?</p>\n<p>The answer is: quite a lot.</p>\n<p>For sites such as <code>ebenezer</code>, <code>davidbrett.im</code>, <code>stevennewcomb.com</code>, <code>indigenouslawinstitute.com</code>, and <code>alfieaward.com</code>, the durable content units are mostly posts, resource pages, or press items. These sites do not all have the same theme, but they share enough 11ty structure to use the same pattern:</p>\n<ol>\n<li>add a shared JSON-LD partial;</li>\n<li>add a paginated <code>metadata.json</code> template;</li>\n<li>add a root <code>/metadata.json</code>;</li>\n<li>add FAIR links and Zotero tags to the head template;</li>\n<li>generate <code>_headers</code> where the host can use it.</li>\n</ol>\n<p>The reusable partial is deliberately conservative. It does not try to infer everything. It emits the fields that are stable in the local content model and front matter:</p>\n<pre class=\"language-njk\" tabindex=\"0\"><code class=\"language-njk\"><span class=\"token delimiter punctuation\">{%-</span> <span class=\"token tag keyword\">set</span> <span class=\"token variable\">postData</span> <span class=\"token operator\">=</span> <span class=\"token variable\">post</span><span class=\"token punctuation\">.</span><span class=\"token variable\">data</span> <span class=\"token operator\">-</span><span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span><span class=\"token operator\">-</span> <span class=\"token variable\">set</span> <span class=\"token variable\">postUrl</span> <span class=\"token operator\">=</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">+</span> <span class=\"token variable\">post</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">-</span><span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span><span class=\"token operator\">-</span> <span class=\"token variable\">set</span> <span class=\"token variable\">postTitle</span> <span class=\"token operator\">=</span> <span class=\"token variable\">postData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">title</span> <span class=\"token keyword\">or</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">title</span> <span class=\"token operator\">-</span><span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span><span class=\"token operator\">-</span> <span class=\"token variable\">set</span> <span class=\"token variable\">postDescription</span> <span class=\"token operator\">=</span> <span class=\"token variable\">postData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">description</span> <span class=\"token keyword\">or</span> <span class=\"token variable\">postData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">summary</span> <span class=\"token keyword\">or</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">description</span> <span class=\"token operator\">-</span><span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span><span class=\"token operator\">-</span> <span class=\"token variable\">set</span> <span class=\"token variable\">postImage</span> <span class=\"token operator\">=</span> <span class=\"token variable\">postData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">image</span> <span class=\"token keyword\">or</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">image</span> <span class=\"token operator\">-</span><span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span>\n  <span class=\"token string\">\"@context\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"https://schema.org\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"@type\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"{{ jsonldType or \"</span><span class=\"token variable\">BlogPosting</span><span class=\"token string\">\" }}\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"@id\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token punctuation\">(</span><span class=\"token variable\">postUrl</span> <span class=\"token operator\">+</span> <span class=\"token string\">\"#metadata\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">|</span> <span class=\"token variable\">dump</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"name\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">postTitle</span> <span class=\"token operator\">|</span> <span class=\"token variable\">dump</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"headline\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">postTitle</span> <span class=\"token operator\">|</span> <span class=\"token variable\">dump</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"description\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">postDescription</span> <span class=\"token operator\">|</span> <span class=\"token variable\">dump</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"url\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">postUrl</span> <span class=\"token operator\">|</span> <span class=\"token variable\">dump</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"identifier\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">postUrl</span> <span class=\"token operator\">|</span> <span class=\"token variable\">dump</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"inLanguage\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">language</span> <span class=\"token operator\">|</span> <span class=\"token variable\">dump</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"datePublished\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">post</span><span class=\"token punctuation\">.</span><span class=\"token variable\">date</span> <span class=\"token operator\">|</span> <span class=\"token variable\">htmlDateString</span> <span class=\"token operator\">|</span> <span class=\"token variable\">dump</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"dateModified\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token punctuation\">(</span><span class=\"token variable\">postData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">updated</span> <span class=\"token keyword\">or</span> <span class=\"token variable\">postData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">modified</span> <span class=\"token keyword\">or</span> <span class=\"token variable\">post</span><span class=\"token punctuation\">.</span><span class=\"token variable\">date</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">|</span> <span class=\"token variable\">htmlDateString</span> <span class=\"token operator\">|</span> <span class=\"token variable\">dump</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"author\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token string\">\"@type\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"Person\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"name\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">author</span><span class=\"token punctuation\">.</span><span class=\"token variable\">name</span> <span class=\"token operator\">|</span> <span class=\"token variable\">dump</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"url\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">author</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">|</span> <span class=\"token variable\">dump</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"publisher\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token string\">\"@type\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"Organization\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"name\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">title</span> <span class=\"token operator\">|</span> <span class=\"token variable\">dump</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"url\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">|</span> <span class=\"token variable\">dump</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"isPartOf\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token string\">\"@type\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"Blog\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"@id\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token punctuation\">(</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">+</span> <span class=\"token string\">\"/#blog\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">|</span> <span class=\"token variable\">dump</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"name\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">title</span> <span class=\"token operator\">|</span> <span class=\"token variable\">dump</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"url\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">|</span> <span class=\"token variable\">dump</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token keyword\">if</span> <span class=\"token variable\">postImage</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"image\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">+</span> <span class=\"token variable\">postImage</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">if</span> <span class=\"token string\">\"/\"</span> <span class=\"token operator\">==</span> <span class=\"token variable\">postImage</span><span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span> <span class=\"token keyword\">else</span> <span class=\"token variable\">postImage</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">|</span> <span class=\"token variable\">dump</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endif</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token keyword\">if</span> <span class=\"token variable\">postData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">citations</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"citation\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">postData</span><span class=\"token punctuation\">.</span><span class=\"token variable\">citations</span> <span class=\"token operator\">|</span> <span class=\"token variable\">dump</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endif</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>The <code>dump</code> filter is useful here because it serializes strings, arrays, and objects into JSON safely. The point is not to hand-build quoted strings in a JSON file. Let the template engine serialize the value.</p>\n<p>The adjacent metadata template then becomes tiny:</p>\n<pre class=\"language-njk\" tabindex=\"0\"><code class=\"language-njk\"><span class=\"token operator\">-</span><span class=\"token operator\">-</span><span class=\"token operator\">-</span>\n<span class=\"token variable\">pagination</span><span class=\"token punctuation\">:</span>\n  <span class=\"token variable\">data</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">collections</span><span class=\"token punctuation\">.</span><span class=\"token variable\">posts</span>\n  <span class=\"token variable\">size</span><span class=\"token punctuation\">:</span> <span class=\"token number\">1</span>\n  <span class=\"token variable\">alias</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">post</span>\n<span class=\"token variable\">permalink</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"{{ post.url }}metadata.json\"</span>\n<span class=\"token variable\">layout</span><span class=\"token punctuation\">:</span> <span class=\"token boolean\">false</span>\n<span class=\"token variable\">eleventyExcludeFromCollections</span><span class=\"token punctuation\">:</span> <span class=\"token boolean\">true</span>\n<span class=\"token operator\">-</span><span class=\"token operator\">-</span><span class=\"token operator\">-</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">include</span> <span class=\"token string\">\"partials/post-jsonld.njk\"</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span></code></pre>\n<p>For a press section, the same partial can emit <code>NewsArticle</code> instead of <code>BlogPosting</code>:</p>\n<pre class=\"language-njk\" tabindex=\"0\"><code class=\"language-njk\"><span class=\"token operator\">-</span><span class=\"token operator\">-</span><span class=\"token operator\">-</span>\n<span class=\"token variable\">pagination</span><span class=\"token punctuation\">:</span>\n  <span class=\"token variable\">data</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">collections</span><span class=\"token punctuation\">.</span><span class=\"token variable\">press</span>\n  <span class=\"token variable\">size</span><span class=\"token punctuation\">:</span> <span class=\"token number\">1</span>\n  <span class=\"token variable\">alias</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">post</span>\n<span class=\"token variable\">permalink</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"{{ post.url }}metadata.json\"</span>\n<span class=\"token variable\">layout</span><span class=\"token punctuation\">:</span> <span class=\"token boolean\">false</span>\n<span class=\"token variable\">eleventyExcludeFromCollections</span><span class=\"token punctuation\">:</span> <span class=\"token boolean\">true</span>\n<span class=\"token operator\">-</span><span class=\"token operator\">-</span><span class=\"token operator\">-</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">jsonldType</span> <span class=\"token operator\">=</span> <span class=\"token string\">\"NewsArticle\"</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">include</span> <span class=\"token string\">\"partials/post-jsonld.njk\"</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span></code></pre>\n<p>This is what I used on the Alfie Award site, where the citable items include both blog posts and press releases. The site does not need an elaborate abstraction. It needs one partial and two paginated metadata templates.</p>\n<p>The root site metadata is separate. It describes the site, not an individual post:</p>\n<pre class=\"language-njk\" tabindex=\"0\"><code class=\"language-njk\"><span class=\"token operator\">-</span><span class=\"token operator\">-</span><span class=\"token operator\">-</span>\n<span class=\"token variable\">permalink</span><span class=\"token punctuation\">:</span> <span class=\"token operator\">/</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">json</span>\n<span class=\"token variable\">layout</span><span class=\"token punctuation\">:</span> <span class=\"token boolean\">false</span>\n<span class=\"token variable\">eleventyExcludeFromCollections</span><span class=\"token punctuation\">:</span> <span class=\"token boolean\">true</span>\n<span class=\"token operator\">-</span><span class=\"token operator\">-</span><span class=\"token operator\">-</span>\n<span class=\"token punctuation\">{</span>\n  <span class=\"token string\">\"@context\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"https://schema.org\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"@type\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"WebSite\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"@id\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token punctuation\">(</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">+</span> <span class=\"token string\">\"/#website\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">|</span> <span class=\"token variable\">dump</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"name\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">title</span> <span class=\"token operator\">|</span> <span class=\"token variable\">dump</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"description\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">description</span> <span class=\"token operator\">|</span> <span class=\"token variable\">dump</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"url\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">|</span> <span class=\"token variable\">dump</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"inLanguage\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">language</span> <span class=\"token operator\">|</span> <span class=\"token variable\">dump</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token string\">\"publisher\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token string\">\"@type\"</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"Organization\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"name\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">title</span> <span class=\"token operator\">|</span> <span class=\"token variable\">dump</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"url\"</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">|</span> <span class=\"token variable\">dump</span> <span class=\"token operator\">|</span> <span class=\"token variable\">safe</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>The head template then advertises the adjacent metadata file and gives Zotero enough information to import the item correctly:</p>\n<pre class=\"language-njk\" tabindex=\"0\"><code class=\"language-njk\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token tag keyword\">set</span> <span class=\"token variable\">isPost</span> <span class=\"token operator\">=</span> <span class=\"token variable\">layout</span> <span class=\"token operator\">==</span> <span class=\"token string\">'post'</span> <span class=\"token keyword\">or</span> <span class=\"token string\">\"posts\"</span> <span class=\"token function\">in</span> <span class=\"token punctuation\">(</span><span class=\"token variable\">tags</span> <span class=\"token keyword\">or</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token keyword\">if</span> <span class=\"token variable\">isPost</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">pageCanonical</span> <span class=\"token operator\">=</span> <span class=\"token variable\">canonical_url</span> <span class=\"token keyword\">or</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">+</span> <span class=\"token variable\">page</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">link</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"cite-as\"</span> <span class=\"token variable\">href</span><span class=\"token operator\">=</span><span class=\"token string\">\"{{ pageCanonical }}\"</span><span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">link</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"type\"</span> <span class=\"token variable\">href</span><span class=\"token operator\">=</span><span class=\"token string\">\"https://schema.org/BlogPosting\"</span><span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">link</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"author\"</span> <span class=\"token variable\">href</span><span class=\"token operator\">=</span><span class=\"token string\">\"{{ metadata.author.url or metadata.url }}\"</span><span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">link</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"describedby\"</span> <span class=\"token variable\">type</span><span class=\"token operator\">=</span><span class=\"token string\">\"application/ld+json\"</span> <span class=\"token variable\">profile</span><span class=\"token operator\">=</span><span class=\"token string\">\"https://schema.org/\"</span> <span class=\"token variable\">href</span><span class=\"token operator\">=</span><span class=\"token string\">\"{{ page.url }}metadata.json\"</span><span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">meta</span> <span class=\"token variable\">property</span><span class=\"token operator\">=</span><span class=\"token string\">\"zotero:itemType\"</span> <span class=\"token variable\">content</span><span class=\"token operator\">=</span><span class=\"token string\">\"blogPost\"</span><span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">meta</span> <span class=\"token variable\">property</span><span class=\"token operator\">=</span><span class=\"token string\">\"dc:title\"</span> <span class=\"token variable\">content</span><span class=\"token operator\">=</span><span class=\"token string\">\"{{ (title or metadata.title) | escape }}\"</span><span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">meta</span> <span class=\"token variable\">property</span><span class=\"token operator\">=</span><span class=\"token string\">\"dc:creator\"</span> <span class=\"token variable\">content</span><span class=\"token operator\">=</span><span class=\"token string\">\"{{ metadata.author.name | escape }}\"</span><span class=\"token operator\">></span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token keyword\">if</span> <span class=\"token variable\">date</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span><span class=\"token operator\">&lt;</span><span class=\"token variable\">meta</span> <span class=\"token variable\">property</span><span class=\"token operator\">=</span><span class=\"token string\">\"dc:date\"</span> <span class=\"token variable\">content</span><span class=\"token operator\">=</span><span class=\"token string\">\"{{ date | htmlDateString }}\"</span><span class=\"token operator\">></span><span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endif</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">meta</span> <span class=\"token variable\">property</span><span class=\"token operator\">=</span><span class=\"token string\">\"dc:language\"</span> <span class=\"token variable\">content</span><span class=\"token operator\">=</span><span class=\"token string\">\"{{ metadata.language }}\"</span><span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">meta</span> <span class=\"token variable\">property</span><span class=\"token operator\">=</span><span class=\"token string\">\"dc:identifier\"</span> <span class=\"token variable\">content</span><span class=\"token operator\">=</span><span class=\"token string\">\"{{ pageCanonical }}\"</span><span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">meta</span> <span class=\"token variable\">name</span><span class=\"token operator\">=</span><span class=\"token string\">\"citation_title\"</span> <span class=\"token variable\">content</span><span class=\"token operator\">=</span><span class=\"token string\">\"{{ (title or metadata.title) | escape }}\"</span><span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">meta</span> <span class=\"token variable\">name</span><span class=\"token operator\">=</span><span class=\"token string\">\"citation_author\"</span> <span class=\"token variable\">content</span><span class=\"token operator\">=</span><span class=\"token string\">\"{{ metadata.author.name | escape }}\"</span><span class=\"token operator\">></span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token keyword\">if</span> <span class=\"token variable\">date</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span><span class=\"token operator\">&lt;</span><span class=\"token variable\">meta</span> <span class=\"token variable\">name</span><span class=\"token operator\">=</span><span class=\"token string\">\"citation_publication_date\"</span> <span class=\"token variable\">content</span><span class=\"token operator\">=</span><span class=\"token string\">\"{{ date | htmlDateString }}\"</span><span class=\"token operator\">></span><span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endif</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">meta</span> <span class=\"token variable\">name</span><span class=\"token operator\">=</span><span class=\"token string\">\"citation_fulltext_html_url\"</span> <span class=\"token variable\">content</span><span class=\"token operator\">=</span><span class=\"token string\">\"{{ pageCanonical }}\"</span><span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">meta</span> <span class=\"token variable\">name</span><span class=\"token operator\">=</span><span class=\"token string\">\"citation_public_url\"</span> <span class=\"token variable\">content</span><span class=\"token operator\">=</span><span class=\"token string\">\"{{ pageCanonical }}\"</span><span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">meta</span> <span class=\"token variable\">name</span><span class=\"token operator\">=</span><span class=\"token string\">\"citation_language\"</span> <span class=\"token variable\">content</span><span class=\"token operator\">=</span><span class=\"token string\">\"{{ metadata.language }}\"</span><span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">meta</span> <span class=\"token variable\">name</span><span class=\"token operator\">=</span><span class=\"token string\">\"prism.genre\"</span> <span class=\"token variable\">content</span><span class=\"token operator\">=</span><span class=\"token string\">\"blogentry\"</span><span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">meta</span> <span class=\"token variable\">name</span><span class=\"token operator\">=</span><span class=\"token string\">\"prism.publicationName\"</span> <span class=\"token variable\">content</span><span class=\"token operator\">=</span><span class=\"token string\">\"{{ metadata.title | escape }}\"</span><span class=\"token operator\">></span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endif</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span></code></pre>\n<p>One small bug surfaced while doing this on Steven Newcomb's site. The original condition checked only <code>layout == 'post'</code>, but that site's actual rendered posts used <code>post.njk</code>. The result was that the generated metadata files existed, but the HTML pages did not advertise them. The fix was to make the condition match the site's real layout and tag patterns:</p>\n<pre class=\"language-njk\" tabindex=\"0\"><code class=\"language-njk\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token tag keyword\">set</span> <span class=\"token variable\">isPost</span> <span class=\"token operator\">=</span> <span class=\"token variable\">layout</span> <span class=\"token operator\">==</span> <span class=\"token string\">'post'</span> <span class=\"token keyword\">or</span> <span class=\"token variable\">layout</span> <span class=\"token operator\">==</span> <span class=\"token string\">'post.njk'</span> <span class=\"token keyword\">or</span> <span class=\"token string\">\"posts\"</span> <span class=\"token function\">in</span> <span class=\"token punctuation\">(</span><span class=\"token variable\">tags</span> <span class=\"token keyword\">or</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span></code></pre>\n<p>This is a good example of the larger rule: do not assume all Eleventy sites use the same layout names. Check the local collection and layout conventions before deciding where the metadata should appear.</p>\n<p>The <code>_headers</code> template follows the same collection:</p>\n<pre class=\"language-njk\" tabindex=\"0\"><code class=\"language-njk\"><span class=\"token operator\">-</span><span class=\"token operator\">-</span><span class=\"token operator\">-</span>\n<span class=\"token variable\">permalink</span><span class=\"token punctuation\">:</span> <span class=\"token operator\">/</span><span class=\"token variable\">_headers</span>\n<span class=\"token variable\">layout</span><span class=\"token punctuation\">:</span> <span class=\"token boolean\">false</span>\n<span class=\"token variable\">eleventyExcludeFromCollections</span><span class=\"token punctuation\">:</span> <span class=\"token boolean\">true</span>\n<span class=\"token operator\">-</span><span class=\"token operator\">-</span><span class=\"token operator\">-</span>\n<span class=\"token operator\">/</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">json</span>\n  <span class=\"token variable\">Content</span><span class=\"token operator\">-</span><span class=\"token variable\">Type</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">application</span><span class=\"token operator\">/</span><span class=\"token variable\">ld</span><span class=\"token operator\">+</span><span class=\"token variable\">json</span>\n\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token keyword\">for</span> <span class=\"token variable\">post</span> <span class=\"token keyword\">in</span> <span class=\"token variable\">collections</span><span class=\"token punctuation\">.</span><span class=\"token variable\">posts</span> <span class=\"token operator\">-</span><span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">post</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span>\n  <span class=\"token variable\">Link</span><span class=\"token punctuation\">:</span> <span class=\"token operator\">&lt;</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">post</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">json</span><span class=\"token operator\">></span><span class=\"token punctuation\">;</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"describedby\"</span><span class=\"token punctuation\">;</span> <span class=\"token variable\">type</span><span class=\"token operator\">=</span><span class=\"token string\">\"application/ld+json\"</span><span class=\"token punctuation\">;</span> <span class=\"token variable\">profile</span><span class=\"token operator\">=</span><span class=\"token string\">\"https://schema.org/\"</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&lt;</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">post</span><span class=\"token punctuation\">.</span><span class=\"token variable\">data</span><span class=\"token punctuation\">.</span><span class=\"token variable\">canonical_url</span> <span class=\"token keyword\">or</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">+</span> <span class=\"token variable\">post</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token operator\">></span><span class=\"token punctuation\">;</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"cite-as\"</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&lt;</span><span class=\"token variable\">https</span><span class=\"token punctuation\">:</span><span class=\"token operator\">//</span><span class=\"token variable\">schema</span><span class=\"token punctuation\">.</span><span class=\"token variable\">org</span><span class=\"token operator\">/</span><span class=\"token variable\">BlogPosting</span><span class=\"token operator\">></span><span class=\"token punctuation\">;</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"type\"</span>\n\n<span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">post</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">json</span>\n  <span class=\"token variable\">Content</span><span class=\"token operator\">-</span><span class=\"token variable\">Type</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">application</span><span class=\"token operator\">/</span><span class=\"token variable\">ld</span><span class=\"token operator\">+</span><span class=\"token variable\">json</span>\n\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endfor</span> <span class=\"token operator\">-</span><span class=\"token operator\">%</span><span class=\"token punctuation\">}</span></code></pre>\n<p>Again, this is not the only discovery path. The HTML <code>describedby</code> link is still the guaranteed path. The header is an extra affordance for hosts that support it.</p>\n<p>The 11ty implementation pattern is now clear enough that I can almost treat it as a checklist:</p>\n<ol>\n<li>identify the citable collections;</li>\n<li>make one shared JSON-LD partial per content family;</li>\n<li>paginate over each collection to produce adjacent <code>metadata.json</code>;</li>\n<li>advertise the file from the rendered page head;</li>\n<li>emit Zotero tags in the same condition;</li>\n<li>generate <code>_headers</code> from the same collection;</li>\n<li>build and parse every generated <code>metadata.json</code> file.</li>\n</ol>\n<p>That last step matters. For the latest pass, I parsed 149 generated Eleventy <code>metadata.json</code> files after the build. It is a cheap test and it catches malformed JSON immediately.</p>\n<h2 id=\"the-jekyll-and-minimal-mistakes-version\" tabindex=\"-1\">The Jekyll and Minimal Mistakes Version <a class=\"header-anchor\" href=\"#the-jekyll-and-minimal-mistakes-version\">#</a></h2>\n<p>Jekyll needs a different implementation. There is no Nunjucks pagination template. The cleanest approach is a small generator plugin that creates a <code>metadata.json</code> page beside each post.</p>\n<p>For the Then and Now sites, Quotidian, NABPR, and WOCATI, the generator follows the same structure:</p>\n<pre class=\"language-ruby\" tabindex=\"0\"><code class=\"language-ruby\"><span class=\"token keyword\">require</span> <span class=\"token string-literal\"><span class=\"token string\">\"json\"</span></span>\n\n<span class=\"token keyword\">module</span> <span class=\"token class-name\">FairMetadataJson</span>\n  <span class=\"token keyword\">class</span> <span class=\"token class-name\">MetadataPage</span> <span class=\"token operator\">&lt;</span> Jekyll<span class=\"token double-colon punctuation\">::</span>PageWithoutAFile\n    <span class=\"token keyword\">def</span> <span class=\"token method-definition\"><span class=\"token function\">initialize</span></span><span class=\"token punctuation\">(</span>site<span class=\"token punctuation\">,</span> dir<span class=\"token punctuation\">,</span> doc<span class=\"token punctuation\">,</span> schema_type<span class=\"token punctuation\">)</span>\n      <span class=\"token variable\">@site</span> <span class=\"token operator\">=</span> site\n      <span class=\"token variable\">@base</span> <span class=\"token operator\">=</span> site<span class=\"token punctuation\">.</span>source\n      <span class=\"token variable\">@dir</span> <span class=\"token operator\">=</span> dir\n      <span class=\"token variable\">@name</span> <span class=\"token operator\">=</span> <span class=\"token string-literal\"><span class=\"token string\">\"metadata.json\"</span></span>\n      process<span class=\"token punctuation\">(</span><span class=\"token variable\">@name</span><span class=\"token punctuation\">)</span>\n      <span class=\"token keyword\">self</span><span class=\"token punctuation\">.</span>data <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> <span class=\"token string-literal\"><span class=\"token string\">\"layout\"</span></span> <span class=\"token operator\">=></span> <span class=\"token keyword\">nil</span><span class=\"token punctuation\">,</span> <span class=\"token string-literal\"><span class=\"token string\">\"sitemap\"</span></span> <span class=\"token operator\">=></span> <span class=\"token boolean\">false</span> <span class=\"token punctuation\">}</span>\n      <span class=\"token keyword\">self</span><span class=\"token punctuation\">.</span>content <span class=\"token operator\">=</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span>pretty_generate<span class=\"token punctuation\">(</span>metadata_for<span class=\"token punctuation\">(</span>site<span class=\"token punctuation\">,</span> doc<span class=\"token punctuation\">,</span> schema_type<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span>\n    <span class=\"token keyword\">end</span>\n\n    <span class=\"token keyword\">private</span>\n\n    <span class=\"token keyword\">def</span> <span class=\"token method-definition\"><span class=\"token function\">metadata_for</span></span><span class=\"token punctuation\">(</span>site<span class=\"token punctuation\">,</span> doc<span class=\"token punctuation\">,</span> schema_type<span class=\"token punctuation\">)</span>\n      site_url <span class=\"token operator\">=</span> site<span class=\"token punctuation\">.</span>config<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"url\"</span></span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>to_s<span class=\"token punctuation\">.</span>sub<span class=\"token punctuation\">(</span><span class=\"token regex-literal\"><span class=\"token regex\">%r{/$}</span></span><span class=\"token punctuation\">,</span> <span class=\"token string-literal\"><span class=\"token string\">\"\"</span></span><span class=\"token punctuation\">)</span>\n      title <span class=\"token operator\">=</span> doc<span class=\"token punctuation\">.</span>data<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"title\"</span></span><span class=\"token punctuation\">]</span> <span class=\"token operator\">||</span> site<span class=\"token punctuation\">.</span>config<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"title\"</span></span><span class=\"token punctuation\">]</span> <span class=\"token operator\">||</span> site<span class=\"token punctuation\">.</span>config<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"name\"</span></span><span class=\"token punctuation\">]</span>\n      description <span class=\"token operator\">=</span> doc<span class=\"token punctuation\">.</span>data<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"description\"</span></span><span class=\"token punctuation\">]</span> <span class=\"token operator\">||</span>\n        doc<span class=\"token punctuation\">.</span>data<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"excerpt\"</span></span><span class=\"token punctuation\">]</span> <span class=\"token operator\">||</span>\n        doc<span class=\"token punctuation\">.</span>output<span class=\"token punctuation\">.</span>to_s<span class=\"token punctuation\">.</span>gsub<span class=\"token punctuation\">(</span><span class=\"token regex-literal\"><span class=\"token regex\">/&lt;[^>]+>/</span></span><span class=\"token punctuation\">,</span> <span class=\"token string-literal\"><span class=\"token string\">\" \"</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>squeeze<span class=\"token punctuation\">(</span><span class=\"token string-literal\"><span class=\"token string\">\" \"</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>strip<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">300</span><span class=\"token punctuation\">]</span>\n      url <span class=\"token operator\">=</span> absolute_url<span class=\"token punctuation\">(</span>site_url<span class=\"token punctuation\">,</span> doc<span class=\"token punctuation\">.</span>url<span class=\"token punctuation\">)</span>\n      author <span class=\"token operator\">=</span> doc<span class=\"token punctuation\">.</span>data<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"author\"</span></span><span class=\"token punctuation\">]</span> <span class=\"token operator\">||</span>\n        site<span class=\"token punctuation\">.</span>config<span class=\"token punctuation\">.</span>dig<span class=\"token punctuation\">(</span><span class=\"token string-literal\"><span class=\"token string\">\"author\"</span></span><span class=\"token punctuation\">,</span> <span class=\"token string-literal\"><span class=\"token string\">\"name\"</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">||</span>\n        site<span class=\"token punctuation\">.</span>config<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"author\"</span></span><span class=\"token punctuation\">]</span> <span class=\"token operator\">||</span>\n        site<span class=\"token punctuation\">.</span>config<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"name\"</span></span><span class=\"token punctuation\">]</span> <span class=\"token operator\">||</span>\n        site<span class=\"token punctuation\">.</span>config<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"title\"</span></span><span class=\"token punctuation\">]</span>\n      language <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span>site<span class=\"token punctuation\">.</span>config<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"locale\"</span></span><span class=\"token punctuation\">]</span> <span class=\"token operator\">||</span> site<span class=\"token punctuation\">.</span>config<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"language\"</span></span><span class=\"token punctuation\">]</span> <span class=\"token operator\">||</span> <span class=\"token string-literal\"><span class=\"token string\">\"en\"</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>to_s<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span><span class=\"token punctuation\">]</span>\n      image <span class=\"token operator\">=</span> doc<span class=\"token punctuation\">.</span>data<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"image\"</span></span><span class=\"token punctuation\">]</span> <span class=\"token operator\">||</span>\n        doc<span class=\"token punctuation\">.</span>data<span class=\"token punctuation\">.</span>dig<span class=\"token punctuation\">(</span><span class=\"token string-literal\"><span class=\"token string\">\"header\"</span></span><span class=\"token punctuation\">,</span> <span class=\"token string-literal\"><span class=\"token string\">\"image\"</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">||</span>\n        doc<span class=\"token punctuation\">.</span>data<span class=\"token punctuation\">.</span>dig<span class=\"token punctuation\">(</span><span class=\"token string-literal\"><span class=\"token string\">\"header\"</span></span><span class=\"token punctuation\">,</span> <span class=\"token string-literal\"><span class=\"token string\">\"teaser\"</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">||</span>\n        site<span class=\"token punctuation\">.</span>config<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"teaser\"</span></span><span class=\"token punctuation\">]</span> <span class=\"token operator\">||</span>\n        site<span class=\"token punctuation\">.</span>config<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"logo\"</span></span><span class=\"token punctuation\">]</span>\n\n      data <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n        <span class=\"token string-literal\"><span class=\"token string\">\"@context\"</span></span> <span class=\"token operator\">=></span> <span class=\"token string-literal\"><span class=\"token string\">\"https://schema.org\"</span></span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-literal\"><span class=\"token string\">\"@type\"</span></span> <span class=\"token operator\">=></span> schema_type<span class=\"token punctuation\">,</span>\n        <span class=\"token string-literal\"><span class=\"token string\">\"@id\"</span></span> <span class=\"token operator\">=></span> <span class=\"token string-literal\"><span class=\"token string\">\"</span><span class=\"token interpolation\"><span class=\"token delimiter punctuation\">#{</span><span class=\"token content\">url</span><span class=\"token delimiter punctuation\">}</span></span><span class=\"token string\">#metadata\"</span></span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-literal\"><span class=\"token string\">\"name\"</span></span> <span class=\"token operator\">=></span> title<span class=\"token punctuation\">,</span>\n        <span class=\"token string-literal\"><span class=\"token string\">\"headline\"</span></span> <span class=\"token operator\">=></span> title<span class=\"token punctuation\">,</span>\n        <span class=\"token string-literal\"><span class=\"token string\">\"description\"</span></span> <span class=\"token operator\">=></span> description<span class=\"token punctuation\">,</span>\n        <span class=\"token string-literal\"><span class=\"token string\">\"url\"</span></span> <span class=\"token operator\">=></span> url<span class=\"token punctuation\">,</span>\n        <span class=\"token string-literal\"><span class=\"token string\">\"identifier\"</span></span> <span class=\"token operator\">=></span> url<span class=\"token punctuation\">,</span>\n        <span class=\"token string-literal\"><span class=\"token string\">\"inLanguage\"</span></span> <span class=\"token operator\">=></span> language<span class=\"token punctuation\">,</span>\n        <span class=\"token string-literal\"><span class=\"token string\">\"author\"</span></span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span> <span class=\"token string-literal\"><span class=\"token string\">\"@type\"</span></span> <span class=\"token operator\">=></span> <span class=\"token string-literal\"><span class=\"token string\">\"Person\"</span></span><span class=\"token punctuation\">,</span> <span class=\"token string-literal\"><span class=\"token string\">\"name\"</span></span> <span class=\"token operator\">=></span> author<span class=\"token punctuation\">.</span>to_s <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-literal\"><span class=\"token string\">\"publisher\"</span></span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n          <span class=\"token string-literal\"><span class=\"token string\">\"@type\"</span></span> <span class=\"token operator\">=></span> <span class=\"token string-literal\"><span class=\"token string\">\"Organization\"</span></span><span class=\"token punctuation\">,</span>\n          <span class=\"token string-literal\"><span class=\"token string\">\"name\"</span></span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span>site<span class=\"token punctuation\">.</span>config<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"title\"</span></span><span class=\"token punctuation\">]</span> <span class=\"token operator\">||</span> site<span class=\"token punctuation\">.</span>config<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"name\"</span></span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>to_s<span class=\"token punctuation\">,</span>\n          <span class=\"token string-literal\"><span class=\"token string\">\"url\"</span></span> <span class=\"token operator\">=></span> site_url\n        <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n        <span class=\"token string-literal\"><span class=\"token string\">\"isPartOf\"</span></span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n          <span class=\"token string-literal\"><span class=\"token string\">\"@type\"</span></span> <span class=\"token operator\">=></span> <span class=\"token string-literal\"><span class=\"token string\">\"WebSite\"</span></span><span class=\"token punctuation\">,</span>\n          <span class=\"token string-literal\"><span class=\"token string\">\"@id\"</span></span> <span class=\"token operator\">=></span> <span class=\"token string-literal\"><span class=\"token string\">\"</span><span class=\"token interpolation\"><span class=\"token delimiter punctuation\">#{</span><span class=\"token content\">site_url</span><span class=\"token delimiter punctuation\">}</span></span><span class=\"token string\">/#website\"</span></span><span class=\"token punctuation\">,</span>\n          <span class=\"token string-literal\"><span class=\"token string\">\"name\"</span></span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span>site<span class=\"token punctuation\">.</span>config<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"title\"</span></span><span class=\"token punctuation\">]</span> <span class=\"token operator\">||</span> site<span class=\"token punctuation\">.</span>config<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"name\"</span></span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>to_s<span class=\"token punctuation\">,</span>\n          <span class=\"token string-literal\"><span class=\"token string\">\"url\"</span></span> <span class=\"token operator\">=></span> site_url\n        <span class=\"token punctuation\">}</span>\n      <span class=\"token punctuation\">}</span>\n\n      data<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"datePublished\"</span></span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> doc<span class=\"token punctuation\">.</span>date<span class=\"token punctuation\">.</span>strftime<span class=\"token punctuation\">(</span><span class=\"token string-literal\"><span class=\"token string\">\"%Y-%m-%d\"</span></span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">if</span> doc<span class=\"token punctuation\">.</span>respond_to<span class=\"token operator\">?</span><span class=\"token punctuation\">(</span><span class=\"token symbol\">:date</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">&amp;&amp;</span> doc<span class=\"token punctuation\">.</span>date\n      data<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"dateModified\"</span></span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> doc<span class=\"token punctuation\">.</span>data<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"last_modified_at\"</span></span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span>to_s <span class=\"token keyword\">if</span> doc<span class=\"token punctuation\">.</span>data<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"last_modified_at\"</span></span><span class=\"token punctuation\">]</span>\n      data<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"image\"</span></span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> absolute_url<span class=\"token punctuation\">(</span>site_url<span class=\"token punctuation\">,</span> image<span class=\"token punctuation\">)</span> <span class=\"token keyword\">if</span> image\n      data<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"citation\"</span></span><span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> doc<span class=\"token punctuation\">.</span>data<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"citations\"</span></span><span class=\"token punctuation\">]</span> <span class=\"token keyword\">if</span> doc<span class=\"token punctuation\">.</span>data<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"citations\"</span></span><span class=\"token punctuation\">]</span>\n      data\n    <span class=\"token keyword\">end</span>\n\n    <span class=\"token keyword\">def</span> <span class=\"token method-definition\"><span class=\"token function\">absolute_url</span></span><span class=\"token punctuation\">(</span>site_url<span class=\"token punctuation\">,</span> value<span class=\"token punctuation\">)</span>\n      <span class=\"token keyword\">return</span> <span class=\"token keyword\">nil</span> <span class=\"token keyword\">unless</span> value\n      value <span class=\"token operator\">=</span> value<span class=\"token punctuation\">.</span>to_s\n      <span class=\"token keyword\">return</span> value <span class=\"token keyword\">if</span> value<span class=\"token punctuation\">.</span>start_with<span class=\"token operator\">?</span><span class=\"token punctuation\">(</span><span class=\"token string-literal\"><span class=\"token string\">\"http://\"</span></span><span class=\"token punctuation\">,</span> <span class=\"token string-literal\"><span class=\"token string\">\"https://\"</span></span><span class=\"token punctuation\">)</span>\n      <span class=\"token string-literal\"><span class=\"token string\">\"</span><span class=\"token interpolation\"><span class=\"token delimiter punctuation\">#{</span><span class=\"token content\">site_url</span><span class=\"token delimiter punctuation\">}</span></span><span class=\"token string\">#{value.start_with?(\"/\") ? value : \"/</span><span class=\"token interpolation\"><span class=\"token delimiter punctuation\">#{</span><span class=\"token content\">value</span><span class=\"token delimiter punctuation\">}</span></span><span class=\"token string\">\"</span></span><span class=\"token punctuation\">}</span>\"\n    <span class=\"token keyword\">end</span>\n  <span class=\"token keyword\">end</span>\n\n  <span class=\"token keyword\">class</span> <span class=\"token class-name\">Generator</span> <span class=\"token operator\">&lt;</span> Jekyll<span class=\"token double-colon punctuation\">::</span>Generator\n    safe <span class=\"token boolean\">true</span>\n    priority <span class=\"token symbol\">:low</span>\n\n    <span class=\"token keyword\">def</span> <span class=\"token method-definition\"><span class=\"token function\">generate</span></span><span class=\"token punctuation\">(</span>site<span class=\"token punctuation\">)</span>\n      site<span class=\"token punctuation\">.</span>posts<span class=\"token punctuation\">.</span>docs<span class=\"token punctuation\">.</span><span class=\"token keyword\">each</span> <span class=\"token keyword\">do</span> <span class=\"token operator\">|</span>doc<span class=\"token operator\">|</span>\n        dir <span class=\"token operator\">=</span> doc<span class=\"token punctuation\">.</span>url<span class=\"token punctuation\">.</span>end_with<span class=\"token operator\">?</span><span class=\"token punctuation\">(</span><span class=\"token string-literal\"><span class=\"token string\">\"/\"</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">?</span> doc<span class=\"token punctuation\">.</span>url <span class=\"token operator\">:</span> <span class=\"token string-literal\"><span class=\"token string\">\"</span><span class=\"token interpolation\"><span class=\"token delimiter punctuation\">#{</span><span class=\"token content\">doc<span class=\"token punctuation\">.</span>url</span><span class=\"token delimiter punctuation\">}</span></span><span class=\"token string\">/\"</span></span>\n        site<span class=\"token punctuation\">.</span>pages <span class=\"token operator\">&lt;&lt;</span> <span class=\"token class-name\">MetadataPage</span><span class=\"token punctuation\">.</span><span class=\"token keyword\">new</span><span class=\"token punctuation\">(</span>site<span class=\"token punctuation\">,</span> dir<span class=\"token punctuation\">,</span> doc<span class=\"token punctuation\">,</span> <span class=\"token string-literal\"><span class=\"token string\">\"BlogPosting\"</span></span><span class=\"token punctuation\">)</span>\n      <span class=\"token keyword\">end</span>\n    <span class=\"token keyword\">end</span>\n  <span class=\"token keyword\">end</span>\n<span class=\"token keyword\">end</span></code></pre>\n<p>This is enough for ordinary Jekyll posts. If a post lives at:</p>\n<pre class=\"language-text\" tabindex=\"0\"><code class=\"language-text\">/2015/07/religion-materiality-and-machines/</code></pre>\n<p>the plugin adds:</p>\n<pre class=\"language-text\" tabindex=\"0\"><code class=\"language-text\">/2015/07/religion-materiality-and-machines/metadata.json</code></pre>\n<p>The PBI NABPR book-series site needed one variation. It does not primarily publish posts. Its durable citation targets are <code>_books</code>. So the generator also loops over the <code>books</code> collection and emits <code>Book</code> metadata:</p>\n<pre class=\"language-ruby\" tabindex=\"0\"><code class=\"language-ruby\"><span class=\"token builtin\">Array</span><span class=\"token punctuation\">(</span>site<span class=\"token punctuation\">.</span>collections<span class=\"token punctuation\">[</span><span class=\"token string-literal\"><span class=\"token string\">\"books\"</span></span><span class=\"token punctuation\">]</span><span class=\"token operator\">&amp;.</span>docs<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token keyword\">each</span> <span class=\"token keyword\">do</span> <span class=\"token operator\">|</span>doc<span class=\"token operator\">|</span>\n  dir <span class=\"token operator\">=</span> doc<span class=\"token punctuation\">.</span>url<span class=\"token punctuation\">.</span>end_with<span class=\"token operator\">?</span><span class=\"token punctuation\">(</span><span class=\"token string-literal\"><span class=\"token string\">\"/\"</span></span><span class=\"token punctuation\">)</span> <span class=\"token operator\">?</span> doc<span class=\"token punctuation\">.</span>url <span class=\"token operator\">:</span> <span class=\"token string-literal\"><span class=\"token string\">\"</span><span class=\"token interpolation\"><span class=\"token delimiter punctuation\">#{</span><span class=\"token content\">doc<span class=\"token punctuation\">.</span>url</span><span class=\"token delimiter punctuation\">}</span></span><span class=\"token string\">/\"</span></span>\n  site<span class=\"token punctuation\">.</span>pages <span class=\"token operator\">&lt;&lt;</span> <span class=\"token class-name\">MetadataPage</span><span class=\"token punctuation\">.</span><span class=\"token keyword\">new</span><span class=\"token punctuation\">(</span>site<span class=\"token punctuation\">,</span> dir<span class=\"token punctuation\">,</span> doc<span class=\"token punctuation\">,</span> <span class=\"token string-literal\"><span class=\"token string\">\"Book\"</span></span><span class=\"token punctuation\">)</span>\n<span class=\"token keyword\">end</span></code></pre>\n<p>That is the same lesson again: the metadata type follows the content type. A book-series page should not pretend to be a blog post merely because that was the first pattern I implemented.</p>\n<p>The Jekyll head include is simpler than the generator. In Minimal Mistakes sites, I used <code>_includes/head/custom.html</code> to include a Zotero/signposting partial:</p>\n<pre class=\"language-liquid\" tabindex=\"0\"><code class=\"language-liquid\"><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">include</span> head/zotero<span class=\"token punctuation\">.</span>html <span class=\"token delimiter punctuation\">%}</span></span></code></pre>\n<p>For non-Minimal Mistakes Jekyll sites, the include goes wherever the site already centralizes head metadata. Quotidian uses <code>_includes/head-seo.html</code>. NABPR uses <code>_includes/_head.html</code>.</p>\n<p>The partial itself follows the same shape as the Eleventy head code, but in Liquid:</p>\n<pre class=\"language-liquid\" tabindex=\"0\"><code class=\"language-liquid\"><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">assign</span> zotero_is_post <span class=\"token operator\">=</span> <span class=\"token boolean\">false</span> <span class=\"token delimiter punctuation\">%}</span></span>\n<span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">if</span> <span class=\"token object\">page</span><span class=\"token punctuation\">.</span><span class=\"token object\">collection</span> <span class=\"token operator\">==</span> <span class=\"token string\">\"posts\"</span> <span class=\"token delimiter punctuation\">%}</span></span>\n  <span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">assign</span> zotero_is_post <span class=\"token operator\">=</span> <span class=\"token boolean\">true</span> <span class=\"token delimiter punctuation\">%}</span></span>\n<span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">endif</span> <span class=\"token delimiter punctuation\">%}</span></span>\n<span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">if</span> zotero_is_post <span class=\"token operator\">and</span> <span class=\"token object\">page</span><span class=\"token punctuation\">.</span>published <span class=\"token operator\">!=</span> <span class=\"token boolean\">false</span> <span class=\"token delimiter punctuation\">%}</span></span>\n<span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">assign</span> zotero_author_name <span class=\"token operator\">=</span> <span class=\"token object\">page</span><span class=\"token punctuation\">.</span>author <span class=\"token operator\">|</span> <span class=\"token function filter\">default</span><span class=\"token operator\">:</span> site<span class=\"token punctuation\">.</span>author<span class=\"token punctuation\">.</span>name <span class=\"token operator\">|</span> <span class=\"token function filter\">default</span><span class=\"token operator\">:</span> site<span class=\"token punctuation\">.</span>author <span class=\"token operator\">|</span> <span class=\"token function filter\">default</span><span class=\"token operator\">:</span> site<span class=\"token punctuation\">.</span>title <span class=\"token delimiter punctuation\">%}</span></span>\n<span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">assign</span> zotero_date <span class=\"token operator\">=</span> <span class=\"token object\">page</span><span class=\"token punctuation\">.</span><span class=\"token object\">date</span> <span class=\"token operator\">|</span> <span class=\"token function filter\">default</span><span class=\"token operator\">:</span> <span class=\"token object\">page</span><span class=\"token punctuation\">.</span><span class=\"token function\">last</span>_modified_at <span class=\"token delimiter punctuation\">%}</span></span>\n<span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">assign</span> zotero_metadata_href <span class=\"token operator\">=</span> <span class=\"token object\">page</span><span class=\"token punctuation\">.</span>url <span class=\"token delimiter punctuation\">%}</span></span>\n<span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">assign</span> zotero_metadata_last <span class=\"token operator\">=</span> zotero_metadata_href <span class=\"token operator\">|</span> <span class=\"token function filter\">slice</span><span class=\"token operator\">:</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1</span> <span class=\"token delimiter punctuation\">%}</span></span>\n<span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">unless</span> zotero_metadata_last <span class=\"token operator\">==</span> <span class=\"token string\">\"/\"</span> <span class=\"token delimiter punctuation\">%}</span></span>\n  <span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">assign</span> zotero_metadata_href <span class=\"token operator\">=</span> zotero_metadata_href <span class=\"token operator\">|</span> <span class=\"token function filter\">append</span><span class=\"token operator\">:</span> <span class=\"token string\">\"/\"</span> <span class=\"token delimiter punctuation\">%}</span></span>\n<span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">endunless</span> <span class=\"token delimiter punctuation\">%}</span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>cite-as<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> <span class=\"token object\">page</span><span class=\"token punctuation\">.</span>url <span class=\"token operator\">|</span> <span class=\"token function filter\">absolute_url</span> <span class=\"token delimiter punctuation\">}}</span></span><span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>type<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://schema.org/BlogPosting<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>author<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> site<span class=\"token punctuation\">.</span>url <span class=\"token delimiter punctuation\">}}</span></span><span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>describedby<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">type</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>application/ld+json<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">profile</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://schema.org/<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> zotero_metadata_href <span class=\"token operator\">|</span> <span class=\"token function filter\">append</span><span class=\"token operator\">:</span> <span class=\"token string\">'metadata.json'</span> <span class=\"token operator\">|</span> <span class=\"token function filter\">relative_url</span> <span class=\"token delimiter punctuation\">}}</span></span><span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">property</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>zotero:itemType<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>blogPost<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">property</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>dc:title<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> <span class=\"token object\">page</span><span class=\"token punctuation\">.</span>title <span class=\"token operator\">|</span> <span class=\"token function filter\">markdownify</span> <span class=\"token operator\">|</span> <span class=\"token function filter\">strip_html</span> <span class=\"token operator\">|</span> <span class=\"token function filter\">strip_newlines</span> <span class=\"token operator\">|</span> <span class=\"token function filter\">escape_once</span> <span class=\"token delimiter punctuation\">}}</span></span><span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">property</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>dc:creator<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> zotero_author_name <span class=\"token operator\">|</span> <span class=\"token function filter\">strip</span> <span class=\"token operator\">|</span> <span class=\"token function filter\">escape_once</span> <span class=\"token delimiter punctuation\">}}</span></span><span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">if</span> zotero_date <span class=\"token delimiter punctuation\">%}</span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">property</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>dc:date<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> zotero_date <span class=\"token operator\">|</span> <span class=\"token object\">date</span><span class=\"token operator\">:</span> <span class=\"token string\">'%Y-%m-%d'</span> <span class=\"token delimiter punctuation\">}}</span></span><span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">endif</span> <span class=\"token delimiter punctuation\">%}</span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">property</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>dc:language<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> site<span class=\"token punctuation\">.</span>locale <span class=\"token operator\">|</span> <span class=\"token function filter\">slice</span><span class=\"token operator\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span> <span class=\"token operator\">|</span> <span class=\"token function filter\">default</span><span class=\"token operator\">:</span> <span class=\"token string\">'en'</span> <span class=\"token delimiter punctuation\">}}</span></span><span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">property</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>dc:identifier<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> <span class=\"token object\">page</span><span class=\"token punctuation\">.</span>url <span class=\"token operator\">|</span> <span class=\"token function filter\">absolute_url</span> <span class=\"token delimiter punctuation\">}}</span></span><span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>citation_title<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> <span class=\"token object\">page</span><span class=\"token punctuation\">.</span>title <span class=\"token operator\">|</span> <span class=\"token function filter\">markdownify</span> <span class=\"token operator\">|</span> <span class=\"token function filter\">strip_html</span> <span class=\"token operator\">|</span> <span class=\"token function filter\">strip_newlines</span> <span class=\"token operator\">|</span> <span class=\"token function filter\">escape_once</span> <span class=\"token delimiter punctuation\">}}</span></span><span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>citation_author<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> zotero_author_name <span class=\"token operator\">|</span> <span class=\"token function filter\">strip</span> <span class=\"token operator\">|</span> <span class=\"token function filter\">escape_once</span> <span class=\"token delimiter punctuation\">}}</span></span><span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">if</span> zotero_date <span class=\"token delimiter punctuation\">%}</span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>citation_publication_date<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> zotero_date <span class=\"token operator\">|</span> <span class=\"token object\">date</span><span class=\"token operator\">:</span> <span class=\"token string\">'%Y-%m-%d'</span> <span class=\"token delimiter punctuation\">}}</span></span><span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">endif</span> <span class=\"token delimiter punctuation\">%}</span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>citation_fulltext_html_url<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> <span class=\"token object\">page</span><span class=\"token punctuation\">.</span>url <span class=\"token operator\">|</span> <span class=\"token function filter\">absolute_url</span> <span class=\"token delimiter punctuation\">}}</span></span><span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>citation_public_url<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> <span class=\"token object\">page</span><span class=\"token punctuation\">.</span>url <span class=\"token operator\">|</span> <span class=\"token function filter\">absolute_url</span> <span class=\"token delimiter punctuation\">}}</span></span><span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>citation_language<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> site<span class=\"token punctuation\">.</span>locale <span class=\"token operator\">|</span> <span class=\"token function filter\">slice</span><span class=\"token operator\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span><span class=\"token number\">2</span> <span class=\"token operator\">|</span> <span class=\"token function filter\">default</span><span class=\"token operator\">:</span> <span class=\"token string\">'en'</span> <span class=\"token delimiter punctuation\">}}</span></span><span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">if</span> <span class=\"token object\">page</span><span class=\"token punctuation\">.</span>doi <span class=\"token delimiter punctuation\">%}</span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>citation_doi<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> <span class=\"token object\">page</span><span class=\"token punctuation\">.</span>doi <span class=\"token operator\">|</span> <span class=\"token function filter\">escape_once</span> <span class=\"token delimiter punctuation\">}}</span></span><span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">endif</span> <span class=\"token delimiter punctuation\">%}</span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>prism.genre<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>blogentry<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>prism.publicationName<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> site<span class=\"token punctuation\">.</span>title <span class=\"token operator\">|</span> <span class=\"token function filter\">escape_once</span> <span class=\"token delimiter punctuation\">}}</span></span><span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">endif</span> <span class=\"token delimiter punctuation\">%}</span></span></code></pre>\n<p>For PBI book pages, the same file can add a book branch:</p>\n<pre class=\"language-liquid\" tabindex=\"0\"><code class=\"language-liquid\"><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">if</span> <span class=\"token object\">page</span><span class=\"token punctuation\">.</span><span class=\"token object\">collection</span> <span class=\"token operator\">==</span> <span class=\"token string\">\"books\"</span> <span class=\"token operator\">and</span> <span class=\"token object\">page</span><span class=\"token punctuation\">.</span>published <span class=\"token operator\">!=</span> <span class=\"token boolean\">false</span> <span class=\"token delimiter punctuation\">%}</span></span>\n<span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">assign</span> zotero_author_name <span class=\"token operator\">=</span> <span class=\"token object\">page</span><span class=\"token punctuation\">.</span>author <span class=\"token operator\">|</span> <span class=\"token function filter\">default</span><span class=\"token operator\">:</span> <span class=\"token object\">page</span><span class=\"token punctuation\">.</span>book_author <span class=\"token operator\">|</span> <span class=\"token function filter\">default</span><span class=\"token operator\">:</span> site<span class=\"token punctuation\">.</span>name <span class=\"token delimiter punctuation\">%}</span></span>\n<span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">assign</span> zotero_metadata_href <span class=\"token operator\">=</span> <span class=\"token object\">page</span><span class=\"token punctuation\">.</span>url <span class=\"token delimiter punctuation\">%}</span></span>\n<span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">assign</span> zotero_metadata_last <span class=\"token operator\">=</span> zotero_metadata_href <span class=\"token operator\">|</span> <span class=\"token function filter\">slice</span><span class=\"token operator\">:</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1</span> <span class=\"token delimiter punctuation\">%}</span></span>\n<span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">unless</span> zotero_metadata_last <span class=\"token operator\">==</span> <span class=\"token string\">\"/\"</span> <span class=\"token delimiter punctuation\">%}</span></span>\n  <span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">assign</span> zotero_metadata_href <span class=\"token operator\">=</span> zotero_metadata_href <span class=\"token operator\">|</span> <span class=\"token function filter\">append</span><span class=\"token operator\">:</span> <span class=\"token string\">\"/\"</span> <span class=\"token delimiter punctuation\">%}</span></span>\n<span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">endunless</span> <span class=\"token delimiter punctuation\">%}</span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>cite-as<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> <span class=\"token object\">page</span><span class=\"token punctuation\">.</span>url <span class=\"token operator\">|</span> <span class=\"token function filter\">absolute_url</span> <span class=\"token delimiter punctuation\">}}</span></span><span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>type<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://schema.org/Book<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>author<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> site<span class=\"token punctuation\">.</span>url <span class=\"token delimiter punctuation\">}}</span></span><span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>describedby<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">type</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>application/ld+json<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">profile</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://schema.org/<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> zotero_metadata_href <span class=\"token operator\">|</span> <span class=\"token function filter\">append</span><span class=\"token operator\">:</span> <span class=\"token string\">'metadata.json'</span> <span class=\"token operator\">|</span> <span class=\"token function filter\">relative_url</span> <span class=\"token delimiter punctuation\">}}</span></span><span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">property</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>zotero:itemType<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>book<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">property</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>dc:title<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> <span class=\"token object\">page</span><span class=\"token punctuation\">.</span>title <span class=\"token operator\">|</span> <span class=\"token function filter\">markdownify</span> <span class=\"token operator\">|</span> <span class=\"token function filter\">strip_html</span> <span class=\"token operator\">|</span> <span class=\"token function filter\">strip_newlines</span> <span class=\"token operator\">|</span> <span class=\"token function filter\">escape_once</span> <span class=\"token delimiter punctuation\">}}</span></span><span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">property</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>dc:creator<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> zotero_author_name <span class=\"token operator\">|</span> <span class=\"token function filter\">strip</span> <span class=\"token operator\">|</span> <span class=\"token function filter\">escape_once</span> <span class=\"token delimiter punctuation\">}}</span></span><span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>citation_title<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> <span class=\"token object\">page</span><span class=\"token punctuation\">.</span>title <span class=\"token operator\">|</span> <span class=\"token function filter\">markdownify</span> <span class=\"token operator\">|</span> <span class=\"token function filter\">strip_html</span> <span class=\"token operator\">|</span> <span class=\"token function filter\">strip_newlines</span> <span class=\"token operator\">|</span> <span class=\"token function filter\">escape_once</span> <span class=\"token delimiter punctuation\">}}</span></span><span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>citation_author<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> zotero_author_name <span class=\"token operator\">|</span> <span class=\"token function filter\">strip</span> <span class=\"token operator\">|</span> <span class=\"token function filter\">escape_once</span> <span class=\"token delimiter punctuation\">}}</span></span><span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>citation_fulltext_html_url<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> <span class=\"token object\">page</span><span class=\"token punctuation\">.</span>url <span class=\"token operator\">|</span> <span class=\"token function filter\">absolute_url</span> <span class=\"token delimiter punctuation\">}}</span></span><span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>citation_public_url<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> <span class=\"token object\">page</span><span class=\"token punctuation\">.</span>url <span class=\"token operator\">|</span> <span class=\"token function filter\">absolute_url</span> <span class=\"token delimiter punctuation\">}}</span></span><span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>prism.genre<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>book<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>prism.publicationName<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>Perspectives on Baptist Identities<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token keyword\">endif</span> <span class=\"token delimiter punctuation\">%}</span></span></code></pre>\n<p>I also added root-level <code>metadata.json</code> files to the Jekyll sites. These are Liquid templates, not generated pages:</p>\n<pre class=\"language-liquid\" tabindex=\"0\"><code class=\"language-liquid\">---\nlayout: null\nsitemap: false\n---\n{\n  \"@context\": \"https://schema.org\",\n  \"@type\": \"WebSite\",\n  \"@id\": <span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> site<span class=\"token punctuation\">.</span>url <span class=\"token operator\">|</span> <span class=\"token function filter\">append</span><span class=\"token operator\">:</span> <span class=\"token string\">\"/#website\"</span> <span class=\"token operator\">|</span> <span class=\"token function filter\">jsonify</span> <span class=\"token delimiter punctuation\">}}</span></span>,\n  \"name\": <span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> site<span class=\"token punctuation\">.</span>title <span class=\"token operator\">|</span> <span class=\"token function filter\">default</span><span class=\"token operator\">:</span> site<span class=\"token punctuation\">.</span>name <span class=\"token operator\">|</span> <span class=\"token function filter\">jsonify</span> <span class=\"token delimiter punctuation\">}}</span></span>,\n  \"description\": <span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> site<span class=\"token punctuation\">.</span>description <span class=\"token operator\">|</span> <span class=\"token function filter\">strip_newlines</span> <span class=\"token operator\">|</span> <span class=\"token function filter\">jsonify</span> <span class=\"token delimiter punctuation\">}}</span></span>,\n  \"url\": <span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> site<span class=\"token punctuation\">.</span>url <span class=\"token operator\">|</span> <span class=\"token function filter\">jsonify</span> <span class=\"token delimiter punctuation\">}}</span></span>,\n  \"inLanguage\": <span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> site<span class=\"token punctuation\">.</span>locale <span class=\"token operator\">|</span> <span class=\"token function filter\">slice</span><span class=\"token operator\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> <span class=\"token number\">2</span> <span class=\"token operator\">|</span> <span class=\"token function filter\">default</span><span class=\"token operator\">:</span> <span class=\"token string\">\"en\"</span> <span class=\"token operator\">|</span> <span class=\"token function filter\">jsonify</span> <span class=\"token delimiter punctuation\">}}</span></span>,\n  \"publisher\": {\n    \"@type\": \"Organization\",\n    \"name\": <span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> site<span class=\"token punctuation\">.</span>title <span class=\"token operator\">|</span> <span class=\"token function filter\">default</span><span class=\"token operator\">:</span> site<span class=\"token punctuation\">.</span>name <span class=\"token operator\">|</span> <span class=\"token function filter\">jsonify</span> <span class=\"token delimiter punctuation\">}}</span></span>,\n    \"url\": <span class=\"token liquid language-liquid\"><span class=\"token delimiter punctuation\">{{</span> site<span class=\"token punctuation\">.</span>url <span class=\"token operator\">|</span> <span class=\"token function filter\">jsonify</span> <span class=\"token delimiter punctuation\">}}</span></span>\n  }\n}</code></pre>\n<p>Jekyll verification was less smooth than Eleventy verification. The custom Ruby plugins all passed:</p>\n<pre class=\"language-sh\" tabindex=\"0\"><code class=\"language-sh\">ruby <span class=\"token parameter variable\">-c</span> _plugins/fair_metadata_json.rb</code></pre>\n<p>But several full Jekyll builds were blocked locally by Ruby and Bundler state: missing Bundler <code>4.0.11</code>, missing local Jekyll gems, and rake version conflicts. That is not unusual with older Jekyll repos, but it changes what can be honestly claimed. In those cases I verified plugin syntax and head-template wiring, and left full build verification for an environment with the repo's bundle installed cleanly.</p>\n<h2 id=\"adding-signposting-links-in-the-page-head\" tabindex=\"-1\">Adding Signposting Links in the Page Head <a class=\"header-anchor\" href=\"#adding-signposting-links-in-the-page-head\">#</a></h2>\n<p>For <code>adamdjbrett.com</code>, the blog SEO partial adds signposting only when the current page is a blog post:</p>\n<pre class=\"language-njk\" tabindex=\"0\"><code class=\"language-njk\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token tag keyword\">if</span> <span class=\"token variable\">page</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token keyword\">and</span> <span class=\"token variable\">page</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span><span class=\"token punctuation\">.</span><span class=\"token function\">startsWith</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"/blog/\"</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">and</span> <span class=\"token variable\">page</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">!=</span> <span class=\"token string\">\"/blog/\"</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">link</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"author\"</span> <span class=\"token variable\">href</span><span class=\"token operator\">=</span><span class=\"token string\">\"{{ metadata.blog.author.identifier }}\"</span><span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">link</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"cite-as\"</span> <span class=\"token variable\">href</span><span class=\"token operator\">=</span><span class=\"token string\">\"{{ page_url }}\"</span><span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">link</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"type\"</span> <span class=\"token variable\">href</span><span class=\"token operator\">=</span><span class=\"token string\">\"https://schema.org/BlogPosting\"</span><span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">link</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"license\"</span> <span class=\"token variable\">href</span><span class=\"token operator\">=</span><span class=\"token string\">\"{{ metadata.blog.license }}\"</span><span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">link</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"describedby\"</span> <span class=\"token variable\">type</span><span class=\"token operator\">=</span><span class=\"token string\">\"application/ld+json\"</span> <span class=\"token variable\">profile</span><span class=\"token operator\">=</span><span class=\"token string\">\"https://schema.org/\"</span> <span class=\"token variable\">href</span><span class=\"token operator\">=</span><span class=\"token string\">\"{{ page.url }}metadata.json\"</span><span class=\"token operator\">></span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endif</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span></code></pre>\n<p>For <code>dominationchronicles.com</code>, the SEO partial already knows when a page is an episode:</p>\n<pre class=\"language-njk\" tabindex=\"0\"><code class=\"language-njk\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token tag keyword\">set</span> <span class=\"token variable\">isEpisode</span> <span class=\"token operator\">=</span> <span class=\"token string\">\"episodes\"</span> <span class=\"token function\">in</span> <span class=\"token punctuation\">(</span><span class=\"token variable\">tags</span> <span class=\"token keyword\">or</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span></code></pre>\n<p>So the episode signposting lives inside that check:</p>\n<pre class=\"language-njk\" tabindex=\"0\"><code class=\"language-njk\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token tag keyword\">if</span> <span class=\"token variable\">isEpisode</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">link</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"author\"</span> <span class=\"token variable\">href</span><span class=\"token operator\">=</span><span class=\"token string\">\"https://stevennewcomb.com/#person\"</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">link</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"author\"</span> <span class=\"token variable\">href</span><span class=\"token operator\">=</span><span class=\"token string\">\"https://peterderrico.substack.com/#person\"</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">link</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"cite-as\"</span> <span class=\"token variable\">href</span><span class=\"token operator\">=</span><span class=\"token string\">\"{{ canonicalUrl }}\"</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">link</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"type\"</span> <span class=\"token variable\">href</span><span class=\"token operator\">=</span><span class=\"token string\">\"https://schema.org/PodcastEpisode\"</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token keyword\">if</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">license</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">link</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"license\"</span> <span class=\"token variable\">href</span><span class=\"token operator\">=</span><span class=\"token string\">\"{{ metadata.license }}\"</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endif</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">link</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"describedby\"</span> <span class=\"token variable\">type</span><span class=\"token operator\">=</span><span class=\"token string\">\"application/ld+json\"</span> <span class=\"token variable\">profile</span><span class=\"token operator\">=</span><span class=\"token string\">\"https://schema.org/\"</span> <span class=\"token variable\">href</span><span class=\"token operator\">=</span><span class=\"token string\">\"{{ page.url }}metadata.json\"</span> <span class=\"token operator\">/</span><span class=\"token operator\">></span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endif</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span></code></pre>\n<p>For Outcome, the head template uses the same folder list as the collection so the HTML and generated files stay aligned:</p>\n<pre class=\"language-njk\" tabindex=\"0\"><code class=\"language-njk\"><span class=\"token delimiter punctuation\">{%</span> <span class=\"token tag keyword\">set</span> <span class=\"token variable\">fairFolders</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'/canopy/'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'/compass/'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'/crosscurrents/'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'/ecozoic/'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'/featured/'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'/ijr/'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'/jcreor/'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'/jcrt/'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'/podcast/'</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">academicFolders</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'/compass/'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'/crosscurrents/'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'/ecozoic/'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'/ijr/'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'/jcrt/'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'/jcreor/'</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">isFairEntry</span> <span class=\"token operator\">=</span> <span class=\"token boolean\">false</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token keyword\">for</span> <span class=\"token variable\">f</span> <span class=\"token keyword\">in</span> <span class=\"token variable\">fairFolders</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token keyword\">if</span> <span class=\"token variable\">page</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span><span class=\"token punctuation\">.</span><span class=\"token function\">startsWith</span><span class=\"token punctuation\">(</span><span class=\"token variable\">f</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">and</span> <span class=\"token variable\">page</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">!=</span> <span class=\"token variable\">f</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">isFairEntry</span> <span class=\"token operator\">=</span> <span class=\"token boolean\">true</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endif</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endfor</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">fairType</span> <span class=\"token operator\">=</span> <span class=\"token string\">\"BlogPosting\"</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token keyword\">for</span> <span class=\"token variable\">f</span> <span class=\"token keyword\">in</span> <span class=\"token variable\">academicFolders</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token keyword\">if</span> <span class=\"token variable\">page</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span><span class=\"token punctuation\">.</span><span class=\"token function\">startsWith</span><span class=\"token punctuation\">(</span><span class=\"token variable\">f</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">and</span> <span class=\"token variable\">page</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">!=</span> <span class=\"token variable\">f</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">fairType</span> <span class=\"token operator\">=</span> <span class=\"token string\">\"ScholarlyArticle\"</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endif</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endfor</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token keyword\">if</span> <span class=\"token variable\">page</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span><span class=\"token punctuation\">.</span><span class=\"token function\">startsWith</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/podcast/'</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">and</span> <span class=\"token variable\">page</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">!=</span> <span class=\"token string\">'/podcast/'</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">fairType</span> <span class=\"token operator\">=</span> <span class=\"token string\">\"PodcastEpisode\"</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endif</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token keyword\">if</span> <span class=\"token variable\">isFairEntry</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">link</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"cite-as\"</span> <span class=\"token variable\">href</span><span class=\"token operator\">=</span><span class=\"token string\">\"{{ fairCanonical }}\"</span><span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">link</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"type\"</span> <span class=\"token variable\">href</span><span class=\"token operator\">=</span><span class=\"token string\">\"https://schema.org/{{ fairType }}\"</span><span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">link</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"license\"</span> <span class=\"token variable\">href</span><span class=\"token operator\">=</span><span class=\"token string\">\"{{ metadata.footer.licency.text2_link }}\"</span><span class=\"token operator\">></span>\n<span class=\"token operator\">&lt;</span><span class=\"token variable\">link</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"describedby\"</span> <span class=\"token variable\">type</span><span class=\"token operator\">=</span><span class=\"token string\">\"application/ld+json\"</span> <span class=\"token variable\">profile</span><span class=\"token operator\">=</span><span class=\"token string\">\"https://schema.org/\"</span> <span class=\"token variable\">href</span><span class=\"token operator\">=</span><span class=\"token string\">\"{{ page.url }}metadata.json\"</span><span class=\"token operator\">></span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endif</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span></code></pre>\n<p>This is the part that gives tools a path from the HTML page to the adjacent machine-readable file.</p>\n<h2 id=\"headers-useful-but-host-dependent\" tabindex=\"-1\">Headers: Useful, but Host-Dependent <a class=\"header-anchor\" href=\"#headers-useful-but-host-dependent\">#</a></h2>\n<p>Martin's post uses Apache <code>.htaccess</code> files to emit HTTP <code>Link</code> headers per post directory. That works well when Apache honors per-directory <code>.htaccess</code>.</p>\n<p>These sites are deployed differently.</p>\n<p><code>adamdjbrett.com</code> deploys through Netlify, so I can generate a Netlify-style <code>_headers</code> file:</p>\n<pre class=\"language-njk\" tabindex=\"0\"><code class=\"language-njk\"><span class=\"token operator\">-</span><span class=\"token operator\">-</span><span class=\"token operator\">-</span>\n<span class=\"token variable\">permalink</span><span class=\"token punctuation\">:</span> <span class=\"token operator\">/</span><span class=\"token variable\">_headers</span>\n<span class=\"token variable\">layout</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">null</span>\n<span class=\"token variable\">eleventyExcludeFromCollections</span><span class=\"token punctuation\">:</span> <span class=\"token boolean\">true</span>\n<span class=\"token operator\">-</span><span class=\"token operator\">-</span><span class=\"token operator\">-</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token keyword\">for</span> <span class=\"token variable\">post</span> <span class=\"token keyword\">in</span> <span class=\"token variable\">collections</span><span class=\"token punctuation\">.</span><span class=\"token variable\">posts</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">post</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span>\n  <span class=\"token variable\">Link</span><span class=\"token punctuation\">:</span> <span class=\"token operator\">&lt;</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">blog</span><span class=\"token punctuation\">.</span><span class=\"token variable\">author</span><span class=\"token punctuation\">.</span><span class=\"token variable\">identifier</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token operator\">></span><span class=\"token punctuation\">;</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"author\"</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&lt;</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">post</span><span class=\"token punctuation\">.</span><span class=\"token variable\">data</span><span class=\"token punctuation\">.</span><span class=\"token variable\">canonical_url</span> <span class=\"token function\">or</span> <span class=\"token punctuation\">(</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">~</span> <span class=\"token variable\">post</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token operator\">></span><span class=\"token punctuation\">;</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"cite-as\"</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&lt;</span><span class=\"token variable\">https</span><span class=\"token punctuation\">:</span><span class=\"token operator\">//</span><span class=\"token variable\">schema</span><span class=\"token punctuation\">.</span><span class=\"token variable\">org</span><span class=\"token operator\">/</span><span class=\"token variable\">BlogPosting</span><span class=\"token operator\">></span><span class=\"token punctuation\">;</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"type\"</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&lt;</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">blog</span><span class=\"token punctuation\">.</span><span class=\"token variable\">license</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token operator\">></span><span class=\"token punctuation\">;</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"license\"</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&lt;</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">post</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">json</span><span class=\"token operator\">></span><span class=\"token punctuation\">;</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"describedby\"</span><span class=\"token punctuation\">;</span> <span class=\"token variable\">type</span><span class=\"token operator\">=</span><span class=\"token string\">\"application/ld+json\"</span><span class=\"token punctuation\">;</span> <span class=\"token variable\">profile</span><span class=\"token operator\">=</span><span class=\"token string\">\"https://schema.org/\"</span>\n\n<span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">post</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">json</span>\n  <span class=\"token variable\">Content</span><span class=\"token operator\">-</span><span class=\"token variable\">Type</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">application</span><span class=\"token operator\">/</span><span class=\"token variable\">ld</span><span class=\"token operator\">+</span><span class=\"token variable\">json</span>\n\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endfor</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span></code></pre>\n<p><code>dominationchronicles.com</code> deploys through XMIT. I do not want to assume XMIT supports Netlify's <code>_headers</code> format. Still, generating <code>_headers</code> is harmless as a best-effort artifact, and the HTML <code>&lt;link&gt;</code> elements remain the guaranteed signposting path.</p>\n<p>The episode version is:</p>\n<pre class=\"language-njk\" tabindex=\"0\"><code class=\"language-njk\"><span class=\"token operator\">-</span><span class=\"token operator\">-</span><span class=\"token operator\">-</span>\n<span class=\"token variable\">permalink</span><span class=\"token punctuation\">:</span> <span class=\"token operator\">/</span><span class=\"token variable\">_headers</span>\n<span class=\"token variable\">layout</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">null</span>\n<span class=\"token variable\">eleventyExcludeFromCollections</span><span class=\"token punctuation\">:</span> <span class=\"token boolean\">true</span>\n<span class=\"token operator\">-</span><span class=\"token operator\">-</span><span class=\"token operator\">-</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token keyword\">for</span> <span class=\"token variable\">episodePost</span> <span class=\"token keyword\">in</span> <span class=\"token variable\">collections</span><span class=\"token punctuation\">.</span><span class=\"token variable\">episodes</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">episodePost</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span>\n  <span class=\"token variable\">Link</span><span class=\"token punctuation\">:</span> <span class=\"token operator\">&lt;</span><span class=\"token variable\">https</span><span class=\"token punctuation\">:</span><span class=\"token operator\">//</span><span class=\"token variable\">stevennewcomb</span><span class=\"token punctuation\">.</span><span class=\"token variable\">com</span><span class=\"token operator\">/</span>#<span class=\"token variable\">person</span><span class=\"token operator\">></span><span class=\"token punctuation\">;</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"author\"</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&lt;</span><span class=\"token variable\">https</span><span class=\"token punctuation\">:</span><span class=\"token operator\">//</span><span class=\"token variable\">peterderrico</span><span class=\"token punctuation\">.</span><span class=\"token variable\">substack</span><span class=\"token punctuation\">.</span><span class=\"token variable\">com</span><span class=\"token operator\">/</span>#<span class=\"token variable\">person</span><span class=\"token operator\">></span><span class=\"token punctuation\">;</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"author\"</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&lt;</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">episodePost</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token operator\">></span><span class=\"token punctuation\">;</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"cite-as\"</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&lt;</span><span class=\"token variable\">https</span><span class=\"token punctuation\">:</span><span class=\"token operator\">//</span><span class=\"token variable\">schema</span><span class=\"token punctuation\">.</span><span class=\"token variable\">org</span><span class=\"token operator\">/</span><span class=\"token variable\">PodcastEpisode</span><span class=\"token operator\">></span><span class=\"token punctuation\">;</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"type\"</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&lt;</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">episodePost</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">json</span><span class=\"token operator\">></span><span class=\"token punctuation\">;</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"describedby\"</span><span class=\"token punctuation\">;</span> <span class=\"token variable\">type</span><span class=\"token operator\">=</span><span class=\"token string\">\"application/ld+json\"</span><span class=\"token punctuation\">;</span> <span class=\"token variable\">profile</span><span class=\"token operator\">=</span><span class=\"token string\">\"https://schema.org/\"</span>\n\n<span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">episodePost</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">json</span>\n  <span class=\"token variable\">Content</span><span class=\"token operator\">-</span><span class=\"token variable\">Type</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">application</span><span class=\"token operator\">/</span><span class=\"token variable\">ld</span><span class=\"token operator\">+</span><span class=\"token variable\">json</span>\n\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endfor</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span></code></pre>\n<p>If the host supports <code>_headers</code>, machines can discover the metadata from HTTP headers. If not, they can still discover it from the HTML.</p>\n<p>Outcome deploys through Netlify, so the <code>_headers</code> file is part of the build output. The template loops over the same <code>fairEntries</code> collection used for <code>metadata.json</code>:</p>\n<pre class=\"language-njk\" tabindex=\"0\"><code class=\"language-njk\"><span class=\"token operator\">-</span><span class=\"token operator\">-</span><span class=\"token operator\">-</span>\n<span class=\"token variable\">permalink</span><span class=\"token punctuation\">:</span> <span class=\"token operator\">/</span><span class=\"token variable\">_headers</span>\n<span class=\"token variable\">layout</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">null</span>\n<span class=\"token variable\">eleventyExcludeFromCollections</span><span class=\"token punctuation\">:</span> <span class=\"token boolean\">true</span>\n<span class=\"token operator\">-</span><span class=\"token operator\">-</span><span class=\"token operator\">-</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">academicFolders</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token string\">'/compass/'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'/crosscurrents/'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'/ecozoic/'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'/ijr/'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'/jcrt/'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'/jcreor/'</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token keyword\">for</span> <span class=\"token variable\">entryPost</span> <span class=\"token keyword\">in</span> <span class=\"token variable\">collections</span><span class=\"token punctuation\">.</span><span class=\"token variable\">fairEntries</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token keyword\">if</span> <span class=\"token variable\">entryPost</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">entryType</span> <span class=\"token operator\">=</span> <span class=\"token string\">\"BlogPosting\"</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token keyword\">for</span> <span class=\"token variable\">f</span> <span class=\"token keyword\">in</span> <span class=\"token variable\">academicFolders</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token keyword\">if</span> <span class=\"token variable\">entryPost</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span><span class=\"token punctuation\">.</span><span class=\"token function\">startsWith</span><span class=\"token punctuation\">(</span><span class=\"token variable\">f</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">and</span> <span class=\"token variable\">entryPost</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">!=</span> <span class=\"token variable\">f</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n    <span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">entryType</span> <span class=\"token operator\">=</span> <span class=\"token string\">\"ScholarlyArticle\"</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endif</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endfor</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token keyword\">if</span> <span class=\"token variable\">entryPost</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span><span class=\"token punctuation\">.</span><span class=\"token function\">startsWith</span><span class=\"token punctuation\">(</span><span class=\"token string\">'/podcast/'</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">and</span> <span class=\"token variable\">entryPost</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">!=</span> <span class=\"token string\">'/podcast/'</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">entryType</span> <span class=\"token operator\">=</span> <span class=\"token string\">\"PodcastEpisode\"</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endif</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">set</span> <span class=\"token variable\">citeAs</span> <span class=\"token operator\">=</span> <span class=\"token variable\">entryPost</span><span class=\"token punctuation\">.</span><span class=\"token variable\">data</span><span class=\"token punctuation\">.</span><span class=\"token variable\">canonical</span> <span class=\"token keyword\">or</span> <span class=\"token variable\">entryPost</span><span class=\"token punctuation\">.</span><span class=\"token variable\">data</span><span class=\"token punctuation\">.</span><span class=\"token variable\">canoncial</span> <span class=\"token keyword\">or</span> <span class=\"token variable\">entryPost</span><span class=\"token punctuation\">.</span><span class=\"token variable\">data</span><span class=\"token punctuation\">.</span><span class=\"token variable\">doi</span> <span class=\"token function\">or</span> <span class=\"token punctuation\">(</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token operator\">~</span> <span class=\"token variable\">entryPost</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">entryPost</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span>\n  <span class=\"token variable\">Link</span><span class=\"token punctuation\">:</span> <span class=\"token operator\">&lt;</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">citeAs</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token operator\">></span><span class=\"token punctuation\">;</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"cite-as\"</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&lt;</span><span class=\"token variable\">https</span><span class=\"token punctuation\">:</span><span class=\"token operator\">//</span><span class=\"token variable\">schema</span><span class=\"token punctuation\">.</span><span class=\"token variable\">org</span><span class=\"token operator\">/</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">entryType</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token operator\">></span><span class=\"token punctuation\">;</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"type\"</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&lt;</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">footer</span><span class=\"token punctuation\">.</span><span class=\"token variable\">licency</span><span class=\"token punctuation\">.</span><span class=\"token variable\">text2_link</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token operator\">></span><span class=\"token punctuation\">;</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"license\"</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&lt;</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">entryPost</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">json</span><span class=\"token operator\">></span><span class=\"token punctuation\">;</span> <span class=\"token variable\">rel</span><span class=\"token operator\">=</span><span class=\"token string\">\"describedby\"</span><span class=\"token punctuation\">;</span> <span class=\"token variable\">type</span><span class=\"token operator\">=</span><span class=\"token string\">\"application/ld+json\"</span><span class=\"token punctuation\">;</span> <span class=\"token variable\">profile</span><span class=\"token operator\">=</span><span class=\"token string\">\"https://schema.org/\"</span>\n\n<span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> <span class=\"token variable\">entryPost</span><span class=\"token punctuation\">.</span><span class=\"token variable\">url</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span><span class=\"token variable\">metadata</span><span class=\"token punctuation\">.</span><span class=\"token variable\">json</span>\n  <span class=\"token variable\">Content</span><span class=\"token operator\">-</span><span class=\"token variable\">Type</span><span class=\"token punctuation\">:</span> <span class=\"token variable\">application</span><span class=\"token operator\">/</span><span class=\"token variable\">ld</span><span class=\"token operator\">+</span><span class=\"token variable\">json</span>\n\n<span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endif</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">{</span><span class=\"token operator\">%</span> <span class=\"token variable\">endfor</span> <span class=\"token operator\">%</span><span class=\"token punctuation\">}</span></code></pre>\n<h2 id=\"citation-automation\" tabindex=\"-1\">Citation Automation <a class=\"header-anchor\" href=\"#citation-automation\">#</a></h2>\n<p>The next layer is citation data.</p>\n<p>Eve's post shows a useful pattern where front matter can include references and the generated <code>metadata.json</code> includes a Schema.org <code>citation</code> array. That matters because it turns a post from an isolated object into part of a citation network.</p>\n<p>For <code>adamdjbrett.com</code>, the source field is:</p>\n<pre class=\"language-yaml\" tabindex=\"0\"><code class=\"language-yaml\"><span class=\"token key atrule\">references</span><span class=\"token punctuation\">:</span>\n  <span class=\"token punctuation\">-</span> https<span class=\"token punctuation\">:</span>//doi.org/10.59348/vrt01<span class=\"token punctuation\">-</span>f3b49\n  <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">type</span><span class=\"token punctuation\">:</span> BlogPosting\n    <span class=\"token key atrule\">title</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"Zotero-Nikola Harmony (One Simple Trick)\"</span>\n    <span class=\"token key atrule\">url</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"https://paregorios.org/posts/2018/05/zotero_nikola_harmony/\"</span>\n    <span class=\"token key atrule\">author</span><span class=\"token punctuation\">:</span>\n      <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Tom Elliott\n      <span class=\"token key atrule\">orcid</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"https://orcid.org/0000-0002-4114-6677\"</span>\n    <span class=\"token key atrule\">date</span><span class=\"token punctuation\">:</span> <span class=\"token datetime number\">2018-05-08</span>\n    <span class=\"token key atrule\">language</span><span class=\"token punctuation\">:</span> en</code></pre>\n<p>The generated field is:</p>\n<pre class=\"language-yaml\" tabindex=\"0\"><code class=\"language-yaml\"><span class=\"token key atrule\">citations</span><span class=\"token punctuation\">:</span>\n  <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">'@type'</span><span class=\"token punctuation\">:</span> ScholarlyArticle\n    <span class=\"token key atrule\">'@id'</span><span class=\"token punctuation\">:</span> https<span class=\"token punctuation\">:</span>//doi.org/10.59348/vrt01<span class=\"token punctuation\">-</span>f3b49\n    <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Making blog posts harvestable by Zotero and preserving case in citation fields\n    <span class=\"token key atrule\">url</span><span class=\"token punctuation\">:</span> https<span class=\"token punctuation\">:</span>//doi.org/10.59348/vrt01<span class=\"token punctuation\">-</span>f3b49</code></pre>\n<p>The helper script supports:</p>\n<ul>\n<li>DOI URLs;</li>\n<li>self-cites to local posts;</li>\n<li>arbitrary web URLs;</li>\n<li>manual override objects.</li>\n</ul>\n<p>The basic resolver looks like this:</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\"><span class=\"token keyword\">async</span> <span class=\"token keyword\">function</span> <span class=\"token function\">resolveReference</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">ref<span class=\"token punctuation\">,</span> localPosts</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>ref <span class=\"token operator\">&amp;&amp;</span> <span class=\"token keyword\">typeof</span> ref <span class=\"token operator\">===</span> <span class=\"token string\">\"object\"</span> <span class=\"token operator\">&amp;&amp;</span> <span class=\"token operator\">!</span>Array<span class=\"token punctuation\">.</span><span class=\"token function\">isArray</span><span class=\"token punctuation\">(</span>ref<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token function\">normalizeManualReference</span><span class=\"token punctuation\">(</span>ref<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> ref <span class=\"token operator\">!==</span> <span class=\"token string\">\"string\"</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">const</span> url <span class=\"token operator\">=</span> ref<span class=\"token punctuation\">.</span><span class=\"token function\">split</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">\\s+#</span><span class=\"token regex-delimiter\">/</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token function\">trim</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>url<span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">doiFromUrl</span><span class=\"token punctuation\">(</span>url<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token function\">citationFromDoi</span><span class=\"token punctuation\">(</span>url<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">const</span> local <span class=\"token operator\">=</span> <span class=\"token function\">citationFromLocalPost</span><span class=\"token punctuation\">(</span>url<span class=\"token punctuation\">,</span> localPosts<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>local<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> local<span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">try</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token keyword\">await</span> <span class=\"token function\">citationFromWebPage</span><span class=\"token punctuation\">(</span>url<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token string-property property\">\"@type\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"WebPage\"</span><span class=\"token punctuation\">,</span>\n      <span class=\"token string-property property\">\"@id\"</span><span class=\"token operator\">:</span> url<span class=\"token punctuation\">,</span>\n      <span class=\"token literal-property property\">name</span><span class=\"token operator\">:</span> url<span class=\"token punctuation\">,</span>\n      url\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>For <code>dominationchronicles.com</code>, there was already a citation generator:</p>\n<pre class=\"language-json\" tabindex=\"0\"><code class=\"language-json\"><span class=\"token property\">\"citations\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"node scripts/generate-citations.cjs\"</span></code></pre>\n<p>That existing script writes RIS and CSL JSON files into <code>public/citations</code>. I did not want to replace it. Instead, the FAIR citation helper focuses only on structured citation data for JSON-LD.</p>\n<p>It uses this input order:</p>\n<ol>\n<li>use front matter <code>references</code> if present;</li>\n<li>otherwise scan the episode body's <code>Resources</code> section for URLs;</li>\n<li>write generated Schema.org objects back to <code>citations</code> only when explicitly run.</li>\n</ol>\n<p>The resource scanner is intentionally simple:</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\"><span class=\"token keyword\">function</span> <span class=\"token function\">extractResourcesSection</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">body</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> start <span class=\"token operator\">=</span> body<span class=\"token punctuation\">.</span><span class=\"token function\">search</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">^##+\\s+\\*{0,2}Resources\\*{0,2}\\s*:?\\s*$</span><span class=\"token regex-delimiter\">/</span><span class=\"token regex-flags\">im</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>start <span class=\"token operator\">===</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">const</span> section <span class=\"token operator\">=</span> body<span class=\"token punctuation\">.</span><span class=\"token function\">slice</span><span class=\"token punctuation\">(</span>start<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">const</span> nextHeading <span class=\"token operator\">=</span> section<span class=\"token punctuation\">.</span><span class=\"token function\">slice</span><span class=\"token punctuation\">(</span><span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">search</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">^##+\\s+</span><span class=\"token regex-delimiter\">/</span><span class=\"token regex-flags\">m</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">return</span> nextHeading <span class=\"token operator\">===</span> <span class=\"token operator\">-</span><span class=\"token number\">1</span> <span class=\"token operator\">?</span> section <span class=\"token operator\">:</span> section<span class=\"token punctuation\">.</span><span class=\"token function\">slice</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">,</span> nextHeading <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">function</span> <span class=\"token function\">extractUrlsFromResources</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">body</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> resources <span class=\"token operator\">=</span> <span class=\"token function\">extractResourcesSection</span><span class=\"token punctuation\">(</span>body<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>resources<span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">const</span> urls <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">const</span> seen <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Set</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> match <span class=\"token keyword\">of</span> resources<span class=\"token punctuation\">.</span><span class=\"token function\">matchAll</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">https?:\\/\\/[^\\s&lt;>)\\]]+</span><span class=\"token regex-delimiter\">/</span><span class=\"token regex-flags\">g</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> url <span class=\"token operator\">=</span> match<span class=\"token punctuation\">[</span><span class=\"token number\">0</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">.</span><span class=\"token function\">replace</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">[.,;:!?]+$</span><span class=\"token regex-delimiter\">/</span><span class=\"token regex-flags\">g</span></span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>seen<span class=\"token punctuation\">.</span><span class=\"token function\">has</span><span class=\"token punctuation\">(</span>url<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      seen<span class=\"token punctuation\">.</span><span class=\"token function\">add</span><span class=\"token punctuation\">(</span>url<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      urls<span class=\"token punctuation\">.</span><span class=\"token function\">push</span><span class=\"token punctuation\">(</span>url<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">return</span> urls<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>That means existing episode resource lists can become structured citation metadata without rewriting every episode by hand.</p>\n<p>Outcome uses the same idea, but broadens it to an archive. The helper is <code>scripts/add-entry-citations.mjs</code>, with this input order:</p>\n<ol>\n<li>use front matter <code>references</code> when it exists;</li>\n<li>otherwise use known citation-like front matter such as <code>doi</code>, <code>canonical</code>, <code>canoncial</code>, or <code>pdf</code>;</li>\n<li>otherwise fall back to local <code>how_to_cite</code> text when available.</li>\n</ol>\n<p>That last fallback is less rich than DOI or web metadata, but it is useful for an archive where many pages already contain human-readable citation guidance.</p>\n<p>The npm scripts are explicit:</p>\n<pre class=\"language-json\" tabindex=\"0\"><code class=\"language-json\"><span class=\"token punctuation\">{</span>\n  <span class=\"token property\">\"citations:fair\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"node scripts/add-entry-citations.mjs\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"citations:fair:check\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"node scripts/add-entry-citations.mjs --dry-run\"</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>The dry run is especially important on Outcome because the script can touch a lot of files. In the first check it found 171 entries with citation-like inputs that could be normalized into <code>citations</code>.</p>\n<p>The dry-run command reports what it would update:</p>\n<pre class=\"language-sh\" tabindex=\"0\"><code class=\"language-sh\"><span class=\"token function\">npm</span> run citations:fair:check</code></pre>\n<p>And the write command is explicit:</p>\n<pre class=\"language-sh\" tabindex=\"0\"><code class=\"language-sh\"><span class=\"token function\">npm</span> run citations:fair</code></pre>\n<p>That separation is important. Metadata scripts should be inspectable before they rewrite editorial files.</p>\n<h2 id=\"build-verification\" tabindex=\"-1\">Build Verification <a class=\"header-anchor\" href=\"#build-verification\">#</a></h2>\n<p>For <code>adamdjbrett.com</code>, I verified:</p>\n<pre class=\"language-sh\" tabindex=\"0\"><code class=\"language-sh\"><span class=\"token function\">npm</span> run build:fast</code></pre>\n<p>Then checked that representative files existed and parsed:</p>\n<pre class=\"language-sh\" tabindex=\"0\"><code class=\"language-sh\"><span class=\"token function\">node</span> <span class=\"token parameter variable\">-e</span> <span class=\"token string\">\"const fs=require('fs'); for (const f of ['_site/blog/zotero-harvestable-blog-posts/metadata.json','_site/blog/2026-06-29-on-being-in-the-middle/metadata.json']) { const d=JSON.parse(fs.readFileSync(f,'utf8')); console.log(f, d['@type'], d.name, d.isPartOf &amp;&amp; d.isPartOf['@id']); }\"</span></code></pre>\n<p>Expected output shape:</p>\n<pre class=\"language-text\" tabindex=\"0\"><code class=\"language-text\">_site/blog/zotero-harvestable-blog-posts/metadata.json BlogPosting Making Blogs Easier to Cite with Zotero https://www.adamdjbrett.com/blog/\n_site/blog/2026-06-29-on-being-in-the-middle/metadata.json BlogPosting Book Review: *On Being in the Middle* by W.J. de Kock https://www.adamdjbrett.com/blog/</code></pre>\n<p>For <code>dominationchronicles.com</code>, I verified:</p>\n<pre class=\"language-sh\" tabindex=\"0\"><code class=\"language-sh\"><span class=\"token function\">npm</span> run build</code></pre>\n<p>Then checked:</p>\n<pre class=\"language-sh\" tabindex=\"0\"><code class=\"language-sh\"><span class=\"token function\">node</span> <span class=\"token parameter variable\">-e</span> <span class=\"token string\">\"const fs=require('fs'); for (const f of ['_site/episodes/e008-words-meanings/metadata.json','_site/episodes/e017-bruce-mcivor-legalized-lawlessness/metadata.json']) { const d=JSON.parse(fs.readFileSync(f,'utf8')); console.log(f, d['@type'], d.url, d.partOfSeries &amp;&amp; d.partOfSeries['@id']); }\"</span></code></pre>\n<p>Expected output shape:</p>\n<pre class=\"language-text\" tabindex=\"0\"><code class=\"language-text\">_site/episodes/e008-words-meanings/metadata.json PodcastEpisode https://dominationchronicles.com/episodes/e008-words-meanings/ https://dominationchronicles.com/#podcast\n_site/episodes/e017-bruce-mcivor-legalized-lawlessness/metadata.json PodcastEpisode https://dominationchronicles.com/episodes/e017-bruce-mcivor-legalized-lawlessness/ https://dominationchronicles.com/#podcast</code></pre>\n<p>For Outcome, I verified:</p>\n<pre class=\"language-sh\" tabindex=\"0\"><code class=\"language-sh\"><span class=\"token function\">npm</span> run build-prod-fastest</code></pre>\n<p>Then checked one scholarly article, one blog-style entry, and one older podcast entry:</p>\n<pre class=\"language-sh\" tabindex=\"0\"><code class=\"language-sh\"><span class=\"token function\">node</span> <span class=\"token parameter variable\">-e</span> <span class=\"token string\">\"const fs=require('fs'); for (const p of ['_site/jcrt/issue2/conclusion/metadata.json','_site/featured/essay2/documenting/metadata.json','_site/podcast/essay1/s2e6/metadata.json']) { const j=JSON.parse(fs.readFileSync(p,'utf8')); console.log(p, j['@type'], j.url, Boolean(j.author), Boolean(j.citation), j.partOfSeries &amp;&amp; j.partOfSeries['@id'], j.isPartOf &amp;&amp; j.isPartOf['@id']); }\"</span></code></pre>\n<p>The output confirmed the mixed-type model:</p>\n<pre class=\"language-text\" tabindex=\"0\"><code class=\"language-text\">_site/jcrt/issue2/conclusion/metadata.json ScholarlyArticle https://jcrt.org/archives/25.1/conclusion/ true true undefined undefined\n_site/featured/essay2/documenting/metadata.json BlogPosting https://www.mdpi.com/2077-1444/15/12/1493 true true undefined undefined\n_site/podcast/essay1/s2e6/metadata.json PodcastEpisode https://podcast.doctrineofdiscovery.org/season2/episode-06/ true true https://outcome.doctrineofdiscovery.org/podcast/ undefined</code></pre>\n<p>I also checked the rendered HTML for signposting links and the generated <code>_headers</code> files.</p>\n<p>For the broader 11ty pass, I ran the normal build command in each local repo:</p>\n<pre class=\"language-sh\" tabindex=\"0\"><code class=\"language-sh\"><span class=\"token builtin class-name\">cd</span> /Users/abrett76/github/ebenezer <span class=\"token operator\">&amp;&amp;</span> <span class=\"token function\">npm</span> run build\n<span class=\"token builtin class-name\">cd</span> /Users/abrett76/github/davidbrett.im <span class=\"token operator\">&amp;&amp;</span> <span class=\"token function\">npm</span> run build\n<span class=\"token builtin class-name\">cd</span> /Users/abrett76/github/stevennewcomb <span class=\"token operator\">&amp;&amp;</span> <span class=\"token function\">npm</span> run build\n<span class=\"token builtin class-name\">cd</span> /Users/abrett76/github/indigenouslawinstitute.com <span class=\"token operator\">&amp;&amp;</span> <span class=\"token function\">npm</span> run build\n<span class=\"token builtin class-name\">cd</span> /Users/abrett76/github/alfieaward.com <span class=\"token operator\">&amp;&amp;</span> <span class=\"token function\">npm</span> run build</code></pre>\n<p>Then I parsed every generated <code>metadata.json</code> file from those five sites:</p>\n<pre class=\"language-sh\" tabindex=\"0\"><code class=\"language-sh\"><span class=\"token function\">node</span> <span class=\"token parameter variable\">-e</span> <span class=\"token string\">\"const fs=require('fs'), cp=require('child_process'); const files=cp.execSync('find ebenezer/_site davidbrett.im/_site stevennewcomb/_site indigenouslawinstitute.com/_site alfieaward.com/_site -path <span class=\"token entity\" title=\"\\\\\">\\\\</span>'*/metadata.json<span class=\"token entity\" title=\"\\\\\">\\\\</span>'', {encoding:'utf8'}).trim().split(/<span class=\"token entity\" title=\"\\\\\">\\\\</span>n/).filter(Boolean); for (const f of files) JSON.parse(fs.readFileSync(f,'utf8')); console.log('Parsed '+files.length+' Eleventy metadata.json files');\"</span></code></pre>\n<p>That produced:</p>\n<pre class=\"language-text\" tabindex=\"0\"><code class=\"language-text\">Parsed 149 Eleventy metadata.json files</code></pre>\n<p>I also checked representative rendered HTML for <code>rel=&quot;describedby&quot;</code>, <code>rel=&quot;type&quot;</code>, and <code>citation_title</code>. One useful catch came from <code>stevennewcomb.com</code>: the metadata files were generated, but the first head condition missed the rendered posts because the site used <code>post.njk</code> instead of <code>post</code>. That is why rendered HTML checks matter. File generation alone is not enough. The human-facing page has to advertise the machine-facing file.</p>\n<p>For the Jekyll sites, I verified the generator plugins with Ruby syntax checks:</p>\n<pre class=\"language-sh\" tabindex=\"0\"><code class=\"language-sh\"><span class=\"token keyword\">for</span> <span class=\"token for-or-select variable\">f</span> <span class=\"token keyword\">in</span> <span class=\"token punctuation\">\\</span>\n  thenandnow-new/_plugins/fair_metadata_json.rb <span class=\"token punctuation\">\\</span>\n  derryveagh-new/_plugins/fair_metadata_json.rb <span class=\"token punctuation\">\\</span>\n  stakedplains-new/_plugins/fair_metadata_json.rb <span class=\"token punctuation\">\\</span>\n  quotidian/_plugins/fair_metadata_json.rb <span class=\"token punctuation\">\\</span>\n  nabpr/_plugins/fair_metadata_json.rb <span class=\"token punctuation\">\\</span>\n  nabpr-pbi2/_plugins/fair_metadata_json.rb <span class=\"token punctuation\">\\</span>\n  wocati-new/_plugins/fair_metadata_json.rb\n<span class=\"token keyword\">do</span>\n  ruby <span class=\"token parameter variable\">-c</span> <span class=\"token string\">\"<span class=\"token variable\">$f</span>\"</span>\n<span class=\"token keyword\">done</span></code></pre>\n<p>All seven returned <code>Syntax OK</code>. Full Jekyll builds were blocked in my local environment by dependency state rather than by the plugin syntax. The errors included missing Bundler <code>4.0.11</code>, missing local <code>jekyll</code> gems, and rake activation conflicts. That is the kind of infrastructure detail I want to preserve in the implementation notes because it tells the truth about old static-site repos: sometimes the metadata work is straightforward and the build environment is the hard part.</p>\n<h2 id=\"why-this-matters\" tabindex=\"-1\">Why This Matters <a class=\"header-anchor\" href=\"#why-this-matters\">#</a></h2>\n<p>This work is not about SEO in the narrow sense. It might help search engines, but that is not the main point.</p>\n<p>The real point is scholarly portability.</p>\n<p>A blog post about Zotero metadata should itself be easy to cite. A podcast episode with a transcript and a resource list should be discoverable as a podcast episode, not just another web page. A book review, article announcement, or episode resource list should have enough structured metadata that a researcher or archive can understand what it is.</p>\n<p>Static sites do not get this automatically. That is the tradeoff. They are durable and transparent, but the metadata affordances have to be built deliberately.</p>\n<p>The pattern I want to keep using is:</p>\n<ol>\n<li>write human-facing pages in Markdown;</li>\n<li>keep stable site metadata in Eleventy data files;</li>\n<li>generate page-adjacent <code>metadata.json</code>;</li>\n<li>advertise that metadata from HTML and headers where possible;</li>\n<li>keep citation data in front matter as structured JSON-LD-ready objects;</li>\n<li>verify the generated files as part of the build workflow.</li>\n</ol>\n<p>That is not a large system. It is a modest layer of structured metadata. But it makes independent scholarly publishing more legible to the rest of the web.</p>\n<p>And that is the part I care about most: if we want small sites, independent publications, podcasts, and personal scholarly blogs to last, we have to make them easier to cite, easier to harvest, and easier to preserve.</p>\n",
			"date_published": "2026-07-05T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2026-07-05-build-awesome-cloudflare-optimization/",
			"url": "https://www.adamdjbrett.com/blog/2026-07-05-build-awesome-cloudflare-optimization/",
			"title": "How Build Awesome alpha, async Nunjucks, and smaller Cloudflare checks fixed my podcast build",
			"content_html": "<p>I spent part of this week cleaning up the build and deploy pipeline for the <a href=\"https://podcast.doctrineofdiscovery.org/\">Mapping the Doctrine of Discovery Podcast</a>. It started as a simple GitHub Actions failure and turned into a useful reminder: the fastest static site is not just the one with the fastest generator. It is the one with the fewest unnecessary moving parts.</p>\n<p>The site was already static, already running on Cloudflare Workers, and already in decent shape. But the deployment workflow had accumulated enough checks, helper installs, metadata files, and generated headers that the system was starting to work harder than it needed to. The main problem was not one dramatic bug. It was several small sources of friction stacked together:</p>\n<ul>\n<li>Eleventy was still pinned directly as <code>@11ty/eleventy</code>.</li>\n<li>The site generated too many Cloudflare <code>_headers</code> rules.</li>\n<li>The deployment workflow installed PDF tools on every deploy.</li>\n<li>The deploy script ran the full <code>npm test</code>, including checks that did not need to block every publish.</li>\n<li>GitHub Actions upgraded npm on every run even though the bundled runner version was good enough.</li>\n</ul>\n<p>The result was a successful but heavier-than-necessary pipeline. After the cleanup, the deploy path is smaller, the package graph is leaner, the <code>_headers</code> file is dramatically simpler, and the Cloudflare deployment runs in about half the time it did before.</p>\n<h2 id=\"moving-from-eleventy-to-build-awesome-alpha\" tabindex=\"-1\">Moving from Eleventy to Build Awesome alpha <a class=\"header-anchor\" href=\"#moving-from-eleventy-to-build-awesome-alpha\">#</a></h2>\n<p>The first major change was moving the site from a direct Eleventy dependency to <a href=\"https://www.11ty.dev/\">Build Awesome</a>, the new package identity for Eleventy. The install command is straightforward:</p>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\"><span class=\"token function\">npm</span> <span class=\"token function\">install</span> @awesome.me/buildawesome --save-dev</code></pre>\n<p>In this repository I pinned the alpha exactly:</p>\n<pre class=\"language-json\" tabindex=\"0\"><code class=\"language-json\"><span class=\"token property\">\"@awesome.me/buildawesome\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"4.0.0-alpha.10\"</span></code></pre>\n<p>and changed the build command from:</p>\n<pre class=\"language-json\" tabindex=\"0\"><code class=\"language-json\"><span class=\"token property\">\"build\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"npm run clean &amp;&amp; eleventy &amp;&amp; npm run generate:postbuild\"</span></code></pre>\n<p>to:</p>\n<pre class=\"language-json\" tabindex=\"0\"><code class=\"language-json\"><span class=\"token property\">\"build\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"npm run clean &amp;&amp; buildawesome &amp;&amp; npm run generate:postbuild\"</span></code></pre>\n<p>That did two things. First, it put the site on the current Build Awesome alpha line. Second, it let me remove the direct <code>@11ty/eleventy</code> dependency from my own <code>package.json</code>. Build Awesome brings its matching Eleventy alpha internally, so my top-level dependency list no longer had to carry both the old direct generator dependency and the new package.</p>\n<p>That made <code>package.json</code> easier to understand. The build tool now reads like the tool I am actually using:</p>\n<pre class=\"language-json\" tabindex=\"0\"><code class=\"language-json\"><span class=\"token property\">\"dependencies\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token property\">\"@11ty/nunjucks\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"4.0.0-alpha.3\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"@awesome.me/buildawesome\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"4.0.0-alpha.10\"</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>The upgrade commit changed the lockfile substantially too: <code>591 insertions</code> and <code>937 deletions</code>. That is not a perfect measurement of complexity, but it is a useful sign that the dependency graph changed meaningfully. After removing the old direct Eleventy dependency, <code>npm uninstall @11ty/eleventy</code> removed 49 packages from the local install.</p>\n<p>The migration did surface one real assumption in my own code. A global data helper still tried to read:</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\">packageJson<span class=\"token punctuation\">.</span>devDependencies<span class=\"token punctuation\">[</span><span class=\"token string\">\"@11ty/eleventy\"</span><span class=\"token punctuation\">]</span></code></pre>\n<p>That worked only while <code>@11ty/eleventy</code> was a direct dependency. Once Build Awesome became the build tool, that value was gone. The fix was simple: read the Build Awesome package version instead. This is the kind of small migration bug I actually like. It shows exactly where my code was coupled to the old package shape.</p>\n<h2 id=\"nunjucks-v4-full-async\" tabindex=\"-1\">Nunjucks v4 full async <a class=\"header-anchor\" href=\"#nunjucks-v4-full-async\">#</a></h2>\n<p>The second important change was using <a href=\"https://github.com/11ty/nunjucks/releases/tag/v4.0.0-alpha.3\"><code>@11ty/nunjucks@4.0.0-alpha.3</code></a>, the full-async Nunjucks alpha.</p>\n<p>This release matters because it moves Nunjucks internals much more fully into async/await territory. For this site, I used it most directly in the post-build <code>_headers</code> generator:</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> Environment <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">\"@11ty/nunjucks\"</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> env <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Environment</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">autoescape</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> headers <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> env<span class=\"token punctuation\">.</span><span class=\"token function\">renderString</span><span class=\"token punctuation\">(</span>template<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">siteUrl</span><span class=\"token operator\">:</span> <span class=\"token constant\">SITE_URL</span><span class=\"token punctuation\">,</span>\n  seasonCategories<span class=\"token punctuation\">,</span>\n  standaloneCategories<span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre>\n<p>That may look like a small thing, but it made the headers script feel like the rest of the modern build pipeline: async data in, rendered text out, no awkward sync/async boundary. It also let me write the Cloudflare header rules as a real template instead of manually pushing strings into an array.</p>\n<p>The larger lesson is not that every file needs Nunjucks. It is that a static site build becomes easier to reason about when the templating layer and the scripting layer both handle async work naturally. Podcast sites are full of derived artifacts: feeds, metadata, citations, headers, redirects, and search indexes. The fewer special cases in the build model, the better.</p>\n<h2 id=\"the-cloudflare-headers-problem\" tabindex=\"-1\">The Cloudflare <code>_headers</code> problem <a class=\"header-anchor\" href=\"#the-cloudflare-headers-problem\">#</a></h2>\n<p>The actual build failure came from Cloudflare's <code>_headers</code> limit.</p>\n<p>The site emits FAIR-style metadata for each podcast episode. Each episode gets a nearby <code>metadata.json</code> file and HTTP <code>Link</code> headers that point to that structured metadata. That is good for machine readability, citation, and long-term discovery. The problem was how I represented those headers.</p>\n<p>The original generator created per-episode rules. With 54 podcast posts, that pushed <code>_site/_headers</code> to 111 rules. Cloudflare Workers allows at most 100. The check failed with:</p>\n<pre class=\"language-txt\" tabindex=\"0\"><code class=\"language-txt\">_site/_headers has 111 rules; Cloudflare Workers allows at most 100</code></pre>\n<p>The first fix collapsed the per-episode rules into wildcard rules by content group. That brought the file down to 9 rules. Then I pushed it further by recognizing that all season paths shared the same structure. Instead of separate rules for <code>season1</code>, <code>season2</code>, <code>season3</code>, and so on, Cloudflare placeholders could express the whole family:</p>\n<pre class=\"language-txt\" tabindex=\"0\"><code class=\"language-txt\">/season:season/*\n  Link: &lt;https://podcast.doctrineofdiscovery.org/season:season/:splatmetadata.json>; rel=\"describedby\"; type=\"application/ld+json\"; profile=\"https://schema.org/\"\n  Link: &lt;https://podcast.doctrineofdiscovery.org/season:season/:splat>; rel=\"cite-as\"\n  Link: &lt;https://schema.org/PodcastEpisode>; rel=\"type\"</code></pre>\n<p>The final <code>_headers</code> file has only four rules:</p>\n<pre class=\"language-txt\" tabindex=\"0\"><code class=\"language-txt\">/*.xml\n/*/metadata.json\n/season:season/*\n/special/*</code></pre>\n<p>That is the kind of optimization I like. It did not remove metadata. It removed repetition. The site still advertises machine-readable episode metadata, canonical feed URLs, JSON content types, and podcast episode type links. It just does so with patterns instead of one rule per page.</p>\n<p>I also tightened the local check so this does not regress. The header test now enforces 5 rules or fewer, not Cloudflare's looser limit of 100. If I accidentally go back to per-page header rules, the build will complain immediately.</p>\n<h2 id=\"splitting-deploy-checks-from-archival-checks\" tabindex=\"-1\">Splitting deploy checks from archival checks <a class=\"header-anchor\" href=\"#splitting-deploy-checks-from-archival-checks\">#</a></h2>\n<p>The next set of improvements came from reading the GitHub Actions logs.</p>\n<p>The old run showed this shape:</p>\n<table>\n<thead>\n<tr>\n<th>Step</th>\n<th style=\"text-align:right\">Approximate time</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Setup Node.js</td>\n<td style=\"text-align:right\">5.2s</td>\n</tr>\n<tr>\n<td>Update npm</td>\n<td style=\"text-align:right\">3.3s</td>\n</tr>\n<tr>\n<td>Install dependencies</td>\n<td style=\"text-align:right\">3.5s</td>\n</tr>\n<tr>\n<td>Install PDF verification tools</td>\n<td style=\"text-align:right\">13.4s</td>\n</tr>\n<tr>\n<td>Build and check site with <code>npm test</code></td>\n<td style=\"text-align:right\">6.8s</td>\n</tr>\n<tr>\n<td>Deploy to Cloudflare Workers</td>\n<td style=\"text-align:right\">9.1s</td>\n</tr>\n</tbody>\n</table>\n<p>The biggest waste was obvious: installing PDF tools during every deploy. The <code>check:pdfs</code> script uses <code>pdfinfo</code> and <code>qpdf</code> to verify PDF metadata, rights text, and outline/bookmark data. Those checks are valuable. They are also not necessary for every Cloudflare deployment.</p>\n<p>So I split the test paths.</p>\n<p>The full test remains:</p>\n<pre class=\"language-json\" tabindex=\"0\"><code class=\"language-json\"><span class=\"token property\">\"test\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"npm run build &amp;&amp; npm run check:esm &amp;&amp; npm run check:build &amp;&amp; npm run check:headers &amp;&amp; npm run check:feeds &amp;&amp; npm run check:assets &amp;&amp; npm run check:links &amp;&amp; npm run check:redirects &amp;&amp; npm run check:metadata &amp;&amp; npm run check:citations &amp;&amp; npm run check:pdfs\"</span></code></pre>\n<p>The deploy test skips PDF verification:</p>\n<pre class=\"language-json\" tabindex=\"0\"><code class=\"language-json\"><span class=\"token property\">\"test:deploy\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"npm run build &amp;&amp; npm run check:esm &amp;&amp; npm run check:build &amp;&amp; npm run check:headers &amp;&amp; npm run check:feeds &amp;&amp; npm run check:assets &amp;&amp; npm run check:links &amp;&amp; npm run check:redirects &amp;&amp; npm run check:metadata &amp;&amp; npm run check:citations\"</span></code></pre>\n<p>Then the Cloudflare workflow changed from <code>npm test</code> to:</p>\n<pre class=\"language-yaml\" tabindex=\"0\"><code class=\"language-yaml\"><span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Build and check Build Awesome site\n  <span class=\"token key atrule\">run</span><span class=\"token punctuation\">:</span> npm run test<span class=\"token punctuation\">:</span>deploy</code></pre>\n<p>That let me delete the entire apt install step from deploy:</p>\n<pre class=\"language-yaml\" tabindex=\"0\"><code class=\"language-yaml\">sudo apt<span class=\"token punctuation\">-</span>get update <span class=\"token important\">&amp;&amp;</span> sudo apt<span class=\"token punctuation\">-</span>get install <span class=\"token punctuation\">-</span>y ghostscript poppler<span class=\"token punctuation\">-</span>utils qpdf</code></pre>\n<p>It also let me remove a redundant shell check that counted files in <code>_site</code>, because <code>npm run check:build</code> already validates the expected output files and checks that the build is not suspiciously small.</p>\n<p>But I did not delete PDF validation. I moved it into its own workflow:</p>\n<pre class=\"language-yaml\" tabindex=\"0\"><code class=\"language-yaml\"><span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Check PDF Metadata</code></pre>\n<p>That workflow runs manually and when PDF-related paths change. It installs only what the script actually uses:</p>\n<pre class=\"language-yaml\" tabindex=\"0\"><code class=\"language-yaml\">sudo apt<span class=\"token punctuation\">-</span>get update <span class=\"token important\">&amp;&amp;</span> sudo apt<span class=\"token punctuation\">-</span>get install <span class=\"token punctuation\">-</span>y poppler<span class=\"token punctuation\">-</span>utils qpdf</code></pre>\n<p>No Ghostscript. No deploy blocking. No loss of metadata discipline.</p>\n<h2 id=\"relaxing-npm-without-giving-up-node-discipline\" tabindex=\"-1\">Relaxing npm without giving up Node discipline <a class=\"header-anchor\" href=\"#relaxing-npm-without-giving-up-node-discipline\">#</a></h2>\n<p>The final small speed win came from npm.</p>\n<p>The workflow was installing npm <code>11.18.0</code> globally on every run because <code>package.json</code> required:</p>\n<pre class=\"language-json\" tabindex=\"0\"><code class=\"language-json\"><span class=\"token property\">\"npm\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\">=11.18.0\"</span></code></pre>\n<p>But the GitHub runner already had npm <code>11.9.0</code> with Node <code>24.14.0</code>, and the project builds cleanly with that. Updating npm cost about 3.3 seconds in the old log and about 2 seconds in the later optimized run.</p>\n<p>So I relaxed the npm engine:</p>\n<pre class=\"language-json\" tabindex=\"0\"><code class=\"language-json\"><span class=\"token property\">\"engines\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token property\">\"node\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\">=24.14.0\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"npm\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\">=11.9.0\"</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>and set:</p>\n<pre class=\"language-json\" tabindex=\"0\"><code class=\"language-json\"><span class=\"token property\">\"packageManager\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"npm@11.9.0\"</span></code></pre>\n<p>Then I removed the workflow step that upgraded npm. Node stays pinned. The build still uses a modern npm. The deployment no longer pays a repeated tax for a version difference that was not buying me anything.</p>\n<h2 id=\"the-timing-change\" tabindex=\"-1\">The timing change <a class=\"header-anchor\" href=\"#the-timing-change\">#</a></h2>\n<p>The deploy timeline now looks much better.</p>\n<p>Before these changes, the Cloudflare deploy run was about 59 seconds. After removing PDF tooling from deploy and using <code>test:deploy</code>, it dropped to about 33 seconds. After relaxing npm and removing the npm upgrade step, it landed around 31 seconds.</p>\n<p>In practical terms:</p>\n<table>\n<thead>\n<tr>\n<th>Version</th>\n<th style=\"text-align:right\">Time</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Before PDF/workflow cleanup</td>\n<td style=\"text-align:right\">~59s</td>\n</tr>\n<tr>\n<td>After deploy-only test path</td>\n<td style=\"text-align:right\">~33s</td>\n</tr>\n<tr>\n<td>After npm engine relaxation</td>\n<td style=\"text-align:right\">~31s</td>\n</tr>\n</tbody>\n</table>\n<p>That is not just a percentage improvement. It changes how the workflow feels. A half-minute deploy is short enough that I can push a content or metadata fix and stay in context while it runs.</p>\n<p>Local build/check time is also comfortably small. The deploy test runs in about 4 seconds on my machine:</p>\n<pre class=\"language-txt\" tabindex=\"0\"><code class=\"language-txt\">npm run test:deploy</code></pre>\n<p>The Build Awesome part itself wrote 215 files and copied 265 files in about 1.1 seconds locally during the most recent run. For a podcast site with feeds, metadata files, citations, redirects, asset checks, link checks, and Cloudflare headers, that is a good place to be.</p>\n<h2 id=\"what-this-solved\" tabindex=\"-1\">What this solved <a class=\"header-anchor\" href=\"#what-this-solved\">#</a></h2>\n<p>The biggest visible problem was the Cloudflare header limit, but the cleanup solved more than that.</p>\n<p>It reduced site complexity. <code>_headers</code> went from 111 rules to 4. That is not a cosmetic change. It means the metadata strategy now scales with the URL structure instead of the number of episodes.</p>\n<p>It reduced deploy complexity. The Cloudflare workflow no longer installs unrelated PDF tools or runs a full archival validation suite on every publish.</p>\n<p>It preserved quality checks. PDF metadata validation still exists, but it runs where it belongs: in a focused workflow that responds to PDF-related changes or manual review.</p>\n<p>It shrank the package surface. The site no longer carries direct <code>@11ty/eleventy</code> as its own top-level build dependency. Build Awesome is the build tool, and the package file says so.</p>\n<p>It clarified responsibility. <code>npm test</code> is the full quality gate. <code>npm run test:deploy</code> is the deploy gate. <code>check:pdfs</code> is archival/document quality. The workflow names now match their jobs.</p>\n<h2 id=\"the-broader-lesson\" tabindex=\"-1\">The broader lesson <a class=\"header-anchor\" href=\"#the-broader-lesson\">#</a></h2>\n<p>This is the kind of maintenance that rarely looks impressive from the outside. There is no redesign screenshot. No shiny homepage. No dramatic feature announcement.</p>\n<p>But it matters.</p>\n<p>Static sites get their power from being understandable. If the build process becomes a pile of inherited assumptions, the site slowly stops being minimal even if the output is static HTML. I do not want a &quot;simple&quot; site with a complicated deploy ritual. I want a publishing system where each check earns its place.</p>\n<p>Moving to Build Awesome alpha, using async Nunjucks, collapsing Cloudflare headers, and splitting PDF validation into its own workflow all moved the site in that direction. The site is still doing the important scholarly and archival work: structured metadata, citation files, podcast feeds, redirects, PDF metadata checks, and durable URLs. It is just doing less unnecessary work on the way to deployment.</p>\n<p>That is the real optimization: not making the computer race through a messy process, but making the process smaller, clearer, and easier to trust.</p>\n",
			"date_published": "2026-07-05T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2026-06-30-png-pdf-ocr-digital-humanities/",
			"url": "https://www.adamdjbrett.com/blog/2026-06-30-png-pdf-ocr-digital-humanities/",
			"title": "PNG to PDF to OCR: A Small Command Line Skill for Digital Humanities Work",
			"content_html": "<p>One of the most useful digital humanities skills is not glamorous at all: knowing how to turn a folder of high quality page images into a searchable PDF. If you are scanning old documents, archival packets, newsletters, church records, syllabi, meeting minutes, or family papers, the fastest workflow is often to separate scanning from digitizing.</p>\n<p>I do not want to sit at a scanner and make decisions about every final PDF while the machine is running. I want the scanner to do what scanners do best: capture clean images at 300 DPI or higher. Then I can group, rename, combine, and OCR the files later from the command line.</p>\n<p>That small shift matters. Scanning becomes a capture process. Digitizing becomes an organization and text-recognition process. The result is less fiddling at the scanner, better preservation images, and a repeatable workflow for making documents searchable.</p>\n<h2 id=\"the-basic-workflow\" tabindex=\"-1\">The Basic Workflow <a class=\"header-anchor\" href=\"#the-basic-workflow\">#</a></h2>\n<p>On a Mac, use homebroew to install two command line tools:</p>\n<ol>\n<li><a href=\"https://gitlab.mister-muffin.de/josch/img2pdf\">img2pdf</a></li>\n<li><a href=\"https://ocrmypdf.readthedocs.io/en/latest/\">ocrmypdf</a></li>\n</ol>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\">brew <span class=\"token function\">install</span> img2pdf ocrmypdf</code></pre>\n<p>Put the PNG files for one document into a folder. Name them in page order:</p>\n<pre class=\"language-text\" tabindex=\"0\"><code class=\"language-text\">001.png\n002.png\n003.png\n004.png</code></pre>\n<p>The leading zeroes are important because the shell will pass the files to the command in sorted order. If you use names like <code>1.png</code>, <code>2.png</code>, and <code>10.png</code>, your pages may not land where you expect.</p>\n<p>Then combine the PNG files into a PDF:</p>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\">img2pdf *.png <span class=\"token parameter variable\">-o</span> combine.pdf</code></pre>\n<p>That gives you a PDF made from the page images. Next, run OCRmyPDF to add searchable text:</p>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\">ocrmypdf combine.pdf combine-ocr.pdf </code></pre>\n<p>The output, <code>combine-ocr.pdf</code>, is still visually based on the original scans, but now the PDF has a text layer. You can search it, select text, index it, quote from it, or add it to a research library.</p>\n<h2 id=\"why-scan-images-first\" tabindex=\"-1\">Why Scan Images First? <a class=\"header-anchor\" href=\"#why-scan-images-first\">#</a></h2>\n<p>Many scanner apps want you to decide everything during the scan: file name, PDF settings, OCR settings, page grouping, destination folder, and sometimes compression. That is fine for a one-off document. It is not ideal when you are working through a box of old papers.</p>\n<p>For digital humanities work, speed and repeatability matter. I would rather scan at 300 DPI or higher, save each page as a PNG, and keep moving. Later, when I am away from the scanner, I can sort the pages into folders, rename them, combine them into PDFs, and OCR them in batches.</p>\n<p>This also preserves better intermediate files. A folder of high-resolution page images is flexible. You can make a PDF from it. You can rerun OCR with different settings. You can crop, deskew, split, reorder, or replace pages. You can keep the images as preservation files and treat the OCR PDF as a derivative.</p>\n<p>That distinction is useful: the scan is the evidence; the OCR PDF is the access copy.</p>\n<h2 id=\"a-small-script\" tabindex=\"-1\">A Small Script <a class=\"header-anchor\" href=\"#a-small-script\">#</a></h2>\n<p>I keep a script called <code>png_to_pdf_to_ocr.sh</code> for this workflow. From inside a folder of PNGs, it combines the images and then runs OCR:</p>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\">./png_to_pdf_to_ocr.sh combined-ocr.pdf</code></pre>\n<p>The logic is simple:</p>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\">img2pdf *.png <span class=\"token parameter variable\">-o</span> combine.pdf\nocrmypdf combine.pdf combine-ocr.pdf --skip-text</code></pre>\n<p>The script just makes the process harder to mistype. It also gives me one command I can reuse when processing multiple documents.</p>\n<h2 id=\"batch-thinking\" tabindex=\"-1\">Batch Thinking <a class=\"header-anchor\" href=\"#batch-thinking\">#</a></h2>\n<p>The real payoff comes when you start thinking in folders:</p>\n<pre class=\"language-text\" tabindex=\"0\"><code class=\"language-text\">archive-box-01/\n  newsletter-1978-03/\n    001.png\n    002.png\n    003.png\n  minutes-1981-11-14/\n    001.png\n    002.png\n    003.png\n    004.png</code></pre>\n<p>Each folder becomes one document. Each folder can become one searchable PDF. That structure is readable by humans, easy to back up, and simple to revisit later.</p>\n<p>This is the kind of ordinary technical practice that supports better humanities work. Digitization is not only about expensive platforms or specialized repositories. It is also about small, durable habits: good scans, clear filenames, reusable commands, and files that remain understandable after the software changes.</p>\n<p>When I am working with old documents, I want the workflow to stay boring. Scan clean images. Group pages. Combine with <code>img2pdf</code>. Run <code>ocrmypdf</code>. Keep the source images. Save the searchable PDF. Repeat.</p>\n",
			"date_published": "2026-06-30T16:45:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2026-06-30-christian-past-review/",
			"url": "https://www.adamdjbrett.com/blog/2026-06-30-christian-past-review/",
			"title": "Review of Warren Throckmorton’s *The Christian Past That Wasn’t*",
			"content_html": "<h2 id=\"warren-throckmorton-the-christian-past-that-wasn-t-debunking-the-christian-nationalist-myths-that-hijack-history-broadleaf-books-2026-isbn-9798889835837\" tabindex=\"-1\">Warren Throckmorton, <em>The Christian Past That Wasn’t: Debunking the Christian Nationalist Myths That Hijack History</em>. Broadleaf Books, 2026. ISBN: 9798889835837 <a class=\"header-anchor\" href=\"#warren-throckmorton-the-christian-past-that-wasn-t-debunking-the-christian-nationalist-myths-that-hijack-history-broadleaf-books-2026-isbn-9798889835837\">#</a></h2>\n<p>This is a patient, careful, and timely book. It takes aim at a way of imagining the American past that has turned politically dangerous. Throckmorton is not attacking Christianity’s place in American history. He is not questioning the faith of early Americans. Many of them were religious, and he says so. His target is a stronger and more specific claim: that the United States was founded as a Christian nation, under a covenant with God, with founding documents drawn from the Bible and a public order meant to favor Christianity. His answer is blunt. That past is a myth. And the myth matters, because people use it to justify real political projects right now. Learn more about the book on the <a href=\"https://christianpast.com/\">Christian Past website</a>.</p>\n<h2 id=\"a-fact-checker-not-a-historian\" tabindex=\"-1\">A fact-checker, not a historian <a class=\"header-anchor\" href=\"#a-fact-checker-not-a-historian\">#</a></h2>\n<p>The book works because Throckmorton knows what kind of book it is. He is not writing a sweeping academic history of religion and the founding. He is writing a fact-checking brief against a set of claims that keep coming back. The preface explains how he got here. He came to this work from psychology, from blogging, and from public fights over figures like Bryan Fischer and David Barton. He did not take the usual historian’s path</p>\n<p>The chapters are built around stories you have probably heard and if not enough context is provided to get up to speed.Throckmorton invites wants ordinary readers to do one thing: check what the sources actually say. Fact check him, fact check the news, put in the work checking sources and reading primary documents for yourself. He is especially writing for Christians who first met these claims in church, in school, on a podcast, or in a campaign speech.</p>\n<p>The opening example shows the method in miniature. Christian nationalist retellings love the story of Benjamin Franklin’s 1787 motion for prayer at the Constitutional Convention. In the popular version, the founders knelt, prayed, and then produced a God-inspired Constitution. Throckmorton slows the scene down and lets the record speak. Franklin did propose prayer. Roger Sherman seconded it. The delegates debated. Hugh Williamson pointed out that the Convention had no money to pay a chaplain. Edmund Randolph offered a compromise. Then the Convention adjourned without ever voting on it. Franklin himself later wrote that, except for “three or four persons,” the Convention thought prayers were unnecessary (<a href=\"https://kristindumez.substack.com/p/the-christian-past-that-wasnt\">Du Mez's The Conversation</a>). The point is not that religion was missing. The point is that the myth has to turn a failed motion into a sacred founding moment.</p>\n<h2 id=\"the-seven-myths\" tabindex=\"-1\">The seven myths <a class=\"header-anchor\" href=\"#the-seven-myths\">#</a></h2>\n<p>The book moves through seven myths in order:</p>\n<ol>\n<li>America is a covenant homeland for European Protestants.</li>\n<li>Colonial church establishments prove America is a Christian nation.</li>\n<li>The founders were orthodox Christians.</li>\n<li>The founders built a Christian government.</li>\n<li>The Declaration and the Constitution are based on the Bible.</li>\n<li>America’s virtues cancel out its sins.</li>\n<li>Christianity should be promoted in public schools.</li>\n</ol>\n<p>Each chapter uses the same move. Throckmorton explores the the claim in details and then he explores Christian nationalist storytellers blow up (whatever kernels of truth there may be) into a false story about the whole nation.</p>\n<h2 id=\"the-limited-truth-strategy\" tabindex=\"-1\">The “limited truth” strategy <a class=\"header-anchor\" href=\"#the-limited-truth-strategy\">#</a></h2>\n<p>This “limited truth” method is the book’s strongest tool. Throckmorton does not pretend the past was secular. Many colonists were devout. Several colonies had established churches. Biblical language ran through public life. Protestant assumptions shaped early schooling. He concedes all of it.</p>\n<p>Then he shows that none of it proves the point Christian nationalists want it to prove. Colonial establishments were plural, local, and unstable. After independence, the country moved toward disestablishment, not toward a national church. The founders’ beliefs varied widely, and several of the most important ones look less like orthodox evangelicals and more like theistic rationalists. The Constitution contains no covenant with God. It bans religious tests for office. It protects religious liberty by refusing to establish any faith at all.</p>\n<p>So the reader is not asked to choose between a Christian founding and an atheist one. That is a false choice, and exposing it is half the work. The real founding was messier than either side’s slogan, and the mess is the truth.</p>\n<h2 id=\"the-moral-core-conquest-slavery-and-race\" tabindex=\"-1\">The moral core: conquest, slavery, and race <a class=\"header-anchor\" href=\"#the-moral-core-conquest-slavery-and-race\">#</a></h2>\n<p>The most important chapters are the ones that refuse to separate Christian-America mythology from conquest, slavery, and racial hierarchy.</p>\n<p>In the chapter on covenant, Throckmorton argues that the “chosen Protestant homeland” story erases Indigenous people and enslaved Africans. It has to. A homeland promised to one people is a homeland taken from another. He traces the line from European Christian claims of discovery and possession, through the doctrine of discovery, into the cleaned-up accounts of colonization that came later (Myth One).</p>\n<p>The chapter on virtues and sins presses the same wound. A national story that needs America to be uniquely Christian has only two options when it meets an atrocity. It can shrink the atrocity down to nothing. Or it can recast it as a regrettable exception inside a providential plan. Either way, the myth survives by editing the evidence. This is where Throckmorton meets recent scholarship most directly. Christian nationalism is not just a pile of historical mistakes. It is an ideology about belonging, threat, and power. The bad history is the tool, not the goal.</p>\n<h2 id=\"a-live-political-fight\" tabindex=\"-1\">A live political fight <a class=\"header-anchor\" href=\"#a-live-political-fight\">#</a></h2>\n<p>Throckmorton’s book is not about dusty arguments. It is about the present.</p>\n<p><a href=\"https://kristindumez.substack.com/p/the-christian-past-that-wasnt\">Kristin Kobes Du Mez</a> places the book in the long shadow of David Barton. She notes that Throckmorton and Michael Coulter’s criticism of Barton’s <a href=\"https://www.cbsnews.com/texas/news/publisher-cancels-bartons-the-jefferson-lies/\"><em>The Jefferson Lies</em></a> helped push Thomas Nelson to withdraw that book in 2012. CBS Texas reported the cancellation at the time. Du Mez also points to a current effort: using the country’s 250th anniversary to sell a “Christian America” story to a new generation.</p>\n<p><a href=\"https://baptistnews.com/article/author-debunks-americas-christian-past-that-wasnt/\">Baptist News Global’s interview</a> drives home the policy stakes. The same myths now feed religious liberty commissions, Ten Commandments laws in public schools, anti-Muslim politics, abortion bans, and the claim that church-state separation is a lie. So this is not antiquarian work. It is an intervention in a live fight over who gets to claim the power of the state.</p>\n<h2 id=\"why-the-myths-feel-true\" tabindex=\"-1\">Why the myths feel true <a class=\"header-anchor\" href=\"#why-the-myths-feel-true\">#</a></h2>\n<p>The book is also smart about emotion. Throckmorton knows a myth survives because people want it, not because it checks out.</p>\n<p>Chapter 2, “Hijacking History,” works through the Washington-at-Valley-Forge prayer scene and Parson Weems’s invented Washington stories. These are case studies in how a flattering fiction hardens into public memory. David Barton runs through the whole book as the modern heir to that tradition: a popularizer who hands his audience certainty, heroes, and political permission (“Hijacking History”).</p>\n<p>Here Throckmorton’s psychology training quietly does its work. He is not only asking whether a claim is false. He is asking why people need it to be true. In the conclusion he names the reasons. Group identity, fear, and the desire for power make these myths attractive. They are most attractive to white Christian Americans who want a usable story of national greatness (Conclusion).</p>\n<h2 id=\"where-the-book-falls-short\" tabindex=\"-1\">Where the book falls short <a class=\"header-anchor\" href=\"#where-the-book-falls-short\">#</a></h2>\n<p>The book’s weaknesses come straight out of its strengths.</p>\n<p>Because it is built to debunk, it says less about the real and sometimes good role of religion in American public life. The <a href=\"https://pres-outlook.org/2026/06/the-christian-past-that-wasnt/\"><em>Presbyterian Outlook</em></a> review makes this case well. The reviewer wishes Throckmorton had spent more time on Lincoln’s “almost chosen people,” and on the honest, democratic uses of biblical language in movements for justice. Religious speech built the abolitionist and civil rights movements too. A debunking book has little room to say so.</p>\n<p>If you want that fuller picture, read Throckmorton alongside other work. Philip Gorski’s <em>American Covenant</em> takes civil religion seriously. Michael Walzer’s <em>Exodus and Revolution</em> shows how biblical narrative fuels political liberation. Randall Balmer maps the rise of the religious right. The older Noll, Hatch, and Marsden volume <em>The Search for Christian America</em> covers much of the same ground from inside evangelical scholarship. These books help you separate Christian nationalism from other kinds of religious politics, including the kind that frees people rather than dominates them.</p>\n<p>The second weakness is tone. Naming today’s mythmakers is part of what makes the book useful. But it can narrow the view down to bad actors and bad claims. <em>Publishers Weekly</em>, quoted on the book site, praises the evidence but says the book sometimes slides into personal attacks on figures like Barton (cf. <a href=\"https://christianpast.com/\">Christian Past</a>). Do not overstate that complaint. Naming the people who spread these myths matters, because the myths travel through real institutions and media networks. Still, the strongest version of the argument is not that a few people are uniquely dishonest. It is that a whole audience, a whole set of institutions, and a whole structure of political incentives keeps rewarding distorted history. The individuals are symptoms.</p>\n<h2 id=\"the-conclusion\" tabindex=\"-1\">The conclusion <a class=\"header-anchor\" href=\"#the-conclusion\">#</a></h2>\n<p>The conclusion is the most theological part of the book.</p>\n<p>Throckmorton does not ends with the Golden Rule. If Christians do not want another religion to rule them through the state, they should not want their own religion to rule everyone else. He calls America an unfinished experiment. He calls church-state separation a practical achievement that protects both the government and the church.</p>\n<p>The counter-truths he leaves you with are sober and clear:</p>\n<ul>\n<li>America was formed through conquest and colonization.</li>\n<li>Colonial establishments do not define the national founding.</li>\n<li>The founders’ beliefs varied.</li>\n<li>The charter documents separate church and state.</li>\n<li>Those documents were not drawn from the Bible.</li>\n<li>Honest history has to include the atrocities done to marginalized people.</li>\n<li>Public schools may not put Christianity above other faiths.</li>\n</ul>\n<p>(Conclusion)</p>\n<h2 id=\"verdict\" tabindex=\"-1\">Verdict <a class=\"header-anchor\" href=\"#verdict\">#</a></h2>\n<p>That final posture is why <em>The Christian Past That Wasn’t</em> deserves a wide readership. It is not the last word on American religion or civil religion or Christian nationalism. It does not try to be. It is a well-documented handbook for answering one specific political and theological myth.</p>\n<p>Its best readers are pastors, teachers, students, journalists, and church members who need compact, sourced answers to claims that sound true only because they get repeated so often. Throckmorton’s central lesson is simple and bracing. The real past is rarely as neat as the myth needs it to be. And Christians who care about truth should not need a fake history to defend their faith.</p>\n<h2 id=\"sources\" tabindex=\"-1\">Sources <a class=\"header-anchor\" href=\"#sources\">#</a></h2>\n<ul>\n<li>Kristin Kobes Du Mez, “The Christian Past That Wasn’t,” Substack, <a href=\"https://kristindumez.substack.com/p/the-christian-past-that-wasnt\">https://kristindumez.substack.com/p/the-christian-past-that-wasnt</a>.</li>\n<li>Book website, <em>The Christian Past That Wasn’t</em>, <a href=\"https://christianpast.com/\">https://christianpast.com/</a></li>\n<li>Presbyterian Outlook, “The Christian Past That Wasn’t,” <a href=\"https://pres-outlook.org/2026/06/the-christian-past-that-wasnt/\">https://pres-outlook.org/2026/06/the-christian-past-that-wasnt/</a>.</li>\n<li>Baptist News Global, “Author debunks America’s ‘Christian past that wasn’t’,” <a href=\"https://baptistnews.com/article/author-debunks-americas-christian-past-that-wasnt/\">https://baptistnews.com/article/author-debunks-americas-christian-past-that-wasnt/</a></li>\n<li>CBS Texas, “Publisher Cancels Barton’s ‘The Jefferson Lies’,” <a href=\"https://www.cbsnews.com/texas/news/publisher-cancels-bartons-the-jefferson-lies/\">https://www.cbsnews.com/texas/news/publisher-cancels-bartons-the-jefferson-lies/</a></li>\n</ul>\n",
			"date_published": "2026-06-29T14:15:45Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/enabling-webmentions-in-11ty/",
			"url": "https://www.adamdjbrett.com/blog/enabling-webmentions-in-11ty/",
			"title": "Enabling Webmentions in Build Awesome (11ty)",
			"content_html": "<p>This post is all about learning and coding in public. We learn from each others mistakes and we get better by building together. Webmentions were, to borrow my own git commit message, &quot;a massive pain&quot; — so here is the honest version of how I finally got them working on this <a href=\"https://11ty.dev\">Eleventy (11ty)</a> site.</p>\n<hr>\n<h2 id=\"what-is-a-webmention\" tabindex=\"-1\">What is a webmention? <a class=\"header-anchor\" href=\"#what-is-a-webmention\">#</a></h2>\n<p>A <a href=\"https://indieweb.org/Webmention\">webmention</a> is a small, open <a href=\"https://www.w3.org/TR/webmention/\">W3C standard</a> for one site to tell another, &quot;hey, I mentioned you.&quot; When someone replies to, likes, or reposts my post on Bluesky, Mastodon, or their own blog, a webmention lets that interaction show up <em>under my post</em>, on my site, that I own. It is the <a href=\"https://indieweb.org/\">IndieWeb</a> answer to comments living inside someone else's silo.</p>\n<p>I had been trying to do this on my own off and on for a couple of months but thanks to impliment webentions to no avail so when I saw <a href=\"https://brennan.day/how-webmentions-work-on-brennan-day/\">Brennan's wonderful post, &quot;How webmentions work on brennan.day&quot;</a>, I got excited because I knew that I could finally accomplish adding webmentions thanks to Brennan's brilliance. From there I read everything I could find, and these were the most useful:</p>\n<ul>\n<li><a href=\"https://github.com/aaronpk/webmention.io\">aaronpk/webmention.io</a></li>\n<li><a href=\"https://webmention.app/docs\">webmention.app docs</a></li>\n<li><a href=\"https://mxb.dev/blog/using-webmentions-on-static-sites/\">Max Böck, &quot;Using Webmentions on Static Sites&quot;</a></li>\n<li><a href=\"https://deepakness.com/blog/adding-webmentions/\">Deepak, &quot;Adding Webmentions&quot;</a></li>\n<li><a href=\"https://sia.codes/posts/webmentions-eleventy-in-depth/\">Sia Karamalegos, &quot;Webmentions and Eleventy in Depth&quot;</a></li>\n</ul>\n<h2 id=\"the-flow-i-landed-on\" tabindex=\"-1\">The flow I landed on <a class=\"header-anchor\" href=\"#the-flow-i-landed-on\">#</a></h2>\n<p>After a lot of trial and error, here is the pipeline I settled on:</p>\n<ol>\n<li><strong><a href=\"https://brid.gy/\">Bridgy</a></strong> — bridges my social silos (Bluesky, Mastodon, GitHub, Tumblr) so their replies and likes become webmentions.</li>\n<li><strong><a href=\"https://webmention.io/\">webmention.io</a></strong> — the endpoint that <em>receives</em> and stores all the webmentions sent to me.</li>\n<li><strong><a href=\"https://www.netlify.com/\">Netlify</a></strong> — builds and deploys the static site where the all-important <code>&lt;link&gt;</code> tags live.</li>\n<li><strong>A GitHub Actions workflow</strong> — pulls the stored mentions into the repo on a schedule and sends my outbound mentions.</li>\n<li><strong>Next step</strong> — having Bridgy publish each new blog post out to my <a href=\"https://github.com/adamdjbrett\">github.com README</a>.</li>\n</ol>\n<p>Let me walk through each piece.</p>\n<h2 id=\"1-webmention-io-the-receiver\" tabindex=\"-1\">1. webmention.io — the receiver <a class=\"header-anchor\" href=\"#1-webmention-io-the-receiver\">#</a></h2>\n<p><a href=\"https://webmention.io/\">webmention.io</a> is the free, hosted endpoint by <a href=\"https://aaronpk.com/\">Aaron Parecki</a> that listens for incoming webmentions. You sign in with your domain using <a href=\"https://indieauth.com/\">IndieAuth</a>, and then you tell the world where to send mentions by dropping two <code>&lt;link&gt;</code> tags into the <code>&lt;head&gt;</code> of every page. On my site those live in my SEO include:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>pingback<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://webmention.io/www.adamdjbrett.com/xmlrpc<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>webmention<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://webmention.io/www.adamdjbrett.com/webmention<span class=\"token punctuation\">\"</span></span> <span class=\"token punctuation\">/></span></span></code></pre>\n<p>To sign in with IndieAuth I also added the endpoint links and a pile of <code>rel=&quot;me&quot;</code> links (GitHub, Bluesky, Mastodon, ORCID, and so on) so the services can confirm that those profiles are really me:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>authorization_endpoint<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://indieauth.com/auth<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>token_endpoint<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://tokens.indieauth.com/token<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>me<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://github.com/adamdjbrett<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>me<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://bsky.app/profile/adjb.co<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>me<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://social.lol/@adjb<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span></code></pre>\n<p>The <code>rel=&quot;me&quot;</code> links are the single most important and most fiddly part. The relationship has to be <strong>two-way</strong>: my site links to my GitHub, <em>and</em> my GitHub links back to my site. If either direction is missing, IndieAuth and Bridgy quietly refuse to work, and you are left staring at an empty webmentions section wondering what you did wrong. (I was.)</p>\n<h2 id=\"2-bridgy-bring-the-silos-home\" tabindex=\"-1\">2. Bridgy — bring the silos home <a class=\"header-anchor\" href=\"#2-bridgy-bring-the-silos-home\">#</a></h2>\n<p>webmention.io only hears about mentions from sites that already speak webmention. Bluesky, Mastodon, and the like do not — so <a href=\"https://brid.gy/\">Bridgy</a> acts as the translator. You connect each account once, and from then on Bridgy watches for replies, likes, and reposts and forwards them to my webmention.io endpoint as proper webmentions.</p>\n<p>I also want to <em>publish</em> in the other direction — to syndicate my posts out to those silos. That is what Bridgy's publish links do, again as <code>&lt;link&gt;</code> tags in the head:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>publisher<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://brid.gy/publish/bluesky<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>publisher<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://brid.gy/publish/github<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>link</span> <span class=\"token attr-name\">rel</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>publisher<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">href</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://brid.gy/publish/mastodon<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span></code></pre>\n<p>I did <strong>not</strong> enable Tumblr at this time — I am keeping the surface area small while I get the core flow solid, and I would rather add a silo deliberately than wire up one I am not actively posting to.</p>\n<h2 id=\"3-netlify-where-the-tags-live\" tabindex=\"-1\">3. Netlify — where the tags live <a class=\"header-anchor\" href=\"#3-netlify-where-the-tags-live\">#</a></h2>\n<p>There is no Netlify-specific magic here, and that is the point. <a href=\"https://www.netlify.com/\">Netlify</a> builds my Eleventy site and serves the static HTML — which means it serves those <code>rel=&quot;webmention&quot;</code>, <code>rel=&quot;me&quot;</code>, and <code>rel=&quot;publisher&quot;</code> link tags on every page. Bridgy and webmention.io both work by <em>reading my live, deployed pages</em>, so every webmention depends on Netlify having shipped the correct markup. Build it, deploy it, and the tags do their job.</p>\n<h3 id=\"the-www-vs-apex-loop-that-nearly-broke-me\" tabindex=\"-1\">The www vs. apex loop that nearly broke me <a class=\"header-anchor\" href=\"#the-www-vs-apex-loop-that-nearly-broke-me\">#</a></h3>\n<p>This is the mistake that cost me the most time, so it gets its own section. When I first set things up I tried to be thorough and registered <strong>both</strong> <code>adamdjbrett.com</code> and <code>www.adamdjbrett.com</code> with webmention.io and Bridgy. That was a trap.</p>\n<p>On Netlify my canonical host is <code>www.adamdjbrett.com</code>, and everything else 301-redirects to it:</p>\n<pre><code>http://adamdjbrett.com/*       https://www.adamdjbrett.com/:splat 301!\nhttp://www.adamdjbrett.com/*   https://www.adamdjbrett.com/:splat 301!\nhttps://adamdjbrett.com/*      https://www.adamdjbrett.com/:splat 301!\n</code></pre>\n<p>So when a webmention target pointed at the bare <code>adamdjbrett.com</code>, it would bounce through a redirect to the <code>www</code> version — while my data, my <code>rel</code> tags, and my page URLs all spoke <code>www</code>. The two hostnames never lined up. Mentions sent to one domain would not match posts living on the other, verification would chase a redirect, and I ended up with what my git log politely calls a &quot;loop.&quot; My workflow was even fetching from <code>WEBMENTION_DOMAIN: adamdjbrett.com</code> while the site served <code>www</code>, so the fetch came back empty and looked like nothing was wrong.</p>\n<p>The fix was to <strong>pick one canonical host and use it everywhere — <code>www.adamdjbrett.com</code>, because that is what Netlify serves.</strong> I changed the workflow and the scripts to default to the <code>www</code> domain:</p>\n<pre class=\"language-diff\" tabindex=\"0\"><code class=\"language-diff\"><span class=\"token deleted-sign deleted\"><span class=\"token prefix deleted\">-</span> WEBMENTION_DOMAIN: adamdjbrett.com\n</span><span class=\"token inserted-sign inserted\"><span class=\"token prefix inserted\">+</span> WEBMENTION_DOMAIN: www.adamdjbrett.com\n</span></code></pre>\n<pre class=\"language-diff\" tabindex=\"0\"><code class=\"language-diff\"><span class=\"token deleted-sign deleted\"><span class=\"token prefix deleted\">-</span> const domain = process.env.WEBMENTION_DOMAIN || \"adamdjbrett.com\";\n</span><span class=\"token inserted-sign inserted\"><span class=\"token prefix inserted\">+</span> const domain = process.env.WEBMENTION_DOMAIN || \"www.adamdjbrett.com\";\n</span></code></pre>\n<p>I also taught my URL normalizer to reject malformed and bare-<code>www</code> targets so a stray hostname could not sneak back in and re-create the mismatch:</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">hasValidUrlHost</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">hostname</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> host <span class=\"token operator\">=</span> hostname<span class=\"token punctuation\">.</span><span class=\"token function\">toLowerCase</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">const</span> isIpAddress <span class=\"token operator\">=</span> <span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">^[0-9.]+$</span><span class=\"token regex-delimiter\">/</span></span><span class=\"token punctuation\">.</span><span class=\"token function\">test</span><span class=\"token punctuation\">(</span>host<span class=\"token punctuation\">)</span> <span class=\"token operator\">||</span> host<span class=\"token punctuation\">.</span><span class=\"token function\">includes</span><span class=\"token punctuation\">(</span><span class=\"token string\">\":\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">return</span> <span class=\"token function\">Boolean</span><span class=\"token punctuation\">(</span>host<span class=\"token punctuation\">)</span> <span class=\"token operator\">&amp;&amp;</span> host <span class=\"token operator\">!==</span> <span class=\"token string\">\"www\"</span> <span class=\"token operator\">&amp;&amp;</span> <span class=\"token punctuation\">(</span>host<span class=\"token punctuation\">.</span><span class=\"token function\">includes</span><span class=\"token punctuation\">(</span><span class=\"token string\">\".\"</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">||</span> host <span class=\"token operator\">===</span> <span class=\"token string\">\"localhost\"</span> <span class=\"token operator\">||</span> isIpAddress<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre>\n<p>The lesson: <strong>decide on a single canonical domain before you touch webmentions, and make webmention.io, Bridgy, your <code>rel</code> tags, and your workflow all agree on it.</strong> Trying to support both the apex and <code>www</code> does not make you more robust — it just gives the redirect a chance to eat your mentions.</p>\n<h2 id=\"4-the-github-action-fetching-and-sending\" tabindex=\"-1\">4. The GitHub Action — fetching and sending <a class=\"header-anchor\" href=\"#4-the-github-action-fetching-and-sending\">#</a></h2>\n<p>This is the part that took the most work. webmention.io stores my mentions, but I want them committed into the repo as data so Eleventy can render them at build time (no client-side JavaScript, no extra requests for my readers). So I wrote a small Node script, <code>scripts/fetch-webmentions.mjs</code>, that hits the webmention.io API and writes the results to <code>_data/webmentions.json</code>:</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\"><span class=\"token keyword\">const</span> endpoint <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">URL</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"https://webmention.io/api/mentions.jf2\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nendpoint<span class=\"token punctuation\">.</span>searchParams<span class=\"token punctuation\">.</span><span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"domain\"</span><span class=\"token punctuation\">,</span> domain<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nendpoint<span class=\"token punctuation\">.</span>searchParams<span class=\"token punctuation\">.</span><span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"token\"</span><span class=\"token punctuation\">,</span> token<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\nendpoint<span class=\"token punctuation\">.</span>searchParams<span class=\"token punctuation\">.</span><span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"per-page\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"100\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre>\n<p>A scheduled <a href=\"https://docs.github.com/en/actions\">GitHub Actions</a> workflow runs this on a cron, then commits the JSON back to the repo if anything changed:</p>\n<pre class=\"language-yaml\" tabindex=\"0\"><code class=\"language-yaml\"><span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Refresh feeds<span class=\"token punctuation\">,</span> status<span class=\"token punctuation\">,</span> and webmentions\n  <span class=\"token key atrule\">env</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">WEBMENTION_IO_TOKEN</span><span class=\"token punctuation\">:</span> $\n    <span class=\"token key atrule\">WEBMENTION_DOMAIN</span><span class=\"token punctuation\">:</span> www.adamdjbrett.com\n  <span class=\"token key atrule\">run</span><span class=\"token punctuation\">:</span> npm run update<span class=\"token punctuation\">:</span>webmentions\n\n<span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Send outbound webmentions\n  <span class=\"token key atrule\">continue-on-error</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n  <span class=\"token key atrule\">run</span><span class=\"token punctuation\">:</span> npm run send<span class=\"token punctuation\">:</span>webmentions</code></pre>\n<p>That second step, <code>scripts/send-webmentions.mjs</code>, walks my posts, finds the outbound links, and sends a webmention to any site that advertises an endpoint — so I am a good neighbor and notify the people <em>I</em> link to, not just collect the mentions sent to me.</p>\n<p>I learned the hard way to verify the setup instead of trusting it. I added a <code>check:webmention</code> script that fails the build if any of the link tags go missing — the <code>rel=&quot;webmention&quot;</code> endpoint, the <code>rel=&quot;me&quot;</code> links, the Bridgy publish links. The token also matters: an early run failed silently because I had the wrong secret name, which is exactly the kind of mistake a check script catches. If you only learn one thing from my pain, let it be this: <strong>write a verifier.</strong></p>\n<h2 id=\"5-rendering-them-in-eleventy\" tabindex=\"-1\">5. Rendering them in Eleventy <a class=\"header-anchor\" href=\"#5-rendering-them-in-eleventy\">#</a></h2>\n<p>With the data in <code>_data/webmentions.json</code>, two small Eleventy filters do the work of matching mentions to the right post and grouping them by type:</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\">eleventyConfig<span class=\"token punctuation\">.</span><span class=\"token function\">addFilter</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"webmentionsForUrl\"</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">...</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>   <span class=\"token comment\">// mentions of this page</span>\neleventyConfig<span class=\"token punctuation\">.</span><span class=\"token function\">addFilter</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"webmentionsByTypes\"</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">...</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>  <span class=\"token comment\">// replies vs likes/reposts</span></code></pre>\n<p>Then a Nunjucks include, <code>webmentions.njk</code>, renders replies and mentions as a list and likes, reposts, and bookmarks as a row of avatars beneath each post:</p>\n<pre class=\"language-njk\" tabindex=\"0\"><code class=\"language-njk\">\n\n\n</code></pre>\n<p>Because all of this happens at build time, my readers download plain HTML. No tracking, no third-party scripts, no slow comment widget.</p>\n<h2 id=\"what-broke-so-you-do-not-have-to-repeat-it\" tabindex=\"-1\">What broke (so you do not have to repeat it) <a class=\"header-anchor\" href=\"#what-broke-so-you-do-not-have-to-repeat-it\">#</a></h2>\n<ul>\n<li><strong>Registering both <code>adamdjbrett.com</code> and <code>www.</code></strong> Pick one canonical host (mine is <code>www</code>, because that is what Netlify serves) and make everything agree. Supporting both just lets the redirect swallow your mentions — see the section above.</li>\n<li><strong>One-way <code>rel=&quot;me&quot;</code> links.</strong> The back-link from each profile is mandatory. Both directions, or nothing.</li>\n<li><strong>The wrong secret name.</strong> My fetch ran, returned nothing, and looked &quot;fine.&quot; It was reading an empty token. Name your secrets carefully and verify them.</li>\n<li><strong>Patience.</strong> Bridgy polls on its own schedule and webmention.io needs your tags live first. After deploying, I had to give the silos time to crawl before anything appeared. It is not instant.</li>\n</ul>\n<h2 id=\"next-step\" tabindex=\"-1\">Next step <a class=\"header-anchor\" href=\"#next-step\">#</a></h2>\n<p>The piece I am building toward now is having <strong>Bridgy publish each new blog post out to my <a href=\"https://github.com/adamdjbrett\">github.com README</a></strong>, so my profile becomes one more place my writing flows automatically — owned by me, syndicated everywhere. More on that once I have it working (and broken, and working again).</p>\n<p>Webmentions were a pain, but owning my own conversations turned out to be very much worth it.</p>\n",
			"date_published": "2026-06-29T14:15:34Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/standard-site-eleventy-sequoia/",
			"url": "https://www.adamdjbrett.com/blog/standard-site-eleventy-sequoia/",
			"title": "Publishing Your Eleventy Blog on the AT Protocol with Standard.site and Sequoia",
			"content_html": "<p><em>Have you ever been conceptually into the idea of the blockchain or NFTs? and wanted to try something a little more confusing and harder? I give you standard.site and this is why I love and hate it.</em></p>\n<p>The web you publish on doesn't have to be the web someone else owns. If you run a static site built with <a href=\"https://www.11ty.dev/\">Build Awesome the SSG formerly known as Eleventy (11ty)</a> — or are thinking about starting one — you can now register it as a first-class publication on the <a href=\"https://atproto.com/\">AT Protocol</a>, the open decentralized network that powers <a href=\"https://bsky.app/\">Bluesky</a>. That means your posts appear in AT Protocol readers and aggregators, readers can follow your blog the way they follow Bluesky accounts, and your content lives in your own repository rather than inside a platform's database.</p>\n<p>This guide walks through the whole process: what AT Protocol is, what <a href=\"https://standard.site\">standard.site</a> and <a href=\"https://tangled.org/stevedylan.dev/sequoia\">sequoia-cli</a> do, and the exact configuration and scripts needed to publish a real Eleventy site. I learned most of what is here the hard way — through broken tokens, wrong path templates, date corruption bugs, orphaned records, and a CI/CD publish loop that failed every single build until I understood <em>where</em> publishing is allowed to happen — so you don't have to.</p>\n<hr>\n<h2 id=\"what-is-at-protocol\" tabindex=\"-1\">What Is AT Protocol? <a class=\"header-anchor\" href=\"#what-is-at-protocol\">#</a></h2>\n<p><a href=\"https://atproto.com/\">AT Protocol</a> (ATProto) is an open standard for decentralized social networking. Bluesky is the most well-known application built on it, but ATProto is protocol-agnostic: it is a general-purpose system for publishing records, following accounts, and federating data across servers.</p>\n<p>A few concepts worth understanding before you dive in:</p>\n<p><strong>DID (Decentralized Identifier):</strong> Your permanent identity on the AT Protocol. It looks like <code>did:plc:abc123xyz</code>. Unlike a username, it never changes even if you move servers. You can verify your DID at <a href=\"https://bsky.social\">bsky.social</a> by looking at your profile's advanced settings.</p>\n<p><strong>PDS (Personal Data Server):</strong> The server that stores your data. Bluesky hosts a PDS for most users at <code>bsky.social</code>, but you can self-host. Your PDS holds your records — posts, likes, follows, and for our purposes, your blog documents.</p>\n<p><strong>Records and Collections:</strong> Everything on AT Protocol is a <em>record</em> in a <em>collection</em>. Bluesky posts are <code>app.bsky.feed.post</code> records. Standard.site defines two collections: <code>site.standard.publication</code> (your blog, once) and <code>site.standard.document</code> (one record per post).</p>\n<p><strong>Handle:</strong> Your human-readable identifier, like <code>adjb.co</code> or <code>yourname.bsky.social</code>. You can verify a custom domain as your handle through DNS.</p>\n<p>The important thing for blog publishing: your blog posts become AT Protocol records that any app or aggregator following the <code>site.standard</code> schema can discover, display, and index — without you being locked into any particular platform.</p>\n<hr>\n<h2 id=\"what-is-standard-site\" tabindex=\"-1\">What Is Standard.site? <a class=\"header-anchor\" href=\"#what-is-standard-site\">#</a></h2>\n<p><a href=\"https://standard.site\">Standard.site</a> is a specification and ecosystem for publishing static websites as AT Protocol publications. It defines the <code>site.standard.publication</code> and <code>site.standard.document</code> lexicons — the schema that tells AT Protocol clients what a blog post looks like (title, description, path, cover image, publication date, tags, and so on).</p>\n<p>Think of it as RSS but native to the decentralized web. Instead of an XML file that feed readers poll, your posts are first-class records in the AT Protocol network that apps can subscribe to, aggregate, and display in real time.</p>\n<hr>\n<h2 id=\"what-is-sequoia-cli\" tabindex=\"-1\">What Is sequoia-cli? <a class=\"header-anchor\" href=\"#what-is-sequoia-cli\">#</a></h2>\n<p><a href=\"https://tangled.org/stevedylan.dev/sequoia\">sequoia-cli</a> (the project, confusingly, also goes by the name <code>sequoia</code> and lives at <code>standard.site</code>) is the command-line tool that bridges your static site to the AT Protocol. It:</p>\n<ul>\n<li>Authenticates with your AT Protocol identity via OAuth</li>\n<li>Reads your staged blog post files</li>\n<li>Creates or updates <code>site.standard.document</code> records on your PDS</li>\n<li>Optionally uploads cover images as blobs</li>\n<li>Writes the resulting AT URIs back to your post front matter so your site can link to them</li>\n</ul>\n<p>You do not need to write any AT Protocol API calls by hand. sequoia-cli handles the protocol, the authentication, and the record management.</p>\n<hr>\n<h2 id=\"prerequisites\" tabindex=\"-1\">Prerequisites <a class=\"header-anchor\" href=\"#prerequisites\">#</a></h2>\n<p>Before starting, you need:</p>\n<ul>\n<li><strong>An Eleventy site</strong> with posts in Markdown files that have YAML front matter. If you are brand new to Eleventy, start with the <a href=\"https://www.11ty.dev/docs/\">official docs</a>.</li>\n<li><strong>A Bluesky account.</strong> Sign up at <a href=\"https://bsky.app\">bsky.app</a>. Your DID is assigned automatically.</li>\n<li><strong>Node.js 20+</strong> installed.</li>\n<li><strong>A custom domain handle</strong> (optional but recommended). You can use <code>yourname.bsky.social</code> to start and upgrade later. Setting a custom domain handle requires adding a DNS TXT record — Bluesky's settings walk you through it.</li>\n<li><strong>npm</strong> for installing dependencies.</li>\n</ul>\n<hr>\n<h2 id=\"step-1-install-sequoia-cli-and-log-in\" tabindex=\"-1\">Step 1: Install sequoia-cli and Log In <a class=\"header-anchor\" href=\"#step-1-install-sequoia-cli-and-log-in\">#</a></h2>\n<p>Install the CLI as a dev dependency in your Eleventy project:</p>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\"><span class=\"token function\">npm</span> <span class=\"token function\">install</span> --save-dev sequoia-cli</code></pre>\n<p>Or run it on demand with <code>npx</code>:</p>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\">npx sequoia-cli <span class=\"token parameter variable\">--version</span></code></pre>\n<p>Next, log in with your AT Protocol identity. This opens a browser OAuth flow:</p>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\">npx sequoia-cli login</code></pre>\n<p>You will be redirected to Bluesky to authorize the app. After completing the flow, sequoia stores an OAuth session token at <code>~/.config/sequoia/oauth.json</code>. This token expires roughly every hour, so you will need to re-run <code>login</code> periodically during development.</p>\n<blockquote>\n<p><strong>Tip:</strong> For automated CI/CD workflows, use a <strong>Bluesky app password</strong> instead (Settings → Privacy and Security → App Passwords). App passwords use legacy Bearer auth and do not expire, making them much more reliable in scripts. We will cover that in the advanced section.</p>\n</blockquote>\n<hr>\n<h2 id=\"step-2-initialize-your-publication\" tabindex=\"-1\">Step 2: Initialize Your Publication <a class=\"header-anchor\" href=\"#step-2-initialize-your-publication\">#</a></h2>\n<p>Run the init wizard to register your site as a publication on the AT Protocol:</p>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\">npx sequoia-cli init</code></pre>\n<p>The wizard asks several questions. Here is what each one means:</p>\n<table>\n<thead>\n<tr>\n<th>Prompt</th>\n<th>What to enter</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Site URL</td>\n<td>Your full site URL, e.g. <code>https://www.example.com</code></td>\n</tr>\n<tr>\n<td>Content directory</td>\n<td>The <strong>staged</strong> directory (see Step 3), e.g. <code>.cache/sequoia-content</code></td>\n</tr>\n<tr>\n<td>Public/static directory</td>\n<td>Where your <code>.well-known</code> files live, e.g. <code>public</code></td>\n</tr>\n<tr>\n<td>Handle</td>\n<td>Your AT Protocol handle, e.g. <code>yourname.bsky.social</code> or <code>yourname.com</code></td>\n</tr>\n<tr>\n<td>Publication name</td>\n<td>The human-readable name for your blog</td>\n</tr>\n<tr>\n<td>Description</td>\n<td>A short description</td>\n</tr>\n<tr>\n<td>Path template</td>\n<td>The URL pattern for posts — <strong>important</strong>, see below</td>\n</tr>\n<tr>\n<td>Cover images directory</td>\n<td>Leave empty, or the path to your image assets folder</td>\n</tr>\n<tr>\n<td>Icon image path</td>\n<td>Optional; your site's icon/logo</td>\n</tr>\n</tbody>\n</table>\n<p><strong>Run <code>init</code> only once.</strong> Running it a second time creates a duplicate publication record on the AT Protocol. If you accidentally run it twice, you will need to manually delete the duplicate record — we will cover that in the troubleshooting section.</p>\n<p>After <code>init</code> completes, two things happen:</p>\n<ol>\n<li>A <code>sequoia.json</code> config file is created in your project root.</li>\n<li>A <code>site.standard.publication</code> record is written to your PDS and the resulting AT URI is written to <code>public/.well-known/site.standard.publication</code>.</li>\n</ol>\n<hr>\n<h2 id=\"step-3-configure-sequoia-json\" tabindex=\"-1\">Step 3: Configure sequoia.json <a class=\"header-anchor\" href=\"#step-3-configure-sequoia-json\">#</a></h2>\n<p>Open <code>sequoia.json</code> and review every field carefully. Here is the full configuration from this site, with each field explained:</p>\n<pre class=\"language-json\" tabindex=\"0\"><code class=\"language-json\"><span class=\"token punctuation\">{</span>\n  <span class=\"token property\">\"$schema\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"https://tangled.org/stevedylan.dev/sequoia/raw/main/sequoia.schema.json\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"contentDir\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\".cache/sequoia-content\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"siteUrl\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"https://www.adamdjbrett.com\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"identity\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"adjb.co\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"publicationUri\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"at://did:plc:3vmq5usrh3yvhbrrzf4ymo23/site.standard.publication/3mpfboadoa72e\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"autoSync\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"publicDir\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"public\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"outputDir\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"_site\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"pathTemplate\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"/blog/{slug}/\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"stripDatePrefix\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"removeIndexFromSlug\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"publishContent\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"bluesky\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token property\">\"enabled\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"maxAgeDays\"</span><span class=\"token operator\">:</span> <span class=\"token number\">7</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"frontmatter\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token property\">\"publishDate\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"date\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"title\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"title\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"description\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"description\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"draft\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"draft\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"tags\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"tags\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"coverImage\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"image\"</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"ignore\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span>\n    <span class=\"token string\">\"**/README.md\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"**/demo.md\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token string\">\"**/_*.md\"</span>\n  <span class=\"token punctuation\">]</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>The most important field to get right is <strong><code>pathTemplate</code></strong>. This controls the <code>path</code> field written into each AT Protocol document record — the path is combined with your <code>siteUrl</code> to produce the canonical URL for the post in any AT Protocol reader.</p>\n<p>If your blog URLs look like <code>https://example.com/blog/my-post/</code>, set:</p>\n<pre class=\"language-json\" tabindex=\"0\"><code class=\"language-json\"><span class=\"token property\">\"pathTemplate\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"/blog/{slug}/\"</span></code></pre>\n<p>If your URLs look like <code>https://example.com/my-post</code>, set:</p>\n<pre class=\"language-json\" tabindex=\"0\"><code class=\"language-json\"><span class=\"token property\">\"pathTemplate\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"/{slug}\"</span></code></pre>\n<p><strong>Getting this wrong is the most common mistake.</strong> If the path is wrong, every link from an AT Protocol reader or aggregator will 404. You can fix it later by updating <code>pathTemplate</code> and re-running publish — sequoia will detect the change and update all records.</p>\n<p>The <strong><code>contentDir</code></strong> field is equally critical. Do <em>not</em> point it at your actual source <code>content/blog</code> directory. Sequoia reads from a <em>staged</em> directory where you have preprocessed and normalized your posts (more on this in Step 4). Using a <code>.cache/</code> subdirectory keeps staged files out of source control.</p>\n<hr>\n<h2 id=\"step-4-stage-your-content-with-a-prepare-script\" tabindex=\"-1\">Step 4: Stage Your Content with a Prepare Script <a class=\"header-anchor\" href=\"#step-4-stage-your-content-with-a-prepare-script\">#</a></h2>\n<p>Your source Markdown files often contain things sequoia cannot handle directly: front matter fields that do not map to AT Protocol fields, posts that should be excluded (drafts, posts mirrored from other platforms, book reviews), or images with paths relative to your site root that need to be resolved against your <code>public/</code> directory.</p>\n<p>The solution is a <strong>prepare script</strong> that runs before <code>sequoia publish</code> and copies your posts into the <code>contentDir</code> staging area, transforming them as needed. Here is a complete example:</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\"><span class=\"token comment\">// scripts/prepare-sequoia-content.mjs</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> mkdir<span class=\"token punctuation\">,</span> readFile<span class=\"token punctuation\">,</span> rm<span class=\"token punctuation\">,</span> writeFile <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">\"node:fs/promises\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> path <span class=\"token keyword\">from</span> <span class=\"token string\">\"node:path\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> yaml <span class=\"token keyword\">from</span> <span class=\"token string\">\"js-yaml\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> fg <span class=\"token keyword\">from</span> <span class=\"token string\">\"fast-glob\"</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> root <span class=\"token operator\">=</span> process<span class=\"token punctuation\">.</span><span class=\"token function\">cwd</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> sourceDir <span class=\"token operator\">=</span> path<span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span>root<span class=\"token punctuation\">,</span> <span class=\"token string\">\"content\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"blog\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> stagedDir <span class=\"token operator\">=</span> path<span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span>root<span class=\"token punctuation\">,</span> <span class=\"token string\">\".cache\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"sequoia-content\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> publicDir <span class=\"token operator\">=</span> path<span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span>root<span class=\"token punctuation\">,</span> <span class=\"token string\">\"public\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// Posts whose canonical URL is on another platform are excluded —</span>\n<span class=\"token comment\">// they already have an authoritative AT record there.</span>\n<span class=\"token keyword\">const</span> excludedCanonicalHosts <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Set</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"lemma.pub\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"www.lemma.pub\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">parseFrontMatter</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">source</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> match <span class=\"token operator\">=</span> source<span class=\"token punctuation\">.</span><span class=\"token function\">match</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">^---\\n([\\s\\S]*?)\\n---\\n?([\\s\\S]*)$</span><span class=\"token regex-delimiter\">/</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>match<span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">data</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">body</span><span class=\"token operator\">:</span> source<span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">hasFrontMatter</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n  <span class=\"token comment\">// IMPORTANT: use CORE_SCHEMA to prevent js-yaml from auto-parsing</span>\n  <span class=\"token comment\">// date strings as JS Date objects, which corrupts timezone-aware dates.</span>\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">data</span><span class=\"token operator\">:</span> yaml<span class=\"token punctuation\">.</span><span class=\"token function\">load</span><span class=\"token punctuation\">(</span>match<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">schema</span><span class=\"token operator\">:</span> yaml<span class=\"token punctuation\">.</span><span class=\"token constant\">CORE_SCHEMA</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">||</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">body</span><span class=\"token operator\">:</span> match<span class=\"token punctuation\">[</span><span class=\"token number\">2</span><span class=\"token punctuation\">]</span> <span class=\"token operator\">||</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">hasFrontMatter</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">stringifyFrontMatter</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">data<span class=\"token punctuation\">,</span> body</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> fm <span class=\"token operator\">=</span> yaml<span class=\"token punctuation\">.</span><span class=\"token function\">dump</span><span class=\"token punctuation\">(</span>data<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token literal-property property\">schema</span><span class=\"token operator\">:</span> yaml<span class=\"token punctuation\">.</span><span class=\"token constant\">CORE_SCHEMA</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">lineWidth</span><span class=\"token operator\">:</span> <span class=\"token number\">1000</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">noRefs</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n    <span class=\"token literal-property property\">sortKeys</span><span class=\"token operator\">:</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">return</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">---\\n</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>fm<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">---\\n</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>body<span class=\"token punctuation\">.</span><span class=\"token function\">replace</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">^\\n+</span><span class=\"token regex-delimiter\">/</span></span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span><span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">shouldSkip</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">data</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>data<span class=\"token punctuation\">.</span>draft <span class=\"token operator\">===</span> <span class=\"token boolean\">true</span> <span class=\"token operator\">||</span> data<span class=\"token punctuation\">.</span>published <span class=\"token operator\">===</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token string\">\"draft\"</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>Array<span class=\"token punctuation\">.</span><span class=\"token function\">isArray</span><span class=\"token punctuation\">(</span>data<span class=\"token punctuation\">.</span>tags<span class=\"token punctuation\">)</span> <span class=\"token operator\">&amp;&amp;</span> data<span class=\"token punctuation\">.</span>tags<span class=\"token punctuation\">.</span><span class=\"token function\">includes</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"book-review\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token string\">\"book-review tag\"</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">try</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> host <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">URL</span><span class=\"token punctuation\">(</span><span class=\"token function\">String</span><span class=\"token punctuation\">(</span>data<span class=\"token punctuation\">.</span>canonical_url <span class=\"token operator\">||</span> data<span class=\"token punctuation\">.</span>canonicalUrl <span class=\"token operator\">||</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>hostname<span class=\"token punctuation\">.</span><span class=\"token function\">toLowerCase</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>excludedCanonicalHosts<span class=\"token punctuation\">.</span><span class=\"token function\">has</span><span class=\"token punctuation\">(</span>host<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">canonical URL is </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>host<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span>\n  <span class=\"token keyword\">return</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// Resolve cover image paths relative to the staged file, since sequoia</span>\n<span class=\"token comment\">// reads images relative to contentDir, not the project root.</span>\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">normalizeCoverImage</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">image<span class=\"token punctuation\">,</span> stagedPath</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">typeof</span> image <span class=\"token operator\">!==</span> <span class=\"token string\">\"string\"</span> <span class=\"token operator\">||</span> <span class=\"token operator\">!</span>image<span class=\"token punctuation\">.</span><span class=\"token function\">startsWith</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"/\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> image<span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">const</span> abs <span class=\"token operator\">=</span> path<span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span>publicDir<span class=\"token punctuation\">,</span> image<span class=\"token punctuation\">.</span><span class=\"token function\">replace</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">^\\/+</span><span class=\"token regex-delimiter\">/</span></span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">return</span> path<span class=\"token punctuation\">.</span><span class=\"token function\">relative</span><span class=\"token punctuation\">(</span>path<span class=\"token punctuation\">.</span><span class=\"token function\">dirname</span><span class=\"token punctuation\">(</span>stagedPath<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> abs<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">split</span><span class=\"token punctuation\">(</span>path<span class=\"token punctuation\">.</span>sep<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"/\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">await</span> <span class=\"token function\">rm</span><span class=\"token punctuation\">(</span>stagedDir<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">recursive</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">force</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">await</span> <span class=\"token function\">mkdir</span><span class=\"token punctuation\">(</span>stagedDir<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">recursive</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> files <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> <span class=\"token function\">fg</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"**/*.md\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">cwd</span><span class=\"token operator\">:</span> sourceDir<span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">onlyFiles</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">let</span> published <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> skipped <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">const</span> relativePath <span class=\"token keyword\">of</span> files<span class=\"token punctuation\">.</span><span class=\"token function\">sort</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> sourcePath <span class=\"token operator\">=</span> path<span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span>sourceDir<span class=\"token punctuation\">,</span> relativePath<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">const</span> stagedPath <span class=\"token operator\">=</span> path<span class=\"token punctuation\">.</span><span class=\"token function\">join</span><span class=\"token punctuation\">(</span>stagedDir<span class=\"token punctuation\">,</span> relativePath<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">const</span> source <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> <span class=\"token function\">readFile</span><span class=\"token punctuation\">(</span>sourcePath<span class=\"token punctuation\">,</span> <span class=\"token string\">\"utf8\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> data<span class=\"token punctuation\">,</span> body<span class=\"token punctuation\">,</span> hasFrontMatter <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">parseFrontMatter</span><span class=\"token punctuation\">(</span>source<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>hasFrontMatter<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> skipped<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span> <span class=\"token keyword\">continue</span><span class=\"token punctuation\">;</span> <span class=\"token punctuation\">}</span>\n  <span class=\"token keyword\">const</span> skipReason <span class=\"token operator\">=</span> <span class=\"token function\">shouldSkip</span><span class=\"token punctuation\">(</span>data<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>skipReason<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span> skipped<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span> <span class=\"token keyword\">continue</span><span class=\"token punctuation\">;</span> <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">const</span> stagedData <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> <span class=\"token operator\">...</span>data <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// Inject a date for posts whose filename has one but front matter doesn't.</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>stagedData<span class=\"token punctuation\">.</span>date<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> m <span class=\"token operator\">=</span> relativePath<span class=\"token punctuation\">.</span><span class=\"token function\">match</span><span class=\"token punctuation\">(</span><span class=\"token regex\"><span class=\"token regex-delimiter\">/</span><span class=\"token regex-source language-regex\">^(\\d{4}-\\d{2}-\\d{2})</span><span class=\"token regex-delimiter\">/</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>m<span class=\"token punctuation\">)</span> stagedData<span class=\"token punctuation\">.</span>date <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>m<span class=\"token punctuation\">[</span><span class=\"token number\">1</span><span class=\"token punctuation\">]</span><span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">T12:00:00.000Z</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token comment\">// If the post already has a live AT URI from a previous publish,</span>\n  <span class=\"token comment\">// pass it to sequoia so it updates rather than creates a new record.</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>stagedData<span class=\"token punctuation\">.</span>standard_site_document <span class=\"token operator\">&amp;&amp;</span> <span class=\"token operator\">!</span>stagedData<span class=\"token punctuation\">.</span>atUri<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    stagedData<span class=\"token punctuation\">.</span>atUri <span class=\"token operator\">=</span> stagedData<span class=\"token punctuation\">.</span>standard_site_document<span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  stagedData<span class=\"token punctuation\">.</span>image <span class=\"token operator\">=</span> <span class=\"token function\">normalizeCoverImage</span><span class=\"token punctuation\">(</span>stagedData<span class=\"token punctuation\">.</span>image<span class=\"token punctuation\">,</span> stagedPath<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">await</span> <span class=\"token function\">mkdir</span><span class=\"token punctuation\">(</span>path<span class=\"token punctuation\">.</span><span class=\"token function\">dirname</span><span class=\"token punctuation\">(</span>stagedPath<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">recursive</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">await</span> <span class=\"token function\">writeFile</span><span class=\"token punctuation\">(</span>stagedPath<span class=\"token punctuation\">,</span> <span class=\"token function\">stringifyFrontMatter</span><span class=\"token punctuation\">(</span>stagedData<span class=\"token punctuation\">,</span> body<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"utf8\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  published<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\nconsole<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">Prepared </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>published<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\"> posts. Skipped </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>skipped<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\">.</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre>\n<p>Install the dependencies this script needs:</p>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\"><span class=\"token function\">npm</span> <span class=\"token function\">install</span> --save-dev js-yaml fast-glob</code></pre>\n<hr>\n<h2 id=\"step-5-wire-up-npm-scripts\" tabindex=\"-1\">Step 5: Wire Up npm Scripts <a class=\"header-anchor\" href=\"#step-5-wire-up-npm-scripts\">#</a></h2>\n<p>Add these scripts to your <code>package.json</code> so you have a consistent publish workflow:</p>\n<pre class=\"language-json\" tabindex=\"0\"><code class=\"language-json\"><span class=\"token punctuation\">{</span>\n  <span class=\"token property\">\"scripts\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token property\">\"standard:prepare\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"node scripts/prepare-sequoia-content.mjs\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"standard:publish:dry\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"npm run standard:prepare &amp;&amp; npx sequoia-cli publish --dry-run\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"standard:publish\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"npm run standard:prepare &amp;&amp; npx sequoia-cli publish\"</span><span class=\"token punctuation\">,</span>\n    <span class=\"token property\">\"standard:inject\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"npx sequoia-cli inject --output _site\"</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>The dry-run command is valuable: it shows you exactly which posts will be published and what their AT Protocol paths will be, without actually writing anything to the network.</p>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\"><span class=\"token function\">npm</span> run standard:publish:dry</code></pre>\n<p>When you are ready to go live:</p>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\">npx sequoia-cli login   <span class=\"token comment\"># refresh the OAuth token first</span>\n<span class=\"token function\">npm</span> run standard:publish</code></pre>\n<p>On first run you will see <code>Published: 57</code> (or however many posts you have). On subsequent runs sequoia detects which posts have changed and shows <code>Updated: 3</code> for only those files. Each record gets an AT URI written back to its front matter field (<code>standard_site_document</code>).</p>\n<hr>\n<h2 id=\"step-6-verify-on-the-at-protocol\" tabindex=\"-1\">Step 6: Verify on the AT Protocol <a class=\"header-anchor\" href=\"#step-6-verify-on-the-at-protocol\">#</a></h2>\n<p>After publishing, you can verify your records are live using the public AT Protocol API. Replace the DID with your own:</p>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\"><span class=\"token function\">curl</span> <span class=\"token string\">\"https://bsky.social/xrpc/com.atproto.repo.listRecords?\\\nrepo=did:plc:YOUR_DID_HERE\\\n&amp;collection=site.standard.document\\\n&amp;limit=5\"</span></code></pre>\n<p>You can also check your publication record:</p>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\"><span class=\"token function\">curl</span> <span class=\"token string\">\"https://bsky.social/xrpc/com.atproto.repo.listRecords?\\\nrepo=did:plc:YOUR_DID_HERE\\\n&amp;collection=site.standard.publication\"</span></code></pre>\n<p>If you see your records with the correct <code>path</code> values (matching your actual blog URLs), everything is working. Standard.site readers and aggregators will begin discovering your content.</p>\n<hr>\n<h2 id=\"step-7-validate-your-work-with-the-standard-site-validator\" tabindex=\"-1\">Step 7: Validate Your Work with the Standard.site Validator <a class=\"header-anchor\" href=\"#step-7-validate-your-work-with-the-standard-site-validator\">#</a></h2>\n<p>Querying the raw API tells you a record <em>exists</em>, but it does not tell you whether your site is actually <strong>verified</strong> — that is, whether the <code>&lt;link&gt;</code> tags and the <code>.well-known</code> publication record line up the way standard.site requires. For that, there is a purpose-built validator.</p>\n<p>Visit <strong><a href=\"https://site-validator.fly.dev/\">site-validator.fly.dev</a></strong> and paste in the full URL of any published blog post, for example:</p>\n<pre><code>https://www.adamdjbrett.com/blog/standard-site-eleventy-sequoia/\n</code></pre>\n<p>The validator checks three things, and you want a green check on all of them:</p>\n<ol>\n<li><strong>Document record</strong> — the <code>&lt;link rel=&quot;site.standard.document&quot;&gt;</code> tag in the page <code>&lt;head&gt;</code> points to a real <code>site.standard.document</code> record on your PDS, and the record's schema fields (title, description, path, publishedAt) are valid.</li>\n<li><strong>Publication record</strong> — the <code>&lt;link rel=&quot;site.standard.publication&quot;&gt;</code> tag resolves, and your <code>site.standard.publication</code> record exists.</li>\n<li><strong>Publication verification</strong> — <code>https://yourdomain.com/.well-known/site.standard.publication</code> is reachable and contains the matching publication AT URI.</li>\n</ol>\n<p>That last check is the one most people miss. Your build has to actually serve the <code>.well-known</code> file. You can confirm it independently with curl:</p>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\"><span class=\"token function\">curl</span> <span class=\"token parameter variable\">-i</span> https://www.adamdjbrett.com/.well-known/site.standard.publication\n<span class=\"token comment\"># Expect: HTTP 200 and a body like</span>\n<span class=\"token comment\"># at://did:plc:YOUR_DID/site.standard.publication/YOUR_RKEY</span></code></pre>\n<blockquote>\n<p><strong>Eleventy gotcha:</strong> Some static site generators silently drop dotfiles and dot-directories from the build output. In Eleventy, make sure your <code>public/</code> passthrough copies the whole folder — <code>eleventyConfig.addPassthroughCopy({ &quot;./public/&quot;: &quot;/&quot; })</code> — so <code>public/.well-known/</code> lands in <code>_site/.well-known/</code>. If the validator reports the publication as unverified but your document record is fine, this missing <code>.well-known</code> file is almost always why.</p>\n</blockquote>\n<p>If you want a second opinion on the raw record schema, <a href=\"https://pds.ls\">pds.ls</a> lets you paste an AT URI and inspect the stored record field by field. It checks schema validity but not standard.site verification, so use it alongside the validator, not instead of it.</p>\n<hr>\n<h2 id=\"a-critical-gotcha-dates-and-yaml-parsing\" tabindex=\"-1\">A Critical Gotcha: Dates and YAML Parsing <a class=\"header-anchor\" href=\"#a-critical-gotcha-dates-and-yaml-parsing\">#</a></h2>\n<p>If your post dates include timezone offsets — like <code>2026-06-28T17:00:00-05:00</code> — and you ever write a script that parses and re-serializes your front matter with <code>js-yaml</code>, you will run into date corruption unless you use the <code>CORE_SCHEMA</code> option.</p>\n<p>By default, <code>js-yaml</code> parses <code>YYYY-MM-DD</code> date strings and timezone-aware ISO strings as JavaScript <code>Date</code> objects. When it serializes them back to YAML, it converts to UTC — silently shifting your dates. A post dated <code>2026-06-28T17:00:00-05:00</code> (5pm Chicago) becomes <code>2026-06-28T22:00:00.000Z</code> in the output.</p>\n<p>The fix is one option in every <code>yaml.load()</code> and <code>yaml.dump()</code> call:</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\"><span class=\"token comment\">// Always pair these options together:</span>\n<span class=\"token keyword\">const</span> data <span class=\"token operator\">=</span> yaml<span class=\"token punctuation\">.</span><span class=\"token function\">load</span><span class=\"token punctuation\">(</span>frontMatter<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">schema</span><span class=\"token operator\">:</span> yaml<span class=\"token punctuation\">.</span><span class=\"token constant\">CORE_SCHEMA</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> output <span class=\"token operator\">=</span> yaml<span class=\"token punctuation\">.</span><span class=\"token function\">dump</span><span class=\"token punctuation\">(</span>data<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">schema</span><span class=\"token operator\">:</span> yaml<span class=\"token punctuation\">.</span><span class=\"token constant\">CORE_SCHEMA</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">lineWidth</span><span class=\"token operator\">:</span> <span class=\"token number\">1000</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre>\n<p><code>CORE_SCHEMA</code> treats date strings as plain strings and never auto-converts them. Make this a habit in any script that touches Markdown front matter.</p>\n<hr>\n<h2 id=\"excluding-posts-selectively\" tabindex=\"-1\">Excluding Posts Selectively <a class=\"header-anchor\" href=\"#excluding-posts-selectively\">#</a></h2>\n<p>Not every post in your blog may belong on the AT Protocol. Common cases to skip:</p>\n<ul>\n<li><strong>Drafts:</strong> Posts with <code>draft: true</code> or <code>published: false</code></li>\n<li><strong>Book reviews or off-topic content:</strong> Filter by tag</li>\n<li><strong>Posts mirrored from another platform:</strong> Filter by <code>canonical_url</code></li>\n</ul>\n<p>All of this lives in the <code>shouldSkip()</code> function in your prepare script. Here is an expanded version:</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\"><span class=\"token keyword\">const</span> <span class=\"token function-variable function\">shouldSkip</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">data</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// Standard draft/hidden flags</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>data<span class=\"token punctuation\">.</span>draft <span class=\"token operator\">===</span> <span class=\"token boolean\">true</span> <span class=\"token operator\">||</span> data<span class=\"token punctuation\">.</span>published <span class=\"token operator\">===</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token string\">\"draft\"</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>data<span class=\"token punctuation\">.</span>eleventyExcludeFromCollections <span class=\"token operator\">===</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token string\">\"excluded from collections\"</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// Skip posts tagged as book reviews (managed separately on lemma.pub)</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>Array<span class=\"token punctuation\">.</span><span class=\"token function\">isArray</span><span class=\"token punctuation\">(</span>data<span class=\"token punctuation\">.</span>tags<span class=\"token punctuation\">)</span> <span class=\"token operator\">&amp;&amp;</span> data<span class=\"token punctuation\">.</span>tags<span class=\"token punctuation\">.</span><span class=\"token function\">includes</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"book-review\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token string\">\"book-review tag\"</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token comment\">// Skip posts whose canonical URL belongs to another platform —</span>\n  <span class=\"token comment\">// those posts already have authoritative records there.</span>\n  <span class=\"token keyword\">try</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">const</span> url <span class=\"token operator\">=</span> data<span class=\"token punctuation\">.</span>canonical_url <span class=\"token operator\">||</span> data<span class=\"token punctuation\">.</span>canonicalUrl<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>url<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">const</span> host <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">URL</span><span class=\"token punctuation\">(</span><span class=\"token function\">String</span><span class=\"token punctuation\">(</span>url<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>hostname<span class=\"token punctuation\">.</span><span class=\"token function\">toLowerCase</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token keyword\">const</span> excluded <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Set</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">[</span><span class=\"token string\">\"lemma.pub\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"www.lemma.pub\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"medium.com\"</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>excluded<span class=\"token punctuation\">.</span><span class=\"token function\">has</span><span class=\"token punctuation\">(</span>host<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">canonical on </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>host<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">return</span> <span class=\"token string\">\"\"</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// empty string = include</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre>\n<hr>\n<h2 id=\"managing-multiple-publications\" tabindex=\"-1\">Managing Multiple Publications <a class=\"header-anchor\" href=\"#managing-multiple-publications\">#</a></h2>\n<p>You can have more than one <code>site.standard.publication</code> record under your DID. For example, this site has:</p>\n<ul>\n<li><strong>Adam DJ Brett's blog</strong> — main technical and academic posts at <code>adamdjbrett.com</code></li>\n<li><strong>Spine &amp; Style</strong> — book reviews published through <a href=\"https://lemma.pub\">lemma.pub</a></li>\n</ul>\n<p>Each publication is a separate AT record with a unique rkey. The <code>sequoia.json</code> <code>publicationUri</code> field controls which publication your Eleventy site's posts are filed under. If you manage content across multiple publications, keep separate <code>sequoia.json</code> configs (or separate Eleventy sites) for each.</p>\n<hr>\n<h2 id=\"a-brief-note-on-lemma-pub\" tabindex=\"-1\">A Brief Note on Lemma.pub <a class=\"header-anchor\" href=\"#a-brief-note-on-lemma-pub\">#</a></h2>\n<p>Before settling on sequoia-cli as the publishing tool for this site, I tried <a href=\"https://lemma.pub\">lemma.pub</a> for publishing book reviews as AT Protocol documents. Lemma.pub is a beautiful platform and it works well for books specifically, but it creates its own <code>site.standard.publication</code> record in your AT Protocol repository and manages its own documents. When I started integrating sequoia for my main blog, the lemma.pub publication and the new sequoia publication existed side by side — which is fine — but I had orphaned documents from earlier failed sequoia attempts piling up under a deleted publication. The cleanup required writing a custom script with DPoP authentication (AT Protocol's OAuth security mechanism) and cost an afternoon of debugging. The short lesson: do not run <code>sequoia init</code> more than once, verify your publication record exists before publishing, and if you use lemma.pub alongside sequoia, treat them as independent — they will not interfere with each other.</p>\n<hr>\n<h2 id=\"troubleshooting-common-issues\" tabindex=\"-1\">Troubleshooting Common Issues <a class=\"header-anchor\" href=\"#troubleshooting-common-issues\">#</a></h2>\n<p><strong><code>publicationUri is required in config</code></strong>\nThis error means your <code>sequoia.json</code> is missing the <code>publicationUri</code> field. After <code>sequoia init</code>, find your publication's AT URI in <code>public/.well-known/site.standard.publication</code> and add it manually:</p>\n<pre class=\"language-json\" tabindex=\"0\"><code class=\"language-json\"><span class=\"token property\">\"publicationUri\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"at://did:plc:YOUR_DID/site.standard.publication/YOUR_RKEY\"</span></code></pre>\n<p><strong>Posts appear at the wrong URL in AT readers</strong>\nCheck <code>pathTemplate</code> in <code>sequoia.json</code>. The path must match your actual Eleventy URL structure exactly. If your posts live at <code>/blog/my-post/</code>, you need <code>&quot;/blog/{slug}/&quot;</code>. After fixing it, re-run publish — sequoia detects the change and updates all 57 records automatically.</p>\n<p><strong><code>InvalidToken: Malformed token</code></strong>\nAT Protocol OAuth uses a security mechanism called DPoP (Demonstrating Proof of Possession) that requires a freshly signed proof JWT with every request. The OAuth token also expires in roughly one hour. If you see this error in a custom script, check that:</p>\n<ol>\n<li>You re-ran <code>npx sequoia-cli login</code> recently (within the hour)</li>\n<li>You are using <code>Authorization: DPoP {token}</code> not <code>Authorization: Bearer {token}</code></li>\n</ol>\n<p>For automation scripts, skip DPoP complexity entirely by using a Bluesky <strong>app password</strong> with the legacy <code>createSession</code> API:</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\"><span class=\"token keyword\">const</span> res <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> <span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"https://bsky.social/xrpc/com.atproto.server.createSession\"</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token literal-property property\">method</span><span class=\"token operator\">:</span> <span class=\"token string\">\"POST\"</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">headers</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span> <span class=\"token string-property property\">\"Content-Type\"</span><span class=\"token operator\">:</span> <span class=\"token string\">\"application/json\"</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token literal-property property\">body</span><span class=\"token operator\">:</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">stringify</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token literal-property property\">identifier</span><span class=\"token operator\">:</span> <span class=\"token string\">\"yourhandle.bsky.social\"</span><span class=\"token punctuation\">,</span> <span class=\"token literal-property property\">password</span><span class=\"token operator\">:</span> <span class=\"token string\">\"your-app-password\"</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> accessJwt <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> res<span class=\"token punctuation\">.</span><span class=\"token function\">json</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token comment\">// Use: Authorization: Bearer ${accessJwt}</span></code></pre>\n<p>App passwords use plain Bearer auth, never expire mid-script, and work perfectly for one-off admin operations.</p>\n<p><strong>Cover images not uploading</strong>\nsequoia-cli resolves cover image paths relative to <code>contentDir</code>, not your project root. If your image is at <code>public/assets/img/post.webp</code> and your staged files are in <code>.cache/sequoia-content</code>, you need a relative path like <code>../../public/assets/img/post.webp</code>. The prepare script in Step 4 handles this automatically with the <code>normalizeCoverImage()</code> helper.</p>\n<hr>\n<h2 id=\"automating-publish-in-ci-cd-and-the-trap-i-fell-into\" tabindex=\"-1\">Automating Publish in CI/CD — and the Trap I Fell Into <a class=\"header-anchor\" href=\"#automating-publish-in-ci-cd-and-the-trap-i-fell-into\">#</a></h2>\n<p>This is the part that cost me the most grief, so it gets the most detail.</p>\n<p>The obvious thing to do is run <code>sequoia publish</code> as part of your normal deploy build — fold it into the same command your host (Netlify, Vercel, Cloudflare Pages) runs. I did exactly that. My Netlify build command was effectively:</p>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\">sequoia publish <span class=\"token operator\">&amp;&amp;</span> eleventy <span class=\"token operator\">&amp;&amp;</span> sequoia inject</code></pre>\n<p>And it worked once. Then every subsequent build failed.</p>\n<h3 id=\"why-publishing-inside-the-host-build-is-a-trap\" tabindex=\"-1\">Why publishing inside the host build is a trap <a class=\"header-anchor\" href=\"#why-publishing-inside-the-host-build-is-a-trap\">#</a></h3>\n<p>Here is the chicken-and-egg problem. When <code>sequoia publish</code> creates a <em>new</em> document record, it writes the resulting AT URI back into your post's front matter and into <code>.sequoia-state.json</code>. That writeback is the whole mechanism that stops the next run from creating a <em>duplicate</em> record.</p>\n<p>But <strong>your host's build environment cannot commit to your git repository.</strong> Netlify checks out your repo, builds, and throws the checkout away. So the AT URI that <code>sequoia publish</code> just wrote vanishes the moment the build finishes. On the next deploy, the post looks new again — and if you have a writeback step that <em>fails</em> when a URI is missing (mine called <code>process.exit(1)</code>), you get a permanent failure loop: every build dies trying to reconcile a URI that never gets persisted.</p>\n<p>The lesson: <strong>the environment that publishes must be the environment that can commit the results back to git.</strong> Your host build is not that environment. A GitHub Action is.</p>\n<h3 id=\"the-fix-publish-in-ci-build-on-the-host\" tabindex=\"-1\">The fix: publish in CI, build on the host <a class=\"header-anchor\" href=\"#the-fix-publish-in-ci-build-on-the-host\">#</a></h3>\n<p>Split the two responsibilities cleanly:</p>\n<ul>\n<li><strong>A GitHub Action publishes</strong> to the AT Protocol and <strong>commits the AT URIs back</strong> into the repo (both the front matter and <code>.sequoia-state.json</code>).</li>\n<li><strong>Your host only builds and injects.</strong> It never runs <code>sequoia publish</code>. It runs your normal Eleventy build plus <code>sequoia inject</code>, which reads the already-committed <code>.sequoia-state.json</code> to stamp the <code>&lt;link&gt;</code> tags into the finished HTML.</li>\n</ul>\n<p><code>.sequoia-state.json</code> is the key. <strong>Commit it to git.</strong> It is the durable record of every AT URI, and because <code>sequoia inject</code> sources its mappings from that file, your host build always produces correct verification tags without needing credentials or network access to your PDS.</p>\n<p>Here is the workflow that does the publishing. It runs on pushes that touch your posts, plus a daily cron as a safety net, plus manual dispatch:</p>\n<pre class=\"language-yaml\" tabindex=\"0\"><code class=\"language-yaml\"><span class=\"token comment\"># .github/workflows/publish-standard-site.yml</span>\n<span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Publish Standard.site AT URIs\n\n<span class=\"token key atrule\">on</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">push</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">branches</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">[</span>main<span class=\"token punctuation\">]</span>\n    <span class=\"token key atrule\">paths</span><span class=\"token punctuation\">:</span>\n      <span class=\"token punctuation\">-</span> <span class=\"token string\">\"content/blog/**\"</span>\n      <span class=\"token punctuation\">-</span> <span class=\"token string\">\"sequoia.json\"</span>\n  <span class=\"token key atrule\">schedule</span><span class=\"token punctuation\">:</span>\n    <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">cron</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"35 10 * * *\"</span>\n  <span class=\"token key atrule\">workflow_dispatch</span><span class=\"token punctuation\">:</span>\n\n<span class=\"token key atrule\">permissions</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">contents</span><span class=\"token punctuation\">:</span> write          <span class=\"token comment\"># lets the job commit AT URIs back</span>\n\n<span class=\"token key atrule\">concurrency</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">group</span><span class=\"token punctuation\">:</span> publish<span class=\"token punctuation\">-</span>standard<span class=\"token punctuation\">-</span>site\n  <span class=\"token key atrule\">cancel-in-progress</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n\n<span class=\"token key atrule\">jobs</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">publish-standard-site</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">runs-on</span><span class=\"token punctuation\">:</span> ubuntu<span class=\"token punctuation\">-</span>latest\n    <span class=\"token key atrule\">steps</span><span class=\"token punctuation\">:</span>\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">uses</span><span class=\"token punctuation\">:</span> actions/checkout@v5\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">uses</span><span class=\"token punctuation\">:</span> actions/setup<span class=\"token punctuation\">-</span>node@v5\n        <span class=\"token key atrule\">with</span><span class=\"token punctuation\">:</span>\n          <span class=\"token key atrule\">node-version-file</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\".nvmrc\"</span>\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">run</span><span class=\"token punctuation\">:</span> npm ci\n\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Publish and write AT URIs into front matter\n        <span class=\"token key atrule\">env</span><span class=\"token punctuation\">:</span>\n          <span class=\"token key atrule\">ATP_IDENTIFIER</span><span class=\"token punctuation\">:</span> yourhandle.bsky.social\n          <span class=\"token key atrule\">ATP_APP_PASSWORD</span><span class=\"token punctuation\">:</span> $\n        <span class=\"token key atrule\">run</span><span class=\"token punctuation\">:</span> npm run standard<span class=\"token punctuation\">:</span>publish\n\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Commit AT URIs if anything changed\n        <span class=\"token key atrule\">run</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">|</span><span class=\"token scalar string\">\n          set -euo pipefail\n          if [ -z \"$(git status --porcelain -- content/blog .sequoia-state.json)\" ]; then\n            echo \"Nothing to commit.\"\n            exit 0\n          fi\n          git config user.name \"github-actions[bot]\"\n          git config user.email \"41898282+github-actions[bot]@users.noreply.github.com\"\n          git add content/blog .sequoia-state.json\n          git commit -m \"chore: backfill standard.site AT URIs\"\n          git push</span></code></pre>\n<p>Two details that make this loop-safe:</p>\n<ol>\n<li><strong><code>sequoia publish</code> in CI authenticates with an app password</strong>, not the interactive OAuth flow. App passwords use plain Bearer auth, never expire mid-run, and are perfect for headless automation. Store yours as a repository secret. (Set <code>ATP_IDENTIFIER</code> and <code>ATP_APP_PASSWORD</code> and sequoia-cli picks them up automatically — no custom wrapper required.)</li>\n<li><strong>The commit uses the default <code>GITHUB_TOKEN</code>.</strong> Pushes made with <code>GITHUB_TOKEN</code> deliberately do <em>not</em> trigger new workflow runs, so the bot's commit cannot retrigger this workflow — no infinite loop. It <em>will</em>, however, trigger your host's deploy webhook, which is exactly what you want: the host rebuilds with the AT URIs now present in git.</li>\n</ol>\n<h3 id=\"the-host-build-build-and-inject-only\" tabindex=\"-1\">The host build: build and inject only <a class=\"header-anchor\" href=\"#the-host-build-build-and-inject-only\">#</a></h3>\n<p>On the host side, drop <code>sequoia publish</code> entirely. My Netlify build command is now just:</p>\n<pre class=\"language-jsonc\" tabindex=\"0\"><code class=\"language-jsonc\">// package.json\n{\n  \"scripts\": {\n    \"build:netlify\": \"npm run build:prod -- --incremental && npm run standard:inject\"\n  }\n}</code></pre>\n<pre class=\"language-toml\" tabindex=\"0\"><code class=\"language-toml\"><span class=\"token comment\"># netlify.toml</span>\n<span class=\"token punctuation\">[</span><span class=\"token table class-name\">build</span><span class=\"token punctuation\">]</span>\n  <span class=\"token key property\">publish</span> <span class=\"token punctuation\">=</span> <span class=\"token string\">\"_site\"</span>\n  <span class=\"token key property\">command</span> <span class=\"token punctuation\">=</span> <span class=\"token string\">\"npm run build:netlify\"</span></code></pre>\n<h3 id=\"make-the-writeback-script-forgiving\" tabindex=\"-1\">Make the writeback script forgiving <a class=\"header-anchor\" href=\"#make-the-writeback-script-forgiving\">#</a></h3>\n<p>Finally, whatever script copies AT URIs back into your front matter should <strong>warn, not fail</strong>, when a URI is missing. A brand-new post legitimately has no URI for the few seconds between staging and publishing, and the daily cron backfill will catch any straggler. Failing the build there is what created my loop in the first place:</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\"><span class=\"token comment\">// scripts/apply-sequoia-at-uris.mjs (tail)</span>\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>missingAtUri <span class=\"token operator\">></span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// Non-fatal: the committed .sequoia-state.json and the daily backfill</span>\n  <span class=\"token comment\">// are the durable source of truth. Failing here only causes retry loops.</span>\n  console<span class=\"token punctuation\">.</span><span class=\"token function\">warn</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">Warning: </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>missingAtUri<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\"> posts had no AT URI yet; they will be backfilled on the next publish.</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>The end result is a system you never have to think about. You write a post, push it, and the Action publishes it, commits the AT URI back, and the resulting commit triggers a clean deploy that injects the verification tags. The daily cron sweeps up anything missed.</p>\n<hr>\n<h2 id=\"cross-posting-new-posts-to-bluesky\" tabindex=\"-1\">Cross-Posting New Posts to Bluesky <a class=\"header-anchor\" href=\"#cross-posting-new-posts-to-bluesky\">#</a></h2>\n<p>sequoia-cli can announce each new article as a Bluesky post automatically, which is the simplest way to get your writing in front of people. I have this turned on now:</p>\n<pre class=\"language-json\" tabindex=\"0\"><code class=\"language-json\"><span class=\"token property\">\"bluesky\"</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token property\">\"enabled\"</span><span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n  <span class=\"token property\">\"maxAgeDays\"</span><span class=\"token operator\">:</span> <span class=\"token number\">7</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>When <code>sequoia publish</code> runs and finds a <em>new or changed</em> post, it creates a Bluesky post with the title, description, cover image, and canonical link, then links that Bluesky post back to your <code>site.standard.document</code> record. The <code>maxAgeDays</code> window is the important safety valve: it only cross-posts articles dated within that many days. Without it, the first time you enable Bluesky posting sequoia would happily dump your entire back catalogue — in my case 58 posts — into your followers' timelines at once. With <code>maxAgeDays: 7</code>, only genuinely recent posts get announced; everything older stays quietly published to the AT Protocol without a Bluesky blast.</p>\n<p>One subtlety worth knowing: because cross-posting only fires for <em>new or changed</em> posts, flipping <code>enabled</code> to <code>true</code> does <strong>not</strong> retroactively post your existing recent articles. It applies going forward. If you specifically want to backfill the last week's posts to Bluesky, you can force a republish (<code>sequoia publish --force</code>) once — but be deliberate about it, since it posts publicly and is not easily undone.</p>\n<hr>\n<h2 id=\"a-future-next-step-adding-comments-via-bluesky-replies\" tabindex=\"-1\">A Future Next Step: Adding Comments via Bluesky Replies <a class=\"header-anchor\" href=\"#a-future-next-step-adding-comments-via-bluesky-replies\">#</a></h2>\n<p>Here is the payoff for enabling Bluesky cross-posting: you can turn the replies on that Bluesky post into a comment section under your blog post — no comment database, no third-party widget, no spam moderation service. The conversation lives on the AT Protocol, and your page just renders it.</p>\n<p>The flow is:</p>\n<ol>\n<li>Cross-posting is enabled (above), so each published post has a corresponding Bluesky post.</li>\n<li>People reply to that Bluesky post.</li>\n<li>A small web component, <code>sequoia-comments</code>, finds the <code>&lt;link rel=&quot;site.standard.document&quot;&gt;</code> tag already in your page head, fetches the linked post and its reply thread, and renders it.</li>\n</ol>\n<p>Install the component into your project — it will ask where to save the file:</p>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\">npx sequoia-cli <span class=\"token function\">add</span> sequoia-comments</code></pre>\n<p>Then drop the element into your post layout wherever you want comments to appear. Since it is a standard Web Component, no framework wiring is needed; in an Eleventy/Nunjucks post template it is just:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>h2</span><span class=\"token punctuation\">></span></span>Comments<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>h2</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>sequoia-comments</span><span class=\"token punctuation\">></span></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>sequoia-comments</span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>script</span> <span class=\"token attr-name\">type</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>module<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">src</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>/js/sequoia-comments.js<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span><span class=\"token script\"></span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>script</span><span class=\"token punctuation\">></span></span></code></pre>\n<p>Because <code>sequoia inject</code> already put the <code>site.standard.document</code> link tag in your <code>&lt;head&gt;</code>, the component knows which thread to load with zero extra configuration. You can tune it with attributes — <code>depth=&quot;10&quot;</code> to fetch deeper reply nesting, or <code>document-uri=&quot;…&quot;</code> to point it at a specific record explicitly — and theme it with CSS custom properties to match your site:</p>\n<pre class=\"language-css\" tabindex=\"0\"><code class=\"language-css\"><span class=\"token selector\">:root</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token property\">--sequoia-accent-color</span><span class=\"token punctuation\">:</span> #3A5A40<span class=\"token punctuation\">;</span>\n  <span class=\"token property\">--sequoia-bg-color</span><span class=\"token punctuation\">:</span> #1a1a1a<span class=\"token punctuation\">;</span>\n  <span class=\"token property\">--sequoia-fg-color</span><span class=\"token punctuation\">:</span> #F5F3EF<span class=\"token punctuation\">;</span>\n  <span class=\"token property\">--sequoia-border-color</span><span class=\"token punctuation\">:</span> #333<span class=\"token punctuation\">;</span>\n  <span class=\"token property\">--sequoia-border-radius</span><span class=\"token punctuation\">:</span> 12px<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre>\n<p>I have deliberately left comments <strong>off</strong> on this site for now — I wanted Bluesky cross-posting settled first, and comments are a presentation choice I would rather make intentionally than by default. But the groundwork is all in place: the moment I add the component to my post template, the Bluesky replies become my comment section. That is the next step whenever I am ready.</p>\n<hr>\n<h2 id=\"whats-next\" tabindex=\"-1\">What's Next <a class=\"header-anchor\" href=\"#whats-next\">#</a></h2>\n<p>Getting your Eleventy blog onto the AT Protocol is a starting point, not a finish line. A few directions worth exploring:</p>\n<ul>\n<li><a href=\"https://www.adamdjbrett.com/blog/zotero-harvestable-blog-posts/\"><strong>Zotero harvestability:</strong></a> Adding RDFa metadata to your HTML makes your posts citable in Zotero with one click. Martin Paul Eve has <a href=\"https://eve.gd/2026/06/23/making-blog-posts-harvestable-by-zotero-and-preserving-case-in-citation-fields/\">written about the technique</a>; it pairs well with the open-access ethic behind AT Protocol publishing.</li>\n<li><strong>DOI integration:</strong> If your posts are formal academic writing, minting DOIs (via services like Zenodo or institutional repositories) and linking them from your AT Protocol records makes your work permanently citable. (I hope to learn this magic from Martin Paul Eve and/or the brilliant people at Knowledge Commons Soon.)</li>\n<li><strong>standard.site Discover:</strong> Once your publication is live, it may appear in the <a href=\"https://standard.site\">standard.site Discover</a> feed. Setting <code>&quot;showInDiscover&quot;: true</code> in your publication's <code>preferences</code> field opts you in.</li>\n<li><strong>Comments via Bluesky:</strong> With cross-posting enabled, the <code>sequoia-comments</code> web component turns replies to your Bluesky posts into a native comment section — see the <a href=\"#a-future-next-step-adding-comments-via-bluesky-replies\">section above</a>. It is the next thing on my own list.</li>\n</ul>\n<p>The decentralized web is most useful when independent publishers actually use it. If you run an Eleventy site and care about owning your content and your audience relationships, adding AT Protocol publishing is a half-day investment with compounding returns. Your posts become discoverable without surrendering them to a platform's terms of service, recommendation algorithm, or business model.</p>\n<hr>\n<p><em>If you get stuck, the <a href=\"https://atproto.com/docs\">AT Protocol docs</a> and the sequoia-cli source at <a href=\"https://tangled.org/stevedylan.dev/sequoia\">tangled.org</a> are the most reliable references.</em></p>\n",
			"date_published": "2026-06-29T05:46:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/11tyx5-five-sites-long-web/",
			"url": "https://www.adamdjbrett.com/blog/11tyx5-five-sites-long-web/",
			"title": "11tyx5: Five Whitestone Foundation Sites, Eleventy, and the Long Open Web",
			"content_html": "<p>Launching one site feels good. Launching five at once feels like a very specific mix of systems thinking, code soup, and questionable sleep habits. In this case it also turned out to be the right call — and it turned out to be just the beginning.</p>\n<p>Over the last year I rebuilt a whole family of <a href=\"https://thewhitestonefoundation.org\">Whitestone Foundation</a> sites with <a href=\"https://www.11ty.dev/\">Eleventy</a>: <a href=\"https://jcrt.org\">JCRT</a>, <a href=\"https://thenewpolis.com\">The New Polis</a>, <a href=\"https://journal.thenewpolis.com\">Journal of The New Polis</a>, <a href=\"https://esthesis.org\">Esthesis</a>, and <a href=\"https://thewhitestonefoundation.org\">The Whitestone Foundation</a>. JCRT's attached <a href=\"https://jcrt.org/religioustheory\"><code>religioustheory</code></a> publication stream came along with that work too, because once you start cleaning up a journal's publishing architecture, the side rooms are part of the house whether you planned for them or not.</p>\n<p>This was never just a redesign. It was a content migration, a metadata cleanup job, a URL preservation campaign, a search rebuild, a workflow reset, and a practical test of how far minimal computing can take an academic publishing network. That last part matters to me. I did not want to swap one fragile setup for another one with nicer CSS and a cooler README. I wanted sites that could stay online, stay editable, stay searchable, and stay legible for a long time.</p>\n<p>But the original launch was only the first chapter. This post is the update.</p>\n<p>Since those five sites went live, I have kept iterating — on <a href=\"https://jcrt.org\">jcrt.org</a> especially, but across the whole network. I split the JCRT repository in two, thanks to a conversation with <a href=\"https://brennan.day/\">Brennan</a>. I integrated <a href=\"https://www.zotero.org/\">Zotero</a> harvestability metadata across every site in the network, thanks to <a href=\"https://eve.gd/2026/06/23/making-blog-posts-harvestable-by-zotero-and-preserving-case-in-citation-fields/\">Martin Paul Eve</a>. I rolled out <a href=\"https://standard.site/\">standard.site</a> machine-readable discovery metadata. And I have a Version 3 redesign for The Whitestone Foundation in progress, plus a plan to work with <a href=\"https://kcommons.org/\">KC Commons</a> on persistent DOI numbers for the journals. The network keeps moving.</p>\n<p>If you spend time around <code>#11ty</code>, <code>#indieweb</code>, or <code>#webdev</code>, you know how often web conversations drift toward novelty. New frameworks, new pipelines, new dashboards, new layers, new reasons to rebuild the rebuild. I like new tools as much as the next person, but these sites needed something more grounded than that. They needed a durable publishing system built from plain files, boringly reliable URLs, and FOSS projects that respect the open web. They needed it at launch, and they still need it now.</p>\n<h2 id=\"why-i-launched-five-sites-at-once\" tabindex=\"-1\">Why I Launched Five Sites at Once <a class=\"header-anchor\" href=\"#why-i-launched-five-sites-at-once\">#</a></h2>\n<p>The sane version of this story would involve one migration at a time.</p>\n<p>Start with one site. Learn the lessons. Refactor the process. Move to the next. That is good project management advice, and I ignored it almost immediately.</p>\n<p>I went after five sites together because they already behaved like a network. They shared editors, institutional context, design history, hosting assumptions, and publishing problems. If I solved <a href=\"https://jcrt.org\">JCRT</a> in isolation, I would still have to solve journal structure for <a href=\"https://journal.thenewpolis.com\">journal.thenewpolis.com</a>, blog logic for <a href=\"https://thenewpolis.com\">thenewpolis.com</a>, organization pages for <a href=\"https://thewhitestonefoundation.org\">thewhitestonefoundation.org</a>, and a more expressive art-and-theory design language for <a href=\"https://esthesis.org\">esthesis.org</a>. The details differ, but the actual questions were the same:</p>\n<ul>\n<li>How should content live on disk?</li>\n<li>What metadata should be required?</li>\n<li>How do authors get represented across sites?</li>\n<li>What should URLs look like if we want them to stay useful?</li>\n<li>How do we make search work across a distributed publishing network?</li>\n<li>What does a low-maintenance editorial workflow actually look like?</li>\n</ul>\n<p>Once I saw that clearly, doing one site at a time started to look less careful and more misleading. I did not need five unrelated solutions. I needed one coherent publishing approach with room for variation.</p>\n<p>That is why I treated the project as <code>11tyx5</code>. Shared architecture, shared lessons, different visual identities, different editorial rhythms.</p>\n<h2 id=\"the-five-sites-five-different-jobs\" tabindex=\"-1\">The Five Sites, Five Different Jobs <a class=\"header-anchor\" href=\"#the-five-sites-five-different-jobs\">#</a></h2>\n<p>One reason this project stayed exciting, even when the build logs were rude, is that each site gave me a different problem to solve.</p>\n<p><a href=\"https://jcrt.org\">JCRT</a> was the heavyweight. It carried the deepest archive, the messiest historical layers, the most fragile old URLs, the heaviest PDF baggage, and the most academic pressure around citations, indexing, and long-term access. JCRT is where every bad decision from multiple web eras shows up in one place. That is not a complaint. That is what history looks like on the web. The <a href=\"https://github.com/The-Whitestone-Foundation/jcrt-v2\">JCRT GitHub repository</a> tells the same story in commit history: hundreds of cleanup passes, metadata fixes, search patches, and structural improvements layered over months of work.</p>\n<p><a href=\"https://journal.thenewpolis.com\">Journal of The New Polis</a> — tracked in its <a href=\"https://github.com/The-Whitestone-Foundation/journal.thenewpolis.com\">own repository</a> — gave me a cleaner laboratory for journal patterns: issue pages, article pages, contributor metadata, and a saner content tree. It let me test approaches that JCRT also needed, but without making every experiment carry the full weight of a late-1990s archive.</p>\n<p><a href=\"https://thenewpolis.com\">The New Polis</a>, now in its own <a href=\"https://github.com/The-Whitestone-Foundation/thenewpolis.com\">actively maintained repo</a>, worked as the faster-moving publication layer. Categories, essays, navigation, feeds, and editorial workflow all mattered there in a slightly different way. A journal can tolerate a little ceremonial structure. A magazine-style site has to move.</p>\n<p><a href=\"https://esthesis.org\">Esthesis</a>, housed in <a href=\"https://github.com/The-Whitestone-Foundation/esthesis-v2\">esthesis-v2</a>, was where I allowed more personality. I did not want a network of cloned sites with different logos pasted into the same template. Esthesis needed a stronger artistic and typographic voice while still living inside the same general publishing philosophy.</p>\n<p><a href=\"https://thewhitestonefoundation.org\">The Whitestone Foundation</a> — its <a href=\"https://github.com/The-Whitestone-Foundation/thewhitestonefoundation.org\">repository here</a> — needed the opposite energy. It had to feel clear, stable, and institutional without turning into a dead bureaucratic shell. It is the parent site. People should be able to understand what the organization is, what it publishes, and where to go next without fighting the interface. A new Version 3 of the site is coming — more on that below.</p>\n<p>That spread is exactly why doing all five together was productive. The differences forced better abstractions. The shared problems forced discipline.</p>\n<h2 id=\"minimal-computing-was-the-actual-method\" tabindex=\"-1\">Minimal Computing Was the Actual Method <a class=\"header-anchor\" href=\"#minimal-computing-was-the-actual-method\">#</a></h2>\n<p>I talk a lot about minimal computing because it has changed the way I think about web publishing. I do not mean &quot;minimal&quot; in the sense of trendy beige websites that mistake emptiness for elegance. I also do not mean some fake monkish purity where every JavaScript file is treated like a moral failure. I mean the working method described by the <a href=\"https://go-dh.github.io/mincomp/\">GO::DH Minimal Computing group</a> and especially the <a href=\"https://go-dh.github.io/mincomp/thoughts/2020/07/21/minimal-ontology/\">minimal computing ontology</a>: minimal design, minimal cost, minimal maintenance, minimal obsolescence, maximum justice.</p>\n<p>That framework fits academic publishing better than a lot of enterprise software ever will.</p>\n<p>A journal or cultural publication does not need a stack that looks impressive in a venture capital pitch deck. It needs to remain editable by future humans. It needs to survive staff changes, budget constraints, broken plugins, old citations, and that one weird article from 2004 whose HTML structure seems to have been assembled in a fever dream. Minimal computing starts from necessity. It asks what a project actually needs in order to endure.</p>\n<p>For these sites, that translated into a few practical commitments.</p>\n<p>Content should live in formats that are readable without specialized software. Markdown, YAML, JSON, and ordinary files win here.</p>\n<p>URLs should be predictable and stable. If someone cites an essay, I want a decent chance that the link will still work years from now. Human-readable archive paths such as <code>/archives/24.2/lastname/</code> are a feature, not a compromise.</p>\n<p>The publishing system should be understandable. I do not want a site that only functions when the original builder remembers the secret handshake.</p>\n<p>Migration paths should stay open. If I need to move a site later, I want content that can travel.</p>\n<p>Performance matters, but performance is not the whole story. A fast site that is impossible to maintain is just a different flavor of bad idea.</p>\n<p>Minimal computing also lines up with what I love about the <code>#indieweb</code>. Keep ownership close to the publisher. Prefer open formats. Avoid unnecessary dependency on platforms that can disappear, get acquired, or quietly decide your project is too small to matter. Use tools that respect the web as a publishing medium instead of treating websites like captive apps.</p>\n<h2 id=\"why-eleventy-now-build-awesome-was-the-right-tool\" tabindex=\"-1\">Why Eleventy (Now Build Awesome) Was the Right Tool <a class=\"header-anchor\" href=\"#why-eleventy-now-build-awesome-was-the-right-tool\">#</a></h2>\n<p><a href=\"https://www.11ty.dev/\">Eleventy</a> keeps proving itself to be the kind of tool I want to build with. It gives me enough power to handle complex publishing structures, but it does not force me into framework theater. I can use templates, data files, collections, filters, and build logic without pretending every site needs to become a JavaScript spectacle or a startup pitch.</p>\n<p>One quick note on naming: Eleventy recently rebranded as <a href=\"https://www.11ty.dev/\">Build Awesome</a>. The tool is the same, the community is the same, and the <code>#11ty</code> hashtag is still where you will find the people building with it. I use &quot;Eleventy&quot; throughout this post because most of this work predates the rename, but Build Awesome is what you should look for going forward.</p>\n<p>For this project, Eleventy solved a few problems at once.</p>\n<p>It let me build journals, blogs, author pages, archive indexes, organizational pages, feeds, and sitemaps inside one general model.</p>\n<p>It plays well with file-based content. That matters when you are moving years of articles out of HTML, SHTML, and WordPress into a structure that humans can still inspect and edit.</p>\n<p>It kept me close to the output. I like being able to reason about what the final HTML will look like.</p>\n<p>It also has one of the healthiest communities in web publishing. The <code>#11ty</code> crowd is unusually generous. I have learned a lot from official docs, community posts, issue threads, examples, and projects like <a href=\"https://11tybundle.dev/\">11ty Bundle</a>. A lot of FOSS survives because people are willing to explain things clearly to strangers. Eleventy has that energy, and when you are elbow-deep in a 1999 journal archive that matters.</p>\n<p>My stack is not ascetic for the sake of purity. I use what I need. On these sites that included Eleventy, Nunjucks, <a href=\"https://github.com/markdown-it/markdown-it\">markdown-it</a>, Luxon, <a href=\"https://pagefind.app/\">Pagefind</a>, a mix of utility scripts, and <a href=\"https://decapcms.org/\">Decap CMS</a> where a browser-based editorial layer made sense. The build got more honest too. In JCRT the main build now runs Eleventy with <code>SKIP_IMAGE_PROCESSING=1</code>, then runs Pagefind as a second step, and even caches the Pagefind index when the content signature has not changed. That is not glamorous. That is me refusing to waste minutes of my life for no reason.</p>\n<h2 id=\"doing-the-migration-work-instead-of-talking-about-it\" tabindex=\"-1\">Doing the Migration Work Instead of Talking About It <a class=\"header-anchor\" href=\"#doing-the-migration-work-instead-of-talking-about-it\">#</a></h2>\n<p>The glamorous version of web migration is a screenshot of an old site next to a new site. The real version is archaeology.</p>\n<p>JCRT in particular came from multiple eras of publishing logic. Some material was hand-built HTML. Some came through SHTML patterns. Some lived in WordPress. Some had inconsistent metadata. Some had weird formatting artifacts from Word. Some had PDFs that mattered a lot to the editorial history, whether or not PDFs are anyone's idea of mobile bliss.</p>\n<p>The first step was getting content out of legacy containers and into plain text workflows. Python scripts helped with the first passes on old HTML and SHTML. Regular expressions helped more than AI did, which is a sentence I have had reason to say a lot lately. Export tools for WordPress helped too, but never in a magical one-click way. There was still cleanup to do around footnotes, shortcodes, headings, links, front matter, and all the weird little historical decisions that only reveal themselves after export number four.</p>\n<p>That cleanup matters more than people admit. Migrations fail quietly when teams treat content as if it will automatically normalize itself once it enters a static site generator. It will not. Someone still has to decide what the canonical title is, which date belongs on the page, how authors should be named, where files belong, and whether the page should keep its old slug.</p>\n<p>A huge amount of this project was exactly that kind of stewardship work. Fix the text. Fix the metadata. Fix the paths. Fix the assumptions. Then do it again until the structure starts to feel boring in a good way.</p>\n<h2 id=\"separate-content-from-presentation-or-pay-later\" tabindex=\"-1\">Separate Content From Presentation, or Pay Later <a class=\"header-anchor\" href=\"#separate-content-from-presentation-or-pay-later\">#</a></h2>\n<p>One of the best decisions in this whole effort was keeping content and presentation more clearly separated.</p>\n<p>That sounds obvious, but old publishing systems have a way of blurring every boundary. Content lives half in the CMS, half in templates, half in custom fields, and somehow three halves later you have a site no one wants to touch.</p>\n<p>By moving toward plain content repositories and treating templates as templates, I could normalize front matter, clean media, and reason about data without destabilizing design every five minutes. That also made collaboration better. The more explicit the content model became, the easier it was for other people to help without needing telepathy.</p>\n<p>This mattered a lot for multi-author work. JCRT and the related sites needed better author handling, especially for essays and issues with several contributors. In <a href=\"https://github.com/The-Whitestone-Foundation/jcrt-v2\">jcrt-v2</a> I finally made peace with the fact that semicolons are policy. The <code>splitAuthors()</code> helper now treats <code>;</code> as canonical, normalizes stray <code>and</code>, <code>&amp;</code>, and Oxford-comma lists, slugs the names, and lets archive templates, <code>collections.authors</code>, author pages, and search all point at the same person without improvising. That sounds small until you have hundreds of pages and multiple editorial eras all spelling collaboration differently.</p>\n<p>That is the kind of improvement readers do notice, even if they never name it. Better author representation improves navigation, attribution, internal linking, search, and citation metadata.</p>\n<h2 id=\"search-metadata-and-the-case-for-boring-infrastructure\" tabindex=\"-1\">Search, Metadata, and the Case for Boring Infrastructure <a class=\"header-anchor\" href=\"#search-metadata-and-the-case-for-boring-infrastructure\">#</a></h2>\n<p>A lot of the exciting work on these sites was, frankly, boring infrastructure. I mean that as praise.</p>\n<p>Search had to improve. Metadata had to improve. Feeds had to improve. Sitemaps had to improve. Redirects had to improve. Those are not the flashy parts of a relaunch, but they are the difference between a site that looks updated and a site that actually works as a publication. They are also the difference between &quot;nice launch&quot; and &quot;Google Scholar can actually see the thing.&quot;</p>\n<p>With <a href=\"https://jcrt.org\">JCRT</a>, I spent a lot of time thinking about archives as archives. If a site has years of essays, issue structures, author pages, PDFs, and citations floating around the web, you cannot treat search or metadata as afterthoughts. That is how you end up with dead links, ghost pages, and the slow disappearance of your own publication history.</p>\n<p><a href=\"https://pagefind.app/\">Pagefind</a> became a big part of the answer. It gave me a way to provide fast, local search without handing the whole job off to a third-party service. For the broader site network, I also worked with shared data patterns like <code>allsites.json</code>, append-only canonical records, and cross-site search weighting so the publications could feel distinct while still participating in one ecosystem. On the Whitestone side, that ranking logic is intentionally opinionated: <code>jcrt.org/archives</code> outranks <code>journal.thenewpolis.com</code>, which outranks <code>jcrt.org/religioustheory</code>, which outranks the broader magazine and organizational sites. That is not favoritism. That is information architecture.</p>\n<p>I also became more serious about canonical data, structured front matter, and stable sitemap generation. The metadata stack now has to do real work: Dublin Core, JSON-LD, microformats, Open Graph, <code>citation_*</code> tags, and feed outputs that can travel. JCRT now exposes OAI-DC and DOAJ XML through sitemap endpoints, because journals live or die by whether machines can understand them as well as humans can. JCRT became the reference implementation here, and the <a href=\"https://github.com/The-Whitestone-Foundation/thewhitestonefoundation.org\">Whitestone Foundation</a>, <a href=\"https://github.com/The-Whitestone-Foundation/thenewpolis.com\">New Polis</a>, <a href=\"https://github.com/The-Whitestone-Foundation/journal.thenewpolis.com\">Journal of The New Polis</a>, and <a href=\"https://github.com/The-Whitestone-Foundation/esthesis-v2\">Esthesis</a> repos are being pulled toward that same baseline so the network behaves like a family instead of five cousins who all forgot each other's names.</p>\n<p>The same goes for redirects. The dream is not to have the trendiest site in 2026. The dream is for a citation from 2011 to still land on the right page in 2036. That is a web development problem. It is also an editorial ethics problem.</p>\n<h2 id=\"why-files-jcrt-org-matters-and-why-brennan-was-right\" tabindex=\"-1\">Why <code>files.jcrt.org</code> Matters — and Why Brennan Was Right <a class=\"header-anchor\" href=\"#why-files-jcrt-org-matters-and-why-brennan-was-right\">#</a></h2>\n<p>One of the more practical moves in the <a href=\"https://jcrt.org\">JCRT</a> rebuild was separating heavy file concerns from the main publication logic. Large PDFs and file collections create weird pressure inside a build pipeline. They slow things down, complicate Git history, and make a content repo feel heavier than it needs to be.</p>\n<p>I want to be honest about where this idea came from: <a href=\"https://brennan.day/\">Brennan</a>. When I was deep in build-time frustration — watching <a href=\"https://github.com/The-Whitestone-Foundation/jcrt-v2\">jcrt-v2</a> crawl through another full rebuild because of asset overhead — Brennan encouraged me to think clearly about the problem and suggested splitting the repository. His encouragement and support made a real difference when I was second-guessing whether the overhead was just something I had to live with. It was not. The solution was to separate concerns at the repo level.</p>\n<p>That meant spinning up <a href=\"https://github.com/The-Whitestone-Foundation/jcrt-files\">jcrt-files</a> as a dedicated CDN repository for <a href=\"https://files.jcrt.org\">files.jcrt.org</a>. The main site repo (<a href=\"https://github.com/The-Whitestone-Foundation/jcrt-v2\">jcrt-v2</a>) focuses entirely on the Eleventy build: templates, content, metadata, search, and output. The <a href=\"https://github.com/The-Whitestone-Foundation/jcrt-files\">jcrt-files</a> repo handles the heavy archive — PDFs, citation files, images, and downloadable assets that would otherwise bloat Git history and drag the build into the mud.</p>\n<p>The results were immediate:</p>\n<ul>\n<li>Reduced churn in the main site repository — commits are about content and templates, not binary files.</li>\n<li>Faster builds because Eleventy is not tripping over large archive assets.</li>\n<li>Clearer separation between editorial workflow and file archiving.</li>\n<li>A better mental model of what belongs where.</li>\n</ul>\n<p>In practice the implementation uses redirect bridges for <code>/images/*</code>, <code>/docs/*</code>, <code>/citations/*</code>, and archive PDFs so the public URLs stay clean and friendly while the heavy lifting moves out to <a href=\"https://files.jcrt.org\">files.jcrt.org</a>. From a reader's perspective nothing changed. From a maintainer's perspective the whole thing got dramatically saner.</p>\n<p>The <a href=\"https://github.com/The-Whitestone-Foundation/jcrt-files\">jcrt-files repo</a> has since become its own active workspace: tagging PDFs with proper metadata, adding canonical URLs, updating citation files, fixing Cloudflare Worker routing, and making sure the file delivery layer stays reliable. That is work that deserves its own space, and now it has one.</p>\n<p>PDF still matters in academic publishing. A clean separation means those files stay first-class without letting them drag the publishing site's build into the mud.</p>\n<h2 id=\"making-these-sites-harvestable-by-zotero\" tabindex=\"-1\">Making These Sites Harvestable by Zotero <a class=\"header-anchor\" href=\"#making-these-sites-harvestable-by-zotero\">#</a></h2>\n<p>One of the most rewarding recent additions across the whole Whitestone network is <a href=\"https://www.zotero.org/\">Zotero</a> harvestability.</p>\n<p>If you do academic work and you do not use Zotero, you should. It is a free, open-source reference manager that collects, organizes, and cites sources. The <a href=\"https://www.zotero.org/download/connectors\">Zotero browser connector</a> is particularly powerful: it can detect when you are on a supported web page and harvest citation metadata automatically. If the page has the right metadata, Zotero captures it as a &quot;Blog Post&quot; or &quot;Journal Article&quot; with proper author, date, title, and publication fields. If the page does not have it, Zotero captures it as a generic &quot;Web Page&quot; — less useful for researchers and far less useful for the journal.</p>\n<p>I owe the approach I used to <a href=\"https://eve.gd/2026/06/23/making-blog-posts-harvestable-by-zotero-and-preserving-case-in-citation-fields/\">Martin Paul Eve</a>, whose article &quot;Making Blog Posts Harvestable by Zotero and Preserving Case in Citation Fields&quot; laid out a clean RDFa-based method. Martin's guide explained exactly how to add the right combination of metadata to make pages register correctly in Zotero's type detection — and critically, how to preserve capitalization in citation fields so titles do not get mangled by citation software.</p>\n<p>The core of the implementation involves two things. First, adding a <code>prefix</code> attribute to the <code>&lt;html&gt;</code> element:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>html</span> <span class=\"token attr-name\">prefix</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>zotero: http://www.zotero.org/namespaces/export#<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span></code></pre>\n<p>Second, adding the right <code>&lt;meta&gt;</code> tags in the head: <code>zotero:itemType</code> to declare the content type, <code>citation_author</code>, <code>citation_publication_date</code>, <code>citation_public_url</code>, <code>prism.publicationName</code>, and <code>citation_language</code>. The key insight from Martin's article is what <em>not</em> to include: <code>citation_title</code> and <code>citation_journal_title</code> can force the wrong item type, so those are deliberately omitted on blog-style posts.</p>\n<p>I rolled this out across all five sites in the Whitestone network — <a href=\"https://jcrt.org\">JCRT</a>, <a href=\"https://thenewpolis.com\">The New Polis</a>, <a href=\"https://journal.thenewpolis.com\">Journal of The New Polis</a>, <a href=\"https://esthesis.org\">Esthesis</a>, and <a href=\"https://thewhitestonefoundation.org\">The Whitestone Foundation</a> — adapting the Eleventy pattern to fit each site's template structure. Each site's SEO partial now conditionally emits the Zotero block for post and article pages. The result: when a researcher visits any of these sites and clicks the Zotero connector, they get a properly typed citation with correct author, date, and publication metadata ready to drop into their reference manager.</p>\n<p>This kind of metadata work is invisible to most readers and invaluable to researchers. Academic publishing that wants to be taken seriously as a scholarly resource cannot afford to skip it.</p>\n<h2 id=\"adding-standard-site-discovery-metadata\" tabindex=\"-1\">Adding Standard.Site Discovery Metadata <a class=\"header-anchor\" href=\"#adding-standard-site-discovery-metadata\">#</a></h2>\n<p>Another significant addition across the Whitestone network is <a href=\"https://standard.site/\">standard.site</a> — a machine-readable discovery layer built on the <a href=\"https://atproto.com/\">AT Protocol</a>.</p>\n<p>Standard.site uses a <code>sequoia.json</code> configuration file and a <code>.well-known/site.standard.publication</code> endpoint to make a site's content machine-readable and discoverable through the AT Protocol network. For publishing sites, this means content can be discovered, syndicated, and interacted with through AT Protocol-native tools, including Bluesky. It is another piece of the &quot;open web by default&quot; philosophy — another way to make sure these publications do not depend on proprietary distribution channels for visibility.</p>\n<p>The Sequoia integration across <a href=\"https://github.com/The-Whitestone-Foundation/jcrt-v2\">jcrt-v2</a>, <a href=\"https://github.com/The-Whitestone-Foundation/thenewpolis.com\">thenewpolis.com</a>, <a href=\"https://github.com/The-Whitestone-Foundation/journal.thenewpolis.com\">journal.thenewpolis.com</a>, <a href=\"https://github.com/The-Whitestone-Foundation/esthesis-v2\">esthesis-v2</a>, and <a href=\"https://github.com/The-Whitestone-Foundation/thewhitestonefoundation.org\">thewhitestonefoundation.org</a> runs alongside the existing OAI-DC, JSON-LD, Open Graph, and feed infrastructure. It is not a replacement for any of that. It is an addition — one more doorway into the network's content for tools and readers that live on the open, federated web.</p>\n<p>This fits the broader pattern I keep returning to: no single discovery channel should be the only channel. Feeds. Sitemaps. JSON-LD. Zotero metadata. Standard.site. The more ways content can be found and cited by machines that respect open standards, the longer it will survive platform shifts.</p>\n<h2 id=\"the-cms-question-sveltia-looked-cool-decap-shipped\" tabindex=\"-1\">The CMS Question: Sveltia Looked Cool, Decap Shipped <a class=\"header-anchor\" href=\"#the-cms-question-sveltia-looked-cool-decap-shipped\">#</a></h2>\n<p>I spent real time trying to make the editorial layer more elegant. I was interested in Sveltia CMS. I am still interested in it. I also keep an eye on new 11ty-native CMS experiments because the idea of a tight, modern editorial interface is appealing.</p>\n<p>But interest and production readiness are not the same thing.</p>\n<p>For this network, <a href=\"https://decapcms.org/\">Decap CMS</a> won because it let the work move. The documentation was better for the workflows I needed. The Git-based model fit the architecture. Git Gateway and Google OAuth were easier to reason about than the stack I was trying to force around Cloudflare Worker auth experiments. Most important, it reduced editorial friction instead of adding another research project on top of an already complicated migration.</p>\n<p>At a certain point you stop asking which tool looks most future-forward and start asking which one lets editors publish reliably this week. That is a useful question. More web projects should ask it earlier.</p>\n<h2 id=\"foss-did-the-heavy-lifting\" tabindex=\"-1\">FOSS Did the Heavy Lifting <a class=\"header-anchor\" href=\"#foss-did-the-heavy-lifting\">#</a></h2>\n<p>One thing I want to say plainly is that this project exists because of FOSS.</p>\n<p><a href=\"https://www.11ty.dev/\">Eleventy</a> gave the publishing framework. <a href=\"https://github.com/markdown-it/markdown-it\">Markdown-it</a> handled parsing. <a href=\"https://pagefind.app/\">Pagefind</a> made local search viable. Python utilities helped with migration cleanup. Git and GitHub gave the history and collaboration layer. A long chain of maintainers, issue writers, example builders, theme makers, and docs writers made it possible for me to keep going when a build broke or a data model got slippery.</p>\n<p>The more invisible pieces mattered too: the scripts that generate Pagefind imports, the SEO partials that emit <code>citation_author</code> and <code>citation_pdf_url</code>, the Zotero metadata blocks, the feed plumbing that keeps RSS, Atom, JSON Feed, and <code>twtxt</code> in the same neighborhood, the build scripts that generate OAI-DC and DOAJ XML endpoints. All of it depends on open standards, open tools, and open communities.</p>\n<p>I do use hosted services when they solve real problems. I am not trying to cosplay purity politics on the internet. But the reason I trust this network more now is that the core publishing model is not locked inside a proprietary box. The content lives in files. The templates are inspectable. The output is HTML. If I need to move the whole thing later, I can.</p>\n<p>That is freedom in a very practical sense. It also fits the values of the publications themselves. Open-access journals and small independent magazines should not have to choose between visibility and technical self-respect. FOSS keeps that door open.</p>\n<h2 id=\"ongoing-work-what-the-git-history-actually-shows\" tabindex=\"-1\">Ongoing Work: What the Git History Actually Shows <a class=\"header-anchor\" href=\"#ongoing-work-what-the-git-history-actually-shows\">#</a></h2>\n<p>One of the things I appreciate about running these sites as open repositories is that the work is visible. The commit history on <a href=\"https://github.com/The-Whitestone-Foundation/jcrt-v2\">jcrt-v2</a> tells an honest story: hundreds of commits across mobile navigation improvements, favicon delivery fixes, Search Console error resolution, SEO patches, canonical URL cleanup, Duotrope badge integration with WebP conversion and a three-tier fallback chain, webfirewall configuration, and continuous Pagefind and metadata refinements.</p>\n<p>The <a href=\"https://github.com/The-Whitestone-Foundation/jcrt-files\">jcrt-files</a> repository has its own parallel history: PDF tagging, canonical URL updates, citation file improvements, Cloudflare Worker routing fixes, and the ongoing work of making decades of PDF archives reliably accessible. Archival access is maintenance work. It does not end.</p>\n<p><a href=\"https://github.com/The-Whitestone-Foundation/thewhitestonefoundation.org\">thewhitestonefoundation.org</a> saw significant infrastructure additions: the metasearch system that aggregates content from across the network, LLM SEO metadata for machine discoverability, the <code>allsites.json</code> data layer that lets the parent site understand the full network, and team page updates. <a href=\"https://github.com/The-Whitestone-Foundation/thenewpolis.com\">thenewpolis.com</a> received major SEO optimization passes, search improvements, author additions, and logo updates. <a href=\"https://github.com/The-Whitestone-Foundation/journal.thenewpolis.com\">journal.thenewpolis.com</a> and <a href=\"https://github.com/The-Whitestone-Foundation/esthesis-v2\">esthesis-v2</a> got the same Zotero and standard.site treatment plus SEO passes and schema improvements.</p>\n<p>Every one of those commits is a choice about what the publication deserves. I keep making those choices because the alternative — a site that slowly stops working and slowly becomes invisible — is not acceptable for publications this important.</p>\n<h2 id=\"the-whitestone-foundation-version-3-is-coming\" tabindex=\"-1\">The Whitestone Foundation Version 3 Is Coming <a class=\"header-anchor\" href=\"#the-whitestone-foundation-version-3-is-coming\">#</a></h2>\n<p>The current <a href=\"https://thewhitestonefoundation.org\">Whitestone Foundation site</a> served its purpose well, but Version 3 is in active development in the <a href=\"https://github.com/The-Whitestone-Foundation/thewhitestonefoundation-v3\">thewhitestonefoundation-v3 repository</a>.</p>\n<p>Version 3 builds on the same Eleventy and minimal computing foundation but with a significantly cleaner design and better representation of the organization's full mission. The parent site needs to make clear what <a href=\"https://thewhitestonefoundation.org\">Whitestone Foundation</a> is, which publications it supports, who the team is, and how to engage — all without fighting the interface.</p>\n<p>The organizational page is the anchor of the network. When it is strong and clear, readers navigate confidently to <a href=\"https://jcrt.org\">JCRT</a>, <a href=\"https://thenewpolis.com\">The New Polis</a>, <a href=\"https://journal.thenewpolis.com\">Journal of The New Polis</a>, and <a href=\"https://esthesis.org\">Esthesis</a>. When it is stale or confusing, everything downstream suffers. Version 3 is about making sure the anchor holds.</p>\n<h2 id=\"designing-for-long-life\" tabindex=\"-1\">Designing for Long Life <a class=\"header-anchor\" href=\"#designing-for-long-life\">#</a></h2>\n<p>The phrase I kept coming back to while building these sites was long life.</p>\n<p>I want these sites to age well.</p>\n<p>I want them to remain comprehensible to future collaborators.</p>\n<p>I want them to keep serving readers on ordinary devices with ordinary connections.</p>\n<p>I want them to survive shifting platform fashions.</p>\n<p>I want them to preserve the publication record instead of treating archives like attic clutter.</p>\n<p>That goal affects design choices, content modeling, and infrastructure choices all at once. It is why I care about plain text, low-friction builds, stable URLs, HTML-first publishing, search that does not depend on a cloud black box, and keeping complexity where complexity earns its keep.</p>\n<p>It also affects aesthetics. I do not think minimal computing means making every site look stripped down or timid. <a href=\"https://esthesis.org\">esthesis.org</a> should still feel alive. <a href=\"https://thenewpolis.com\">thenewpolis.com</a> should still feel like a publication with momentum. <a href=\"https://thewhitestonefoundation.org\">thewhitestonefoundation.org</a> should still feel coherent and welcoming. Long-life design is not anti-style. It just asks style to cooperate with maintenance, readability, and public access.</p>\n<h2 id=\"what-this-work-has-taught-me\" tabindex=\"-1\">What This Work Has Taught Me <a class=\"header-anchor\" href=\"#what-this-work-has-taught-me\">#</a></h2>\n<p>The biggest lesson from <code>11tyx5</code> is that shared infrastructure can create momentum instead of flattening identity.</p>\n<p>All five sites now make more sense to me as a group and as individual publications. They have stronger boundaries. They also have a better common language. The Zotero integration, standard.site metadata, OAI-DC feeds, and shared Pagefind infrastructure all reinforce that language. When I add something to <a href=\"https://github.com/The-Whitestone-Foundation/jcrt-v2\">jcrt-v2</a> that works, I know where else it belongs.</p>\n<p>I learned that migration work gets easier once you stop chasing perfect tools and start building dependable habits.</p>\n<p>I learned, again, that plain files are a gift.</p>\n<p>I learned that archives demand respect — and that respecting them means continuing to work on them, not just migrating them once and moving on.</p>\n<p>I learned that build performance matters, and sometimes the right answer is architectural. Splitting the repo was not a hack. It was a clarity move.</p>\n<p>I learned that metadata is audience. When the metadata is right, researchers find the work. When it is wrong, the work disappears behind a search result that says &quot;Web Page&quot; instead of &quot;Journal Article.&quot;</p>\n<p>I also learned that if you are going to do a weirdly ambitious web project, it helps to work with people who can tell you when your repo habits have become nonsense — and who will encourage you when you are worried about build times at midnight.</p>\n<h2 id=\"thanks-and-what-comes-next\" tabindex=\"-1\">Thanks, and What Comes Next <a class=\"header-anchor\" href=\"#thanks-and-what-comes-next\">#</a></h2>\n<p>I owe a lot of this work to collaborators and communities.</p>\n<p>Thanks to <a href=\"https://brennan.day/\">Brennan</a> for encouragement, support, and the idea of splitting the JCRT repository into a site repo and a separate assets CDN. That conversation made a real difference. When I was frustrated with build times and second-guessing whether the architecture was workable, Brennan helped me see the solution clearly. The <a href=\"https://github.com/The-Whitestone-Foundation/jcrt-files\">jcrt-files</a> repository exists because of that conversation.</p>\n<p>Thanks to <a href=\"https://eve.gd/\">Martin Paul Eve</a> for his article <a href=\"https://eve.gd/2026/06/23/making-blog-posts-harvestable-by-zotero-and-preserving-case-in-citation-fields/\">&quot;Making Blog Posts Harvestable by Zotero and Preserving Case in Citation Fields&quot;</a>. That post gave me exactly what I needed to roll out Zotero harvestability across the entire Whitestone network. Martin's clear explanation of the RDFa prefix approach and the key tags required saved me a significant amount of reverse engineering. I am grateful for it, and I am grateful that he published it openly for anyone trying to do the same work.</p>\n<p>Thanks to the editors, authors, and organizers who trusted the process while the infrastructure was changing under their feet. Thanks to the broader <code>#11ty</code>, <code>#indieweb</code>, and FOSS communities for continuing to prove that the open web still has builders who care about durability as much as novelty.</p>\n<p>There is still more to do. There always is. <a href=\"https://jcrt.org\">JCRT</a> in particular will keep receiving archive, metadata, and performance work because a site that old is never really finished. The Version 3 redesign of <a href=\"https://thewhitestonefoundation.org\">The Whitestone Foundation</a> is in progress. And the next major milestone I am working toward is DOI number integration — working with <a href=\"https://kcommons.org/\">KC Commons</a> to assign persistent Digital Object Identifiers to journal content across the network. DOIs matter for academic citation permanence and indexing in places like CrossRef, Google Scholar, and JSTOR. Getting them right is the kind of infrastructure work that academic publishing depends on, and it is the logical next step for a network that already has clean URLs, structured metadata, Zotero harvestability, and OAI-DC feeds in place.</p>\n<p>The important shift has already happened. These publications are no longer trapped in a pile of inherited workflows. They have a modern stack, portable content, better search, stronger metadata, Zotero integration, AT Protocol discoverability, and a much better chance of still being online, legible, and useful years from now.</p>\n<p>That is the part I am proud of.</p>\n<p>Not that I launched five sites at once, though I am proud of that too.</p>\n<p>I am proud that the result is more durable, more open, and more alive. And I keep making it better.</p>\n",
			"date_published": "2026-06-28T17:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2026-06-29-embodied-wisdom/",
			"url": "https://www.adamdjbrett.com/blog/2026-06-29-embodied-wisdom/",
			"title": "Book Review: *Embodied Wisdom* by W.J. de Kock",
			"content_html": "<p><a href=\"https://www.amazon.com/Embodied-Wisdom-Professional-Practice-University-ebook/dp/B0FMY2K89D/?\"><em>Embodied Wisdom</em></a> is a book-length argument for an interdisciplinary, praxis-based advanced course of study, written by Dr. W. J. de Kock, director of Eastern University’s PhD in Professional Practice and Professor of Practical Theology at Palmer Theological Seminary. Framed by forewords from the university’s provost and the seminary’s dean, it reads less like a conventional monograph and more like a founding document: part curriculum rationale, part theological treatise, and part recruiting letter to the reader it imagines—a seasoned professional who has never quite had academic language for what they already know.</p>\n<p>Scholar-Practitioners, the de Kock argues, has been underserved by traditional doctoral education. A pastor, engineer, or nonprofit director who has spent twenty years solving real problems has produced something de Kock calls an &quot;artifact&quot; — a strategy document, a curriculum, a policy, a body of casework — that most PhD programs would treat as résumé material, not as a text worth scholarly attention. <em>Embodied Wisdom</em> inverts that. It treats the artifact as a primary source, the practitioner's accumulated judgment as a form of knowledge in its own right, and the doctorate as a structured way of excavating and articulating what that judgment already contains.</p>\n<p>The book is organized around the program's five-phase structure: Describe and Define, Gather and Interpret, Identify and Ideate, Create and Evaluate, and Compose and Share. Each phase maps onto a stage of an action-research cycle — examine the artifact, situate it in the literature, generate new theoretical insight, build something new from that insight, then write the dissertation that ties the cycle together. De Kock is explicit that this isn't a novel invention so much as a formalization of a rhythm professionals already use without naming it: act, reflect, refine, repeat.</p>\n<p>What keeps the book from reading as motivational management theory is its intellectual scaffolding. De Kock draws on Michael Polanyi's account of tacit knowledge, Esther Lightcap Meek's covenant epistemology, Martin Buber's I-Thou, and Donald Schön's reflection-in-action to argue that practitioners often know more than they can say, and that naming it is itself a scholarly act. These aren't name-dropped for credibility. They do real work in the argument: Polanyi explains why a carpenter knows wood before naming its grain; Schön explains how that knowledge gets refined through cycles of action and retrospection; Meek and Buber supply the relational frame that lets de Kock treat knowing as something closer to encounter than extraction.</p>\n<p>The theology runs through all of it, and it's not incidental. De Kock frames professional competence as vocation — work as a considered response to a calling rather than a credential to be earned. The forewords lean hard into this: the provost writes about God's call extending into &quot;corporate boardrooms, engineering labs, classrooms, and creative studios,&quot; and the dean describes candidates as people who sense &quot;something sacred stirring beneath quarterly reports.&quot; Readers outside a faith-based institution, or simply allergic to that register, will find long stretches of the book reading more like a sermon than a curriculum guide. That's not a flaw exactly — it's an honest signal of what the program is and who built it — but it does mean the book is doing double duty as both program description and theological argument, and the second job sometimes crowds out the first.</p>\n<p>The prose itself tends toward the expansive. Sentences pile clause on clause, metaphors stack (DNA strands, sacred archaeology, spiral dance), and the second-person address — &quot;you bring more to this academic table than you realize&quot; — reads as recruitment copy as often as exposition. That's worth knowing going in: this is a book meant to persuade a prospective candidate they belong, not a neutral handbook for evaluating whether they do.</p>\n<p>Where the book earns its keep is in the structural argument underneath the language. Treating professional output as a legitimate object of scholarly inquiry, and treating the practitioner's tacit judgment as something a doctorate can help articulate rather than discard, is a genuinely useful corrective for a certain kind of student — someone with twenty years of expertise and no academic home for it. The five-phase cycle gives that idea an actual shape, not just a slogan, and the theoretical apparatus behind it (Polanyi, Schön, Meek) gives it real philosophical weight.</p>\n<p>Who should read it: prospective candidates for practice-based doctorates who want to understand the thinking behind the model before they apply, and program designers or supervisors building something similar who want a theological as well as methodological case for it. General readers curious about alternatives to the standard research PhD will get something out of the first chapter and the forewords, but should expect the theological framing to be load-bearing throughout, not a side note.</p>\n<p>It's an invitation to a doctoral education that seeks to integrate theory and praxis, building on the work the Scholar-Practitioner are already doing. It is a creative and careful invitation.</p>\n",
			"date_published": "2026-06-28T14:45:34Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2026-06-29-on-being-in-the-middle/",
			"url": "https://www.adamdjbrett.com/blog/2026-06-29-on-being-in-the-middle/",
			"title": "Book Review: *On Being in the Middle* by W.J. de Kock",
			"content_html": "<p><a href=\"https://wipfandstock.com/9781666706185/on-being-in-the-middle/\"><em>On Being in the Middle: Doing Theology in the Face of Uncertainty</em> (Wipf &amp; Stock, 2024)</a> is W.J. de Kock's account of a life spent between things: between a middle child and his siblings, between an Afrikaner identity and the violence that identity justified, between the answers his theological training gave him and the questions his students forced him to ask instead. De Kock directs Eastern University's PhD in Professional Practice and wrote the more recent <em>Embodied Wisdom</em> as a vision document for that program. This book is the personal and theological ground that program stands on, and it reads nothing like a curriculum guide.</p>\n<p>The book splits into two parts. Part A, &quot;Alone in the Middle,&quot; is memoir and history. Part B, &quot;With God in the Middle,&quot; is constructive theology. A short Methodological Postscript ties the two together. De Kock frames the whole project through liminality — Arnold van Gennep and Victor Turner's anthropological term for the threshold state between one identity and the next — and reads it back into Genesis, Exodus, and Ecclesiastes as a basic condition of life with God.</p>\n<p>Part A is where the book earns its weight. De Kock traces the theological roots of Afrikaner nationalism: the Great Trek, the 1838 covenant vow after the Battle of Blood River, the nationalist poetry of &quot;Totius&quot; Du Toit, the all-Afrikaner cabinet Daniel Malan formed in 1948. He's not writing this as outside history. He grew up inside the theology that justified apartheid, absorbed it the way Michael Polanyi says we absorb any tacit knowledge — before we can name it, let alone question it. The turn comes in 1979, when a meeting with Archbishop Desmond Tutu cracks that formation open. The following year he witnesses a police officer assault and racially abuse a Black driver on the street, an episode he doesn't soften or summarize away. From there the book follows him out of complicity and into ministry on the Cape Flats, teaching at an unaccredited, racially mixed Bible college under a mentor named Allen Jansen, in the years when that kind of classroom was itself a quiet act of defiance.</p>\n<p>This material is rawer and more specific than anything in <em>Embodied Wisdom</em>, and it changes what &quot;liminality&quot; means in practice. It stops being an abstraction and becomes the literal space de Kock occupied: between the theology he was taught and the one he came to live by, between a white South African's safety and the violence done in his community's name.</p>\n<p>Part B shifts register. The chapter &quot;Trinity&quot; works through Jürgen Moltmann's theology of the crucified God — God present in suffering rather than removed from it — using Moltmann's own captivity as a German prisoner of war and Elie Wiesel's account of a child's execution to ground the claim. &quot;Indwelling&quot; argues past the standard choice between materialism and dualism toward a vision of God and matter as mutually indwelling, leaning on Pitirim Sorokin's sociology of cultural cycles to make the case. Later chapters — Belonging, Conversing, Loving, Serving, Growing — keep building outward from there. The argument is serious, but the prose settles into the same expansive, second-person, slightly devotional register that marks de Kock's other book. Long stretches read like an extended reflection delivered from a pulpit rather than a tightly argued claim, and the literature surveys (Sorokin gets several pages) can slow the book down without clearly paying off the slower pace.</p>\n<p>The Methodological Postscript is the strongest piece of connective tissue in the book. De Kock draws on Paulo Freire's idea of conscientization — the process by which people start questioning the answers handed to them by those in power — to explain his own shift from a teacher who dispensed settled doctrine to one who taught his students to ask harder questions instead. He's honest that this wasn't a clean conversion: he names the discomfort of realizing his own theological confidence may have done some of the damage he was trying to undo. That admission, and the specificity behind it, is worth more than most of the abstract argument in Part B.</p>\n<p>The unevenness is real. Part A has the discipline of memoir: concrete events, named people, consequences. Part B has the discipline of a sermon: it circles, accumulates, and trusts repetition to do work that tighter argument would do faster. Readers who come for the first half's history may find the second half diffuse by comparison.</p>\n<p>Who should read it: anyone interested in the theological roots of apartheid and one insider's account of growing out of them, practical theologians working with liminality as a category, and readers of <em>Embodied Wisdom</em> who want the personal history behind that book's method. Readers looking for a rigorously argued systematic theology should expect long devotional stretches alongside the argument, not in place of it. The first half alone is reason enough to pick the book up.</p>\n",
			"date_published": "2026-06-28T14:15:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2026-06-26-out-of-my-mind/",
			"url": "https://www.adamdjbrett.com/blog/2026-06-26-out-of-my-mind/",
			"title": "Book Review: W. J. de Kock&#39;s *Out of My Mind*",
			"content_html": "<p>de Kock, W. J. <em>Out of My Mind: Following the Trajectory of God's Regenerative Story</em>. Foreword by Tony Campolo. Eugene, OR: Wipf &amp; Stock, 2014. ISBN 9781625642322.</p>\n<hr>\n<p>One Sunday afternoon in late-1970s Johannesburg, a young Afrikaner university student watched a former classmate, now a plainclothes policeman, force a Black motorist's car off the road and drag him through the shattered windshield to beat him. When real police arrived, they arrested not the assailant but the victim, sent off with a racial slur ringing in his ears. That roadside scene, witnessed from his own front lawn, is where de Kock locates the first crack in an inherited theological world — and where his hybrid of memoir and constructive theology, <em>Out of My Mind</em>, begins.</p>\n<p>De Kock, now professor of practical theology at Palmer Theological Seminary and founding director of Openseminary, has written something rarer than a confessional memoir or a systematic treatise: a book that uses his own unraveling as an Afrikaner Pentecostal reared inside apartheid theology to test a constructive proposal he calls &quot;regenerative theology.&quot; Twelve chapters, each riffing on the book's title (Splintered Mind, Anxious Minds, God Minding, Trajectory Minding, Maturing Mind), trace the arc from a childhood faith that cast Afrikaners as Israel reborn on African soil, through a &quot;dark night of the soul&quot; precipitated by a Desmond Tutu lecture and a hard season of seminary poverty, to a mature theological method built on four moving parts: sacred questions arising from lived context, the regenerative Story of Scripture, beliefs transformed through following Jesus in the liminal space between &quot;already&quot; and &quot;not yet,&quot; and purposeful action.</p>\n<p>What keeps this from becoming one more deconstruction narrative is de Kock's insistence on real constructive work. His central image, the &quot;trajectory,&quot; tracks how Scripture itself bends: a text that tolerates slavery and patriarchy in Genesis curves, by Paul, toward what de Kock quotes as Christ's vision that &quot;there can be no division into Jew and non-Jew, slave and free, male and female. Among us you are all equal.&quot; He treats that bending as a compass heading rather than a finished map, asking the church to keep following it rather than stopping at any single waypoint. His treatment of the Trinity does similar work: drawing on Miroslav Volf and Thomas Torrance's accounts of <em>perichoresis</em> — the mutual indwelling of Father, Son, and Spirit — he argues that a Godhead built on reciprocity rather than hierarchy cannot honestly authorize the one-upmanship of apartheid, patriarchy, or clerical power. The African concept of <em>ubuntu</em>, &quot;I am because we are,&quot; gives that Trinitarian vision its social shape.</p>\n<p>The writing shows real journalistic instinct. De Kock knows how to open a chapter on a scene — a London Underground warning to &quot;mind the gap,&quot; his daughter's invented word &quot;strugglety,&quot; a night janitorial shift spent ignoring a Ugandan classmate out of ingrained racial prejudice — and let the theology grow out of the image. He moves between <em>The Matrix</em> and the Cappadocian Fathers, between Nietzsche's Übermensch and Tutu's quiet authority, without the seams showing. Tony Campolo's foreword rightly names this fusion as the book's power: de Kock never abandons theological discipline, he simply insists that reflection start from a body on a roadside rather than a doctrine in a book.</p>\n<p>Endorsers Alan Hirsch, Brian McLaren, and John Christopher Thomas call this narrative theology at its best, and the praise holds up under scrutiny rather than dissolving into blurb inflation. Underneath the storytelling runs a working bibliography — James Fowler on faith development, John Westerhoff on searching faith, Charles Gerkin on practical theology, Georg Vicedom on the missio Dei — that keeps the case academically honest.</p>\n<p>The theological memoir is generous in scope and honest about its own unfinished edges — de Kock calls even his own conclusions &quot;a resting place along the way,&quot; not a destination. It serves as an important constructive theological waypoint between <em>ethnoautobiography</em> as method and theological anthropology. Having been introduced in 2023 by Lily Mendoza and James W. Perkinson to <em>Ethnoautobiography</em>By Jürgen Werner Kremer, Robert Jackson-Paton, R. Jackson-Paton, as I re-read <em>Out of my mind</em> I see a powerful and fruitful conversation and dialogue for constructive theologians like De Kock to have with Indigenous studies and antropology around bringing eithnoautobiography into the classroom and theological reflection. I see<em>Out of My Mind</em> as a kindred spirit and fellow traveler with the methodology of ethnoautobiography and providing part of a roadmap for doing theological memoir while reflecting on race/ethnicity, gender, class, and identity.</p>\n<p><em>Out of My Mind</em> belongs on syllabi for practical, contextual, and postcolonial theology, but it rewards any reader curious how one conscience metabolized a nation's theological crimes into something more durable than guilt. McLaren's blurb says the book carries a message &quot;especially . . . for today's Christians around the world.&quot; More than a decade after publication, that claim has only sharpened: a theology built to mind the gap between belief and practice has rarely felt more necessary.</p>\n",
			"date_published": "2026-06-26T17:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2026-06-25-book-review-grant-writing/",
			"url": "https://www.adamdjbrett.com/blog/2026-06-25-book-review-grant-writing/",
			"title": "Book Review: *The Grant Writing Guide: A Road Map for Scholars* by Betty S. Lai",
			"content_html": "<p>Betty S. Lai’s <em>The Grant Writing Guide: A Road Map for Scholars</em> is a practical, generous, and clear guide to one of the most stressful parts of academic and nonprofit life, grant writing. The book is written for scholars across disciplines who need to turn research ideas into fundable proposals. But its real subject is broader than grant writing. Lai is teaching scholars how to move from uncertainty to action. She approaches grant writing as a learnable craft, none that is creative much like the rest of ones writing.</p>\n<hr>\n<h1 id=\"book-review-the-grant-writing-guide-a-road-map-for-scholars-by-betty-s-lai\" tabindex=\"-1\">Book Review: <em>The Grant Writing Guide: A Road Map for Scholars</em> by Betty S. Lai <a class=\"header-anchor\" href=\"#book-review-the-grant-writing-guide-a-road-map-for-scholars-by-betty-s-lai\">#</a></h1>\n<p>Betty S. Lai. <em>The Grant Writing Guide: A Road Map for Scholars</em>. Princeton University Press, 2023. Skills for Scholars series. ISBN: 9780691231877.</p>\n<p>Betty S. Lai's <em>The Grant Writing Guide</em> does something most grant writing advice fails to do: it treats the whole enterprise as a learnable craft rather than a mysterious talent. Written for scholars across disciplines, the book is nominally about funding proposals. But its real subject is how to move from paralysis to action — and how to do that without losing your intellectual identity in the process.</p>\n<p>Grants shape academic and nonprofit life in ways that go beyond money. They fund research time, students, travel, equipment, community partnerships, and new projects. They also shape who gets heard. Lai opens from this equity problem. Funding systems are not neutral. Men, white investigators, older scholars, and researchers at already well-resourced institutions tend to receive more support. She doesn't pretend individual skill can fix structural bias. But she focuses on what scholars can control: learning the hidden curriculum well enough to submit stronger proposals, more often, with less fear.</p>\n<p>The book's organization is one of its best features. The table of contents functions as a workflow. Lai divides grant writing into four tasks: develop an idea, target a funder, draft the grant, and polish the grant. Each contains short chapters that move readers through a concrete process. Task A covers finding available grants, generating ideas from your values, aligning them with career goals, and building a one-page pitch. Task B focuses on talking to program officers, studying sample grants, understanding a grant's anatomy, and writing to evaluation criteria. Task C takes on the literature review, research plan, structure, and figures. Task D handles style, the &quot;Pick Me Factor,&quot; and critique. The book closes with a checklist, glossary, FAQ, and index.</p>\n<p>This structure is part of the argument. Grant writing isn't one big terrifying act — it's a sequence of smaller decisions. Find opportunities. Name your values. Choose a funder. Study samples. Write a one-pager. Build a timeline. Draft clearly. Revise. Submit. Each step is still work, but the work becomes visible. That visibility is the book's most important contribution.</p>\n<p><strong>The hidden curriculum.</strong> Lai uses a memorable analogy: when she moved to New England, she prepared for winter but didn't know she needed wool socks. No one mentioned it because insiders assumed it was obvious. Grant writing works the same way. Scholars are told to apply for funding but rarely taught how to find the right programs, contact program officers, read evaluation criteria, or use funded samples as models. This book is a set of wool socks. It makes insider knowledge explicit.</p>\n<p><strong>Values before funders.</strong> Lai doesn't start with what funders want. She asks scholars to clarify their own &quot;North Star&quot; first. This matters because grant writing can turn reactive fast — you chase the call, bend your project, and end up with a proposal that no longer looks like yours. Lai teaches you to understand your intellectual values and then align them with funders, career goals, and feasible scope. It's a humane approach. It helps you write grants without losing your scholarly identity.</p>\n<p><strong>Fit over hope.</strong> A strong proposal doesn't ask reviewers to spot the connection on their own. You target a funder. You talk to a program officer when possible. You read funded samples. You write directly to the mission and evaluation criteria. This reframe — grants as acts of communication within a specific institutional setting, not as tests of personal worth — is one of the most useful shifts the book offers, especially for early-career scholars.</p>\n<p>The drafting chapters are the book's strongest. On literature reviews, Lai is clear: your grant is not the place to show everything you know. Its purpose is to give reviewers the information they need to evaluate your work — nothing more. Scholars are trained to demonstrate mastery and nuance. Grant reviewers read many proposals under time pressure and need clarity. Lai's distinction between writing as a peer and writing as a guide cuts right to it. Don't wander with the reviewer through your process of discovery. Lead them.</p>\n<p>The research plan chapter is equally useful. Lai describes the plan as the substance and heart of the grant — it needs to show what you'll do, why those methods fit, how the work will unfold, who will do it, what risks exist, and why the project can succeed. She pushes writers to answer basic questions: who, how many, what, when, where, and how. This works across fields because it forces specificity. Reviewers shouldn't have to guess what you'll actually do with the money.</p>\n<p>On structure, Lai's phrase &quot;consistency is comforting&quot; captures a central truth. Reviewers track an argument quickly. When aims, sections, headings, figures, timelines, and outcomes all use consistent language, the proposal feels organized. When terms shift or key ideas hide in dense paragraphs, the reviewer works too hard. Structure isn't cosmetic. It's part of persuasion.</p>\n<p>The polishing section is where Lai's voice gets most direct. Short sentences. Clear terms. Active structure. No jargon, no performative complexity. This isn't dumbing down — it's respect for the reviewer. And it reflects the book's larger ethics: if funding systems are already unequal, obscurity makes them harder to enter. Clear writing expands access.</p>\n<p>The &quot;Pick Me Factor&quot; chapter asks scholars to explain why they, their team, and their environment can carry out the work. This can feel uncomfortable for people trained to avoid self-promotion. Lai reframes it as evidence. The goal isn't to boast. It's to make confidence easy for reviewers to see.</p>\n<p>The critique chapter is one of the most realistic parts of the book. Lai urges readers to seek hard, honest feedback before submission — not validation. Grant writing isn't a solitary act. Strong proposals are built through pressure-testing.</p>\n<p>The conclusion is honest about rejection. Most grants aren't funded the first time. But rejection isn't proof that the idea lacks value. Lai asks readers to build a practice that can survive it: submit, get feedback, revise, resubmit. This shifts the emotional center of grant writing. The point isn't to protect yourself from rejection by never submitting.</p>\n<p><em>The Grant Writing Guide</em> is especially valuable for graduate students, postdocs, early-career faculty, and scholars without strong mentoring networks. Senior scholars who mentor others will benefit too. The book belongs in graduate seminars, faculty writing groups, research development offices, and professional development programs. It's practical enough to use while drafting and reflective enough to change how you think about funding.</p>\n<p>Lai knows the system is unequal. She knows rejection hurts and grants take time. But she insists scholars deserve access to the tools that make participation possible. That's why the book works. It's not only a guide to winning grants — it's a guide to entering the conversation with more confidence, clarity, and purpose.</p>\n",
			"date_published": "2026-06-25T17:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/zotero-harvestable-blog-posts/",
			"url": "https://www.adamdjbrett.com/blog/zotero-harvestable-blog-posts/",
			"title": "Making Blogs Easier to Cite with Zotero",
			"content_html": "<p>I spent part of this week making my sites easier to cite with Zotero. The spark was Martin Paul Eve’s post, “<a href=\"https://doi.org/10.59348/vrt01-f3b49\">Making blog posts harvestable by Zotero and preserving case in citation fields</a>.” After reading this post I imemdiately how to try and impliment it!.</p>\n<p>I implemented the Zotero pattern across several sites I maintain: <a href=\"https://adamdjbrett.com\">adamdjbrett.com</a>, <a href=\"https://jcrt.org\">jcrt.org</a>, <a href=\"https://thewhitestonefoundation.org\">thewhitestonefoundation.org</a>, <a href=\"https://journal.thenewpolis.com\">journal.thenewpolis.com</a>, <a href=\"https://thenewpolis.com\">thenewpolis.com</a>, and <a href=\"https://esthesis.org\">esthesis.org</a>. These sites do not all do the same job. Some are personal writing spaces. Some are journals. Some are publication archives. Some are organizational pages. So the implementation had to preserve those differences instead of forcing one metadata pattern everywhere.</p>\n<p>The core lesson from Eve’s post is simple: if you want Zotero to import a blog post as a Blog Post, tell Zotero directly. Do not rely only on Open Graph, Dublin Core, or a vague genre hint. The key tag is:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">property</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>zotero:itemType<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>blogPost<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span></code></pre>\n<p>But that tag only works if the page declares the Zotero RDFa namespace. That means adding a prefix to the <code>html</code> element, usually alongside Dublin Core and PRISM prefixes:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>html</span> <span class=\"token attr-name\">lang</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>en<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">prefix</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>zotero: http://www.zotero.org/namespaces/export# dc: http://purl.org/dc/elements/1.1/ prism: http://prismstandard.org/namespaces/basic/2.0/<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span></code></pre>\n<p>This is the small piece I had been missing. Metadata tags are not magic. They need to be expressed in a form the translator understands.</p>\n<p>The second lesson is more subtle: avoid the wrong scholarly tags on blog posts. Eve notes that <code>citation_title</code> and <code>citation_journal_title</code> can push Zotero toward a journal-article interpretation. That is useful for actual journal articles, but not for blog posts. For blog posts, I used <code>og:title</code> and <code>dc:title</code> for the title, plus <code>citation_author</code>, <code>citation_publication_date</code>, <code>citation_public_url</code>, and <code>citation_language</code> for the rest of the citation data.</p>\n<p>For blog posts, the pattern became:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">property</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>zotero:itemType<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>blogPost<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">property</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>dc:title<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>Post Title<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">property</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>dc:creator<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>Author Name<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">property</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>dc:date<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>2026-06-25<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">property</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>dc:identifier<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://example.org/post/<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>citation_author<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>Author Name<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>citation_publication_date<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>2026-06-25<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>citation_public_url<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>https://example.org/post/<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>citation_language<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>en<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>prism.genre<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>blogentry<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span>\n<span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>prism.publicationName<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>Site Name<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span></code></pre>\n<p>For journal articles, I kept the journal metadata. That means <code>citation_title</code>, <code>citation_journal_title</code>, <code>citation_issn</code>, volume, issue, page range, publication date, full-text HTML URL, and PDF URL where available. This distinction was important on JCRT and The New Polis Journal. A journal article should remain a journal article. A blog post should import as a blog post. Zotero should not have to guess.</p>\n<p>The third lesson is about case. CSL processors sometimes title-case fields in ways that damage names. Eve’s example is <code>eve.gd: Martin Paul Eve</code>, which became <code>Eve.Gd: Martin Paul Eve</code>. The fix is CSL’s <code>nocase</code> span:</p>\n<pre class=\"language-html\" tabindex=\"0\"><code class=\"language-html\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>meta</span> <span class=\"token attr-name\">name</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span>prism.publicationName<span class=\"token punctuation\">\"</span></span> <span class=\"token attr-name\">content</span><span class=\"token attr-value\"><span class=\"token punctuation attr-equals\">=</span><span class=\"token punctuation\">\"</span><span class=\"token entity named-entity\" title=\"&lt;\">&amp;lt;</span>span class=<span class=\"token entity named-entity\" title=\"&quot;\">&amp;quot;</span>nocase<span class=\"token entity named-entity\" title=\"&quot;\">&amp;quot;</span><span class=\"token entity named-entity\" title=\"&gt;\">&amp;gt;</span>eve.gd<span class=\"token entity named-entity\" title=\"&lt;\">&amp;lt;</span>/span<span class=\"token entity named-entity\" title=\"&gt;\">&amp;gt;</span>: Martin Paul Eve<span class=\"token punctuation\">\"</span></span><span class=\"token punctuation\">></span></span></code></pre>\n<p>I am able to partilially this working with the Firefox Zotero plugin but I am unable to get this working with the Chrome Zotero plugin. Using the chrome plugin here is what I get in Zotero:</p>\n<p><strong>Firefox</strong></p>\n<pre class=\"language-YAML\" tabindex=\"0\"><code class=\"language-YAML\">Blog Title: \"<span class=\"nocase\">eve.gd</span>: Martin Paul Eve\"\nDate: 2026/05/21\nDOI: 10.59348/2thwp-wm553\n</code></pre>\n<p><strong>Chrome</strong></p>\n<pre class=\"language-YAML\" tabindex=\"0\"><code class=\"language-YAML\">Blog Title: \"<span class=\"nocase\">eve.gd</span>: Martin Paul Eve\"\nDate: 00:00:00 +0100\nDOI: empty</code></pre>\n<p>Both the Firefox and Chrome extensions leave the span class in. Firefox successfully picks up the date from Eve's blog but Chrome does not. The same with the DOI.</p>\n<p>I am working on trying ot fix the Blog Title upper/lowercase span class issue because I think it would be really helpful to say lowercase, uppercase, sentence case etc while keeping the visible site title can stay clean for social cards, while <code>prism.publicationName</code> carries the case-preserving version for citation tools.</p>\n<p>On my personal site, the implementation went into shared Eleventy head and SEO includes. The Codex archive shows the concrete pattern: add RDFa prefixes to the head templates, create a shared Zotero include, and include it from both regular SEO and blog SEO templates. Rendered blog pages then emitted <code>zotero:itemType=blogPost</code>, Dublin Core basics, citation author/date/url/language, and PRISM blog metadata. Other normal pages emitted <code>zotero:itemType=webPage</code>. Redirect and noindex pages were skipped. Just as important: no <code>citation_title</code> or <code>citation_journal_title</code> tags were emitted for blog posts.</p>\n<p>For the Whitestone publication sites, the implementation had to be more careful. JCRT has archive articles, Religious Theory posts, author pages, issue pages, and organizational pages. <code>journal.thenewpolis.com</code> has journal-style content. <code>thenewpolis.com</code> and <code>esthesis.org</code> work more like publication/blog hybrids. <code>thewhitestonefoundation.org</code> is the organizational parent, not a journal archive. The shared rule was simple: add the Zotero prefix globally, then conditionally emit item types and citation fields based on page type.</p>\n<p>That conditional logic is the difference between useful metadata and noisy metadata. It is tempting to spray every citation tag across every page. But that makes tools guess. Better metadata is more restrained. A post gets post metadata. An article gets article metadata. A homepage gets website metadata. An author page gets creator/person metadata. A search page probably does not need to pretend to be a scholarly object.</p>\n<p>This work also sat alongside a broader metadata cleanup. On the Whitestone sites, I was already working with Dublin Core, Schema.org JSON-LD, h-card and h-entry microformats, RSS/Atom feeds, citation sitemaps, and Standard.site records. Zotero harvestability fit into that larger pattern. The aim was not just SEO. It was scholarly interoperability. These sites should be readable by people, citation managers, search engines, archives, and future systems we do not control.</p>\n<p>There is a practical reason for doing this on static sites. Static sites are fast, durable, and easier to preserve. But they do not automatically get the metadata affordances that large journal platforms provide. If you publish scholarship with Eleventy, Astro, Jekyll, Hugo, or another static-site generator, you have to build those affordances yourself. That can be annoying, but it is also freeing. You can make the metadata better than the defaults.</p>\n<p>The workflow I would use again is straightforward:</p>\n<ol>\n<li>Decide which page types exist.</li>\n<li>Add the RDFa prefixes to the base HTML template.</li>\n<li>Emit <code>zotero:itemType</code> conditionally.</li>\n<li>Use <code>blogPost</code> for blog posts and keep journal tags for real journal articles.</li>\n<li>Use Dublin Core as a fallback.</li>\n<li>Use PRISM <code>publicationName</code> for the blog or site title.</li>\n<li>Preserve case with <code>span class=&quot;nocase&quot;</code> where needed.</li>\n<li>Avoid <code>citation_title</code> and <code>citation_journal_title</code> on blog posts.</li>\n<li>Build the site and inspect rendered HTML.</li>\n<li>Test the deployed page in Zotero, remembering that the Zotero Connector can cache translators.</li>\n</ol>\n<p>The final point is important. I checked rendered HTML during implementation. That confirms the templates produced the intended tags. Zotero import testing still needs to happen on deployed pages, and after metadata changes it is worth resetting Zotero translators before testing. Metadata work always has this split: you can verify your output, but you still need to test the consuming tool.</p>\n<p>What I like about Eve’s post is that it treats citation metadata as part of web craft. It is not glamorous. It is not the part of the site most readers notice. But it changes how writing travels. A post that imports cleanly into Zotero has a better chance of being cited correctly. A journal article with good metadata has a better chance of being found and reused. A publication title with preserved case respects the way authors and editors name their work.</p>\n<p>That is the larger lesson for me. Scholarly web publishing is not only about putting words online. It is about making those words portable, citable, and durable. Zotero is one small part of that infrastructure, but it is a part many scholars actually use every day. If we want independent scholarly sites to matter, we need to make them easier to cite.</p>\n<h2 id=\"sources\" tabindex=\"-1\">Sources <a class=\"header-anchor\" href=\"#sources\">#</a></h2>\n<ul>\n<li>Eve, Martin Paul. 2026. “Making Blog Posts Harvestable by Zotero and Preserving Case in Citation Fields.” eve.gd: Martin Paul Eve, June 23. <a href=\"https://doi.org/10.59348/vrt01-f3b49\">https://doi.org/10.59348/vrt01-f3b49</a>.</li>\n<li>Elliott, Tom. 2018. “Zotero-Nikola Harmony (One Simple Trick).” <em>Paregorios.Org</em>, May 8. <a href=\"https://paregorios.org/posts/2018/05/zotero_nikola_harmony/\">https://paregorios.org/posts/2018/05/zotero_nikola_harmony/</a>.</li>\n</ul>\n<h3 id=\"p-s\" tabindex=\"-1\">P.S. <a class=\"header-anchor\" href=\"#p-s\">#</a></h3>\n<p>Martin has his own dois for his site and that is super cool.</p>\n",
			"date_published": "2026-06-25T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2026-06-24-spiritual-violence-book-review/",
			"url": "https://www.adamdjbrett.com/blog/2026-06-24-spiritual-violence-book-review/",
			"title": "Book Review: *Spiritual Violence: Religious Phenomena That Defile the Faith* by Rev. Alba Onofrio",
			"content_html": "<p>Rev. Alba Onofrio, with Nadia Arellano and Dr. Judith Bautista Fajardo. <em>Spiritual Violence: Religious Phenomena That Defile the Faith</em>. Soulforce“ 2026. <a href=\"htps://www.lulu.com/shop/rev-alba-onofrio-and-nadia-arellano-and-dr-judith-bautista-fajardo-and-bryony-dick/\">ebook</a> <a href=\"https://www.lulu.com/shop/alba-onofrio-and-nadia-arellano-and-judith-bautista-fajardo-and-arelis-benitez/spiritual-violence/paperback/product-p6w4q4w.html\">print</a>, ISBN: 9781736126783. <a href=\"https://bookshop.org/p/books/spiritual-violence-religious-phenomena-that-defile-the-faith-alba-onofrio/9d710745ed0dc722?ean=9781736126783&amp;next=t\">Buy now via Bookshop.org</a></p>\n<p><em>Spiritual Violence: Religious Phenomena That Defile the Faith</em> is an urgent critical intervention in the study of religious nationalism. It gives language to forms of harm that many people know in their bodies long before they can name them. The central thesis is that white Christian Supremacy turns sacred texts, traditions, and institutions into tools of domination. When that happens, religion does not merely fail to protect vulnerable people. It becomes the means through which they are shamed, controlled, isolated, punished, and taught to doubt their own dignity. The book is hopeful in its theological horizon, but not thoughtful in its diagnosis. It insists that faith can heal, but only when communities tell the truth about the ways faith has been weaponized.</p>\n<p>One of the things I appreciate about the volume is how it refuses to separate theology from embodied life. Its method is not only theoretical but also pastoral, political, testimonial, and somatic. The authors write from queer, feminist, Latinx, diasporic, and Christian commitments, and they hold these commitments together holistically and intersectionally, foregrounding the whole person. The prologue introduces <em>Lxs Sinvergüenzas</em> as a community of faithful resistance. <em>Sinvergüenza</em> becomes more than a reclaimed epithet. It becomes a theological posture: bold, unashamed, irreverent toward domination, and devoted to healing. Beginning with  <em>Lxs Sinvergüenzas</em>, this book reveals its goal: liberation through naming, truth-telling, somatic wisdom, and collective repair.</p>\n<p>”The book has five important and heavy chapters: “Spiritual Traum  “white Christian Supremac  “Spiritual Violenc  “Spiritual Terrorism,” and “Religious Abuse.” It then closes with “Closing Thoughts,” a visual analogy of white Christian Supremacy as a weapons factory, and four appendices: a Spiritual Violence Reflective Awareness Tool, healing practices after Spiritual Violence, a Religious Abuse Reflective Awareness Tool, and healing practices after Religious Abuse. It was helpful to me to take breaks between chapters and journal reflecting on my own experience and engagement with the text, allowing myself time to process. This structure is one of the book’s strengths. It begins with the wounds survivors carry, moves backward through the historical and ideological roots of those wounds, then traces the continuum of harm from everyday spiritual injury to systemic terror and intimate abuse.</p>\n<p>Chapter 1, “Spiritual Trauma,” starts with enfleshed corporeal bodies. We begin at the site and location of spiritual violence, the body/mind/soul. In refusing to separate the body into a trichotomy, the authors  ask a simple yet important question: what happens when religion wounds the spirit? (I paused here to journal. I recommend readers to the same.) <em>Spiritual Violence</em>; defines Spiritual Trauma as the trauma experienced by those subjected to Spiritual Violence, Religious Abuse, or Spiritual Terrorism. Through a careful weaving of survivors’ stories, the authors provide a substantial account of spiritual trauma. Chapter 1 illustrates the harm that occurs when God, sacred texts, or religious authorities become attached to harm; survivors lose not only community but also a source of resilience. Nadia’s courageous account grounds the theology in lived religious experience. The account shows how religious authority can bind together belonging, fear, obedience, and bodily control. Nadia's story and the analytical support for it in the chapter illustrate how spiritual harm is material harm. The spiritual and material worlds are intertwined and inseparable. It does not reduce it to hurt feelings, theological disagreement, or private disappointment. Chapter one illustrates so beautifully and poignantly what Dr. Biko Mandela Gray always tells students, &quot;critique is an act of care.&quot; Nadia tells her story with care, and she is held in care by the community of <a href=\"https://soulforce.org/\">Soulforce</a>.</p>\n<p>Chapter 2, “white Christian Supremacy,” provides a historical frame. The chapter argues that Christian hegemony shapes what a society treats as normal and good, even when that society calls itself secular. But the authors distinguish Christian hegemony from white Christian Supremacy. Christian hegemony names the dominance of Christian values and rhythms across social life. white Christian Supremacy names the weaponized form of Christianity that serves conquest, patriarchy, racism, empire, and control. This distinction is valuable because it highlights the contested nature of Christianity. There is not one Christianity but a multiplicity of Christianities, and some of them can be liberative and life-giving, as the authors highlight. However this nuanced and careful analysis does not occlude the powerful critique that Christianity, in the singular (and I would add the plural) has been repeatedly captured by power, violence, and hegemony.</p>\n<p>In light of the chapter’s Examination of Christian Hegemony, the examination of the <a href=\"https://doctrineofdiscovery.org/what-is-the-doctrine-of-discovery/\">Doctrine of Christian Discovery</a> is especially important. By reading papal bulls such as <a href=\"https://doctrineofdiscovery.org/dum-diversas/\"><em>Dum Diversas</em></a>, <a href=\"https://doctrineofdiscovery.org/the-bull-romanus-pontifex-nicholas-v/\"><em>Romanus Pontifex</em></a>, and <a href=\"https://doctrineofdiscovery.org/inter-caetera/\"><em>Inter Caetera</em></a><sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1\">[1]</a></sup> as theological and jurisprudential technologies of conquest, the book links spiritual harm to land theft, enslavement, genocide, and the denial of Indigenous sovereignty. This is one of the volume’s key contributions, highlighting the past, present, and left unchecked future harms of the Doctrine of Christian Discovery as it continues to be weaponized and used as a tool of Spiritual Violence. It refuses the narrow idea that spiritual violence only happens inside churches or families. The book shows that religion-based violence also organizes law, property, borders, race, gender, and national identity. That makes the concept useful far beyond pastoral care. It belongs in theology, religious studies, ethnic studies, trauma studies, and political education.\nIt\nChapter 3, “Spiritual Violence,” is the key contribution of this book, articulating what Spiritual Violence is and how and when it occurs when religious morality or divine authority is used to question or deny the sacred worth and inherent dignity of a person or group. This concept is powerful because it names a wide range of harms without flattening them. Spiritual violence includes physical violence, sexual violence, and discursive forms of violence like jokes, shame, exclusion, proof-texting, family pressure, church discipline, legal discrimination, and internalized self-hatred. The chapter is strongest when it shows how ordinary and intimate this violence can be. The stories of Jelena and Sofia show that spiritual violence often comes through people who think they are protecting faith, family, or morality. The book is careful here. It does not say intent is irrelevant, but it insists that good intentions do not erase harm.</p>\n<p>This chapter also makes a major contribution through its account of patriarchy and the weaponizing of the Bible. The authors show how gender hierarchy becomes harder to challenge when it is framed as God’s design. Patriarchy is not only a social system in this account. It becomes a theology of control. The book’s discussion of biblical literalism is useful because it connects interpretation to power. When a text is treated as simple, fixed, and infallible, authority shifts to those who claim the right to interpret it. The chapter then models another way of reading. It points toward feminist, queer, trans, and liberationist approaches that treat Scripture as a site of struggle rather than a weapon already owned by the powerful.</p>\n<p>Chapter 4, “Spiritual Terrorism,” expands the scale. Spiritual Terrorism is defined as the systematic mobilization of white Christian supremacist logic and morality against people marked as evil, dangerous, or disposable. The authors distinguish it from Spiritual Violence by scale, scope, and intensity. This is one of the book’s most important conceptual moves. Spiritual Terrorism names what happens when a targeted group faces threats from many directions at once: family, church, school, police, law, media, and the state. The chapter’s examples involving 2SLGBTQIA+ people, migrants, and trans communities show how moral panic becomes a structure of fear. The point is not only that people are harmed. The point is that they are made to live under constant surveillance and threat.</p>\n<p>The chapter’s treatment of Christian hegemonic impunity as a type of Spiritual Terrorism illuminates part of the reason so many people are leaving churches today, and that is the lack of accountability and support for survivors of sexual abuse and spiritual abuse. Spiritual Terrorism works because perpetrators believe they are doing the right thing, and because institutions often agree with them, and provide them with theologized impunity coupled with an apathy and refusal to act. Phrases like “following the law,” “defending values,” or “maintaining order“ become moral shields. The story of Yadira and Emilio shows this clearly. In college, one of my professors, Ron Crtichfiled, used to say that &quot;proof-text theology is bad theology.&quot; <em>Spiritual Violence</em> highlights how proof-text theology is not only bad theology but also toxic theology. The volume  uses the example of how white Christian Supremacy uses Romans 13 to defend family separation at the US border, which becomes an example of how biblical language can legitimate state violence. Through this example, one can see how spiritual violence moves from sermon to statute, from private belief to public cruelty.</p>\n<p>Chapter 5, “Religious Abuse,” brings the argument back into the intimate space of churches and spiritual communities. Religious Abuse is presented as a severe form of Spiritual Violence that occurs when a person with religious authority exploits someone under their care for personal benefit or gratification. The chapter is painful but necessary. It explains why abuse in religious communities can be so hard to name. Churches often operate with trust, hospitality, reverence, and emotional closeness. These can be life-giving. But they can also hide coercion when leaders use divine authority to demand obedience. I read this chapter slowly, carefully, taking breaks, as it is practical, insightful, and encouraging of the reader to take time to reflect upon spiritual abuse.</p>\n<p>The chapter’s discussion of clergy power, church ecosystems, religious legalism, prosperity teachings, purity culture, disability, conversion therapy, and theologies of bodily harm is one of the most practical parts of the book. It shows that abuse is not the act of a single bad leader. It often depends on a whole environment: hierarchy, secrecy, gendered authority, unpaid labor, financial dependence, fear of scandal, and teachings that make suffering seem holy. Juliana's story is devastating because it shows how religious reverence can obstruct justice. As one sits with Juliana's story, the chapter also examines how liberative theologies that honor the body, center lived experience, and call communities to material practices of repair serve as a counterpoint to the toxic theologies of religious violence.</p>\n<p>The closing visual analogy of a weapons factory brings the book’s concepts together. white Christian Supremacy is the factory. The Bible, doctrine, and tradition are raw materials. The weapons produced include daily Spiritual Violence, Religious Abuse, Spiritual Terrorism, internalized Spiritual Violence, and mass forms of violence such as colonization and genocide. The analogy works because it clarifies scale. A BB gun is not a machine gun, and a handgun is not a nuclear bomb. But all are weapons. Likewise, a shaming joke, a coercive pastoral relationship, a discriminatory law, and a theology that blesses conquest are not identical. But they can come from the same ideological machinery, and they can all cause harm.</p>\n<p>The appendices are incredibly helpful and informative for (non)-religious communities, community groups, and collective organizing. The Reflective Awareness Tools help readers identify experiences of Spiritual Violence and Religious Abuse without presenting themselves as clinical diagnostic instruments. The healing practices are practical and grounded: studying history, telling stories, growing in community, responding to violence, practicing disobedience, doing theology, exploring other spiritual paths, changing language, observing the violence we replicate, engaging in activism, focusing on joy, and seeking professional help. These sections matter because the book does not leave readers alone with recognition. It offers steps toward repair. I would encourage reading the appendices first and applying these practices as one reads. I did this the second time I read through the book, and it was incredibly helpful.</p>\n<p>The book’s key concepts—Spiritual Trauma, white Christian Supremacy, Spiritual Violence, Spiritual Terrorism, Religious Abuse, <em>Sentipensar</em>, and <em>Sinvergüenza</em>—are important because they give readers a lexicon for articulating and describing these experiences in ways that can be understood by those who have not experienced these abuses. Survivors are often told they are too sensitive, rebellious, sinful, confused, bitter, or faithless. This book says something else: the problem is not your body, your questions, your sexuality, your gender, your anger, or your refusal to submit. The problem is the weaponization of religion by systems of domination. That shift in language is not cosmetic. It changes where responsibility belongs.</p>\n<p>The review should also name the book’s hermeneutics of generosity and care. <em>Spiritual Violence</em> is written by people who care enough about faith to reclaim it from domination, as the Soulforce website boldly proclaims, &quot;We are Queer people reclaiming our spirits from weaponized religion.&quot; The authors repeatedly distinguish weaponized religion from liberating faith. They name churches and Christians as sources of harm but also of sanctuary, courage, civil disobedience, feminist theology, queer theology, trans theology, abolitionist practice, and communal care. It would be easy and perhaps understandable for the authors to turn to cynicism and despair, but instead, they have put in the work to focus on repair and healing for themselves and their beloveds and beloved communities.</p>\n<p><em>Spiritual Violence</em> is a significant contribution to  public theology. Through its reflexive weaving of applied theology, survivor testimony, decolonial history, queer feminist theology, trauma awareness, and practical tools for community education, it provides a representative example of the best of prophetic public theology. Listen closely and hear the loving invitation from Rev. Alba Onofrio to readers who have felt the ache of quietly loving God after being harmed by God’s people to find spaces for repair and healing. For classrooms, churches, activist groups, pastoral training, and survivor-led healing spaces, this book offers a shared vocabulary for addressing <em>Spiritual Violence.</em></p>\n<p>The book’s importance lies in its core invitation: name the violence, trace the system, return to the body, tell the truth, and build communities where faith no longer serves domination. That is a serious task. <em>Spiritual Violence</em> gives readers resources to begin it. For those looking for next steps look at the wounderful resources that <a href=\"https://soulforce.org/what-we-do/resources/\">Soulforce Resource Library</a> where you can find materials in seven languages.</p>\n<h2 id=\"footnotes\" tabindex=\"-1\">Footnotes <a class=\"header-anchor\" href=\"#footnotes\">#</a></h2>\n<hr class=\"footnotes-sep\">\n<section class=\"footnotes\">\n<ol class=\"footnotes-list\">\n<li id=\"fn1\" class=\"footnote-item\"><p>New translation by Sebastian Modrow and Melissa Smith. Indigenous Values Initiative &quot;Inter Caetera,&quot; translated by Sebastian Modrow and Melissa Smith, <em>Doctrine of Discovery Project</em> (13 June 2022), <a href=\"https://doctrineofdiscovery.org/inter-caetera/\">https://doctrineofdiscovery.org/inter-caetera/</a>. <a href=\"#fnref1\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n</ol>\n</section>\n",
			"date_published": "2026-06-24T17:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/byword-app-review/",
			"url": "https://www.adamdjbrett.com/blog/byword-app-review/",
			"title": "Byword app review: the Markdown writing room that still earns its place",
			"content_html": "<h1 id=\"byword-app-review-the-markdown-writing-room-that-still-earns-its-place\" tabindex=\"-1\">Byword app review: the Markdown writing room that still earns its place <a class=\"header-anchor\" href=\"#byword-app-review-the-markdown-writing-room-that-still-earns-its-place\">#</a></h1>\n<p><strong>Verdict:</strong> Byword remains a strong example of what a distraction-free Markdown app should be: quiet, plain-text-first, and useful for common web and PDF workflows. Its official materials describe Markdown writing, live word counters, iCloud/Dropbox sync, in-app preview, export to HTML/PDF/rich text, and direct publishing to Medium, WordPress, Blogger, Tumblr, and Evernote.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1\">[1]</a></sup> The Mac and iOS App Store listings also advertise footnotes, tables, cross-references, PDF/HTML export, and cross-device sync across Apple devices.<sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2\">[2]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3\">[3]</a></sup></p>\n<p>Byword does not try to be Microsoft Word, Scrivener, Ulysses, or a reference manager. Its value is simpler. It gives you a calm writing surface, plain-text portability, and enough extended Markdown features to draft serious work without getting stuck in interface decisions.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:1\">[1:1]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2:1\">[2:1]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3:1\">[3:1]</a></sup></p>\n<p>The main caveat is Word export. Current public Byword listings emphasize PDF and HTML export. Older coverage reported Word and LaTeX export.<sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2:2\">[2:2]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn4\" id=\"fnref4\">[4]</a></sup> I treat DOC/DOCX performance here as <strong>user-reported and unverified</strong>, not as a tested result. My recommendation is simple: use Byword as the writing environment, then use Pandoc for high-stakes conversion. Pandoc is documented as a converter among Markdown, HTML, LaTeX, Word DOCX, PDF, and many other formats.<sup class=\"footnote-ref\"><a href=\"#fn5\" id=\"fnref5\">[5]</a></sup></p>\n<p><strong>Method note:</strong> This is a source-based app review, not an installed-app benchmark. I did not install Byword or run fresh export tests. App Store price, version, compatibility, and update metadata were fetched on <strong>2026-07-07</strong>. They may vary by region or change after that date.</p>\n<h2 id=\"what-byword-is\" tabindex=\"-1\">What Byword is <a class=\"header-anchor\" href=\"#what-byword-is\">#</a></h2>\n<p>Byword is a Markdown text editor for Mac, iPhone, and iPad by Metaclassy.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:2\">[1:2]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2:3\">[2:3]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3:2\">[3:2]</a></sup> The official site frames the app around three verbs: <strong>Write</strong>, <strong>Sync</strong>, and <strong>Export &amp; Publish</strong>.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:3\">[1:3]</a></sup> It advertises Markdown formatting, keyboard shortcuts, subtle syntax highlighting, live word counters, iCloud/Dropbox sync, in-app preview, export to HTML/PDF/rich text, and publishing to Medium, WordPress, Blogger, Tumblr, and Evernote.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:4\">[1:4]</a></sup></p>\n<p>The Mac App Store listing describes Byword as “Writing made easier.” The fetched US listing showed a <strong>$10.99</strong> price, version <strong>2.9.6</strong>, an update date of <strong>2023-10-16</strong> for macOS Sonoma, macOS 10.13 or later, and Metaclassy, Lda as the seller.<sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2:4\">[2:4]</a></sup> It lists Markdown writing, cross-device sync, keyboard shortcuts, dark theme, footnotes, tables, cross-references, PDF/HTML export, and blog publishing.<sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2:5\">[2:5]</a></sup> The iOS listing advertises the same broad feature set. The fetched listing showed <strong>$5.99</strong>, version <strong>2.9.3</strong>, an update date of <strong>2020-04-09</strong>, and compatibility beginning at iOS/iPadOS 10.3.<sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3:3\">[3:3]</a></sup></p>\n<p>That positioning matters. Byword is not a layout tool first. Its official materials and store listings present it as a Markdown/plain-text writing, export, and publishing tool.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:5\">[1:5]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2:6\">[2:6]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3:4\">[3:4]</a></sup> Older coverage and user commentary suggest that this continuity is part of the appeal. A 2012 Macworld review described it as a minimalist Markdown-focused editor. A 2018 MacUpdate user review said it “hasn’t changed a huge amount over the years, but it doesn’t need to.”<sup class=\"footnote-ref\"><a href=\"#fn4\" id=\"fnref4:1\">[4:1]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn6\" id=\"fnref6\">[6]</a></sup></p>\n<h2 id=\"why-it-works-so-well-for-focused-writing\" tabindex=\"-1\">Why it works so well for focused writing <a class=\"header-anchor\" href=\"#why-it-works-so-well-for-focused-writing\">#</a></h2>\n<p>Byword’s best feature is restraint. A 2012 Macworld review described it as part of a wave of minimalist OS X editors. It stood out for Markdown support, a no-frills window, light and dark themes, word and character counts, full-screen mode, Typewriter Mode, and paragraph/line focus.<sup class=\"footnote-ref\"><a href=\"#fn4\" id=\"fnref4:2\">[4:2]</a></sup> A MacUpdate user review from 2018 made a similar point from long-term use: Byword “hasn’t changed a huge amount over the years, but it doesn’t need to.” The reviewer pointed to full-screen mode, typewriter scrolling, line focus, dark/light modes, and page-width control.<sup class=\"footnote-ref\"><a href=\"#fn6\" id=\"fnref6:1\">[6:1]</a></sup></p>\n<p>That is also my assessment: Byword stays out of the way. It makes Markdown feel less like coding and more like writing. The interface does not keep asking you to make formatting choices. You can draft a paragraph, add a heading, drop in a footnote, and keep moving. The Mac and iOS listings specifically advertise Markdown support, footnotes, tables, and cross-references.<sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2:7\">[2:7]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3:5\">[3:5]</a></sup></p>\n<p>That matters for academic writing. Argument, evidence, structure, quotation, citation, and revision all compete for attention. A writing environment that reduces formatting noise helps.</p>\n<h2 id=\"academic-writing-footnotes-without-the-word-processor-fog\" tabindex=\"-1\">Academic writing: footnotes without the word-processor fog <a class=\"header-anchor\" href=\"#academic-writing-footnotes-without-the-word-processor-fog\">#</a></h2>\n<p>For academic work, Byword’s most important feature is not “Markdown support” in the generic sense. It is extended Markdown support. The current Mac and iOS App Store listings advertise footnotes, tables, and cross-references.<sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2:8\">[2:8]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3:6\">[3:6]</a></sup> Blot’s Byword documentation also says Byword supports advanced Markdown features such as footnotes, tables, and cross-references for web publishing workflows.<sup class=\"footnote-ref\"><a href=\"#fn7\" id=\"fnref7\">[7]</a></sup></p>\n<p>This makes Byword useful for early-stage academic prose. Footnotes let you park qualifications, historiographical asides, source notes, and “come back to this” arguments without breaking the main paragraph. Markdown tables and lists work for notes, outlines, syllabi, literature matrices, and lecture planning. Cross-references can support longer documents when the Markdown flavor and export path preserve them. Byword and Blot document cross-reference support, and Pandoc documents an extended Markdown dialect with additional features and extensions.<sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2:9\">[2:9]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3:7\">[3:7]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn7\" id=\"fnref7:1\">[7:1]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn8\" id=\"fnref8\">[8]</a></sup></p>\n<p>The limit is clear. Treat Byword as a drafting and plain-text authoring environment, not as the final authority on scholarly document production. If the target is a journal template, a supervisor’s Word comments, a grant agency’s DOCX form, or a publisher’s style sheet, the last mile matters.</p>\n<h2 id=\"export-excellent-until-word-becomes-the-boss\" tabindex=\"-1\">Export: excellent until Word becomes the boss <a class=\"header-anchor\" href=\"#export-excellent-until-word-becomes-the-boss\">#</a></h2>\n<p>Byword’s current official site says it can preview documents in-app and export to HTML, PDF, and rich text.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:6\">[1:6]</a></sup> The current Mac App Store listing specifically says PDF and HTML export.<sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2:10\">[2:10]</a></sup> The older 2012 Macworld review reported export to HTML, PDF, RTF, Word, or LaTeX.<sup class=\"footnote-ref\"><a href=\"#fn4\" id=\"fnref4:3\">[4:3]</a></sup> I would not make current DOCX support the center of Byword’s official value proposition without testing the installed app. The strongest current public evidence emphasizes PDF/HTML. Word export appears in older secondary coverage.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:7\">[1:7]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2:11\">[2:11]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn4\" id=\"fnref4:4\">[4:4]</a></sup></p>\n<p>The user-reported complaint about Word output is plausible but <strong>unverified here</strong>. Word documents can encode paragraph styles, list styles, table styles, footnote styles, numbering, margins, and indentation. Byword’s current public materials emphasize Markdown writing and PDF/HTML-oriented export rather than Word-native collaboration or DOCX production.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:8\">[1:8]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2:12\">[2:12]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3:8\">[3:8]</a></sup></p>\n<p>When a Markdown editor’s export layer misreads tables, indents them too far, breaks numbered lists, or inconsistently preserves footnotes, the resulting document can cost more time than the app saved. I did not reproduce that failure pattern in this pass. So the criticism should stay bounded: <strong>Byword works well for writing, but I would not trust it as the only conversion engine for high-stakes DOC/DOCX submission without a fresh installed-app test.</strong></p>\n<h2 id=\"the-pandoc-solution\" tabindex=\"-1\">The Pandoc solution <a class=\"header-anchor\" href=\"#the-pandoc-solution\">#</a></h2>\n<p>Pandoc fits this workflow because it is built for document conversion rather than minimalist drafting. Its official manual describes Pandoc as a tool for converting among markup and word-processing formats, including Markdown, HTML, LaTeX, Word DOCX, and PDF.<sup class=\"footnote-ref\"><a href=\"#fn5\" id=\"fnref5:1\">[5:1]</a></sup> It supports enhanced Markdown features including tables, footnotes, citations, math, and more.<sup class=\"footnote-ref\"><a href=\"#fn5\" id=\"fnref5:2\">[5:2]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn8\" id=\"fnref8:1\">[8:1]</a></sup> It also supports <code>docx</code> as an output format and documents <code>--reference-doc</code> for controlling DOCX styles such as Normal, Body Text, headings, footnotes, captions, and table style.<sup class=\"footnote-ref\"><a href=\"#fn5\" id=\"fnref5:3\">[5:3]</a></sup></p>\n<p>A pragmatic workflow is:</p>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\">pandoc manuscript.md <span class=\"token parameter variable\">-o</span> manuscript.docx --reference-doc<span class=\"token operator\">=</span>academic-reference.docx</code></pre>\n<p>For PDF:</p>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\">pandoc manuscript.md <span class=\"token parameter variable\">-o</span> manuscript.pdf</code></pre>\n<p>For HTML:</p>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\">pandoc <span class=\"token parameter variable\">-s</span> manuscript.md <span class=\"token parameter variable\">-o</span> manuscript.html</code></pre>\n<p>These commands follow Pandoc’s documented role as a converter from Markdown to DOCX, PDF, and HTML outputs.<sup class=\"footnote-ref\"><a href=\"#fn5\" id=\"fnref5:4\">[5:4]</a></sup> This does not make conversion automatic or perfect. Pandoc warns that some formats are more expressive than its intermediate document model and that complex tables may not fit its simple model.<sup class=\"footnote-ref\"><a href=\"#fn5\" id=\"fnref5:5\">[5:5]</a></sup> But Pandoc gives the writer a documented and repeatable conversion layer: explicit input/output formats, a documented Markdown dialect, reference DOCX styling, table/footnote syntax, filters when needed, and a command-line workflow.<sup class=\"footnote-ref\"><a href=\"#fn5\" id=\"fnref5:6\">[5:6]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn8\" id=\"fnref8:2\">[8:2]</a></sup></p>\n<p>The workflow is straightforward: Byword for writing, Pandoc for production.</p>\n<h2 id=\"who-should-use-byword\" tabindex=\"-1\">Who should use Byword <a class=\"header-anchor\" href=\"#who-should-use-byword\">#</a></h2>\n<p>Byword is still easy to recommend for:</p>\n<ul>\n<li>writers who want a quiet Markdown-first drafting environment;<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:9\">[1:9]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2:13\">[2:13]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn4\" id=\"fnref4:5\">[4:5]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn6\" id=\"fnref6:2\">[6:2]</a></sup></li>\n<li>academics who like footnotes but do not want to draft inside Word;<sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2:14\">[2:14]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3:9\">[3:9]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn7\" id=\"fnref7:2\">[7:2]</a></sup></li>\n<li>bloggers who publish from Markdown or use HTML workflows;<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:10\">[1:10]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2:15\">[2:15]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3:10\">[3:10]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn7\" id=\"fnref7:3\">[7:3]</a></sup></li>\n<li>students and researchers who want notes and drafts in portable plain-text files;<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:11\">[1:11]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2:16\">[2:16]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3:11\">[3:11]</a></sup></li>\n<li>Apple users who value a native-feeling, low-distraction app.<sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2:17\">[2:17]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3:12\">[3:12]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn4\" id=\"fnref4:6\">[4:6]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn6\" id=\"fnref6:3\">[6:3]</a></sup></li>\n</ul>\n<p>It is less ideal for:</p>\n<ul>\n<li>people who need complex tables, tracked changes, comments, and Word-native collaboration from the beginning;</li>\n<li>writers whose final deliverable is always a heavily formatted DOCX;</li>\n<li>users who want a continuously updated cross-platform writing platform beyond Apple devices, since the cited store listings are for Mac, iPhone, and iPad;<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:12\">[1:12]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2:18\">[2:18]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3:13\">[3:13]</a></sup></li>\n<li>anyone unwilling to learn a separate conversion workflow for serious exports.</li>\n</ul>\n<h2 id=\"final-judgment\" tabindex=\"-1\">Final judgment <a class=\"header-anchor\" href=\"#final-judgment\">#</a></h2>\n<p>Byword works because it knows what it is. It is a focused writing room for Markdown: clean, calm, and durable. Official and store materials consistently present it as a Markdown writing, sync, export, and publishing tool rather than a full word processor.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:13\">[1:13]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2:19\">[2:19]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn3\" id=\"fnref3:14\">[3:14]</a></sup> For the kind of writer who began using it in the early 2010s and still loves it, that durability is not only nostalgia. It shows that the app’s design solved a real problem and did not overcomplicate itself. Long-term public comments and older review coverage support the claim that Byword’s focused-writing identity has stayed stable over time.<sup class=\"footnote-ref\"><a href=\"#fn4\" id=\"fnref4:7\">[4:7]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn6\" id=\"fnref6:4\">[6:4]</a></sup></p>\n<p>The criticism should stay bounded by the evidence gathered here. Current public sources support PDF/HTML/rich-text export. Older coverage supports historical Word/LaTeX export. This pass did not test current installed-app DOC/DOCX behavior.<sup class=\"footnote-ref\"><a href=\"#fn1\" id=\"fnref1:14\">[1:14]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn2\" id=\"fnref2:20\">[2:20]</a></sup><sup class=\"footnote-ref\"><a href=\"#fn4\" id=\"fnref4:8\">[4:8]</a></sup> If your workflow ends in PDF, HTML, web publishing, or plain-text archival drafts, Byword is a good fit. If your workflow ends in DOCX, keep using Byword, but make Pandoc part of the system.<sup class=\"footnote-ref\"><a href=\"#fn5\" id=\"fnref5:7\">[5:7]</a></sup></p>\n<p><strong>Editorial rating:</strong> 4.5/5 as a focused Markdown writing app; 3/5 if judged as a standalone academic DOCX production tool. These ratings are personal/editorial judgments based on the cited feature evidence and the unverified user-reported Word-export concern, not benchmark results or a comparative hands-on test.</p>\n<hr class=\"footnotes-sep\">\n<section class=\"footnotes\">\n<ol class=\"footnotes-list\">\n<li id=\"fn1\" class=\"footnote-item\"><p>Byword official site, <a href=\"https://www.bywordapp.com/\">https://www.bywordapp.com/</a>. <a href=\"#fnref1\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:1\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:2\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:3\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:4\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:5\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:6\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:7\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:8\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:9\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:10\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:11\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:12\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:13\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref1:14\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn2\" class=\"footnote-item\"><p>Byword Mac App Store listing, <a href=\"https://apps.apple.com/us/app/byword/id420212497\">https://apps.apple.com/us/app/byword/id420212497</a>. <a href=\"#fnref2\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref2:1\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref2:2\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref2:3\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref2:4\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref2:5\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref2:6\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref2:7\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref2:8\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref2:9\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref2:10\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref2:11\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref2:12\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref2:13\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref2:14\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref2:15\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref2:16\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref2:17\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref2:18\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref2:19\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref2:20\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn3\" class=\"footnote-item\"><p>Byword iOS App Store listing, <a href=\"https://apps.apple.com/us/app/id482063361\">https://apps.apple.com/us/app/id482063361</a>. <a href=\"#fnref3\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref3:1\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref3:2\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref3:3\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref3:4\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref3:5\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref3:6\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref3:7\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref3:8\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref3:9\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref3:10\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref3:11\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref3:12\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref3:13\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref3:14\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn4\" class=\"footnote-item\"><p>Macworld, “Byword is a solid text editor for Markdown-focused writing,” <a href=\"https://www.macworld.com/article/216766/byword_is_a_solid_text_editor_for_markdown_focused_writing.html\">https://www.macworld.com/article/216766/byword_is_a_solid_text_editor_for_markdown_focused_writing.html</a>. <a href=\"#fnref4\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref4:1\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref4:2\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref4:3\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref4:4\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref4:5\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref4:6\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref4:7\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref4:8\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn5\" class=\"footnote-item\"><p>Pandoc User's Guide, <a href=\"https://pandoc.org/demo/example2.html\">https://pandoc.org/demo/example2.html</a>. <a href=\"#fnref5\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref5:1\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref5:2\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref5:3\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref5:4\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref5:5\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref5:6\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref5:7\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn6\" class=\"footnote-item\"><p>MacUpdate, “Download Byword for Mac,” <a href=\"https://byword.macupdate.com/\">https://byword.macupdate.com/</a>. <a href=\"#fnref6\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref6:1\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref6:2\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref6:3\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref6:4\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn7\" class=\"footnote-item\"><p>Blot, “Byword,” <a href=\"https://blot.im/tools/byword\">https://blot.im/tools/byword</a>. <a href=\"#fnref7\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref7:1\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref7:2\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref7:3\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n<li id=\"fn8\" class=\"footnote-item\"><p>Pandoc's Markdown, <a href=\"https://pandoc.org/demo/example33/8-pandocs-markdown.html\">https://pandoc.org/demo/example33/8-pandocs-markdown.html</a>. <a href=\"#fnref8\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref8:1\" class=\"footnote-backref\">↩︎</a> <a href=\"#fnref8:2\" class=\"footnote-backref\">↩︎</a></p>\n</li>\n</ol>\n</section>\n",
			"date_published": "2026-06-24T15:30:34Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2026-06-25-lemma.pub-review/",
			"url": "https://www.adamdjbrett.com/blog/2026-06-25-lemma.pub-review/",
			"title": "App Review of *Lemma.pub*",
			"content_html": "<p>I have recently started using <a href=\"https://lemma.pub\">lemma.pub</a> for my new book review blog called <a href=\"https://lemma.pub/did:plc:3vmq5usrh3yvhbrrzf4ymo23/pub/3mpfn7klatsip/\"><em>Spine &amp; Style</em></a>, and it has quickly become one of the most promising writing and publishing spaces I have encountered on the open social web.</p>\n<p>At its best, <a href=\"https://lemma.pub\">lemma.pub</a> feels like a publishing platform built for people who care about writing as writing. It does not bury the work beneath unnecessary dashboards, marketing tools, or platform noise. Instead, it gives writers a clean place to think, draft, publish, and share. That matters. For a project like <a href=\"https://lemma.pub/did:plc:3vmq5usrh3yvhbrrzf4ymo23/pub/3mpfn7klatsip/\"><em>Spine &amp; Style</em></a>, where the goal is to collect and share reflective reading, review, and commentary, <a href=\"https://lemma.pub\">lemma.pub</a> offers the right kind of environment: minimal enough to stay focused, but powerful enough to support serious publication.</p>\n<p>One of <a href=\"https://lemma.pub\">lemma.pub</a>’s strongest features is its flexibility. It is not only a blogging platform in the narrow sense. It supports rich writing across multiple forms: essays, reviews, technical notes, creative work, and media-rich posts. The support for Markdown, embedded media, code, diagrams, math, music notation, images, and other formats makes it unusually versatile. That versatility matters because contemporary writing is rarely just plain text. Good public writing often needs links, quotations, images, references, media, and occasionally more specialized formatting. <a href=\"https://lemma.pub\">lemma.pub</a> understands that without making the publishing process feel complicated.</p>\n<p>I also appreciate that <a href=\"https://lemma.pub\">lemma.pub</a> is part of the broader AT Protocol ecosystem. The ability to connect publishing with Bluesky-style social conversation is especially compelling. Rather than treating publication and discussion as separate worlds, <a href=\"https://lemma.pub\">lemma.pub</a> points toward a more integrated model: write something substantial, share it socially, and allow conversation to gather around the work. For writers, reviewers, scholars, and public intellectuals, that is a meaningful shift. It helps bridge the distance between long-form writing and social engagement.</p>\n<p>For <a href=\"https://lemma.pub/did:plc:3vmq5usrh3yvhbrrzf4ymo23/pub/3mpfn7klatsip/\"><em>Spine &amp; Style</em></a>, <a href=\"https://lemma.pub\">lemma.pub</a> feels like a natural fit. It gives book notes, short reviews, excerpts, and reading reflections a durable home while still making them easy to circulate. It is especially useful for someone who wants a page that feels more intentional than a social media feed but less cumbersome than maintaining a full CMS-heavy website for every small publication. <a href=\"https://lemma.pub\">lemma.pub</a> sits in that productive middle space: lightweight, open, flexible, and writer-centered.</p>\n<p>The platform also has a strong aesthetic advantage. It feels calm. So much of the contemporary web is cluttered, extractive, or algorithmically overdetermined. <a href=\"https://lemma.pub\">lemma.pub</a>’s value is that it gives the writer room. It lets the post breathe. It respects the reader’s attention. For book-related writing in particular, that kind of quiet design is part of the experience.</p>\n<p>I am still early in my use of <a href=\"https://lemma.pub\">lemma.pub</a>, but my first impression is very positive. It is a thoughtful platform with real promise for writers, scholars, reviewers, artists, and technically minded creators who want a richer publishing space connected to the open social web. For <a href=\"https://lemma.pub/did:plc:3vmq5usrh3yvhbrrzf4ymo23/pub/3mpfn7klatsip/\"><em>Spine &amp; Style</em></a>, it offers exactly what I need right now: a clean, flexible, public-facing place to collect reading, write about books, and share that work with others.</p>\n",
			"date_published": "2026-06-24T15:30:34Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2026-06-23-urgency-of-indigenous-values/",
			"url": "https://www.adamdjbrett.com/blog/2026-06-23-urgency-of-indigenous-values/",
			"title": "Book Review: *The Urgency of Indigenous Values* by Philip P. Arnold",
			"content_html": "<p>Philip P. Arnold’s book <a href=\"https://press.syr.edu/supressbooks/5835/urgency-of-indigenous-values-the/\"><em>The Urgency of Indigenous Values</em></a><a href=\"https://www.jstor.org/content/oa_book_monograph/jj.6605389\">Open Access via JSTOR</a> is a clear and urgent intervention into religious studies, Indigenous studies, environmental humanities, and the ongoing critique of settler colonialism. Rather than treating Indigenous lifeways through the limited category of “religion,” Arnold argues for the language of Indigenous values: a framework that better names land, relation, ceremony, reciprocity, responsibility, ancestors, nonhuman beings, and future generations as part of a living moral world.</p>\n<p>The review highlights Arnold’s grounding in Haudenosaunee traditions and his long relationship with Haudenosaunee communities in central New York, especially the Onondaga Nation. It also traces the book’s critique of Western categories that separate religion from politics, ecology, land, and public life. Arnold’s concepts of paying attention, habitus, and exchange give readers a practical vocabulary for thinking beyond extraction, commodification, and domination.</p>\n<p>At its center, <a href=\"https://www.jstor.org/content/oa_book_monograph/jj.6605389\"><em>The Urgency of Indigenous Values</em></a> argues that the ecological crisis is also a crisis of relation. The problem is not only what modern societies do to land, water, and nonhuman life. The deeper problem is what those societies have been taught to believe land is. Arnold connects this crisis to Christian colonialism, dominion theology, and the Doctrine of Christian Discovery, while also pointing toward Indigenous values of attention, reciprocity, restraint, and responsibility.</p>\n<p><a href=\"https://lemma.pub/did:plc:3vmq5usrh3yvhbrrzf4ymo23/pub/3mpfn7klatsip/3mpfnpakfe2ql\">Read the full review on the Atmosphere network (Bluesky)⁠</a></p>\n<hr>\n<h2 id=\"full-review-archived-below-from-lemma-pub\" tabindex=\"-1\"><a href=\"https://lemma.pub/did:plc:3vmq5usrh3yvhbrrzf4ymo23/pub/3mpfn7klatsip/3mpfnpakfe2ql\">Full review archived below from Lemma.pub</a> <a class=\"header-anchor\" href=\"#full-review-archived-below-from-lemma-pub\">#</a></h2>\n<h3 id=\"book-review-the-urgency-of-indigenous-values-by-philip-p-arnold\" tabindex=\"-1\">Book Review: The Urgency of Indigenous Values by Philip P. Arnold <a class=\"header-anchor\" href=\"#book-review-the-urgency-of-indigenous-values-by-philip-p-arnold\">#</a></h3>\n<p><a href=\"https://artsandsciences.syracuse.edu/people/faculty/arnold-philip-p/\">Philip P. Arnold</a>'s <a href=\"https://press.syr.edu/supressbooks/5835/urgency-of-indigenous-values-the/\"><em>The Urgency of Indigenous Values</em></a><a href=\"https://www.jstor.org/content/oa_book_monograph/jj.6605389\">Open Access via JSTOR</a> is a clear and forceful book about land, relation, colonialism, and survival. Its central claim is simple but demanding: the category of &quot;religion&quot; often fails to describe Indigenous lifeways because it separates belief from land, body, community, ceremony, and responsibility. Arnold argues that &quot;Indigenous values&quot; is a better frame because it names a way of living in relation with the natural world, ancestors, nonhuman beings, and future generations.</p>\n<p>The book is grounded mainly in Haudenosaunee traditions and in Arnold's long relationship with Haudenosaunee communities in central New York, especially the Onondaga Nation. This is one of its strengths. Arnold writes from a decades-long relationship he and his wife, Sandy Bigtree (Akwesasne Mohawk), have had with the Haudenosaunee. Trained in the History of Religions, He writes from place, relationship, and obligation. The result is not a detached survey of Indigenous religions. It is an argument about why the words scholars use matter, and why those words have real consequences for land, people, and public life.</p>\n<p>Arnold's most important move is his critique of &quot;religion&quot; as a settler-colonial category. In much Western thought, religion is treated as belief, doctrine, private meaning, or institutional affiliation. Arnold shows why that model does not fit many Indigenous traditions. It also distorts them. Indigenous life, in his account, cannot be divided into religion over here, politics over there, and ecology somewhere else. Land is not a background setting. It is a living relation. Ceremony is not an isolated ritual act. It is part of a larger order of responsibility. Values are not abstract ideals. They are practiced through attention, exchange, gratitude, and restraint.</p>\n<p>This shift from religion to values gives the book its power. To call something &quot;religion&quot; can make it seem optional, private, or symbolic. To speak of &quot;values&quot; makes the issue broader and more material. It asks how people live, what they honor, what they consume, what they damage, and what they owe. That is why the book connects Indigenous studies, religious studies, and environmental humanities so well.</p>\n<p>The middle chapters are especially compelling; here Arnold develops several key ideas: paying attention, <em>habitus</em>, and exchange. &quot;Paying attention&quot; is situated ontology or a way of living responsibly in a world full of relations. <em>Habitus</em> challenges the idea that land is property or space to be occupied. It points instead to dwelling with land in a sustained and reciprocal way. &quot;Exchange&quot; contrasts Indigenous practices of reciprocity with capitalist habits of extraction and commodification. These concepts give readers a practical vocabulary. They also make the book teachable. Students can see how Arnold's argument moves from theory into daily life.</p>\n<p>The book becomes most urgent when Arnold links Indigenous values to ecological crisis. Listening to and learning from Onondaga Nation Turtle Clan Faithkeeper Oren Lyons, Arnold calls for religious studies as a field/discipline to pay attention to the climate emergency, which is not only a scientific problem. It is also a moral and spiritual crisis rooted in destructive values like dominion theology and the <a href=\"https://doctrineofdiscovery.org/\">doctrine of discovery</a>. Modern settler-colonial society has treated land as property, water as a resource, and nonhuman life as material for human use. Arnold connects this worldview to Christian colonialism and to the Doctrine of Christian Discovery. In his reading, ecological destruction and Indigenous dispossession are not separate histories. They belong to the same structure of domination.</p>\n<p>Arnold's critique of the Doctrine of Christian Discovery is sharp and succinct. Readers may find themselves wanting more detail, and they should. If they wish to learn more, they can listen to <a href=\"https://podcast.doctrineofdiscovery.org/\"><em>Mapping the Doctrine of Discovery</em></a>, the podcast that Arnold and Bigtree co-host. <em>Urgency of Indigenous Values</em> builds on the critique of Christian Hegemony that Arnold and Bigtree published for the Doctrine of Discovery Project (<a href=\"https://doctrineofdiscovery.org/10-religous-dimensions/\">Ten Religious Themes of the Doctrine of Christian Discovery (DoCD) that Contrast with Indigenous Values</a>). Expounding upon the '10 Themes' essay, Arnold highlights how Christian ideas and institutions helped justify conquest, missionization, land theft, and cultural destruction. Still, the book sometimes moves quickly across a large historical field. Readers looking for a more detailed account of internal Christian differences, legal history, or anti-colonial Christian traditions may find the treatment compressed. How do you fit 500 years of colonization into 200 pages? This is where the book as an Open Educational Resource becomes so exciting and important. The monograph serves as a large and shady branch on the tree of Digital humanities projects that Arnold and Bigtree are involved in, including, but not limited to, the aforementioned Doctrine of Discovery Project site and podcast. <em>Urgency of Indigenous Values</em> is best read with a pencil in one hand and an iPad in the other.</p>\n<p>That said, the book is strongest when read as a framework rather than a complete map. Arnold gives readers a way to rethink inherited categories. He shows that scholarly language is never neutral. It can repeat colonial habits or help unsettle them. His account of collaboration is central here. He rejects the image of the scholar as an outside expert who studies Indigenous peoples as objects. Instead, he argues for scholarship shaped by relationship, accountability, and shared concern. This is not only an ethical preference. It is part of the book's method. If knowledge is relational, then scholarship must also be relational.</p>\n<p><em>The Urgency of Indigenous Values</em> is a serious and needed book. Its main contribution is not that it discovers a new topic, but that it reframes an urgent one. Arnold asks readers to see that the ecological crisis is also a crisis of relation. The problem is not only what modern societies do to the land. The problem is what modern societies believe land is.</p>\n<p>The book is best read as an intervention. It challenges the academic study of religion, settler colonial law, Christian supremacy, environmental destruction, and the habits of extraction that shape modern life. Its strongest chapters show how Indigenous values offer more than critique. They offer practices of attention, habitation, reciprocity, and responsibility.</p>\n<p>Arnold's central lesson builds on the work of Faithkeeper Oren Lyons, as <a href=\"https://www.peacecouncil.net/NOON/articles/pnl732icemelting.html\">the ice melts in the north</a>, humanity's survival depends on a value change. And the values that produced the crisis will not solve it.</p>\n",
			"date_published": "2026-06-23T17:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/catastrophic-christianity/",
			"url": "https://www.adamdjbrett.com/blog/catastrophic-christianity/",
			"title": "Catastrophic Christianity Is Now Available",
			"content_html": "<p>I am pleased to share that my dissertation has now been published as a book: <em>Catastrophic Christianity: An Iconological Study of the Messianic Idea in American Protestant Christianity circa 1900--1940</em>. The book is available now through DTL Press and can be purchased through <a href=\"https://dtlcommons.org/product/catastrophic-christianity-brett/\">DTL Commons</a> and <a href=\"https://www.amazon.com/dp/B0GY8ZJLJG/\">Amazon</a>.</p>\n<p><a href=\"/assets/img/979-8-89731-285-6.webp\"><img src=\"/assets/img/979-8-89731-285-6_tn.webp\" alt=\"Art Deco black and gold style cover for Catastrophic Christianity\"></a></p>\n<p><a href=\"https://dtlcommons.org/product/catastrophic-christianity-brett/\">DTL Commons</a> <svg class=\"icon-svg\" aria-hidden=\"true\" viewBox=\"0 0 256 256\" focusable=\"false\"><path fill=\"currentColor\" d=\"M224,104a8,8,0,0,1-16,0V59.32l-66.33,66.34a8,8,0,0,1-11.32-11.32L196.68,48H152a8,8,0,0,1,0-16h64a8,8,0,0,1,8,8Zm-40,24a8,8,0,0,0-8,8v72H48V80h72a8,8,0,0,0,0-16H48A16,16,0,0,0,32,80V208a16,16,0,0,0,16,16H176a16,16,0,0,0,16-16V136A8,8,0,0,0,184,128Z\"></path></svg> or <a href=\"https://www.amazon.com/dp/B0GY8ZJLJG/\">Amazon</a> <svg class=\"icon-svg\" aria-hidden=\"true\" viewBox=\"0 0 256 256\" focusable=\"false\"><path fill=\"currentColor\" d=\"M224,104a8,8,0,0,1-16,0V59.32l-66.33,66.34a8,8,0,0,1-11.32-11.32L196.68,48H152a8,8,0,0,1,0-16h64a8,8,0,0,1,8,8Zm-40,24a8,8,0,0,0-8,8v72H48V80h72a8,8,0,0,0,0-16H48A16,16,0,0,0,32,80V208a16,16,0,0,0,16,16H176a16,16,0,0,0,16-16V136A8,8,0,0,0,184,128Z\"></path></svg></p>\n<p><em>Catastrophic Christianity</em> examines the messianic idea in &quot;America&quot; through early twentieth-century U.S. Protestant culture and popular media. The book traces how figures such as <em>The Fundamentals</em>, Superman comic books, Bruce Barton's capitalist Christianity, and <em>The Wizard of Oz</em> reveal two recurring ideological impulses: authoritarian-populism and catastrophic-utopianism. Together, these case studies show how messianism functions not only as a theological category, but as an iconological force shaping American religious, political, and cultural imagination.</p>\n<p>This project began as my doctoral dissertation in the Department of Religion at Syracuse University, and I remain deeply grateful to the people who made it possible. Thank you to my spouse, Stephanie Wyatt, for her love, patience, and support throughout the long life of this project. Thank you to my good friend Betty Hill, née Lyons, whose friendship, insight, and work continue to shape how I think about religion, power, and responsibility. I am also grateful to my advisors, Zachary J. Braiterman and Philip P. Arnold, whose guidance at Syracuse University helped bring this project into being. Finally, thank you to Tom Phillips and DTL Press for publishing the book and helping make this work available to a wider public.</p>\n<p>I am grateful that this work is now out in the world and available to readers interested in American Christianity, messianism, religion and popular culture, authoritarianism, and the religious imagination of catastrophe.</p>\n<p>Purchase the book here: <a href=\"https://dtlcommons.org/product/catastrophic-christianity-brett/\">DTL Commons</a> <svg class=\"icon-svg\" aria-hidden=\"true\" viewBox=\"0 0 256 256\" focusable=\"false\"><path fill=\"currentColor\" d=\"M224,104a8,8,0,0,1-16,0V59.32l-66.33,66.34a8,8,0,0,1-11.32-11.32L196.68,48H152a8,8,0,0,1,0-16h64a8,8,0,0,1,8,8Zm-40,24a8,8,0,0,0-8,8v72H48V80h72a8,8,0,0,0,0-16H48A16,16,0,0,0,32,80V208a16,16,0,0,0,16,16H176a16,16,0,0,0,16-16V136A8,8,0,0,0,184,128Z\"></path></svg> or <a href=\"https://www.amazon.com/dp/B0GY8ZJLJG/\">Amazon</a> <svg class=\"icon-svg\" aria-hidden=\"true\" viewBox=\"0 0 256 256\" focusable=\"false\"><path fill=\"currentColor\" d=\"M224,104a8,8,0,0,1-16,0V59.32l-66.33,66.34a8,8,0,0,1-11.32-11.32L196.68,48H152a8,8,0,0,1,0-16h64a8,8,0,0,1,8,8Zm-40,24a8,8,0,0,0-8,8v72H48V80h72a8,8,0,0,0,0-16H48A16,16,0,0,0,32,80V208a16,16,0,0,0,16,16H176a16,16,0,0,0,16-16V136A8,8,0,0,0,184,128Z\"></path></svg></p>\n<h2 id=\"marc-records\" tabindex=\"-1\">MARC Records <a class=\"header-anchor\" href=\"#marc-records\">#</a></h2>\n<ul>\n<li><a href=\"/assets/docs/catastrophic-christianity.mrc\">MARC Record</a></li>\n<li><a href=\"/assets/docs/catastrophic-christianity.csl.json\">CSL JSON</a></li>\n<li><a href=\"/assets/docs/catastrophic-christianity.ris\">RIS</a></li>\n</ul>\n",
			"date_published": "2026-05-21T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/postscript/",
			"url": "https://www.adamdjbrett.com/blog/postscript/",
			"title": "A Postscript: Sovereignty is Still the Issue",
			"content_html": "<h2 id=\"new-publication-a-postscript-sovereignty-is-still-the-issue\" tabindex=\"-1\"><strong>New Publication: &quot;A Postscript: Sovereignty Is Still the Issue&quot;</strong> <a class=\"header-anchor\" href=\"#new-publication-a-postscript-sovereignty-is-still-the-issue\">#</a></h2>\n<p>I am pleased to share the publication of &quot;A Postscript: Sovereignty Is Still the Issue,&quot; co-authored with Betty Hill (Lyons) and Nethanial Belmont, in the <a href=\"https://jcrt.org/\">Journal for Cultural and Religious Theory</a>.</p>\n<p>This article appears as part of JCRT 25.1 and reflects on the larger scholarly conversation generated by two special issues on domination, religion, law, Indigenous resistance, and the ongoing work of undoing Christian empire. In the postscript, we argue that sovereignty remains one of the most urgent questions for Indigenous studies, religious studies, and critical theory. Rather than treating sovereignty as a narrow legal category or as something granted through settler colonial recognition, we emphasize Indigenous sovereignty as lived, enacted, and grounded in land, language, traditional governance, and responsibilities to all living beings.</p>\n<p>I am grateful to have worked alongside Betty Hill (Lyons) and Nethanial Belmont on this piece, and I am thankful for the many scholars, elders, teachers, and community leaders whose work continues to shape this conversation. The publication represents one part of an ongoing effort to think beyond the Doctrine of Christian Discovery toward healing, restoration, and the renewal of right relationships with one another and with Mother Earth.</p>\n<p>Read the article here: <a href=\"https://jcrt.org/archives/25.1/postscript/\">&quot;A Postscript: Sovereignty Is Still the Issue&quot;</a></p>\n<p>Download the PDF here: <a href=\"https://files.jcrt.org/archives/25.1/postscript.pdf\">PDF version</a></p>\n",
			"date_published": "2026-05-20T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/zettelkasten/",
			"url": "https://www.adamdjbrett.com/blog/zettelkasten/",
			"title": "Zettelkasten as a Mind Garden",
			"content_html": "<p>It is not enough to read a text. Reading, by itself, too often leaves ideas inert—underlined passages fading into memory, PDFs piling up in folders never to be reopened. Learning begins when reading turns into thinking, and thinking turns into writing. For me, that transformation has long happened through a practice many of my students now encounter as the <em>Zettelkasten</em>—what I like to call a <em>mind garden</em>.</p>\n<p>Each week in my courses, students are expected to take notes and write short reflections on what they read in textbooks, articles, podcasts, and other course materials. These reading logs are not busywork. They are tools for cultivating critical reading and thinking skills. Active reading requires sustained engagement with a text: asking questions, noticing patterns, identifying tensions, and making connections across ideas. When students participate in this kind of reading, comprehension deepens, learning becomes stickier, and the course itself becomes more intellectually alive. You move from being a passive recipient of information to an active curator of knowledge.</p>\n<p>I still use reading logs myself. My own notes usually begin with the name of the piece and a short summary written in my own words. I add hashtags to help me rediscover ideas later, especially across projects and years. I include quotations that strike me as generative—phrases I know I will want to return to in future writing or teaching. Over time, these notes form a dense web of ideas rather than a linear archive. When I sit down to write, I am rarely starting from nothing; I am entering a conversation I have already been having with myself for years.</p>\n<p>This practice is inspired by the sociologist Niklas Luhmann, whose <em>Zettelkasten</em>—literally “slip box”—has become famous for its role in supporting an astonishingly productive scholarly life. Luhmann wrote short, self-contained notes, each focused on a single idea, and linked them together through references and keywords. The power of the system was not in any single note, but in the relationships between them. Ideas collided, cross-pollinated, and produced unexpected insights. Writing, for Luhmann, was not the final step of thinking; it was the continuation of thinking by other means.</p>\n<p>That is why I describe the <em>Zettelkasten</em> as a mind garden. Each note is a seed. Some grow quickly into sturdy trees—arguments, essays, lectures, podcasts. Others remain dormant for years until the right conditions bring them back to life. Connections between notes act as nutrients, helping ideas flourish in unexpected ways. The goal is not perfection or polish, but steady, thoughtful cultivation. Short, simple notes written consistently over time can support excellence in both thinking and writing.</p>\n<p>In my classes, I am not expecting students to create public-facing digital gardens or elaborate knowledge management systems. What I <em>am</em> asking is that they practice the habit of weekly note-making: slowing down, reflecting critically, and learning to trust that small intellectual investments compound over time. A well-kept reading log becomes the backbone of future assignments, especially larger projects like podcasts or research essays. More importantly, it becomes a companion—something students can carry with them beyond a single semester.</p>\n<p>The tools and resources below offer excellent entry points into the <em>Zettelkasten</em> tradition and its contemporary adaptations. Whether you are a student, a scholar, or simply someone trying to think more carefully in a noisy world, the invitation is the same: tend your mind as a garden. Read attentively. Write regularly. Let ideas grow together.</p>\n<hr>\n<h2 id=\"resources\" tabindex=\"-1\">Resources <a class=\"header-anchor\" href=\"#resources\">#</a></h2>\n<ul>\n<li>\n<p><strong>Mental Nodes</strong> – <em>A Gardening Guide for Your Mind</em><br>\nhttps://www.mentalnodes.com/a-gardening-guide-for-your-mind</p>\n</li>\n<li>\n<p>Schmidt, J. F. (2018). <em>Niklas Luhmann's Card Index: The Fabrication of Serendipity.</em><br>\n<em>Sociologica</em>, 12(1), 53–60. https://doi.org/10.6092/issn.1971-8853/8350</p>\n</li>\n<li>\n<p><strong>Sönke Ahrens</strong>, <em>Take Smart Notes</em><br>\nhttps://www.soenkeahrens.de/en/takesmartnotes#zettelkasten-en</p>\n</li>\n<li>\n<p><strong>Zettelkasten Method – Overview</strong><br>\nhttps://zettelkasten.de/overview/</p>\n</li>\n</ul>\n",
			"date_published": "2026-01-11T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2025-12-31-examining-doctrine-of-discovery/",
			"url": "https://www.adamdjbrett.com/blog/2025-12-31-examining-doctrine-of-discovery/",
			"title": "Examining the Doctrine of Discovery in Religion and Indigenous Studies",
			"content_html": "<h2 id=\"abstract\" tabindex=\"-1\">Abstract <a class=\"header-anchor\" href=\"#abstract\">#</a></h2>\n<p>Since the publication of <em>Pagans in the Promised Land</em> by Steven T. Newcomb (Shawnee/Lenape), scholarship on the Doctrine of Discovery has expanded significantly as a central issue in Indigenous law and politics. However, its implications remain underexamined in Religious Studies, Indigenous Studies, and legal scholarship. This article analyzes the matrix of enslavement, exploitation, and extraction that Newcomb identifies within settler-colonial systems and examines how scholars in Religious Studies, Legal Studies, and Indigenous Studies have engaged with the Doctrine of Discovery. Situating the Doctrine of Discovery within the broader analytical frameworks of enslavement, systemic violence, and religious imperialism reveals its deep entanglement with historic and legal structures of oppression. Examining its intersections with Religious Studies and postcolonial scholarship uncover how white Christian hegemony maintains its dominion and exposes the fragility of any perceived boundary between church and state.</p>\n<p><a href=\"https://doi.org/10.1111/rec3.70039\">read now</a></p>\n<h2 id=\"citation\" tabindex=\"-1\">Citation <a class=\"header-anchor\" href=\"#citation\">#</a></h2>\n<p>Brett, Adam D. J., and Betty Hill. 2026. “ Examining the Doctrine of Discovery in Religion and Indigenous Studies,” <em>Religion Compass</em>: e70039. <a href=\"https://doi.org/10.1111/rec3.70039\">https://doi.org/10.1111/rec3.70039</a>.</p>\n",
			"date_published": "2025-12-30T15:15:34Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2025-12-16-eleventy-build-times/",
			"url": "https://www.adamdjbrett.com/blog/2025-12-16-eleventy-build-times/",
			"title": "How I fixed an 11ty performance error that caused my build time to be seven minutes",
			"content_html": "<p>Inspired by the <a href=\"https://11tymeetup.dev/\">11tymeetup</a>, I decided to add a <a href=\"/blogroll\">blogroll</a>. I followed the suggestions in various tutorials; however, I forgot to include <a href=\"https://www.11ty.dev/docs/plugins/fetch/\">11ty fetch</a>. Satisfied, I ran my build, and I was horrified when my build time was a whopping 7 minutes!!!</p>\n<h2 id=\"what-changed\" tabindex=\"-1\">What changed <a class=\"header-anchor\" href=\"#what-changed\">#</a></h2>\n<p>Knowing I needed to make immediate changes to make the site leaner and faster, I made the following changes using the fetch plugin and <a href=\"https://www.11ty.dev/docs/deployment/#using-netlify-plugin-cache-to-persist-cache\">Netlify's persistent cache across deploys</a>. It wasn't until halfway through making changes that I started writing down the changes to remember in case I make this mistake again in the future.</p>\n<ol>\n<li><strong>Faster blogroll</strong> – Rewrote the blogroll data loader to use <a href=\"https://www.11ty.dev/docs/plugins/fetch/\">Eleventy Fetch</a> so RSS/Atom responses are cached to <code>.cache/blogroll</code>. The fetcher now logs how long it takes to hydrate the list and skips network calls during <code>FAST_BUILD=true</code> runs.</li>\n<li><strong>Cache persistence</strong> – Enabled <code>netlify-plugin-cache</code> in <code>netlify.toml</code> so deploys reuse the <code>.cache</code> directory. No more re-downloading dozens of feeds on every publish.</li>\n<li><strong>Node 22 + File polyfill</strong> – Bumped the toolchain to Node 22, added an <code>.nvmrc</code>.</li>\n<li><a href=\"https://www.raymondcamden.com/2025/04/30/a-test-of-eleventy-fetch\">Thanks to Raymond Camden's posts on Eleventy Fetch,</a> I realized my approach to 11ty fetch was far too hacky, and I needed something faster and lightweight, so I followed his recommendations.</li>\n<li><strong>Order of Build Operations</strong>  – Tag archive generation now skips the blogroll, minification and purgeCSS now happen before pagefind.app.</li>\n</ol>\n<p>These changes brought my build time down from the horrific high of seven minutes to 1.6 seconds on my machine and 37 seconds on Netlify.</p>\n<p>Having made these changes, I realized that I still had one more change to make, and that is to make sure my sitmap, feed, and tag collections exclude /blogroll/ and feed endpoints. I did this by making sure the sitemap template ignores pages whose permalink is <code>false</code> and this keeps the invalid URLs at bay.</p>\n<h2 id=\"other-changes\" tabindex=\"-1\">Other changes <a class=\"header-anchor\" href=\"#other-changes\">#</a></h2>\n<p>I also made some tweaks to speed up my local development.</p>\n<ul>\n<li><strong>Quicker feedback loops</strong>: With <code>FAST_BUILD=true</code>, the dev server spins up without waiting for purgeCSS, pagefind, or the blogroll fetch queue.</li>\n<li><strong>More resilient deploys</strong>: Netlify's cache keeps the pre-fetched feed responses and avoids hammering partner sites or rate-limiting APIs.</li>\n</ul>\n<h2 id=\"next-steps\" tabindex=\"-1\">Next Steps <a class=\"header-anchor\" href=\"#next-steps\">#</a></h2>\n<ul>\n<li><strong>Node Versions</strong>: The most recent Node version I can run on Netlify is Node 22, but Node is on versions 24 and 25, so I am making a note to watch Node versions and make sure my sites are on Node 24/25 as soon as they can be to keep future errors to a minimum.</li>\n<li><strong>Feed Errors</strong> Figure out what Apple Podcasts in my blogroll feed have valid XML but are logging parsing errors.</li>\n<li><strong>Pagefind.app and purgeCSS</strong>. I think I am doing something wrong, but everything is working for now, so it's my problem now. I definitely need to explore running pagefind and purgeCSS in parallel once heavy builds are re-enabled.</li>\n</ul>\n<p>If you are a newbie to Elveventy like me, I hope this is helpful but mostly this post is for future me.</p>\n",
			"date_published": "2025-12-16T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2025-12-15-eleventy-shortlinks-qr-code-purl/",
			"url": "https://www.adamdjbrett.com/blog/2025-12-15-eleventy-shortlinks-qr-code-purl/",
			"title": "Announcing a new 11ty Shortlink and QR Code Generator purl.im",
			"content_html": "<h2 id=\"announcing-a-new-11ty-shortlink-and-qr-code-generator-purl-im\" tabindex=\"-1\">Announcing a new 11ty Shortlink and QR Code Generator: <a href=\"https://purl.im\">purl.im</a> <a class=\"header-anchor\" href=\"#announcing-a-new-11ty-shortlink-and-qr-code-generator-purl-im\">#</a></h2>\n<p>Ever since the originary essay, I have been firmly committed to the philosophy of <a href=\"https://indieweb.org/A_Domain_of_One%27s_Own\">A Domain of One's Own (DoOO)</a> (<a href=\"https://www.adamdjbrett.com/blog/2024-11-22-why-scholars-should-own-their-online-presence/\">see a previous post</a>). Even before the concept came around, I had too many domain names and was encouraging others to have their own sites as well. One of the central problems with having your own site has been the walled gardens of social media. Getting people to leave the walled gardens of social media, stop scrolling, and read/watch/listen to human-crafted information remains a serious problem. Some ways around this have been &quot;link in bio&quot; and short links. The issues with these tools are that they tend to be yet another big tech walled garden. My friend <a href=\"https://eileencampbellreed.org/\">Eileen Campbell-Reed</a>, in her book <em><a href=\"https://bookshop.org/p/books/pastoral-imagination-bringing-the-practice-of-ministry-to-life-eileen-r-campbell-reed/9db03535934f6de8?ean=9781506470061&amp;next=t&amp;\">Pastoral Imagination</a>,</em> used her own custom link shortener that I helped her set up. This link shortener has worked great for easily typeable URLs for readers of the book and has allowed her to stop link rot in the book by updating the short links whenever links change (big shout-out to the internet's best friend, archive.org). Link rot is sadly a problem that is not going away soon. As link shorteners like goo.gl are being phased out and authors move between web frameworks and Content management systems, these problems persist.</p>\n<h3 id=\"a-shortlink-qr-code-combo\" tabindex=\"-1\">A Shortlink/QR code combo <a class=\"header-anchor\" href=\"#a-shortlink-qr-code-combo\">#</a></h3>\n<p>Working with Eileen helped me to see the ease of using a <a href=\"https://indieweb.org/A_Domain_of_One%27s_Own\">DoOO</a> for your own shortlink system; likewise, working with activists and organizers has taught me the frustration and limits of services like TinyURL and Bit.ly, where the shortlinks get increasingly convoluted to type. These issues led me to search for a solution. I wanted to find a self-hosted shortlink and QR code solution that was lightweight, easy to use and deploy, and, of course, open source. Netlify provides a super simple way to shorten links; however, I also wanted to be able to automatically generate QR codes for the shortlinks because if I need one, I will need the other. After asking around on Mastodon and Discord, I found two outstanding projects that I combined to make this project.  By the powers of <a href=\"https://github.com/nhoizey/1y\">1y</a> and <a href=\"https://github.com/philhawksworth/findthat.at\">findth.At</a>, I give you Frankenstein's Monster. The goal of this project was two-fold: first, to see if I could combine two of my favorite open-source projects into one, and second, to create a useful link shortener and QR code generator for my colleagues and me to use---my deepest gratitude and apologies to everyone involved. <a href=\"https://github.com/nhoizey\">@Nhoizey</a> and <a href=\"https://github.com/philhawksworth\">@philhawksworth</a>, you are both brilliant and incredible web developers. Thank you for shipping such outstanding open-source projects.</p>\n<h3 id=\"the-tech-stack-of-purl-im\" tabindex=\"-1\">The tech stack of <a href=\"https://purl.im\">purl.im</a> <a class=\"header-anchor\" href=\"#the-tech-stack-of-purl-im\">#</a></h3>\n<p>Under the hood, <a href=\"https://purl.im\">purl.im</a> is:</p>\n<ul>\n<li><a href=\"https://11ty.dev\"><strong>Built with 11ty</strong></a> for a fast, static site workflow</li>\n<li><a href=\"https://xmit.co\"><strong>Hosted on xmit</strong> (xmit.co)</a></li>\n<li><a href=\"https://pagescms.org\"><strong>Managed with Pages CMS</strong> (pagescms.org)</a> for easy shortlink creation</li>\n</ul>\n<p>The result is a link shortener and QR code generator that I can confidently share with colleagues, knowing it won't go anywhere as long as I maintain my domain.</p>\n<p>I decided not to use Netlify or Decap at this time because I have concerns about Netlify's new pricing model and did not want to receive a large surprise bill. On the 11ty Discord and Mastodon, people speak highly of Pages CMS's ease of use. Using and implementing Pages CMS was relatively easy. It did take me a while to figure out how to prevent pages from automatically appending a date to the markdown files, but after I solved that issue, it has been relatively smooth sailing. My one remaining problem with Pages is that it has been very confusing for non-technical users to log in. My next task is to create a help document outlining the workflow for <a href=\"https://purl.im\">purl.im</a> and the Pages CMS.</p>\n<h3 id=\"roll-out\" tabindex=\"-1\">Roll out <a class=\"header-anchor\" href=\"#roll-out\">#</a></h3>\n<p>Presently, I have implemented <a href=\"https://purl.im\">purl.im</a> on the following sites:</p>\n<ul>\n<li><a href=\"https://brett.im\">brett.im</a></li>\n<li><a href=\"https://aila.li\">aila.li</a></li>\n<li><a href=\"https://dofd.fyi\">dofd.fyi</a></li>\n</ul>\n",
			"date_published": "2025-12-15T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2025-12-04-uls-democracy/",
			"url": "https://www.adamdjbrett.com/blog/2025-12-04-uls-democracy/",
			"title": "United Lutheran Seminary to host &#39;A Vision for Liberating Our Democracy&#39; Conference, February 27–28",
			"content_html": "<h2 id=\"united-lutheran-seminary-to-host-a-vision-for-liberating-our-democracy-conference-february-27-28-2026\" tabindex=\"-1\">United Lutheran Seminary to Host &quot;A Vision for Liberating Our Democracy&quot; Conference, February 27--28, 2026 <a class=\"header-anchor\" href=\"#united-lutheran-seminary-to-host-a-vision-for-liberating-our-democracy-conference-february-27-28-2026\">#</a></h2>\n<h3 id=\"two-day-gathering-will-explore-the-religious-and-racialized-roots-of-american-democracy-and-paths-toward-a-more-just-future\" tabindex=\"-1\">Two-day gathering will explore the religious and racialized roots of American democracy and paths toward a more just future. <a class=\"header-anchor\" href=\"#two-day-gathering-will-explore-the-religious-and-racialized-roots-of-american-democracy-and-paths-toward-a-more-just-future\">#</a></h3>\n<p>United Lutheran Seminary (ULS) will host A Vision for Liberating Our Democracy: Examining the Religious and Racialized Roots of American Democracy on February 27--28, 2026, at its Philadelphia campus. The interdisciplinary conference will bring together scholars, activists, educators, and faith leaders to examine how religion and race have shaped democratic life in the United States and to explore liberative visions for the future.</p>\n<p>The conference builds on a growing body of research that examines the theological, cultural, and political intersections of democracy, citizenship, and power. Participants will investigate how worldviews and faith traditions have informed concepts of governance, belonging, and personhood from the founding era to the present. The conference will highlight not only the Haudenosaunee Influence on American Democracy but also the historic and present contributions to Democratic thought by Black, Indigenous, and Latine communities, contributions which are often forgotten and ignored.</p>\n<p>&quot;As America's oldest Lutheran seminary, founded by an antislavery theologian 200 years ago in Gettysburg on land that was to become part of the Civil War's greatest battlefield, United Lutheran Seminary has always been part of the nation's conversation on race and freedom,&quot; said the Rev. Dr. R. Guy Erwin (Osage Nation), ULS president. &quot;The Lutheran heritage of freedom of conscience and its emphasis on serving the common good draw us always from faith toward action. With this conference, our Seminary returns to the center of our current national debates.&quot;</p>\n<p>Dean Teresa L. Smallwood said, &quot;The American context is ripe for a time of reflection on the concept of democracy. &quot;We the People&quot; must evaluate our democratic commitments as we witness our nation entering a period of structural erosion. It is felt across all pockets of the nation. Have we redefined the governance schemata such that democracy is literally on life support? Do we continue to believe in the checks and balances of government? Is America a bastion for equality or have we reordered our commitments as a nation? These are some of the questions we must wrestle with at this conference.&quot;</p>\n<p>&quot;United Lutheran Seminary is committed to fostering public conversations about the moral and historical foundations of democracy,&quot; said the conference organizing committee member Adam DJ Brett. &quot;By examining the ways religion and race intertwine with political life, we can better imagine inclusive and equitable systems of governance.&quot;</p>\n<h3 id=\"featured-speakers\" tabindex=\"-1\"><strong>Featured Speakers</strong> <a class=\"header-anchor\" href=\"#featured-speakers\">#</a></h3>\n<p>The conference will feature exciting plenary addresses by:</p>\n<ul>\n<li><a href=\"https://civilrights.org/about/our-staff/maya-wiley/\">Maya D. Wiley</a>, President and CEO of Leadership Conference on Civil and Human Rights</li>\n<li><a href=\"https://soulforce.org/alba/\">Rev. Alba Onofrio</a> (Reverend Sex), Executive Director of Soulforce</li>\n<li><a href=\"https://www.morgan.edu/institute-for-urban-research/about/our-team/raymond-winbush\">Dr. Raymond Winbush</a>, Research Professor and the Director of the Institute for Urban Research, Morgan State University</li>\n<li><a href=\"https://bst.edu/people/joseph-evans/\">Rev. Dr. Joseph Evans</a>, The J. Alfred Smith, Senior Professor of Theology in the Public Square Director at Berkeley School of Theology</li>\n<li><a href=\"https://law.rutgers.edu/brandon-paradise\">Brandon Paradise</a>, Associate Professor of Law and Professor Dallas Willard Scholar at Rutgers Law School</li>\n<li><a href=\"https://www.doubleloveexperience.org/thewilkes\">Rev. Dr. Gabby Cudjoe Wilkes</a>, Pastor of The Double Love Experience Church</li>\n<li><a href=\"https://www.cnyhistory.org/wp-content/themes/oha/press/2015-10-11-55-SH.pdf\">Tadodaho Sidney Hill</a> of the Haudenosaunee Confederacy</li>\n<li><a href=\"https://aila.ngo/staff-and-board/\">Betty Hill (Lyons)</a>, (Onondaga Nation, Snipe Clan), Executive Director of the American Indian Law Alliance</li>\n<li><a href=\"https://thechavischronicles.com/about/\">Rev. Dr. Benjamin F. Chavis, Jr</a>., President and CEO of the National Newspaper Publishers Association (NNPA): The Black Press of America.</li>\n<li><a href=\"https://politicalresearch.org/bio/rev-naomi-washington-leapheart\">Rev. Naomi Washington-Leapheart</a>, Strategic Partnerships Director, Political Research Associates</li>\n<li><a href=\"https://www.feedingamerica.org/research/equity-research-fellow\">Rev. Dr. Yvette R. Blair-Lavallais</a>, Equity Research Fellow for Feeding America and Professor at Memphis Theological Seminary</li>\n<li><a href=\"https://religion.columbia.edu/content/obery-m-hendricks\">Rev .Dr. Obery M. Hendricks, Jr.</a>, Visiting Scholar, Departments of Religion &amp; African and African Diaspora Studies at Columbia University</li>\n<li><a href=\"https://sdpconference.info/news-and-highlights/leadership-transition\">Rev. Damien C. Durr</a>, General Secretary of the Proctor Conference</li>\n</ul>\n<h3 id=\"call-for-papers-the-organizing-committee-invites-papers-on-the-following-topics-to-be-covered-during-exploring-religion-race-and-democracy\" tabindex=\"-1\"><strong>Call for Papers - The organizing committee invites papers on the following Topics to Be Covered During Exploring Religion, Race, and Democracy:</strong> <a class=\"header-anchor\" href=\"#call-for-papers-the-organizing-committee-invites-papers-on-the-following-topics-to-be-covered-during-exploring-religion-race-and-democracy\">#</a></h3>\n<ul>\n<li>The Middle Passage, The Mid-Atlantic Slave Trade, Maa'afa</li>\n<li>The Continental Congress and the Balance of Power</li>\n<li>The Haudenosaunee Influence on American Democracy</li>\n<li>E.B. Du Bois and the Black Reconstruction of Democracy</li>\n<li>The Doctrine of Discovery and settler colonial foundations</li>\n<li>White Christian nationalism and the myth of civil religion</li>\n<li>Religion, race, and legal personhood</li>\n<li>Religion and resistance in Black, Indigenous, Latine, and immigrant communities</li>\n<li>Race, religion, and the media in shaping democratic narratives</li>\n<li>Womanist, Feminist, and Mujerista Methodologies</li>\n<li>Foreign Policy and Human Crises</li>\n</ul>\n<h3 id=\"submission-information\" tabindex=\"-1\"><strong>Submission Information</strong> <a class=\"header-anchor\" href=\"#submission-information\">#</a></h3>\n<p>The organizing committee invites proposals for papers, panel discussions, roundtables, and creative presentations. Submissions from scholars at all career stages, including graduate students and early-career researchers, are encouraged. We are open to presentations from independent scholars as well.</p>\n<p>The program will also include undergraduate poster sessions, graduate student panels, and live podcast recordings designed for classroom and public scholarship use. Following the event, an open-access journal volume will publish selected presentations.</p>\n<p>Proposals should include a 300-word abstract and a 100-word biography. The submission deadline is January 15, 2025. Proposals may be sent to <a href=\"mailto:abrett@uls.edu\">abrett@uls.edu</a>.</p>\n<h3 id=\"event-details\" tabindex=\"-1\"><strong>Event Details</strong> <a class=\"header-anchor\" href=\"#event-details\">#</a></h3>\n<ul>\n<li>Conference: A Vision for Liberating Our Democracy: Examining the Religious and Racialized Roots of American Democracy</li>\n<li>Dates: February 27--28, 2026</li>\n<li>Location: United Lutheran Seminary, 7301 Germantown Avenue, Philadelphia, PA 19119</li>\n<li>Submission Deadline: January 15, 2025</li>\n<li>Contact: Adam DJ Brett, <a href=\"mailto:abrett@uls.edu\">abrett@uls.edu</a></li>\n</ul>\n",
			"date_published": "2025-12-04T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2025-11-30-scholars-indieweb-carrd/",
			"url": "https://www.adamdjbrett.com/blog/2025-11-30-scholars-indieweb-carrd/",
			"title": "Embracing #nocode &amp; creating a website with Carrd",
			"content_html": "<h2 id=\"why-scholars-should-build-their-own-site-with-indieweb-carrd\" tabindex=\"-1\">Why Scholars Should Build Their Own Site with IndieWeb + Carrd <a class=\"header-anchor\" href=\"#why-scholars-should-build-their-own-site-with-indieweb-carrd\">#</a></h2>\n<p>As social media platfoms move more and more towards being walled gardens with ever shifting policies and AI creep opting out of these platforms takes on a new sense of urgency. For graduate students, contigent faculty, tenure track faculty, and independent scholars having a webpresence that does not rely on a university becomes increasingly vital.</p>\n<p>My personal theory is that as we see more AI creep and the decrease in search enginges abilities to return meaningful results there is going to be a resurgent interest in directories and individual webpages, in short the 90s are back this time out of necessity not nostalgia. I believe that scholars still need a stable, independent home on the web --- and that's exactly what the IndieWeb and no-code tools like Carrd make possible.</p>\n<h3 id=\"your-scholarly-identity-deserves-a-real-home-not-a-silo\" tabindex=\"-1\">Your scholarly identity deserves a real home, not a silo <a class=\"header-anchor\" href=\"#your-scholarly-identity-deserves-a-real-home-not-a-silo\">#</a></h3>\n<p>The IndieWeb isn't a fad or a niche movement --- it's a philosophy: personal websites, on your own domain, as your primary online identity. It champions owning your content, not renting your presence from algorithmic platforms. (<a href=\"https://indieweb.org/IndieWeb\">indieweb.org</a>)</p>\n<p>For a scholar, that means instead of relying on fragmented, institutionally-controlled pages or transient social media profiles, you have a stable digital &quot;room of your own.&quot; As many have argued, academics benefit greatly from such personal websites --- they offer a space for your CV, publications, syllabi, reflections, teaching philosophy, blog posts, and more. (<a href=\"https://www.insidehighered.com/digital-learning/views/2017/09/27/academics-need-develop-digital-presence-support-their-work\">Inside Higher Ed</a>)</p>\n<p>Your domain becomes a durable digital identity --- one that you control regardless of where life or your institution takes you. As one recent post noted, a custom domain &quot;signals authority and permanence&quot; (<a href=\"/blog/2024-11-22-why-scholars-should-own-their-online-presence/\">adamdjbrett.com</a>).</p>\n<h3 id=\"2-indieweb-no-code-low-friction-high-control\" tabindex=\"-1\">💡 2. IndieWeb + &quot;no-code&quot; = low friction, high control <a class=\"header-anchor\" href=\"#2-indieweb-no-code-low-friction-high-control\">#</a></h3>\n<p>If you're not a developer --- or simply very busy with teaching and research --- the technical overhead of building and maintaining a website can feel daunting. That's where no-code tools like Carrd really shine.</p>\n<p>Carrd lets you create clean, professional, responsive sites in minutes --- no coding required. As highlighted in &quot;Why Carrd.co Is the Best Platform for Simple, Responsive One-Page Sites,&quot; Carrd is ideal when what you need is a quick, budget-friendly online presence that still looks polished and professional. I have written on this topic previously, (<a href=\"/blog/2024-12-12-why-i-love-carrd-discount-code/\">&quot;Why Carrd.co Is the Best Platform for Simple, Responsive One-Page Sites, with Discount Code&quot;</a>)</p>\n<p>For many academics, a simple one-page site --- with links to your CV, publication list, contact info, maybe a short bio or blog feed --- may be all you need. And Carrd gives you just that: minimal hassle, full control, and a site that works on any device. Virginia Woolf was right you need a room of ones one and a domain of one's own, (<a href=\"/blog/2024-11-22-why-scholars-should-own-their-online-presence/\">&quot;Why Scholars Should Own Their Online Presence&quot;</a>).</p>\n<h3 id=\"a-personal-website-becomes-your-anchor-and-your-networked-hub\" tabindex=\"-1\">A personal website becomes your anchor --- and your &quot;networked&quot; hub <a class=\"header-anchor\" href=\"#a-personal-website-becomes-your-anchor-and-your-networked-hub\">#</a></h3>\n<p>When you own your site, you also determine how and where your content lives. A personal academic website can become a central hub: a place to house your scholarship, teaching resources, blog reflections, syllabi, podcasts, and more. You can link to social media, preprints, press coverage --- whatever represents your work --- on your terms (<a href=\"https://bastian.rieck.me/blog/2019/personal_website/\">bastian.rieck.me</a>).</p>\n<p>Moreover, the IndieWeb encourages not just ownership but connection: by using its open-web standards, your site can participate in decentralized conversations, syndicate posts, and stay compatible with long-term web culture built on openness, not walled gardens (<a href=\"https://indieweb.org/IndieWeb\">indieweb.org</a>).</p>\n<h3 id=\"for-scholars-especially-those-in-humanities-and-theology-nuance-and-control-matter\" tabindex=\"-1\">For scholars --- especially those in humanities and theology --- nuance and control matter <a class=\"header-anchor\" href=\"#for-scholars-especially-those-in-humanities-and-theology-nuance-and-control-matter\">#</a></h3>\n<p>As someone teaching courses working broadly in the &quot;Digital Humanities (???)&quot;, I am increasingly concerned about how quickly and easily trendy and popular platforms fade in and out of existence. A personal site gives you the flexibility to curate how your work is presented: syllabi, lecture notes, reading lists, public resources, multimedia, etc.</p>\n<h3 id=\"diy-vs-nocode\" tabindex=\"-1\">DIY vs #NoCode <a class=\"header-anchor\" href=\"#diy-vs-nocode\">#</a></h3>\n<p>I love building things for the web which is why I love and have built so many websites and projects with <a href=\"https://11ty.dev\">11ty</a>. While I believe that building and making your own site from scratch is not only doable but also fun! I realize that most other people have a very diffent definition of fund and hobbies and this is where high quality exportable #nocode tools like Carrd come into the piecture.</p>\n<h3 id=\"low-cost-easy-setup-minimal-barrier-to-entry\" tabindex=\"-1\">Low cost + easy setup = minimal barrier to entry <a class=\"header-anchor\" href=\"#low-cost-easy-setup-minimal-barrier-to-entry\">#</a></h3>\n<p>With Carrd, you don't need to invest in complex hosting, themes, or devops. As the post &quot;Why Carrd.co Is the Best Platform...&quot; explains, you can get a polished site for just ~$19/year with the Pro plan --- cheap, accessible, and sustainable (<a href=\"/blog/2024-12-12-why-i-love-carrd-discount-code/\">adamdjbrett.com</a>).</p>\n<p>If you want to experiment --- maybe a simple homepage, a pointer to a CV, a short blog --- it's an easy &quot;first step&quot; into the IndieWeb universe without committing to heavy website infrastructure.</p>\n<p>🔗 Want to explore more? <a href=\"https://try.carrd.co/adjb\">try.carrd</a>. If you sign up using this <a href=\"https://try.carrd.co/adjb\">discount code you can save 40%</a>.</p>\n<hr>\n<p>P.S. I never know exactly how to write for the web. Do you like the parenehttical footnote style hyperlinks I did here or do you want a more traditional web forward style where I link relevant text? I prefer the ladder.</p>\n",
			"date_published": "2025-11-30T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/deploying-eleventy-xmit/",
			"url": "https://www.adamdjbrett.com/blog/deploying-eleventy-xmit/",
			"title": "Deploying an Eleventy Site to XMIT using GitHub Actions",
			"content_html": "<h2 id=\"overview\" tabindex=\"-1\">Overview <a class=\"header-anchor\" href=\"#overview\">#</a></h2>\n<p>Thanks to the wonderful <a href=\"https://hcommons.social/tags/11ty\">#11ty</a> and <a href=\"https://hcommons.social/tags/webdev\">#webdev</a> communities on Mastodon, I interacted with <a href=\"https://pcarrier.com/\">Pierre Carrier</a> and learned about his great free web hosting project, <a href=\"https://xmit.co\">xmit.co</a>. To test it out, I migrated one website from an old shared hosting server and some others from Netlify. In both cases, moving to XMIT was easy.</p>\n<p>As Pierre explained recently on Discord, the whole project is super small and minimalistic, taking a direct path from vision to inception.  Wednesday, November 19<sup>th</sup>, He shared this on Discord. Look how beautiful small xmit's production codebase is:</p>\n<pre><code>pcarrier@dog /s/xmit.co (main) [124]&gt; tokei src\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n Language              Files        Lines         Code     Comments       Blanks\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n CSS                       1          241          201            0           40\n TSX                      11         2040         1951            1           88\n TypeScript                2           23           19            1            3\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n Total                    14         2304         2171            2          131\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n</code></pre>\n<p>I appreciate the minimalist/brutalist style of the project, even if it was rather disorienting to come from a fancy VC-backed host to something much more raw and independent. Personally, I love being back here amongst the <a href=\"https://hcommons.social/tags/indieweb\">#indieweb</a> community and living with the ethos of early web development with modern tools.</p>\n<h2 id=\"setup\" tabindex=\"-1\">Setup <a class=\"header-anchor\" href=\"#setup\">#</a></h2>\n<ol>\n<li>First, I signed up for an account over at <a href=\"https://xmit.co/\">xmit.com</a> and then I started exploring the user interface.</li>\n</ol>\n<p><img src=\"/assets/img/xmit/xmit-admin.webp\" alt=\"xmit admin screenshot\"></p>\n<ol start=\"2\">\n<li>As you can see from the screenshot above, the interface is no frills.\n<ol>\n<li>Once you are logged in, please add a recovery email and phone number</li>\n<li>Next, you will need to decide whether you want to bring your own domain or use one of the two included subdomains. If you are going to bring your own domain, follow <a href=\"https://xmit.co/docs\">this helpful guide in the docs</a>.\n<ol>\n<li>\n<p>Make sure your domain registrar allows you to use ANAME/ALIAS records. Then you will create an ANAME record for your team number at xmit.co. My team number is 268, so I will replace 42 in the examples below with my team number. The examples Pierre gives are repeated below\n<blockquote>\n<code>  \t@ CNAME 42.xmit.co.  \t* CNAME 42.xmit.co.  \t</code>\n</blockquote></p>\n</li>\n<li>\n<p>I found it very easy to create ANAME/ALIAS and CNAME records with the appropriate info, super easy. Personally, I went for the combo of an @ and a www. record for my domain names. <strong>One important note here is that you will need two records.</strong>.  I had to go back and create <a href=\"https://www.xmit.000000076.xyz/\">www.xmit.000000076.xyz</a> to get my sites working.</p>\n</li>\n<li>\n<p>For good measure, don't forget to also create the TXT record with your team number <code>@ TXT &quot;xmit=42&quot;</code> or in my case 268.</p>\n</li>\n<li>\n<p>If you decided to use one of the two included subdomains, you can skip these steps.</p>\n</li>\n</ol>\n</li>\n<li>Then, in your team marked by the  🏭 factory emoji, create your API keys. These are the keys you will use to deploy your site.</li>\n<li>Once the key is created, rename the key. In the box that pops up, type a name, and to save the key, press Enter; otherwise, the work you did won't save.</li>\n</ol>\n</li>\n<li>There are lots of ways to deploy your site. I chose to use GitHub Actions, so after naming my API key, I copied it and opened my repository in VS Code (my editor of choice), then created a file called <a href=\"https://github.com/adamdjbrett/dominationchronicles.com/blob/main/.github/workflows/xmit-deploy.yml\">.github/workflows/xmit-deploy.yml</a>.</li>\n<li>If you are going to use my <a href=\"https://github.com/adamdjbrett/dominationchronicles.com/blob/main/.github/workflows/xmit-deploy.yml\">.github/workflows/xmit-deploy.yml</a>, please make sure and change the following line:  <code>XMIT_SITE: dominationchronicles.com@268</code> to be your domain name and team number. Based on the Discord chat, I think the number is only needed the first time, but your mileage may vary.</li>\n<li>After creating this file, I went to GitHub.co &gt;&gt; my repository&gt;&gt; settings &gt;&gt; secrets and variables &gt;&gt; actions and created an action entitled <code>XMIT_KEY</code> where I then copied my XMIT API key. For all that is good and holy, never expose your API key publicly.</li>\n<li>Once my API key was safe and tucked away inside ```XMIT_KEY ``, I then pushed my repo to GitHub, and in less than two minutes, my site was live!.</li>\n</ol>\n<p>Thus far, I have been super happy with how hosting with XMIT has been going. I liked how easy it was, that there was no added bloat, and that it was a fairly turnkey, quick solution for web hosting.</p>\n<p>If you do decide to host with XMIT, please also join the Discord; it is a helpful place.</p>\n<p>Oh, and if you were wanting a more GUI-friendly deployment option, the newly released <a href=\"https://onclebob.com/\">Bob's your Oncole</a> can help.</p>\n<h2 id=\"to-cache-or-not-to-cache-on-github-actions\" tabindex=\"-1\">To Cache or Not to Cache on Github actions <a class=\"header-anchor\" href=\"#to-cache-or-not-to-cache-on-github-actions\">#</a></h2>\n<h3 id=\"with-cache\" tabindex=\"-1\">With Cache <a class=\"header-anchor\" href=\"#with-cache\">#</a></h3>\n<pre class=\"language-yaml\" tabindex=\"0\"><code class=\"language-yaml\"><span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Setup Node.js\n  <span class=\"token key atrule\">uses</span><span class=\"token punctuation\">:</span> actions/setup<span class=\"token punctuation\">-</span>node@v4\n  <span class=\"token key atrule\">with</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">node-version</span><span class=\"token punctuation\">:</span> <span class=\"token number\">20</span>\n    <span class=\"token key atrule\">cache</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'npm'</span>\n\n<span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Install dependencies\n  <span class=\"token key atrule\">run</span><span class=\"token punctuation\">:</span> npm ci</code></pre>\n<h3 id=\"without-cache\" tabindex=\"-1\">Without Cache <a class=\"header-anchor\" href=\"#without-cache\">#</a></h3>\n<pre class=\"language-yaml\" tabindex=\"0\"><code class=\"language-yaml\"><span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Setup Node.js\n  <span class=\"token key atrule\">uses</span><span class=\"token punctuation\">:</span> actions/setup<span class=\"token punctuation\">-</span>node@v4\n  <span class=\"token key atrule\">with</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">node-version</span><span class=\"token punctuation\">:</span> <span class=\"token number\">20</span>\n\n<span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Install dependencies\n  <span class=\"token key atrule\">run</span><span class=\"token punctuation\">:</span> npm install</code></pre>\n<p>in my experience <a href=\"https://github.com/adamdjbrett/11covers-theme/blob/main/.github/workflows/xmit-deploy.yml\">11Covers-Theme</a> Deploys fasters without the cache than with the cache. I cache <a href=\"https://github.com/adamdjbrett/dominationchronicles.com/blob/main/.github/workflows/xmit-deploy.yml\">Domination Chronicles</a> because of the number of assets in /public/ but I dont know if its the right thing to do. Based on the speed difference I'm debating removing the cache.</p>\n",
			"date_published": "2025-11-29T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2025-11-26-deploying-jekyll-xmit/",
			"url": "https://www.adamdjbrett.com/blog/2025-11-26-deploying-jekyll-xmit/",
			"title": "Deploying Jekyll to XMIT",
			"content_html": "<p>As the year comes to a close I am still working on reducing my hosting bills and exploring using <a href=\"https://xmit.co\">xmit.co</a> for hosting. In the last few days Pierre has refactored the homepage and documentation which makes using the service even easier and more appealing. Today's site that I decided to move over from netlify to xmit uses Jekyll so it was a bit tricky for the move. I havent touched Jekyll in a few months so I was a little out of practice. First I decoupled the site from netlify, updated the DNS ANAME, CNAME, and TXT records to using the <a href=\"https://xmit.co/docs\">DNS Configuration settings</a>. Then I updated the <code>xmity-deploy.yml</code> github action to work for jekyll. the file is below:</p>\n<pre class=\"language-yaml\" tabindex=\"0\"><code class=\"language-yaml\"><span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Deploy Jekyll to XMIT\n\n<span class=\"token key atrule\">on</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">push</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">branches</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">[</span><span class=\"token string\">\"main\"</span><span class=\"token punctuation\">,</span> <span class=\"token string\">\"master\"</span><span class=\"token punctuation\">]</span>\n  <span class=\"token key atrule\">workflow_dispatch</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">inputs</span><span class=\"token punctuation\">:</span>\n      <span class=\"token key atrule\">site</span><span class=\"token punctuation\">:</span>\n        <span class=\"token key atrule\">description</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"XMIT site/domain (e.g. example.com)\"</span>\n        <span class=\"token key atrule\">required</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n        <span class=\"token key atrule\">type</span><span class=\"token punctuation\">:</span> string\n\n<span class=\"token key atrule\">concurrency</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">group</span><span class=\"token punctuation\">:</span> deploy<span class=\"token punctuation\">-</span>xmit<span class=\"token punctuation\">-</span>$<span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> github.ref <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span>\n  <span class=\"token key atrule\">cancel-in-progress</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n\n<span class=\"token key atrule\">permissions</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">contents</span><span class=\"token punctuation\">:</span> read\n\n<span class=\"token key atrule\">jobs</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">deploy</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">runs-on</span><span class=\"token punctuation\">:</span> ubuntu<span class=\"token punctuation\">-</span>latest\n    <span class=\"token key atrule\">env</span><span class=\"token punctuation\">:</span>\n      <span class=\"token comment\"># Target site/domain for XMIT deploy</span>\n      <span class=\"token key atrule\">XMIT_SITE</span><span class=\"token punctuation\">:</span> example.com@268 \n    <span class=\"token key atrule\">steps</span><span class=\"token punctuation\">:</span>\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Checkout\n        <span class=\"token key atrule\">uses</span><span class=\"token punctuation\">:</span> actions/checkout@v4\n\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Setup Ruby\n        <span class=\"token key atrule\">uses</span><span class=\"token punctuation\">:</span> ruby/setup<span class=\"token punctuation\">-</span>ruby@v1\n        <span class=\"token key atrule\">with</span><span class=\"token punctuation\">:</span>\n          <span class=\"token key atrule\">ruby-version</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'3.3'</span>\n          <span class=\"token key atrule\">bundler-cache</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Build Jekyll site\n        <span class=\"token key atrule\">run</span><span class=\"token punctuation\">:</span> bundle exec jekyll build\n\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Verify build output\n        <span class=\"token key atrule\">run</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">|</span><span class=\"token scalar string\">\n          if [ ! -d _site ]; then\n            echo \"_site directory missing after build\" >&amp;2\n            exit 1\n          fi\n          ls -1 _site | head -n 20</span>\n\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Setup Node.js (for XMIT CLI)\n        <span class=\"token key atrule\">uses</span><span class=\"token punctuation\">:</span> actions/setup<span class=\"token punctuation\">-</span>node@v4\n        <span class=\"token key atrule\">with</span><span class=\"token punctuation\">:</span>\n          <span class=\"token key atrule\">node-version</span><span class=\"token punctuation\">:</span> <span class=\"token number\">20</span>\n\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Deploy to XMIT (CLI)\n        <span class=\"token key atrule\">env</span><span class=\"token punctuation\">:</span>\n          <span class=\"token key atrule\">XMIT_KEY</span><span class=\"token punctuation\">:</span> $<span class=\"token punctuation\">{</span><span class=\"token punctuation\">{</span> secrets.XMIT_KEY <span class=\"token punctuation\">}</span><span class=\"token punctuation\">}</span>\n        <span class=\"token key atrule\">run</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">|</span><span class=\"token scalar string\">\n          if [ -z \"$XMIT_KEY\" ]; then\n            echo \"XMIT_KEY secret is not set\" >&amp;2\n            exit 1\n          fi\n          # Use manual input when workflow_dispatch triggers this workflow\n          SITE_INPUT=\"${{ github.event_name == 'workflow_dispatch' &amp;&amp; inputs.site || '' }}\"\n          if [ -n \"$SITE_INPUT\" ]; then\n            export XMIT_SITE=\"$SITE_INPUT\"\n          fi\n          if [ -z \"$XMIT_SITE\" ]; then\n            echo \"XMIT site/domain not provided. Set repo Variable 'XMIT_SITE' or pass 'site' input.\" >&amp;2\n            exit 1\n          fi\n          echo \"Deploying _site to $XMIT_SITE via XMIT CLI\";\n          npx -y @xmit.co/xmit \"$XMIT_SITE\" _site || { echo 'XMIT deploy failed' >&amp;2; exit 1; }</span>\n\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Post<span class=\"token punctuation\">-</span>deploy summary\n        <span class=\"token key atrule\">run</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">|</span><span class=\"token scalar string\">\n          echo \"Deployment attempt finished for $XMIT_SITE\";\n          echo \"Visit: https://$XMIT_SITE\";</span>\n\n    <span class=\"token comment\"># Uncomment below for an alternative raw API upload if you have endpoint details</span>\n    <span class=\"token comment\"># steps:</span>\n    <span class=\"token comment\">#   - name: Deploy via API (curl)</span>\n    <span class=\"token comment\">#     run: |</span><span class=\"token scalar string\">\n    #       tar -czf site.tar.gz -C _site .\n    #       curl -f -X POST \\\n    #         -H \"Authorization: Bearer $XMIT_KEY\" \\\n    #         -F \"bundle=@site.tar.gz\" \\\n    #         https://api.xmit.example/deploy?site=$XMIT_SITE</span></code></pre>\n<p>After updating the <code>xmit-deploy.yml</code> file I naively thought that I would be good to go. However that was not the case. Immiediately my github action failed so I had to:</p>\n<ul>\n<li>upgrade ruby, bundler, and Jekyll</li>\n<li>remove the broken plugins of <code>jekyll-author-page</code> and <code>jekyll-tagsgenerator</code></li>\n</ul>\n<pre class=\"language-ruby\" tabindex=\"0\"><code class=\"language-ruby\">source <span class=\"token string-literal\"><span class=\"token string\">\"https://rubygems.org\"</span></span>\n\n<span class=\"token comment\"># This will help ensure the proper Jekyll version is running.</span>\ngem <span class=\"token string-literal\"><span class=\"token string\">\"jekyll\"</span></span><span class=\"token punctuation\">,</span> <span class=\"token string-literal\"><span class=\"token string\">\">= 4.3.3\"</span></span>\n\n<span class=\"token comment\"># Windows does not include zoneinfo files, so bundle the tzinfo-data gem</span>\ngem <span class=\"token string-literal\"><span class=\"token string\">'tzinfo-data'</span></span><span class=\"token punctuation\">,</span> <span class=\"token symbol\">platforms</span><span class=\"token operator\">:</span> <span class=\"token punctuation\">[</span><span class=\"token symbol\">:mingw</span><span class=\"token punctuation\">,</span> <span class=\"token symbol\">:mswin</span><span class=\"token punctuation\">,</span> <span class=\"token symbol\">:x64_mingw</span><span class=\"token punctuation\">,</span> <span class=\"token symbol\">:jruby</span><span class=\"token punctuation\">]</span>\n\n<span class=\"token comment\"># Required for Ruby 3.3+ (Jekyll/kramdown dependency)</span>\ngem <span class=\"token string-literal\"><span class=\"token string\">'rexml'</span></span>\n\ngroup <span class=\"token symbol\">:jekyll_plugins</span> <span class=\"token keyword\">do</span>\n  gem <span class=\"token string-literal\"><span class=\"token string\">'jekyll-paginate'</span></span><span class=\"token punctuation\">,</span> <span class=\"token string-literal\"><span class=\"token string\">'1.1.0'</span></span>\n  gem <span class=\"token string-literal\"><span class=\"token string\">'jekyll-seo-tag'</span></span><span class=\"token punctuation\">,</span> <span class=\"token string-literal\"><span class=\"token string\">'>= 2.8.0'</span></span>\n  gem <span class=\"token string-literal\"><span class=\"token string\">'jekyll-sitemap'</span></span><span class=\"token punctuation\">,</span> <span class=\"token string-literal\"><span class=\"token string\">'>= 1.4.0'</span></span>\n  gem <span class=\"token string-literal\"><span class=\"token string\">'jekyll-redirect-from'</span></span><span class=\"token punctuation\">,</span> <span class=\"token string-literal\"><span class=\"token string\">'>= 0.16.0'</span></span>\n  <span class=\"token comment\"># Remove jekyll-tagsgenerator and jekyll-author-page as they are not maintained for Jekyll 4.x. If you need similar functionality, consider alternatives or custom plugins.</span>\n<span class=\"token keyword\">end</span></code></pre>\n<p>I replaced the tag pages with <a href=\"https://rfong.github.io/rflog/2020/02/28/jekyll-tags/\">rflog's Automated Jekyll blog tags</a> and that worked nice and easily. I still havent replaced the <code>jekyll-author-page</code> plugin but that is tomorrows problem, I found <a href=\"https://jetholt.com/micro/jekyll-author-pages/\">jetroid's Jekyll Author Pages</a> which seems like a nice gem free alternative.</p>\n<p>After these updates to jekyll, I pushed to github and everything is working nicely with the site now living its best life over at <a href=\"https://xmit.co\">xmit.co</a></p>\n",
			"date_published": "2025-11-26T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2025-11-22-eleventy-xmit-redirects/",
			"url": "https://www.adamdjbrett.com/blog/2025-11-22-eleventy-xmit-redirects/",
			"title": "XMIT Redirects and 11ty",
			"content_html": "<p>If you followed the <a href=\"/blog/deploying-eleventy-xmit/\">setup on my previous article</a> on using <a href=\"https://xmit.co\">xmit.co</a> with Github actions you should also be mindful of how to setup redirects. Pierre the creator of XMIT was kind enough to help me when <a href=\"https://hcommons.social/@pc@rrier.fr/115590889337368819\">I posted on Mastodon</a>. He said if you want your redirects to work dont forget to copy your <code>xmit.toml</code> file into your <code>_site</code> directory. I took his advice and it works great. If you want to see how I did it check out my <a href=\"https://github.com/adamdjbrett/dominationchronicles.com/blob/main/eleventy.config.js\">11ty config file</a>.</p>\n<p>If yo uwish to use a custom 404 page on xmit.co along with redirects please note the 404 has to be before the redirect section. For example:</p>\n<pre class=\"language-toml\" tabindex=\"0\"><code class=\"language-toml\"><span class=\"token key property\">404</span> <span class=\"token punctuation\">=</span> <span class=\"token string\">\"404.html\"</span>\n\n<span class=\"token punctuation\">[</span><span class=\"token punctuation\">[</span><span class=\"token table class-name\">redirects</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span>\n<span class=\"token key property\">from</span> <span class=\"token punctuation\">=</span> <span class=\"token string\">\"^/youtube/?$\"</span>\n<span class=\"token key property\">to</span> <span class=\"token punctuation\">=</span> <span class=\"token string\">\"https://www.youtube.com/@DominationChronicles\"</span>\n<span class=\"token key property\">permanent</span> <span class=\"token punctuation\">=</span> <span class=\"token boolean\">true</span>\n\n<span class=\"token punctuation\">[</span><span class=\"token punctuation\">[</span><span class=\"token table class-name\">redirects</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span>\n<span class=\"token key property\">from</span> <span class=\"token punctuation\">=</span> <span class=\"token string\">\"^/podcast/?$\"</span>\n<span class=\"token key property\">to</span> <span class=\"token punctuation\">=</span> <span class=\"token string\">\"https://redcircle.com/shows/dominationchronicles\"</span>\n<span class=\"token key property\">permanent</span> <span class=\"token punctuation\">=</span> <span class=\"token boolean\">true</span></code></pre>\n",
			"date_published": "2025-11-25T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2024-12-13-my-eleventy-sites/",
			"url": "https://www.adamdjbrett.com/blog/2024-12-13-my-eleventy-sites/",
			"title": "My Eleventy Sites",
			"content_html": "<p>When it comes to building websites, static site generators (SSGs) have become a popular choice for developers who want fast, secure, and easily maintainable sites. Among the many options available, <a href=\"https://1ty.dev\">Eleventy | 11ty</a> stands out as one of the best. Lightweight yet powerful, <a href=\"https://1ty.dev\">Eleventy | 11ty</a> offers flexibility and simplicity that make it a top-tier choice. But how does <a href=\"https://1ty.dev\">Eleventy | 11ty</a> stack up against WordPress, the reigning CMS heavyweight, or Jekyll, another beloved SSG? Let’s break it down.</p>\n<h2 id=\"why-eleventy-is-the-best-static-site-generator-around\" tabindex=\"-1\">Why Eleventy Is the Best Static Site Generator Around <a class=\"header-anchor\" href=\"#why-eleventy-is-the-best-static-site-generator-around\">#</a></h2>\n<p>When it comes to building websites, static site generators (SSGs) have become a popular choice for developers who want fast, secure, and easily maintainable sites. Among the many options available, <a href=\"https://1ty.dev\">Eleventy | 11ty</a> stands out as one of the best. Lightweight yet powerful, Eleventy offers flexibility and simplicity that make it a top-tier choice. But how does Eleventy stack up against WordPress, the reigning CMS heavyweight, or Jekyll, another beloved SSG? Let's break it down.</p>\n<h3 id=\"1-eleventy-vs-wordpress\" tabindex=\"-1\"><strong>1. Eleventy vs. WordPress</strong> <a class=\"header-anchor\" href=\"#1-eleventy-vs-wordpress\">#</a></h3>\n<p>WordPress has long been a go-to solution for building websites, but its reliance on dynamic content generation comes with significant trade-offs. Here's why <a href=\"https://1ty.dev\">Eleventy</a> wins:</p>\n<h4 id=\"performance\" tabindex=\"-1\"><strong>Performance</strong> <a class=\"header-anchor\" href=\"#performance\">#</a></h4>\n<p>WordPress generates pages dynamically on each request, which can slow down loading times---especially for high-traffic sites. <a href=\"https://1ty.dev\">Eleventy</a>, on the other hand, pre-builds your site into static files, making it lightning-fast for end users. Static files are also better for SEO since page speed is a ranking factor.</p>\n<h4 id=\"security\" tabindex=\"-1\"><strong>Security</strong> <a class=\"header-anchor\" href=\"#security\">#</a></h4>\n<p>WordPress's complexity can be a double-edged sword. Its reliance on plugins and databases introduces vulnerabilities that often make it a target for hackers. With <a href=\"https://1ty.dev\">Eleventy</a>, your site is static, meaning there's no database to breach or server-side scripts to exploit. It's inherently more secure.</p>\n<h4 id=\"developer-control\" tabindex=\"-1\"><strong>Developer Control</strong> <a class=\"header-anchor\" href=\"#developer-control\">#</a></h4>\n<p><a href=\"https://1ty.dev\">Eleventy</a> is a developer-first tool. Unlike WordPress, which can feel bloated with unnecessary features, <a href=\"https://1ty.dev\">Eleventy</a> gives you full control over the codebase. You decide on the structure, templating language, and build process, without being locked into a proprietary ecosystem.</p>\n<h4 id=\"no-bloat\" tabindex=\"-1\"><strong>No Bloat</strong> <a class=\"header-anchor\" href=\"#no-bloat\">#</a></h4>\n<p>WordPress sites often accumulate &quot;plugin creep,&quot; where additional plugins are installed for minor functionality, resulting in unnecessary overhead. <a href=\"https://1ty.dev\">Eleventy</a> is lean by design, letting you build only what you need.</p>\n<h3 id=\"2-eleventy-vs-jekyll\" tabindex=\"-1\"><strong>2. Eleventy vs. Jekyll</strong> <a class=\"header-anchor\" href=\"#2-eleventy-vs-jekyll\">#</a></h3>\n<p>Jekyll has been a staple of the SSG community for years, especially for GitHub Pages. But <a href=\"https://1ty.dev\">Eleventy</a> has several advantages that make it a better choice in most cases:</p>\n<h4 id=\"speed-of-development\" tabindex=\"-1\"><strong>Speed of Development</strong> <a class=\"header-anchor\" href=\"#speed-of-development\">#</a></h4>\n<p>Jekyll relies on Ruby, which can have a steeper learning curve for developers unfamiliar with the language. <a href=\"https://1ty.dev\">Eleventy</a>, written in JavaScript, leverages a language most web developers already know. This makes it easier to onboard and maintain projects.</p>\n<h4 id=\"flexibility\" tabindex=\"-1\"><strong>Flexibility</strong> <a class=\"header-anchor\" href=\"#flexibility\">#</a></h4>\n<p>While Jekyll is tied to its Liquid templating system, <a href=\"https://1ty.dev\">Eleventy</a> supports multiple templating languages, including Markdown, Nunjucks, Liquid, and Handlebars. This flexibility allows you to pick the right tool for your specific needs or even mix and match templates within a single project.</p>\n<h4 id=\"modern-ecosystem\" tabindex=\"-1\"><strong>Modern Ecosystem</strong> <a class=\"header-anchor\" href=\"#modern-ecosystem\">#</a></h4>\n<p><a href=\"https://1ty.dev\">Eleventy</a> integrates seamlessly with modern JavaScript tooling, such as npm and bundlers like Vite. It also supports advanced features like serverless functions and API-driven workflows, making it more versatile than Jekyll for modern web projects.</p>\n<h4 id=\"simplified-build-process\" tabindex=\"-1\"><strong>Simplified Build Process</strong> <a class=\"header-anchor\" href=\"#simplified-build-process\">#</a></h4>\n<p><a href=\"https://1ty.dev\">Eleventy</a>'s setup is refreshingly simple. It doesn't require a rigid folder structure or opinionated defaults. You can drop files in any directory and configure the build process to your liking, which is much harder to achieve with Jekyll.</p>\n<h3 id=\"what-makes-eleventy-truly-special\" tabindex=\"-1\"><strong>What Makes Eleventy Truly Special?</strong> <a class=\"header-anchor\" href=\"#what-makes-eleventy-truly-special\">#</a></h3>\n<ol>\n<li><strong>Minimalism Meets Power</strong>: <a href=\"https://1ty.dev\">Eleventy</a>'s &quot;zero config&quot; philosophy means you can get started quickly, but it also offers deep customization options for complex projects.</li>\n<li><strong>Data Agnosticism</strong>: <a href=\"https://1ty.dev\">Eleventy</a> lets you pull content from almost anywhere---Markdown files, CMS APIs, JSON files, or even JavaScript functions. This makes it highly adaptable for projects of all sizes.</li>\n<li><strong>Community-Driven</strong>: <a href=\"https://1ty.dev\">Eleventy</a>'s open-source community is active and innovative, consistently contributing plugins and best practices.</li>\n<li><strong>Eco-Friendly</strong>: Static sites built with <a href=\"https://1ty.dev\">Eleventy</a> require fewer server resources, aligning with sustainable web development practices.</li>\n</ol>\n<h3 id=\"when-should-you-choose-eleventy\" tabindex=\"-1\"><strong>When Should You Choose Eleventy?</strong> <a class=\"header-anchor\" href=\"#when-should-you-choose-eleventy\">#</a></h3>\n<p><a href=\"https://1ty.dev\">Eleventy</a> is perfect for developers and designers who want:</p>\n<ul>\n<li>A fast, SEO-friendly site without the complexity of dynamic CMS platforms.</li>\n<li>A lightweight, flexible, and modern approach to building static websites.</li>\n<li>Complete control over the design and functionality of their projects.</li>\n</ul>\n<p>Whether you're building a personal blog, a portfolio site, or a small business website, <a href=\"https://1ty.dev\">Eleventy</a> offers an unbeatable combination of simplicity, performance, and adaptability.</p>\n<h3 id=\"conclusion\" tabindex=\"-1\"><strong>Conclusion</strong> <a class=\"header-anchor\" href=\"#conclusion\">#</a></h3>\n<p><a href=\"https://1ty.dev\">Eleventy</a> isn't just another static site generator; it's a game-changer in the world of web development. By combining the best aspects of speed, security, and flexibility, <a href=\"https://1ty.dev\">Eleventy</a> offers a superior alternative to WordPress and Jekyll.</p>\n<p>If you're ready to embrace a minimalist, developer-friendly approach to building websites, <a href=\"https://1ty.dev\">Eleventy</a> is the clear choice. So why wait? Dive into the <a href=\"https://1ty.dev\">Eleventy</a> ecosystem and discover how this powerful SSG can transform your web development workflow.</p>\n<h3 id=\"postscript\" tabindex=\"-1\">Postscript <a class=\"header-anchor\" href=\"#postscript\">#</a></h3>\n<h4 id=\"current-eleventy-sites\" tabindex=\"-1\">Current Eleventy Sites. <a class=\"header-anchor\" href=\"#current-eleventy-sites\">#</a></h4>\n<p>I plan on transferring as many sites as possible away from Jekyll and WorPress to #11ty. Here is my list of 11ty sites so far:</p>\n<h4 id=\"static-sites-built-and-managed\" tabindex=\"-1\">Static sites built and managed <a class=\"header-anchor\" href=\"#static-sites-built-and-managed\">#</a></h4>\n<p>The red balloon emojii means an 11ty site</p>\n<ul>\n<li><a href=\"https://adamdjbrett.com\">🎈 adamdjbrett.com</a></li>\n<li><a href=\"https://adamdj.tel\">🎈 adamdj.tel</a></li>\n<li><a href=\"https://aila.social\">🎈 aila.social</a></li>\n<li><a href=\"https://lakeback.org\">🎈 #lakeback</a></li>\n<li><a href=\"https://dofd.info\">🎈 dofd.info</a></li>\n<li><a href=\"https://desecratingthesacred.com\">🎈 desecratingthesacred.com</a></li>\n<li><a href=\"https://stevennewcomb.com\">🎈 stevennewcomb.com</a></li>\n<li><a href=\"https://doctrineofdiscovery.org\">🎈 doctrineofdiscovery.org</a></li>\n<li><a href=\"https://wocati.org/\">🎈 wocati.org</a></li>\n<li><a href=\"https://nabpr.org/\">🎈 nabpr.org</a></li>\n<li><a href=\"https://pbi.nabpr.org\">🎈 pbi.nabpr.org</a></li>\n<li><a href=\"https://relcfp.com/\">🎈 relcfp.com</a>Freelance Web Developer</li>\n<li><a href=\"https://rs-rss.com/\">🎈 rs-rss.com</a></li>\n<li><a href=\"https://podcasts.rs-rss.com/\">🎈 podcasts.rs-rss.com</a></li>\n</ul>\n<ul>\n<li><a href=\"https://www.thenandnow.us/\">thenandnow.us</a></li>\n<li><a href=\"http://www.sullivanclinton.com/\">sullivanclinton.com</a></li>\n<li><a href=\"https://www.derryveagh.com/\">derryveagh.com</a></li>\n<li><a href=\"https://www.stakedplains.com/\">stakedplains.com</a></li>\n<li><a href=\"http://stephaniewyatt.net/\">🎈 stephaniewyatt.net</a></li>\n<li><a href=\"https://stephaniewyatt.tel\">🎈 stephaniewyatt.tel</a></li>\n<li><a href=\"http://web.archive.org/web/20200322051959/https://www.waysofknowingskanonh.org/\">waysofknowingskanonh.org</a></li>\n<li><a href=\"http://web.archive.org/web//https://www.matildaeffect.events/\">matildaeffect.events</a></li>\n<li><a href=\"http://web.archive.org/web/20190325034727/https://honororenlyons.com/\">honororenlyons.com</a></li>\n<li><a href=\"http://spirittwinslacrosse.com/\">spirittwinslacrosse.com</a></li>\n<li><a href=\"https://www.virtualcomedycafe.com/\">virtualcomedycafe.com</a></li>\n<li><a href=\"https://lyons.chat/\">🎈 lyons.chat</a></li>\n<li><a href=\"https://doctrineofdiscovery.org/\">🎈 doctrineofdiscovery.org</a></li>\n<li><a href=\"https://podcast.doctrineofdiscovery.org/\">🎈 podcast.doctrineofdiscovery.org</a></li>\n<li><a href=\"https://outcome.doctrineofdiscovery.org\">🎈 outcome.doctrineofdiscovery.org</a></li>\n<li><a href=\"http://davidbrett.im/\">🎈 davidbrett.im</a></li>\n<li><a href=\"https://www.quotidian.pub/\">quotidian.pub</a> </li>\n<li><a href=\"https://www.alexanderosmith.com/\">alexanderosmith.com</a></li>\n<li><a href=\"https://podcast.doctrineofdiscovery.org/\">🎈 podcast.doctrineofdiscovery.org</a></li>\n<li><a href=\"https://000000076.xyz/\">🎈 themes: 000000076.xyz</a></li>\n<li><a href=\"https://rootedregalia.com\">🎈 rootedregalia.com</a></li>\n</ul>\n<h5>Cover Style Templates</h5>\n<ul>\n<li><a href=\"https://cover.000000076.xyz/\">11 Covers Theme</a> and <a href=\"https://github.com/adamdjbrett/11covers-theme\">Github repo</a>.\n<ul>\n<li><a href=\"https://adamdj.tel\">Adam DJ Brett | AdamDJ.tel</a> and <a href=\"https://github.com/adamdjbrett/adamdj-tel-11ty\">Github repo</a></li>\n<li><a href=\"https://cover.000000076.xyz/\">Cover</a></li>\n<li><a href=\"https://stephaniewyatt.tel\">Stephanie M. Wyatt - Card</a> and <a href=\"https://github.com/adamdjbrett/stephaniewyatt-tel-11ty\">Github repo</a></li>\n</ul>\n</li>\n</ul>\n<h5><a href=\"https://github.com/shanerobinson/linkist\">Linkist</a> Themes</h5>\n<ul>\n<li><a href=\"https://000000076.xyz/\">76 Oranges</a></li>\n<li><a href=\"https://aila.social\">AILA.social</a> and <a href=\"https://github.com/adamdjbrett/aila-social\">github repo</a></li>\n<li><a href=\"https://dofd.info\">DOFD.info</a> and <a href=\"https://github.com/adamdjbrett/dofd-info\">github repo</a></li>\n</ul>\n<h5>Multiplicity Themed Sites</h5>\n<ul>\n<li><a href=\"https://input.relcfp.com/\">Input for RELCFP</a> and <a href=\"https://github.com/adamdjbrett/input.relcfp.com\">Github repo</a></li>\n<li><a href=\"https://themidgeekcrisis.app/\">The Mid-Geek Crisis RSS News Aggregator</a> and <a href=\"https://github.com/adamdjbrett/themidgeekcrisis-app\">Github repo</a></li>\n<li><a href=\"https://rs-rss.com/\">The Religious Studies News RSS Aggregator</a> and <a href=\"https://github.com/adamdjbrett/rs-rss.com\">Github repo</a></li>\n<li><a href=\"https://podcast.rs-rss.com/\">The Religious Studies Podcast RSS Aggregator</a> and <a href=\"https://github.com/adamdjbrett/podcasts.rs-rss.com\">Github repo</a></li>\n<li><a href=\"https://theological.me/\">Theology RSS Aggregator</a> and <a href=\"https://github.com/adamdjbrett/theological.me\">Github repo</a></li>\n</ul>\n<h2 id=\"my-main-site\" tabindex=\"-1\">My Main site <a class=\"header-anchor\" href=\"#my-main-site\">#</a></h2>\n<ul>\n<li><a href=\"https://adamdjbrett.com\">AdamDJBrett.com</a></li>\n</ul>\n<h3 id=\"11ty-starters\" tabindex=\"-1\">11ty Starters <a class=\"header-anchor\" href=\"#11ty-starters\">#</a></h3>\n<ul>\n<li>\n<p><a href=\"https://inter.000000076.xyz/\">Inter/Swissfolio clone</a> and <a href=\"https://github.com/adamdjbrett/11ty-inter\">github repo</a></p>\n</li>\n<li>\n<p><a href=\"https://monospace.000000076.xyz/\">Monospace</a> and <a href=\"https://monospace.000000076.xyz/\">github repo</a></p>\n</li>\n<li>\n<p><a href=\"https://book.000000076.xyz/\">Monochrome Book</a> and <a href=\"https://github.com/adamdjbrett/11ty-book\">github repo</a></p>\n</li>\n<li>\n<p><a href=\"https://imbricate.000000076.xyz/\">Imbricate (μ CSS)</a> and <a href=\"https://github.com/adamdjbrett/11ty-imbricate\">github repo</a></p>\n</li>\n<li>\n<p><a href=\"https://neobrutalist.000000076.xyz/\">Neobrutalist</a> and <a href=\"https://github.com/adamdjbrett/11ty-neobrutalist\">github repo</a></p>\n</li>\n<li>\n<p><a href=\"https://brutalism.000000076.xyz/\">🧱 11ty Brutalism Theme</a> and <a href=\"https://github.com/adamdjbrett/11ty-brutalism\">github repo</a></p>\n</li>\n<li>\n<p><a href=\"https://long.000000076.xyz/\">11ty Long Reads</a> and <a href=\"https://github.com/adamdjbrett/11ty-long-reads\">github repo</a></p>\n</li>\n<li>\n<p><a href=\"https://clean.000000076.xyz/\">11ty Clean Blog by Start Boostrap</a> and <a href=\"https://github.com/adamdjbrett/11ty-clean-blog-startboostrap\">github repo</a></p>\n</li>\n<li>\n<p><a href=\"https://github.com/adamdjbrett/11covers-theme\">11 Covers Theme</a> and <a href=\"https://github.com/adamdjbrett/11covers-theme\">g ithub repo</a>.</p>\n<ul>\n<li>Demos: <a href=\"https://adamdj.tel\">AdamDJ.tel</a> and <a href=\"https://www.stephaniewyatt.tel/\">Stephanie M. Wyatt (tel)</a></li>\n</ul>\n</li>\n<li>\n<p><a href=\"https://eddy.000000076.xyz/\">11ty EDDY Template</a> and <a href=\"https://github.com/adamdjbrett/11ty-eddy\">github repo</a></p>\n</li>\n<li>\n<p><a href=\"https://journal.000000076.xyz/\">11ty Journal</a> and <a href=\"https://github.com/adamdjbrett/11ty-journal\">github repo</a></p>\n</li>\n<li>\n<p><a href=\"https://tufte.000000076.xyz/\">11ty Gets Tufte</a> and <a href=\"https://github.com/adamdjbrett/11ty-gets-tufte/\">github repo</a></p>\n</li>\n<li>\n<p><a href=\"https://strawberry.000000076.xyz/\">11ty Strawberry theme</a> and <a href=\"https://github.com/adamdjbrett/11ty-strawberry\">github repo</a></p>\n</li>\n<li>\n<p><a href=\"https://wisp.000000076.xyz/\">11ty Wisp theme</a> and <a href=\"https://github.com/adamdjbrett/11ty-wisp\">github repo</a></p>\n</li>\n<li>\n<p><a href=\"https://research.000000076.xyz/\">11ty Research Guide</a> and <a href=\"https://github.com/adamdjbrett/11ty-research-guide\">github repo</a></p>\n</li>\n<li>\n<p><a href=\"https://clean.000000076.xyz/\">11ty Clean Blog by Start Boostrap</a> and <a href=\"https://github.com/adamdjbrett/11ty-clean-blog-startboostrap\">github repo</a></p>\n</li>\n<li>\n<p><a href=\"https://github.com/adamdjbrett/11covers-theme\">11 Covers Theme</a> and <a href=\"https://github.com/adamdjbrett/11covers-theme\">github repo</a>.</p>\n<ul>\n<li>Demos: <a href=\"https://adamdj.tel\">AdamDJ.tel</a> and <a href=\"https://www.stephaniewyatt.tel/\">Stephanie M. Wyatt (tel)</a></li>\n</ul>\n</li>\n<li>\n<p><a href=\"https://eddy.000000076.xyz/\">11ty EDDY Template</a> and <a href=\"https://github.com/adamdjbrett/11ty-eddy\">github repo</a></p>\n</li>\n<li>\n<p><a href=\"https://journal.000000076.xyz/\">11ty Journal</a> and <a href=\"https://github.com/adamdjbrett/11ty-journal\">github repo</a></p>\n</li>\n<li>\n<p><a href=\"https://long.000000076.xyz/\">11ty Long Reads</a> and <a href=\"https://github.com/adamdjbrett/11ty-long-reads\">github repo</a></p>\n</li>\n<li>\n<p><a href=\"https://tufte.000000076.xyz/\">11ty Gets Tufte</a> and <a href=\"https://github.com/adamdjbrett/11ty-gets-tufte/\">github repo</a></p>\n</li>\n<li>\n<p><a href=\"https://research.000000076.xyz/\">11ty Research Guide</a> and <a href=\"https://github.com/adamdjbrett/11ty-research-guide\">github repo</a></p>\n</li>\n<li>\n<p><a href=\"https://strawberry.000000076.xyz/\">11ty Strawberry theme</a> and <a href=\"https://github.com/adamdjbrett/11ty-strawberry\">github repo</a></p>\n</li>\n<li>\n<p><a href=\"https://wisp.000000076.xyz/\">11ty Wisp theme</a> and <a href=\"https://github.com/adamdjbrett/11ty-wisp\">github repo</a></p>\n</li>\n</ul>\n<h3 id=\"other-sites\" tabindex=\"-1\">Other sites <a class=\"header-anchor\" href=\"#other-sites\">#</a></h3>\n<ul>\n<li><a href=\"https://outcome.doctrineofdiscovery.org\">Outcome</a></li>\n<li><a href=\"https://github.com/adamdjbrett/thanksforthereply\">Mirror of Andy Bell's Thanks for the Reply Guy</a></li>\n<li><a href=\"https://www.virtualcomedycafe.com/\">Virutal Comedy Cafe</a> and <a href=\"https://github.com/adamdjbrett/virtual-comedy-cafe\">Github repo</a></li>\n</ul>\n",
			"date_published": "2025-11-19T03:15:34Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2025-11-07-nuclear-energy-new-york/",
			"url": "https://www.adamdjbrett.com/blog/2025-11-07-nuclear-energy-new-york/",
			"title": "Commentary: Nuclear power is wrong for New York, environmentally and economically",
			"content_html": "<blockquote>\n<p>Gov. Kathy Hochul insists that nuclear power is the future for New York. We at the American Indian Law Alliance strongly oppose this view and call for caution.\nNuclear reactors are fundamentally dangerous and harmful to the environment and all living beings. Nuclear power is a controlled explosion until it becomes uncontrolled, at which point it turns deadly. Humans cannot control what is inherently uncontrollable.</p>\n</blockquote>\n<p><a href=\"https://www.timesunion.com/opinion/article/nuclear-power-wrong-new-york-environmentally-21125124.php\">Times Union</a> | <a href=\"https://archive.is/jnVYj\">Archive.org</a></p>\n",
			"date_published": "2025-11-07T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2025-10-30-profbook/",
			"url": "https://www.adamdjbrett.com/blog/2025-10-30-profbook/",
			"title": "Leave forprofit Academic Networking",
			"content_html": "<h2 id=\"update\" tabindex=\"-1\">Update <a class=\"header-anchor\" href=\"#update\">#</a></h2>\n<p>As of 2026 Profbook has shutdown</p>\n<h2 id=\"old-post\" tabindex=\"-1\">Old post <a class=\"header-anchor\" href=\"#old-post\">#</a></h2>\n<p>Looking for a not-for profit alternative for academics by academics? An alt to academia DOT edu, Facebook, Research Gate, etc.</p>\n",
			"date_published": "2025-10-30T01:15:34Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2025-10-09-qr-codes/",
			"url": "https://www.adamdjbrett.com/blog/2025-10-09-qr-codes/",
			"title": "How to Generate QR codes in macOS",
			"content_html": "<p>Generating a QR code used to be so simple when goo.gl existed, as it was a great link shortener and QR code generator. However, Alphabet/Google, in their infinite wisdom, has decided to close the service, and then they were going to sunset all the links, which would have caused massive <a href=\"https://en.wikipedia.org/wiki/Link_rot\">linkrot</a> on a <a href=\"https://en.wikipedia.org/wiki/Dead_Internet_theory\">dying(dead?) internet</a>. However, thanks to public outcry, Google has reversed <a href=\"https://blog.google/technology/developers/googl-link-shortening-update/\">its decision</a>.  Google's decision further illustrates the importance of <a href=\"https://bavatuesdays.com/a-domain-of-ones-own/\">a domain of ones own</a>. My dear friend and colleague, Eileen Campbell-Reed, understood this point. When she published her book, <em><a href=\"https://eileencampbellreed.org/about/pastoral-imagination-bringing-the-practice-of-ministry-to-life/\">Pastoral Imagination: Bringing the Practice of Ministry to Life,</a></em> she utilized her own domain name, linkshorter, and QR codes, ensuring that her book had little to no link rot.  </p>\n<p>Thanks to the simplicity of <a href=\"https://docs.netlify.com/manage/routing/redirects/overview/\">Netlify's</a> <code>_redirects</code> file, I can easily run my own link shorteners. However, one ongoing issue I face is generating QR codes quickly and effortlessly. I dislike using standard link shortening QR code services because some of these services want to lock you into high monthly fees, inject their own tracking, and set arbitrary limits on the codes. Another concern is what happens if the service is case sensitive, which can cause users to accidentally visit a different site. I want to create branded shortlinks and QR codes on a domain I own so that users and scanners can trust both, without injecting third-party code. For a while, I considered building my own QR code generator website, but that seemed like overkill. Instead, I once again turned to my trusty homebrew solution for Mac.</p>\n<h2 id=\"generating-qr-codes-on-macos\" tabindex=\"-1\">Generating QR Codes on macOS <a class=\"header-anchor\" href=\"#generating-qr-codes-on-macos\">#</a></h2>\n<ol>\n<li>Install <a href=\"https://brew.sh\">homebrew</a></li>\n<li>install <a href=\"https://formulae.brew.sh/formula/qrencode\">qrencode</a>\n<ol>\n<li><a href=\"https://github.com/fukuchi/libqrencode?tab=readme-ov-file\">Qrencode on Github</a></li>\n<li><a href=\"https://fukuchi.org/en/works/qrencode/\">Qrencode official site</a></li>\n</ol>\n</li>\n</ol>\n<p>I found the official documentation to be deeply unhelpful, however <a href=\"https://medium.com/macoclock/i-cant-explain-how-useful-these-9-mac-homebrew-tools-are-66ee1ec7870\">Nikhil Vemu</a> has a very helpful explainer. Here is what was most helpful to me:</p>\n<pre><code>qrencode -o code.png &quot;https://aila.li/olp&quot; -s 8\n</code></pre>\n<p>The default size of 3 is barely 99 pixels square, size 8 is almost 250 pixels which for me is a much more useful size.</p>\n",
			"date_published": "2025-10-09T05:02:34Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2025-10-09-webp-jpg/",
			"url": "https://www.adamdjbrett.com/blog/2025-10-09-webp-jpg/",
			"title": "How to convert JPG to WEBP in macOS",
			"content_html": "<p>In the quest for ultrafast websites and the every elusive four-hundos score in Google's lighthouse, I have recently begun to explore what are the best and fastest ways to convert JPG and PNG files to webp. Certainly I could use online tools to convert the images but then, there are concerns of course about webtools renaming files, modifying metadata, and of course having limits on them. Therefore I turned to a Mac users best friend <a href=\"https://brew.sh\">homebrew</a> where I found the wonderful <a href=\"https://formulae.brew.sh/formula/webp\">Homebrew Formulae for webp</a>. The tool is super easy to install and use.</p>\n<ol>\n<li>install <a href=\"https://brew.sh/\">homebrew</a></li>\n<li><code>brew install webp</code></li>\n<li>press return</li>\n<li>wait</li>\n<li>navigate to the folder that has the image you want to convert</li>\n<li><code>cwebp input.jpg -o output.webp</code></li>\n<li>press return\nDone</li>\n</ol>\n<p>If you have a whole folder you wish to convert you can use <a href=\"https://medium.com/@philwornath/macos-convert-all-images-in-folder-to-webp-24bdf50c121c\">Phil Warnath</a>'s super helpful script:</p>\n<pre class=\"language-bash\" tabindex=\"0\"><code class=\"language-bash\"><span class=\"token function\">find</span> <span class=\"token builtin class-name\">.</span> <span class=\"token parameter variable\">-type</span> f <span class=\"token punctuation\">\\</span><span class=\"token punctuation\">(</span> <span class=\"token parameter variable\">-iname</span> <span class=\"token string\">'*.png'</span> <span class=\"token parameter variable\">-o</span> <span class=\"token parameter variable\">-iname</span> <span class=\"token string\">'*.jpg'</span> <span class=\"token parameter variable\">-o</span> <span class=\"token parameter variable\">-iname</span> <span class=\"token string\">'*.jpeg'</span> <span class=\"token punctuation\">\\</span><span class=\"token punctuation\">)</span> <span class=\"token parameter variable\">-exec</span> <span class=\"token function\">sh</span> <span class=\"token parameter variable\">-c</span> <span class=\"token string\">'cwebp -quiet \"$1\" -o \"${1%.*}.webp\"'</span> _ <span class=\"token punctuation\">{</span><span class=\"token punctuation\">}</span> <span class=\"token punctuation\">\\</span><span class=\"token punctuation\">;</span>\n</code></pre>\n",
			"date_published": "2025-10-09T01:15:34Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2025-10-02-erie-canal/",
			"url": "https://www.adamdjbrett.com/blog/2025-10-02-erie-canal/",
			"title": "What are we celebrating with the Erie Canal?",
			"content_html": "<blockquote>\n<p>Looking at the ecocide caused and still being caused by the Erie Canal and Onondaga Lake, we ask ourselves: What does the Erie Canal symbolize? Genocide and ecocide.\n<a href=\"https://www.syracuse.com/opinion/2025/10/what-are-we-celebrating-with-the-erie-canal-a-gash-in-mother-earth-guest-opinion-by-betty-hill-adam-dj-brett.html\">Read more at Syracuse.com</a></p>\n</blockquote>\n",
			"date_published": "2025-10-02T01:15:34Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2025-09-01-healing-the-sacred/",
			"url": "https://www.adamdjbrett.com/blog/2025-09-01-healing-the-sacred/",
			"title": "Healing the Sacred",
			"content_html": "<h2 id=\"healing-the-sacred-the-fight-to-restore-onondaga-lake-and-honor-indigenous-land\" tabindex=\"-1\">Healing the Sacred: The Fight to Restore Onondaga Lake and Honor Indigenous Land <a class=\"header-anchor\" href=\"#healing-the-sacred-the-fight-to-restore-onondaga-lake-and-honor-indigenous-land\">#</a></h2>\n<h3 id=\"abstract\" tabindex=\"-1\">Abstract <a class=\"header-anchor\" href=\"#abstract\">#</a></h3>\n<p>The Onondaga Nation is petitioning the Organization of American States (OAS) for land rights to Onondaga Lake, a notoriously polluted body of water in Central New York State. The Onondaga Nation is one of six nations of the Haudenosaunee Confederacy (Iroquois), and Onondaga Lake is the sacred site where <em>Gayanashagowa</em>, the Great Law of Peace, was established. As Keepers of the Central Fire, the Onondaga Nation bears the responsibility of maintaining unity and peace within the Haudenosaunee Confederacy. This article examines the history of the lake, its significance to the Haudenosaunee Confederacy, and the consequences of its desecration through industrial pollution. By juxtaposing Haudenosaunee teachings with the European Christian Doctrine of Discovery, we reveal how clashing worldviews led to violence, land theft, and genocide against the Haudenosaunee and other Indigenous Nations. Specifically, we apply Steven T. Newcomb's Domination Code to analyze the settler-colonial justification for resource extraction, which left behind ecological and social devastation. We argue that returning Onondaga Lake to the Onondaga Nation is a vital step toward restoring this sacred place, bringing long-overdue healing to its people, the surrounding communities, and the natural world. The protection and restoration of Onondaga Lake is not only essential for its future but for the well-being of all. The restoration of Indigenous sacred spaces is a catalyst for meaningful social and ecological change.</p>\n<p><a href=\"https://commons.lib.jmu.edu/ijr/vol9/iss1/2/\">read more</a></p>\n",
			"date_published": "2025-09-01T01:15:34Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2025-06-27-crosscurrents/",
			"url": "https://www.adamdjbrett.com/blog/2025-06-27-crosscurrents/",
			"title": "New CrossCurrents Special Issue",
			"content_html": "<p>New CrossCurrents Special Issue Vol.74.No.4 out now: <a href=\"https://muse.jhu.edu/issue/55074\"><em>200 Years of Johnson v. M’Intosh: Indigenous Responses to the Religious Foundations of Racism</em></a></p>\n<p><img src=\"/assets/img/9781469683744.webp\" alt=\"Front Cover\"></p>\n<p><a href=\"https://muse.jhu.edu/issue/55074\">Read Now</a> or <a href=\"https://uncpress.org/book/9781469683744/crosscurrents-200-years-of-johnson-v-mintosh-indigenous-responses-to-the-religious-foundations-of-racism/\">buy as a print book or ebook</a>.</p>\n",
			"date_published": "2025-02-23T03:15:34Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2025-02-23-get-tufte/",
			"url": "https://www.adamdjbrett.com/blog/2025-02-23-get-tufte/",
			"title": "Get Tufte with 11ty",
			"content_html": "<h2 id=\"embracing-tuftes-design-principles-in-my-new-11ty-starter\" tabindex=\"-1\">Embracing Tufte’s Design Principles in My New 11ty Starter <a class=\"header-anchor\" href=\"#embracing-tuftes-design-principles-in-my-new-11ty-starter\">#</a></h2>\n<p>I've always admired Edward Tufte’s approach to design—his emphasis on clarity, simplicity, and the thoughtful presentation of information. That’s why I’m excited to share my latest 11ty web starter, which is built around Tufte’s design principles.</p>\n<p>Tufte’s philosophy is all about maximizing the data-to-ink ratio, meaning every element on the page should serve a purpose. His designs prioritize content over decoration, offering a minimalist aesthetic that feels timeless and professional. In my 11ty starter, I’ve incorporated features like side notes, subtle typography, and a focus on whitespace to create a clean and readable web experience.</p>\n<p>For me, this project isn’t just about building a theme—it’s about creating a tool for anyone who wants to share information clearly and effectively. Whether you’re crafting essays, publishing research, or just want a no-nonsense blog, this starter is designed to keep the focus on your content.</p>\n<p>If you're interested, you can check out the demo and explore the <a href=\"https://tufte.000000076.xyz/\">demo</a> code on <a href=\"https://github.com/adamdjbrett/11ty-gets-tufte/\">GitHub</a>. I hope this project inspires others to embrace Tufte’s principles and build websites that are as beautiful as they are functional.</p>\n<p>I used these same principals for another 11ty starter called <a href=\"https://wisp.000000076.xyz/\">Wisp</a>.</p>\n<h2 id=\"demos\" tabindex=\"-1\">Demos <a class=\"header-anchor\" href=\"#demos\">#</a></h2>\n<ul>\n<li><a href=\"https://tufte.000000076.xyz/\">11ty Gets Tufte</a> and <a href=\"https://github.com/adamdjbrett/11ty-gets-tufte/\">github repo</a></li>\n<li><a href=\"https://wisp.000000076.xyz/\">11ty Wisp theme</a> and <a href=\"https://github.com/adamdjbrett/11ty-wisp\">github repo</a></li>\n</ul>\n",
			"date_published": "2025-02-23T03:15:34Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2025-02-22-brutalism-eleventy-web-design/",
			"url": "https://www.adamdjbrett.com/blog/2025-02-22-brutalism-eleventy-web-design/",
			"title": "My (Neo)Brutalism 11ty Web Design Experiments",
			"content_html": "<h2 id=\"neo-brutalism\" tabindex=\"-1\">(Neo)Brutalism <a class=\"header-anchor\" href=\"#neo-brutalism\">#</a></h2>\n<h3 id=\"why-i-m-drawn-to-brutalist-web-design\" tabindex=\"-1\">Why I’m Drawn to Brutalist Web Design <a class=\"header-anchor\" href=\"#why-i-m-drawn-to-brutalist-web-design\">#</a></h3>\n<p>Brutalist web design has always fascinated me for its raw and unapologetic aesthetic. Much like its architectural counterpart, brutalism in web design strips away the polished layers of modern design trends and focuses instead on functionality and honesty. There's something refreshing about a site that doesn’t hide behind gradients, soft shadows, or overly smooth animations. Instead, it presents itself with bold typography, stark contrasts, and an almost jarring straightforwardness.</p>\n<p>For me, the appeal lies in how brutalist design challenges our expectations of the web. It invites users to engage with content directly—without distraction—and often carries a playful or experimental edge. The aesthetic isn't about being crude for its own sake; it’s about rejecting unnecessary embellishments and embracing a kind of digital honesty.</p>\n<p>I also love how brutalism opens up creative possibilities. When you’re not bound by conventional design rules, you have the freedom to try unconventional layouts, bold color schemes, and unique interactions. It’s an aesthetic playground that encourages exploration and offers a kind of authenticity that’s rare in a world where many websites look and feel the same.</p>\n<p>Ultimately, brutalist web design is about embracing imperfection and valuing substance over style. It aligns perfectly with my interest in minimal computing and the #minicomp movement—both prioritize function, sustainability, and a bit of rebellion against the status quo.</p>\n<h3 id=\"embracing-neo-brutalism\" tabindex=\"-1\">Embracing Neo-Brutalism <a class=\"header-anchor\" href=\"#embracing-neo-brutalism\">#</a></h3>\n<p>I've been experimenting with design frameworks lately, and I'm excited to share an 11ty web starter, which uses the <a href=\"https://matifandy8.github.io/NeoBrutalismCSS/\"><strong>NeoBrutalismCSS</strong></a> framework by Matias Fandiño. <a href=\"https://matifandy8.github.io/NeoBrutalismCSS/\">NeoBrutalismCSS</a> is all about embracing the raw and unapologetic aesthetics of neo-brutalism in web design. It offers a minimalist approach, applying fundamental styles based on HTML semantics without the clutter of endless class names and complex configurations.</p>\n<p>What I love most about NeoBrutalismCSS is how it pairs simplicity with boldness. The design language is straightforward---there are no hidden tricks or unnecessary flourishes. Instead, it focuses on creating a visually striking and highly functional web experience. The framework's minimalist approach aligns perfectly with the #minicomp philosophy I'm so passionate about, emphasizing minimal design, minimal maintenance, and minimal obsolescence.</p>\n<p>If you're curious, you can check out the <a href=\"https://neobrutalist.000000076.xyz/\"><strong>11ty NeoBrutalismCSS demo</strong></a> and explore the <a href=\"https://github.com/adamdjbrett/11ty-neobrutalist\">GitHub repository</a>. I hope this new starter inspires others to experiment with neo-brutalist aesthetics and build websites that are as bold as they are simple.</p>\n<h3 id=\"classic-brutalism\" tabindex=\"-1\">Classic Brutalism <a class=\"header-anchor\" href=\"#classic-brutalism\">#</a></h3>\n<p>Going back to basics here is an 11ty web starter using the <a href=\"https://github.com/pruger/tiny-brutalism-css\"><strong>Tiny Brutalism CSS</strong> framework</a>. This minimalist framework is all about bold, monochrome colors, hard edges, and those iconic prominent drop shadows. At under 4KB, Tiny Brutalism CSS lives up to its name---tiny, fast, and to the point.</p>\n<p>What I love most about this framework is how it strips design down to the essentials. There's a kind of honesty in the starkness of brutalism that challenges the polished, overproduced aesthetics we see everywhere online. Plus, the simplicity of Tiny Brutalism CSS aligns perfectly with my passion for minimal computing---focusing on minimal design, minimal maintenance, and minimal obsolescence.</p>\n<p>If you'd like to see it in action, check out the <a href=\"https://brutalism.000000076.xyz/\"><strong>11ty Brutalism Theme demo</strong> here</a> and explore the <a href=\"https://github.com/adamdjbrett/11ty-brutalism\">GitHub repository</a>. I hope this starter inspires others to experiment with bold, minimalistic web design and embrace the power of simplicity.</p>\n<h2 id=\"demos\" tabindex=\"-1\">Demos <a class=\"header-anchor\" href=\"#demos\">#</a></h2>\n<ul>\n<li><a href=\"https://neobrutalist.000000076.xyz/\">Neobrutalist</a> and <a href=\"https://github.com/adamdjbrett/11ty-neobrutalist\">github repo</a></li>\n<li><a href=\"https://brutalism.000000076.xyz/\">11ty Brutalism Theme</a> and <a href=\"https://github.com/adamdjbrett/11ty-brutalism\">github repo</a></li>\n</ul>\n",
			"date_published": "2025-02-22T03:15:34Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2025-02-21-my-tiny-11ty-sites/",
			"url": "https://www.adamdjbrett.com/blog/2025-02-21-my-tiny-11ty-sites/",
			"title": "My Tiny Eleventy (11ty) Sites",
			"content_html": "<h2 id=\"new-11ty-website-starters-my-approach-to-lightweight-and-reader-friendly-web-design\" tabindex=\"-1\">New 11ty Website Starters: My Approach to Lightweight and Reader-Friendly Web Design <a class=\"header-anchor\" href=\"#new-11ty-website-starters-my-approach-to-lightweight-and-reader-friendly-web-design\">#</a></h2>\n<p>I've been diving deep into the Eleventy (11ty) Static Site Generator (SSG) lately, and I'm excited to share some new website starters I've developed with a friend. These themes are built around the <a href=\"https://go-dh.github.io/mincomp/thoughts/2020/07/21/minimal-ontology/\">#minicomp ontology</a>: minimal design, minimal maintenance, and minimal obsolescence. My goal with both projects was to create lightweight, flexible, and highly readable web experiences that reflect my passion for simplicity and usability.</p>\n<h3 id=\"1-imbricate-feat-m-css\" tabindex=\"-1\">1. <strong>Imbricate feat. μ CSS</strong> <a class=\"header-anchor\" href=\"#1-imbricate-feat-m-css\">#</a></h3>\n<p><a href=\"https://imbricate.000000076.xyz/\">Imbricate feat. μ CSS</a> started as a thought experiment with a friend. We wanted to see how far we could take the concept of an ultra-lightweight theme using the μ CSS framework, which is just 1KB in size. This theme is all about keeping things simple and responsive, staying true to the #minicomp principles.</p>\n<p>Some of the features I'm particularly proud of include:</p>\n<ul>\n<li><strong>Tiny footprint:</strong> The minimal size of the μ CSS framework keeps the site fast and efficient.</li>\n<li><strong>Simplicity and Responsiveness:</strong> I aimed to make a theme that's easy to maintain and perfect for projects where speed and simplicity are top priorities.</li>\n</ul>\n<p>If you'd like to see it in action, check out the <a href=\"https://imbricate.000000076.xyz/\">demo site</a> or dig into the <a href=\"https://github.com/adamdjbrett/11ty-imbricate\">GitHub repository</a> to explore the code.</p>\n<h4 id=\"m-css\" tabindex=\"-1\">μ CSS <a class=\"header-anchor\" href=\"#m-css\">#</a></h4>\n<p><a href=\"https://github.com/BafS/mu\">μ CSS</a> is an incredibly interesting framework for website development due to its ultra-compact size, lightning-fast speed, and refreshing simplicity. At just 1 KB, μ CSS embodies the &quot;less is more&quot; philosophy, ensuring that websites load quickly and maintain a minimal footprint. Its mobile-first design approach guarantees compatibility across all screen sizes and browsers, while its straightforward styling keeps content legible and accessible to all visitors. <a href=\"https://github.com/BafS/mu\">μ CSS</a> proves that effective web design doesn't need to be complicated—it just needs to get the point across.</p>\n<h3 id=\"2-11ty-long-reads\" tabindex=\"-1\">2. <strong>11ty Long Reads</strong> <a class=\"header-anchor\" href=\"#2-11ty-long-reads\">#</a></h3>\n<p>The idea for <a href=\"https://long.000000076.xyz/\">11ty Long Reads</a> came from a conversation on Blue Sky with <a href=\"https://bsky.app/profile/tessa.germnetwork.com\">@tessalaprofessa</a>. They mentioned how great it would be if blog themes had features like Instapaper and e-readers, giving users control over the reading experience by adjusting font family, font size, line height, font color, and background color.</p>\n<p>I built this theme with that vision in mind, offering:</p>\n<ul>\n<li><strong>Customizable Reading Experience:</strong> Readers can adjust visual settings to make long-form content more comfortable to read.</li>\n<li><strong>E-Reader Style Features:</strong> The theme is ideal for blogs or any site with a focus on extended reading sessions.</li>\n</ul>\n<p>Feel free to explore the <a href=\"https://long.000000076.xyz/\">demo</a> and, if you're interested, the <a href=\"https://github.com/adamdjbrett/11ty-long-reads\">GitHub repository</a> has all the code.</p>\n<h3 id=\"what-i-like-about-these-themes\" tabindex=\"-1\">What I like about these themes <a class=\"header-anchor\" href=\"#what-i-like-about-these-themes\">#</a></h3>\n<p>I believe that websites shouldn't just look good---they should also be practical and sustainable. Both of these 11ty starters are designed to help creators build sites that are not only beautiful and functional but also align with the ideals of the #minicomp movement.</p>\n<p>Whether you're looking to create a no-frills, fast-loading site or a customizable, reader-focused blog, I hope these starters provide a solid foundation. As always, I'm looking forward to seeing how others might use and adapt these tools.</p>\n",
			"date_published": "2025-02-21T03:15:34Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2025-01-06-religious-freedom-limits/",
			"url": "https://www.adamdjbrett.com/blog/2025-01-06-religious-freedom-limits/",
			"title": "On the Limits of the Concept of Religious Freedom in Indigenous Communities",
			"content_html": "<h2 id=\"abstract\" tabindex=\"-1\">Abstract <a class=\"header-anchor\" href=\"#abstract\">#</a></h2>\n<p>In this essay, we will argue that firstly, the international and national legal framings of religion or belief are limited in scope, and one must ask not only religious freedom <em>for whom</em> but also <em>from whom</em>. Secondly, we will underscore the continued limitations of international human rights-based discourse. Why are Indigenous nations consistently excluded from rights-based discourses? We have the UN Declaration on Human Rights (UNDHR), the UN Declaration on the Rights of Indigenous Peoples (UNPFII), the Expert Mechanism on the Rights of Indigenous Peoples (EMRIP), this new report, and so many other reports. We will ask at what stage we move from declarations and reports to protecting and supporting Indigenous nations and peoples. Thirdly, building on the limitations of rights-based reporting, we will highlight what this report gets right and invite activists, lawyers, scholars, and all folks to take up and read the report and follow up on the elements we believe to be most salient. Finally, we will conclude by offering an alternative to declarations that support Indigenous nations and peoples' inherent right to sovereignty. Our conclusion emphasizes Faithkeeper Lyons' urgent message, &quot;The Ice is Melting in the North,&quot; and provides a framework for how people could respond by explaining the Two Row Wampum treaty and the Two Row Wampum Method.</p>\n<h2 id=\"citation\" tabindex=\"-1\">Citation <a class=\"header-anchor\" href=\"#citation\">#</a></h2>\n<p>Brett, Adam DJ, and Betty Hill (Lyons). 2024. “On the Limits of the Concept of Religious Freedom in Indigenous Communities”. <em>Journal of the Council for Research on Religion</em> 5 (2). Montreal, QC, Canada:75-96. <a href=\"https://doi.org/10.26443/jcreor.v5i2.117\" target=\"_blank\" rel=\"noopener\">https://doi.org/10.26443/jcreor.v5i2.117</a>.</p>\n<p><a href=\"/assets/pdfs/Limits-religious-freedom-Brett-Hill-Lyons.bib\">RIS File</a></p>\n",
			"date_published": "2025-01-06T03:15:34Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2025-01-01-11ty-clean-blog-clean-repo/",
			"url": "https://www.adamdjbrett.com/blog/2025-01-01-11ty-clean-blog-clean-repo/",
			"title": "11ty Clean blog and cleaner repository",
			"content_html": "<p>I have been loving the new <a href=\"https://11ty.dev/\">11ty</a> 3.0.0 release. This release is radically simple and for someone like me who is just dipping my toes into the <a href=\"https://11ty.dev/\">11ty</a> waters having a simplifed SSG is critical. One of the things I have been working on this holiday break is trying to figure out what is my optimal repoistory layout. I want to keep things, clean, simple, and easy for myself and whomever may look at my code or projects later.</p>\n<p>In order to better understand one how best to create an <a href=\"https://11ty.dev/\">11ty</a> template for myself and two how best to make this structure, I ported <a href=\"https://startbootstrap.com/theme/clean-blog\">Start Boostrap</a>'s Clean blog template to <a href=\"https://11ty.dev/\">11ty</a>.</p>\n<p>The strucutre that I like is below</p>\n<pre><code>/11ty-clean-blog-startboostrap\n├── /_config\n├── /_data\n├── /_includes\n│   └── /_includes/partials\n├── /content\n│   ├── /content/blog\n│   └── /content/feed\n└── /public\n    ├── /public/css\n    ├── /public/images\n    └── /public/js\n</code></pre>\n<p>Filters go in <code>_config</code> to be set and left alone. <code>_Data</code> for anyting I want to customize. <code>_includes</code> was tricky. I am still trying to figure out a reasonable balance between too many and not enough partials for templating here. Any guidance would be appreciated.</p>\n<p>Pages go out in the open in /content/, Collections into a lovely subfolder (/blog), and beautiful RSS feeds go into /feed. Taking advantage of the new <a href=\"https://github.com/11ty/eleventy/releases/tag/v3.0.0\">11ty 3.0.0</a> plugins like image transform, and others I have moved images, css, and js to make pass through easier and in order to simply my own config files.</p>\n<p>Also thanks to <a href=\"https://11tybundle.dev\">Bob Monsor</a>, <a href=\"https://www.creativitas.dev/\">Creativas.dev</a> and all of the wonderful folks in the community who have written posts about implementing <a href=\"https://pagefind.app/\">pagefind.app</a>.</p>\n<p>If you wish to see my porting of clean blog the demo is at: <a href=\"https://clean.000000076.xyz/\">clean.000000076.xyz/</a> and <a href=\"https://github.com/adamdjbrett/11ty-clean-blog-startboostrap\">github repo</a></p>\n",
			"date_published": "2025-01-01T03:15:34Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2024-12-27-learning-eleventy-by-adapting-jekyll/",
			"url": "https://www.adamdjbrett.com/blog/2024-12-27-learning-eleventy-by-adapting-jekyll/",
			"title": "Learning 11ty by adapting a Jekyll Template",
			"content_html": "<p>Presently my favorite Static Site Generator (SSG) is <a href=\"https://11ty.dev\">11ty</a>. I love 11ty for many reasons first its adaptability, customizability, speed, and stability. 11ty unlike WordPress and Jekyll gets out of the way and allows me to focus on content.  Jekyll feels fun but as many have said it feels <a href=\"https://talk.jekyllrb.com/t/has-jekyll-development-stalled/8478\">abandoned/stalled</a>. Perhaps due to Jekyll being stalled, Dependabot is consistently giving me notices and alerts, which I appreciate but it takes my time away from other things. Likewise I'm consistently fussing with settings on Github Pages and Netlify to get Netlify to deploy. None of those issues exist when I am working with 11ty. Therefore one of my goals for 2025 is to transition away from Jekyll and towards 11ty.</p>\n<p>One of the things that is overwhelming to me about 11ty is just how customizable and open it is. I frequently find myself overwhelmed by the fact that everything is possible but I am limited by my own skills and ability (which fair). Another barrier that trips me up is often 11ty <em>feels</em> and acts so similar to Jekyll that I get surprised and confused when 11ty doesn't work like Jekyll.</p>\n<p>Over the holiday break I decided to work with <a href=\"https://www.creativitas.dev/\">Creativitas.dev</a>&amp;emdash;a colleague from the 11ty community&amp;emdash; on adapting/porting a <a href=\"https://minicomp.github.io/ed/\">Ed.</a> a <a href=\"https://go-dh.github.io/mincomp/\">#minicomp</a> theme for public humanities.</p>\n<h2 id=\"process\" tabindex=\"-1\">Process <a class=\"header-anchor\" href=\"#process\">#</a></h2>\n<p>What I started by doing was taking the Jekyll theme, breaking it down into its component parts and then 11ty-ifying [<em>sic</em>] them.</p>\n<h3 id=\"directory-structure\" tabindex=\"-1\">Directory Structure <a class=\"header-anchor\" href=\"#directory-structure\">#</a></h3>\n<p>I roughed out the following directory structure\n11ty-eddy</p>\n<pre><code>├── LICENSE.md\n├── README.md\n├── _data\n│   ├── metadata.json\n├── _includes\n│   ├── article.njk\n│   ├── base.njk\n│   ├── home.njk\n│   ├── narrative.njk\n│   ├── partials\n│   │   ├── aside _narrative.njk\n│   │   ├── aside.njk\n│   │   ├── editor_notes.njk\n│   │   ├── head.njk\n│   │   ├── header.njk\n│   │   ├── menu.njk\n│   │   ├── menu_narrative.njk\n│   │   ├── narrative_info.njk\n│   │   ├── nav.njk\n│   │   ├── search.njk\n│   │   ├── sidebar.njk\n│   │   ├── sidebar_narrative.njk\n│   │   └── toc.njk\n│   └── textslist.njk\n├── content\n│   ├── index.md\n│   ├── pages\n│   │   ├── 404.md\n│   │   ├── about.md\n│   │   ├── credits.md\n│   │   ├── documentation.md\n│   │   ├── pages.11tydata.js\n│   │   └── search.md\n│   ├── sitemap.xml.njk\n│   ├── tag-pages.njk\n│   ├── tags.njk\n│   ├── texts\n│   │   ├── drama\n│   │   │   └── raisin.md\n│   │   ├── narrative\n│   │   │   └── narrative.md\n│   │   ├── poem\n│   │   │   ├── a-julia.md\n│   │   │   ├── delayed.md\n│   │   │   ├── dreams.md\n│   │   │   └── o-captain.md\n│   │   └── texts.11tydata.js\n│   └── texts.njk\n├── public\n│   ├── css\n│   │   ├── main.css\n│   │   └── nu.css\n│   ├── img\n│   ├── js\n│   │   └── main.js\n└── END\n</code></pre>\n<p>The biggest changes that I made were first splitting the texts out by type to make it easier for me to template in 11ty and to see visually in my codebase which texts are using which layout types. Next I had to wrap my head around Jekyll <code>layouts</code> and <code>includes</code> versus 11ty <code>includes</code> and <code>partials.</code> As I was porting the template, there were so many differences that in order to better focus and make problem solving simple, Creativitas recommended splitting the <code>partials</code> up into very small files and that helped tremendously with the issues.</p>\n<h2 id=\"scss-css\" tabindex=\"-1\">SCSS --&gt; CSS <a class=\"header-anchor\" href=\"#scss-css\">#</a></h2>\n<p>Another big change was moving away from SCSS to CSS because I want to be able to use and teach this template in a public humanities course and while I love SCSS I think for students CSS might be easier? We will see.</p>\n<h2 id=\"liquid\" tabindex=\"-1\">Liquid <a class=\"header-anchor\" href=\"#liquid\">#</a></h2>\n<p>Thanks to Creativitas assistance and thanks to <a href=\"https://web.archive.org/web/20240401170655/https://blog.ltgt.net/from-jekyll-to-eleventy/\">this tutorial</a> by Thomas Broyer, I learned that when adapting Jekyll to 11ty there are differences in liquid templating and while minor they are still important. <a href=\"https://katiekodes.com\">Katie Kodes</a> outlined the <a href=\"https://katiekodes.com/liquid-includes-jekyll-vs-11ty/\">5 things you need to know about Jekyll vs. 11ty Liquid includes</a>.</p>\n<h2 id=\"markdown\" tabindex=\"-1\">Markdown <a class=\"header-anchor\" href=\"#markdown\">#</a></h2>\n<p>The next big issue with adapting this template was markdown processors. I am most familiar with Kramdown but 11ty defaults to <a href=\"https://www.11ty.dev/docs/languages/markdown/#default-options\">Markdown-it</a> so then we had issues with footnotes and table of contents two vital features of this theme. Thankfully <a href=\"https://rknight.me/\">robb knight</a> and <a href=\"https://11tybundle.dev/\">Bob Monsour</a> over on Mastodon were able to point me in the right direction. Also Bob humorously reminded me of the awesome resource that is his site <a href=\"https://11tybundle.dev/\">11tybundle.dev</a>.</p>\n<h3 id=\"markdown-plugins\" tabindex=\"-1\">Markdown Plugins <a class=\"header-anchor\" href=\"#markdown-plugins\">#</a></h3>\n<p>Thanks to these fine folks, <a href=\"https://plug11ty.com/plugins/table-of-contents/\">11ty TOC</a>, and <a href=\"https://www.npmjs.com/package/markdown-it-footnote\">markdown-it-footnote</a> the template now has a Table of Contents and Footnotes! Both plugins were very straight forward to add. Also shout out to the community repository <a href=\"https://plug11ty.com/\">plug11ty</a>.</p>\n<h2 id=\"pagefind\" tabindex=\"-1\">pagefind <a class=\"header-anchor\" href=\"#pagefind\">#</a></h2>\n<p>the next change that we made to the template was replacing lunr JS with <a href=\"https://pagefind.app/\">pagefind</a>. I really love pagefind it is such an excellent and lightweight search bundle but it constantly give me fits setting it up in 11ty. Someone should write a post on how to add page find easily to 11ty.</p>\n<h2 id=\"other-changes\" tabindex=\"-1\">Other changes <a class=\"header-anchor\" href=\"#other-changes\">#</a></h2>\n<ul>\n<li>We also updated to the newer <a href=\"https://web.hypothes.is/help/installing-the-bookmarklet/\">Hypothes.is bookmarklet</a></li>\n<li>We also added <code>language:</code> to <code>texts</code> front matter so that browsers can be notified if sites have multilingual content.</li>\n</ul>\n<h2 id=\"conclusion\" tabindex=\"-1\">Conclusion <a class=\"header-anchor\" href=\"#conclusion\">#</a></h2>\n<p>Overall it took fifteen hours for <a href=\"https://minicomp.github.io/ed/\">Ed</a> to become <a href=\"https://eddy.000000076.xyz/\">Eddy</a>. Porting this site would not have been possible without the wonderful folks in the <a href=\"https://11ty.dev\">11ty</a> community and the brave folks who not only #BuildinPublic but also blog and talk about their experience so that others can learn from them. Once again building <em>anything</em> is an activity that is best done in community, at least for me.</p>\n",
			"date_published": "2024-12-27T03:15:34Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2024-12-12-why-i-love-carrd-discount-code/",
			"url": "https://www.adamdjbrett.com/blog/2024-12-12-why-i-love-carrd-discount-code/",
			"title": "Why Carrd.co Is the Best Platform for Simple, Responsive One-Page Sites, with Discount Code",
			"content_html": "<p>If you need a quick, clean, and professional online presence without the fuss of managing a full website, <a href=\"https://carrd.co\"><strong>Carrd.co</strong></a> is the perfect platform. It’s specifically designed for creating simple, fully responsive one-page websites for nearly any purpose—portfolios, resumes, small business pages, event promotions, or personal profiles. Carrd excels in its ease of use, affordability, and elegant design options. With its intuitive drag-and-drop editor, anyone can build a polished site in minutes, no coding required. Plus, every site automatically adjusts to look great on desktops, tablets, and smartphones, ensuring you make a strong impression on any device.</p>\n<p>Compared to platforms like WordPress, Carrd is often the better choice for most users who only need a single, streamlined page. WordPress is a powerful tool, but its complexity can be overwhelming for simpler needs. Managing plugins, themes, and hosting can feel like overkill when all you want is a concise, beautiful webpage. Carrd eliminates that hassle entirely—no hosting worries, no unnecessary features, just everything you need to create a sleek, professional page. For only $19 a year for a Pro plan, Carrd is budget-friendly and perfect for showcasing what matters most without the distractions of a multi-page setup. When simplicity and functionality are key, Carrd is the clear winner.</p>\n<h2 id=\"carrd-co-for-single-page-websites\" tabindex=\"-1\"><a href=\"https://try.carrd.co/adjb\">Carrd.co</a> for single page websites. <a class=\"header-anchor\" href=\"#carrd-co-for-single-page-websites\">#</a></h2>\n<ul>\n<li>If you visit Carrd.co <a href=\"https://try.carrd.co/adjb\">through my link</a> (or enter your referral code – <code>adjb</code> or <code>YXJL3</code> – directly at checkout) I will earn you 30% of the amount paid towards their next Pro upgrade or renewal. You will also get a discount.</li>\n<li>here is my page <a href=\"https://adjb.carrd.co\">adjb.carrd.co</a></li>\n<li>Carrd.co has a bunch of plans my favorite plans are:\n<ul>\n<li>Carrd.co Pro Standard is $19 a year. That is it just $19 a year.</li>\n<li>Carrd.co Pro Lite is $9 a year for a more budget friendly plan.</li>\n</ul>\n</li>\n<li><a href=\"https://try.carrd.co/adjb\">My Carrd discount code</a> is: <code>adjb</code> or <code>YFSYXJL3</code>.</li>\n</ul>\n<h2 id=\"sample-carrd-sites\" tabindex=\"-1\">Sample Carrd sites <a class=\"header-anchor\" href=\"#sample-carrd-sites\">#</a></h2>\n<ul>\n<li><a href=\"https://andrewgardnerphd.com/\">Andrew Gardner</a></li>\n<li><a href=\"https://alfieaward.com/\">Alfie Jacques Ambassador Award</a></li>\n<li><a href=\"https://adjb.carrd.co/\">Adam's Sample Site</a></li>\n<li><a href=\"https://dallasnostalgic.club/\">Dallas Nostaligic Gaming and Culture Club</a></li>\n<li><a href=\"https://www.jordanbradyloewen.com/\">Jordan Brady Loewen</a></li>\n<li><a href=\"https://lyonshillwedding.com/\">Lyons Hill Wedding</a></li>\n<li><a href=\"https://katepollackresumes.com/\">Kate Pollack Resumes</a></li>\n<li><a href=\"https://kaitlynstarbrett.com/\">Kaitlyn Star Brett</a></li>\n<li><a href=\"https://www.coinop-collective.com/\">The Coin-Op Collective</a></li>\n<li><a href=\"https://themidgeekcrisis.com/\">The Mid-Geek Crisis</a></li>\n</ul>\n",
			"date_published": "2024-12-12T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2024-12-11-new-publication-documenting-domination/",
			"url": "https://www.adamdjbrett.com/blog/2024-12-11-new-publication-documenting-domination/",
			"title": "Documenting Domination: From the Doctrine of Christian Discovery to Dominion Theology",
			"content_html": "<blockquote>\n<p>The Doctrine of Christian Discovery is a series of fifteenth-century papal bulls that served as the theological and legal justification for the colonization of the world and the enslavement of the Original Free Nations, starting first on the African continent before spreading across the globe. In the 1800s, these bulls and other documents like <em>The Requerimiento</em> and colonial charters would be codified and enshrined together in U.S. law as the Doctrine of Christian Discovery, becoming the foundation of property law and international law. Also, considering what Peter d’Errico calls Federal Anti-Indian Law, we will trace and document how this framework of domination began with the Catholic crowns of Europe and transformed into the dominion theology found within Christian nationalist theologies today. Our research highlights how the Doctrine became enshrined and encoded within Protestantism and the imagined “secular” of the U.S. and Canada, countries who rhetorically espouse separation of church and state while justifying land theft, treaty violations, and the abuse of Indigenous nations and peoples through the Doctrine. We craft a genealogy of Christian domination by carefully analyzing primary sources, especially the colonial charters. We will conclude by juxtaposing the domination framework and the Haudenosaunee Confederacy’s principles of the <em>Gayanashagowa</em> (Great Law of Peace).</p>\n</blockquote>\n<p><a href=\"https://doi.org/10.3390/rel15121493\">Read More</a></p>\n<hr>\n<p>This publication is free and open access</p>\n",
			"date_published": "2024-12-11T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2024-11-22-why-scholars-should-own-their-online-presence/",
			"url": "https://www.adamdjbrett.com/blog/2024-11-22-why-scholars-should-own-their-online-presence/",
			"title": "Why Scholars Should Own Their Online Presence",
			"content_html": "<h2 id=\"a-domain-of-ones-own\" tabindex=\"-1\">A Domain of One's Own <a class=\"header-anchor\" href=\"#a-domain-of-ones-own\">#</a></h2>\n<p>In the digital age, having a domain name is a critical step for scholars to establish their professional identity. A personal domain name, such as &quot;FirstNameLastName.com,&quot; signals authority and permanence. Unlike social media platforms, which can change policies or even shut down, a custom domain provides a stable foundation for an academic's online presence. It also lends credibility to their work, as a dedicated web address conveys professionalism and makes it easier for colleagues, students, and collaborators to locate relevant information about their research and publications. For scholars who aim to control how they are perceived online, owning a domain is non-negotiable  (Cf. <a href=\"http://umwdtlt.com/a-brief-history-of-domain-of-ones-own-part-two-the-12-days-of-domains/\">A Brief History of A Domain of One's Own</a>).</p>\n<p>Creating and maintaining a professional website is the logical next step for academics seeking to showcase their achievements. A well-designed website can serve as a digital portfolio, featuring a CV, publications, teaching resources, and links to external projects. Such a site centralizes information, making it accessible to diverse audiences. Moreover, owning and managing the website ensures that the scholar has full control over its content and design, avoiding dependency on external platforms that might introduce ads or unrelated distractions. For scholars in fields like history or religious studies, where nuanced presentations of complex ideas matter, a self-owned website allows for a thoughtful and intentional representation of their work.</p>\n<h2 id=\"the-tools-that-can-help\" tabindex=\"-1\">The Tools that Can Help <a class=\"header-anchor\" href=\"#the-tools-that-can-help\">#</a></h2>\n<h3 id=\"carrd\" tabindex=\"-1\">Carrd <a class=\"header-anchor\" href=\"#carrd\">#</a></h3>\n<p><a href=\"https://try.carrd.co/adjb\">Carrd</a>, a platform known for its simplicity and elegance, is an excellent tool for building a professional website quickly. Its intuitive interface requires no prior coding knowledge, making it accessible to even the busiest of academics. <a href=\"https://try.carrd.co/adjb\">Carrd</a> offers customizable templates that strike a balance between aesthetics and functionality, enabling scholars to create visually appealing and well-organized websites. With affordable pricing and responsive designs, <a href=\"https://try.carrd.co/adjb\">Carrd</a> allows users to focus on curating content rather than grappling with technical challenges. For scholars who value efficiency and design, <a href=\"https://try.carrd.co/adjb\">Carrd</a> provides a straightforward path to establishing an impressive online presence.</p>\n<h3 id=\"advanced-options-for-robust-scholarly-websites\" tabindex=\"-1\">Advanced Options for Robust Scholarly Websites <a class=\"header-anchor\" href=\"#advanced-options-for-robust-scholarly-websites\">#</a></h3>\n<p>For scholars seeking a more robust, multipage website that remains easy to maintain, tools like <a href=\"https://11ty.dev\">11ty</a> and <a href=\"https://astro.build\">Astro</a> provide exceptional solutions. Unlike simpler platforms such as Carrd or feature-heavy systems like WordPress, 11ty and Astro strike a balance between customization, performance, and simplicity. These static site generators allow academics to build websites that are not only fast and secure but also flexible enough to accommodate complex needs, such as hosting blogs, research archives, multimedia, and teaching materials. Scholars can use these platforms to create a polished and highly functional website without relying on heavy, plugin-dependent systems that can slow performance or introduce vulnerabilities.</p>\n<p>Both <a href=\"https://11ty.dev\">11ty</a> and <a href=\"https://astro.build\">Astro</a> cater to users with some basic familiarity with web development while offering extensive documentation to guide new adopters. 11ty is renowned for its lightweight design, enabling scholars to create static websites that load quickly and perform well on search engines. Astro, on the other hand, is optimized for creating hybrid sites, where dynamic elements coexist seamlessly with static content. These tools emphasize modular design and are compatible with modern web standards, ensuring long-term sustainability. For scholars who value autonomy and efficiency, 11ty and Astro provide a professional-grade foundation for crafting feature-rich, aesthetically pleasing websites that grow with their academic careers.</p>\n",
			"date_published": "2024-11-22T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2024-09-07-digital-humanities-limits/",
			"url": "https://www.adamdjbrett.com/blog/2024-09-07-digital-humanities-limits/",
			"title": "Digital Humanities as Preserving Inherently Ephemeral Information",
			"content_html": "<h2 id=\"abstract\" tabindex=\"-1\">Abstract <a class=\"header-anchor\" href=\"#abstract\">#</a></h2>\n<p>The Download is where we bring you up to speed on all things digital when it comes to working in our field. In this issue, we are pleased to have a piece from Adam DJ Brett. Many of us have been working long enough to know that technologies change and fade away. Brett gives us a framework for thinking about how to make sure our content is built to last.</p>\n<h2 id=\"citation\" tabindex=\"-1\">Citation <a class=\"header-anchor\" href=\"#citation\">#</a></h2>\n<p>Brett, Adam DJ. 2024. &quot;Digital Humanities As Preserving Inherently Ephemeral Information&quot;. <em>Bulletin for the Study of Religion</em> 53 (1): 24-28. <a href=\"https://doi.org/10.1558/bsor.28913\">https://doi.org/10.1558/bsor.28913</a>.</p>\n<p><a href=\"/assets/pdfs/the-download-brett.ris\">RIS File</a></p>\n",
			"date_published": "2024-09-07T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2024-07-29-teaching-religious-studies/",
			"url": "https://www.adamdjbrett.com/blog/2024-07-29-teaching-religious-studies/",
			"title": "On Teaching Religious Studies",
			"content_html": "<p><a href=\"https://eileencampbellreed.org/2024/07/28/3mmm-episode-240-teaching-religious-studies-by-adam-d-j-brett/\">Episode 240: Teaching Religious Studies</a></p>\n",
			"date_published": "2024-07-29T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2024-07-16-ten-commandments-truthiness/",
			"url": "https://www.adamdjbrett.com/blog/2024-07-16-ten-commandments-truthiness/",
			"title": "Louisiana’s Ten Commandment Truthiness",
			"content_html": "<blockquote>\n<p>HB71 continues Christian nationalists’ terraforming of the United States, conflating “American” with “Christian” to refashion the country in their image. To make this equivocation successful, they must profess fealty to their trinity of sacred texts: the Bible, the Declaration of Independence and the Constitution.</p>\n<p>At its core, the bill directly attacks the Establishment Clause of the First Amendment, which ensures the constitutional right to religious freedom. But for and from whom does religious freedom exist?</p>\n</blockquote>\n<p>Read More: <a href=\"https://goodfaithmedia.org/louisianas-ten-commandment-truthiness/\">Louisiana’s Ten Commandment Truthiness - Good Faith Media</a>.</p>\n",
			"date_published": "2024-07-16T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2024-06-26-pll-lacrosse-buddy/",
			"url": "https://www.adamdjbrett.com/blog/2024-06-26-pll-lacrosse-buddy/",
			"title": "Will you be my Premier Lacrosse League buddy?",
			"content_html": "<p>Growing up I played sports but I did not really love sports. However that all changed when I moved to study at Syracuse University and I feell in love with <a href=\"https://indigenousvalues.org/contributions/lacrosse/\"><em>Deyhontsigwa'ehs</em> (lacrosse)</a>. In many ways lacrosse chose me. What I love about lacrosse is its deep roots in the Haudenosaunee Confederacy, its role as a Medicine Game, a way to bring healing and how it is used diplomatically. The athletes playing for the <a href=\"https://haudenosauneenationals.com/\">Haudenosuanee Nationals</a> travel on the Haudenosaunee passport. I love that lacrosse provides a reminder and chance to affirm Haudenosaunee Confederacy sovereignty and tell the story of the Great Law of Peace. The past, present, and future of lacrosee are inspiring to me. My first lacrosse stick is a wooden lacrosse stick made by the late great Onondaga Nation stickmaker <a href=\"https://alfieaward.com/\">Alfie Jacques</a>. My favorite types of lacrosse to watching collegiate lacrosse, box lacrosse, field lacrosse, and Olympic sixes. Of course the Syracuse University :orange: are my favorite team. Professionally I love the <a href=\"https://nll.com\">National Lacrosse League (NLL)</a> which is box lacrosse and the <a href=\"https://premierlacrosseleague.com/\">Premier Lacrosse League</a> which is field.</p>\n<p>While I love lacrosse deeply I am bit of an odd duck because I have never played lacrosse. I am learning but as a geek my hand eye skills are not great.</p>\n<p>Anyway here is my post asking if there are any other fellow lacrosse fans out there who might be interested in playing fantasy lacrosse with me? No money involved and it will be deeply casual. I am super bad at fantasy sports and just enjoy the camaraderie.</p>\n<p>If you are interested please join the <a href=\"https://pll.gg/Eqeddqhn6Hb\">PLL Nation using my referral code below!</a>.</p>\n<p><a href=\"https://pll.gg/Eqeddqhn6Hb\">https://pll.gg/Eqeddqhn6Hb</a></p>\n<h2 id=\"merch\" tabindex=\"-1\">Merch <a class=\"header-anchor\" href=\"#merch\">#</a></h2>\n<p><a href=\"https://refer.premierlacrosseleague.com/adam4673\">PLL Merch Discount refferal link</a></p>\n",
			"date_published": "2024-06-26T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2024-06-25-annoucing-alf-jacques-award/",
			"url": "https://www.adamdjbrett.com/blog/2024-06-25-annoucing-alf-jacques-award/",
			"title": "Annoucing the Alf Jacques Ambassador Award",
			"content_html": "<p><a href=\"/assets/img/alf-jacques-social-image.webp\"><img src=\"/assets/img/alf-jacques-social-image.webp\" alt=\"Alf Jacques Award Social Image\"></a></p>\n<p>Alf Jacques was known as a stick maker, but he was also a lacrosse ambassador. He took time to teach the values of the Medicine Game and let the world know that lacrosse is a game of community, friendship and peace. Please consider a small donation towards the creation of the next major lacrosse award. The Alf Jacques Ambassador Award will be given to a member of the International lacrosse community who has spent a lifetime not simply growing the game, but growing the game in a way that fosters friendship and peace. This is a brand new award, please spread the word. New website and donation link below.</p>\n<p><a href=\"https://alfieaward.com\">AlfieAward.com</a></p>\n<p>~ annoucement text by Robert Carpenter</p>\n",
			"date_published": "2024-06-25T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2024-06-17-why-i-switched-from-namedotcom-namecheap/",
			"url": "https://www.adamdjbrett.com/blog/2024-06-17-why-i-switched-from-namedotcom-namecheap/",
			"title": "Why I switched from Name.com to Namecheap",
			"content_html": "<p>I have used numerous domain name registrars including some of the most popular ones 1&amp;1, Gandi.net, <a href=\"https://killedbygoogle.com/\">Google Domains (🪦)</a>, hover, name.com, and namecheap.com. My all-time favorite was name.com. I started using name.com in June of 2010 when I setup <a href=\"https://adamdjbrett.com\">adamdjbrett.com</a> and <a href=\"https://stephaniewyatt.net\">stephanieywatt.net</a>. Back in 2011 name.com was still a young Denver based startup with incredible customer service, engaging social media, and most importantly was 1) affordable 2) high quality and 3) easy to use. I appreciated their stance against as being anti-SOPA, pro-net neutrality, and how the ceased DNS wildcarding. Now name.com is part of Identity Digital. The biggest change I have seen from 2011 to today has been the rise in prices, and fewer customer first initiatives, the fun is gone. I miss the bearglecorn mascot.</p>\n<p>I am leaving name.com behind because of the rising renewal costs. I had several domains up for renewal at $125.89 which was quite steep. Part of that cost was I was being charged $4.99 per domain for <a href=\"https://www.name.com/account/whoisprivacy\">whoisprivacy</a>. I began to shop around and see what some other options and I were decided to go with namecheap because domain privacy was included, and the renewal fee is $76.52.</p>\n<p>Namecheap is a private company and they support the <a href=\"https://www.eff.org/\">Electronic Freedom Foundation</a> and the <a href=\"https://www.fightforthefuture.org/\">Fight For The Future</a>.</p>\n<p>What I like about namecheap thus far has been the price and the privacy. The features I lost from name.com have not yet to me justified the price difference. While Namecheap's interface is not as user friendly for me as name.com, it is still easy to navigate and moving the domains over was a rather painless process.</p>\n<h1 id=\"comparison-and-contrast\" tabindex=\"-1\">Comparison &amp; Contrast <a class=\"header-anchor\" href=\"#comparison-and-contrast\">#</a></h1>\n<table>\n<tbody>\n  <thead>\n<tr>\n<th><strong>Service Element</strong></th>\n<th><strong>Name.com</strong></th>\n<th><strong>Namecheap</strong></th>\n</tr>\n  </thead>\n<tr>\n<td>WHOIS Privacy</td>\n<td>$4.99</td>\n<td>Free</td>\n</tr>\n<tr>\n<td>DNS</td>\n<td>Free</td>\n<td>Free &amp; Premium</td>\n</tr>\n<tr>\n<td>DNSSEC</td>\n<td>&nbsp;NO</td>\n<td>Premium</td>\n</tr>\n<tr>\n<td>SSL</td>\n<td>Paid Add-On</td>\n<td>Paid Add-on</td>\n</tr>\n<tr>\n<td>Email</td>\n<td>&nbsp;Titan Email</td>\n<td>&nbsp;Private Email</td>\n</tr>\n<tr>\n<td>Email Forwarding</td>\n<td>&nbsp;Yes</td>\n<td>Yes</td>\n</tr>\n<tr>\n<td>User Interface</td>\n<td>⭐️⭐️⭐️⭐️⭐️&nbsp;</td>\n<td>&nbsp;⭐️⭐️⭐️</td>\n</tr>\n<tr>\n<td>Customer Support</td>\n<td>⭐️⭐️⭐️⭐️⭐️&nbsp;</td>\n<td>&nbsp;⭐️⭐️⭐️⭐️⭐️&nbsp;</td>\n</tr>\n</tbody>\n</table>\n<p>Name.com had wonderfully fast DNS and offered ALIAS records for an included price. Namecheap charges extra for premium DNS which has features I don't need for each domain name. Now I use Cloudflare for DNS, so I don't have to use namecheap DNS. Additionally, instead of using namecheap or name.com email redirects as I found both so limited I use IMPROVMX, a service which I highly recommend.</p>\n<h2 id=\"conclusion\" tabindex=\"-1\">Conclusion <a class=\"header-anchor\" href=\"#conclusion\">#</a></h2>\n<p>I think I am going to transfer most of my domain names away from name.com towards namecheap. I much prefer domain + Google Workspace integrated billing of name.com so I am going to keep at least one domain and project on name.com. Plus I can hope that name.com may lower their domain prices and start offering included privacy protection.</p>\n<h2 id=\"my-tech-stacks\" tabindex=\"-1\">My tech stacks <a class=\"header-anchor\" href=\"#my-tech-stacks\">#</a></h2>\n<p>For those who might be interested here are my present tech stacks.</p>\n<table>\n<tbody>\n<tr>\n<th style=\"text-align: center;\"><strong>Elements</strong></th>\n<th style=\"text-align: center;\"><strong>#NoCode or </strong><br /><strong>Low Code</strong></th>\n<th style=\"text-align: center;\"><strong>Static Site Generators </strong><br /><strong> (<a href=\"https://jamstack.org/\" target=\"_blank\" rel=\"noopener\">SSG/Jamstack</a>)</strong></th>\n<td style=\"text-align: center;\"><strong>WordPress</strong></td>\n</tr>\n<tr>\n<td style=\"text-align: center;\">Domain Name&nbsp;</td>\n<td style=\"text-align: center;\">Namecheap <br />or Name.com</td>\n<td style=\"text-align: center;\">Namecheap <br />or Name.com</td>\n<td style=\"text-align: center;\">Namecheap <br />or Name.com</td>\n</tr>\n<tr>\n<td style=\"text-align: center;\">DNS&nbsp;</td>\n<td style=\"text-align: center;\">Namecheap or <br /> Name.com</td>\n<td style=\"text-align: center;\">Cloudflare&nbsp;</td>\n<td style=\"text-align: center;\">Cloudflare</td>\n</tr>\n<tr>\n<td style=\"text-align: center;\">Email Forwarding</td>\n<td style=\"text-align: center;\">ImprovMX</td>\n<td style=\"text-align: center;\">&nbsp;ImprovMX</td>\n<td style=\"text-align: center;\">&nbsp;ImprovMX</td>\n</tr>\n<tr>\n<td style=\"text-align: center;\">Site Builder</td>\n<td style=\"text-align: center;\">&nbsp;Carrd.co</td>\n<td style=\"text-align: center;\">Eleventy or Jekyll&nbsp;</td>\n<td style=\"text-align: center;\">WordPress&nbsp;</td>\n</tr>\n<tr>\n<td style=\"text-align: center;\">Hosting</td>\n<td style=\"text-align: center;\">&nbsp;Carrd.co</td>\n<td style=\"text-align: center;\">Cloudlfare Pages&nbsp;</td>\n<td style=\"text-align: center;\">Digital Ocean&nbsp;</td>\n</tr>\n<tr>\n<td style=\"text-align: center;\">&nbsp;</td>\n<td style=\"text-align: center;\">&nbsp;</td>\n<td style=\"text-align: center;\">Github Pages&nbsp;</td>\n<td style=\"text-align: center;\">Vultr&nbsp;</td>\n</tr>\n<tr>\n<td style=\"text-align: center;\">&nbsp;</td>\n<td style=\"text-align: center;\">&nbsp;</td>\n<td style=\"text-align: center;\">Netlify</td>\n<td style=\"text-align: center;\">Linode</td>\n</tr>\n<tr>\n<td style=\"text-align: center;\">Advanced Additions&nbsp;</td>\n<td style=\"text-align: center;\">&nbsp;</td>\n<td style=\"text-align: center;\">&nbsp;</td>\n<td style=\"text-align: center;\">&nbsp;</td>\n</tr>\n<tr>\n<td style=\"text-align: center;\">Hosted Email&nbsp;</td>\n<td style=\"text-align: center;\">&nbsp;Google Workspace</td>\n<td style=\"text-align: center;\">Google Workspace&nbsp;</td>\n<td style=\"text-align: center;\">Google Workspace&nbsp;</td>\n</tr>\n<tr>\n<td>&nbsp;</td>\n<td>&nbsp;</td>\n<td>&nbsp;</td>\n<td>&nbsp;</td>\n</tr>\n</tbody>\n</table>\n<h2 id=\"afiliate-links\" tabindex=\"-1\">Afiliate links <a class=\"header-anchor\" href=\"#afiliate-links\">#</a></h2>\n<p>Using these links I may earn a comission.</p>\n<ul>\n<li><a href=\"https://bunnycdn.com/?ref=wtn001abeo\">BunnyCDN</a></li>\n<li><a href=\"https://m.do.co/c/ff35163be632\">Digital Ocean</a></li>\n<li><a href=\"https://try.carrd.co/adjb\">Carrd</a></li>\n<li><a href=\"https://improvmx.com/\">ImprovMX</a></li>\n<li><a href=\"https://refer.premierlacrosseleague.com/adam4673\">Premier Lacrosse League Merch</a></li>\n</ul>\n<h3 id=\"more-codes\" tabindex=\"-1\">More codes: <a class=\"header-anchor\" href=\"#more-codes\">#</a></h3>\n<ul>\n<li><a href=\"https://invt.co/@adjb\">Invite Codes</a></li>\n</ul>\n<h2 id=\"conclusion-1\" tabindex=\"-1\">Conclusion <a class=\"header-anchor\" href=\"#conclusion-1\">#</a></h2>\n<p>If you have any domain name reigstrar recomemndations for me or other elements I should consider about name.com and namecheap please drop me a line.</p>\n",
			"date_published": "2024-06-17T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2024-06-12-using-github-actions-convert-file-formats/",
			"url": "https://www.adamdjbrett.com/blog/2024-06-12-using-github-actions-convert-file-formats/",
			"title": "Using Github Actions to Convert File Formats",
			"content_html": "<p>This post is all about learning and coding in public. We learn from each others mistakes and we get better by building together.</p>\n<hr>\n<p>One of my favorite longterm projects has been <a href=\"https://relcfp.com\">RELCFP</a>. It is a simple site that aggregate <a href=\"https://relcfp.com\">religious studies call for papers</a>. The site works by pulling in a <a href=\"https://input.relcfp.com\">custom RSS Feed</a> and CFPs that have been submitted via the site. I like to blend the data together so that people can quickly and easily get to the main location of these call for papers. Recently the script I have been using  broke. <code>XMLHttpREquest</code> is no longer recommended as a way to display and style XML. Here is the broken script 🪦.</p>\n<pre class=\"language-js\" tabindex=\"0\"><code class=\"language-js\">    <span class=\"token operator\">&lt;</span>script type<span class=\"token operator\">=</span><span class=\"token string\">\"text/javascript\"</span><span class=\"token operator\">></span>\n        <span class=\"token keyword\">function</span> <span class=\"token function\">loadXMLDoc</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">dname</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n          xhttp <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">XMLHttpRequest</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n          xhttp<span class=\"token punctuation\">.</span><span class=\"token function\">open</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"GET\"</span><span class=\"token punctuation\">,</span>dname<span class=\"token punctuation\">,</span><span class=\"token boolean\">false</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n          xhttp<span class=\"token punctuation\">.</span><span class=\"token function\">send</span><span class=\"token punctuation\">(</span><span class=\"token string\">\"\"</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n         <span class=\"token keyword\">return</span> xhttp<span class=\"token punctuation\">.</span>responseXML<span class=\"token punctuation\">;</span>\n        <span class=\"token punctuation\">}</span>\n   \n        <span class=\"token keyword\">var</span> processor <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">XSLTProcessor</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">var</span> theXML <span class=\"token operator\">=</span> <span class=\"token function\">loadXMLDoc</span><span class=\"token punctuation\">(</span><span class=\"token string\">'feed.xml'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token keyword\">var</span> theXSL <span class=\"token operator\">=</span> <span class=\"token function\">loadXMLDoc</span><span class=\"token punctuation\">(</span><span class=\"token string\">'feed.xsl'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   \n        <span class=\"token comment\">// prepare the processor</span>\n        processor<span class=\"token punctuation\">.</span><span class=\"token function\">importStylesheet</span><span class=\"token punctuation\">(</span>theXSL<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n   \n        <span class=\"token keyword\">var</span> theResult <span class=\"token operator\">=</span> processor<span class=\"token punctuation\">.</span><span class=\"token function\">transformToDocument</span><span class=\"token punctuation\">(</span>theXML<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n        <span class=\"token comment\">// now you have a DomDocument with the result</span>\n        <span class=\"token comment\">// if you want to serialize (transform to a string) it you van use</span>\n   \n        document<span class=\"token punctuation\">.</span><span class=\"token function\">write</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">new</span> <span class=\"token class-name\">XMLSerializer</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">serializeToString</span><span class=\"token punctuation\">(</span>theResult<span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>  \n     <span class=\"token operator\">&lt;</span><span class=\"token operator\">/</span>script<span class=\"token operator\">></span>\n</code></pre>\n<p>I am working on several ways to replace this script. First I replaced my old FreshRSS server with a wonderful <a href=\"https://11ty.dev\">Eleventy</a> starter theme called <a href=\"https://github.com/lwojcik/eleventy-template-multiplicity\">Multiplicity-M10ty</a> by <a href=\"https://github.com/lwojcik/\">@lwojcik</a>. Now instead of a bland RSS feed and yet another server bill I have a nicely <a href=\"https://input.relcfp.com/\">stylized feed</a> with clear attributions. Plus this new site is much easier to upate.</p>\n<p>Now for part 2 fixing the homepage of <a href=\"https://relcfp.com\">relcfp.com</a>. I want and need an automated and easy way to style the data. I am able to easily import the RSS. Now I just need to style it. Styling the XML is proving rather difficult. One of the solutions I am exploring is convering the XML into JSON and styling JSON something which is a much clearer and more well documented process. Using CI/CD I want to create a Github Action that will automatically convert XML to JSON and then commit the new JSON file to the repository.</p>\n<p>I found a really cool github action <a href=\"https://github.com/fabasoad/data-format-converter-action\">&quot;Data Format Converter Action&quot;</a> by <a href=\"https://github.com/fabasoad\">@fabasoad</a>. Through lots of trial and error and kind assistance by fabasoad. I wwas able to get the Github Action <strong>almost</strong> working on <a href=\"https://github.com/adamdjbrett/data-format-converter-action-demo/\">my repository</a>. Presently my issue is that <a href=\"https://github.com/adamdjbrett/data-format-converter-action-demo/blob/main/.github/workflows/xml2yml.yml\">the script</a> runs but it does not output and add a new results.json to the repository.</p>\n<h2 id=\"setting-up-data-format-converter-github-action-by-fabasoad\" tabindex=\"-1\">Setting up <a href=\"https://github.com/fabasoad/data-format-converter-action\">&quot;Data Format Converter Github Action&quot; by @fabasoad</a> <a class=\"header-anchor\" href=\"#setting-up-data-format-converter-github-action-by-fabasoad\">#</a></h2>\n<p>Here is what I have learned for how to setup this Github Action.</p>\n<h3 id=\"current-instructions\" tabindex=\"-1\">Current Instructions <a class=\"header-anchor\" href=\"#current-instructions\">#</a></h3>\n<p>The <a href=\"https://github.com/fabasoad/data-format-converter-action/blob/main/docs/Examples.md\">current instructions</a> are rather threadbare but thanks to the assistance of @fabasoad I was able to get them working.</p>\n<blockquote>\n<h3 id=\"option-1-personal-access-token-pat\" tabindex=\"-1\">Option 1: Personal access token (PAT) <a class=\"header-anchor\" href=\"#option-1-personal-access-token-pat\">#</a></h3>\n<ol>\n<li><a href=\"https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-personal-access-token-classic\">Create PAT</a>\nwith <code>repo</code> permission.</li>\n<li><a href=\"https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions\">Create repository secret</a>\n(e.g. <code>MY_GITHUB_TOKEN</code>) with the PAT value.</li>\n<li>Use the following configuration:</li>\n</ol>\n<pre class=\"language-yml\" tabindex=\"0\"><code class=\"language-yml\">YAML\n<span class=\"token punctuation\">-</span> <span class=\"token key atrule\">uses</span><span class=\"token punctuation\">:</span> fabasoad/data<span class=\"token punctuation\">-</span>format<span class=\"token punctuation\">-</span>converter<span class=\"token punctuation\">-</span>action@v0\n<span class=\"token key atrule\">with</span><span class=\"token punctuation\">:</span>\n<span class=\"token key atrule\">input</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"person.xml\"</span>\n<span class=\"token key atrule\">from</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"xml\"</span>\n<span class=\"token key atrule\">to</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"yaml\"</span>\n<span class=\"token key atrule\">token</span><span class=\"token punctuation\">:</span> $</code></pre>\n</blockquote>\n<h3 id=\"my-comments\" tabindex=\"-1\">My comments <a class=\"header-anchor\" href=\"#my-comments\">#</a></h3>\n<p>In this section please make sure that you create your ``MY_GITHUB_TOKEN<code>via the</code>Personal access tokens (classic)``` method. I tried the newer approach but I could not get it to work. if you can please let me know.</p>\n<blockquote>\n<h3 id=\"option-2-github-app-token\" tabindex=\"-1\">Option 2: GitHub App token <a class=\"header-anchor\" href=\"#option-2-github-app-token\">#</a></h3>\n<ol>\n<li><a href=\"https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/registering-a-github-app\">Register a GitHub App</a>\nwith <code>contents: read</code> permission.</li>\n<li>Create private key and save it somewhere on your local disk.</li>\n<li><a href=\"https://docs.github.com/en/apps/using-github-apps/installing-your-own-github-app\">Install GitHub App</a>\nto your repository.</li>\n<li><a href=\"https://docs.github.com/en/actions/security-guides/using-secrets-in-github-actions\">Create repository secret</a>\n(e.g. <code>APP_PRIVATE_KEY</code>) with the private key created on step 2.</li>\n<li>Create repository variable (e.g. <code>APP_ID</code>) with the GitHub App ID.</li>\n<li>Use the following configuration:</li>\n</ol>\n<pre class=\"language-yaml\" tabindex=\"0\"><code class=\"language-yaml\"><span class=\"token punctuation\">-</span> <span class=\"token key atrule\">uses</span><span class=\"token punctuation\">:</span> actions/create<span class=\"token punctuation\">-</span>github<span class=\"token punctuation\">-</span>app<span class=\"token punctuation\">-</span>token@v1\n<span class=\"token key atrule\">id</span><span class=\"token punctuation\">:</span> generate<span class=\"token punctuation\">-</span>app<span class=\"token punctuation\">-</span>token\n<span class=\"token key atrule\">with</span><span class=\"token punctuation\">:</span>\n<span class=\"token key atrule\">app-id</span><span class=\"token punctuation\">:</span> $\n<span class=\"token key atrule\">private-key</span><span class=\"token punctuation\">:</span> $\n<span class=\"token punctuation\">-</span> <span class=\"token key atrule\">uses</span><span class=\"token punctuation\">:</span> fabasoad/data<span class=\"token punctuation\">-</span>format<span class=\"token punctuation\">-</span>converter<span class=\"token punctuation\">-</span>action@v0\n<span class=\"token key atrule\">with</span><span class=\"token punctuation\">:</span>\n<span class=\"token key atrule\">input</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"person.xml\"</span>\n<span class=\"token key atrule\">from</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"xml\"</span>\n<span class=\"token key atrule\">to</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"yaml\"</span>\n<span class=\"token key atrule\">token</span><span class=\"token punctuation\">:</span> $NaN</code></pre>\n</blockquote>\n<h3 id=\"my-comments-1\" tabindex=\"-1\">My Comments <a class=\"header-anchor\" href=\"#my-comments-1\">#</a></h3>\n<p>This section really tripped me up. Creating the app and installing the app take time but the setup eventually was fairly direct. Here is a screenshot of the settings I used.\n<a href=\"/assets/img/screencapture-github-settings-apps-adjb-dfca-2024-06-11-20_03_59_tn.webp\"><img src=\"/assets/img/screencapture-github-settings-apps-adjb-dfca-2024-06-11-20_03_59_tn.webp\" alt=\"Screenshot of the App Settings click to enlarge\"></a></p>\n<p>For permissions they need to be for content and metadata.\nWhen installing the APP I chose to limit to just the repositories I am using it on for this project for added security.</p>\n<p>When Creating your APP you will be asked to create a ``private key<code>and this key will download to your computer. You are going to copy and paste that whole key into the</code>APP_PRIVATE_KEY``` that you create on your repository. Likewise you will want to use the APP_ID and not the Client_ID as your vairable.</p>\n<h2 id=\"setting-up-the-app\" tabindex=\"-1\">Setting up the App <a class=\"header-anchor\" href=\"#setting-up-the-app\">#</a></h2>\n<p>I had a lot of issues trying to figure out the keys. If you are having trouble, I do recomend walks to give your brain a break and to reset. I did not take enough breaks and that actually, ironically slowed me down and made this whole process take way longer.</p>\n<h3 id=\"current-settings\" tabindex=\"-1\">Current Settings <a class=\"header-anchor\" href=\"#current-settings\">#</a></h3>\n<pre class=\"language-yml\" tabindex=\"0\"><code class=\"language-yml\"><span class=\"token comment\"># This is a basic workflow to help you get started with Actions</span>\n\n<span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> XML2JSON <span class=\"token comment\">#Change the Name</span>\n\n<span class=\"token comment\"># Controls when the workflow will run</span>\n<span class=\"token key atrule\">on</span><span class=\"token punctuation\">:</span>\n  <span class=\"token comment\"># Triggers the workflow on push or pull request events but only for the \"main\" branch</span>\n  <span class=\"token key atrule\">push</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">branches</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">[</span> <span class=\"token string\">\"main\"</span> <span class=\"token punctuation\">]</span>\n  <span class=\"token key atrule\">pull_request</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">branches</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">[</span> <span class=\"token string\">\"main\"</span> <span class=\"token punctuation\">]</span>\n\n  <span class=\"token comment\"># Allows you to run this workflow manually from the Actions tab</span>\n  <span class=\"token key atrule\">workflow_dispatch</span><span class=\"token punctuation\">:</span>\n\n<span class=\"token comment\"># A workflow run is made up of one or more jobs that can run sequentially or in parallel</span>\n<span class=\"token key atrule\">jobs</span><span class=\"token punctuation\">:</span>\n\n  <span class=\"token comment\"># This workflow contains a single job called \"build\"</span>\n  <span class=\"token key atrule\">build</span><span class=\"token punctuation\">:</span>\n    <span class=\"token comment\"># The type of runner that the job will run on</span>\n    <span class=\"token key atrule\">runs-on</span><span class=\"token punctuation\">:</span> ubuntu<span class=\"token punctuation\">-</span>latest\n\n    <span class=\"token comment\"># Steps represent a sequence of tasks that will be executed as part of the job</span>\n    <span class=\"token key atrule\">steps</span><span class=\"token punctuation\">:</span>\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">uses</span><span class=\"token punctuation\">:</span> actions/checkout@v4\n\n      <span class=\"token comment\"># Runs a set of commands using the runners shell</span>\n      <span class=\"token comment\"># name: Use Github App</span>\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">uses</span><span class=\"token punctuation\">:</span> actions/create<span class=\"token punctuation\">-</span>github<span class=\"token punctuation\">-</span>app<span class=\"token punctuation\">-</span>token@v1\n        <span class=\"token key atrule\">id</span><span class=\"token punctuation\">:</span> generate<span class=\"token punctuation\">-</span>app<span class=\"token punctuation\">-</span>token\n        <span class=\"token key atrule\">with</span><span class=\"token punctuation\">:</span>\n          <span class=\"token key atrule\">app-id</span><span class=\"token punctuation\">:</span> $\n          <span class=\"token key atrule\">private-key</span><span class=\"token punctuation\">:</span> $\n      <span class=\"token comment\"># name: Data Format Converter Action</span>\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">uses</span><span class=\"token punctuation\">:</span> fabasoad/data<span class=\"token punctuation\">-</span>format<span class=\"token punctuation\">-</span>converter<span class=\"token punctuation\">-</span>action@main\n        <span class=\"token key atrule\">id</span><span class=\"token punctuation\">:</span> xml2json\n        <span class=\"token key atrule\">with</span><span class=\"token punctuation\">:</span>\n          <span class=\"token key atrule\">input</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"person.xml\"</span>\n          <span class=\"token key atrule\">from</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"xml\"</span>\n          <span class=\"token key atrule\">to</span><span class=\"token punctuation\">:</span> <span class=\"token string\">\"json\"</span>\n          <span class=\"token key atrule\">token</span><span class=\"token punctuation\">:</span> $NaN\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Print result\n        <span class=\"token key atrule\">run</span><span class=\"token punctuation\">:</span> echo  '$' <span class=\"token punctuation\">></span> result.json\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Print result\n        <span class=\"token key atrule\">run</span><span class=\"token punctuation\">:</span> echo  '$' <span class=\"token punctuation\">></span> result.json\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">run</span><span class=\"token punctuation\">:</span> cat result.json\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Configure Git\n        <span class=\"token key atrule\">run</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">|</span><span class=\"token scalar string\">\n          git config --global user.name 'adamdjbrett'\n          git config --global user.email '22662978+adamdjbrett@users.noreply.github.com'</span>\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Commit and push changes\n        <span class=\"token key atrule\">run</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">|</span><span class=\"token scalar string\">\n          git add result.json\n          git commit -m \"Save output to file\"\n          git push</span>\n        <span class=\"token key atrule\">env</span><span class=\"token punctuation\">:</span>\n          <span class=\"token key atrule\">GITHUB_TOKEN</span><span class=\"token punctuation\">:</span> $\n</code></pre>\n<p>Presently I am stuck on what do I do next, how do I output the demo data to a json file and commit that file to my repository? After I commit the file to my repository, then I can move over to trying to do this with a full RSS XML feed and see how well that works.</p>\n<p>In order to get the &quot;Configure Git&quot; step to work I followed this article: <a href=\"https://www.raulmelo.me/en/til/how-to-solve-permission-to-x-denied-to-github-actions-bot\">&quot;How to solve &quot;Permission to x denied to github-actions[bot]&quot;&quot;</a>.</p>\n<p>Following that article I was able to get my file to save and commit to the repository.</p>\n<p>What wound up working was two things first sanitzing the json thanks to <a href=\"https://github.com/spenserblack\">@spenserblack</a></p>\n<pre class=\"language-yml\" tabindex=\"0\"><code class=\"language-yml\"><span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Print result\n<span class=\"token key atrule\">run</span><span class=\"token punctuation\">:</span> echo \"$RESULT\" <span class=\"token punctuation\">></span> feed.json\n<span class=\"token key atrule\">env</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">RESULT</span><span class=\"token punctuation\">:</span> $</code></pre>\n<p>Second switching to python thanks to <a href=\"https://github.com/imajeetyadav\">@imajeetyadav</a></p>\n<pre class=\"language-yml\" tabindex=\"0\"><code class=\"language-yml\">      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Set up Python\n        <span class=\"token key atrule\">uses</span><span class=\"token punctuation\">:</span> actions/setup<span class=\"token punctuation\">-</span>python@v5\n        <span class=\"token key atrule\">with</span><span class=\"token punctuation\">:</span>\n          <span class=\"token key atrule\">python-version</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'3.11'</span>\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Install dependencies\n        <span class=\"token key atrule\">run</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">|</span><span class=\"token scalar string\">\n          python -m pip install --upgrade pip\n          pip install xmltodict</span>\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> Data Format Converter Action\n        <span class=\"token key atrule\">shell</span><span class=\"token punctuation\">:</span> python\n        <span class=\"token key atrule\">id</span><span class=\"token punctuation\">:</span> xml2json\n        <span class=\"token key atrule\">run</span><span class=\"token punctuation\">:</span> <span class=\"token punctuation\">|</span><span class=\"token scalar string\">\n          import xmltodict\n          import json\n          def validate_json(json_string):\n            try:\n                json.loads(json_string)\n                return True\n            except ValueError as e:\n                print(f\"Invalid JSON: {e}\")\n                return False\n          with open('feed.xml', 'r') as xml_file:\n              xml_data = xml_file.read()\n              xml_dict = xmltodict.parse(xml_data)\n              json_data = json.dumps(xml_dict, indent=4)\n              with open('feed.json', 'w') as json_file:\n                  json_file.write(json_data) </span></code></pre>\n<p><a href=\"https://github.com/adamdjbrett/relcfp/blob/main/feed.json\">The current full file may be viewed in the repo</a></p>\n<h2 id=\"thank-you-to\" tabindex=\"-1\">Thank you to: <a class=\"header-anchor\" href=\"#thank-you-to\">#</a></h2>\n<ul>\n<li><a href=\"https://github.com/fabasoad\">@fabasoad</a> on github</li>\n<li>Mahboob Ahmed on Stack Overflow</li>\n<li><a href=\"https://www.raulmelo.me\">Raule Melo</a></li>\n<li><a href=\"https://github.com/imajeetyadav\">@imajeetyadav</a></li>\n<li><a href=\"https://github.com/spenserblack\">@spenserblack</a></li>\n</ul>\n<p>Thank you to all of them for being willing to learn, create, and help in public.</p>\n<p>Now to apply this to my main repo. <a href=\"https://relcfp.com\">relcfp.com</a></p>\n<h2 id=\"update\" tabindex=\"-1\">Update <a class=\"header-anchor\" href=\"#update\">#</a></h2>\n<p>Everything is working great now. Please go check out the site <a href=\"https://relcfp.com\">relcfp.com</a></p>\n",
			"date_published": "2024-06-12T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2024-05-19-rs-rss/",
			"url": "https://www.adamdjbrett.com/blog/2024-05-19-rs-rss/",
			"title": "New Religious Studies Aggregators",
			"content_html": "<p>I love the open web. I believe that knoweldge and information should be as free and open source as possible. In college when I really started becoming a geek, I fell in love with open sources software (Linux I love you), websites without paywalls, and nominal walled gardens. As time has passed the web has become more and more less open. RSS readers like Google Reader have been <a href=\"https://killedbygoogle.com\">killed</a> off. Now social media platforms lock us viewers into to their ecosystems, only feeding news to us algorithmically not syncronously. These platforms frequently have PR crisies, close down, get bought out, or the data goes missing. This is once again a plea for everyone to have a <a href=\"https://www.wired.com/insights/2012/07/a-domain-of-ones-own/\">domain of ones own</a>. You should own your information and be the one keeping that information online, transpporting your data from one style of website to another seamlessly.</p>\n<p>Another problem is that <a href=\"https://mashable.com/article/google-search-low-quality-research\">Google Search Results</a> have gotten worse and it has been increasingly difficult to like, find and subscribe to the information I want. As newsletters have become more popular again they are also super annoying b/c I hate email. Plus reading your brilliant words in my email drives me to distraction when yet more email arrives. I have decided to fix this problem (at least for myslef and I wanted).</p>\n<p>I want a simple quiet, easy to use feed reader that looks great on all devices even grayscale e-ink screens. I also do not want yet another app which is yet another walled garden. The open web is so much easier.</p>\n<p>During the <a href=\"https://conf.11ty.dev/\">11ty Conf</a>, I learned about <a href=\"https://github.com/lwojcik\">@lwojcik's</a> awesome 11ty template <a href=\"https://github.com/lwojcik/eleventy-template-multiplicity\">m10y</a>. It is perfect. It is exactly what I want an open web RSS reader.</p>\n<p>I have created a couple versions for myself and maybe even you.</p>\n<h2 id=\"tl-dr\" tabindex=\"-1\">TL;DR <a class=\"header-anchor\" href=\"#tl-dr\">#</a></h2>\n<ul>\n<li><a href=\"https://rs-rss.com\">Religious Studies Blog RSS Aggregator</a> updated 2x daily.</li>\n<li><a href=\"https://rs-rss.com\">Religious Studies Podcast RSS Aggregator</a> updated 2x daily.</li>\n</ul>\n",
			"date_published": "2024-05-19T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2024-04-02-trump-dangerous-rhetoric-dehumanization/",
			"url": "https://www.adamdjbrett.com/blog/2024-04-02-trump-dangerous-rhetoric-dehumanization/",
			"title": "Trump’s Dangerous Rhetoric of Dehumanization",
			"content_html": "<p>Thank you to <a href=\"https://goodfaithmedia.org/\">Good Faith Media</a> for publishing my first op-ed.</p>\n<blockquote>Civilization and personhood are the intellectual bulwarks for the justification of colonization. The colonizer assumes they are made in the image of their God while spreading the message of conquest, civilization and Christianity.\n<p>The Doctrine of Discovery, a set of 15th-century papal bulls, provides the theological and legal framework for Christian domination. It communicates that “explorers” who “discover” lands not occupied by Christians can view them as “terra nullis”–a territory without a master–and claim them for their sovereign.</blockquote></p>\n<p><a href=\"https://goodfaithmedia.org/432273-2/\">Read Now</a></p>\n",
			"date_published": "2024-04-02T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2024-03-26-23rd-unpfii-events/",
			"url": "https://www.adamdjbrett.com/blog/2024-03-26-23rd-unpfii-events/",
			"title": "The 23rd UN Permanent Forum on Indigenous Issues (UNPFII)",
			"content_html": "<h2 id=\"side-events\" tabindex=\"-1\">Side Events <a class=\"header-anchor\" href=\"#side-events\">#</a></h2>\n<ul>\n<li><a href=\"https://aila.ngo/global-indigenous-womens-caucus-2024/\">Global Indigenous Women’s Caucus 2024</a></li>\n<li><a href=\"https://aila.ngo/global-indigenous-peoples-caucus-2024/\">Global Indigenous People’s Caucus 2024</a></li>\n<li><a href=\"https://aila.ngo/2024-craft-fair/\">Indigenous Craft Fair</a></li>\n<li><a href=\"https://aila.ngo/from-land-theft-to-land-back/\">From Land Theft To Land Back The OAS And The Onondaga Nation Land Rights Action</a></li>\n</ul>\n<h2 id=\"posters\" tabindex=\"-1\">Posters <a class=\"header-anchor\" href=\"#posters\">#</a></h2>\n<p><img src=\"/assets/img/20240GIWC-EN.webp\" alt=\"GIWC Flyer\">\n<img src=\"/assets/img/20240GIPC-EN.webp\" alt=\"GIPC Flyer\">\n<img src=\"/assets/img/2024-Craft-EN.webp\" alt=\"Craft Fair Flyer\">\n<img src=\"/assets/img/OAS-Event.webp\" alt=\"OAS Event Flyer\"></p>\n",
			"date_published": "2024-03-26T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2024-02-26-v8-website-award/",
			"url": "https://www.adamdjbrett.com/blog/2024-02-26-v8-website-award/",
			"title": "Volunteer V8 Wins Second Place",
			"content_html": "<p>It was an honor to colloboare with Mickey Holton and the <a href=\"https://volunteerv8.com/\">Volunteer V8 Ford Club</a> on their website. Using their comments and feedback I built them an image driven, easy to use and maintain WordPress website. Our hardwork was honored by the national V8 car club organization which gave our website a second place ribbon for our sites layout, event information, and photo galleries. I am honored to have designed and built an award winning site.</p>\n<p><a href=\"/assets/img/screencapture-web-archive-org-web-20240119214301-https-volunteerv8-com-2024-02-26-09_34_46.webp\"><img src=\"/assets/img/tn/screencapture-web-archive-org-web-20240119214301-https-volunteerv8-com-2024-02-26-09_34_46_tn.webp\" alt=\"Volunteer V8 Website Thumbnail\"></a></p>\n<p><a href=\"/assets/pdfs/2023-website-comeptition-volunteer-v8.pdf\">Annoucement PDF</a></p>\n",
			"date_published": "2024-02-26T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2024-02-20-doctrine-christian-discovery-podcast/",
			"url": "https://www.adamdjbrett.com/blog/2024-02-20-doctrine-christian-discovery-podcast/",
			"title": "Doctrine of Christian Discovery Podcast",
			"content_html": "<p><a href=\"https://megaphone.link/AOOOI9257433215\"><img src=\"/assets/img/doctrine-podcast-artwork.webp\" alt=\"Doctrine of Christian Discovery Podcast Art\"></a></p>\n<p>The conference The Religious Origins of White Supremacy: Johnson v. M'Intosh and the Doctrine of Christian Discovery represented a unique opportunity. Indigenous leaders, scholars, and activists from 20 countries gathered together with non-Indigenous peoples for a collaborative dialogue around three themes 1) the Doctrine of Christian Discovery, 2) the legacy of <em>Johnson v M'Intosh</em>; and 3) the religious origins of white supremacy. The conference intentionally incorporated the arts with two powerful indigenous performances <em>In the Court of the Conqueror</em> and <em>Tēnei Te Põ Nau Mai Te Ao: Ancient Māori Puppetry Healing Traumatic Histories</em>. Additionally art and poetry were present in many sessions. </p>\n<p>Conference organizers Prof. Philip P. Arnold, Sandy Bigtree (Mohawk Nation), and Adam DJ Brett, established the conference methodology as following the Two Row Wampum treaty. This 1613 treaty between the Haudenosaunee and the Dutch is represented in a wampum belt where each nation is a row of purple beads traveling side by side down the river of live. Each one not interfering with one another but moving forward in symmetrical and mutual directions living in harmony with the natural world. </p>\n<p>Acknowledging the singular and unique nature of this gathering Syracuse University and Indigenous Values Initiative partnered with Good Faith Media to produce a podcast which would highlight the conference themes and be the opening presentation of conference outcomes. This podcast hosted are Mitch Randall (Mvskoke Creek) and his son Tanner Randall (Mvskoke Creek). We were excited to have Tanner a recent graduate from Dartmouth's Native Studies program as the host because we envision this podcast as a teaching resource for undergraduate courses.  Our hope is that having a recent undergraduate as the host will help make the podcast more engaging and useful to an undergraduate and other audiences new to the conversation. We are so excited to hear how people are able to use this podcast in their teaching and organizing.</p>\n<p>Finally this podcast represents the first of many educational resources that will be coming out of this conference which will hopefully be useful not only for challenging the legacy of <em>Johnson v. M'Intosh</em> but also dismantling the Doctrine of Christian Discovery, and further challenging white supremacy through understanding its longer history.</p>\n<h2 id=\"credits\" tabindex=\"-1\">Credits <a class=\"header-anchor\" href=\"#credits\">#</a></h2>\n<ul>\n<li>Hosts: Mitch and Tanner Randall, Good Faith Media.</li>\n<li>Executive producers: Mitch Randall, Good Faith Media; Philip P. Arnold and Sandy Bigtree, Indigenous Values Initiative; and Adam DJ Brett, Syracuse University and American Indian Law Alliance.</li>\n<li>Producer: Cliff Vaughn.</li>\n<li>Editor: David Pang.</li>\n<li>Music: Pond5.</li>\n<li>Production assistance: American Indian Law Alliance.</li>\n<li>Sponsors: The Henry Luce Foundation; Syracuse\nUniversity; Indigenous Values Initiative; American Indian Law Alliance; American Indian Community House; Good Faith Media; Tonatierra; and\nToward Our Common Public Life. We appreciate your support.</li>\n</ul>\n<h2 id=\"resources\" tabindex=\"-1\">Resources <a class=\"header-anchor\" href=\"#resources\">#</a></h2>\n<iframe src=\"https://playlist.megaphone.fm/?p=AOOOI2818414790\" width=\"100%\" height=\"482\" frameborder=\"0\"></iframe>\n<ul>\n<li><a href=\"https://goodfaithmedia.org/new-good-faith-media-podcast-highlights-doctrine-of-christian-discovery/\">Here is the press release</a></li>\n<li><a href=\"https://goodfaithmedia.org/doctrine-of-christian-discovery/\">Podcast main page</a></li>\n<li>Listen to the podcast on <a href=\"https://goodfaithmedia.org/doctrine-of-christian-discovery/\">Megaphone</a>, <a href=\"https://open.spotify.com/show/4VnMhbq2UJbu3fdehsQ66I\">Spotify</a> or <a href=\"https://podcasts.apple.com/us/podcast/doctrine-of-christian-discovery/id1729219360\">Apple</a>. </li>\n<li>Transcripts posted on <a href=\"https://podcast.doctrineofdiscovery.org/\">https://podcast.doctrineofdiscovery.org/</a>.</li>\n</ul>\n",
			"date_published": "2024-02-20T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2024-02-01-mapping-doctrine-discovery-podcast/",
			"url": "https://www.adamdjbrett.com/blog/2024-02-01-mapping-doctrine-discovery-podcast/",
			"title": "Mapping the Doctrine of Discovery Podcast",
			"content_html": "<p><a href=\"https://podcast.doctrineofdiscovery.org/about/\"><img src=\"/assets/img/mapping-doctrine-of-discovery-favicon.webp\" alt=\"Mapping the Doctrine of Discovery Cover Art\"></a></p>\n<p><a href=\"https://podcast.doctrineofdiscovery.org\">The Mapping the Doctrine of Discovery Podcast</a> is designed to educate and inform people bout the lasting harmful effects of white Christian hegemony not only upon Indigenous peoples but all peoples. The podcast tells the story of how the Doctrine of Christian Discovery and domination is interwoven into settler-colonial society. As Shawnee/Lenape scholar Steven T. Newcomb highlights in his book <a href=\"https://www.chicagoreviewpress.com/pagans-in-the-promised-land-products-9781555916428.php\"><em>Pagans in the Promised Land</em></a>, the Doctrine of Discovery is the theological and legal justification of domination. This attempt to justify domination focuses on three things enslavement, exploitation, and extraction. With something as deeply rooted and embedded in our society as the Doctrine of Discovery it is difficult to know where to begin so this podcast begins, in the middle. We begin tracing the roots of this system of domination by starting with what does it mean to resist white Christian hegemony.</p>\n<p>Likewise, this podcast is rooted in another story, the story of the Great Law of Peace and the Haudenosaunee Confederacy's labors to create, preserve, and maintain another system of relationship not only with each other but also the natural world.  Through this podcast week seek to juxtapose the Doctrine of Christian Discovery over and against other modes of being. Rabbi Abraham Joshua Heschel famously wrote that &quot;words create worlds.&quot; This podcast seeks to interrogate not only the rhetorics of domination but also the rhetorics of liberation. We look to the past to learn the lessons of the prior generations in order to create a better world for the generations yet to come.</p>\n<p>Please take a moment and listen to our podcast, peruse our show notes, resources, and transcripts.</p>\n<p><a href=\"https://podcast.doctrineofdiscovery.org\">The Mapping the Doctrine of Discovery podcast</a> is one part of the larger <a href=\"https://doctrineofdiscovery.org\">Doctrine of Discovery Project</a> presented by the <a href=\"https://indigenousvalues.org/\">Indigenous Values Initiative</a>.</p>\n<div id='buzzsprout-large-player'></div><script type='text/javascript' charset='utf-8' src='https://www.buzzsprout.com/1926214.js?container_id=buzzsprout-large-player&player=large'></script>\n<h2 id=\"resources\" tabindex=\"-1\">Resources: <a class=\"header-anchor\" href=\"#resources\">#</a></h2>\n<ul>\n<li><a href=\"https://podcast.doctrineofdiscovery.org\">Mapping the Doctrine of Discovery</a></li>\n<li><a href=\"https://doctrineofdiscovery.org\">Doctrine of Discovery Project</a></li>\n<li><a href=\"https://www.thenandnow.us/\">Then and Now Project</a></li>\n<li><a href=\"https://www.sullivanclinton.com/\">Sullivan Clinton Project</a></li>\n<li><a href=\"https://indigenousvalues.org/\">Indigenous Values Initiative</a></li>\n<li><a href=\"https://aila.ngo\">American Indian Law Alliance AILA</a></li>\n</ul>\n",
			"date_published": "2024-02-01T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2023-09-29-doctrine-discovery-conference/",
			"url": "https://www.adamdjbrett.com/blog/2023-09-29-doctrine-discovery-conference/",
			"title": "Syracuse University to Host Conference that Addresses Legal and Theological Theory of the Doctrine of Christian Discovery",
			"content_html": "<p><a href=\"https://artsandsciences.syracuse.edu/religion/news/university-to-host-conference-that-addresses-legal-and-theological-theory-of-the-doctrine-of-christian-discovery/\">Syracuse University to Host Conference that Addresses Legal and Theological Theory of the Doctrine of Christian Discovery.</a></p>\n",
			"date_published": "2023-09-29T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2023-03-10-canopy-forum-series/",
			"url": "https://www.adamdjbrett.com/blog/2023-03-10-canopy-forum-series/",
			"title": "200 Years of Johnson v. M’Intosh: Law, Religion, and Native American Lands, A Canopy Forum Thematic Series",
			"content_html": "<ul>\n<li>Co-author, Lyons, Betty and Adam DJ Brett. “However, Extravagant The Pretensions Of Johnson V. M’Intosh.” <em>Canopy Forum</em>, March 23, 2023, <a href=\"https://canopyforum.org/2023/03/23/however-extravagant-the-pretensions-of-johnson-v-mintosh/\">https://canopyforum.org/2023/03/23/however-extravagant-the-pretensions-of-johnson-v-mintosh/</a>.</li>\n<li>Co-author, Philip P. Arnold, Sandra L. Bigtree and Adam DJ Brett. &quot;Introduction to the 200 Years of <em>Johnson v. M'Intosh</em>: Law, Religion, and Native American Lands Series. March 10, 2023&quot; <a href=\"https://canopyforum.org/2023/03/10/introduction-to-the-200-years-of-johnson-v-mintosh-law-religion-and-native-american-lands-series/\">https://canopyforum.org/2023/03/10/introduction-to-the-200-years-of-johnson-v-mintosh-law-religion-and-native-american-lands-series/</a>.</li>\n<li>Co-author, &quot;200 Years of <em>Johnson v. M'Intosh</em>: Law, Religion, and Native American Lands A Canopy Forum Thematic Series, <em>March -- April 2023</em>,&quot; <em>Canopy Forum</em> <a href=\"https://canopyforum.org/200-years-of-johnson-v-mintosh-law-religion-and-native-american-lands/\">https://canopyforum.org/200-years-of-johnson-v-mintosh-law-religion-and-native-american-lands/</a>.</li>\n</ul>\n",
			"date_published": "2023-03-10T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2020-06-30-mother-earths-pandemic/",
			"url": "https://www.adamdjbrett.com/blog/2020-06-30-mother-earths-pandemic/",
			"title": "Mother Earth&#39;s Pandemic: The Doctrine of Discovery",
			"content_html": "<blockquote>\n<p>“Peace can only be attained when human beings live in proper relationship to the natural world” ~Tadodaho of the Haudenosaunee Confederacy, Sid Hill</p>\n</blockquote>\n<blockquote>\n<p>“The pandemic gives us all an opportunity to be at home and reflect on what we have done and where we are going. It is an opportunity for Mother Earth to breath, rest and recover.” ~Jake Haiwhagai'i Edwards, Onondaga Nation citizen</p>\n</blockquote>\n<p><a href=\"/assets/img/Broken-Treaties-Brandon-Lazore-Web-credit.webp\"><img src=\"/assets/img/Broken-Treaties-Brandon-Lazore-Web-credit.webp\" alt=\"&quot;Photo credit: Broken Treaties by Brandon Lazore&quot;\"></a></p>\n<h2 id=\"event-details\" tabindex=\"-1\">Event Details <a class=\"header-anchor\" href=\"#event-details\">#</a></h2>\n<ul>\n<li><strong>Title</strong>: Mother Earth’s Pandemic: The Doctrine of Discovery</li>\n<li><strong>Dates</strong>: Thursday August 6, 13, and 20, 2020</li>\n<li><strong>Times</strong>: 6-9 PM EST each Thursday, followed by caucuses/small group discussions.</li>\n<li><strong>Sponsors</strong>: <a href=\"https://indigenousvalues.org\">Indigenous Values Initiative</a> and <a href=\"https://aila.ngo\">American Indian Law Alliance</a></li>\n</ul>\n<p><a href=\"https://indigenousvalues.org/mother-earths-pandemic/\">→ Register for the Conference</a></p>\n<p>The “Doctrine of Discovery,” better described as the “Doctrine of Christian Discovery and World Domination,” established the worldview that not only brought devastation to the natural world, but also impaired the ability for human beings to live in proper relationship with the Earth. 15<sup>th</sup> century Papal Bulls, issued by the Vatican, justified the assault upon Indigenous Peoples as an artificial justification to take possession of their bodies, lands and resources in order to finance their New World Order. This worldview advanced the Age of Discovery as an extension of the Crusades, and was the conceptual framework behind the Protestant Reformation, the establishment of Nation States around the world, and later secularized to define colonialism, white supremacy and global capitalism.</p>\n<p>Essentially, what defines Indigenous Peoples is their relationship with a living landscape that includes the soil, water, air, and all other non-human being co-inhabitants. This orientation to land is distinctly opposed to the European concept of owning land and the process of colonization. Indigenous scholars have discussed these two opposing orientations as being one of habitation and the other, of occupation. Although the violent seizure of Indigenous lands was initiated with “discovery,” corporations today, continue exploiting Indigenous Peoples and their land all over the world. The Doctrine of Discovery is the root of the problem, and the reason that it is discussed at the United Nations Permanent Forum on Indigenous Issues.</p>\n<p>This current pandemic and the escalating climate chaos clarify to everyone that there are consequences to the devastation humans have perpetrated upon the environment. As Oren Lyons has pointed out, Natural Law will reestablish balance, and these climate changes will not destroy the Earth, but will most likely destroy the human beings who abuse her. The earth will rebound in its own time. If we are to survive as a species, we must reorient to an Indigenous worldview acknowledging that we are first and foremost, co-inhabitants with this Earth—not in charge of it. These Indigenous values, along with the acceptance of traditional ecological knowledge, will transform future technological innovations possibly resulting in a viable future for our species. Religious concepts of imperial thinking urgently need to be re-imagined; messages from Indigenous Peoples need to be heeded; and environmental justice needs to be restored. Racist ideologies of conquest and domination are directly connected with domination of the Earth and other non-human beings.</p>\n<p>This conference will connect the dots between our current pandemic, environmental devastation, the Doctrine of Discovery, and a way forward. Too often these are thought of as unrelated concepts, rather than being the core impediment in working towards social justice in an ecologically balanced Earth. Our speakers have been working in these areas for many decades. Participants will hear the wisdom from the traditions of the Haudenosaunee (Iroquois), as well as other Indigenous Peoples. Through virtual discussion groups, you will be able to interact on how best to implement these values of respect, thanksgiving, and peace into your lives. Please join us in August 2020 for conversations about the Doctrine of Discovery, so we can begin the process of decolonization back to understanding our proper relationship to the natural world and peace.</p>\n<ul>\n<li><a href=\"https://indigenousvalues.org/mother-earths-pandemic/\">→ View the schedule</a>{: .btn .btn--success}</li>\n<li><a href=\"/assets/pdfs/mother-earth-pandemic-doctrine-discovery-2020.pdf\">⤓ Download the flyer as a PDF</a>{: .btn .btn--info}</li>\n</ul>\n",
			"date_published": "2020-06-30T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2020-04-18-nocode/",
			"url": "https://www.adamdjbrett.com/blog/2020-04-18-nocode/",
			"title": "Embracing #nocode &amp; creating a website",
			"content_html": "<p>Let’s learn to build a website using <a href=\"https://www.name.com/referral/da845\">name.com</a> and <a href=\"https://try.carrd.co/adjb\">carrd.co</a> in order to create excellent #nocode one page portfolios and more. There are lots of wonderful website builders out there but none faster, easier, and more <strong>fun</strong> than <a href=\"https://try.carrd.co/yfsyxjl3\">carrd.co</a>. If you don't believe me I will show you.</p>\n<h2 id=\"episode-10-of-the-gladden-podcast\" tabindex=\"-1\">Episode 10 of the 🎙 Gladden Podcast <a class=\"header-anchor\" href=\"#episode-10-of-the-gladden-podcast\">#</a></h2>\n<h3 id=\"embracing-the-nocode-movement-and-creating-an-online-portfolio\" tabindex=\"-1\">Embracing the #nocode movement and creating an online portfolio <a class=\"header-anchor\" href=\"#embracing-the-nocode-movement-and-creating-an-online-portfolio\">#</a></h3>\n<ul>\n<li>Saturday April 18, 2020 7:00PM EST</li>\n<li>Host: D Garmondyu Whorway</li>\n<li>Guest: Adam DJ Brett</li>\n<li>Watch: <a href=\"https://www.facebook.com/gladdenpodcast/\">Facebook</a></li>\n<li>Listen: <a href=\"https://www.spreaker.com/show/gladden\">Spreaker</a></li>\n<li>Slides: <a href=\"/nocode-slides/\">#nocode slides</a></li>\n<li>Demos: <a href=\"https://bleannatorres.uwu.ai/\">B'Elanna Torres</a></li>\n</ul>\n<h2 id=\"watch\" tabindex=\"-1\">Watch <a class=\"header-anchor\" href=\"#watch\">#</a></h2>\n<style>.embed-container { position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden; max-width: 100%; } .embed-container iframe, .embed-container object, .embed-container embed { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }</style><div class='embed-container'><iframe src='https://player.vimeo.com/video/409573487' frameborder='0' webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe></div>\n<h2 id=\"listen\" tabindex=\"-1\">Listen <a class=\"header-anchor\" href=\"#listen\">#</a></h2>\n<iframe src=\"https://widget.spreaker.com/player?episode_id=25729238&theme=light&autoplay=false&playlist=false&cover_image_url=https%3A%2F%2Fd3wo5wojvuv7l.cloudfront.net%2Fimages.spreaker.com%2Foriginal%2Fdf03c21140ffbb44506b840bebb0e003.webp\" width=\"100%\" height=\"400px\" frameborder=\"0\"></iframe>\n<h3 id=\"discounts\" tabindex=\"-1\">Discounts: <a class=\"header-anchor\" href=\"#discounts\">#</a></h3>\n<ul>\n<li><a href=\"https://www.name.com/referral/da845\">name.com</a> - $5 promo credit</li>\n<li><a href=\"https://try.carrd.co/adjb\">carrd.co</a>\n<ul>\n<li>Users who visit Carrd through your link (or enter your referral code –  – directly at checkout) will earn you 30% of the amount paid towards their next Pro upgrade or renewal</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"resources-and-links\" tabindex=\"-1\">Resources and Links: <a class=\"header-anchor\" href=\"#resources-and-links\">#</a></h3>\n<ul>\n<li><a href=\"/nocode-slides/\">Episode Slides</a></li>\n<li><a href=\"https://www.wired.com/insights/2012/07/a-domain-of-ones-own/\">A Domain of One's Own</a></li>\n<li><a href=\"https://templates-of.carrd.co/\">templates-of.carrd.co</a></li>\n</ul>\n<h4 id=\"sites-mentioned-on-the-show\" tabindex=\"-1\">Sites mentioned on the show: <a class=\"header-anchor\" href=\"#sites-mentioned-on-the-show\">#</a></h4>\n<ul>\n<li><a href=\"https://www.facebook.com/gladdenpodcast/\">Gladden Podcast</a></li>\n<li><a href=\"https://www.spreaker.com/show/gladden\">Gladden on Spreaker</a></li>\n<li><a href=\"https://black.af\">black.af</a></li>\n<li><a href=\"https://davidrose.style/\">davidrose.style</a></li>\n<li><a href=\"http://syndicate.network\">syndicate.network</a></li>\n<li><a href=\"https://adamdjbrett.com\">adamdjbrett.com</a></li>\n<li><a href=\"https://suhrff.syr.edu/\">suhrff.syr.edu</a></li>\n<li><a href=\"http://goodwin.hcommons.org/\">goodwin.hcommons.org</a>\n<ul>\n<li><a href=\"https://keepingit101.com/\">keepingit101.com</a></li>\n<li><a href=\"https://www.sacred-writes.org/\">www.sacred-writes.org</a></li>\n</ul>\n</li>\n</ul>\n<h4 id=\"my-favorite-carrd-sites\" tabindex=\"-1\">My Favorite Carrd sites: <a class=\"header-anchor\" href=\"#my-favorite-carrd-sites\">#</a></h4>\n<ul>\n<li><a href=\"https://kaitlynstarbrett.com/\">Kaitlyn Star Brett</a></li>\n<li><a href=\"https://www.jordanbradyloewen.com/\">Jordan Brady Loewen</a></li>\n<li><a href=\"https://themidgeekcrisis.com/\">The Mid-Geek Crisis</a></li>\n<li><a href=\"https://www.coinop-collective.com/\">Coin-Op Collective</a></li>\n<li><a href=\"https://www.siblingstreamer.com/\">Sibling Streamers</a></li>\n</ul>\n<h3 id=\"lets-connect-on-social-media\" tabindex=\"-1\">Lets Connect on Social Media <a class=\"header-anchor\" href=\"#lets-connect-on-social-media\">#</a></h3>\n<ul>\n<li><a href=\"http://facebook.com/adamdjbrett\">Facebook</a></li>\n<li><a href=\"http://twitter.com/__adjb\">Twitter</a></li>\n<li><a href=\"http://instagram.com/__adjb\">Instagram</a></li>\n<li><a href=\"http://linkedin.com/in/adamdjbrett\">LinkedIn</a></li>\n<li><a href=\"https://github.com/adamdjbrett\">Github</a></li>\n<li><a href=\"https://orcid.org/0009-0004-6725-8425\">ORCID</a></li>\n</ul>\n<h3 id=\"tip-jar\" tabindex=\"-1\">Tip Jar <a class=\"header-anchor\" href=\"#tip-jar\">#</a></h3>\n<ul>\n<li><a href=\"https://paypal.com/adamdjbrett\">paypal</a></li>\n<li><a href=\"https://venmo.com/adamdjbrett\">venmo</a></li>\n<li><a href=\"https://cash.app/$adamdjbrett\">cashapp</a></li>\n</ul>\n<hr>\n<h2 id=\"presentation-outline\" tabindex=\"-1\">Presentation Outline <a class=\"header-anchor\" href=\"#presentation-outline\">#</a></h2>\n<h3 id=\"goals\" tabindex=\"-1\">Goals <a class=\"header-anchor\" href=\"#goals\">#</a></h3>\n<ol>\n<li>Convince everyone that they should have a website</li>\n<li>Show and Tell\n- In 30 minutes I will\na. Show everyone how quick and affordable it is to get started hosting their own site\nb. demonstrate how to this using <a href=\"https://name.com\">name.com</a> and <a href=\"https://carrd.co\">carrd.co</a>.</li>\n<li>Give everyone discounts</li>\n<li>If you need help I'm just a <a href=\"https://paypal.com/adamdjbrett\">paypal</a>, <a href=\"https://venmo.com/adamdjbrett\">venmo</a>, <a href=\"https://cash.app/$adamdjbrett\">cashapp</a> away @adamdjbrett.</li>\n</ol>\n<h3 id=\"everyone-should-have-a-website\" tabindex=\"-1\">Everyone should have a website <a class=\"header-anchor\" href=\"#everyone-should-have-a-website\">#</a></h3>\n<ul>\n<li>Freelancers, hobbits, pastors, professors, and politicians all have a website</li>\n<li>especially graduate students</li>\n</ul>\n<h3 id=\"why\" tabindex=\"-1\">Why? <a class=\"header-anchor\" href=\"#why\">#</a></h3>\n<ul>\n<li>creates your visual and visible centralized hub that curates your digital identity.</li>\n<li>it is way easier and more consistent when someone asks what's your etsy store, venmo, cashapp, social media to say go to: <code>example.com</code></li>\n<li>If you have a podcast or live stream and you are making graphics its cleaner and neater to say visit example.com click the youtube button and subscribe etc.</li>\n</ul>\n<h3 id=\"picking-a-domain-name\" tabindex=\"-1\">Picking a Domain name <a class=\"header-anchor\" href=\"#picking-a-domain-name\">#</a></h3>\n<ul>\n<li>Now that I have convinced you to have a website. How should you have a website?</li>\n<li>There are a couple of different ways\n<ol>\n<li>Have your own domain name like me <a href=\"https://adamdjbrett.com\">adamdjbrett.com</a></li>\n<li>If you are university affiliated use your institutional hosting like Garmondyu <a href=\"https://suhrff.syr.edu/\">suhrff.syr.edu/</a></li>\n<li>Have a subdomain on a popular platform like <code>your-name.wordpress.com</code>, <code>your-name.wix.com</code>, etc</li>\n</ol>\n</li>\n</ul>\n<h4 id=\"pros-and-cons-of-each-approach\" tabindex=\"-1\">Pros and Cons of each approach <a class=\"header-anchor\" href=\"#pros-and-cons-of-each-approach\">#</a></h4>\n<ul>\n<li>institutional Hosting:\n<ul>\n<li>pros:\n<ul>\n<li>feels authoritative</li>\n<li>.edu is cool 😎</li>\n<li>Free</li>\n<li>cheap</li>\n</ul>\n</li>\n<li>Cons:\n<ul>\n<li>eventually you will change institutions\n<ul>\n<li>loss of visual identity</li>\n<li>loss of traffic and incoming links</li>\n<li>your search engine optimization dies</li>\n<li>moving platforms is a giant massive pain.</li>\n<li>If you need help moving platforms pay me, I can help</li>\n</ul>\n</li>\n<li>often the URL is quite long and not memorable</li>\n</ul>\n</li>\n<li>subdomains\n<ul>\n<li>Pros:\n<ul>\n<li>free or lowcost</li>\n<li>ubiquitious popular wix, weebly, WordPress, Squarespace</li>\n</ul>\n</li>\n<li>Cons:\n<ul>\n<li>covered in advertising</li>\n<li>long urls</li>\n<li>can feel not as personal</li>\n<li><strong>exception</strong> hcommons :heart:</li>\n</ul>\n</li>\n</ul>\n</li>\n<li>personal domain name\n<ul>\n<li>Pros:\n<ul>\n<li>awesome</li>\n<li>memorable</li>\n<li>yours</li>\n</ul>\n</li>\n<li>Cons:\n<ul>\n<li>costs money</li>\n<li>isn't always private</li>\n<li>.com, .net, .name are boring</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"a-domain-of-ones-own\" tabindex=\"-1\"><a href=\"https://www.wired.com/insights/2012/07/a-domain-of-ones-own/\">A Domain of One's Own</a> <a class=\"header-anchor\" href=\"#a-domain-of-ones-own\">#</a></h3>\n<ul>\n<li>Virginia Wolff taught us we need a room of one's own.</li>\n<li>You need a domain of your own</li>\n<li><a href=\"https://www.wired.com/insights/2012/07/a-domain-of-ones-own/\">A Domain of One's Own (DoOO)</a> comes out of a project at the University of Mary Washington in the 2000's.</li>\n</ul>\n<h3 id=\"code-levels-and-types\" tabindex=\"-1\">Code Levels and types <a class=\"header-anchor\" href=\"#code-levels-and-types\">#</a></h3>\n<p>now that I have hopefully convinced you that you need a domain name lets talk about what type of site do you need:</p>\n<h4 id=\"code-levels\" tabindex=\"-1\">Code levels <a class=\"header-anchor\" href=\"#code-levels\">#</a></h4>\n<ul>\n<li>High Code.\n<ul>\n<li>I host my site in Jekyll because I like to tweak all the things. I'm working on moving to Eleventy where thus far the gras looks greener.</li>\n</ul>\n</li>\n<li>Medium Code.\n<ul>\n<li>WordPress, Squarespace, etc. You will probably have to configure or code some things and copy paste stuff from stackexchange and hope it works</li>\n</ul>\n</li>\n<li>#nocode.\n<ul>\n<li>A mythical :unicorn: where you just do your thing and don't stress about life under the hood.</li>\n<li>#Nocode sounds expensive but with the right tools like <a href=\"https://carrd.co\">carrd.co</a> it doesn't have to be.</li>\n</ul>\n</li>\n</ul>\n<h4 id=\"website-types\" tabindex=\"-1\">Website Types: <a class=\"header-anchor\" href=\"#website-types\">#</a></h4>\n<ul>\n<li>Multi-page: You have all the pages and plan to have even more pages. Both of us have sites like this. Where we have all the data. Now you just gotta up keep the thing.</li>\n<li>One-page: You are a genius among mortals and like to keep it simple. You know that one page can have multiple elements.</li>\n</ul>\n<h3 id=\"show-and-tell-portion-of-the-show\" tabindex=\"-1\">Show and Tell Portion of the show <a class=\"header-anchor\" href=\"#show-and-tell-portion-of-the-show\">#</a></h3>\n<ol>\n<li>Buy a domain name via name.com</li>\n<li>Setup Carrd.co</li>\n<li>Connect them together</li>\n</ol>\n<h4 id=\"buy-a-domain-name\" tabindex=\"-1\">Buy a domain name <a class=\"header-anchor\" href=\"#buy-a-domain-name\">#</a></h4>\n<ul>\n<li>There are lots of companies that will sell you a domain name. I like <a href=\"https://name.com\">name.com</a> a lot.\n<ul>\n<li>Their customer service has always been quick and responsive for me. They actually read and reply to tweets and emails.</li>\n<li>They have had my back.</li>\n<li>Affordable</li>\n<li>easy to use</li>\n<li>only thing I don't like is privacy isn't included in the price but an extra add-on</li>\n<li>again lots of domain resellers like hover.com, namecheap.com, but name.com is mine.</li>\n</ul>\n</li>\n</ul>\n<h5>Domain options</h5>\n<p>- Classics\n- .com, .net, .org\n- Country Codes\n- .af, .co, .fm, .in, .us, .tv\n- New gTLDs\n- .cool, .coffee, .expert, .style</p>\n<h2 id=\"hosting-your-new-awesome-site\" tabindex=\"-1\">Hosting your new awesome site. <a class=\"header-anchor\" href=\"#hosting-your-new-awesome-site\">#</a></h2>\n<p>Again one page website</p>\n<ul>\n<li>Carrd.co offers two levels</li>\n<li>Pro Lite: $9 a year. up to 3 sites. Subdomains only but there are unbranded subdomains like crd.co and uwu.ai</li>\n<li>Pro Standard: $20 a year up to 10 sites and custom domains are incldued\nToday I will be using pro standard in my presentation</li>\n</ul>\n<h3 id=\"setup\" tabindex=\"-1\">Setup <a class=\"header-anchor\" href=\"#setup\">#</a></h3>\n<ul>\n<li>pick a template. If you don't like those defaults you can of course DIY or visit <a href=\"https://templates-of.carrd.co\">templates-of.carrd.co</a></li>\n<li>add your information</li>\n<li>for academics: host your CV on Google Docs, or some other online service.</li>\n<li>One thing I have learned from coding is keep your code <code>DRY</code>\n<ul>\n<li>Don't :claps: Repeat :claps: yourself :claps:</li>\n<li>Academics we are terrible at this 19 versions of your CV, putting it online as a PDF and its out of date by the time it goes up</li>\n<li>Make it easy to update. Keep once nice copy in a lovely online doc tool site. Now you only have to update it in once place and people can view it easily on whatever a device</li>\n<li>seriously PDFs are terrible. Especially on phones. UGH the worst.</li>\n<li>Give us a responsive document</li>\n</ul>\n</li>\n<li>I could make a lovely interactive and visual CV here. Instead I will link to the CV</li>\n<li>now lets publish</li>\n<li>you can visit the site at <a href=\"https://bleannatorres.uwu.ai/\">https://bleannatorres.uwu.ai/</a></li>\n<li>done</li>\n</ul>\n<h3 id=\"conclusion\" tabindex=\"-1\">Conclusion <a class=\"header-anchor\" href=\"#conclusion\">#</a></h3>\n<p>We talked about</p>\n<ol>\n<li>Why you should have a Website</li>\n<li>Why you should embrace #nocode for so many things. I love the low barrier of entry and how Carrd helps open the web back up for so many types of things</li>\n<li>We bought a domain name from name.com</li>\n<li>We setup carrd.co</li>\n<li>We left a tip?</li>\n</ol>\n<p>Thank you to Garmondyu for being such a wonderful host and having me on the Gladden Podcast which hopefully one day soon will have its own domain name and landing page possibly even with Carrd.co</p>\n",
			"date_published": "2020-04-18T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2020-03-17-referral-links/",
			"url": "https://www.adamdjbrett.com/blog/2020-03-17-referral-links/",
			"title": "Referral Links and Discount Codes",
			"content_html": "<p>When consulting on projects and/or working as a developer on a project I use a wide variety of tools in my tech stacks. These resources are all things I have found incredibly helpful for myself and/or clients. If you use any of these links I will earn a discount off of them and so will you.</p>\n<h3 id=\"domains\" tabindex=\"-1\">Domains <a class=\"header-anchor\" href=\"#domains\">#</a></h3>\n<h3 id=\"namecheap\" tabindex=\"-1\">Namecheap <a class=\"header-anchor\" href=\"#namecheap\">#</a></h3>\n<p><a href=\"https://namecheap.pxf.io/c/5542094/1632743/5618\">Namecheap</a> stands out as an excellent choice for purchasing domains and hosting websites due to its affordability, extensive features, and commitment to customer satisfaction. Offering over 400 top-level domains (TLDs) at competitive prices, it caters to a wide range of needs, from personal blogs to professional businesses. Customers benefit from free domain privacy protection, free BasicDNS, DNSSEC security, and a free website builder for easy and stylish layouts. Its hosting packages, including shared, VPS, and dedicated servers, guarantee 100% uptime, making it reliable for all website types. Namecheap also emphasizes security and privacy, providing free SSL certificates, robust firewalls, and round-the-clock support from a knowledgeable and friendly team. Whether you're a beginner or an advanced user, Namecheap offers the tools and services needed to build a strong online presence without breaking your budget.</p>\n<h4 id=\"name-com\" tabindex=\"-1\"><a href=\"https://www.name.com/referral/da845\">Name.com</a> <a class=\"header-anchor\" href=\"#name-com\">#</a></h4>\n<p><a href=\"https://www.name.com/referral/da845\">If you need a domain, Name.com is pretty amazing. Become a new customer and we both get $5!</a>. Every domain name I own is registered with name.com. I especially appreciate the ability to do ANAME or ALIAS records for DNS. This is incredibly helpful for &quot;serverless&quot; hosting like github, netlify, zeit.co, surge, etc. Name.com's customer support is super fast and responsive. Whenever I have had questions or concerns they have been right there ready to help. Register or transfer your domains with them today. The code is\n<code>da845</code></p>\n<h3 id=\"hosting\" tabindex=\"-1\">Hosting <a class=\"header-anchor\" href=\"#hosting\">#</a></h3>\n<h4 id=\"carrd-co-for-single-page-websites\" tabindex=\"-1\"><a href=\"https://try.carrd.co/adjb\">Carrd.co</a> for single page websites. <a class=\"header-anchor\" href=\"#carrd-co-for-single-page-websites\">#</a></h4>\n<ul>\n<li>If you visit Carrd.co <a href=\"https://try.carrd.co/adjb\">through my link</a> (or enter your referral code – <code>adjb</code> or <code>YXJL3</code> – directly at checkout) I will earn you 30% of the amount paid towards their next Pro upgrade or renewal. You will also get a discount.</li>\n<li>here is my page <a href=\"https://adjb.carrd.co\">adjb.carrd.co</a></li>\n<li>Carrd.co has a bunch of plans my favorite plans are:\n<ul>\n<li>Carrd.co Pro Standard is $19 a year. That is it just $19 a year.</li>\n<li>Carrd.co Pro Lite is $9 a year for a more budget friendly plan.</li>\n</ul>\n</li>\n<li><a href=\"https://try.carrd.co/adjb\">My Carrd discount code</a> is: <code>adjb</code> or <code>YFSYXJL3</code>.</li>\n</ul>\n<p>Carrd.co is the best #nocode utility out there. It is great for academics, professionals, and anyone who needs <a href=\"https://www.wired.com/insights/2012/07/a-domain-of-ones-own/\">a domain of one's own</a>. A domain of one's own is exactly like a room of one's own but only its digital. Carrd.co provides a simple and easy to use graphical user interface for creating amazing one-page sites for everything. Carrd.co has plenty of templates to get you started or you can DIY. Personally I use <strong>carrd.co pro standard</strong> all the time because it lets you bring and use your own domain name.  The only downside of <em>carrd.co pro lite</em> is you cant use your own domain name you do get a free subdomain name. Your options are: &quot;carrd.co&quot;, &quot;crd.co&quot;, or &quot;uwu.ai&quot;. UWU is an emoticon depicting cuteness overload. Carrd.co replaces: about.me, flavors.me, linkin.bio, linktr.ee, or whatever leadpage software you are running. Nine times out of ten Carrd also replaces WordPress, Wix, and Squarespace. Most of the time all a person needs is a snazzy one page website. Still not convinced to try <a href=\"https://try.carrd.co/adjb\">Carrd.co</a>? Here are some samples from my consulting clients:</p>\n<ul>\n<li><a href=\"http://kaitlynstarbrett.com/\">Kaitlyn Star Brett</a>\n<ul>\n<li>discount code: <a href=\"https://try.carrd.co/YFSYXJL3\">try.carrd.co/YFSYXJL3</a></li>\n</ul>\n</li>\n<li><a href=\"https://themidgeekcrisis.com/\">The Mid-Geek Crisis</a>\n<ul>\n<li><a href=\"http://try.carrd.co/midgeekcrisis\">The Mid-Geek Crisis Carrd discount code</a> is: <code>MIDGEEKCRISIS</code>.</li>\n</ul>\n</li>\n<li><a href=\"https://www.coinop-collective.com/\">Coin-Op Collective</a>.\n<ul>\n<li>The whole collective runs on nostalgia and carrd.co</li>\n</ul>\n</li>\n</ul>\n<h4 id=\"cloud-vps-hosting\" tabindex=\"-1\">Cloud VPS Hosting <a class=\"header-anchor\" href=\"#cloud-vps-hosting\">#</a></h4>\n<ul>\n<li><a href=\"https://m.do.co/c/ff35163be632\">Digital Ocean</a><br>\nDeploy your first cloud server with <a href=\"https://m.do.co/c/ff35163be632\">Digital Ocean</a> today! <a href=\"https://upcloud.com/signup/?promo=63JE42\">Get a $25 bonus when signing up with this referral link</a>.\nDo you need something more robust than a one page website and are you not ready to go &quot;serverless&quot; with a static site generator like Jekyll or 11ty? Then DigitalOcean is for you. In my experience UpCloud is way easier to use than Vultr and Digital Ocean. You can deploy a robust and fast WordPress site in about 2-3 minutes based on my experience. You will be able to have WordPress + your bespoke theme up and going quickly. Plus your server bill and hosting will be very reasonable and if you want you can always boost your WordPress site performance by adding a Content Delivery Network (CDN) to take a lhelp your audience get your content even faster.</li>\n</ul>\n<h3 id=\"content-delivery-network-cdn\" tabindex=\"-1\">Content Delivery Network (CDN) <a class=\"header-anchor\" href=\"#content-delivery-network-cdn\">#</a></h3>\n<h4 id=\"bunnycdn\" tabindex=\"-1\"><a href=\"https://bunnycdn.com/?ref=wtn001abeo\">BunnyCDN</a>. <a class=\"header-anchor\" href=\"#bunnycdn\">#</a></h4>\n<ul>\n<li>Refer a friend, get $20</li>\n<li>$20 earned for every new verified user you refer to BunnyCDN.</li>\n<li>A user must be active for at least 14 days and make a payment to count as verified.</li>\n<li>Apply the referral balance to your account at any time.</li>\n</ul>\n<p>Sometimes fast isn't fast enough. When you need to speed up your website try BunnyCDN. BunnyCDN is fast, reliable, and quite powerful. It is also the most cost effective CDN I have found thus far at mere pennies on the GB served up to your website visitors. If you have a resource intensive website or if your website is just extremely popular check out BunnyCDN.</p>\n<h3 id=\"email-forwarding\" tabindex=\"-1\">Email Forwarding <a class=\"header-anchor\" href=\"#email-forwarding\">#</a></h3>\n<p><a href=\"https://improvmx.com/\">Improv MX</a></p>\n<h2 id=\"shopping-discounts\" tabindex=\"-1\">Shopping Discounts <a class=\"header-anchor\" href=\"#shopping-discounts\">#</a></h2>\n<h3 id=\"pll-merch\" tabindex=\"-1\">PLL Merch <a class=\"header-anchor\" href=\"#pll-merch\">#</a></h3>\n<p><a href=\"https://refer.premierlacrosseleague.com/adam4673\">Merch</a></p>\n<h3 id=\"be-frugal\" tabindex=\"-1\">Be Frugal <a class=\"header-anchor\" href=\"#be-frugal\">#</a></h3>\n<ul>\n<li><a href=\"https://unionplus.befrugal.com/rs/OBADWWG/\">Be Frugal</a></li>\n</ul>\n<h3 id=\"web-stacks\" tabindex=\"-1\">Web Stacks <a class=\"header-anchor\" href=\"#web-stacks\">#</a></h3>\n<h4 id=\"personal-stack\" tabindex=\"-1\">Personal Stack <a class=\"header-anchor\" href=\"#personal-stack\">#</a></h4>\n<ul>\n<li>name.com (domain name)</li>\n<li>Google GSuite (email)</li>\n<li>Github (codebase + hosting)</li>\n<li><a href=\"http://jekyllrb.com/\">Jekyll (static site generator)</a></li>\n<li>Mac Apps\n<ul>\n<li>Terminal</li>\n<li><a href=\"https://atom.io/\">Atom text editor</a></li>\n<li>Sublime Text 3</li>\n<li>Safari Technology Preview</li>\n<li>Firefox Developer Edition</li>\n</ul>\n</li>\n</ul>\n<h4 id=\"static-site-client-stack\" tabindex=\"-1\">Static Site client stack <a class=\"header-anchor\" href=\"#static-site-client-stack\">#</a></h4>\n<ul>\n<li>name.com (domain name)</li>\n<li>Google GSuite (email)</li>\n<li>Github (codebase)</li>\n<li>Netlify (hosting)</li>\n<li><a href=\"http://jekyllrb.com/\">Jekyll (static site generator)</a></li>\n<li>Terminal</li>\n<li><a href=\"https://atom.io/\">Atom</a></li>\n</ul>\n<h4 id=\"dynamic-site-client-stack\" tabindex=\"-1\">Dynamic site client stack <a class=\"header-anchor\" href=\"#dynamic-site-client-stack\">#</a></h4>\n<ul>\n<li>name.com, namcheap.com, hover.com (domain names)</li>\n<li>Github (Codebase)</li>\n<li><a href=\"https://m.do.co/c/ff35163be632\">Digital Ocean</a> (hosting)\n<ul>\n<li><a href=\"https://www.vultr.com/?ref=8341661\">Vultr (hosting)</a></li>\n</ul>\n</li>\n<li>WordPress (Content Management System)</li>\n<li>BunnyCDN (Content Delivery Network)</li>\n</ul>\n<h3 id=\"mail\" tabindex=\"-1\">Mail <a class=\"header-anchor\" href=\"#mail\">#</a></h3>\n<ul>\n<li><a href=\"https://improvmx.com/\">ImprovMX</a></li>\n</ul>\n<h3 id=\"community\" tabindex=\"-1\">Community <a class=\"header-anchor\" href=\"#community\">#</a></h3>\n<ul>\n<li><a href=\"https://home.omg.lol/referred-by/adjb\">omg.lol</a></li>\n</ul>\n",
			"date_published": "2020-03-17T03:15:34Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2020-02-01-national-association-baptist-professors-religion/",
			"url": "https://www.adamdjbrett.com/blog/2020-02-01-national-association-baptist-professors-religion/",
			"title": "National Association of Baptist Professors of Religion",
			"content_html": "<p>The National Association of Baptist Professors of Religion is a community of teaching scholars. Most members teach at Baptist-affiliated schools, colleges, and seminaries, but members also hail from a wide range of institutions in the United States, Canada, and abroad, including church-related and state-supported schools.</p>\n<h2 id=\"the-national-association-of-baptist-professors-of-religion-nabpr\" tabindex=\"-1\">The National Association of Baptist Professors of Religion <a href=\"https://nabpr.org\">(NABPR)</a> <a class=\"header-anchor\" href=\"#the-national-association-of-baptist-professors-of-religion-nabpr\">#</a></h2>\n<p>I serve as the Assistant Executive Secretary. My two primary roles are social media coordinator and web administrator.</p>\n<h2 id=\"social-media-coordinator\" tabindex=\"-1\">Social Media Coordinator <a class=\"header-anchor\" href=\"#social-media-coordinator\">#</a></h2>\n<p>Recently I was hired to be the social media manager for NABPR and in this capacity I manage the website, two facebook groups, facebook page, twitter, and other social media platforms. Presently we use social media to reach out to members, live tweet conference keynotes and more. Until recently the website was hosted as a google site, until I moved it over to wordpress to better facilitate updating and maintaining the site while giving it a more modern look. Plus Wordpress allows for easier integration of online payments via paypal and better conforms to google and other search engines best practices.</p>\n<h2 id=\"web-administrator\" tabindex=\"-1\">Web Administrator <a class=\"header-anchor\" href=\"#web-administrator\">#</a></h2>\n<h3 id=\"programming-languages\" tabindex=\"-1\">Programming languages <a class=\"header-anchor\" href=\"#programming-languages\">#</a></h3>\n<ul>\n<li>HTML</li>\n<li>CSS</li>\n<li>Javascript</li>\n</ul>\n<h3 id=\"other-elements\" tabindex=\"-1\">Other elements <a class=\"header-anchor\" href=\"#other-elements\">#</a></h3>\n<ul>\n<li>Full responsive website</li>\n<li>social media manager</li>\n<li>Jekyll</li>\n<li>Github</li>\n<li>BunnyCDN</li>\n<li>integrated social media</li>\n<li>google analytics</li>\n<li>google search console</li>\n<li>PayPal integration</li>\n<li>online conference registration</li>\n</ul>\n",
			"date_published": "2020-03-17T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2020-02-20-haudenosaunee-womens-influence/",
			"url": "https://www.adamdjbrett.com/blog/2020-02-20-haudenosaunee-womens-influence/",
			"title": "Gloria Steinem",
			"content_html": "<p><em>The event was cancelled due to COVID-19 concerns</em></p>\n<h2 id=\"haudenosaunee-womens-influence-on-the-womens-rights-movement\" tabindex=\"-1\">Haudenosaunee Women's Influence on the Women's Rights Movement <a class=\"header-anchor\" href=\"#haudenosaunee-womens-influence-on-the-womens-rights-movement\">#</a></h2>\n<h2 id=\"featuring-gloria-steinem-sally-roesch-wagner-jeanne-shenandoah-and-betty-lyons\" tabindex=\"-1\">Featuring: Gloria Steinem, Sally Roesch Wagner, Jeanne Shenandoah, &amp; Betty Lyons <a class=\"header-anchor\" href=\"#featuring-gloria-steinem-sally-roesch-wagner-jeanne-shenandoah-and-betty-lyons\">#</a></h2>\n<p>While we celebrate the 100th anniversary of women gaining the right to vote in the United States, to celebrate the fact that women of the Haudenosaunee Confederacy have exercised political voice in this land for 1,000 years. These Indigenous women were the model for early suffragists like Lucretia Mott, Elizabeth Cady Stanton, and Matilda Joslyn Gage. In the mid-1800s, women of the United States were considered “dead in the law” after they married, which meant they had no rights and were under the control of their husbands. They looked at their Indigenous sisters, with whom they had formed friendships, and saw another society, one in which women and men were equals. Women were able to choose their political representatives, while having responsibility for the economy, land, and spiritual ceremonies. This model became the impetus for American women to demand equality under the law and the right to vote.</p>\n<p>![Haudenosaunee Women's Influence Poster](/assets/img/posters/2020-Haudenosaunee-women-influence-web.webp &quot;The central image features Onondaga Nation women (left to right) &quot;Clanmother Audrey Shenandoah, daughters Rochelle Brown and Jessica Jeanne Shenandoah with cameos of Elizabeth Cady Stanton (left), Matilda Joslyn Gage (center) and Lucretia Mott (right). Image SCW ©2018, Onondaga Nation photograph: Toba Tucker ©1991&quot;)</p>\n<p>To learn more about this amazing confluence of cultures and to celebrate the 100th anniversary of woman suffrage in 2020, join us as we honor our Haudenosaunee Sisters for their inspiration and guidance.</p>\n<ul>\n<li><strong>Gloria Steinem</strong>, writer, lecturer, political activist, and feminist organizer</li>\n<li><strong>Dr. Sally Roesch Wagner</strong>, Executive Director of the Matilda Joslyn Gage Foundation</li>\n<li><strong>Jeanne Shenandoah</strong>, Onondaga Nation Eel Clan Traditional Medicine Keeper</li>\n<li><strong>Gaeñ hia uh/Betty Lyons</strong>, Onondaga Nation, Snipe Clan, Executive Director of the <a href=\"https://aila.ngo\">American Indian Law Alliance</a></li>\n</ul>\n<p>After the panel, we will present the first Annual Matilda Effect Project Award to the family of Audrey Shenandoah held the title of Deer Clanmother of the Onondaga Nation. Audrey has represented the Haudenosaunee Confederacy internationally as a writer, teacher, and adviser of the Haudenosaunee Confederacy to the United Nations.</p>\n<h3 id=\"matilda-effect\" tabindex=\"-1\">Matilda Effect <a class=\"header-anchor\" href=\"#matilda-effect\">#</a></h3>\n<p>The term “Matilda Effect” was created by scientist Margaret Rossiter to refer to women like Gage who are not recognized for their achievements and inventions. The Matilda Effect Project will design a database that will memorialize their important contributions in an effort to repopulate our history with intersectional women who, like Gage, have worked for social justice and peace by creating a database that will memorialize their important efforts.</p>\n<p>The event is a fundraiser for the American Indian Law Alliance and the Matilda Joslyn Gage Foundation and is co-sponsored by the American Indian Community House and the Ethical NYC. For <a href=\"http://wwww.matildaeffect.events/\">TICKETS</a> visit: <a href=\"http://matildaeffect.events/\">http://matildaeffect.events/</a>.</p>\n<h2 id=\"event-details\" tabindex=\"-1\">Event Details <a class=\"header-anchor\" href=\"#event-details\">#</a></h2>\n<ul>\n<li>Date: March 9th, 2020</li>\n<li>Time:\n<ul>\n<li>VIP: 6:00-6:45PM</li>\n<li>Event: 7:00-9:00PM</li>\n</ul>\n</li>\n<li>Place: Ethical NYC, 2 West 64th Street New York, NY 10023</li>\n<li>Tickets:\n<ul>\n<li>VIP $200</li>\n<li>Event &amp; autographed copy of Sally Roesch Wagner’s <em>The Women’s Suffrage Movement</em>: $75</li>\n<li>Event: $50</li>\n</ul>\n</li>\n</ul>\n<p><a href=\"https://www.matildaeffect.events\">source: Matilda Effect</a></p>\n",
			"date_published": "2020-02-20T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2017-11-17-flourish-and-decay/",
			"url": "https://www.adamdjbrett.com/blog/2017-11-17-flourish-and-decay/",
			"title": "CFP: Flourish and Decay",
			"content_html": "<p>A Religion Department Graduate Conference with a keynote by Dr. Kathryn Lofton.</p>\n<h2 id=\"call-for-papers\" tabindex=\"-1\">Call for Papers <a class=\"header-anchor\" href=\"#call-for-papers\">#</a></h2>\n<p>The Religion Graduate Organization and the <a href=\"https://artsandsciences.syracuse.edu/religion//\">Department of Religion at Syracuse University</a> announce <a href=\"/\">the 2018 Graduate Student Conference <strong>Flourish and Decay: Exploring Religion in Process on Friday, April 13<sup>th</sup>, 2018.</strong></a>\n<a href=\"/assets/img/misc/2019-flourish-and-decay-header-main-min.webp\"><img src=\"/assets/img/tn/flourish-and-decay-header-main-min_tn.webp\" alt=\"Flourish and Decay Decorative Header\"></a></p>\n<p><em><strong>Flour·ish</strong>: [‘flǝriSH] (n., v.) growth and development in a good environment; a gesture or to gesture in such a way that attracts attention.</em></p>\n<p><em><strong>De·cay</strong>: [dǝ͘‘kā] ‘(n., v.) to rot organically or the process of decomposition; to deteriorate; to fall into a state of disrepair. Rotten matter. A gradual decline of quality.</em></p>\n<p>This conference proposes the terms “flourish” and “decay” as entry points through which to further understand how religion emerges and envelops within past, present, and future worlds.</p>\n<p>Both flourish and decay can operate as either overarching metaphors of change, transformation, and fluctuation or as literal descriptions of cycles of growth, consumption, and loss. We embrace the capaciousness of these terms and encourage graduate students to think innovatively through them as an opportunity to explore religion <em>in</em> process. We welcome diversity in topics, theoretical approaches, and methodologies from all academic fields and disciplines across a broad range of histories, geographies, and religious traditions.</p>\n<h3 id=\"keynote-kathryn-lofton-yale-university\" tabindex=\"-1\">Keynote: <a href=\"//keynote-speaker-kathryn-lofton/\">Kathryn Lofton, Yale University</a> <a class=\"header-anchor\" href=\"#keynote-kathryn-lofton-yale-university\">#</a></h3>\n<p>Papers and panels might engage the following (but not limited to) themes of:</p>\n<ul>\n<li>Fame, thriving, and prosperity</li>\n<li>Politics, conflict, and resistance</li>\n<li>Misogynoir, toxic masculinity, gender</li>\n<li>Afrofuturism, critical race theory</li>\n<li>Indigenous futurism, de/colonization practices</li>\n<li>Ruins, cities, empire, and war</li>\n<li>Futurity, millenarianism, apocalypticism and utopianism</li>\n<li>Community, class, geography, place, space</li>\n<li>Pollution in texts, bodies, environments, landscapes</li>\n<li>Disaster, trauma, toxicity, and recovery</li>\n<li>Life, biopolitics, necropolitics, health, governmentality</li>\n<li>Aesthetics, beauty, and the grotesque</li>\n<li>Precarity, neoliberalism, late capitalism, globalism, nationalism</li>\n<li>Environmentalism, the Anthropocene, climate change, waste</li>\n<li>Technology, transhumanism, robotics, and artificial intelligence</li>\n<li>The viral and the virtual, affect theory</li>\n<li>Death, funerary and burial rites</li>\n<li>Temporalities, histories</li>\n</ul>\n<p>Please submit a short abstract (350 words for papers; 500 words for panels) and a CV in PDF format to: SUReligionConference@gmail.com by <strong>January 20, 2018.</strong><br>\n<strong><a href=\"//\">religionconference.syr.edu</a></strong></p>\n<h4 id=\"download-promotional-flyers\" tabindex=\"-1\">Download Promotional Flyers <a class=\"header-anchor\" href=\"#download-promotional-flyers\">#</a></h4>\n<ul>\n<li><a href=\"//wp-content/uploads/2017/11/CFPflyer-print.pdf\">Print Flyer</a></li>\n<li><a href=\"//wp-content/uploads/2017/11/CFPflyer-web.pdf\">Web Flyer</a></li>\n</ul>\n<p><a href=\"/\">source</a></p>\n",
			"date_published": "2017-11-17T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2017-08-16-syallbus-design/",
			"url": "https://www.adamdjbrett.com/blog/2017-08-16-syallbus-design/",
			"title": "Syllabus Design Resources at Syracuse University",
			"content_html": "<p>Syracuse University syallbi design resources for teaching assistants.</p>\n<h2 id=\"syracuse-university-teaching-assistant-orientation\" tabindex=\"-1\">Syracuse University Teaching Assistant Orientation <a class=\"header-anchor\" href=\"#syracuse-university-teaching-assistant-orientation\">#</a></h2>\n<h3 id=\"syllabus-design-workshop\" tabindex=\"-1\">Syllabus Design Workshop <a class=\"header-anchor\" href=\"#syllabus-design-workshop\">#</a></h3>\n<p>Small Group #2\nAugust 16, 2017</p>\n<h2 id=\"syllabus-recommendations\" tabindex=\"-1\">Syllabus Recommendations <a class=\"header-anchor\" href=\"#syllabus-recommendations\">#</a></h2>\n<ul>\n<li>\n<p>Please check with <a href=\"https://class.syr.edu\">CLASS</a> and your department to ensure that you are including the required syallbi elements.</p>\n</li>\n<li>\n<p><a href=\"https://class.syr.edu/academic-integrity/policy/\">Updated Academic Integrity Policy</a></p>\n<ul>\n<li><a href=\"https://class.syr.edu/academic-integrity/syllabus-recommendations/\">Academic Integrity Syllabus Recommendations</a></li>\n<li><a href=\"https://class.syr.edu/academic-integrity/expectations/\">Academic Integrity Expecations</a>\n<ul>\n<li>It is important to take time in class to cover these expectations with studies</li>\n</ul>\n</li>\n</ul>\n</li>\n<li>\n<p><a href=\"https://class.syr.edu/academic-integrity/syllabus-recommendations/\">Course Specific Policies on the Use of Turnitin</a></p>\n</li>\n<li>\n<p>Religious Observance Policy</p>\n<blockquote>\n<blockquote>\n<p>Religious Observances Notification and Policy</p>\n</blockquote>\n</blockquote>\n<blockquote>\n<blockquote>\n<p>SU religious observances notification and policy, found at  https://hendricks.syr.edu/spiritual-life/index.html, recognizes the diversity of faiths represented among the campus community and protects the rights of students, faculty, and staff to observe religious holidays according to their tradition.  Under the policy, students are provided an opportunity to make up any examination, study, or work requirements that may be missed due to a religious observance provided they notify their instructors before the end of the second week of classes for regular session classes and by the submission deadline for flexibly formatted classes.</p>\n</blockquote>\n</blockquote>\n<blockquote>\n<blockquote>\n<p>For fall and spring semesters, an online notification process is available for students in <strong>My Slice / StudentServices / Enrollment / MyReligiousObservances / Add a Notification.</strong>  Instructors may access a list of their students who have submitted a notification in My Slice Faculty Center. [Enter course specific language as appropriate, about how and when academic requirements will be made up.]</p>\n</blockquote>\n</blockquote>\n</li>\n<li>\n<p><a href=\"https://coursecatalog.syr.edu/content.php?catoid=3&amp;navoid=270#Student_Academic_Work\">Student Academic Work Policy</a></p>\n</li>\n</ul>\n<h2 id=\"syllabus-required-statement-on-disability-related-accommodations\" tabindex=\"-1\">Syllabus Required Statement on Disability-Related Accommodations <a class=\"header-anchor\" href=\"#syllabus-required-statement-on-disability-related-accommodations\">#</a></h2>\n<ul>\n<li><a href=\"https://universitysenate.syr.edu/curricula/courses-proc/syllabus/disability-syllabus-statement/\">Syllabus Statement Regarding Disability-Related Academic Adjustments (required)</a></li>\n<li><a href=\"https://disabilityservices.syr.edu/faculty-staff/syllabus-statement/\">Optional Diversity and Disability Syllabus Statement: (in addition to the required syllabus statement)</a></li>\n</ul>\n<h2 id=\"template\" tabindex=\"-1\">Template <a class=\"header-anchor\" href=\"#template\">#</a></h2>\n<ul>\n<li><a href=\"https://universitysenate.syr.edu/curricula/forms/course-syllabus-template/\">Site for Course Syllabus Template</a></li>\n<li><a href=\"https://universitysenate.syr.edu/curricula/wp-content/uploads/sites/2/2013/08/syllabus-template.docx\">Syllabus Template docx file</a></li>\n</ul>\n<h3 id=\"disclaimer\" tabindex=\"-1\">Disclaimer <a class=\"header-anchor\" href=\"#disclaimer\">#</a></h3>\n<p>This page is designed to point Syracuse University Teaching Assitants towards <strong>some</strong> of the relveant rescources to consider when doing course design. This list is by no means exhaustive and should not in any way be considered definitive.</p>\n<h4 id=\"image-credit\" tabindex=\"-1\">image credit <a class=\"header-anchor\" href=\"#image-credit\">#</a></h4>\n<p><a href=\"https://pixabay.com/en/technology-classroom-education-1095751/\">LTDSupport</a></p>\n",
			"date_published": "2017-08-16T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2017-08-16-su-policy-statements/",
			"url": "https://www.adamdjbrett.com/blog/2017-08-16-su-policy-statements/",
			"title": "Selected Syracuse University Policy Statements",
			"content_html": "<p>These are selected Syracuse University policy documents which might be useful in helping to facilitate leading TA orientation small groups.</p>\n<p>This list is not exhaustive and was for an exercise in 2017.\nPlease discuss SU policy with your department and <a href=\"supolicies.syr.edu\">Syracuse University  Governance, Ethics, Integrity, and Legal Compliance</a>.</p>\n<h1 id=\"su-policy-statements\" tabindex=\"-1\">SU Policy Statements <a class=\"header-anchor\" href=\"#su-policy-statements\">#</a></h1>\n<p><a href=\"supolicies.syr.edu\">Syracuse University  Governance, Ethics, Integrity, and Legal Compliance</a></p>\n<ul>\n<li><a href=\"https://class.syr.edu/academic-integrity/policy/\">Academic Integrity (effective January 1, 2017)</a></li>\n<li><a href=\"http://supolicies.syr.edu/ethics/athletic_comply.htm\">Athletic Compliance Policy Statement</a></li>\n<li><a href=\"http://supolicies.syr.edu/ethics/alcohol.htm\">Alcohol, Other Drugs, and Tobacco Policies</a></li>\n<li><a href=\"http://supolicies.syr.edu/ethics/ferpa.htm\">Compliance with the Family Educational Rights and Privacy Act (FERPA)</a></li>\n<li><a href=\"http://supolicies.syr.edu/ethics/nonD_equal_policy.htm\">Non-Discrimination and Equal Opportunity Policy Statement</a></li>\n<li><a href=\"http://supolicies.syr.edu/ethics/nonD_disability_policy.htm\">Non-Discrimination on the Basis of Disability Policy Statement</a></li>\n<li><a href=\"http://supolicies.syr.edu/ethics/nonD_harass_emp.htm\">Non-Discrimination and Anti-Harassment in Employment</a></li>\n<li><a href=\"http://supolicies.syr.edu/ethics/nonD_emp_disability.htm\">Non-Discrimination in Employment on the Basis of Disability</a></li>\n<li><a href=\"http://supolicies.syr.edu/ethics/nonD_equal_emp.htm\">Non-Discrimination, Equal Employment Opportunity and Affirmative Action</a></li>\n<li><a href=\"http://supolicies.syr.edu/ethics/nonD_stud_disability.htm\">Non-Discrimination, Students with Disabilities Policy</a></li>\n<li><a href=\"http://supolicies.syr.edu/ethics/retaliation.htm\">prohibition of retaliation</a></li>\n<li><a href=\"http://supolicies.syr.edu/ethics/sexual_harass.htm\">sexual harassment.</a></li>\n<li><a href=\"http://counselingcenter.syr.edu/faculty-staff/title-ix-reporting.html\">Title IX Reporting</a></li>\n<li><a href=\"http://inclusion.syr.edu\">Office of Equal Opportunity, Inclusion, and Resolution Services</a></li>\n</ul>\n<h3 id=\"disclaimer\" tabindex=\"-1\">Disclaimer <a class=\"header-anchor\" href=\"#disclaimer\">#</a></h3>\n<p>This page shows a sample of some of the Syracuse University Policy Statements, for those looking for a place to begin examining university policies and proceedures. This list is not exhaustive.Please review and study the full list of SU Policy Statements. If you have questions or concerns please contact supolicy@syr.edu <a href=\"http://supolicies.syr.edu/\">http://supolicies.syr.edu/</a></p>\n<h4 id=\"image-credit\" tabindex=\"-1\">image credit <a class=\"header-anchor\" href=\"#image-credit\">#</a></h4>\n<p><a href=\"https://pixabay.com/en/technology-classroom-education-1095751/\">LTDSupport</a></p>\n",
			"date_published": "2017-08-16T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2017-08-16-integrating-techology/",
			"url": "https://www.adamdjbrett.com/blog/2017-08-16-integrating-techology/",
			"title": "Integrating Technology in the Classroom",
			"content_html": "<p>A presentation on integrating technology into the classroom.</p>\n<h2 id=\"integrating-technology-in-the-classroom\" tabindex=\"-1\">Integrating Technology in the Classroom <a class=\"header-anchor\" href=\"#integrating-technology-in-the-classroom\">#</a></h2>\n<p>by <strong>Adam DJ Brett &amp; Caleb McWhorter</strong>\nAugust 16, 2017</p>\n<p><a href=\"https://goo.gl/vwqW4A\">Google Apps Presentation slides</a></p>\n<h2 id=\"main-points\" tabindex=\"-1\">Main Points <a class=\"header-anchor\" href=\"#main-points\">#</a></h2>\n<ul>\n<li>Student Engagement</li>\n<li>Student Evaluation</li>\n<li>Student Assessment</li>\n<li>Graduate Student Resources</li>\n</ul>\n<h3 id=\"student-engagement-attendance\" tabindex=\"-1\">Student Engagement - Attendance <a class=\"header-anchor\" href=\"#student-engagement-attendance\">#</a></h3>\n<ul>\n<li><a href=\"https://itunes.apple.com/us/app/attendance2/id536206472?mt=8\">Attendance2 for iOS - David M. Reed Software</a></li>\n<li><a href=\"https://play.google.com/store/apps/details?id=peterman.apps.attendance&amp;hl=en\">Attendance Tracker for Android - PeterMan Apps </a></li>\n<li><a href=\"https://tophat.com/\">TopHat</a></li>\n<li>Sign in sheet with two signature spaces</li>\n</ul>\n<h3 id=\"student-engagement\" tabindex=\"-1\">Student Engagement <a class=\"header-anchor\" href=\"#student-engagement\">#</a></h3>\n<ul>\n<li>Kahoot.it\n<ul>\n<li>Gamification of classroom</li>\n</ul>\n</li>\n<li>Google Docs/Blackboard</li>\n<li>Discussion pages &amp; collaborative note taking\nPrompts</li>\n<li>Class hashtag for introverts</li>\n<li>Flipping the Classroom and Video</li>\n<li>Youtube/Vimeo/<a href=\"http://ensemble.syr.edu\">Ensemble Video (SU private)</a></li>\n<li>Handouts - question tools</li>\n</ul>\n<h3 id=\"student-engagement-flipping-the-classroom\" tabindex=\"-1\">Student Engagement - Flipping the Classroom <a class=\"header-anchor\" href=\"#student-engagement-flipping-the-classroom\">#</a></h3>\n<ul>\n<li>Video\n<ul>\n<li>Youtube/Vimeo/Ensemble Video (SU private Youtube)</li>\n</ul>\n</li>\n<li><a href=\"https://coursecast.ischool.syr.edu/Panopto/Pages/Home.aspx\">Panopto CourseCast - iSchool only Lecture capture tool</a></li>\n<li>Handouts</li>\n<li>Question Pools</li>\n<li><a href=\"https://www.symbaloo.com/\">Symbaloo</a> - Personal Learning Environment\n<ul>\n<li>Alternative Delicious - <a href=\"https://del.icio.us/\">del.icio.us</a></li>\n</ul>\n</li>\n</ul>\n<h3 id=\"student-evaluation\" tabindex=\"-1\">Student Evaluation <a class=\"header-anchor\" href=\"#student-evaluation\">#</a></h3>\n<ul>\n<li>Pedagogy and not Policing/ Plagiarism.\n<ul>\n<li>Rubrics</li>\n<li>TurnitIn works with Blackboard and can be used as a stand alone tool as well</li>\n</ul>\n</li>\n<li>Google Docs/Blackboard</li>\n<li>Clickers and the Blackboard app\n<ul>\n<li><a href=\"https://answers.syr.edu/pages/viewpage.action?pageId=7111328\">TurningPoint - Student Response System</a></li>\n</ul>\n</li>\n<li><a href=\"https://web.hypothes.is/\">Hypothes.is</a>\n<ul>\n<li>Annotate anything anywhere online and collaboratively</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"student-assessment-by-you\" tabindex=\"-1\">Student Assessment by You <a class=\"header-anchor\" href=\"#student-assessment-by-you\">#</a></h3>\n<ul>\n<li>Comment cards</li>\n<li>Written</li>\n<li>On Blackboard</li>\n<li>Mid-semester evaluations</li>\n<li>Write your own questions</li>\n<li>Create an online pool</li>\n<li>Office hour progress meeting</li>\n<li>Orange Success</li>\n</ul>\n<h3 id=\"student-assessment-of-you\" tabindex=\"-1\">Student Assessment of You <a class=\"header-anchor\" href=\"#student-assessment-of-you\">#</a></h3>\n<ul>\n<li>Comment cards</li>\n<li>Written</li>\n<li>Tweeted</li>\n<li>On Blackboard</li>\n<li>Mid-semester evaluations</li>\n<li>Write your own questions</li>\n<li>Create an online pool</li>\n<li>Office hour progress meeting</li>\n</ul>\n<h3 id=\"graduate-resources\" tabindex=\"-1\">Graduate Resources <a class=\"header-anchor\" href=\"#graduate-resources\">#</a></h3>\n<ul>\n<li><a href=\"https://expresions.syr.edu\">Expressions</a>\n<ul>\n<li>Syracuse University Wordpress</li>\n</ul>\n</li>\n<li>[Google Apps g.syr.edu] (G.syr.edu)\n<ul>\n<li>Syracuse University Google Docs</li>\n</ul>\n</li>\n<li><a href=\"https://collage.syr.edu\">Collage</a>\n<ul>\n<li>SU photo library</li>\n</ul>\n</li>\n<li><a href=\"https://prezi.com\">Prezi</a>\n<ul>\n<li>Powerpoint alternative</li>\n</ul>\n</li>\n<li>Dropbox / Google Drive / <a href=\"https://drive.syr.edu\">SU Drive</a></li>\n<li><a href=\"https://slack.com\">Slack</a>\n<ul>\n<li>chat app</li>\n</ul>\n</li>\n<li><a href=\"https://www.mindmeister.com/\">MindMeister</a>\n<ul>\n<li>Collaborative mind mapping tool. (paid)</li>\n</ul>\n</li>\n<li><a href=\"https://zoom.it\">Zoom.it</a>\n<ul>\n<li>Screen-capture &amp; annotation tool.</li>\n</ul>\n</li>\n<li><a href=\"http://researchguides.library.syr.edu/az.php\">SU Library Databases</a></li>\n<li><a href=\"https://www.merlot.org/merlot/index.htm\">Merlot - Multimedia Educational Resource for Learning and Online Teaching</a></li>\n<li><a href=\"http://doodle.com/\">Doodle</a></li>\n<li><a href=\"http://whenisgood.net/\">When is good</a></li>\n</ul>\n<h3 id=\"graduate-student-resources-stem-edition\" tabindex=\"-1\">Graduate Student Resources - STEM Edition <a class=\"header-anchor\" href=\"#graduate-student-resources-stem-edition\">#</a></h3>\n<ul>\n<li><a href=\"http://pages.uoregon.edu/koch/texshop/\">LaTeX</a></li>\n<li><a href=\"https://its.syr.edu/licenses/\">Mathematica/Matlab</a></li>\n<li><a href=\"http://demonstrations.wolfram.com/\">Wolfram</a></li>\n</ul>\n<h3 id=\"citation-management-tools\" tabindex=\"-1\">Citation Management Tools <a class=\"header-anchor\" href=\"#citation-management-tools\">#</a></h3>\n<ul>\n<li><a href=\"https://zotero.org\">Zotero</a> (free)</li>\n<li><a href=\"https://mendeley.com\">Mendeley</a> (free)</li>\n<li><a href=\"https://endnote.com\">Endnote</a> (expensive)</li>\n<li><a href=\"http://researchguides.library.syr.edu/refworks\">RefWorks - supported by the library.</a></li>\n<li>LaTex</li>\n</ul>\n<h3 id=\"help\" tabindex=\"-1\">Help <a class=\"header-anchor\" href=\"#help\">#</a></h3>\n<ul>\n<li>ITS Help\n<ul>\n<li>help@syr.edu / (315) 443-2677</li>\n<li>Scheduling appointments to see people is the best. Excellent help for blackboard</li>\n<li>Life Sciences/CST Service Center Room 1-227</li>\n</ul>\n</li>\n<li><a href=\"http://ols.syr.edu/\">Online Learning Services</a>\n<ul>\n<li>Blackboard, Adobe Connect, TurningPoint, Expressions, Turnitin, Ensemble, Social Media</li>\n<li><a href=\"http://graduateschool.syr.edu/wp-content/uploads/2015/05/Blackboard-for-TAs-instructions-72613.pdf\">Blackboard for Teaching Assistants PDF</a></li>\n</ul>\n</li>\n<li><a href=\"http://graduateschool.syr.edu/\">The Graduate School</a></li>\n<li><a href=\"http://disabilityservices.syr.edu/\">Office of Disability Services. ODS</a></li>\n<li><a href=\"http://sudcc.syr.edu/\">Disability Cultural Center</a></li>\n<li><a href=\"https://library.syr.edu/staff/subjects.php\">Subject Area Librarians</a></li>\n</ul>\n<h4 id=\"image-credit\" tabindex=\"-1\">image credit <a class=\"header-anchor\" href=\"#image-credit\">#</a></h4>\n<p><a href=\"https://pixabay.com/en/technology-classroom-education-1095751/\">LTDSupport</a></p>\n",
			"date_published": "2017-08-16T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/wocati/",
			"url": "https://www.adamdjbrett.com/wocati/",
			"title": "WOCATI",
			"content_html": "<p>I have been part of WOCATI since 2008, when Prof. Dr. Namsoon Kang asked me to serve as the Web Administrator for the organization.\nIn this capacity I have been part of several major projects for WOCATI.</p>\n<ul>\n<li>Including the WOCATI Executive Committee Meeting held on March 17-20, 2009 held at Princeton Theological Seminary, Princeton, New Jersey 08540.</li>\n<li>Several revisions of the website and shifts in hosts and platforms</li>\n<li>Type-setting, copy editing, layout, and design of the WOCATI book <a href=\"https:///wocati.org/work/challenges-promises-quality-assurance-theological-education/\"><em>Challenges and Promises of Quality Assurance in Theological Education</em></a>.</li>\n</ul>\n<h2 id=\"the-world-conference-of-associations-of-theological-institutions-wocati\" tabindex=\"-1\">The World Conference of Associations of Theological Institutions (WOCATI) <a class=\"header-anchor\" href=\"#the-world-conference-of-associations-of-theological-institutions-wocati\">#</a></h2>\n<h2 id=\"wocati-book-cover\" tabindex=\"-1\">WOCATI Book Cover <a class=\"header-anchor\" href=\"#wocati-book-cover\">#</a></h2>\n<p><img src=\"/assets/img/misc/wocati-cover.webp\" alt=\"WOCAT Book Cover\" title=\"WOCATI Book Cover\"></p>\n<h2 id=\"wocati-website-evolution\" tabindex=\"-1\">WOCATI website evolution <a class=\"header-anchor\" href=\"#wocati-website-evolution\">#</a></h2>\n<p>WOCATI started out as raw HTML and iFrames before moving onto typo3 hosted by the <a href=\"https:///oikoumene.org\">World Council of Churches</a> before moving onto WordPress with a custom theme. Presently WOCATI's website is running on the static site generator Jekyll and is hosted on Github. Transitioning to Jekyll + Github allows for WOCATI's website to be fast and responsive for its global audience.</p>\n<h2 id=\"programming-languages\" tabindex=\"-1\">Programming languages <a class=\"header-anchor\" href=\"#programming-languages\">#</a></h2>\n<ul>\n<li>HTML</li>\n<li>CSS</li>\n<li>Javascript</li>\n<li>schema.org</li>\n</ul>\n<h2 id=\"other-elements\" tabindex=\"-1\">other elements <a class=\"header-anchor\" href=\"#other-elements\">#</a></h2>\n<ul>\n<li>responsive design</li>\n<li>Jekyll + Github</li>\n<li>google analytics</li>\n<li>google search console</li>\n<li>vertical social media integration</li>\n</ul>\n",
			"date_published": "2016-10-24T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2016-10-24-stephanie-wyatt/",
			"url": "https://www.adamdjbrett.com/blog/2016-10-24-stephanie-wyatt/",
			"title": "Stephanie M. Wyatt",
			"content_html": "<p>Stephanie M. Wyatt earned her PhD in Hebrew Bible (Old Testament) from Brite Divinity School at Texas Christian University.</p>\n<p>Her dissertation is <em>Widows in the Memories of Biblical Israel</em>. She is an ordained Baptist ministry who loves biblical interpretation, Christian education, pastoral care and ministry, social justice, and living sustainably.</p>\n<h2 id=\"stephanie-m-wyatt\" tabindex=\"-1\"><a href=\"http://stephaniewyatt.net\">Stephanie M. Wyatt</a> <a class=\"header-anchor\" href=\"#stephanie-m-wyatt\">#</a></h2>\n<p>I helped Stephanie develop a website that highlights her work as a teacher-scholar, minister, and community builder.</p>\n<h3 id=\"programming-languages\" tabindex=\"-1\">Programming languages <a class=\"header-anchor\" href=\"#programming-languages\">#</a></h3>\n<ul>\n<li>HTML</li>\n<li>CSS</li>\n<li>Javascript</li>\n<li>Jekyll + Github</li>\n</ul>\n<h3 id=\"other-elements\" tabindex=\"-1\">Other elements <a class=\"header-anchor\" href=\"#other-elements\">#</a></h3>\n<ul>\n<li>Full responsive website</li>\n<li>Wordpress</li>\n<li>Wordpress plugins</li>\n<li>google apps integration for mail.</li>\n<li>CDN using Amazon Cloudfront and S3</li>\n<li>integrated social media</li>\n<li>google analytics</li>\n<li>google search console</li>\n</ul>\n",
			"date_published": "2016-10-24T00:00:00Z"
		}
		,
		{
			"id": "https://www.adamdjbrett.com/blog/2016-10-24-warner/",
			"url": "https://www.adamdjbrett.com/blog/2016-10-24-warner/",
			"title": "Warner Southern College",
			"content_html": "<p>My work at Warner Southern College.</p>\n<h2 id=\"warner-university-formerly-warner-southern-college\" tabindex=\"-1\">Warner University formerly Warner Southern College <a class=\"header-anchor\" href=\"#warner-university-formerly-warner-southern-college\">#</a></h2>\n<p><a href=\"http://warner.edu/\">Warner University</a> is a evangelical Christian College located in Lake Wales, Florida. I attended Warner from 2002-2006. During this time I double majored in History and Biblical Studies while also working several on campus jobs, until I eventually became the Web Administrator for the college.\nAs the web admin I my responsibilities were to oversee and maintain the website and to assist in transitioning the website from multiple servers some IIS running ASP and ASP.net and others a php based LAMP server.</p>\n<h3 id=\"projects\" tabindex=\"-1\">Projects <a class=\"header-anchor\" href=\"#projects\">#</a></h3>\n<ul>\n<li>Consolidation of webpages to a single server</li>\n<li>Creating a streamlined unified ASP/HTML/CSS style and structure.</li>\n<li>develop an HTML/CSS online catalog and ebook reader for the library</li>\n<li>assisting the library in updating the card catalog and student ID system</li>\n<li>assisting the athletics department</li>\n<li>assisting with rolling out Active Directory to a network of five-hundred and thirty-eight system</li>\n<li>Assisting in transitioning online education to the <em>Moodle</em> Learning Management System running on WAMP servers.</li>\n</ul>\n<figure>\n\t<a href=\"/assets/img/websites/wsc-original.webp\"><img src=\"/assets/img/websites/wsc-761x440.webp\" alt=\"Warner University website screenshot\"></a>\n\t<figcaption>Warner University/Warner Southern College.</figcaption>\n</figure>\n<h3 id=\"programming-languages\" tabindex=\"-1\">Programming languages <a class=\"header-anchor\" href=\"#programming-languages\">#</a></h3>\n<ul>\n<li>ASP/ASP.net</li>\n<li>HTML</li>\n<li>CSS</li>\n<li>Javascript</li>\n</ul>\n<h3 id=\"other-technical-elements\" tabindex=\"-1\">other technical elements <a class=\"header-anchor\" href=\"#other-technical-elements\">#</a></h3>\n<ul>\n<li>google analytics</li>\n<li>google search console</li>\n<li>google search gadget integration</li>\n<li>search engine optimization</li>\n<li>working in LAMP and WAMP environments</li>\n</ul>\n",
			"date_published": "2016-10-20T00:00:00Z"
		}
		
	]
}