Supabase in Vue Made Simple
Supabase has become one of the most popular choices for building modern web applications. It gives you: - PostgreSQL database - Authentication - Realtime subscriptions - Storage - Edge Functions - TypeScript support The official Supabase JavaScript client already makes it relatively easy to use these features from a Vue application. But integrating Supabase into a Vue application usually means creating a client and then making it available throughout your application. This is where the new @supabase-community/vue-supabase package comes in. The package provides a Vue-friendly integration for Supabase, allowing you to access your Supabase client through useSupabaseClient() while keeping the familiar Supabase API. You can check out the package on GitHub here: https://github.com/supabase-community/vue-supabase In this article, we'll explore: - What @supabase-community/vue-supabase is - How to install and configure it - How to query your database - How to use TypeScript with it - How to handle authentication - How to use Supabase Realtime - How to structure Supabase logic using Vue composables - What security considerations you need to remember Let's dive in. ๐ค What Is @supabase-community/vue-supabase ? @supabase-community/vue-supabase is a Vue integration for Supabase that provides a convenient way to access the Supabase client inside your Vue application. The main API you'll use is: import { useSupabaseClient } from '@supabase-community/vue-supabase' const supabase = useSupabaseClient() Once you have the client, you can use the standard Supabase API: const { data, error } = await supabase .from('profiles') .select('') This is important because the package doesn't introduce a completely new way of working with Supabase. You still use the APIs you're familiar with: supabase.from() supabase.auth supabase.channel() supabase.storage The package mainly provides the Vue integration layer around them. ๐ข Installing and Configuring the Package The package can be installed with: npm install @supabase-community/vue-supabase You can then configure your Supabase client using your project URL and key. For example: VITE_SUPABASE_URL=https://your-project.supabase.co VITE_SUPABASE_ANON_KEY=your-publishable-key And then: import { useSupabaseClient } from '@supabase-community/vue-supabase' const supabase = useSupabaseClient({ supabaseUrl: import.meta.env.VITE_SUPABASE_URL, supabaseKey: import.meta.env.VITE_SUPABASE_ANON_KEY, }) The important part is that you don't need to install or configure a separate Supabase Vue SDK. The package provides the integration you need. ๐ข Querying Your Database Let's say you have a profiles table: profiles โโโ id โโโ name โโโ email You can query it directly from a Vue component: import { useSupabaseClient } from '@supabase-community/vue-supabase' const supabase = useSupabaseClient() const { data, error } = await supabase .from('profiles') .select('') {{ profile.name }} The nice thing is that once you have the client, you're using the standard Supabase query API. You can filter, sort, insert, update, and delete data exactly as you normally would with Supabase. For example: const { data, error } = await supabase .from('profiles') .select('id, name') .eq('active', true) .order('name') This makes the package easy to adopt even if you're already familiar with Supabase. ๐ข TypeScript Support TypeScript becomes especially important when your Supabase project grows. Supabase can generate TypeScript definitions directly from your database schema. For example: npx supabase gen types typescript \ --project-id \ --schema public \ > src/types/supabase.ts You can then use your generated Database type with the Supabase client: import { useSupabaseClient } from '@supabase-community/vue-supabase' import type { Database } from './types/supabase' const supabase = useSupabaseClient () Now TypeScript knows about your database structure. For example: const { data } = await supabase .from('profiles') .select('id, name') The returned data can now be typed according to your actual database schema. This is particularly useful because it moves your database schema closer to your application's type system. Instead of manually maintaining interfaces such as: interface Profile { id: string name: string } you can generate them from the actual database. ๐ข Authentication Supabase Authentication is available through the same client. For example, you can sign in a user with email and password: const supabase = useSupabaseClient() const { data, error } = await supabase.auth .signInWithPassword({ email: 'u***@example.com', password: 'password', }) You can also create a new account: const { data, error } = await supabase.auth .signUp({ email: 'u***@example.com', password: 'password', }) And signing out is just as simple: await supabase.auth.signOut() You can access the currently authenticated user with: const { data: { user }, } = await supabase.auth.getUser() The important thing here is that the Vue integration doesn't force you to learn a completely different authentication API. You're still working with: supabase.auth just like with the regular Supabase client. ๐ข Listening to Authentication Changes Supabase also provides an API for reacting to authentication changes. For example: const { data } = supabase.auth.onAuthStateChange( (event, session) => { console.log(event) console.log(session) } ) This can be useful for things like: - updating navigation - showing authenticated UI - handling logout - reacting to session changes In a larger application, this logic can be extracted into a composable or a dedicated authentication store. ๐ข Realtime Subscriptions One of the most interesting Supabase features is Realtime. Imagine you want your Vue application to react whenever a record in the profiles table changes. You can create a channel: const supabase = useSupabaseClient() const channel = supabase .channel('profiles-updates') .on( 'postgres_changes', { event: '*', schema: 'public', table: 'profiles', }, (payload) => { console.log('Change received:', payload) }, ) .subscribe() Now your application can react to: - inserts - updates - deletes without manually polling the database. This is useful for applications such as: - dashboards - chat applications - collaborative tools - notifications - live admin panels ๐ข Cleaning Up Realtime Subscriptions There's one important thing to remember when using Realtime inside Vue components. If you create a subscription when a component is mounted, you should also clean it up when the component is destroyed. For example: import { onUnmounted } from 'vue' onUnmounted(() => { supabase.removeChannel(channel) }) Without proper cleanup, you can accidentally create multiple active subscriptions when navigating between components. You might end up with: Component mounted โ Subscription created Component unmounted โ Subscription still exists Component mounted again โ Another subscription created Eventually, the same event might be handled multiple times. Always think about the lifecycle of your Realtime subscriptions. ๐ข Supabase Storage The same client can also be used for Supabase Storage. For example, uploading an image: const { data, error } = await supabase .storage .from('avatars') .upload('user-avatar.png', file) And you can retrieve a public URL: const { data } = supabase .storage .from('avatars') .getPublicUrl('user-avatar.png') This makes it possible to use Supabase as the backend for applications that need: - profile pictures - document uploads - media files - user-generated content without introducing another storage provider. ๐ข Don't Forget Row Level Security One thing that doesn't change when using this Vue integration is security. Your Vue application runs in the browser. That means anything included in your client-side application should be considered publicly accessible. You should never expose a Supabase service_role key in your Vue application. Instead, use the appropriate client-side key and protect your database using Row Level Security (RLS). For example: alter table profiles enable row level security; Then you can create policies that define exactly what users are allowed to access. For example: create policy "Users can read profiles" on profiles for select to authenticated using (true); The exact policy should depend on your application's requirements. The important concept is: ๐ The frontend is not a security boundary. Don't rely on Vue code to decide whether someone is allowed to access data. The database should enforce those rules. ๐งช Best Practices - Generate TypeScript types from your Supabase database schema - Always use Row Level Security to protect database access - Never expose a service_role key in client-side code - Clean up Realtime subscriptions when components are unmounted - Keep database logic out of your Vue components - Use the existing Supabase API instead of creating unnecessary abstractions - Keep authentication and data-access logic reusable through composables - Treat client-side environment variables as public ๐ 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: It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects ๐ ๐งช Advance skills A certification boosts your skills, builds credibility, and opens doors to new opportunities. Whether you're advancing your career or switching paths, it's a smart step toward success. Check out Certificates.dev by clicking this link or by clicking the image below: Invest in yourself-get certified in Vue.js, JavaScript, Nuxt, Angular, React, and more! โ Summary The new @supabase-community/vue-supabase package provides a simple way to integrate Supabase into Vue applications while keeping the familiar Supabase client API. The biggest advantage of the package is that it doesn't try to reinvent Supabase. Instead, it gives Vue developers a cle
Comments
No comments yet. Start the discussion.