Use Clerk with Remix
You will learn the following:
- Install
@clerk/remix
- Set up your environment variables
- Configure rootAuthLoader
- Configure ClerkApp
- Protecting your pages
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.
Install @clerk/remix
Once you have a Remix application ready, you need to install Clerk's Remix SDK. This gives you access to our prebuilt components and hooks for Remix applications.
npm install @clerk/remix
yarn add @clerk/remix
pnpm add @clerk/remix
Set environment variables
Below is an example of an .env
file.
Pro tip! If you are signed into your Clerk Dashboard, your secret key should become visible by clicking on the eye icon. Otherwise, you can find your keys in the Clerk Dashboard on the API Keys page.
CLERK_PUBLISHABLE_KEY=YOUR_PUBLISHABLE_KEY
CLERK_SECRET_KEY=YOUR_SECRET_KEY
Configure rootAuthLoader
To configure Clerk in your Remix application, you will need to update your root loader. This will enable you to have access to authentication state in any Remix routes.
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 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 />;
}
If you need to load in additonal data, you can pass your loader directly to the rootAuthLoader
.
// Imports
export const loader: LoaderFunction = args => {
return rootAuthLoader(args, ({ request }) => {
const { sessionId, userId, getToken } = request.auth;
// fetch data
return { yourData: 'here' };
});
};
// Additonal application code
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.
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 />;
}
export default ClerkApp(App);
Protecting your pages
Client side
Clerk offers Control Components that allow you to protect your pages. These components are used to control the visibility of your pages based on the user's authentication state.
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>
<div>
<p>View your profile here</p>
<UserButton />
</div>
<div>
<SignOutButton />
</div>
</SignedIn>
<SignedOut>
<p>You are signed out</p>
<div>
<SignInButton />
</div>
<div>
<SignUpButton />
</div>
</SignedOut>
</div>
);
}
Server side
To protect your routes, you can use the the loader to check for the userId
singleton. If it doesn't exist, redirect your user back to the sign-in page.
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 { userId } = await getAuth(args);
if (!userId) {
return redirect("/sign-in");
}
return {};
}
export default function Index() {
return (
<div>
<h1>Index route</h1>
<p>You are signed in!</p>
<UserButton />
</div>
);
}
Next steps
Now that you have an application integrated with Clerk, you will want to read the following documentation:
Create custom sign-up and sign-in pages
Learn how add custom sign-up and sign-in pages with Clerk components.
Read user and session data
Learn how to use Clerk's hooks and helpers to access the active session and user data in your Remix application.
Customization & Localization
Learn how to customize and localize the Clerk components.
Authentication Components
Learn more about all our authentication components.