September 12, 2023

Our pixel-rendered planner with a Rust backend

Just because we're engineers, doesn´t mean we build ALL our applications ourselves. But sometimes inspiration hits and good things happen. So our company planner is now canvas-rendered, has a Rust backend and works like a charm.


Tweede golf is by no means a mega-corporation (there's 18 of us), but keeping track of who works on which project, what they are currently doing and whether they're available to help out on an awesome project next week... is a bit of a hassle on paper.

In 2015, we were old-school and used a whiteboard. No lie. Here's a picture.


But today (and for a while now), we have a pretty neat online version, home-made, with TypeScript and Rust of course!

The Tech

Where it came from

Once it was decided that the whiteboard had to go, we started developing, mostly in React, with a NodeJS backend, and have since had several versions of this planner called TGenda.

As the company grew, and the number of actual plans to be recorded grew with it, so did the number of DOM elements. This resulted in performance issues for the React/HTML build we were using, because we used the drag-and-drop functionality a lot. This was problematic: we needed that to be smooth, so it was time for a reimplementation.

Wanting to get rid of the DOM elements brought me to the Canvas API, which uses pixels instead, because who doesn't love awesomely fast animations? (More about that later.)

We had previously experienced that maintaining a TypeScript frontend with many dependencies is tricky and tends to bring about security issues. So for the greater good I deciced to challenge myself to not use any runtime dependencies for the frontend at all, except of course for TypeScript itself, as a direct dependency.

The backend was created using Rust with the excellent Axum and SQLX crates.

The current version in Rust

This version has an exceptionally clean and organized codebase:

  • A global state, that is updated through events and a reducer (inspired by redux)
  • State updates trigger a render of the whole canvas
  • Renders are quick - mere milliseconds
  • The Rust backend has the same event type as the frontend, and a bus that several services can listen to
  • A selection of frontend events is also sent to the backend through a websocket connection
  • The backend broadcasts these events to all other clients, creating a live update mechanism
  • The backend runs a service that listens to certain events and turns these into database updates

How it works How it's made: our digital company planner

This event-based mechanism is very flexible; by changing only one line, I was able to make the scroll position a shared state, which means every client then shared a scroll position (for fun, just to test the performance). The combination of a websocket and the Rust backend provides such low latencies that multi-client scrolling is smooth!

The frontend looks similar to this example - try dragging an event to a different day!

Other things I'm happy about:

  • Forms are rendered with HTML, by my own implementation of JSX, without Virtual DOM like in React. This makes the code readable and allows you to easily follow the logic behind it. It delivers excellent performance for our use-cases.
  • The application is only a single Rust binary! All static files (like JavaScript and CSS) are put into this binary at compilation time and served straight from memory.

The best features

And the features that get their own paragraph are confetti 🎉 and the snake 🐍︎ game.

Make confetti to celebrate never having to be bored: Confetti

And then play snake to literally eat your work:


Stay up-to-date

Stay up-to-date with our work and blog posts?

Related articles

February 24, 2023

Introducing MailCrab!

MailCrab is an email test server for development, written entirely in Rust.
Most of our web applications use either Node.js or Symfony for their server-side part. Both offer a lot in terms of productivity. But every now and again, when you look at the computing power used or the amount of time a simple HTTP request takes, you can't help to think "what if..?".
Sending documents over the internet can be a pain. Email providers generally support attachments with a maximum size between 10 and 50 MB, for larger files one would need to find another way. Most people would probably use one of the many public cloud or file sender solutions. But what if the files to be sent contain personal information, medical information or are private family photos? And how do you know that only the recipient can access and download these files?