ADAM DJ BRETT

Home / Blog / A Summer of Plumbing: JCRT, KC Works, and the Build Awesome Builds

I keep trying and failing to code, write and learn in public but after doing the development, I'm often too tired to do the write-up so future Adam, this essay is for you. Most of my summer went into work nobody sees. The Journal for Cultural and Religious Theory looks about the same as it did in June. Under the hood, almost everything about how it gets built, deposited, and served has changed.

Three threads ran at once: getting the whole JCRT archive into KC Works with real DOIs, fixing and speeding up the BuildAwesome Eleventy builds across my sites, and a long day this week spent making jcrt.org load fast on a phone and build clean on a laptop. I'll take them in that order.

829 articles, 829 DOIs #

JCRT has published online since 1999, and for most of that time its articles had no persistent identifiers. If you cited a JCRT piece, you cited a URL and hoped we kept it stable (we did and do). As of this summer that is no longer true. On August 30 the last numbered issue landed in KC Works, the Knowledge Commons repository: 67 issue collections, 829 records, and 829 DOIs on the 10.17613 prefix, minted through DataCite. Every one of those DOIs is now written back into the article's front matter on jcrt.org, so the site, the PDF, and the repository record all point at each other.

A few things I learned depositing at that scale, in case you ever do it:

  • KC Works calls a collection a "collection" in the interface and a "community" in every API path. It runs on InvenioRDM, and the InvenioRDM docs cover everything under the surface.
  • A published record locks its file bucket. You cannot swap a PDF on a published record. You publish a new version instead, which mints a new version DOI while the parent DOI keeps resolving to the latest. Get the file right the first time.
  • The import API only creates. Re-import an identifier and you get a 409. Deleted collection slugs cannot be reused either.
  • The profile image for a collection has to be 800 by 800 at 72 DPI, under a megabyte, with no alpha channel. I lost more time to that than I want to admit.

The mapping itself was the fun part: Family, Given creators with affiliations, the journal custom fields (volume, issue, pages, ISSN), rights, and a URL identifier that points at the PDF on files.jcrt.org rather than the landing page. I wrote the conventions down as I settled them, because I will need them again for the next issue.

Alongside the DOIs, every content page on jcrt.org now carries a short stable id in its front matter. A pre-commit hook assigns one to any new page before it can be committed, and the build refuses to run if one is missing or duplicated. Those ids are what let the KC Works records, the sitemaps, and the Standard.site documents on AT Protocol all agree about which article is which.

Fixing the Build Awesome builds #

All of my sites run on the Eleventy 4 alpha, which is being renamed Build Awesome. The alpha is good. It is also an alpha, and I hit most of the sharp edges this summer.

The one that cost me the most was on adamdjbrett.com, this site. A fresh npm install had been failing for weeks with an error about linkify-it not providing a default export, while cached builds on Netlify kept passing, so nobody saw it. The cause was a single line in package.json: an overrides entry pinning linkify-it to 6.x. Overrides apply to the whole dependency tree, and markdown-it needs 5.x. Removing the override fixed the install. While I was in there I declared two packages the config imported but never listed, and removed four it never used.

The second trap is worth knowing if you use the alpha: npm install @awesome.me/buildawesome will downgrade your site. The latest tag on that package points at a 0.0.1 placeholder. The real releases are the 4.0.0-alpha line, and you have to pin one exactly.

The third was on thenewpolis.com, where builds had crept up to sixty seconds. The culprit was Nunjucks' built-in trim filter, which uses a regular expression that goes quadratic on large strings with lots of whitespace, and the firehose feed was trimming the full HTML of every post. Overriding trim with native String.trim() brought the build to three and a half seconds. Same content, same output, one filter.

Smaller alpha notes, so I do not have to relearn them: the slug filter is gone (use slugify), Nunjucks namespace assignment inside set can fail to compile, and eleventyImport belongs only on templates that consume a collection, never on its members, or the collection silently comes back empty.

One long day on jcrt.org #

This week I ran out of GitHub Actions and Netlify credits, which turned out to be useful. Everything had to be proven on my laptop before it could ship, so I spent a day with Claude Code working through a mobile-speed handoff and then kept going.

The site had already dropped Font Awesome for an inline SVG sprite, but the sprite was missing eight icons that author pages referenced, so those rendered as nothing. The sprite is now drawn from Phosphor Icons, with the ORCID iD from Academicons, and the symbol ids stayed the same so none of the 650 content files that name an icon had to change. Body text moved to a Palatino system stack, headings kept Rockwell, nothing is downloaded, and there is now a credits page that says all of this.

The sidebar was the part I had been putting off. It is the Editorial layout from HTML5 UP, and on phones it flashed on every page load (and there was still gasp jquery). Three things were wrong: the hamburger was not positioned until the main stylesheet arrived, the sidebar animated every state change, and a "resize guard" I had added that morning fired on every scroll because the address bar collapsing counts as a resize. All three are gone. The sidebar now paints in its final position from the inline critical CSS, never slides, and on desktop remembers whether you left it open for the life of the tab. It also gained the dropdown submenus from the Ghost version of Editorial, with a Phosphor chevron and a nested list under About.

The bug I did not expect was the sidebar width. It was declared in em, and the hamburger button resolved that same value against its own larger font size, so with the menu open the button sat three hundred pixels too far right, over the page title. It had been that way before any of this week's work touched the sidebar. Declaring the widths in pixels at the sizes they were already rendering fixed it without moving anything else.

Then came the scripts. I asked a swarm of local agents (Qwen 3.8 and Gemmma4) to study the twenty scripts around the build with two rules, You Aint Gonna Need It (YAGNI) and Don't Repeat Yourself (DRY), and the report was humbling. They caught several errors I had made thanks to the ponytail.dev skill. The production build was failing. A post I had saved through the CMS carried a field the CMS config did not declare, and the check that catches exactly that had been left out of a second copy of the build chain I used locally, so it looked green. The same twelve-line front-matter parser existed twelve times. The sitemap checker validated, I was so proud of, 21 URLs out of 8,666. The OAI-PMH feed stamped every build with the current time, so git status was never clean.

Most of that is fixed and waiting to be pushed: one build registry, one shared library that fifteen files import, a checker that walks every sitemap in a tenth of a second, tests that run first, deterministic output so two builds are byte-identical. The build went from red to green in seventeen seconds, and the repo is five hundred lines lighter. The Sequoia stager that feeds Standard.site had been staging 205 articles with empty titles because of a hand-rolled YAML reader. The next publish will correct them.

What I would tell you #

Two lessons. The first is that the boring infrastructure is what makes the scholarship usable. DOIs, stable ids, harvestable metadata, and a build that fails when something is wrong are what let a twenty-seven-year-old open access journal be cited and found. The second is that running out of credits forced me to do a detailed audit of my code. When you cannot deploy, you have to prove it, and proving it found bugs that deploying had been hiding.

If you run an Eleventy site on the alpha and any of the above sounds familiar, than I say "Courage Willow, Courage."


Disclosures #

Grammarly was used for spelling, grammar, and syntax fixes.

Tags : jcrt eleventy web-development open-access digital-humanities knowledge-commons

Webmentions

No webmentions yet.

Previous

A Cable of Many Fibers: An Overview of Pragmatism for Graduate Students in the Humanities and Social Sciences

An accessible graduate-level overview of pragmatism's major thinkers, contested lineages, theories of truth and inquiry, and uses for humanities and social-science research.