Trying Out Nuxt

I have enjoyed using Astro to run both this site and DBaaS Review. I’ve written before about Astro now and again. Recently I decided to migrate DBaaS Review from Astro on Render to Nuxt on Cloudflare.

My original motivation was receiving a bill from Render for DBaaS Review’s API. Now $7/month is pretty reasonable, but it got me to thinking. If I could switch from Render to Cloudflare Pages, I might be able to stay within the free tier for a while. Plus, having two different projects, one for the API and another for the UI, was getting tiresome. How good would it be to have just one static frontend with a dynamic API, all hosted on the edge for free?

As long as I was going to tear everything apart, I thought “why not try Nuxt?” After all, Nuxt/Nitro has a Cloudflare Pages preset. So I merged the Express API with the Astro site to form a single Nuxt app. It went fairly well at first, and Nuxt has a slick DX. I especially appreciated the file-based-routing for the API endpoints. It was tedious converting the JSX-like .astro files to .vue components, but I prefer the Vue syntax anyway, especially for loops:

Astro

---
const visible = true;
const items = ["Dog", "Cat", "Platypus"];
---
{visible && <p>Show me!</p>}
<ul>
  {items.map((item) => (
    <li>{item}</li>
  ))}
</ul>

Vue

<script setup>
import { ref } from "vue";
const visible = ref(true);
const items = ref(["Dog", "Cat", "Platypus"]);
</script>
<template>
  <p v-if="visible">Show me!</p>
  <ul>
    <li v-for="item in items">{{ item }}</li>
  </ul>
</template>

I ended up getting stuck on some sharp edges with the Nuxt/Cloudflare migration. One was that I just couldn’t find a nice way for Nuxt to find and open a SQLite file. I finally realized that Cloudflare Pages’ workers would never allow me to access the filesystem and load a SQLite file anyway.

Discouraged, I tried implementing a combined app with Astro in Docker. It went very smoothly. I was able to reuse much of the work I did for the Nuxt API endpoints, and reading the SQLite file worked without a fuss. Astro’s Docker SSR recipe worked well. Now that I had a containerized app, I was able to deploy my app to Fly.io. Render and Fly both have a free tier which they spin down services for inactivity, but unlike Render, Fly.io’s spin up seems speedy enough that it doesn’t feel like a penalty. Fly Machines are Firecracker VMs that boot in about 300ms. Goodbye, Render.

Could a containerized Nuxt have worked on Fly.io? Likely yes. Could SSR Astro have worked on Cloudflare? Maybe? I admit to my bias and laziness; Nuxt had to be much better than Astro to be worth the migration hassle, but it just wasn’t. They’re both about equal in terms of Pros and Cons, except I’d give the edge to Astro’s docs right now. I’m glad I tried Nuxt and I think for a brand new app I’d try it again. But then again, I might experiment with SvelteKit or SolidStart instead. Anything but Next.js/React. 🤢 PHP even.

As for the main thing I don’t like about Astro, the JSX style templates? Using SSR Vue components within Astro is feasible to a point. But, there are certain things that can only happen inside an .astro file, so I just have to learn to live with weird loops and conditionals.

Support