This article is somewhat of a memoir where I share my experience getting dynamic routing to work with Firebase. To understand what’s going on, you should be familiar with their and products. I’ve condensed all the essential technical stuff into the . Feel free to skip this section if you’re willing to read the whole article. Hosting Functions mini tutorial tl;dr Mini Tutorial Firebase Hosting serves static files from your custom domain. Firebase Functions are executed by calling them via ugly URLs. As of Google IO 2017, they now play nicely together. In your ’s configuration, you can any specific route on your custom domain to call a instead of serve a static page. cloudfunctions.net firebase.json hosting rewrite function Check out the docs. To simulate dynamic routes like , I did the following: Create a function called . Set up to have all requests for call the function. The function fetches data and returns pre-rendered containing all the proper social and SEO meta tags for the requested post, to make crawlers happy and support . example.com/posts/123 [post](https://gist.github.com/pejalo/1715c896658d660e0ded0d49d9910896) firebase.json /posts/** post HTML unfurling The page also includes a redirect snippet, so a real user is redirected to . This static index page reads the query parameter, displays the correct screen with the post content, and leverages HTML5’s to put back into the browser’s address bar. Serverless dynamic routing for all! JavaScript window.location example.com/?post=123 replaceState() example.com/posts/123 ❤ Firebase Firebase has single-handedly reignited my relationship with web development. Instead of building a frontend and backend for every project, I now only ever have to worry about the frontend. As broad as Firebase’s offering is, it still lacks many sought after (like , complex database , insight into , etc). But I’m so invested at this point that I’d rather jump through a couple hoops to make something work with Firebase than go back to setting up a foundational backend myself as if we were still living in a pre- era. (Yes, us developers are lazy.) features search querying usage Parse A couple weeks ago I was working on a Product Hunt clone that had a pretty simple requirement: dynamic routing. Each post needed its own URL to share around the web, like . These links had to return pre-rendered social and SEO meta tags to support . example.com/posts/123 unfurling Up until this point I had everything happily hosted on Firebase as a notorious , connecting directly to the database from the client. But with this new pre-rendering requirement, which was not yet supported by Firebase, it looked as though I’d have to point our domain to a custom VPS and host the site myself. single page app So I spent a weekend learning about (a great option BTW), getting our site up and running, doing some load testing, watching the site crash, scouring the internet to try and figure out why, convincing myself the app had memory leaks, then realizing I just needed a machine with more memory, bla bla bla all the while wishing I could just get back to building features and stop dealing with this dev ops nonsense. Dokku A couple days later, someone in the Firebase Slack group posted a livestream. I tuned in just for fun and right there, the exact feature was announced that I needed: With this new integration developers can run some backend code behind a custom domain before sending HTTP responses to the client. Within a couple hours I had dynamic routing working in production and could put Dokku back on the shelf. Google IO Hosting + Functions! Hosting + Functions Firebase Hosting now has a new configuration option. In , where you specify all your like caching, rewrites, redirects, etc, you can any path to point to a function instead of a static file. Here’s an example: firebase.json hosting behavior rewrite // firebase.json { "hosting": { "public": "public", "rewrites": [ { "source": "/posts/**", "function": "post" } ] }} With this config, any requests to will ignore whatever static files you might have hosted there and call your function instead. The function is called with Express and objects through which you can send an arbitrary HTTP response. example.com/posts/postidorhashorwhatever post Request Response This lets us perform any logic we want before returning to the client! (As long as it runs within Firebase’s cloud function Node environment…) Great, you might think: We can return anything, but how do we return an entire page of our website showing the proper post content, when the website is built to be served as static pages? The truth is, I don’t know. Maybe some day the Webpack gurus will create super fancy plugins that separate dynamic routes into functions with their own deployment configurations. Who knows what they’ll come up with next. Meanwhile, I’ve got a hacky solution that isn’t too complex and achieves the same result. Redirects Because our function can return anything, it’s pretty easy to have it return valid HTML with whatever content-specific social and SEO meta tags we need. This is the only part of our page that really needs to be pre-rendered to support unfurling. And if we can make it return an HTML string, we can certainly include a snippet of JavaScript in there to help get the rest of the page displayed asynchronously. Here’s a shortened version of what my function looks like: post As you can see, the HTML response to be sent includes . A crawler just looking for your meta tags will be happy to receive them and won’t bother to execute this script. But a real user who loads this page in a browser will be immediately redirected to . '<script>window.location="[https://example.com/?post=](https://example.com/?post=)' + post.id + '";</script>' example.com/?post=123 Now what exactly happens on is out of the scope of this article, because it completely depends on the frontend framework you’re using. You just want to show the post content without redirecting the browser back to . (My website was built with , so in my index page’s function I check . If it exists, I show the requested post within the index page, without touching the route.) The important thing to know is that you can what’s displayed in the browser’s address bar to look nice again. To replace the ugly with , you can call . example.com/?post=123 /posts/123 Vue.js beforeMount() this.$route.query.post manipulate ?post=123 /posts/123 window.history.replaceState({}, ‘Title’, ‘/posts/’ + postId); Voila! Unless the user paid attention compulsively to their address bar, all they know is that they clicked on a link and ended up on the proper page of our website. Honestly, as a design freak, this double-redirection does irk me a bit. It’s not sparkling clean. But it only ever happens to users who navigate to our site via a standalone link like from another source. The jarring experience of jumping from the referring website to our site overshadows the quick redirects happening in the background. example.com/posts/123 And you know what’s dirtier than a little redirect hack? Spinning up a new virtual machine, installing Ubuntu, adding your SSH keys, creating a new sudo user, , etc etc you get the picture… sudo apt-get update Firebase FTW. Made it to the end and learned something? Leave some love 💚 Peter LoBue is a freelance UX designer, web developer and iOS developer living between Philadelphia and San Francisco. Reach out for availability: @pejalo