All skills
clerk avatar

/clerk-astro-patterns

@932e2dd official
by clerkclerk/skills83 stars
5

Astro patterns with Clerk — middleware, SSR pages, island components, API routes, static vs SSR rendering. Triggers on: astro clerk, clerk astro middleware, astro protected page, clerk island component, astro API route auth, clerk astro SSR.

Use this Skill: https://skilld.dev/gh/clerk/skills/clerk-astro-patterns

This session only. Nothing lands on disk.

referencesapi-routes.md

≈503 tokens on demand. Your agent reads this file only when SKILL.md points to it.

API Routes

Basic Auth Check

// src/pages/api/data.ts
import type { APIRoute } from 'astro'

export const GET: APIRoute = async (context) => {
  const { userId } = context.locals.auth()

  if (!userId) {
    return new Response('Unauthorized', { status: 401 })
  }

  const data = await fetchData(userId)
  return new Response(JSON.stringify(data), {
    headers: { 'Content-Type': 'application/json' },
  })
}

POST with Org Check

export const POST: APIRoute = async (context) => {
  const { userId, orgId } = context.locals.auth()

  if (!userId) return new Response('Unauthorized', { status: 401 })
  if (!orgId) return new Response('No active org', { status: 403 })

  const body = await context.request.json()
  await saveOrgData(orgId, body)

  return new Response(JSON.stringify({ ok: true }), {
    headers: { 'Content-Type': 'application/json' },
  })
}

Permission Check

export const DELETE: APIRoute = async (context) => {
  const auth = context.locals.auth()
  if (!auth.userId) return new Response('Unauthorized', { status: 401 })

  const canDelete = auth.has({ permission: 'org:items:delete' })
  if (!canDelete) return new Response('Forbidden', { status: 403 })

  await deleteItem(context.params.id!)
  return new Response(null, { status: 204 })
}

Using clerkClient in API Routes

import { clerkClient } from '@clerk/astro/server'

export const GET: APIRoute = async (context) => {
  const { userId } = context.locals.auth()
  if (!userId) return new Response('Unauthorized', { status: 401 })

  const client = clerkClient(context)
  const user = await client.users.getUser(userId)

  return new Response(JSON.stringify({ name: user.fullName }), {
    headers: { 'Content-Type': 'application/json' },
  })
}

CRITICAL

  • API routes are always SSR — prerender does not apply
  • Use context.locals.auth() (not Astro.locals.auth()) in API routes
  • Return proper HTTP status codes: 401 = not authenticated, 403 = not authorized

Source: SKILL.md on GitHub

No alerts16d4 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    The skill provides safe documentation, templates, and patterns for integrating Clerk authentication with the Astro framework. No security issues, malicious code, or unsafe data practices were detected.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: LOW · No issues

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 932e2dd. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated 6 months ago
What it can do
Network
metadata
{
  "author": "clerk",
  "version": "1.0.0"
}
All 1 allowed tools
WebFetch
  • TypeScript
  • astro
  • clerk
  • authentication
  • middleware
  • ssr
  • api-routes
  • island-components

README badge

README badge for clerk/skills/clerk-astro-patterns

Provides Clerk authentication patterns for Astro projects using @clerk/astro v3+, covering middleware setup, SSR page protection, island components, and API route auth across Astro's static and server rendering modes. Includes import paths, config examples, and a troubleshooting table for common integration issues.

Generated from the current SKILL.md.

Does this skill work with static Astro sites?
Partially. Clerk middleware skips static prerendered pages; you must use `export const prerender = false` or move authentication logic to client-side island components with `client:load`.
What Astro and Clerk SDK versions are required?
Astro 4.15 or later and @clerk/astro v3 or later.
How do I protect pages with authentication?
Use `clerkMiddleware` in `src/middleware.ts` with `createRouteMatcher` to define protected routes, then check `auth().userId` and redirect to sign-in if needed. For SSR pages, retrieve auth from `Astro.locals.auth()`.
Can I use Clerk in React island components?
Yes. Import hooks like `useAuth()` and `useUser()` from `@clerk/astro/react`, and ensure the island component has the `client:load` directive.
Why is `Astro.locals.auth` undefined?
The Clerk middleware is missing. Add `clerkMiddleware` and `onRequest` to `src/middleware.ts`.

Generated from the current SKILL.md. These answers refresh after source changes.