In this lesson, we'll create a new Next.js application, and add the Supabase client to our project. We'll also look at how Supabase authorizes applications using client keys, and cover some things you need to know about securely using Supabase in your applications.
Kristian Freeman: [0:00] Let's create a new Next.js project, which we'll use to start working on our first Supabase-powered application. To do this, we'll use npx create-next-app, passing in our application name, which is Supabase chat server.
[0:12] Install a dependency real quick, and then you'll see it'll run through all of the project dependencies that it needs, like React, ReactDOM, and Next. When it's done, you'll have a ready-to-go Next.js application.
[0:23] Now, it's time to install the Supabase JavaScript client. To do this, we'll run npm install @supabase/supabase-js. In order to work with the Supabase-js client inside of our project, we need to set up a new file that will store our environment variables for accessing our personal Supabase instance.
[0:42] You can do this by creating a new file called .env.local. Here. I'll use the touch command in my command line. You can also do this in the VSCode sidebar as well. The .env.local file is where you'll store local environment variables for your project. You can set up something similar for production or for development as many of these other environments as you might have.
[1:04] Since we're just running this locally right now, we'll just make .env.local. The two environment variables that we need to store here are our Supabase URL and our Supabase API key.
[1:15] If we come back into our Supabase Dashboard and go to our settings page, and go to the API section, you can see that there is the URL here, which is the restful endpoint for querying and managing your database as well as two sets of API keys.
[1:29] One is the anon or public API key which we can use in browser. This will be the one that we will copy. The second is the service_role or secret, which allows you to basically have administrator level access and bypass any security in your Supabase project.
[1:45] It's very highly recommended that you pretty much always use this key as much as possible, though for some background tasks or something that you feel are running securely.
[1:55] Say in a note instance on a server or something like that, you can use this key some times. Though I would really recommend as much as possible, you try and use this anon public key.
[2:04] First, let's copy our Supabase URL and back in .env.local will make our first environment variable NEXT_PUBLIC_SUPABASE_URL. We'll also come back and grab our anon/public API key which I'll copy. I'll paste here as NEXT_PUBLIC_SUPABASE_API_KEY.
[2:28] Again, both of these environment variables are prefixed with NEXT_PUBLIC_, which will make them available to be used inside of the browser in our Next.js application. Let's save this file and create a new file called utils/useSupabase.js.
[2:43] This is going to contain the code for working with our Supabase client. To start, I'm going to import the create client function from the Supabase-js SDK. I'll import create client from @supabase/supabase-js.
[2:58] Then I'll create a new variable called Supabase. I'll just call that create client here, with the two variables I need to pass in the URL, as well as the API key. In our create client function call, we need to pass in two things, our URL and our API key.
[3:17] These are those two environment variables that we just set up. Next public Supabase URL and Next public Supabase API key. I'm just going to copy this here. Next public Supabase URL. I'm going to say process.env, which is going to refer to the environment for our running application.
[3:36] Then paste in Next public Supabase URL, as well as the same for our API key. Process.env.next public Supabase API key. That will be the two things we need to create our Supabase client.
[3:53] Now, we created a Supabase client based on our URL and API key that can be used to make requests and update data from JavaScript to our Supabase instance. Now that we've set up our Supabase client, we can actually use it in our application by setting up a useSupabase hook.
[4:09] Create a new function called useSupabase. Inside of it we'll set up a new useState hook. useState is a function from React that returns an array with two things inside of it. The actual value that you want to refer to and then a function for updating that value.
[4:25] In this case, we'll be using session. I'll call it session and set session. Then inside of the useState function itself, we need to pass a initial value. In this case, I'm going to use Supabase's session function to return a instance of our current session.
[4:41] I'll say Supabase.auth.session and then call that function. Now we have a session which is based on our Supabase auth session.
[4:50] This is going to be a way for us just to refer to our session more easily inside of our code that contains all the information about, for instance, if our user is logged in, what that user's ID is, and things like that.
[5:02] Now, when something changes in our auth session, that is, if I login or logout or any change to the session information, I need to handle that change and update the session variable here with the new information.
[5:15] To do that, I'm going to attach a new event based on this on auth state change. This is just going to be a function. Here you can see the callback function that has two arguments. One is event, which is prefixed with an underscore here because we aren't using it, and then session which represents our new session. Inside of that, I can use this set session function to just update my session anytime that there is an auth state change.
[5:42] If I login or logout or anything else, this session variable that's coming from that event will be used to update the instance of session that I have inside of this useState. We also want to make sure to import useState here. Let's import useState from React.
[5:59] That will allow us to actually use that function. Now with that, it's time to return the session information from this function. I'll return an object. Inside of that, I'm just going to return session, which is the session that is being stored and updated inside of this hook.
[6:19] Then I also want to return Supabase which is just the Supabase client that we set up here earlier. Again, I've set up this function called useSupabase, which is a custom hook that we've defined. I've set up a variable called session here, which gets updated using set session.
[6:34] Then any time that there's an auth state change here with Supabase, I just update the session variable here and then return it back as part of this hook along with the Supabase client itself.
[6:45] Now with all of that, I can get ready to export this useSupabass function as the default export for this code. I'll say export default useSupabase. Now with this set up, we need to import it and use it inside of our code. Let's open up pages/app.js.
[7:05] Actually, while we're here, let's just delete this API folder. We won't be needing it. In app.js, we can import our useSupabase function. I'll say, import useSupabase from ../ going up one directory and then utils/useSupabase. With that imported, we need to actually use it.
[7:27] Here inside of our function for our application, which basically just gets ready to return whatever the component is that's being rendered, I'm just going to say const. Then I'm going to set up a destructuring object here where I'm going to get session and Supabase.
[7:44] That is going to come from useSupabase, which is the function that we just set up. I import this useSupabase function and I call it down here below. Then I get access to the session and Supabase.
[7:56] Now here inside of the component, I just want to pass those as props to this component, whatever this component may be. I'll say session = session, and Supabase = Supabase. I just pass that in as props into this component.
[8:14] Whenever I use something like index.js, which is a different page, I'll have access to the session and the Supabase client inside of that. Let's come in here.
[8:26] To show what that looks like, we'll just come into the function definition here where there's currently no function arguments. We'll just destructure session and Supabase out of the props that are being passed into this function. We won't quite use these yet.
[8:44] We'll come back here and begin using them to provide some authorization functionality, but we can have access to them because they're being passed in as props into this component.