Dynamic Routes with Static, Vanilla HTML Pages Using Zeit's Now...

by Michael Szul on

No ads, no tracking, and no data collection. Enjoy this article? Buy us a ☕.

If you follow me on Twitter, you know that I'm a big fan of Zeit. I use several of the technologies that they've developed, including Hyper and Now. Now is a deployment engine that connects with their hosting service, and is centered on serverless architecture. In fact, even if your web application is a monolith, Now will break it down into serverless components for hosting purposes. This opens up a wide range of side effects that you can take advantage of.

For example: Sometimes, you want to quickly stand up a web site--either as a placeholder or as a starter web site. Maybe you want to put together a handful of static web pages, and eventually migrate to a static site generator like Gatsby or Jekyll. In most situations, your URL structure follows your file structure, so your HTML files tend to be *.html files in a specific folder that you're serving from. When you later move to Gatsby (or something else), you might have to adjust your URL paths, or put server redirects in place, so that you don't lose your hard-earned search engine indexes.

With Zeit's Now, you can control all of this through the now.json file, so that your routes are uncoupled from your file structure.

In my case, I started to put back issues of the newletter on the web site, in order to not have them locked down on Mailchimp. Mailchimp only allows recipients to access a limited number of previous campaigns, and they use a robots.txt file to prevent search engine crawling. Eventually, I probably will move to a template engine, but in the meantime, I just want to write some HTML (with the help of copy/paste). Two of my concerns: I didn't want *.html at the end of every URL, and I didn't want to have to change the URLs when I move to a static site generator.

Zeit's Now makes this easy. Here's my now.json file:

          "version": 2,
          "name": "codepunk.io",
          "builds": [
              { "src": "**/*.html", "use": "@now/static" },
              { "src": "static/**", "use": "@now/static" },
              { "src": "package.json", "use": "@now/static-build",  "config": { "distDir": "./" }}
          "routes": [
              { "src": "^/", "dest": "/index.html" },
              { "src": "^/about", "dest": "/about.html" },
              { "src": "^/issues/(.+)", "dest": "/issues/$1.html" },
              { "src": "^/static/(.+)", "dest": "/static/$1" }
          "alias": [

Zeit's Now uses builders to know how to break out and serve your application or web site. Above, I'm using the static site builders built into Now. The first object in the builds array says to grab everything with a *.html extension and serve it using the static builder. Meanwhile, in the routes array, zero in on the second to last line. This is where I'm handling the back issues of the newsletter. This object says that anything sub of the "issues" folder should be routed to the corresponding HTML file in the issues folder. So with that one line of code, I can rewrite the URLs the way I need them to be. In this case, I'm simply removing the *.html, but in the future the files could be in a completely different directory, and that would be okay, since Zeit's Now is controlling the routing instead of the file structure.