ecton.dev

My Vision for Creating Cross-platform Applications with Rust

Hi, I'm Jon. I left my day job three years ago with two goals:

  • Learn Rust: I believed that investing in Rust would be good for my career, if I was unable to build a new business before running out of my savings (my runway).
  • Write a Game: I love thinking about game design, and I would still love to make a lifestyle business around a small community-driven MMO-like game.

This post is my love letter to what myself and a dear friend have been working on. Unfortunately, my friend has had other life events that have pulled him away from these projects for the past year, and I've recently realized I need more friends who I can talk to about these projects on a regular basis.

To help understand how I ended up with hundreds of thousands of lines of open-source code strewn across a large number of repositories, I want to give an overview of the main events in the last three years. After that, I will describe what I am trying to build, and why I believe each major project I've been working on is still important for the Rust ecosystem.

Regardless of your experience level in Rust, if you find yourself relating to my goals, I would love to hear from you. Or, if you would like to see any of these projects come to fruition but aren't really interested in interacting, "starring" the repository on GitHub is a passive way for me to see that people are interested in these projects.

Beginning my Rust Game Dev Journey (2020)

During the first year, I tried many Rust game engines and none worked the way I wanted. I craved several features out of whatever windowing/graphics library I was going to use:

  • The ability to not redraw the screen if nothing has changed. Too many games these days eat up way too many resources for me want to leave running in the background while doing other tasks. I wanted to create a game that people didn't worry about quitting while letting it run in the background. Players should be able to idle and chat without slowing their machine down or draining their batteries.
  • Multi-window support. Most MMOs use a virtual windowing system to pop up various menus and user interface. As someone who always has multiple monitors, I've always wished a game allowed popping some of those windows out into their own stand-alone windows.

Additionally, at the time of evaluating frameworks, Bevy did not exist. Eventually, I wrote my own WGPU-based framework that I named Kludgine. I was in the middle of implementing a UI framework for it when I set it aside for the first time.

Re-evaluating my goals: Transitioning to FOSS (2021)

At the end of 2020, my dog Cocoa passed away. I've been lucky enough to work from home almost every year since about 2007, and he was a constant companion for all of those years. Beyond that, I realized how much my social life hinged on being able to chat with my coworkers about programming, games, books, music, and life. My main friends were my coworkers, and I missed having them.

I saw three paths out of the loneliness I found myself in:

  1. Change my vision to be smaller and hire someone to work with me, shortening how long my runway is.
  2. Create an open-source game and try to create something community-driven. Attempt to find friends who are interested in buliding something similar.
  3. Switch back to regular employment / Try to find someone looking for a technical cofounder.

After taking a break for the rest of the year, I knew I wanted to make a game. I decided if I was going to make a game, I wanted to try to simplify my scope, so I set aside Kludgine and decided to create a browser-only game, and I presented a live version of Cosmic Verge at the February 2021 Rust GameDev Meetup.

Shortly after that, I finally made up my mind to open-source the game and went to bed without posting it anywhere. The next morning, I woke up to a message from @Daxpedda asking about the project. Despite having just decided to reduce my scope, he convinced me to go back to Kludgine. We set our sights on a common goal: create what we thought is our best approach to building an internet-connected application with Rust.

While discussing how to build a clustered server environment, we began discussing various database options. We had overly ambitious goals, allowing a truly highly-available design. To achieve this, we needed to provision many databases and share them across the cluster with independent redundancy. This just wasn't teneble at the time for my favorite database: PostgreSQL. To be clear, PostgreSQL can absolutely be clustered, but it is not a straightforward operation, and the idea of deploying many clusters inside of a larger cluster of machines felt too complex for a small team to truly understand and maintain.

I previously had the pleasure of working with CouchDB. For those unfamiliar, it's a database built around the idea of what a "RESTful" document database might look like, with support for cached map/reduce views against its data. Their documentation is also spectacular in describing how the database actually works, so I've long thought it would be fun to build my own version of it.

During one of our multi-hour long conversations, we decided to explore what it might look like to build our own database that powered the cluster for our game. This exploration became BonsaiDb. Daxpedda focused on QUIC-based networking and OPAQUE Key Exchange/Authentication while I worked on the database itself.

A few months later, I had reached a state where I wanted to build some sort of demo application that had a GUI, and again, we debated the right approach. Practically speaking, I mostly cared about a user interface being available in a web browser using real DOM elements. Why? Accessibility. While there are projects exploring how to add better accessibility support to cross-platform native applications in Rust, the web browser today supports many accessibility features on nearly every platform.

Still, Daxpedda convinced me: why should we settle? This is Rust, and we are trying to create our ideal application architecture. Rust deserves a framework that supports the DOM and native applications equally.

So, I refactored the not-that-great-UI-framework out of Kludgine, and began a new project: Gooey. Over the next few months, I built up the basics of how I thought the ideal widget-based architecture with multiple backends might work. In theory, Gooey could be extended to even use native widgets on Windows and macOS someday. For now, it's a proof-of-concept framework that is missing many critical features.

Stabilizing BonsaiDb (2022)

As 2021 wrapped up, I set my sights on releasing an alpha version of BonsaiDb. My goal at the start of the year was to push BonsaiDb along far enough that I was ready to trust it enough to begin hosting applications I built with it. To me, dogfooding is one of the best ways to improve your own frameworks.

I released many updates over the next few months. In May, however, I stumbled upon some mistakes that dated back to the previous fall. I cover the details in the post, and over the next several months I explored how to rebuild BonsaiDb's storage layer to improve its performance.

It was these months of trying and never quite succeeding that led to me getting burned out towards the end of October. I finished reaching my goals on my new write-ahead log's performance, which I think will be the final piece in the puzzle, but there is a mountain of work left to incoporate it into my new storage layer, then refactor Nebari to utilize it, and finally be able to test BonsaiDb against it.

Bud: A distraction towards my game vision

As is usual around this time of year, I start getting the itch to "just make a game already." For most of my ideas, I've always wanted aspects that were able to be customized by players, potentially by writing their own code. I looked at the landscape of scripting languages written in Rust, and I was shocked to not find a mature #[forbid(unsafe_code)] scripting langauge. Nearly every implementation relied upon unsafe, and I was curious: could I make an efficient, no-unsafe scripting language? The answer is yes, and Bud is the result of those explorations.

I've always enjoyed developing languages and compilers, so this project has been a breath of fresh air for me. It's helped me decompress and think about what I would like to try to accomplish this next year. Additionally, this year my wife and I hosted Thanksgiving, and the preparation as well as having family stay in our house led to many distractions and eventually a bout with COVID that I'm still recovering from as I write this post.

All of this is to say that I've had plenty of time to think about what I really want to accomplish with my remaining runway.

My Rusty Vision

EVE Online is jokingly called "Spreadsheets in Space." When I played it, 90% of the game could be played by menu interactions and looking at tables of "data." Even combat in space could largely be driven by "the overview" panel. It's these basic facts that made me want to build a highly-accessible game that focused on user interface first and had a simplistic 2d game environment to tie it all together.

Why would I want to do this? To be honest, I don't have any real belief that I can make enough money building a game to live off of. I'd love to, but I don't want to put all my eggs in one basket. When discussing with Daxpedda what we were building, we always agreed: we wanted to make a game, but we just wanted to build a great architecture that we could use to build nearly any application we wanted.

By building an ecocystem that makes it easy to build cross-platform, database-driven applications, I am setting myself up to be able to not only pursue building a game, but also being able to try other entreprenurial ideas. Rust can provide the language for a write-once, deploy anywhere ecosystem, and I want BonsaiDb and Gooey to be one of the ecosystem choices.

It's this motivation that keeps me working on my projects. And, despite having some burnout, I am still committed to seeing this vision through. Still, it's lonely working on such a lofty vision while flying solo for most of the year, which has led me to writing this post.

Why BonsaiDb?

BonsaiDb aims to make developing, testing, and deploying database-driven applications easier. By utilizing BonsaiDb's account management, permissions, networking, PubSub, and more, applications can have a jump start and not worry about how to deploy additional services onto their hardware. Shipping a BonsaiDb-powered server is as simple as shipping your regular server executable.

BonsaiDb uses Rust's trait system to allow writing code that works regardless of whether the database is stored locally or remotely. It is compatible with both threaded and async applications. It can work completely offline like SQLite or with a remote server today. And, when clustering is eventually supported, it will be easy to scale your application across multiple servers with high availability.

The last idea that I think differentiates BonsaiDb is my vision for a plugin/pacakage system. I want to develop a way for reusable database-driven services to be packaged and shipped to multiple BonsaiDb servers as add-on services. For example, a job-queue system like Amazon SQS/Resque/Sidekiq could be packaged as a plugin and be reused by multiple applications/servers. The BonsaiDb Admin should also support custom administration panels, enabling a unified monitoring and administration interface.

For those who are interested in a truly Rust-only deployment, pairing BonsaiDb's architecture with a microkernel such as RustyHermit could someday create a 100% Rust powered infrastructure.

Why Gooey?

Gooey takes a unique approach to its architecture to ensure that the developer can always get the behavior they are looking for.

Gooey Architecture Diagram

The core of Gooey has no knowledge of any specific widget type. The core just defines the traits and shared functionality that all "frontends" may need. The Gooey repository includes two frontends:

  • Rasterizer: Uses a Rasterizer trait implementation to render the user interface. A Kludgine rasterizer implementation is provided. This frontend is what is used when running an application outside of the browser.
  • Web: Uses web-sys and wasm-bindgen to manage DOM elements for each widget.

Finally, a separate "Widgets" crate is provided, which contains completely cross-platform widget implementations. Because the widget crate is separate from the frontend crates, this ensures that no special support is provided for any widget that a developer couldn't write on their own without changing the core or frontend. This design also ensures that third-party widgets can be written and reused.

The last unique feature of Gooey is the ability to override the behavior for a widget on a given frontend. If you dislike how the built-in Button widget works on Web, you can replace its "Transmogrifier" with your own implementation without altering the rest of your applications code.

Gooey is still very much at a proof-of-concept stage (demo at December 2021 Rust Game Dev Meetup). It is missing grid and/or flexbox layout options, doesn't support scrolling yet, and is missing many important controls. Still, as I think about what I would like to use to build a BonsaiDb Admin, I wish that Gooey were more developed so that I could use it.

Call for Friends and Contributors

I really miss being able to talk about my daily accomplishments and struggles with someone that I can trust to laugh with me and not at me when I pursue some thought that ends up being a really bad idea. Or, to be able to talk through several ideas I am having and having someone else provide additional perspective from their experiences. If you're a Rustacean who is looking to cowork or chat occasionally during Pacific timezone working hours, I would love to hear from you.

If you're interested in contributing to any of these projects, regardless of experience level, please reach out to me. I'm especially interested to find someone else who is passionate about the goals behind Gooey. I fear that if I don't find another motivated person to help me push it forward that I will archive Gooey out of necessity of focusing on fewer large projects.

If neither of those apply but you have truly disposable income that you would like to put towards this vision, I currently only have GitHub Sponsors set up to accept donations. I do not currently need additional money to support myself, but contributions would extend my runway. If there were enough support and interest, I would use it to hire developers to help me build this vision.

On a typical workday, I usually am on Khonsu Labs Discord Server while working. If you don't use Discord and would still like to contact me, I'm on Mastodon or you can email me at [email protected].

As always, thank you to everyone who has taken the time to read my posts or interact with me in any way (even a star on a repository or an upvote/like on social media sites). I wish everyone happy holidays and a Happy Rusty New Year!

P.S. I'm recovering from a recent COVID infection (wasn't severe), and this post took me several days to write. I may be a bit slow to respond in the coming week as I continue to get my energy back.