clerk-astro-patterns
This skill provides best practices and patterns for integrating Clerk authentication into Astro applications. It covers authentication implementation in middleware, SSR pages, and island components, ensuring secure and seamless user authentication across various rendering modes. Developers can quickly build robust authentication solutions, enhancing application security and user management within their Astro projects.
npx skills add https://github.com/clerk/skills --skill clerk-astro-patternsBefore / After Comparison
1 组In development, Clerk authentication functions correctly, but upon deployment to production, user authentication fails, preventing access to protected pages. This often leads to significant time spent debugging configuration issues, typically several hours.
By following Clerk Astro patterns and explicitly configuring `output: 'server'` or `hybrid`, production SSR pages correctly handle authentication logic. This reduces authentication debugging time from hours to minutes, significantly improving deployment efficiency.
Astro Patterns
SDK: @clerk/astro v3+. Requires Astro 4.15+.
What Do You Need?
| Task | Reference |
|---|---|
| Configure middleware | references/middleware.md |
| Protect SSR pages | references/ssr-pages.md |
| Use Clerk in island components | references/island-components.md |
| Auth in API routes | references/api-routes.md |
| Use Clerk with React in Astro | references/astro-react.md |
Mental Model
Astro has two rendering modes per page: SSR and static prerender. Clerk works differently in each:
- SSR pages — use
Astro.locals.auth()which is populated by the middleware - Static pages (
export const prerender = true) — Clerk middleware skips them; use client-side hooks in islands - Islands — React/Vue/Svelte components; use
useAuth()and other hooks from@clerk/astro/react
Request → clerkMiddleware() → SSR page → Astro.locals.auth()
↓
Island (.client) → useAuth() hook
Setup
astro.config.mjs
import { defineConfig } from 'astro/config'
import clerk from '@clerk/astro'
export default defineConfig({
integrations: [clerk()],
output: 'server',
})
src/middleware.ts
import { clerkMiddleware, createRouteMatcher } from '@clerk/astro/server'
const isProtectedRoute = createRouteMatcher(['/dashboard(.*)'])
export const onRequest = clerkMiddleware((auth, context, next) => {
if (isProtectedRoute(context.request) && !auth().userId) {
return auth().redirectToSignIn()
}
return next()
})
SSR Page Auth
---
const { userId, orgId } = Astro.locals.auth()
if (!userId) return Astro.redirect('/sign-in')
---
<h1>Dashboard</h1>
Common Pitfalls
| Symptom | Cause | Fix |
|---|---|---|
Astro.locals.auth is undefined | Missing middleware | Add clerkMiddleware to src/middleware.ts |
| Auth works in dev but not production | output: 'static' globally | Set output: 'server' or hybrid for protected pages |
| Static page has no auth | Prerendered pages skip middleware | Use export const prerender = false or move to island |
| Island not reactive to sign-in | Missing client:load directive | Add client:load to the island component |
Import Map
| What | Import From |
|---|---|
clerkMiddleware, createRouteMatcher | @clerk/astro/server |
useAuth, useUser, UserButton | @clerk/astro/react |
Astro components (<SignIn>, etc.) | @clerk/astro/components |
Env Variables
# .env
PUBLIC_CLERK_PUBLISHABLE_KEY=pk_...
CLERK_SECRET_KEY=sk_...
Astro uses PUBLIC_ prefix for client-exposed variables (not NEXT_PUBLIC_).
See Also
clerk-setup- Initial Clerk installclerk-custom-ui- Custom flows & appearanceclerk-orgs- B2B organizations
Docs
User Reviews (0)
Write a Review
No reviews yet
Statistics
User Rating
Rate this Skill