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

Publishing Dense Technical Work Without Watering It Down

3rd article in Building My Portfolio Into a Publishing System
Software Writing Notebooks Gatsby Project Solutions Land
2020-1-12

At some point I realized that plain markdown was not visually or structurally distinct enough for the kind of work I wanted to publish.

Expanded the site into a denser technical publishing tool with notebook embedding, richer article framing, and better support for project artifacts that did not fit clean blog-post shapes.

A lot of my projects are not just “here is the final result.” They involve experiments, code, notebooks, logs, hardware iterations, and notes that make more sense when they are preserved as part of the article instead of flattened into a clean summary.

That was the problem this phase was trying to solve.

The goal was not more content. It was denser content.

Around early 2020, the repo starts leaning hard into technical project writeups:

  • Embedding jupyter notebooks rather than creating pages
  • New camera mount post, task-digest work
  • Publishing task digest
  • Publishing first hanging plotter articlers and docker strace
  • Updating esp article
  • Describing spinning up a stepper
  • Connecting esp32 to bluetooth post
  • Upgrading deps, reorg generated types
  • Adding remark42 commenting system from fork

That is not just “more posts.” It is the repo bending toward technical publishing.

At the time I was also working on a headless CMS, which had me thinking more about algorithmic handling of content instead of pure 1:1 writing and display. I did not want the site to be a dumb markdown renderer.

Getting notebooks to work was a real milestone

The turning point in this phase was getting Jupyter notebooks embedded in markdown.

That mattered a lot to me because it changed the relationship I had with Gatsby. Up until then, a lot of the content pipeline felt like something I was negotiating with. Once notebooks worked the way I wanted, it felt more like Gatsby was under my control instead of me being under Gatsby’s control.

The relevant plugin code is refreshingly blunt:

const JUPYTER_REGEX = /^{% jupyter (.*) %}$/

visit(markdownAST, "text", (node) => {
  const match = JUPYTER_REGEX.exec(node.value)
  if (match) {
    markdownJupyterNodes.push({ node, jupyterPath: match[1] })
  }
})

and then:

const children = jupyterFileNode.children
  .map(getNode)
  .filter((node) => node.internal.type === "JupyterNotebook")

if (children.length < 1) {
  return `Error: notebook not found for file ${jupyterPath}, is gatsby-transformer-ipynb installed?`
}

return jupyterNode.html

That is from plugins/gatsby-remark-jupyter/index.js.

There is a lot I like about this pattern. It is not magical. It is just: find the notebook reference, resolve the local file, get the transformed notebook node, and replace the marker with generated HTML.

In practice, the setup was: keep the notebook file beside the article assets, let the transformer generate the notebook HTML during Gatsby’s data pipeline, and then let the remark plugin swap a lightweight inline marker for the rendered notebook output at markdown-processing time.

Why embed notebooks inside markdown instead of making them their own pages?

Because I wanted more control over the chrome around them.

When notebooks were their own pages, I had less control over how they were framed. Embedding them in markdown let me preface them, contextualize them, and treat them as part of a larger article instead of a separate artifact awkwardly hanging off the side.

A typical rendered result was an article section that introduced the experiment in prose, embedded the notebook output directly underneath, and then resumed with conclusions or next steps. That made the notebook feel like evidence inside the story instead of a detached appendix.

That is an important distinction. I was not trying to show that I could technically render a notebook. I was trying to make notebooks useful inside a narrative.

Gatsby plugin work was annoying in exactly the way you would expect

This phase also includes a lot of plugin frustration.

Gatsby obscures the workflow behind several layers of indirection. Determining what inputs are available for a page, which transforms have already happened, and where types should come from is harder than it should be.

The plugin ecosystem made this worse. Small plugins would bit-rot, dependencies would drift, and debugging often meant spelunking through a chain of packages maintained at different levels of seriousness.

One of the most revealing external references from this phase is a Gatsby PR I had to care about directly:

  • gatsbyjs/gatsby#20586

That is not the whole notebook story, but it captures the broader pattern: sometimes the thing that is broken is not even your plugin. It is upstream Gatsby itself, or some transitive dependency interaction around it. In this case, the PR mattered because it was part of making notebook rendering behave again on a newer Gatsby stack instead of quietly rotting behind plugin boundaries.

I upstreamed the Gatsby change when it made sense. I did not always upstream plugin changes, mostly because a lot of those plugins had so little traffic that maintaining a private or vendored path was more practical than waiting around.

Comments were part of the same philosophy

The comment-system work belongs in this phase for the same reason notebooks do: I wanted more useful technical publishing behavior without handing the whole experience over to a provider.

That is the connecting thread for the whole article: notebooks, plugin work, and comments were all attempts to make the site better at carrying live technical material instead of just polished summaries.

Later in 2020 I added Remark42, based in part on a simple Gatsby integration pattern inspired by posts like this one:

  • Adding Commento to React apps like Gatsby

I chose Remark42 because it was minimal and self-hostable. The integration logic was simple enough that I could just add it directly instead of depending on a bloated abstraction layer. That fit the rest of the repo pretty well.

I do not love systems that are “easy” only as long as somebody else keeps the SaaS alive.

What this phase changed

This was the point where the site became capable of carrying work that was messy, technical, and still in touch with its original artifacts.

That includes things like:

  • notebook-backed explanations
  • richer code block handling
  • hardware/software project logs
  • longer project sequences like the hanging plotter work
  • comments without surrendering the whole discussion layer to a hosted product

It also clarified one of my broader preferences: I care a lot about preserving the shape of the work.

I do not just want a polished summary. I want to keep enough of the notebook, experiment, code, and debugging trail that the project still feels real.

Result

By the end of this phase, the repo was no longer just a custom site with a content model.

It was becoming a publishing environment for technical artifacts.

That is a more specific and more demanding job.

It also made the next set of problems inevitable. Once you depend on notebooks, transforms, comments, and a stack of plugins to publish dense work, dependency drift stops being background maintenance and starts becoming an existential threat to whether the site builds at all.

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