Skip to main content Accessibility Feedback

Creating a dynamic web app with the Jamstack and SSGs

Yesterday, I wrote about the grain of the web. Today, I wanted to talk about how to work with the grain of the web when building dynamic web apps with the Jamstack and static site generators.

Let’s dig in!

What’s a Jamstack? What are SSGs?

The Jamstack is an approach to building websites that relies on mostly pre-rendered HTML. Dynamic components are powered by small APIs instead of a big backend.

One of the big tools used in the Jamstack approach to building websites is the static site generator (or SSG). An SSG takes content from markdown files, mashes it together with some templates (written in mostly HTML), and spits out flat HTML files.

That’s kind of like how a tool like WordPress works, except the HTML is all generated ahead of time, and sits precompiled and ready to send on your server.

SSGs provide the performance and resilience wins of static HTML files with the templating benefits of a CMS-driven website. My sites are all lightning fast, and using an SSG to power things is a big part of why that’s the case.

I use Hugo, but options like 11ty and Bridgetown are great, too!

Dynamic sites built with SSGs often work against the grain of the web

One of the biggest challenges with SSGs, though, is dynamic content. Because SSGs are static, dynamic content generally requires JavaScript.

Students who purchase my books, and courses, workshops access them through a web portal.

A site powered by WordPress would be able to detect if the user is logged in or not, determine what they’ve purchased, and rendered different HTML based on which conditions were met… all from the server!

With an SSG, though, the HTML is rendered ahead of time and generally unaware of the user’s context. As a result, most Jamstack sites—including my student portal—end up rendering any dynamic HTML with API calls and JavaScript instead.

It works, but it adds needless fragility to the UI, slows down rendering on what’s otherwise an incredibly fast front end, and works against the grain of the web.

PHP to the rescue!

That’s not a joke.

I’m working on a new subscription learning app. It’s literally the most important work I’ve ever done, and I can’t wait to tell you more about it. But today, I want to talk briefly about how it’s built under-the-hood.

I’m still using an SSG to create my HTML.

But some static site generators let you generate multiple file outputs from a single markdown file, and Hugo is one of them. I’m using it to generate the HTML for each view and an index.php file.

The HTML file isn’t publicly accessible. It’s only readable on the server.

When someone visits any particular the page, the PHP file checks if they’re logged in, and if they have access to the page, and then either reads and prints the contents of the matching HTML file or redirects them elsewhere.

The end result is an absurdly fast experience that requires little work from the server, is much more resilient, and is much easier to manage and maintain than a big monolithic backend.

I’m using PHP, of course, but you could use any server language you want and do the same thing.

There’s still some JavaScript

I’m still using JavaScript for form submissions.

It provides a more elegant experience for the end user, and is the only reasonable way I can show dynamically generated errors and form status messages to users.

In the future, I do want to add server-side fallbacks for form submissions.

How do you handle authentications?

I’m a huge fan of flat JSON files. In my experience, they’ve proven far more resilient, maintainable, and performant than using a proper database.

However, you can use anything you want.

You could have a serverless integration. You could have a database you query. You could use some OAuth service. The key part of this technique is that most of the validations and checks happen on the server, not in the browser.