Amy Pillow UP | HOME chaos.social Fedi | Atom Feed

Maintenance thoughts

Alright, one more vintage article has been resurrected from my old blog: my sass-powered layout engine packages. It actually has already been listed in the index on my blog for who knows how long, but it led to a 404 until now :[

While restoring this blog post, I decided to move these node packages away from my old github to my new namespace at codeberg.org/strawburster. However, NPM as a package registry has become more cumbersome to deal with. My understanding now is that automation tokens, used to publish packages from 'continuous integration/deployment' pipelines, now need to be rotated at least every 90 days, which is just untenable for a package I update maybe twice a year. This, of course, can be avoided by using one of many trusted options NPM provides for continuous deployment, including and limited to: Github.

On top of that, new accounts need to be configured with 'passkeys' to even access those tokens, which are a huge pain for people not in the google-sphere. I briefly tried to manage an NPM namespace entirely from my phone's chrome browser, but found some self respect eventually and switched to using codeberg's package registry, which has gone relatively smoothly1. All the packages here have nearly identical continuous testing and delivery workflows in the .forgejo/workflows folder if you are curious.

In the process of transferring the projects over to codeberg, I spent a little time maintaining and upgrading each. Despite no outstanding issues or bugs that I knew about, the development tooling, which is not installed by end users, had known security flaws come up which needed to be updated, and in some cases API changes that I needed to adopt.

However, looking closer at the json2scss-map-webpack-importer package, I realized it was not designed very well, by me, in my opinion. The point of the package is to allow importing json files into sass files, but the name also implies that it relies on or extends webpack functionality, but in fact it was closely tied to an old, deprecated implementation of the sass compiler. I don't know if this was a misunderstanding on my part, or maybe the name stuck after the implementation started to rely on sass.

Either way, I decided to create an entirely new package, @strawburster/sass-json-loader, which does not rely on the sass compiler, it instead provides a new loader that will transform the source code as part of a pipeline which will continue to the sass-loader and maybe others on its way to becoming a css asset. The decoupling here should allow this package to go longer without maintenance.

I've done even more to decouple the other packages listed in the blog post, @strawburster/switch and @strawburster/router, from their pretty extensive dev tooling, which have a faster software lifecycle and fewer guarantees about their interfaces or vulnerabilities.

If you've caught on a theme yet, it's probably my prioritization of maintainability. I've tried to design packages that don't do anything more or less than what's in the readme, and depend only on interfaces which are widely used and unlikely to change, with no third party libraries directly relied upon. These three packages, despite a thick layer of dust accumulating on them, received no vulnerability reports. Installing the dev tooling did come with some vulnerability warnings, but inside a container, the tests and linter still ran fine. I was able to fix the audit reports by upgrading the dependencies (with eslint causing the most headaches2)

Since late high school, I've dealt with clinical levels of depression and anxiety. Part of dealing with that is acknowledging that the most accurate indicator of whether someone will have a depressive episode is how many episodes they've already had. Doing the best I can to prepare for these spells reduces my anxiety. I don't think any of these node packages are mission critical, or even widely used, but this thought goes into every piece of code I write, and every server I provision: can I maintain it in the future? Can someone else maintain it if necessary?

Depression also causes me immense levels of self-doubt. In maintaining these packages, I found myself at first even scared to open the source files directly. I fixed the dependency vulnerabilities, which I unfortunately have too much experience with, and then I relied on the newer versions of the compiler and linter I installed to suggest some changes, without really putting any thought into them.

I sometimes think to myself: what if I tried to look too deeply at the source code and realize I don't understand it anymore? I know I wrote every line at some point3, but that was a different person, a whole person. How can I, a depressed shell of a human, fit anything more than a few tokens of code in my limited context window? My attention span has dropped to 0.3s, everyone on TV told me so, so I might as well just fix the dependency tree and move on. I couldn't possibly improve upon her implementation even if I understood it.

I'll cut to the chase and say that I did eventually dive fully into these projects. But it wasn't easy, or quick; my last blog update was almost three months ago.

The first major change was the one where I was already sure I knew better than my former self: the 'webpack' sass json importer package. Once I realized it needed a serious improvement, that it was no longer compatible with the current sass compiler, or that it was dependent on the compiler at all, I let it fester in the back of my head for a while.

This whole project was started because I wanted to restore this blog article. But what use would the blog article be if the packages couldn't be hacked on safely by the readers? I needed to update the sass compiler, which meant I needed to make significant changes to the sass json importer just to publish this post. I was reminded of a talk I saw Powen Shiah give in person, not so recently, titled "Open Source is a sewer". I came in expecting to update some contact info, change a few pronouns, and reflect on what an odd creation this is. If that was my higher ideal of what working on this project would be like, rewriting this transitive dependency was as deep in the sewage as it could get.

That first step though, of starting from the bottom, led me to realize that a countable number of people were downloading this package, sometimes up to 15 per week. The downloads alone could be caused by anything, but I know for sure there is at least one person who has looked through and tried it: while reading the documentation for the json2scss package powering the importer, I realized the maintainers, AS Devs had mentioned my package and linked to it right from the README.

This is the other part of what Powen meant by open source being a sewer. My importer wasn't perfect, but as long as you didn't need the newest sass language features, it is reliable. And seeing confirmation that others found it useful, even just by directing users to it from his project, pushed me to finally rewrite it correctly. This is public infrastructure. Even if it's the equivalent of a small well that a few neighbors share, it is worth preserving.

Slowly but surely, every step I took increased my confidence and allowed me to take more daring steps, making more improvements to the source code. I can actually read and write regular expressions, I can convert an async data stream into an async callback. I ended up adding a new feature to the @strawburster/router package that I remember seemed impossible when I first created the package: wildcard routes and parameterized paths. And throughout, I kept the API backward compatible and actually decreased the total size of compiled css files.

I hope you can take a look at the resulting blog post and packages, and maybe try some of it out yourself. I can't promise any of it will be actively maintained, but I promise to try.

Footnotes:

1

One issue I still have is that when publishing a package using a codeberg access token is that the codeberg registry almost always returns a 500 error on the first upload attempt. Despite that, it does publish it successfully, so when automatically retried a second time, the registry now returns a 400 error saying that the same version can't be published twice.

I spent some time trying to parse the stderr to ignore nonzero exit codes if given a 400 response, but what ended up being easier and more reliable is simply ignoring the exit code from npm publish entirely, then afterwards checking that the version in the local package.json file matches the latest published version. This hasn't steared me wrong yet, but I can imagine a situation where I might want to publish a package that is not the latest, like a critical security fix for an out-of-date major version that is still being used, in which case the shell script might need to become more complex.

2

Eslint provides warnings about code smell, which is, basically, software patterns that probably only work in controlled environments or are difficult to maintain. Even if it passes the test cases, smelly code can lead to unexpected behavior or it may be easy to misunderstand in the future. That is a deliberately broad definition because eslint is a quickly evolving set of rules that search for code smell, and the onus is on package maintainers to enable or disable each rule individually, or add a third party list of rules, like one maintained by AirBnB, to define what code smell is.

I decided a while ago to use a list of rules maintained by the Alloy Team but the entire configuration system changed a few years ago, the old style deprecated, and version 10 removed the ability to read old configs entirely. It is a bad decision in my opinion, and both Alloy and I have not upgraded yet to version 10. The new config style completely disables pluggable rulesets like the one I was using. Despite eslint version 9 being officially deprecated, it has been maintained well for years and hopefully it will continue to be maintained and eventually forked away from the eslint team.

3

I hope all the AI-boosted software 'developers' read this sentence twice. I can only say that because I'm not offloading my work onto a statistical model to obscure ownership and join some mythical new era of productivity. I can't imagine dealing with the anxiety of not even knowing which parts of a project are mine or why I chose certain abstractions. I would second guess everything I wrote from more than two weeks ago, at best.

The really crazy thing to me is that a lot of these llm tools are hiding their user's sole contribution to the projects: the input prompts. I know that 'prompt engineers' exist, and other power users find ways to share their inputs among coworkers, but my experience working, or trying to work with other AI-enabled engineers is that their prompts are never stored in the git repository, only the outputs. And asking to see what prompted certain changes or commits is sometimes even seen as an invasion of privacy, and again, this is sometimes the only thing vibe coders are themselves providing to a project, and I'm not allowed to see how they crafted their specifications.

These tools are teaching developers that their thoughts are useless, even embarassing, something to feed into a machine to extrude into a more palatable, useful, thing. The truth is these machines are the useless thing, and without your prompts they would do nothing at all. You are the spark, the most critical component. Your input is valuable.

And that's what it comes down to, isn't it? They need our prompts, desperately. They all do: Anthropic, Microsoft, Kimi etc. They need us to refine their models, provide post-training data. And they've convinced a lot of their users the exact opposite, that the users need them, that the outputs are the valuable thing. Don't fall for it.

Created: 2026-04-27

Last modified: 2026-04-27