šŸ“ Sign Up | šŸ” Log In

← Root | ↑ Up

ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā” │ šŸ“„ shadcn/directory/clerk/clerk-docs/getting-started/quickstart.remix │ ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

╔══════════════════════════════════════════════════════════════════════════════════════════════╗
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘

title: Remix Quickstart description: Learn how to use Clerk to quickly and easily add secure authentication and user management to your Remix application. sdk: remix

<Include src="_partials/remix/maintenance-mode" />

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

}

]} beforeYouStart={[ { title: "Set up a Clerk application", link: "/docs/getting-started/quickstart/setup-clerk", icon: "clerk", }, { title: "Create a Remix application", link: "https://remix.run/docs/en/main/start/quickstart", icon: "remix", } ]} />

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

[!NOTE] If you are using Remix SPA mode, follow the Remix SPA mode guide.

<Steps> ## Install `@clerk/remix`

The Clerk Remix SDK gives you access to prebuilt components, hooks, and helpers to make user authentication easier.

Run the following command to install the SDK:

<CodeBlockTabs options={["npm", "yarn", "pnpm", "bun"]}> bash {{ filename: 'terminal' }} npm install @clerk/remix

```bash {{ filename: 'terminal' }}
yarn add @clerk/remix
```

```bash {{ filename: 'terminal' }}
pnpm add @clerk/remix
```

```bash {{ filename: 'terminal' }}
bun add @clerk/remix
```
</CodeBlockTabs>

Set your Clerk API keys

<SignedIn> Add the following keys to your `.env` file. These keys can always be retrieved from the [**API keys**](https://dashboard.clerk.com/~/api-keys) page in the Clerk Dashboard. </SignedIn> <SignedOut> 1. In the Clerk Dashboard, navigate to the [**API keys**](https://dashboard.clerk.com/~/api-keys) page. 1. In the **Quick Copy** section, copy your Clerk Publishable and Secret Keys. 1. Paste your keys into your `.env` file.
The final result should resemble the following:
</SignedOut>
CLERK_PUBLISHABLE_KEY={{pub_key}}
CLERK_SECRET_KEY={{secret}}

Configure rootAuthLoader()

The rootAuthLoader() function is a helper function that provides the authentication state to your Remix application. You must export rootAuthLoader() as the root loader() function.

Update your root.tsx file with the following code:

import type { MetaFunction, LoaderFunction } from '@remix-run/node'
import { Links, Meta, Outlet, Scripts, ScrollRestoration } from '@remix-run/react'

// Import `rootAuthLoader()`
import { rootAuthLoader } from '@clerk/remix/ssr.server'

export const meta: MetaFunction = () => [
  {
    charset: 'utf-8',
    title: 'New Remix App',
    viewport: 'width=device-width,initial-scale=1',
  },
]

// Export `rootAuthLoader()` as the root route `loader`
export const loader: LoaderFunction = (args) => rootAuthLoader(args)

export function Layout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <head>
        <Meta />
        <Links />
      </head>
      <body>
        {children}
        <ScrollRestoration />
        <Scripts />
      </body>
    </html>
  )
}

export default function App() {
  return <Outlet />
}

Configure ClerkApp

Clerk provides a ClerkApp wrapper to provide the authentication state to your React tree. This helper works with Remix SSR out-of-the-box and follows the "higher-order component" paradigm.

Update your root.tsx file with the following code:

import type { MetaFunction, LoaderFunction } from '@remix-run/node'

import { Links, Meta, Outlet, Scripts, ScrollRestoration } from '@remix-run/react'

import { rootAuthLoader } from '@clerk/remix/ssr.server'
// Import ClerkApp
import { ClerkApp } from '@clerk/remix'

export const meta: MetaFunction = () => [
  {
    charset: 'utf-8',
    title: 'New Remix App',
    viewport: 'width=device-width,initial-scale=1',
  },
]

export const loader: LoaderFunction = (args) => rootAuthLoader(args)

export function Layout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <head>
        <Meta />
        <Links />
      </head>
      <body>
        {children}
        <ScrollRestoration />
        <Scripts />
      </body>
    </html>
  )
}

function App() {
  return <Outlet />
}

// Wrap your app with `ClerkApp`
export default ClerkApp(App)

Protect your pages

Client-side

To protect your pages on the client-side, Clerk's prebuilt control components control the visibility of content based on the user's authentication state.

The following example uses the following components:

import {
  SignInButton,
  SignOutButton,
  SignUpButton,
  SignedIn,
  SignedOut,
  UserButton,
} from '@clerk/remix'

export default function Index() {
  return (
    <div>
      <h1>Index Route</h1>
      <SignedIn>
        <p>You are signed in!</p>

        <UserButton />
      </SignedIn>
      <SignedOut>
        <p>You are signed out</p>

        <SignInButton />
      </SignedOut>
    </div>
  )
}

Server-side

To protect your routes, use the getAuth() function in your loader. This function retrieves the authentication state from the request object, returning an Auth object that includes the isAuthenticated, allowing you to determine if the user is authenticated.

import { UserButton } from '@clerk/remix'
import { getAuth } from '@clerk/remix/ssr.server'
import { LoaderFunction, redirect } from '@remix-run/node'

export const loader: LoaderFunction = async (args) => {
  const { isAuthenticated } = await getAuth(args)
  if (!isAuthenticated) {
    return redirect('/sign-in')
  }
  return {}
}

export default function Index() {
  return (
    <div>
      <h1>Index route</h1>
      <p>You are signed in!</p>
      <UserButton />
    </div>
  )
}

Create your first user

Run your project with the following command:

<CodeBlockTabs options={["npm", "yarn", "pnpm", "bun"]}> bash {{ filename: 'terminal' }} npm run dev

```bash {{ filename: 'terminal' }}
yarn dev
```

```bash {{ filename: 'terminal' }}
pnpm dev
```

```bash {{ filename: 'terminal' }}
bun dev
```
</CodeBlockTabs>

Visit your app's homepage at http://localhost:5173. Sign up to create your first user. </Steps>

Next steps

<Cards> - [Create a custom sign-in-or-up page](/docs/remix/guides/development/custom-sign-in-or-up-page) - Learn how add custom sign-in-or-up page with Clerk components.


ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•‘
ā•šā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•ā•

← Root | ↑ Up