# redwood-clerk

Unofficial [Clerk](https://clerk.com/) integration for RedwoodSDK.

Minimal example: https://github.com/wobsoriano/redwood-clerk-minimal

## Installation

```bash
npm install redwood-clerk
```

## Quickstart

### Add `clerkMiddleware()` to your app

`clerkMiddleware()` grants you access to user authentication state throughout your app.

In your entry point (`src/worker.tsx`) file, add the `clerkMiddleware()` helper to the `defineApp` function:

```tsx
import { clerkMiddleware } from 'redwood-clerk/server';
import type { ClerkAppContext } from 'redwood-clerk/server';

export type AppContext = ClerkAppContext & {
  // Addition context properties
};

export default defineApp([
  setCommonHeaders(),
  clerkMiddleware(),
  render(Document, [...]),
]);
```

### Configure Clerk Content-Security-Policy headers

In your `src/app/headers.ts` file, update the `Content-Security-Policy` header for Clerk to work correctly in your application:

```ts
import { frontendApi } from 'redwood-clerk/server';

const cspHeader = `
  default-src 'self';
  script-src 'self' 'strict-dynamic' 'nonce-${nonce}' https://${frontendApi} https://challenges.cloudflare.com;
  connect-src 'self' https://${frontendApi};
  img-src 'self' https://img.clerk.com;
  style-src 'self' 'unsafe-inline';
  frame-src https://challenges.cloudflare.com;
  object-src 'none';
  form-action 'self';
`

headers.set('Content-Security-Policy', cspHeader.replace(/\n/g, ''));
```

### Add `<ClerkProvider>` to your app

Add the `<ClerkProvider>` component to your app's layout. This component provides Clerk's authentication context to your app.

```tsx
import {
  ClerkProvider,
  SignInButton,
  SignUpButton,
  SignedIn,
  SignedOut,
  UserButton,
} from 'redwood-clerk';

export const AppLayout = ({ children }) => {
	return (
		<ClerkProvider>
		  <header>
        <SignedOut>
          <SignInButton />
          <SignUpButton />
        </SignedOut>
        <SignedIn>
          <UserButton />
        </SignedIn>
      </header>
			{children}
		</ClerkProvider>
	);
}
```

### Create your first user

Run your project in development mode and go to http://localhost:5173

## Read session and user data in your RedwoodSDK app

### Server components

```tsx
import { auth, clerkClient } from 'redwood-clerk/server'

export default async function Page() {
  const { userId } = await auth()

  // Protect the route by checking if the user is signed in
  if (!userId) {
    return <div>Sign in to view this page</div>
  }

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

  return <div>Welcome, {user.firstName}!</div>
}
```

### Client components

```tsx
'use client'
import { useAuth } from 'redwood-clerk'

export default function Example() {
  const { isLoaded, isSignedIn, userId } = useAuth()

  // Use `isLoaded` to check if Clerk is loaded
  if (!isLoaded) {
    return <div>Loading...</div>
  }

  // Use `isSignedIn` to check if the user is signed in
  if (!isSignedIn) {
    return <div>Sign in to view this page</div>
  }

  return (
    <div>
      Hello, {userId}! Your current active session is {sessionId}.
    </div>
  )
}
````

## License

MIT
