Módulo de Auth — Clerk (Next.js 16 / App Router)
Módulo de autenticación construido sobre @clerk/nextjs (Core 3 / v7).
Dependencias
@clerk/nextjs
Mapa de archivos
proxy.ts # Route protection (Next.js 16 middleware replacement)
app/
├── sign-in/[[...sign-in]]/page.tsx # Sign-in page (see client.ts for the component)
└── sign-up/[[...sign-up]]/page.tsx # Sign-up page (see client.ts for the component)
lib/clerk/
├── service.ts # Server-only logic. Don't touch — everything else calls into this.
├── actions.ts # Server Actions for Server Components ("use server")
├── types.ts # AuthUser, AuthSession, AuthResult<T>
└── client.ts # Client component/hook re-exports + copy-paste usage examples
.env.local # Clerk keys and URLs
| Necesito... | Ir a |
|---|---|
| Obtener el usuario actual en un Server Component | lib/clerk/service.ts → getUser() / requireUser() |
| Llamar a auth desde un Server Component (botón, formulario) | lib/clerk/actions.ts |
| Agregar un tipo para algo relacionado con auth | lib/clerk/types.ts |
Renderizar <SignIn/>, <SignUp/>, <UserButton/>, <Show/>, o usar un hook de cliente | lib/clerk/client.ts |
| Cambiar qué rutas son públicas/protegidas | proxy.ts (raíz del proyecto) |
Configuración
1. Variables de entorno
Completá .env.local con las keys de tu instancia de Clerk (Dashboard → API Keys):
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=
CLERK_SECRET_KEY=
2. Envolvé la app con ClerkProvider
// app/layout.tsx
import { ClerkProvider } from "@/lib/clerk/client";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<ClerkProvider>
<html lang="en">
<body>{children}</body>
</html>
</ClerkProvider>
);
}
3. Páginas de inicio de sesión / registro
Ya están cubiertas por app/sign-in/[[...sign-in]]/page.tsx y app/sign-up/[[...sign-up]]/page.tsx: mirá client.ts para ver el código exacto del componente que tenés que pegar.
4. proxy.ts
Ya está configurado en la raíz del proyecto. createRouteMatcher() está deprecado, por lo que ya no decide qué es público o privado: solo adjunta el contexto de sesión de Clerk a cada request. La protección real ocurre por recurso: llamá a requireUser() de lib/clerk/service.ts al principio de cualquier Server Component, Server Action o Route Handler que necesite un usuario con sesión iniciada. Una página es "pública" simplemente porque nada en ella llama a requireUser().
Checklist del Clerk Dashboard
Configurá esto directamente en el Dashboard: no hace falta código de este lado:
- Inicio de sesión con email + contraseña habilitado
- Verificación de email habilitada
- Flujo de olvidé mi contraseña / restablecer contraseña habilitado
- Proveedores OAuth conectados: Google, GitHub, Apple, Facebook
- Los paths de inicio de sesión/registro en Dashboard → Paths coinciden con
/sign-iny/sign-up
No incluido en este módulo (fuera de alcance): Magic Link, MFA/2FA, Passkeys, roles/permisos, organizaciones.
Ejemplos de uso
Proteger un Server Component:
import { requireUser } from "@/lib/clerk/service";
export default async function DashboardPage() {
const user = await requireUser(); // redirects to /sign-in if not authenticated
return <p>Welcome, {user.firstName}</p>;
}
Menú de usuario (avatar, perfil, cerrar sesión):
import { UserButton } from "@/lib/clerk/client";
<UserButton />
Cerrar sesión desde una Server Action:
import { signOutAction } from "@/lib/clerk/actions";
<form action={signOutAction}>
<button type="submit">Sign out</button>
</form>
Mostrar contenido según el estado de la sesión:
import { Show } from "@/lib/clerk/client";
<Show when="signed-in">You're logged in</Show>
<Show when="signed-out">Please sign in</Show>