How to Manage User Authentication in React.js, Next.js, Vue.js, and Nuxt.js Using Clerk
INTRODUCTION
Authentication is a very important component to any software, application, system, it provides an extra layer of security by restricting areas of your application. For example a dashboard with important information, it can not be accessed unless the user is authenticated. Of course we can implement user, email and password for the user to create and then the user receives an email to validate the email and only then the user can access the content which is allowed for the ones authenticated, this flow is still very popular in use, but it has additional steps that many users are somewhat bored to take, since authentication with a provider be it Google, Microsoft, Apple or others is much simpler, with just a few clicks you can get authenticated and you don’t even have to leave the current screen you are in. This ease of access should definitely be considered when building your applications so that the user can choose which one he wants.
In this article we will use Clerk with React.js, Next.js, Vue.js and Nuxt.js. Until the present data, Clerk is not fully supported for Vue.js or Nuxt.js applications yet, in the Clerk’s official docs we can find mentions for Vue.js but to use it via SDK.
CLERK WITH REACT.JS
The first step is to log into Clerk’s website and choose the providers you want to be available in your application. You can choose up to 3 providers in the free-tier, if you wish to have more providers then you will need to upgrade your account.
The second step to add it to a React.js application is quite simple. First we need to install the clerk package:
npm install @clerk/clerk-react
Then we need to set up our environment variables, first check if you already have a env.local file to add the key there, in case you don’t have this file you can go ahead and create it to add the clerk publishable key, as follows:
VITE_CLERK_PUBLISHABLE_KEY=pk_test_************************
The next step is to import the publishable key, we can do this by going to the main.ts file and import it there, you can also add a if check to avoid Typescript errors.
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.tsx'
import './index.css'
// Import your publishable key
const PUBLISHABLE_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY
if (!PUBLISHABLE_KEY) {
throw new Error('Missing Publishable Key')
}
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<App />
</React.StrictMode>,
)
Now we have to add the <ClerkProvider /> to our application also in the main.ts file but now we have to wrap the whole app with the <ClerkProvider /> as shown below and attach the publishableKey to it:
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.tsx'
import './index.css'
import { ClerkProvider } from '@clerk/clerk-react'
// Import your publishable key
const PUBLISHABLE_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY
if (!PUBLISHABLE_KEY) {
throw new Error('Missing Publishable Key')
}
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<ClerkProvider publishableKey={PUBLISHABLE_KEY} afterSignOutUrl="/">
<App />
</ClerkProvider>
</React.StrictMode>,
)
Now the final step is to add the Clerk components in the Header component to handle the authentication steps such as sign in, sign out, the button with the authenticators we choose during the process like Google, Microsoft, Github, Apple and many others available. You can organize your Header component the way you want just import the components from Clerk and it should work.
import {
SignedIn,
SignedOut,
SignInButton,
UserButton
} from '@clerk/clerk-react'
export function Header() {
return (
<header>
<SignedOut>
<SignInButton />
</SignedOut>
<SignedIn>
<UserButton />
</SignedIn>
</header>
)
}
And don’t forget to add the package React-Router-Dom to navigate to whatever the page is after the user is authenticated.
CLERK WITH NEXT.JS
To add Clerk to a Next.js application the steps are almost identical, just a few changes, let’s see how to do that.
First log into Clerk’s website with your account and select the providers and proceed to add the publishable key and remember that Next.js has a different naming convention for its environment variables.
And using Next.js requires 2 values to be added in the environment file, a secret key is added in Next.js a publishable key and a secret key:
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_************************
CLERK_SECRET_KEY=sk_test_************************
Next step is to add a middleware to intercept routes for unauthenticated users, you can create a file named middleware.ts in the root directory. Then this is the code to make it validate routes and force authentication by using the functions auth() and protect() provided by Clerk:
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'
const isProtectedRoute = createRouteMatcher(['/dashboard(.*)', '/forum(.*)'])
export default clerkMiddleware((auth, req) => {
if (isProtectedRoute(req)) auth().protect()
})
export const config = {
matcher: [
// Skip Next.js internals and all static files, unless found in search params
'/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
// Always run for API routes
'/(api|trpc)(.*)',
],
}
And now we are going to add <Clerkprovider /> to our main layout.tsx file wrapping the entire application and make Clerk globally available.
import {
ClerkProvider,
SignInButton,
SignedIn,
SignedOut,
UserButton
} from '@clerk/nextjs'
import './globals.css'
import Header from '@/components/Header';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<ClerkProvider>
<html lang="en">
<body>
<Header />
<main>{children}</main>
</body>
</html>
</ClerkProvider>
)
}
And now we add our Header component and use Clerk components:
import {
SignedIn,
SignedOut,
SignInButton,
UserButton
} from '@clerk/nextjs';
export function Header() {
return (
<header>
<SignedOut>
<SignInButton />
</SignedOut>
<SignedIn>
<UserButton />
</SignedIn>
</header>
)
}
This is it, now your authentication is ready to be used in Next.js
CLERK WITH VUE.JS
In order to add Clerk to a Vue.js application we are gonna need to use the Clerk’s SDK. And the process is very simple, this is one of the benefits of using Clerk, its simplicity.
Install the SDK into your project by using the command:
npm install vue-clerk
Add the publishable key to your project, unlike Next.js, for Vue.js and React.js there is only one key to be added to the .env.local file:
VITE_CLERK_PUBLISHABLE_KEY=pk_test_************************
Then import the Clerk publishable key in the main.ts file into the src folder:
import { createApp } from 'vue'
import App from './App.vue'
const PUBLISHABLE_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY
if (!PUBLISHABLE_KEY) {
throw new Error('Missing Publishable Key')
}
const app = createApp(App)
app.mount('#app')
Add clerkPlugin from vue-clerk
import { createApp } from 'vue'
import App from './App.vue'
import { clerkPlugin } from 'vue-clerk'
const PUBLISHABLE_KEY = import.meta.env.VITE_CLERK_PUBLISHABLE_KEY
if (!PUBLISHABLE_KEY) {
throw new Error('Missing Publishable Key')
}
const app = createApp(App)
app.use(clerkPlugin, {
publishableKey: PUBLISHABLE_KEY
})
app.mount('#app')
Now create your header component and make use of the Clerk pre-built components:
<script setup>
import {
SignedIn,
SignedOut,
SignInButton,
UserButton
} from 'vue-clerk'
</script>
<template>
<SignedOut>
<SignInButton />
</SignedOut>
<SignedIn>
<UserButton />
</SignedIn>
</template>
And use vue-router to navigate to the authenticated pages when the user is done authenticating.
CLERK WITH NUXT.JS
Nuxt.js applications require the use of Vue-clerk to and some additional steps in order to make Clerk work with Nuxt.js architecture. It’s a different process just like with Next.js because both technologies have similar purposes.
In the nuxt.config.ts we add the module vue-clerk/nuxt into the modules array and by doing so all the components and composables will be auto-imported
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['vue-clerk/nuxt'],
clerk: {
appearance: {},
}
})
And now the environment variables are added in your environment file:
NUXT_PUBLIC_CLERK_PUBLISHABLE_KEY=your_publishable_key
NUXT_CLERK_SECRET_KEY=your_secret_key
The environment variables will be loaded in the nuxt.config.ts file using the runtimeConfig and beware the naming conventions they must match the NUXT_PUBLIC_YOUR_ENV and the runtimeConfig object otherwise we might run into inconsistencies between the dev and build environment.
export default defineNuxtConfig({
modules: ['vue-clerk/nuxt'],
clerk: {
appearance: {},
}
runtimeConfig: {
public: {
clerkPublishableKey: process.env.CLERK_PUBLISHABLE_KEY,
},
}
});
Now the next step is to use Clerk Components in for example a Header component and use it.
<script lang="ts" setup>
// You don't have to import anything from Clerk
</script>
<template>
<div>
<SignIn />
</div>
</template>
We also have to protect the routes that need authentication and if the user is not authorized he will be redirected to a home page or wherever we want.
// middleware/auth.ts
import { defineNuxtRouteMiddleware, navigateTo } from '#app';
import { useClerk } from '@clerk/clerk-vue';
export default defineNuxtRouteMiddleware(() => {
const clerk = useClerk();
if (!clerk.user.value) {
return navigateTo('/sign-in');
}
});
Next step is to add types to make sure Clerk works with Typescript. Since we are using SDKs for Vue.js and Nuxt.js it is not necessary to install the package @clerk/types because the SDKs include their own type definitions. You can read the file in the repository to be certain of what the exact types are.
import { UserResource } from '@clerk/types';
function getUserName(user: UserResource) {
return {
user.firstName || 'Guest',
user.emailAddresses;
}
}
The only thing that is left is to enable typescript module for building the application to be later deployed into production.
export default defineNuxtConfig({
modules: ['vue-clerk/nuxt'],
clerk: {
appearance: {},
}
runtimeConfig: {
public: {
clerkPublishableKey: process.env.CLERK_PUBLISHABLE_KEY,
},
}
buildModules: ['@nuxt/typescript-build'], // Enable TypeScript
});
CONCLUSION
Authentication with Clerk is very simple and easy, now you can add it to your projects and have another option for your users to choose and this will be better for User Experience.
REFERENCES
https://clerk.com/docs/quickstarts/react
https://clerk.com/docs/quickstarts/nextjs
https://clerk.com/docs/references/react/use-clerk
https://github.com/wobsoriano/nuxt-clerk-template/tree/main
Subscribe to my newsletter
Read articles from Hugo Ramon Pereira directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Hugo Ramon Pereira
Hugo Ramon Pereira
Frontend Developer with experience in building modern interfaces, providing the user with great experience, accessibility and responsiveness.