{"id":14570,"plugin_id":"plugin_asdk_app_6a9a3c1cd0108191807da33c4cd319ed","kind":"skill","collection_source":null,"comparison_source":null,"observed_at":"2026-09-30T23:09:49.199Z","digest":"4960b72c523a2e754c20fbc46cdbcf1fbe04de05eb1d214e659035cd15becfe0","against":null,"payload":{"name":"clerk-astro-patterns","description":"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.","included_files":[{"relative_path":"evals/evals.json","size_in_bytes":5580},{"relative_path":"references/api-routes.md","size_in_bytes":2009},{"relative_path":"references/astro-react.md","size_in_bytes":2309},{"relative_path":"references/island-components.md","size_in_bytes":1456},{"relative_path":"references/middleware.md","size_in_bytes":1645},{"relative_path":"references/ssr-pages.md","size_in_bytes":1811},{"relative_path":"templates/astro-basic-auth/astro.config.mjs","size_in_bytes":229},{"relative_path":"templates/astro-basic-auth/package.json","size_in_bytes":227},{"relative_path":"templates/astro-basic-auth/src/layouts/Layout.astro","size_in_bytes":520},{"relative_path":"templates/astro-basic-auth/src/middleware.ts","size_in_bytes":98},{"relative_path":"templates/astro-basic-auth/src/pages/index.astro","size_in_bytes":258},{"relative_path":"templates/astro-basic-auth/tsconfig.json","size_in_bytes":42}],"skill_md_contents":"---\nname: clerk-astro-patterns\ndescription: 'Astro patterns with Clerk — middleware, SSR pages, island components,\n  API routes, static vs SSR rendering. Triggers on: astro clerk, clerk astro middleware,\n  astro protected page, clerk island component, astro API route auth, clerk astro\n  SSR.'\nlicense: MIT\nallowed-tools: WebFetch\nmetadata:\n  author: clerk\n  version: 1.0.0\n---\n\n# Astro Patterns\n\nSDK: `@clerk/astro` v3+. Requires Astro 4.15+.\n\n## What Do You Need?\n\n| Task | Reference |\n|------|-----------|\n| Configure middleware | references/middleware.md |\n| Protect SSR pages | references/ssr-pages.md |\n| Use Clerk in island components | references/island-components.md |\n| Auth in API routes | references/api-routes.md |\n| Use Clerk with React in Astro | references/astro-react.md |\n\n## Mental Model\n\nAstro has two rendering modes per page: **SSR** and **static prerender**. Clerk works differently in each:\n\n- **SSR pages** — use `Astro.locals.auth()` which is populated by the middleware\n- **Static pages** (`export const prerender = true`) — Clerk middleware skips them; use client-side hooks in islands\n- **Islands** — React/Vue/Svelte components; use `useAuth()` and other hooks from `@clerk/astro/react`\n\n```\nRequest → clerkMiddleware() → SSR page → Astro.locals.auth()\n                                ↓\n                         Island (.client) → useAuth() hook\n```\n\n## Setup\n\n### astro.config.mjs\n\n```ts\nimport { defineConfig } from 'astro/config'\nimport clerk from '@clerk/astro'\n\nexport default defineConfig({\n  integrations: [clerk()],\n  output: 'server',\n})\n```\n\n### src/middleware.ts\n\n```ts\nimport { clerkMiddleware, createRouteMatcher } from '@clerk/astro/server'\n\nconst isProtectedRoute = createRouteMatcher(['/dashboard(.*)'])\n\nexport const onRequest = clerkMiddleware((auth, context, next) => {\n  if (isProtectedRoute(context.request) && !auth().userId) {\n    return auth().redirectToSignIn()\n  }\n  return next()\n})\n```\n\n## SSR Page Auth\n\n```astro\n---\nconst { userId, orgId } = Astro.locals.auth()\nif (!userId) return Astro.redirect('/sign-in')\n---\n\n<h1>Dashboard</h1>\n```\n\n## Common Pitfalls\n\n| Symptom | Cause | Fix |\n|---------|-------|-----|\n| `Astro.locals.auth` is undefined | Missing middleware | Add `clerkMiddleware` to `src/middleware.ts` |\n| Auth works in dev but not production | `output: 'static'` globally | Set `output: 'server'` or `hybrid` for protected pages |\n| Static page has no auth | Prerendered pages skip middleware | Use `export const prerender = false` or move to island |\n| Island not reactive to sign-in | Missing `client:load` directive | Add `client:load` to the island component |\n\n## Import Map\n\n| What | Import From |\n|------|-------------|\n| `clerkMiddleware`, `createRouteMatcher` | `@clerk/astro/server` |\n| `useAuth`, `useUser`, `UserButton` | `@clerk/astro/react` |\n| Astro components (`<SignIn>`, etc.) | `@clerk/astro/components` |\n\n## Env Variables\n\n```\n# .env\nPUBLIC_CLERK_PUBLISHABLE_KEY=pk_...\nCLERK_SECRET_KEY=sk_...\n```\n\nAstro uses `PUBLIC_` prefix for client-exposed variables (not `NEXT_PUBLIC_`).\n\n## See Also\n\n- `clerk-setup` - Initial Clerk install\n- `clerk-custom-ui` - Custom flows & appearance\n- `clerk-orgs` - B2B organizations\n\n## Docs\n\n[Astro SDK](https://clerk.com/docs/astro/getting-started/quickstart)\n"},"changes":[],"summary":"First saved snapshot. No earlier version is available for comparison.","summary_kind":"deterministic","summary_metadata":{}}