Pushup: a new tool for creating dynamic web apps

To build and maintain server-side web applications faster and easier, we’ve created a new tool: Pushup.

We designed Pushup for the Go programming language as a page-oriented, server-side web framework, similar to applications developed in PHP, Ruby on Rails, and Django for Python. Check out the repo and our video demo to get started. In the meantime, here’s the breakdown.

Lightweight syntax compiles to Go

Pushup introduces a lightweight new syntax that glues HTML markup and Go code into a single file – a Pushup page (noted by its .up file extension). You can think of these as self-contained units of VC (as in “view” and “controller” in the MVC pattern). The Pushup compiler translates Pushup source into pure Go code.

Filesystem-based routing

Pushup embraces filesystem-based routing. Requests to a Pushup app are routed to pages based on their filenames and location in the project directory structure. For example, a request to the URL path /about/contact-us is handled by the Pushup page at ./app/pages/about/contact-us.up. It’s fast and easy to wire up a set of pages in a Pushup app because it’s all just files with their own logic and markup.

Modern server-side apps with rich client interactivity

As these things tend to go, server-side web development is an old idea that’s getting new traction in the JavaScript web framework world. The pendulum had swung all the way to the client, with HTTP being relegated to mere RPC transport and HTML to application shells. But Pushup is not advocating a return to 2006. We can have 99% of the rich client UI we’ve come to expect (no full page reloads, streaming updates, enhanced interactivity, etc.) and all the performance benefits and power of HTML, HTTP, and REST. Recent tools like htmx point the way back to the future of hypermedia and its under-realized potential. Pushup embraces this new development by providing first-class support for concepts that make it easy to add client behavior via libraries like htmx. The first main feature to this regard is “inline partials.” This allows a page author to denote a fragment of markup and have it be directly routable without its surrounding markup. This simple pattern turns out to be incredibly useful in making highly interactive pages without a lot of additional work.

It’s just Go

At Ad Hoc, we are big fans of Go. We have used Go successfully since the beginning of the company. For example, it powers portions of HealthCare.gov. It’s been a great backend web programming language and ecosystem. Part of the reason we started Pushup was that we were curious whether Go could be an even better web frontend language.

Pushup apps compile down to pure Go code. The generated Pushup app is just a regular Go binary executable that can be deployed to a host target like a regular Go web app. Because it’s just Go code, the resulting package can be trivially included in a larger Go app. For example, a Pushup app could be the admin panel inside an existing e-commerce store or CMS. Pushup apps use net/http under the hood and implement the http.ServeHTTP interface, meaning they can also be used as middleware.

A new experiment

We started Pushup as an experiment to see how far we could push Go as a web development language occupying similar spaces as Rails and Django. Go is already a great and battle-hardened language for web apps, but it tends to be used with JavaScript SPAs playing the supporting role of JSON RPC API or in other transport and proxy roles. We love Go for its performance, static typing, standard library, and community. But we think it could be even better on the web, especially with respect to page-oriented apps, than the traditional niche of Rails and Django.

The Pushup markup syntax, page-orientation, opinionated project filesystem layout, and support for enhanced hypermedia allow us to experiment with some concepts and see what a modern server-side web app requires. Pushup is (currently) a playground for ideas like i18n/l10n syntax and tooling, compiled-checked accessibility flags, and various ops-related concepts.

Where to next?

Pushup is in a preview state. We’ve made it work for small-ish applications of our own use-cases, but it’s probably clunky and has many stumbling blocks we don’t currently see. There’s also a long list of features and improvements we’d like to make, but we decided to pause and show our work so far. We’re soliciting design feedback at this stage, including fundamental design choices. If you like the cut of our jib, are interested in Go and HTML and things like htmx, we’d invite you to watch the demo below, take it for a spin, and let us know what you think.