Next.js authentication using Clerk, Drizzle ORM, and Neon
Learn how to build a Next.js application that uses Clerk for authentication and Neon's Serverless Postgres with Drizzle ORM to store data.
Building an effective authentication and authorization system into your application is as equally fraught with challenges as managing database infrastructure. As the old wisdom says, never “roll your own” regarding authentication and authorization.
In addition to the effort required to develop the login, logout, and social provider integration, you must consider compliance with standards such as SOC 2 and HIPAA, multi-factor authentication, and user management.
Using Clerk enables you to seamlessly add advanced authentication and user management features to your application and comply with data security regulations by storing personally identifiable information in their compliant infrastructure.
In this article, you’ll learn how to use Clerk to add authentication to a Next.js application and how to use Clerk’s Next.js helpers to obtain user details in your components. You’ll also learn to use Drizzle ORM to store non-PII data in Neon’s serverless Postgres.
A complete example application with instructions for local development and deployment on Vercel can be found on GitHub at evanshortiss/neon-clerk-drizzle-nextjs. A live preview of the sample application is hosted on Vercel; try it out at neon-clerk-drizzle-nextjs.vercel.app and vote for your favorite periodic element!
Solution Architecture
Before diving into the implementation, let’s review the high-level architecture of this application.
Vercel will provide serverless hosting for your Next.js application. The Next.js application will direct your users to Clerk for authentication. Clerk will redirect users to your application once they’ve completed an authentication flow using a supported provider such as Google or Discord OAuth.
Once a user is signed in, they can access protected pages and routes in your application, and you can read their session data as needed to obtain the user ID to query or associate data with the authenticated user in your Neon Postgres database.
Sign Up to Neon and Configure Postgres
Sign up for Neon and create a project. This project will contain the Postgres database and a user_messages
table that you will use to follow along with the rest of this article.
- Enter a project name.
- Use the default database name of
neondb
. - Choose the region closest to the location where your application will be deployed.
- Click the Create project button.
You’ll instantly be provided with a connection string you can use to connect to your serverless Postgres database.
Sign Up to Clerk and Configure Application Sign In
Visit dashboard.clerk.com and sign up, or sign in if you’re an existing user. Create a new application and enable some of the available sign-in options. You can see that I’ve enabled Discord and Google as sign-in options for my application.
Once the application has been created on Clerk, you’ll find your API keys on the Home screen of your application in the Clerk dashboard. Specifically, you’ll need the API keys listed in the Next.js section soon!
Using Neon’s Serverless Driver with Next.js and Drizzle ORM
Create a Next.js Project and Install Dependencies
Create a Next.js application in your development environment. This requires Node.js v18 or newer to be installed in your development environment. This article assumes you use the following options when creating your Next.js application using create-next-app.
Once your Next.js application has been created, change to the project directory in your terminal, then add the Neon serverless driver and Drizzle ORM to your project’s dependencies using npm or your preferred package manager.
Create a Schema and Database Connection
Create a file named src/app/db/schema.ts and define a user_messages
schema using the types provided by Drizzle ORM.
To use Neon’s serverless driver with Drizzle ORM, create a file named src/app/db/index.ts and add the following code. Exporting the Drizzle instance from a file means it’s created on application startup and exported as a singleton that other modules can import and reuse to execute typesafe SQL queries against your Postgres database hosted by Neon.
Next, create a file named .env.local in the root of the Next.js project directory and add your database URL from the Neon Console as an environment variable named DATABASE_URL.
Start your Application
Use the npm run dev command to start your Next.js application in development mode and confirm it’s available at http://localhost:3000. You won’t be prompted to authenticate since you haven’t added the Clerk middleware to your application yet – you’ll take care of that soon.
Generate and Apply Database Migrations using Drizzle Kit
Before using Drizzle ORM to perform database operations in your application, you’ll need to generate and apply schema migrations to your database. Drizzle Kit streamlines this process by detecting changes in your schema.ts file and generating the necessary SQL migrations to apply to your database.
To get started, add Drizzle Kit and dotenv to your project’s development dependencies.
Next, create a file named drizzle.config.ts at the root of your repository and add the following configuration.
Now you can use the generate command from the Drizzle Kit CLI to generate migration files. Run the following command to generate migrations for your user schema.
A new src/app/db/migrations folder will be created, and an SQL migration file will be created that contains a CREATE TABLE
statement for the user_messages
table. You can read more about migrations in the Drizzle documentation.
Use the push command from the Drizzle Kit CLI to apply the migrations to your Postgres database on Neon. The following command runs the push
command from Drizzle Kit and sets the config path for dotenv to load the DATABASE_URL
from your .env.local file.
Visit the Tables view in the Neon Console, and your new user_messages table will be listed once the push command has finished.
Add Authentication to your Next.js Application using Clerk
The Next.js documentation provides a comprehensive overview of authentication, session management, and authorization with sample code. This requires writing a non-trivial amount of code and middleware. Since you’re using Clerk, it will handle this complexity for you!
To start, install Clerk’s Next.js package and add it to your Next.js project’s dependencies.
Update your layout.tsx file to use the ClerkProvider
and UserButton
from the @clerk/nextjs package
. The ClerkProvider
provides access to the current session and user context. The UserButton
renders a component that shows the user’s profile picture, provides access to account management, and a sign-out button.
Next, create a file named src/middleware.ts, and add the authMiddleware
provided by Clerk as shown in the following snippet.
Lastly, add the API keys provided in Next.js format on the Clerk dashboard to your .env.local file.
Start your application using the npm run dev command, and visit http://localhost:3000 in your web browser. If you’re prompted to sign in to your application, everything is going as planned!
Store Data in Postgres associated with a Clerk User ID
The final step in the process is to add some interactivity to your application. You will let users store their favorite quote in your Neon Postgres database. This will involve defining Next.js Server Actions and a Server Component that uses them.
Start by creating a file named src/app/actions.ts and add the following code to define createUserMessage
and deleteUserMessage
actions. Both actions obtain the user ID from the current session using Clerk’s currentUser helper.
Add the following code to src/app/page.tsx to create a minimalist web page that uses your actions. This enables users to create or delete a quote associated with their user ID. If you recall the schema you defined earlier using Drizzle ORM, it uses the user ID as the primary key. This means each user can store a single quote.
Start your application using npm run dev
, visit http://localhost:3000, and sign in using one of your chosen providers. You will be redirected to your application after signing in. The application displays a web page that contains an input field where you can submit a quote to associate with your user account and a lovely header with your username and profile picture powered by Clerk’s UserButton
component.
Type in your favorite quote, for example, “To infinity and beyond!” by Buzz Lightyear. Click the Save Quote button or press Enter to save your quote. When you visit http://localhost:3000 in the future, the quote associated with your user ID will be displayed.
Conclusion
Congratulations, you’ve built a Next.js application that integrates with Clerk for user management and authentication and uses Neon’s serverless Postgres as its database.
Now that you’ve got an application up and running, you should visit Clerk’s Next.js documentation to learn how to deploy your application to production. You can use Neon’s Vercel Integration to manage development and preview database branches when you deploy your Next.js application on Vercel, which uses Neon’s serverless Postgres.
We would love to get your feedback. Follow us on X, join us on Discord, and let us know how we can help you build the next generation of applications.