Setup & Configuration
Configure Clerk authentication with environment variables, middleware protection, and custom sign-in flows
Complete guide to setting up Clerk authentication in Plainform, from API keys to middleware configuration.
Prerequisites
Before setting up Clerk, ensure you have:
- A Plainform project installed and running
- Node.js 18+ installed
- A Clerk account (free tier available)
Clerk is already installed in Plainform (@clerk/nextjs v6.38+). You only need to configure environment variables.
Quick Setup
Create Clerk Application
- Sign up at clerk.com
- Click "Add application"
- Name your application (e.g., "Plainform App")
- Select "Next.js" as your framework
- Click "Create application"
Get API Keys
In your Clerk Dashboard:
- Navigate to API Keys in the sidebar
- You'll see two keys:
- Publishable Key (starts with
pk_test_orpk_live_) - Secret Key (starts with
sk_test_orsk_live_)
- Publishable Key (starts with
- Keep this page open - you'll need these keys in the next step
Never commit your Secret Key to version control. It should only be in .env files.
Configure Environment Variables
Add these variables to your .env file in the project root:
| Env Variable | Type | Default |
|---|---|---|
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY | string | pk_test_xxxx |
CLERK_SECRET_KEY | string | sk_test_xxxx |
NEXT_PUBLIC_CLERK_SIGN_IN_URL | string | /sign-in |
NEXT_PUBLIC_CLERK_SIGN_UP_URL | string | /sign-up |
Example .env file:
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="pk_test_xxxxxxxxxxxxxxxxxxxx"
CLERK_SECRET_KEY="sk_test_xxxxxxxxxxxxxxxxxxxx"
NEXT_PUBLIC_CLERK_SIGN_IN_URL="/sign-in"
NEXT_PUBLIC_CLERK_SIGN_UP_URL="/sign-up"These variables are validated on startup by env.ts. The app won't start if any required variable is missing or invalid.
Verify Setup
Start your development server:
npm run devIf configuration is correct, you'll see:
- No validation errors in the terminal
- The app starts successfully on
http://localhost:3000
If you see errors, double-check:
- Variable names match exactly (case-sensitive)
- Keys are copied correctly from Clerk Dashboard
.envfile is in the project root
Test Authentication
- Navigate to
http://localhost:3000/sign-up - Create a test account
- You should be redirected to the home page
- Check the Clerk Dashboard → Users to see your new user
Middleware Configuration
Plainform includes pre-configured middleware to protect routes. The configuration is in middleware.ts:
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';
// Define public routes (accessible without authentication)
const isPublicRoute = createRouteMatcher([
'/',
'/sign-in(.*)',
'/sign-up(.*)',
'/forgot-password(.*)',
'/sso-callback(.*)',
'/blog(.*)',
'/docs(.*)',
'/api/webhooks(.*)',
]);
export default clerkMiddleware(async (auth, req) => {
// Protect all routes except public ones
if (!isPublicRoute(req)) {
await auth.protect();
}
});
export const config = {
matcher: [
'/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
'/(api|trpc)(.*)',
],
};Customizing Protected Routes
To add or remove protected routes, modify the isPublicRoute matcher:
const isPublicRoute = createRouteMatcher([
'/',
'/sign-in(.*)',
'/sign-up(.*)',
'/pricing', // Add this
'/about', // Add this
'/blog(.*)',
'/docs(.*)',
]);To protect specific routes with additional checks:
const isAdminRoute = createRouteMatcher(['/admin(.*)']);
export default clerkMiddleware(async (auth, req) => {
if (!isPublicRoute(req)) {
await auth.protect();
}
// Additional check for admin routes
if (isAdminRoute(req)) {
await auth.protect((has) => {
return has({ role: 'admin' });
});
}
});Provider Setup
Clerk is initialized in the root layout via ClerkProvider. This is already configured in Plainform:
import { ClerkProvider } from '@clerk/nextjs';
export default function RootLayout({ children }) {
return (
<ClerkProvider>
<html lang="en">
<body>{children}</body>
</html>
</ClerkProvider>
);
}The provider wraps your entire app, making Clerk hooks available everywhere.
Sign-In/Sign-Up Pages
Plainform includes custom sign-in and sign-up pages at:
app/(auth)/sign-in/[[...sign-in]]/page.tsxapp/(auth)/sign-up/[[...sign-up]]/page.tsx
These pages use custom forms built with Clerk's useSignIn and useSignUp hooks, not Clerk's pre-built components:
import { SignInForm } from '@/components/user/SignInForm';
export default function SignInPage() {
return <SignInForm />;
}The custom forms (SignInForm and SignUpForm) are located in components/user/ and provide:
- Custom styling that matches Plainform's design system
- OAuth integration (Google, GitHub)
- Email/password authentication
- Form validation with Zod and React Hook Form
- Error handling with toast notifications
Custom Form Implementation
The forms use Clerk's authentication hooks directly:
'use client';
import { useSignIn } from '@clerk/nextjs';
import { useForm } from 'react-hook-form';
export function SignInForm() {
const { signIn, setActive } = useSignIn();
const { register, handleSubmit } = useForm();
const onSubmit = async (data) => {
const signInAttempt = await signIn.create({
identifier: data.identifier,
password: data.password,
});
if (signInAttempt.status === 'complete') {
await setActive({ session: signInAttempt.createdSessionId });
router.push('/');
}
};
return (
<form onSubmit={handleSubmit(onSubmit)}>
{/* Custom form fields */}
</form>
);
}This approach gives you full control over the UI while leveraging Clerk's authentication logic.
OAuth Providers
Plainform's custom forms include OAuth integration for Google and GitHub. To enable OAuth providers:
Enable in Clerk Dashboard
- Go to Clerk Dashboard → User & Authentication → Social Connections
- Toggle on desired providers (Google, GitHub, Microsoft, etc.)
- Follow provider-specific setup instructions
- Save changes
OAuth in Custom Forms
The custom forms (SignInForm and SignUpForm) include OAuth buttons using the OAuthConnection component:
import { OAuthConnection } from '@/components/user/OAuthConnection';
<OAuthConnection strategy="oauth_google" icon="Google">
Continue with Google
</OAuthConnection>
<OAuthConnection strategy="oauth_github" icon="Github">
Continue with GitHub
</OAuthConnection>Once enabled in the Clerk Dashboard, these buttons will work automatically.
Test OAuth Flow
- Navigate to
/sign-in - Click an OAuth provider button (Google or GitHub)
- Complete OAuth flow
- You'll be redirected back to your app
OAuth providers require additional configuration (OAuth client IDs, secrets) in the Clerk Dashboard. Follow Clerk's provider-specific guides.
Development vs Production
Development Setup:
- Use test keys (
pk_test_,sk_test_) - Test mode in Clerk Dashboard
- No real emails sent (use Clerk's test email feature)
- Webhooks can use Clerk's webhook testing tool
Testing:
npx @clerk/cli webhooks listen --forward-to http://localhost:3000/api/webhooks/clerkProduction Setup:
- Use live keys (
pk_live_,sk_live_) - Production mode in Clerk Dashboard
- Real emails sent to users
- Configure production webhook endpoints
Environment Variables: Set these in your hosting platform (Vercel, etc.):
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY(live key)CLERK_SECRET_KEY(live key)NEXT_PUBLIC_CLERK_SIGN_IN_URLNEXT_PUBLIC_CLERK_SIGN_UP_URL
Verification
After setup, verify everything works:
- Sign Up Flow: Create a new account at
/sign-up - Sign In Flow: Sign in at
/sign-in - Protected Routes: Try accessing a protected page without auth
- User Data: Check Clerk Dashboard → Users for new accounts
- Middleware: Verify public routes are accessible, protected routes require auth
Next Steps
How is this guide ?
Last updated on