Encoding Tools gets Svelte

My modest goal for this website is to publish at least one post per year. And yet… here I am on Dec 27th like a 6th grader who didn’t start the science project until the night before it’s due. Much like the blog, my pet project Encoding Tools has been languishing for a while, but over the last few weeks I finally sat down and started working on it again.

Porting to SvelteJS

The first version of Encoding Tools was written 3 years ago in the Dart language, which in the intervening years has mostly died off as a viable webdev language. (It is still finding success in the mobile dev space as the language that underlies Flutter.) At the time, there were not many great web frameworks for Dart, so I ended up writing a framework-less app, which felt pretty satisfying at the time.

But time passes. Dart is a moving target and frequently when I sat down to work on Encoding Tools, I would find that my Dart version had changed and I needed to make fixes just to keep the old code running. Eventually I recognized that Dart was a deadend, but I’m such a moron with the JavaScript ecosystem that I couldn’t work up the energy to plunge into it.

Until, that is, a coworker recommended SvelteJS, which is a really compelling JavaScript web framework. Some of its adherents call it a “non-framework” because it eschews the common strategies of reactive programming (like React) or shadow DOM and digesting (like Angular). Svelte moves most of the component logic into a “compiler” step that automatically generates code to update the DOM in a very precise way. Instead of re-rendering or diffing an entire DOM tree, the compiler statically analyzes your code and figures out which elements and properties need to be updated, then generates plain-old JavaScript DOM code to do just that.

Svelte’s clever design reduces the runtime computation for DOM updates, which in theory improves user experience by reducing latency and energy usage. But Svelte is also well-known for its excellent developer experience, including a VS Code extension, language server, and sensible state management built into the framework. Overall, it was really enjoyable to learn and use on this project, and the result is a revamped Encoding Tools that will be easier to hack on in the future. (And hopefully easier for others to contribute to as well.)

Finally, I took this opportunity to set up continuous deployment through GitHub actions, so now all pushes to master automatically run tests and then deploy to the production web site. All of these changes will help improve velocity, especially for “small” issues that would only take an hour or two to implement if not for the complexity baggage of the old implementation.

Improvements to Encoding Tools

In the process of porting the application over to Svelte and JavaScript, I also took the opportunity to fix some long-standing issues. The first noticeable difference is that the UI has been refined and some new controls added.

Comparison of Dart and SvelteJS Encoding Tools.

Each input now a control for copying its value (something I personally want nearly every time I use Encoding Tools). It also has a control to delete the gadget, so users don’t need to guess the hidden right-click-to-delete gesture. Input gadgets also have a paste button so that its easy to pop in data that you copied from somewhere else (e.g. Burp Suite). The rendering is also refined. The edges are drawn as thin bezier curves instead of chonky straight lines, and gadgets and ports have consistent border radii.

In the previous version of Encoding Tools, I wanted the ability to deeplink to certain assemblies of gadgets for SEO purposes, for example a URL decoder deeplink would open up a new workspace with an input wired to a URL decoder. I also put links to these assemblies inside the toolbox so that it was easy to find them from inside the app. In practice, I use these links way more often than I actually drag and drop gadgets.

In the new version of Encoding Tools, I expanded this idea into a new component called “The Warehouse” that holds pre-assembled gadgets. (Get it?) I also realized that creating a new assembly for each gadget won’t scale well as I add more and more gadgets, so I added a shortcut: if you double click a gadget in the toolbox, it takes you to a deep link that creates an assembly for that gadget. The warehouse contains deep links that build complex assemblies. It also opens the door to being able to save your own assemblies and load them again later.

The new warehouse drawer.

Finally, I added a feature that I completely overlooked in the past: a sitemap! Encoding Tools gets horrendous organic search traffic. (Most of the traffic is direct entry, thank you friends who bookmark the site!) The main reason for the poor organic search is probably because it’s a single page application and spiders don’t know how to index it.

The new warehouse drawer.

The sitemap should improve organic search by telling spiders which deeplinks to visit. Of course, spiders still need to execute a bit of JavaScript in order to see the rendered page, but this should at least boost Google and Bing results. The sitemap is automatically generated at deployment time, so it will always stay in sync with the gadgets and assemblies defined in the application.

Follow me on Twitter or subscribe to this site via RSS for project updates. If you have feature requests or bug reports, please create an issue on GitHub.