Skip to main content
Nora Codes

Infrastructure Photography Manifesto (and Decker-in-HTML)

Leonora Tindall 2025/11/08

Hey look, I made a zine in Decker! You can read it right here, or download the deck file.

And now for the nerd shit. Decker is really cool. It carries on the legacy of HyperCard, one of the first real hypertext media systems; it’s got that dithered, lo-fi, retro flair that I adore; and it runs in a lot of places - anywhere with SDL, and anywhere with a full-fledged browser.

I made a zine with it a while back, but I didn’t publish it, or make anything else with it, because I didn’t realize that it was possible to publish Decker decks without the Decker UI. (You can do this by going to File -> Properties -> Protect…, which doesn’t add DRM but rather just emits a Decker deck that has the UI turned off. It can still be opened in Decker and edited.)

There was still the problem, though, that you can only really export a full-page HTML document with a single Decker canvas in the middle of it, and only at 2x scale. This is normally really good, but I’m a weirdo and wanted Decker embedded on my website. Several folks were happy to tell me that this could be done with an iframe, but I had a hunch that I could produce a better experience with a straight-in embed of the Decker canvas. And, well:

This page, in my Hugo setup, includes two shortcodes like this:

<script language="decker">
{{< include "static/code/decks/infrastructure exp04.deck" >}}
</script>

{{< decker >}}

That first shortcode, include, is very simple:

{{ .Get 0 | readFile | safeHTML }}

The second, decker, looks like this:

<a id="target" style="display:none"></a>
<img id="loader" style="display:none">
<input id="source" type="file" style="display:none">
<canvas id="render" style="display:none"></canvas>
<canvas id="lrender" style="display:none"></canvas>
<canvas id="rrender" style="display:none"></canvas>
<canvas width="0" height="0" id="ltools"></canvas>
<div class="decker-container">
    <canvas class="decker-display" id="display"></canvas>
</div>
<canvas width="0" height="0" id="rtools"></canvas>

<script src="/code/decker-itself/lil.js"> </script>
<script src="/code/decker-itself/decker.js"> </script>

This is almost verbatim from the Decker-web HTML file (as of v1.60+8360e66), with a few modifications:

  <canvas width="0" height="0" id="ltools"></canvas>
+ <div class="decker-container">
- <canvas class="decker-display" id="display"></canvas>
+   <canvas class="decker-display" id="display"></canvas>
+ </div>
  <canvas width="0" height="0" id="rtools"></canvas>

+ <script src="/code/decker-itself/lil.js"> </script>
+ <script src="/code/decker-itself/decker.js"> </script>

Those two scripts are also copied verbatim from the repo, at commit 8360e66.

I used a small CSS snippet to change the size and position of the Decker display canvas:

div.decker-container {
  display: flex;
  align-items: center;
}

canvas.decker-display {
  width: 512;
  height: 324;
  margin-left: auto;
  margin-right: auto;
  cursor: default;
}

Some issues remain. Namely:

That’s expected, but there are some straight-up bugs I ran into during this process, too:

If folks have advice on how to fix it, or if we could get an embed-into-page export format for Decker, that’d be great!

Huge thanks to Millie Millennium for inspiring me to get back into Decker, and for giving me helpful info on this particular silly quest.