Skip to content

Commit e6e24aa

Browse files
docs: Update user management docs for next JS (supabase#37664)
* Draft * Update text for guide * Update text for guide * Update code for newer next js versions * Final small change * Update apps/docs/content/_partials/project_setup.mdx Co-authored-by: Charis <[email protected]> * Changes from review * Use project name in tutorial text * Fix up inclusion * Fix inclusion * Prettier --------- Co-authored-by: Charis <[email protected]>
1 parent a61927e commit e6e24aa

File tree

19 files changed

+4527
-2286
lines changed

19 files changed

+4527
-2286
lines changed

apps/docs/content/_partials/project_setup.mdx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,13 @@ Now set up the database schema. You can use the "User Management Starter" quicks
2222
<TabPanel id="dashboard" label="Dashboard">
2323

2424
1. Go to the [SQL Editor](https://supabase.com/dashboard/project/_/sql) page in the Dashboard.
25-
2. Click **User Management Starter**.
25+
2. Click **User Management Starter** under the **Community > Quickstarts** tab.
2626
3. Click **Run**.
2727

2828
<Admonition type="note">
2929

3030
You can pull the database schema down to your local project by running the `db pull` command. Read the [local development docs](/docs/guides/cli/local-development#link-your-project) for detailed instructions.
3131

32-
{/* TODO: discuss */}
33-
3432
```bash
3533
supabase link --project-ref <project-id>
3634
# You can get <project-id> from your project's dashboard URL: https://supabase.com/dashboard/project/<project-id>

apps/docs/content/_partials/quickstart_intro.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ This tutorial demonstrates how to build a basic user management app. The app aut
22

33
- [Supabase Database](/docs/guides/database) - a Postgres database for storing your user data and [Row Level Security](/docs/guides/auth#row-level-security) so data is protected and users can only access their own information.
44
- [Supabase Auth](/docs/guides/auth) - allow users to sign up and log in.
5-
- [Supabase Storage](/docs/guides/storage) - users can upload a profile photo.
5+
- [Supabase Storage](/docs/guides/storage) - allow users to upload a profile photo.

apps/docs/content/guides/getting-started/tutorials/with-nextjs.mdx

Lines changed: 34 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ If you get stuck while working through this guide, refer to the [full example on
1717

1818
## Building the app
1919

20-
Let's start building the Next.js app from scratch.
20+
Start building the Next.js app from scratch.
2121

2222
### Initialize a Next.js app
2323

24-
We can use [`create-next-app`](https://nextjs.org/docs/getting-started) to initialize an app called `supabase-nextjs`:
24+
Use [`create-next-app`](https://nextjs.org/docs/getting-started) to initialize an app called `supabase-nextjs`:
2525

2626
<Tabs
2727
scrollable
@@ -54,8 +54,7 @@ Then install the Supabase client library: [supabase-js](https://github.com/supab
5454
npm install @supabase/supabase-js
5555
```
5656

57-
And finally we want to save the environment variables in a `.env.local`.
58-
Create a `.env.local` file at the root of the project, and paste the API URL and the `anon` key that you copied [earlier](#get-the-api-keys).
57+
Save the environment variables in a `.env.local` file at the root of the project, and paste the API URL and the `anon` key that you copied [earlier](#get-the-api-keys).
5958

6059
```bash .env.local
6160
NEXT_PUBLIC_SUPABASE_URL=YOUR_SUPABASE_URL
@@ -65,13 +64,13 @@ NEXT_PUBLIC_SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEY
6564
### App styling (optional)
6665

6766
An optional step is to update the CSS file `app/globals.css` to make the app look nice.
68-
You can find the full contents of this file [here](https://raw.githubusercontent.com/supabase/supabase/master/examples/user-management/nextjs-user-management/app/globals.css).
67+
You can find the full contents of this file [in the example repository](https://raw.githubusercontent.com/supabase/supabase/master/examples/user-management/nextjs-user-management/app/globals.css).
6968

7069
### Supabase Server-Side Auth
7170

7271
Next.js is a highly versatile framework offering pre-rendering at build time (SSG), server-side rendering at request time (SSR), API routes, and middleware edge-functions.
7372

74-
To better integrate with the framework, we've created the `@supabase/ssr` package for Server-Side Auth. It has all the functionalities to quickly configure your Supabase project to use cookies for storing user sessions. See the [Next.js Server-Side Auth guide](/docs/guides/auth/server-side/nextjs) for more information.
73+
To better integrate with the framework, we've created the `@supabase/ssr` package for Server-Side Auth. It has all the functionalities to quickly configure your Supabase project to use cookies for storing user sessions. Read the [Next.js Server-Side Auth guide](/docs/guides/auth/server-side/nextjs) for more information.
7574

7675
Install the package for Next.js.
7776

@@ -184,11 +183,11 @@ Since Server Components can't write cookies, you need middleware to refresh expi
184183
- Passing the refreshed Auth token to Server Components through `request.cookies.set`, so they don't attempt to refresh the same token themselves.
185184
- Passing the refreshed Auth token to the browser, so it replaces the old token. This is done with `response.cookies.set`.
186185

187-
You could also add a matcher, so that the middleware only runs on route that access Supabase. For more information, check out this [documentation](https://nextjs.org/docs/app/building-your-application/routing/middleware#matching-paths).
186+
You could also add a matcher, so that the middleware only runs on routes that access Supabase. For more information, read [the Next.js matcher documentation](https://nextjs.org/docs/app/api-reference/file-conventions/middleware#matcher).
188187

189188
<Admonition type="danger">
190189

191-
Be careful when protecting pages. The server gets the user session from the cookies, which can be spoofed by anyone.
190+
Be careful when protecting pages. The server gets the user session from the cookies, which anyone can spoof.
192191

193192
Always use `supabase.auth.getUser()` to protect pages and user data.
194193

@@ -358,17 +357,17 @@ meta="name=app/login/page.tsx"
358357

359358
</Tabs>
360359

361-
Navigate to `http://localhost:3000/login`. You should see your login form, but it's not yet hooked up to the actual login function. Next, you need to create the login/signup actions. They will:
360+
Next, you need to create the login/signup actions to hook up the form to the function. Which does the following:
362361

363362
- Retrieve the user's information.
364-
- Send that information to Supabase as a signup request, which in turns will send a confirmation email.
363+
- Send that information to Supabase as a signup request, which in turns sends a confirmation email.
365364
- Handle any error that arises.
366365

367366
<Admonition type="caution">
368367

369-
Note that cookies is called before any calls to Supabase, which opts fetch calls out of Next.js's caching. This is important for authenticated data fetches, to ensure that users get access only to their own data.
368+
The `cookies` method is called before any calls to Supabase, which takes fetch calls out of Next.js's caching. This is important for authenticated data fetches, to ensure that users get access only to their own data.
370369

371-
See the Next.js docs to learn more about [opting out of data caching](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#opting-out-of-data-caching).
370+
Read the Next.js docs to learn more about [opting out of data caching](https://nextjs.org/docs/app/building-your-application/data-fetching/fetching-caching-and-revalidating#opting-out-of-data-caching).
372371

373372
</Admonition>
374373

@@ -382,6 +381,8 @@ See the Next.js docs to learn more about [opting out of data caching](https://ne
382381

383382
<TabPanel id="js" label="JavaScript">
384383

384+
Create the `action.js` file in the `app/login` folder, which contains the login and signup functions and the `error/page.jsx` file, and displays an error message if the login or signup fails.
385+
385386
<$CodeTabs>
386387

387388
```js name=app/login/actions.js
@@ -409,7 +410,6 @@ export async function login(formData) {
409410
}
410411

411412
revalidatePath('/', 'layout')
412-
redirect('/account')
413413
}
414414

415415
export async function signup(formData) {
@@ -427,7 +427,6 @@ export async function signup(formData) {
427427
}
428428

429429
revalidatePath('/', 'layout')
430-
redirect('/account')
431430
}
432431
```
433432

@@ -443,6 +442,8 @@ export default function ErrorPage() {
443442

444443
<TabPanel id="ts" label="TypeScript">
445444

445+
Create the `action.ts` file in the `app/login` folder, which contains the login and signup functions and the `error/page.tsx` file, which displays an error message if the login or signup fails.
446+
446447
<$CodeTabs>
447448

448449
<$CodeSample
@@ -461,35 +462,31 @@ meta="name=app/error/page.tsx"
461462

462463
</TabPanel>
463464

464-
When you enter your email and password, you will receive an email with the title **Confirm Your Signup**. Congrats 🎉!!!
465-
466465
</Tabs>
467466

468467
### Email template
469468

470-
Change the email template to support a server-side authentication flow.
471-
472-
Before we proceed, let's change the email template to support sending a token hash:
469+
Before proceeding, change the email template to support support a server-side authentication flow that sends a token hash:
473470

474471
- Go to the [Auth templates](/dashboard/project/_/auth/templates) page in your dashboard.
475-
- Select `Confirm signup` template.
472+
- Select the **Confirm signup** template.
476473
- Change `{{ .ConfirmationURL }}` to `{{ .SiteURL }}/auth/confirm?token_hash={{ .TokenHash }}&type=email`.
477474

478475
<Admonition type="tip">
479476

480-
Did you know? You could also customize emails sent out to new users, including the email's looks, content, and query parameters. Check out the [settings of your project](/dashboard/project/_/auth/templates).
477+
**Did you know?** You can also customize other emails sent out to new users, including the email's looks, content, and query parameters. Check out the [settings of your project](/dashboard/project/_/auth/templates).
481478

482479
</Admonition>
483480

484481
### Confirmation endpoint
485482

486-
As we are working in a server-side rendering (SSR) environment, it is necessary to create a server endpoint responsible for exchanging the `token_hash` for a session.
483+
As you are working in a server-side rendering (SSR) environment, you need to create a server endpoint responsible for exchanging the `token_hash` for a session.
487484

488-
In the following code snippet, we perform the following steps:
485+
The code performs the following steps:
489486

490-
- Retrieve the code sent back from the Supabase Auth server using the `token_hash` query parameter.
491-
- Exchange this code for a session, which we store in our chosen storage mechanism (in this case, cookies).
492-
- Finally, we redirect the user to the `account` page.
487+
- Retrieves the code sent back from the Supabase Auth server using the `token_hash` query parameter.
488+
- Exchanges this code for a session, which you store in your chosen storage mechanism (in this case, cookies).
489+
- Finally, redirects the user to the `account` page.
493490

494491
<Tabs
495492
scrollable
@@ -505,7 +502,6 @@ In the following code snippet, we perform the following steps:
505502

506503
```js name=app/auth/confirm/route.js
507504
import { NextResponse } from 'next/server'
508-
509505
import { createClient } from '@/utils/supabase/server'
510506

511507
// Creating a handler to a GET request to route /auth/confirm
@@ -562,9 +558,9 @@ meta="name=app/auth/confirm/route.ts"
562558

563559
### Account page
564560

565-
After a user is signed in we can allow them to edit their profile details and manage their account.
561+
After a user signs in, allow them to edit their profile details and manage their account.
566562

567-
Let's create a new component for that called `AccountForm` within the `app/account` folder.
563+
Create a new component for that called `AccountForm` within the `app/account` folder.
568564

569565
<Tabs
570566
scrollable
@@ -589,7 +585,6 @@ export default function AccountForm({ user }) {
589585
const [fullname, setFullname] = useState(null)
590586
const [username, setUsername] = useState(null)
591587
const [website, setWebsite] = useState(null)
592-
const [avatar_url, setAvatarUrl] = useState(null)
593588

594589
const getProfile = useCallback(async () => {
595590
try {
@@ -609,7 +604,6 @@ export default function AccountForm({ user }) {
609604
setFullname(data.full_name)
610605
setUsername(data.username)
611606
setWebsite(data.website)
612-
setAvatarUrl(data.avatar_url)
613607
}
614608
} catch (error) {
615609
alert('Error loading user data!')
@@ -631,7 +625,6 @@ export default function AccountForm({ user }) {
631625
full_name: fullname,
632626
username,
633627
website,
634-
avatar_url,
635628
updated_at: new Date().toISOString(),
636629
})
637630
if (error) throw error
@@ -680,7 +673,7 @@ export default function AccountForm({ user }) {
680673
<div>
681674
<button
682675
className="button primary block"
683-
onClick={() => updateProfile({ fullname, username, website, avatar_url })}
676+
onClick={() => updateProfile({ fullname, username, website })}
684677
disabled={loading}
685678
>
686679
{loading ? 'Loading ...' : 'Update'}
@@ -719,7 +712,7 @@ meta="name=app/account/account-form.tsx"
719712
720713
</Tabs>
721714
722-
Create an account page for the `AccountForm` component we just created
715+
Create an account page for the `AccountForm` component you just created
723716
724717
<Tabs
725718
scrollable
@@ -769,7 +762,7 @@ meta="name=app/account/page.tsx"
769762
770763
### Sign out
771764
772-
Let's create a route handler to handle the signout from the server side. Make sure to check if the user is logged in first!
765+
Create a route handler to handle the sign out from the server side, making sure to check if the user is logged in first.
773766
774767
<Tabs
775768
scrollable
@@ -829,13 +822,15 @@ meta="name=app/auth/signout/route.ts"
829822
830823
### Launch!
831824
832-
Now that we have all the pages, route handlers and components in place, let's run this in a terminal window:
825+
Now you have all the pages, route handlers, and components in place, run the following in a terminal window:
833826
834827
```bash
835828
npm run dev
836829
```
837830
838-
And then open the browser to [localhost:3000](http://localhost:3000) and you should see the completed app.
831+
And then open the browser to [localhost:3000/login](http://localhost:3000/login) and you should see the completed app.
832+
833+
When you enter your email and password, you will receive an email with the title **Confirm Your Signup**. Congrats 🎉!!!
839834
840835
## Bonus: Profile photos
841836
@@ -844,7 +839,7 @@ photos and videos.
844839
845840
### Create an upload widget
846841
847-
Let's create an avatar widget for the user so that they can upload a profile photo. We can start by creating a new component:
842+
Create an avatar widget for the user so that they can upload a profile photo. Start by creating a new component:
848843
849844
<Tabs
850845
scrollable
@@ -970,7 +965,7 @@ meta="name=app/account/avatar.tsx"
970965
971966
### Add the new widget
972967
973-
And then we can add the widget to the `AccountForm` component:
968+
Then add the widget to the `AccountForm` component:
974969
975970
<Tabs
976971
scrollable

0 commit comments

Comments
 (0)