Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Moved signin/up routes and user data each to their own pages #1270

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions docs/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -1760,7 +1760,18 @@
"title": "SPA Mode",
"wrap": false,
"href": "/docs/references/remix/spa-mode"
},
{
"title": "Add custom sign up and sign in pages",
"wrap": true,
"href": "/docs/references/remix/custom-signup-signin-pages"
},
{
"title": "Read session and user data",
"wrap": true,
"href": "/docs/references/remix/read-session-data"
}

]
]
},
Expand Down
221 changes: 31 additions & 190 deletions docs/quickstarts/remix.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,32 @@ description: Learn how to use Clerk to quickly and easily add secure authenticat

# Use Clerk with Remix

<TutorialHero
framework="remix"
exampleRepo={[
{
title: "Remixt Quickstart Repo",
link: "https://github.com/clerk/clerk-remix-quickstart"

}
]}
beforeYouStart={[
{
title: "Set up a Clerk application",
link: "https://clerk.com/docs/quickstarts/setup-clerk",
icon: "clerk",
}
]}
>
- Install `@clerk/remix`
- Set up your environment variables
- Configure rootAuthLoader
- Configure ClerkApp
- Protecting your pages
</TutorialHero>



Learn how to use Clerk to quickly and easily add secure authentication and user management to your Remix application. This guide assumes that you are using Remix v2 or later.

<Callout type="info">
Expand Down Expand Up @@ -160,55 +186,6 @@ function App() {
export default ClerkApp(App);
```

### Build your own sign-in and sign-up pages

In addition to the [Account Portal pages](/docs/account-portal/overview), Clerk also offers a set of [prebuilt components](/docs/components/overview) that you can use instead to embed sign-in, sign-up, and other user management functions into your Remix application. We are going to use the `<SignIn /> `and `<SignUp />` components by utilizing the Remix optional catch-all route.

The functionality of the components are controlled by the instance settings you specify in your [Clerk Dashboard](https://dashboard.clerk.com).

#### Build your sign-up page

```tsx filename="app/routes/sign-up.$.tsx"
import { SignUp } from "@clerk/remix";

export default function SignUpPage() {
return (
<div>
<h1>Sign Up route</h1>
<SignUp />
</div>
);
}
```

#### Build your sign-in page

```tsx filename="app/routes/sign-in.$.tsx"
import { SignIn } from "@clerk/remix";

export default function SignInPage() {
return (
<div>
<h1>Sign In route</h1>
<SignIn />
</div>
);
}
```

### Update your environment variables

Next, add environment variables for the `signIn`, `signUp`, `afterSignUp`, and `afterSignIn` paths:

```sh filename=".env"
CLERK_SIGN_IN_URL=/sign-in
CLERK_SIGN_UP_URL=/sign-up
CLERK_SIGN_IN_FALLBACK_URL=/
CLERK_SIGN_UP_FALLBACK_URL=/
```

These values control the behavior of the components when you sign in or sign up and when you click on the respective links at the bottom of each component.

### Protecting your pages

#### Client side
Expand All @@ -217,12 +194,13 @@ Clerk offers [Control Components](/docs/components/overview) that allow you to p

```tsx filename="routes/_index.tsx"
import {
SignInButton,
SignOutButton,
SignUpButton,
SignedIn,
SignedOut,
UserButton,
} from "@clerk/remix";
import { Link } from "@remix-run/react";

export default function Index() {
return (
Expand All @@ -231,7 +209,7 @@ export default function Index() {
<SignedIn>
<p>You are signed in!</p>
<div>
<p>View your profile here 👇</p>
<p>View your profile here</p>
<UserButton />
</div>
<div>
Expand All @@ -241,10 +219,10 @@ export default function Index() {
<SignedOut>
<p>You are signed out</p>
<div>
<Link to="/sign-in">Go to Sign in</Link>
<SignInButton />
</div>
<div>
<Link to="/sign-up">Go to Sign up</Link>
<SignUpButton />
</div>
</SignedOut>
</div>
Expand Down Expand Up @@ -280,145 +258,8 @@ export default function Index() {
}
```

### Read session and user data

Clerk provides a set of [hooks and helpers](/docs/references/react/use-user) that you can use to access the active session and user data in your Remix application. Here are examples of how to use these helpers.

#### Client side

#### `useAuth()`

The `useAuth` hook is a convenient way to access the current auth state. This hook provides the minimal information needed for data-loading and helper methods to manage the current active session.

```tsx filename="routes/example.tsx"
import { useAuth } from "@clerk/remix";

export default function Example() {
const { isLoaded, userId, sessionId, getToken } = useAuth();

// In case the user signs out while on the page.
if (!isLoaded || !userId) {
return null;
}

return (
<div>
Hello, {userId} your current active session is {sessionId}
</div>
);
}
```

#### `useUser()`

The `useUser` hook is a convenient way to access the current user data where you need it. This hook provides the user data and helper methods to manage the current active session.

```tsx filename="routes/example.tsx"
import { useUser } from "@clerk/remix";

export default function Example() {
const { isLoaded, isSignedIn, user } = useUser();

if (!isLoaded || !isSignedIn) {
return null;
}

return <div>Hello, {user.firstName} welcome to Clerk</div>;
}
```

#### Server side

#### `getAuth()`

<Tabs type="function" items={["Loader Function", "Action Function"]}>
<Tab>
The [`getAuth()`][get-auth] helper allows you to access the [`Auth` object](/docs/references/nextjs/auth-object), including the current `userId`. You can use this helper to protect your loader function or get data for the initial render of the route.

```tsx filename="routes/example.tsx"
export const loader: LoaderFunction = async (args) => {
// Use getAuth to retrieve user data
const { userId, sessionId, getToken } = await getAuth(args);

// If there is no userId, then redirect to sign-in route
if (!userId) {
return redirect("/sign-in?redirect_url=" + args.request.url);
}

// Use the userId to fetch data from your database
const posts = await mockGetPosts(userId);

return { posts };
};
```
</Tab>

<Tab>
The [`getAuth()`][get-auth] helper allows you to access the [`Auth` object](/docs/references/nextjs/auth-object). You can use the returns from `getAuth()` to protect the action function, update the user or perform mutations on data in your database.

```tsx filename="routes/example.tsx"
export const action: ActionFunction = async (args) => {

// Use getAuth to retrieve user data
const { userId, getToken } = await getAuth(args)

// Use the userId to perform a mutation on data in your database
const updatedPost = await mockUpdatePost(userId, postId, body)

return { updatedPost };
}
```
</Tab>
</Tabs>

#### Examples of fetching and mutating user data

<Tabs type="function" items={["Loader Function", "Action Function"]}>
<Tab>
```tsx filename="routes/profile.tsx"
import { LoaderFunction, redirect } from "@remix-run/node";
import { getAuth } from "@clerk/remix/ssr.server";
import { createClerkClient } from '@clerk/remix/api.server';

export const loader: LoaderFunction = async (args) => {
const { userId } = await getAuth(args);

if (!userId) {
return redirect("/sign-in?redirect_url=" + args.request.url);
}

const user = await createClerkClient({secretKey: process.env.CLERK_SECRET_KEY}).users.getUser(userId);
return { serialisedUser: JSON.stringify(user) };
};
```
</Tab>

<Tab>
```tsx filename="routes/profile.tsx"
import { ActionFunction, redirect } from "@remix-run/node";
import { getAuth } from "@clerk/remix/ssr.server";
import { createClerkClient } from '@clerk/remix/api.server';

export const action: ActionFunction = async (args) => {
// Use getAuth to retrieve user data
const { userId } = await getAuth(args)

// If there is no userId, then redirect to sign-in route
if (!userId) {
return redirect("/sign-in?redirect_url=" + args.request.url);
}
// Prepare the data for the mutation
const params = { firstName: 'John', lastName: 'Wicker' };

// Initialize clerkClient and perform the mutations
const updatedUser = await createClerkClient({ secretKey: process.env.CLERK_SECRET_KEY }).users.updateUser(userId, params);

// Return the updated user
return { serialisedUser: JSON.stringify(updatedUser) };
};
```
</Tab>
</Tabs>

</Steps>

Expand Down
Loading