About clerk-astro-patterns
A reference skill for coding agents integrating Clerk into Astro 5+ projects with `@clerk/astro` v4+. It covers authentication patterns for SSR pages, prerendered pages, islands, and API routes.
Key features
- 01Explains SSR and static-page auth
- 02Covers middleware setup
- 03Guides auth for island components
- 04Covers API route authentication
- 05Lists SDK imports and environment variables
Use cases
- 01Protect an Astro SSR page
- 02Add authentication to an API route
- 03Use Clerk in a client-rendered island
Install
Copy the command and run it in a terminal.
npx skills add https:/ / github.com/ clerk/ skills --skill clerk-astro-patternsAfter installing, type/clerk-astro-patternsin Claude Code to confirm it loaded.
Bundled files
References and scripts installed along with SKILL.md.
evals/evals.jsonreferences/api-routes.mdastro-react.mdisland-components.mdmiddleware.mdssr-pages.mdtemplates/astro-basic-auth/astro.config.mjspackage.jsontsconfig.jsontemplates/astro-basic-auth/src/middleware.tstemplates/astro-basic-auth/src/layouts/Layout.astrotemplates/astro-basic-auth/src/pages/index.astrosign-in.astroDetails
From the project READMEAstro Patterns
SDK: @clerk/astro v4+. Requires Astro 5+.
What Do You Need?
| Task | Reference |
|---|---|
Configure middleware (bare clerkMiddleware(), checks per page) | 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 } from '@clerk/astro/server'
export const onRequest = clerkMiddleware()
The middleware populates Astro.locals.auth(). Each page and API route checks for itself. createRouteMatcher was removed in @clerk/astro 4.0 (deprecated in 3.x). Don't add it. Existing uses must move to page and API-route checks before upgrading. See the Astro clerkMiddleware() reference.
SSR Page Auth
---
const { userId, orgId } = Astro.locals.auth()
if (!userId) return Astro.redirect('/sign-in')
---
<h1>Dashboard</h1>
API Route Auth
// src/pages/api/data.ts
import type { APIRoute } from 'astro'
export const GET: APIRoute = ({ locals }) => {
const { userId } = locals.auth()
if (!userId) return new Response('Unauthorized', { status: 401 })
return Response.json({ userId })
}
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, clerkClient | @clerk/astro/server |
useAuth, UserButton (no useUser) | @clerk/astro/react |
$userStore, $authStore | @clerk/astro/client |
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