
Build a money-tracking app with Vue 3 and Quasar powered by Supabase, implementing read, add, update, and delete, real-time updates, authentication for multiple users, row-level security, storage, and edge functions.
Configure VS Code on Mac with zsh for a Supabase and Vue three project, using extensions like auto rename tag, split HTML attributes, and Vue three support.
Debug your Vue.js views and code using Chrome with the Vue.js DevTools extension, installed from the Chrome Web Store, using the non-legacy, non-beta version to get started.
Download and extract the starter moneyballs app, load the folder into VS Code, open the terminal, run npm install, then run Quasar dev to view the app in the browser.
Moneyballs overview introduces a money management app that adds income and expense entries, shows a live balance in green and red, and supports editing, sorting, paid status, and deletion.
Explore Supabase as an open source Firebase alternative, featuring PostgreSQL, authentication, edge functions, storage, real-time, and RESTful APIs for a scalable backend.
Compare Supabase and Firebase, noting both provide database, authentication, cloud functions, storage and real-time features; Firebase offers app hosting and proprietary NoSQL databases, while Supabase uses PostgreSQL with self-hosting options.
Create a Supabase project for Moneyballs app, configuring a database with entry CRUD, authentication, row-level security, avatar storage, and edge functions; note the project URL and API key to connect.
Install the Supabase API in the Moneyballs project, set up environment variables via Quasar config, and export a ready-to-use client for database and authentication.
Set up a Supabase database and an entries table, disable row level security, switch the id to uuid, add name, amount, and paid columns, and display entries in Moneyballs.
Display entries from the Supabase entries table in Moneyballs and enable real-time updates across devices, while refactoring the store to load entries from Supabase into state and drop local storage.
Display entries from the Supabase entries table on Moneyballs page by importing the Supabase client, using the from method to query all rows, and binding results to the entries ref.
Learn to handle Supabase errors in a Vue 3 app by logging errors, simulating failures, and using a reusable composable to display error dialogs with Quasar.
Enable real time for the entries table and subscribe to all changes to fetch initial data from Supabase and listen for inserts, updates, or deletes.
Handle the insert event from the entries subscription by pushing payload.new into the entries ref in state to update and display the new entry.
Handle real-time deletions from Supabase by detecting the delete event, removing the corresponding entry from the local entries array via its ID, and updating the user interface instantly.
Handle real-time update events from Supabase by updating the matching local entry with payload data using the entry id, then reflect changes in the Vue 3 UI.
Implement a real-time loading screen for entries by introducing a loading state, replacing the no-entries widget with a centered Quasar spinner during the initial data fetch from Supabase.
Learn to perform create, update, and delete actions on the Supabase entries table from a Vue 3 app, using real-time updates to sync the UI via a subscription.
learn to delete an entry in a Vue 3 app using Supabase by deleting the database row with a matching ID, and sync local state via real-time updates.
Update the entry by sending an updates object to Supabase, targeting the row with the entry ID, and handle errors asynchronously with a dialog.
Improve performance in a Supabase and Vue 3 app by updating the local entries array before sending the update, eliminating flicker and delivering a Firebase-style instant experience.
Learn how to handle update errors for a local entries array backed by Supabase, creating a non-reactive copy via JSON stringify/parse to revert changes when updates fail.
Add an order column to the entries table and order by this column in the Supabase query, updating order numbers via Pinia for a Vue 3 app.
Use a generate order number helper to compute the next order by taking the max of existing orders and adding one, collecting orders via map from entries.
Learn to assign the correct order number for new entries in a Supabase-backed Vue 3 app using Quasar and Pinia, handling the first entry by defaulting to one.
Update the order numbers in the Supabase entries table after a drag-and-drop sort to reflect the new local order, ensuring persistence and visible sequencing.
Update order numbers on Supabase by batching an upsert of local entries mapped to id and order, ensuring the server matches the drag-and-drop sort and handling errors.
Set up an authentication page with email and password for register or log in, and create a dedicated auth layout without header or navigation; route it to /auth.
Add a card with an email and a password form and submit button, centered, styled with minimum width, primary background, white text, and large padding; create a reusable toolbar title.
Add two quasar tabs for login and register, wiring a tab ref and labels, remove icons, enforce lowercase labels, and set the default tab to login for the form.
Learn to build a login form with email and password inputs using Quasar form components, add autocomplete and styling, and wire the submit button to navigate between auth and entries.
Demonstrates adjusting a login form for dark mode by using a light-or-dark composable to switch input bgcolor and text colors, ensuring white in light mode and black in dark mode.
connects a login and register form by dynamically updating the submit button label using a computed property in Vue 3, showing login or register based on the active tab.
Create a credentials reactive object to store email and password, import reactive from Vue, bind inputs with credentials.email and credentials.password, and reset to empty strings.
Add a submit method triggered on form submission, wire it to the queue form component, and set the button to type submit while logging form submitted with email and password.
Implement a basic validation that requires both email and password, and show a quasar error dialog when either is missing by using the use quasar composable and dialog plugin.
Trigger the formSubmitSuccess method to differentiate login or register flows by the active tab, logging credentials and routing to login or register handlers.
Import the Vue router's use router, create a router constant, and push the path '/' after a successful submission to return to the entries page and enable authentication.
Enable supabase authentication to allow users to register, log in, and log out, and store the current user's email and user ID with redirects based on auth state.
Learn how to implement user registration with Supabase in a Vue 3 app, including creating a register action in the auth store, handling errors, and persisting login after signup.
Learn to log out a user with Supabase auth sign out by wiring an auth store action. Show error dialogs on failure and trigger from the drawer logout button.
Configure the login tab on the auth page and create a login user action in the auth store using sign in with password. Verify success and error flows.
Store the user’s unique ID in the app store and listen for auth changes with a single hook to handle signed in, signed out, and initial session events.
Store user email and id in a reactive auth store, update on the auth state change, and reset to default values with Object.assign in a Vue 3 app.
Enhance the logout button in the main layout drawer by displaying the logged-in user's email from the auth store, using conditional rendering and styling with Quasar components.
Redirect users on auth state changes: on login to the entries page, on logout to the auth page, using router push for login and router replace for logout.
Modify the Supabase entries table to support multiple users by adding a user_id UUID and filtering entries by that ID, enabling Moneyballs to work for every user.
Load only the current user’s entries in a Vue 3 app using Supabase, Quasar, and Pinia by filtering with the authenticated user id and handling login state.
Subscribe to changes in the entries table for the currently logged-in user by applying a filter on user_id with the auth store. Watch real-time updates reflect only that user's entries.
Assign the current user's unique id from the auth store to the user_id field when adding a new entry. Link each entry to its creator across multi-user sessions.
Clear the entries array on user logout to prevent exposing data, by adding a clear entries action in the Pinia store and invoking it from the auth store after sign-out.
Learn to unsubscribe from the real-time entries subscription on user logout, using a remove channel action in the auth flow to prevent updates after sign-out.
protect the Moneyballs app routes with a global before guard in a Quasar boot file, ensuring logged-in users access entries and unauthenticated users see auth.
Implement a beforeEach navigation guard that redirects non-authenticated users to the auth page by checking store auth.user details.id and path, and prevents access for logged-in users to /auth.
See how to secure the entries table with row level security and policies so each user can read, update, or delete only their own data, demonstrated with Jim and Steve.
Learn how to enable row level security (RLS) for the entries table and create read, insert, update, and delete policies in the Supabase console, using templates to simplify setup.
Create a select policy to let authenticated users view only their own data in the entries table by matching the auth uuid to the user_id column.
Explore an insert policy in Supabase using row-level security (rls). Learn to allow inserts on the entries table only when the user_id matches the currently logged-in user, demonstrated with Jim.
The delete policy in Supabase uses row-level security to allow users to delete only rows where user_id matches their id, via the delete for users based on user ID template.
Learn to implement an update policy with row level security (RLS) in Supabase, allowing updates only when the authenticated user's UID matches the user_id in the entries table.
Add the user_id to the upsert payload to satisfy the row level security policy and fix the upsert issue when reordering entries under the LRS rules.
In this course, you'll learn how to connect a Quasar 2 app (with Vue 3 & Pinia) to a Supabase backend.
You'll start by downloading and launching the course app, Moneyballs (from my course Vue 3: Create a Mobile & Desktop App (with Quasar 2 & Pinia).
You'll connect Moneyballs to a Supabase Database and add full CRUD capabilities for one user:
Read and display Entries from Supabase
Add Entry
Delete Entry
Update Entry
Reorder Entries
Realtime Updates
You'll then create an Auth page where a user can login & register and setup Supabase Authentication:
Register User
Logout User
Login User
Listen for Auth Changes
Redirect the User on Login & Logout
You'll then add support for Multiple Users and add security to the app:
Navigation Guards
Supabase Row Level Security (RLS) & Policies
Next you'll learn about Database Functions & Triggers, you will:
Create a Database Function which keeps track of the total number of entries created with Moneyballs
Learn how to fire the Database Function straight from Moneyballs
Create a Trigger which fires this Database Function (automatically) every time any user adds a new entry
You'll learn about Supabase Storage, you will:
Create an Avatars Storage Bucket
Allow each user to upload an Avatar
Display the Avatar within Moneyballs
Next you'll learn how to take your entire Supabase instance and run it locally, you'll:
Install Supabase locally
Import all Database Tables & Data from the Live Supabase instance
Learn how to make changes to the Database locally
Learn how to push these changes to the Live instance
You'll then learn about Edge Functions, you will:
Create an Edge Function (locally) which displays a random greeting to the user
Access Auth and the Database in the Edge Function, so that we can display the user's total number of entries in the greeting
Deploy the local Edge Function to the Live Supabase instance
Finally, you'll build the app for production and get it working on 5 platforms:
Web browser
iOS
Android
Mac
Windows
For this course, I recommend:
Having completed my course Vue 3: Create a Mobile & Desktop App (with Quasar 2 & Pinia)
Using a Mac
Having a basic understanding of Vue 3 (Composition API), Quasar, Pinia & JavaScript