Skip to content

feat(ctr): Dynamically generate spritesheets#288

Merged
ashquarky merged 20 commits intodevfrom
work/sprites
Jan 19, 2026
Merged

feat(ctr): Dynamically generate spritesheets#288
ashquarky merged 20 commits intodevfrom
work/sprites

Conversation

@ashquarky
Copy link
Member

Resolves #XXX

Changes:

The old Juxt spritesheet system had a lot of up/down scaling of the sprites, background positioning mixed with normal styling, and other things that made it very hard to adjust any layouts involving sprites at all. This PR:

  • Resamples each sprite according to the actual resolution it's rendered at on hardware
  • Adds a script using the spritesmith library to create the sheet and suitable CSS on the fly
  • Ports all pages using sprites to this new CSS stylesheet

Every effort was kept to keep the same layout (or slightly improve it) but like anything that touches Juxt's stylesheets, a bit of shifting around is kinda inevitable. Something something redesign something something new markup.

@ashquarky ashquarky requested a review from mrjvs January 10, 2026 12:18
Copy link
Contributor

@mrjvs mrjvs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, I'll give it a test when I next have a chance (wednesday probably)

An idea, have you considered making the spritesmith script an esbuild plugin?
It would make it so you don't have to run it manually, then we can also add the output files to the ignore.

It doesn't have to be complicated, you can hook into onEnd to just run the script you already have:

import fs from "fs/promises";
import path from "path";

const myPlugin = {
  name: "my-plugin",
  setup(build) {
    build.onEnd(async result => {
      if (result.errors.length > 0) return;

      const outdir = build.initialOptions.outdir;
      if (!outdir) return;

      const filePath = path.join(outdir, "my-file.js");
      await fs.writeFile(filePath, 'hello-world');
    });
  },
};

@ashquarky
Copy link
Member Author

My only concern with making it a build plugin is that anything we do with #266 needs to be automated in the build process rather than in the repo, since the spritesheet image itself is generated dynamically. The 3DS especially benefits from image optimisation.
Keeping it in the repo is more messy, but means we only have to re-run optimisations when something actually changes on the spritesheet.
Not sure if @lumiscosity and @suprstarrd have opinions here. oxipng is just, a command we can run, right? I could see about adding that to the build too...

@lumiscosity
Copy link
Contributor

lumiscosity commented Jan 12, 2026

yup, pure oxipng should work. the sheet is fairly small and you only update it on changes as you said so zopfli is fair game. the other programs i've mentioned are nice to have but getting them in a raw linux env is nowhere as easy as oxipng and downloading questionably licensed binaries from random forums isn't exactly a good idea for reproducibility :p

@suprstarrd
Copy link
Contributor

^ agree!

@ashquarky
Copy link
Member Author

Oki. I can try to add a build step for this, at least for stuff that passes through ESBuild.

@ashquarky
Copy link
Member Author

If curious, here's the results of the new oxipng plugin against just the CTR assets:

SMTH: wrote 24 sprites
OXI tab.png: 124b -> 124b
OXI background.png: 437b -> 175b
OXI headline-green.png: 563b -> 556b
OXI header.png: 3592b -> 3592b
OXI headline.png: 581b -> 574b
OXI sprites.png: 14710b -> 6696b

Not bad!

@ashquarky ashquarky requested a review from mrjvs January 13, 2026 03:07
Copy link
Contributor

@mrjvs mrjvs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've tested everything and it looks good. Should be ready to merge after fixing the one tooling bug.

Copy link
Contributor

@mrjvs mrjvs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The nodemon reload works now. So it's good to merge!

@ashquarky ashquarky merged commit 262b310 into dev Jan 19, 2026
10 checks passed
@ashquarky ashquarky deleted the work/sprites branch January 19, 2026 02:42
@mrjvs mrjvs mentioned this pull request Jan 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants