Create React App

This guide will help you install and initialize Clerk in a new Create React App.


1. Create a Create React App app

Start by creating a new Create React App app.

npx create-react-app yourapp
# or
yarn create react-app yourapp

For more information about these commands, please reference the Create React App documentation.


2. Install Clerk

Install Clerk's NPM package.

# From your application's root directory
cd yourapp
npm install @clerk/clerk-react
# or
yarn add @clerk/clerk-react

3. Configure src/App.js

Clerk requires every page to be wrapped in the <ClerkProvider> context. In Create React App, we add this in src/App.js.

In the code below, we've also added a sign in requirement, and show a greeting when a user is signed in.

// Contents of src/App.js
import { useEffect } from "react";
import {
ClerkProvider,
SignedIn,
SignedOut,
UserButton,
useUser,
} from "@clerk/clerk-react";
// Replace with your instance settings
const clerkClientHost = "auth.abc123.lcl.dev";
const clerkSignInURL = "https://accounts.abc123.lcl.dev/sign-in";
function App() {
return (
<ClerkProvider host={clerkClientHost}>
<SignedIn>
<UserButton />
<Greeting />
</SignedIn>
<SignedOut>
<RedirectToSignIn />
</SignedOut>
</ClerkProvider>
);
}
function Greeting() {
const { firstName } = useUser();
return <div>Hello, {firstName}!</div>;
}
function RedirectToSignIn() {
useEffect(() => {
window.location.href = clerkSignInURL;
});
return null;
}
export default App;

4. Add a router

A common next step is to add a router. Here we use React Router to add public and protected routes to our application.

Before using this code, you must install React Router:

npm install react-router
# or
yarn add react-router

This is just one example of how authentication can be handled with Clerk. Feel free to adjust the strategy to better serve your use case!

// Contents of src/App.js
import { useEffect } from "react";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import {
ClerkProvider,
SignedIn,
SignedOut,
UserButton,
useUser,
} from "@clerk/clerk-react";
// Replace with your instance settings
const clerkClientHost = "auth.abc123.lcl.dev";
const clerkSignInURL = "https://accounts.abc123.lcl.dev/sign-in";
function App() {
return (
<Router>
<ClerkProvider host={clerkClientHost}>
<Switch>
{/* Public routes, accesible whether or not a user is signed in */}
<Route path="/public">
<div>
Reached the public route. <Link to="/">Return home.</Link>
</div>
</Route>
{/* Private routes, accesible only if a user is signed in */}
<PrivateRoute path="/private">
<div>
Reached the private route. <Link to="/">Return home.</Link>
</div>
</PrivateRoute>
{/* Catch-all route will render if no other route renders */}
<Route>
<SignedIn>
<UserButton />
<Greeting />
<div>You are signed in. You can access both routes.</div>
<Navigation />
</SignedIn>
<SignedOut>
<div>You are signed out. You can access the public route.</div>
<Navigation />
</SignedOut>
</Route>
</Switch>
</ClerkProvider>
</Router>
);
}
function PrivateRoute(props) {
// If the route matches but the user is not signed in, redirect to /sign-in
return (
<>
<SignedIn>
<Route {...props} />
</SignedIn>
<SignedOut>
<RedirectToSignIn />
</SignedOut>
</>
);
}
function Navigation() {
return (
<ul>
<li>
<Link to="/public">Public route</Link>
</li>
<li>
<Link to="/private">Private route</Link>
</li>
</ul>
);
}
function Greeting() {
const { firstName } = useUser();
return <div>Hello, {firstName}!</div>;
}
function RedirectToSignIn() {
useEffect(() => {
window.location.href = clerkSignInURL;
});
return null;
}
export default App;

5. Mount components

By default, Clerk hosts the SignIn, SignUp, and UserProfile components on the "accounts" subdomain for your instance. In production, this will be accounts.yourdomain.com.

If you prefer, you can also "mount" these components directly in your application.

This is the same router logic as above, but with 3 additional changes:

  1. We add public routes for Sign In and Sign Up, and a private route for User Profile.

  2. We create a <ClerkProviderWithNavigate> component that uses React Router's useHistory hook to pass a navigate prop to <ClerkProvider>. This allows Clerk to navigate inside and between components without conflicting with React Router.

  3. We replace our custom <RedirectToSignIn> component with React Router's <Redirect> component, since now the navigation is internal.

i. Update src/App.js

// Contents of src/App.js
import { useEffect } from "react";
import {
BrowserRouter as Router,
Switch,
Route,
Link,
useHistory,
Redirect,
} from "react-router-dom";
import {
ClerkProvider,
SignedIn,
SignedOut,
UserButton,
useUser,
SignIn,
SignUp,
UserProfile,
} from "@clerk/clerk-react";
// Replace with your instance settings
const clerkClientHost = "auth.abc123.lcl.dev";
const clerkSignInPath = "/sign-in";
function App() {
return (
<Router>
<ClerkProviderWithNavigate>
<Switch>
{/* Public routes, accesible whether or not a user is signed in */}
<Route path="/public">
<div>
Reached the public route. <Link to="/">Return home.</Link>
</div>
</Route>
<Route path="/sign-in/(.*)?">
<SignIn routing="path" path="/sign-in" />
</Route>
<Route path="/sign-up/(.*)?">
<SignUp routing="path" path="/sign-up" />
</Route>
{/* Private routes, accesible only if a user is signed in */}
<PrivateRoute path="/private">
<div>
Reached the private route. <Link to="/">Return home.</Link>
</div>
</PrivateRoute>
<PrivateRoute path="/user/(.*)?">
<UserProfile routing="path" path="/user" />
</PrivateRoute>
{/* Catch-all route will render if no other route renders */}
<Route>
<SignedIn>
<UserButton />
<Greeting />
<div>You are signed in. You can access both routes.</div>
<Navigation />
</SignedIn>
<SignedOut>
<div>You are signed out. You can access the public route.</div>
<Navigation />
</SignedOut>
</Route>
</Switch>
</ClerkProviderWithNavigate>
</Router>
);
}
function Navigation() {
return (
<ul>
<li>
<Link to="/public">Public route</Link>
</li>
<li>
<Link to="/private">Private route</Link>
</li>
</ul>
);
}
function Greeting() {
const { firstName } = useUser();
return <div>Hello, {firstName}!</div>;
}
function PrivateRoute(props) {
// If the route matches but the user is not signed in, redirect to /sign-in
return (
<>
<SignedIn>
<Route {...props} />
</SignedIn>
<SignedOut>
<Redirect to={clerkSignInPath} />
</SignedOut>
</>
);
}
function ClerkProviderWithNavigate({ children }) {
const { push } = useHistory();
return (
<ClerkProvider
host={clerkClientHost}
navigate={(to) => {
return push(new URL(to).pathname);
}}
>
{children}
</ClerkProvider>
);
}
export default App;

ii. Update instance settings

The final step is to update your instance settings so that users will be defaulted to your mounted components instead of the "accounts" subdomain.

Dashboard update instructions coming soon.