DEV Community

Cover image for Taking Nuxt to the Backend with Supabase 🚀
Jakub Andrzejewski
Jakub Andrzejewski

Posted on • Updated on

Taking Nuxt to the Backend with Supabase 🚀

Two months ago, I was giving a talk at Nuxt Nation which is currently my favourite online conference related to Vue.js. This time, I decided to speak about topic that was not fully related to what I am doing with Nuxt on a daily basis but rather an interesting use case.

Instead of using Frontend Framework as it was supposed to be used (in the Frontend), I decided to instead use it as a backend and more specifically, a microservice that I was later using to fetch the data from. The recording of my talk is available below:

And if you would like to see the GitHub repository for this project, check out the following link:

https://github.com/Baroshem/nuxt-backend

Below, I have added some definitions and items from my slide to allow you to better understand the concept :)

Enjoy!

🤔 Using Nuxt on the Backend

Nuxt 3 is powered by a new server engine, Nitro ⚡️:

  • Cross-platform support for Node.js, Browsers, service-workers and more.
  • Serverless support out-of-the-box.
  • API routes support.
  • Automatic code-splitting and async-loaded chunks.
  • Hybrid mode for static + serverless sites.
  • Development server with hot module reloading.

Server API endpoints and Middleware are added by Nitro that internally uses h3 that provides:

  • Handlers can directly return objects/arrays for an automatically-handled JSON response
  • Handlers can return promises, which will be awaited (res.end() and next() are also supported)
  • Helper functions for body parsing, cookie handling, redirects, headers and more

This server API allows us to write API endpoints in the server directory like following:

// server/api/hello.ts

export default defineEventHandler((event) => {
  return {
    hello: 'world'
  }
})
Enter fullscreen mode Exit fullscreen mode

And then, use it in your Frontend like following:

// pages/index.vue

<script setup lang="ts">
const { data } = await useFetch('/api/hello')
</script>

<template>
  <pre>{{ data }}</pre>
</template>
Enter fullscreen mode Exit fullscreen mode

We can utilize this fullstack concept by building a microservice but first lets learn what this concept is.

What are microservices?

Microservices - also known as the microservice architecture - is an architectural style that structures an application as a collection of services that are:

  • Independently deployable
  • Loosely coupled
  • Organized around business capabilities
  • Owned by a small team

The microservice architecture enables an organization to deliver large, complex applications rapidly, frequently, reliably and sustainably - a necessity for competing and winning in today’s world.

What are the benefits of using Nuxt on the backend?

Using Nuxt on the backend may seem strange at first but take a look at following pros:

  • As Frontend developers, we don’t like to touch the infrastructure
  • Simple deployment for many popular hosting providers
  • No extensive configuration needed
  • Usage of popular and widely used Nuxt modules

Supabase helped Frontend devs work with databases and auth. Nuxt allows extend it even further to infrastructure allowing to streamline dev process by a mile!

Using Nuxt here, allows us to utilize the concept of Micromodules (Microfrontend + Microservice) that comes with following pros:

  • Separation of concerns
  • Ability to call One Nuxt Backend from another Nuxt Frontend
  • One module that handles both UI and Logic
  • One repository for certain domain of your app

Using Supabase as our database

In this example, I decided to use Supabase due to simplicity of usage and great Developer Experience. The usage of Supabase in Nuxt is really straightforward.

First we need to install the module and add it to the nuxt.config.ts file:

export default defineNuxtConfig({
  devtools: { enabled: true },
  modules: ['@nuxtjs/supabase', 'nuxt-security'],

  security: {
    corsHandler: {
        origin: '*'
    }
  },
})
Enter fullscreen mode Exit fullscreen mode

As I needed to share resources with cross origins, I decided to also add Nuxt Security

Next, we need to create a new Event Handler:

import { serverSupabaseClient } from "#supabase/server";

export default defineEventHandler(async (event) => {
  const query = getQuery(event);

  const name = query.name;

  const client = await serverSupabaseClient(event);

  return !name
    ? (await client.from("cats").select("*")).data
    : (await client.from("cats").select("*").eq("name", name).single()).data;
});
Enter fullscreen mode Exit fullscreen mode

This event handler basically allows to fetch either one cat by a name query or all cats from Supabase.

Finally, to fetch the data from another application, we need to use following code:

<template>
  <div>
    <ul>
      <li v-for="cat in cats" :key="cat.id">
        <img :src="cat.image" />
        <h2>{{ cat.name }}</h2>
      </li>
    </ul>
  </div>
</template>

<script setup lang="ts">
const cats = ref();
onMounted(async () => {
  // https://nuxt-backend.vercel.app/
  const res = await $fetch("http://localhost:3001/api/cat", {
    method: "GET",
  });

  cats.value = res;
});
</script>
Enter fullscreen mode Exit fullscreen mode

And that's it! We now have a simple microservice architecture by using Nuxt and Supabase.

📖 Learn more

If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this link or by clicking the image below:

Vue School Link

It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects 😉

✅ Summary

Well done! You have just learned how you could use Nuxt as the Backend with the usage of Supabase.

Take care and see you next time!

And happy coding as always 🖥️

Top comments (8)

Collapse
 
aloisseckar profile image
Alois Sečkár • Edited

Question - is there a way to manually export current Supabase contents into SQL? On free tier? I don't mind they don't offer automatic backups for free, but I would like to do a manual one from time to time. But I only found CSV exports.

Collapse
 
jacobandrewsky profile image
Jakub Andrzejewski

Heym thanks for the question. I dont have an answer yet (I asked it in the Supabase ambassadors channel) and I will get back to you when I will have it.

From my knowledge, the CSV export is the only option but I will confirm that :)

Collapse
 
jacobandrewsky profile image
Jakub Andrzejewski

I got the info back:

They could just use pg_dump, I think even the CLI officially supports this too. You can find the docs for the CLI here https://supabase.com/docs/reference/cli/supabase-db-dump, there is a --data-only tag to dump just the data and not the schema too.
Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
aloisseckar profile image
Alois Sečkár

Thank you for investigating :)

Collapse
 
aloisseckar profile image
Alois Sečkár • Edited

I fully agree with Supabase being easy to use and I have it on several project. However, I am not sure about scaling it up for a real production apps.

I already hit the limits of free tier - only 2 separate organizations = databases, it allows file uploads, but only 1 GB, so for storing images I am moving to Cloudinary. And $25 monthly PER ORGANISATION sounds a bit too much for non-commercial apps.

I will eventually give $20 monthly to Netlify to host ALL my websites, but I would rather spend some time researching how to set my own PostgreSQL server somewhere in cloud.

I agree simplicity comes with a price. But for me it seems too high here. However, I find supabase great for small apps or for learning stuff.

Collapse
 
realbuddy profile image
DanielL

@jacobandrewsky it looks like getQuery doesn't work on Vercel
Locally everything is working just fine
Am I missing something?

Collapse
 
jacobandrewsky profile image
Jakub Andrzejewski

Hey, that is strange. getQuery is a built in feature of Nuxt so it is not related to the project I have built. Could you check in the Nuxt repository for similar issues?

Collapse
 
realbuddy profile image
DanielL

Thank you
It was because of ISR
For some reason query params don't work on vercel with ISR