Nice... and I hope it works out for you as a passive income source.. I'm working on a software package myself intending to sell up-feature editions.
I would note that you can definitely hit cold start issues in Cloudflare if your site/service isn't called often enough for a given region... It's not too bad, just worth being aware that it can happen.
I worked at a SaaS startup for a while, where there was a very heavy demand to do a lot of work under 100ms "always" including the RTT, so in practice we'd need to be in the 30-50ms range, which included a few parallel database calls and a custom AI model.
While interesting, you posted this just over a week ago... Posting more frequently than every other month or so gets really noisy here and a lot of users tend to actively dislike that activity over time.
I'm glad to see you've added some usability features in place. As a stretch goal, may want to look into publishing the entire package as an SVG based color font using the nerd font code points that match the logos, for the logos that overlap. Though, in doing that, you might, or may not, want to also include or incorporate a nice svg emojii set. Then you can be used as a fallback font for color iconography altogether.
I was kind of curious about the JS payload to the browser, and maybe how the dom node rendering was handled, or if any used canvas/wasm, etc.
I build an expandable Gantt chard for a job in 1999-2000 that was pretty tough going, had to work in NN4.x and IE4/5. It worked, but with NN, you pretty much need to cover the area with a solid ILayer otherwise it'll give someone a seizure with the repaint flickering. Today is so much nicer.
Depending on the level of interactivity, I'd probably try leaning into Rust+WASM with Canvas... As much as I love JS, been running a couple projects playing with Rust WASM and Canvas interactivity and it's been pretty nice. You of course do lose some accessibility though, so that may be an issue depending no your needs.
Cool tool... I tend to be pretty anal about making all options available via command line parameters or via environment and search up from working and executable path(s) for a .env file.
I'm not always the best myself at keeping the example up to date, I usually locate my active .env a directory above my project, so I can reset --hard without losing my .env ... I don't know how often OP is cycling in and out new devs though.
FWIW, this has been around for a bit.. That said, I still think there's room to improve some of the tooling around imports, both JSON here, and CSS (future)... I think web components are pretty nifty and finally relatively broadly supported, so it would be nice to see a bit more work there.
https://caniuse.com/mdn-javascript_statements_import_import_attributes_type_json
Minor bit of advice... linting and formatting as a pre-commit and pre-release sanity check can help to spot these things...
If your release lint/format changes any files, then fail the release, you had raw commits that bypassed checks.
At least this way you can better spot malware additions to files before they get into the repo... this doesn't help against upstream attacks, but can at least help you spot these things... I set my max line length to 120 (what I tend to see on the screen when editing).
Worth noting there are polyfills[1] for this, if you need to support older environments.
In practice, I'll usually use something like...
function MyAppError(msg, code, details) {
return Object.assign(
new Error(msg),
{code},
details
)
}
Or helper functions that do the same for assigning attributes to a baseline error... I have gone as far as to pop the top entry off the stack as well, to make it look closer to native.
1. https://www.npmjs.com/package/error.iserror
In a database driver I once wrote, I took advantage of String objects in how I extended attributes for the purpose of parameterizing queries... it worked pretty well for my use case. That said, other features I was trying to take advantage of got up streamed into a more popular dv driver, so I left it alone.
Worth noting there are polyfills[1] for this, if you need to support older environments. In practice, I'll usually use something like... function MyAppError(msg, code, details) { return Object.assign( new Error(msg), {code}, details ) } Or helper functions that do the same for assigning attributes to a baseline error... I have gone as far as to pop the top entry off the stack as well, to make it look closer to native. 1. https://www.npmjs.com/package/error.iserror