integrating supabase authentication with nuxt.js: a developers guide
why authentication matters for your full-stack app
before we dive into the coding, let's talk about the 'why'. authentication is the bouncer at the door of your web application. it checks user ids, manages who gets in, and decides what they can access. for any full-stack project, getting this right is non-negotiable. it's a core part of your app's devops and security pipeline. a smooth, secure login experience also contributes to good seo by reducing bounce rates and improving user engagement metrics.
this guide will walk you through integrating supabase, an open-source firebase alternative, with nuxt.js, the intuitive vue.js framework. together, they create a powerful, modern stack for building authenticated web applications.
prerequisites: what you need to get started
let's make sure you have all your tools ready. this will make the process much smoother.
- a supabase account: head over to supabase.com and create a free account.
- node.js installed: you'll need node.js (version 18 or later is recommended) to run nuxt.
- basic knowledge: comfort with javascript, vue.js fundamentals, and the command line will be very helpful.
step 1: setting up your supabase project
think of supabase as your ready-made backend. it provides a postgres database, authentication, and apis out of the box.
- create a new project: in your supabase dashboard, click "new project". give it a name and a strong database password.
- get your api keys: once the project is ready, go to settings > api. you will find two crucial pieces of information here:
- project url: your unique supabase api endpoint.
- anon (public) key: this key is safe to use in your nuxt.js frontend. it respects your database's row level security (rls) policies.
- configure your site url: under authentication > url configuration, set your site url. for local development, this will be
http://localhost:3000.
step 2: creating and configuring your nuxt.js app
now, let's get our frontend framework set up.
open your terminal and create a new nuxt project:
npx nuxi@latest init my-supabase-app
cd my-supabase-app
next, install the official supabase client library:
npm install @supabase/supabase-js
managing environment variables
never hardcode your api keys in your source code. nuxt has built-in support for environment variables.
- in the root of your project, create a file named
.env. - add your supabase keys here:
supabase_url="https://your-project-ref.supabase.co"
supabase_key="your-anon-public-key"
nuxt automatically makes these available in your app via useruntimeconfig().
creating a supabase client plugin
we'll create a nuxt plugin to initialize the supabase client and make it available throughout our app.
- create a new file:
/plugins/supabase.client.ts(the.client.tssuffix ensures it only runs on the client side). - add the following code:
import { createclient } from '@supabase/supabase-js'
export default definenuxtplugin(() => {
const config = useruntimeconfig()
const supabase = createclient(
config.public.supabaseurl,
config.public.supabasekey
)
return {
provide: {
supabase
}
}
})
update your nuxt.config.ts to expose your environment variables:
export default definenuxtconfig({
runtimeconfig: {
public: {
supabaseurl: process.env.supabase_url,
supabasekey: process.env.supabase_key,
}
}
})
you can now access your supabase client in any component or page using usenuxtapp().$supabase.
step 3: building the login and registration flow
let's build the core ui for your application. we'll create a simple sign-up and sign-in form.
creating a registration page
create a new page at /pages/register.vue. this will contain a form to capture an email and password.
<template>
<div>
<h2>create an account</h2>
<form @submit.prevent="handleregister">
<input v-model="email" type="email" placeholder="email" required />
<input v-model="password" type="password" placeholder="password" required />
<button type="submit">sign up</button>
</form>
<p v-if="message">{{ message }}</p>
</div>
</template>
<script setup>
const { $supabase } = usenuxtapp()
const email = ref('')
const password = ref('')
const message = ref('')
const handleregister = async () => {
const { error } = await $supabase.auth.signup({
email: email.value,
password: password.value,
})
if (error) {
message.value = error.message
} else {
message.value = 'success! please check your email to confirm your account.'
}
}
</script>
creating a login page
similarly, create /pages/login.vue for existing users to sign in.
<template>
<div>
<h2>welcome back</h2>
<form @submit.prevent="handlelogin">
<input v-model="email" type="email" placeholder="email" required />
<input v-model="password" type="password" placeholder="password" required />
<button type="submit">sign in</button>
</form>
<p v-if="errormessage">{{ errormessage }}</p>
</div>
</template>
<script setup>
const { $supabase } = usenuxtapp()
const router = userouter()
const email = ref('')
const password = ref('')
const errormessage = ref('')
const handlelogin = async () => {
const { error } = await $supabase.auth.signinwithpassword({
email: email.value,
password: password.value,
})
if (error) {
errormessage.value = error.message
} else {
router.push('/dashboard') // redirect to a protected page on success
}
}
</script>
step 4: managing auth state and protecting routes
this is a critical part of the full-stack integration. we need to know if a user is logged in and block access to certain pages if they are not.
using a composable for auth state
create a composable to easily access the current user's session. create the file /composables/useauthstate.ts.
import { ref } from 'vue'
export const useauthstate = () => {
const user = ref(null)
const { $supabase } = usenuxtapp()
// fetch the initial session
$supabase.auth.getsession().then(({ data: { session } }) => {
user.value = session?.user ?? null
})
// listen for auth state changes (login, logout, token refresh)
$supabase.auth.onauthstatechange((event, session) => {
user.value = session?.user ?? null
})
return { user }
}
protecting pages with middleware
nuxt's middleware is perfect for route protection. create a file /middleware/auth.global.ts. the .global suffix means it runs on every route change.
export default definenuxtroutemiddleware((to, from) => {
const { $supabase } = usenuxtapp()
// get the current session. this is a client-side check.
const session = $supabase.auth.getsession()
// if there's no session and the user is trying to access a protected page...
if (!session && to.path !== '/login' && to.path !== '/register') {
// ...redirect them to the login page.
return navigateto('/login')
}
})
for a more robust solution, you should check the session on the server side as well, especially for initial page loads.
step 5: adding a logout functionality
a logout button is essential. you can place this in a navigation component.
<template>
<nav>
<nuxtlink to="/dashboard">dashboard</nuxtlink>
<button @click="handlelogout">log out</button>
</nav>
</template>
<script setup>
const { $supabase } = usenuxtapp()
const router = userouter()
const handlelogout = async () => {
await $supabase.auth.signout()
router.push('/login')
}
</script>
next steps and advanced topics
congratulations! you now have a working authentication system. but there's more you can explore to level up your devops and full-stack skills:
- row level security (rls): this is supabase's killer feature. write sql policies to ensure users can only access their own data. this is fundamental for security.
- social logins: supabase makes it easy to add "login with google" or "login with github" with just a few lines of code.
- deploying your app: learn how to deploy your nuxt + supabase app to platforms like vercel or netlify. properly setting environment variables in your deployment pipeline is a key devops practice.
- testing auth flows: write end-to-end tests using tools like cypress to ensure your authentication and protected routes work as expected.
frequently asked questions (faq)
is supabase free to use?
yes! supabase has a generous free tier that is perfect for development, prototyping, and small projects. you only need to pay when your project scales beyond the free limits.
can i use supabase auth with nuxt 2?
absolutely. the principles are very similar. the main differences will be in the setup: you'd use nuxt 2 plugins and the composition api plugin if you're not using nuxt 2.12+.
how does this help with seo?
while authentication itself is user-side, a well-built app with fast page loads (which nuxt excels at) and great user engagement (thanks to secure, personalized experiences) signals quality to search engines. the technical seo foundation of your site remains crucial.
by following this guide, you've taken a significant step in your journey as a full-stack developer. you've implemented a core application feature using modern tools and best practices. keep coding, keep building, and explore the powerful combination of nuxt.js and supabase further!
Comments
Share your thoughts and join the conversation
Loading comments...
Please log in to share your thoughts and engage with the community.