AboutCapabilitiesPortfolioExplore
Projects
Building My Portfolio Into a Publishing System
From Static Site to Publishing System
Inventing a Content Model for Real Projects
Publishing Dense Technical Work Without Watering It Down
Owning the Seams: Plugin Forks and Toolchain Drift
Turning the Site into a Portfolio Editorial Machine
LLM Tooling for Portfolio Writing
The benefits of trad-coding

Owning the Seams: Plugin Forks and Toolchain Drift

4th article in Building My Portfolio Into a Publishing System
Software Maintenance Gatsby Dependencies Project Solutions Land
2021-4-30

The least glamorous part of this repo is probably the most representative part.

Recovered the site from toolchain drift by pinning dependencies, vendoring unstable pieces, and treating maintenance work as part of the product instead of background cleanup.

This article is a retrospective written later, but it centers on the maintenance phase that started in 2021 and continued through later cleanup and vendoring work.

The big recurring problem was not inventing a clever layout or writing a nice article. It was keeping a custom publishing stack alive while Gatsby, React, plugins, and transitive dependencies all moved at different speeds.

This is where the repo history gets extremely honest.

The build rotted out from under me

The blunt version of this maintenance era is simple: I came back and I could no longer build my site.

That shows up in two of the best commit messages in the repo:

  • May 2021 — Big ole code rot fightoff
  • April 2024 — Clear out 3 years of tech debt

Those are not exaggerated.

I had updated packages to current versions and immediately found myself in a long dependency repair effort. Notebook rendering was especially frustrating. Gatsby internals had moved, plugin APIs had shifted around, and smaller dependencies had not kept pace.

This is the part of software work that tends to disappear in polished case studies. In reality there was a lot of ugly in-between work with local checkouts, yarn link, hacked dependency versions, and debugging repos in place before I committed a working state.

The git history mostly catches the moment after I had already crawled out of the hole.

Why I did not rewrite

This was the phase where it would have been easy to tell myself a dramatic story about starting fresh.

I decided pretty explicitly not to do that.

I did not want to fall into the rewrite fallacy.

That mattered because the repo already contained a lot of hard-won publishing behavior. Rewriting into some new framework might have felt emotionally cleaner, but it would also have thrown away a lot of accumulated domain-specific knowledge.

So instead I kept the repo and moved the integration problems closer.

The dependency evidence is right there in package.json

The clearest example is the notebook stack getting pinned to GitHub commits during repair work.

From the notes around that May 2021 recovery work:

"@gatsby-contrib/gatsby-transformer-ipynb": "https://github.com/sdobz/gatsby-transformer-ipynb#f2a60fd",
"@nteract/notebook-render": "https://github.com/sdobz/notebook-render#ec5a226"

and then in resolutions:

"@gatsby-contrib/gatsby-transformer-ipynb/@nteract/notebook-render": "https://github.com/sdobz/notebook-render#ec5a226"

That is not elegant, but it is very real.

There is also upstream evidence for why this happened:

  • gatsby-transformer-ipynb Gatsby v3 update comparison
  • gatsbyjs/gatsby#20586

The main thing I want to emphasize here is that maintenance pain was not coming from one dramatic failure. It was coming from relationships between packages.

That is why I say complexity is the number of relationships. A lot of these fights were not about huge codebases. They were about too many little pieces needing to agree at once.

Vendoring was not a detour. It was the practical path.

As the repo got older, I got less interested in maintaining elegant distance from upstream and more interested in getting the site back under control.

That is how local plugins and vendored code became a normal part of the architecture.

By the later phases the repo includes things like:

  • plugins/gatsby-plugin-matomo
  • plugins/gatsby-plugin-prefetch-google-fonts
  • plugins/gatsby-remark-jupyter
  • plugins/gatsby-remark-obsidian
  • plugins/presentational-components

Each one has its own reason.

Some were vendored because upstream was frustrating to manage. Some because I wanted small logic changes. Some because I kept needing updates and did not want the overhead of a separate fork. Some because the original behavior simply did not match my workflow.

A good later example is presentational-components.

  • upstream package: @nteract/presentational-components
  • initial vendoring pass in October 2025 — Vendoring presentational-components
  • repair pass right after that — Fix presentational-components

The root problem there was pretty practical: I needed a newer React for Gatsby, and the upstream package depended on an older React. I did not want to fork a large monorepo just to make a relatively mechanical compatibility update.

So I extracted the part I needed, committed a pristine vendored copy first, and then modified it locally.

That workflow matters to me:

  1. vendor the original cleanly
  2. commit that state
  3. make local fixes in a follow-up commit

That gives me a clean diff of what I changed. If I get lost, I can back out my patch without losing the imported baseline. If I later decide to upstream something, I can see exactly what the patch is.

It is not glamorous, but it is sane.

Obsidian support is another example of owning the seam

plugins/gatsby-remark-obsidian/index.js is a good example of the kind of customization I eventually wanted to own directly.

For example, this bit resolves wiki-style image embeds by filename:

node.value.matchAll(obsidianReference).forEach(([full, filename, label]) => {
  const isEmbed = full.startsWith("!")
  const file = filesByBase[filename]
  if (!file) {
    reporter.warn(`${full}: ${file} not found`)
    return
  }
  // ...resolve relative path and insert an image node...
})

The practical goal was simple: support embeds like this in markdown:

![[image.jpg]]

I wanted those embeds to resolve through Gatsby file nodes using a simple filename map instead of forcing path-heavy references everywhere. That makes content more resilient to reorganizations.

That is the kind of feature that sounds tiny until you notice how much smoother it makes authoring.

Toolchain drift also changed my emotional relationship to the repo

There is a personal cost here that the code does not show very well.

After the code-rot fightoff I had very little energy left to add new content. I was burned out from repair work.

That is worth saying because maintenance is not just technical. It affects whether the project still feels inviting.

If every return to the repo starts with dependency archaeology, the repo stops feeling like a writing tool and starts feeling like a chores folder.

A lot of the later work was shaped by not wanting to repeat that experience.

I was not especially disciplined about proactive drift detection during the worst of this. If I were formalizing it now, I would add regular build checks and dependency audits so breakage gets caught while it is still small instead of after a long gap.

Result

This phase taught me something I still believe pretty strongly: if a system matters to your workflow, you eventually need to own the seams.

Not every seam. That way lies madness.

But the important seams? Yes.

If your publishing stack depends on plugins that drift, nested package relationships that break quietly, or ecosystem corners that nobody is maintaining with your exact use case in mind, the practical move is often to pull the critical pieces closer until the system becomes debuggable again.

That is not as shiny as a rewrite. It is usually more useful.

Previous Next
Related Building My Portfolio Into a Publishing System:
From Static Site to Publishing System Inventing a Content Model for Real Projects Publishing Dense Technical Work Without Watering It Down Owning the Seams: Plugin Forks and Toolchain Drift Turning the Site into a Portfolio Editorial Machine
Featured Work
Welding PositionerSurface Grinder Retrofit
Company Info
About UsContactAffiliate DisclosurePrivacy Policy
Specific Solutions LLC
Portland, OR