Announcements // Mar 08, 2024

Launch: Joystick RC1, Push Private Beta, and Mod Pre-Release

Announcing the official release of Joystick RC1, the private beta of our deployment service Push, and pulling the covers back on our new CSS framework, Mod.

Launch: Joystick RC1, Push Private Beta, and Mod Pre-Release

About 2 1/2 years ago, I launched Joystick as a beta release.

At the time, I was excited to get a 1.0 out as fast as possible. While I certainly could have called an earlier version of Joystick a "1.0," it didn't feel right.

I asked myself "why should a 1.0 be synonymous with a lesser-version of software? Why can't 1.0 be the only major version?" These questions were in mind because around the same time I launched Joystick, I started to refer to it as the "Honda Civic of JavaScript Frameworks" (a nod to the car's simplicity and longevity). After nearly a decade of rug pulls using other tools, I was desperate for something I could rely on today, tomorrow, next year, and a decade from now.

Honing in on "why"

When I stopped and looked around at the JavaScript ecosystem, I realized that long-term thinking was more-or-less absent. It made perfect sense why things kept changing so rapidly: there was no commitment to a singular vision; it was no-holds barred, anything goes development.

That's fun, for awhile, but eventually you get the "JavaScript Fatigue" meme that reared its head around ~2017. Despite a craving for novelty and the "hot new thing," you hit the point as a developer where frankly, you get tired of the bullshit.

As I started to really think about Joystick's long-term future, I realized that what I was aiming at could be encapsulated in a single phrase: "it just works."

Slowing Down

While the Joystick beta was surprisingly functional, I knew it was far from the "it just works" ideal. It was a proof of concept, sure, but if I was going to turn it into something that ran like a tank, I had to take my time.

And so that's what I did. Instead of rushing out a 1.0 on my original timeline of "a few months" after the beta, I took a different approach. I started to build apps for myself and clients, tinkered with some of the mechanics under-the-hood, and made a point to let ideas simmer for a few weeks to months before I said "yep, this needs to be in the framework."

The end result? In its current form, Joystick is remarkably stable. It's currently powering Moumint, CheatCode, SAUCR, and FeatureComplete. Anecdotally, it's far faster than the beta release and it's rare to bump into a legitimate crash.

Joystick RC1 + The Road to 1.0

Having achieved the goal of a productive, stable framework, today, I'm excited to announce the release of Joystick RC1 (release candidate #1). What does RC1 mean? Well, unlike the beta release, I'd now consider Joystick safe and reliable for production use.

If you want to skip ahead, head over to the Getting Started Tutorial on the new Joystick docs site.

It also leaves me room to complete some long-standing tasks that I put off while Joystick's code took shape:

Writing Tests

You may be surprised (or shocked/terrified) to learn that Joystick currently relies on zero tests. How is that possible? Well, as I started to work on Joystick, I realized that it's the type of tool that's binary, meaning, it either works or it doesn't. Tests can be helpful for verifying that edge-cases are handled properly, but I found that simply using the framework every day for years made it easy to write stable code without a lot of tests.

As part of the RC1 release, Joystick now includes its own, custom testing framework. This allows you to write and run tests against a mirror of your app and its databases. Instead of having to chase mocks and author fragile tests, when you write tests for a Joystick app, you're testing the actual app.

Early on in the beta, I started to write tests for Joystick's internals using Jest but realized I was having to mock a lot of stuff. Not only was that tedious, but it didn't really improve my confidence in the code as I was—more often than not testing a mock's behavior, not the actual code.

Now that Joystick has its own testing framework, I decided that the best way to test Joystick was to test it with itself (meta!). After a short breather, I'm going to dig into instrumenting Joystick with tests, building a "kitchen sink" app that will be publicly available for auditing purposes. That app will implement all of Joystick's APIs and include tests verifying each API with clear, easy-to-understand examples.

What's cool about that is not only being able to verify Joystick's behavior, but as a developer, you'll have a robust example of how to write tests for your own Joystick app.

Adding JSDoc Annotations

Over the past two years, I've had a few people ask me if/when I was going to add TypeScript support or implement features in TypeScript. My answer then, as it is now is a firm no. That will be disappointing for some, but the point is based on this rationale: TypeScript is an entirely different language from JavaScript, owned and managed by a corporation. While it does serve a purpose, I'm of the opinion that it serves that purpose poorly (a lot of developer time is wasted on learning/writing TypeScript, maintaining the tools necessary to use it, etc.).

Not only that, but there are active proposals for adding type annotations to JavaScript itself. Having been burned in the past by wünderkind JavaScript replacements, I decided two things:

  1. I want to keep Joystick friendly for beginners.
  2. I don't want to create the potential for a rug pull down the road.

So, what I've landed on is to substitute TypeScript with JSDoc. That may sound wild, but the cool news is that the TypeScript compiler actually understands JSDoc comments. That means that I can "type" Joystick's code as comments that—assuming annotations come into JavaScript core—can be removed later with zero cost to you as a developer.

I know I'™ll get skewered for not using TypeScript, but I don'™t care. TypeScript is necessary like leather pants on a man are necessary (read: they aren't). They might make you feel good about yourself—and occasionally account for aerodynamic efficiency—”but they'™re just a little do the kids say...extra?

Rounding out the feature set

As of today, Joystick includes nearly all of the "wishlist" features I wanted to add to it. To name a few: component-level data fetching, WebsSckets, uploads, job queues, cron jobs, email, a testing framework, and internationalization. In addition to this, the built-in server-side rendering is killer and makes it incredibly easy to render pages, modify their SEO metadata, and handle complex routing with a few lines of code.

Despite this list, there's still more that I'd like to incorporate.

In particular, I've been playing around with how to handle building an SPA-style app with Joystick. My early designs were overly-complex, but I've landed on a design that will make SPA-style behavior opt-in (I'll be writing in detail about this in the coming weeks).

Aiming for the fall

The current goal for putting a 1.0 stamp on Joystick is September. After that point, I will consider Joystick's core APIs "feature complete." Joystick itself won't be "done" (gnar gnar, "fashion is never finished"), but the core, every day APIs that you'll rely on to build your app will be. Over the next few years, Joystick's version will only increment on a minor or patch basis (don't anticipate a "2.0" as my goal is to never have one—at best you'll get 1.291.3).

The punchline? Joystick apps that you build today will work the same 1, 3, 5, and 10 years down the road (the only exception being if some core language or Node.js feature changes that inhibits that). I'll be adding new features, improving stability, etc., indefinitely, but the code you write will look and behave the same.


Though I only started to talk about it recently on the CheatCode mailing list, for the past two years, I've been working to also crack the deployment problem for Joystick apps.

Quick story. When I launched CheatCode in March of 2021, I deployed everything using Next.js and a Kubernetes cluster. Fast forward to October 2022 and a forced upgrade I had no control over at DigitalOcean took my cluster down. Due to how Kubernetes config files were written, my version of the config files was becoming incompatible with the new cluster version. Uh oh. Literally overnight, CheatCode and every other business I was running was taken down.

Fortunately, I had started building a prototype for a Joystick deployment service in January of 2022. By the October Apocalypse, it was just stable enough to eek out a replacement site for CheatCode. Funny enough, up until today, that prototype has managed to keep CheatCode running, untouched, for two years.

Now, after significant iteration, that prototype has reached a private beta status and is being given the name Push. Just like Joystick is designed to make app development "just work," Push will do the same for deploying, monitoring, and scaling your app.

What's unique about Push is not only that it's purpose-built for Joystick apps, but also, it enables scaling your app across multiple providers. So, instead of relying on a single point of failure in the form of a host, you can deploy multiple copies of your app, globally, to different hosts. This means that your app will be performant and resilient, requiring a global thermonuclear war to be taken offline completely (don't say it).

In addition to multiple providers, scaling your app just takes a few clicks (with autoscaling rolling out this summer). You have direct access to metrics and searchable logs. Rolling out a new version of your app after the initial deployment takes ~30 seconds.

Once Push launches to the public, there will be a few different tiers available to get access (I'm still working out pricing). What I can say is that Push will be made available at a higher premium than you might be used to as the value it provides (coupled with Joystick) is leaps and bounds ahead of the clunky alternatives.

Today, I'm making Push available on a Private Beta basis. It's working well, but to get it on the same level as Joystick, it needs to be put through the paces carefully. Developers who sign up during the beta will get lifetime discounts on the service. If you'd like to get access and help out with getting it solid, head over to the landing page and pop in your email to request access.


Now for the big one. For as long as I can remember, I've always wanted to build a CSS framework. I was originally a UI designer and only got into development because I was tired of building static mockups that didn't work. After a decade of doing development stuff, I'm ready to get my hands dirty with design again.

Today, I'm announcing Mod: a CSS framework backed by an ever-expanding library of components and themes. Mod will work in one of two ways: as a standalone, HTML/CSS framework that can be used with any framework (making it available for use outside of Joystick) and as pre-built Joystick components that snap right into the framework.

While I've built some of the initial infrastructure side of Mod, work will begin in earnest over the next couple of weeks with the first version launching this summer. Mod will be available for free with a limited set of components and themes, or, with a paid, lifetime license that gives you access to all components indefinitely and discounts on new themes.

One stack to rule them all

So that's where I'm at. Unofficially, I'm referring to the combination of Joystick, Push, and Mod as "The CheatCode Stack." By the end of the year, my goal is to give you everything you need to design, build, and deploy an app with HTML, CSS, and JavaScript. No more cobbling together parts. No more getting burned by this service or that service. A single stack that just works.

I've been a bit quiet on the tutorials + writing front, but now that the crazy stuff is out of the way, expect to see more on the blog here soon.

Thanks again for your continued support and interest. For now, go check out the new docs for Joystick and take the getting started tutorial for a spin.

Written By
Ryan Glover

Ryan Glover

CEO/CTO @ CheatCode