Skip to main content
Docs

Add React Router to your Clerk-powered Chrome Extension

You will learn the following:

  • Install react-router
  • Create components for your routes
  • Create layouts
  • Wire layouts and routes up with createMemoryRouter

This tutorial demonstrates how to integrate React Router into your Chrome Extension application. It assumes you're using Plasmo to build your Chrome Extension.

Install react-router

React Router is a lightweight, fully-featured routing library. To install it in your project, run the following command:

terminal
pnpm add react-router

Important

This guide assumes you're using Plasmo to build your Chrome Extension, so you must use pnpm as your package manager.

Create routes

  1. In the src/ directory, create a popup/ directory.
  2. In the popup/ directory, create a routes/ directory.
  3. In the routes/ directory, create the home.tsx, sign-in.tsx, sign-up.tsx, and settings.tsx files.
  4. Use the following tabs to view the code necessary for each file.
src/popup/routes/home.tsx
export const Home = () => {
  return (
    <>
      <h1>Clerk + Chrome Extension + React Router</h1>
    </>
  )
}
src/popup/routes/sign-in.tsx
import { SignIn } from '@clerk/chrome-extension'

export const SignInPage = () => {
  return (
    <>
      <p>Sign In</p>
      <SignIn routing="virtual" />
    </>
  )
}
src/popup/routes/sign-up.tsx
import { SignUp } from '@clerk/chrome-extension'

export const SignUpPage = () => {
  return (
    <>
      <p>Sign Up</p>
      <SignUp routing="virtual" />
    </>
  )
}
src/popup/routes/settings.tsx
import { UserProfile } from '@clerk/chrome-extension'

export const Settings = () => {
  return (
    <>
      <h1>Settings</h1>
      <UserProfile routing="virtual" />
    </>
  )
}

Create layouts

  1. Delete your src/popup.tsx file.
  2. In your src/popup/ directory, create a layouts/ directory.
  3. In the layouts/ directory, create a root-layout.tsx file.
  4. In the root-layout.tsx file, paste the following code to create a layout for your app.
    • The layout contains an <Outlet /> component from react-router. This behaves similar to {children} in Next.js or more generic React components.
    • The footer includes Clerk's <UserButton /> component and a link to the /settings page, which renders Clerk's <UserProfile /> component. Clerk's <SignedIn> and <SignedOut> control components determine what's displayed based on the user's authentication state.
src/popup/layouts/root-layout.tsx
import { Link, Outlet, useNavigate } from 'react-router'
import { ClerkProvider, SignedIn, SignedOut, UserButton } from '@clerk/chrome-extension'

const PUBLISHABLE_KEY = process.env.PLASMO_PUBLIC_CLERK_PUBLISHABLE_KEY

if (!PUBLISHABLE_KEY) {
  throw new Error('Please add the PLASMO_PUBLIC_CLERK_PUBLISHABLE_KEY to the .env.development file')
}

export const RootLayout = () => {
  const navigate = useNavigate()

  return (
    <ClerkProvider
      routerPush={(to) => navigate(to)}
      routerReplace={(to) => navigate(to, { replace: true })}
      publishableKey={PUBLISHABLE_KEY}
      afterSignOutUrl="/"
    >
      <div className="plasmo-w-[785px] plasmo-h-[600px]">
        <main>
          <Outlet />
        </main>
        <footer>
          <SignedIn>
            <Link to="/settings">Settings</Link>
            <UserButton />
          </SignedIn>
          <SignedOut>
            <Link to="/">Home</Link>
            <Link to="/sign-in">Sign In</Link>
            <Link to="/sign-up">Sign Up</Link>
          </SignedOut>
        </footer>
      </div>
    </ClerkProvider>
  )
}

Configure layouts and routes with createMemoryRouter

React Router's createMemoryRouter is a router that uses memory to store the state of the router instead of the browser's history. This is useful for creating a router in a non-browser environment like a Chrome Extension.

  1. In the src/popup/ directory, create an index.tsx file.
  2. In the index.tsx file, paste the following code to configure your routes with createMemoryRouter.
src/popup/index.tsx
import React from 'react'

import '../style.css'

import { createMemoryRouter, RouterProvider } from 'react-router'

import { RootLayout } from './layouts/root-layout'
import { Home } from './routes/home'
import { Settings } from './routes/settings'
import { SignInPage } from './routes/sign-in'
import { SignUpPage } from './routes/sign-up'

const router = createMemoryRouter([
  {
    // Wraps the entire app in the root layout
    element: <RootLayout />,
    // Mounted where the <Outlet /> component is inside the root layout
    children: [
      { path: '/', element: <Home /> },
      { path: '/sign-in', element: <SignInPage /> },
      { path: '/sign-up', element: <SignUpPage /> },
      { path: '/settings', element: <Settings /> },
    ],
  },
])

export default function PopupIndex() {
  return <RouterProvider router={router} />
}

Test the integration

  1. Run your project with the following command:
    terminal
    pnpm dev
  2. In your Chrome browser, open the extension popup. Ensure that the home page displays with a footer containing the Home, Sign In, and Sign Up links.
  3. Visit the Sign Up link and ensure the <SignUp /> component is rendered.
  4. Visit the Sign In link and ensure the <SignIn /> component is rendered. Sign in with your account. You'll be redirected to the home page and the footer will display the Settings link and the <UserButton /> component.
  5. Select the <UserButton /> component to open the user menu.
  6. Visit the Settings link and ensure the <UserProfile /> component is rendered.

Feedback

What did you think of this content?

Last updated on