> ## Documentation Index
> Fetch the complete documentation index at: https://usegately.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Next.js SDK

> Official Next.js SDK for Gately - App Router, Server Components, and middleware support

The **@gately/nextjs** SDK provides production-ready authentication for Next.js applications with App Router, Server Components, and middleware support.

<Info>
  **Version:** @gately/nextjs\@2.2.0\
  **Features:** `useGately` hook, `GatelyProvider`, server utilities, route middleware, SSR support
</Info>

## Installation

```bash theme={null}
npm install @gately/nextjs@latest
```

Or install a specific version:

```bash theme={null}
npm install @gately/nextjs@2.2.0
```

Get your API key: **[Dashboard → Settings → API Keys](https://www.usegately.com/dashboard?settings=api)**

## Quick Start

### 1. Create a Providers Component

Because `GatelyProvider` uses browser APIs, it must run client-side:

```tsx theme={null}
// app/components/providers.tsx
'use client'
import { GatelyProvider } from '@gately/nextjs'

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <GatelyProvider apiKey={process.env.NEXT_PUBLIC_GATELY_API_KEY!}>
      {children}
    </GatelyProvider>
  )
}
```

### 2. Add to Root Layout

```tsx theme={null}
// app/layout.tsx
import { Providers } from './components/providers'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <Providers>{children}</Providers>
      </body>
    </html>
  )
}
```

### 3. Use in Client Components

```tsx theme={null}
// app/dashboard/page.tsx
'use client'
import { useGately } from '@gately/nextjs'

export default function DashboardPage() {
  const { user, isAuthenticated, isLoading, logout } = useGately()

  if (isLoading) return <div>Loading...</div>
  if (!isAuthenticated) return <div>Not logged in</div>

  return (
    <div>
      <h1>Welcome, {user?.email}!</h1>
      <button onClick={logout}>Logout</button>
    </div>
  )
}
```

### 4. Protect Pages with Middleware

```typescript theme={null}
// middleware.ts
import { gatelyMiddleware } from '@gately/nextjs/middleware'
import type { NextRequest } from 'next/server'

export async function middleware(request: NextRequest) {
  return gatelyMiddleware(request, {
    apiKey: process.env.NEXT_PUBLIC_GATELY_API_KEY!,
    protectedRoutes: ['/dashboard'],
    redirectToLogin: '/login'
  })
}

export const config = {
  matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)']
}
```

## GatelyProvider

```tsx theme={null}
import { GatelyProvider } from '@gately/nextjs'

<GatelyProvider
  apiKey={process.env.NEXT_PUBLIC_GATELY_API_KEY!}
  apiUrl="https://api.usegately.com"  // optional
  autoRefresh={true}                   // optional, default: true
>
  {children}
</GatelyProvider>
```

| Prop          | Type      | Required | Description                             |
| ------------- | --------- | -------- | --------------------------------------- |
| `apiKey`      | `string`  | ✅        | Your Gately API key                     |
| `apiUrl`      | `string`  | No       | Custom API URL                          |
| `autoRefresh` | `boolean` | No       | Auto-refresh sessions (default: `true`) |

## useGately Hook

For use in `'use client'` components:

```tsx theme={null}
'use client'
import { useGately } from '@gately/nextjs'

export function ProfileCard() {
  const {
    user,
    session,
    isAuthenticated,
    isLoading,
    error,
    login,
    signup,
    logout,
    sendMagicLink,
    resetPassword,
    updateUserProfile,
    changePassword
  } = useGately()

  // ...
}
```

## Server Utilities

Use in Server Components, Route Handlers, and Server Actions:

```typescript theme={null}
import { getSession, getUser, isAuthenticated } from '@gately/nextjs/server'
```

### getSession()

```typescript theme={null}
// app/dashboard/page.tsx
import { getSession } from '@gately/nextjs/server'
import { redirect } from 'next/navigation'

export default async function DashboardPage() {
  const session = await getSession()

  if (!session) redirect('/login')

  return <h1>Welcome, {session.user?.email}</h1>
}
```

### getUser()

```typescript theme={null}
import { getUser } from '@gately/nextjs/server'

export default async function Page() {
  const user = await getUser()
  return <p>{user?.email}</p>
}
```

### isAuthenticated()

```typescript theme={null}
import { isAuthenticated } from '@gately/nextjs/server'

export default async function Page() {
  if (!await isAuthenticated()) redirect('/login')
  return <div>Protected content</div>
}
```

### API Route Handler

```typescript theme={null}
// app/api/profile/route.ts
import { getSession } from '@gately/nextjs/server'

export async function GET() {
  const session = await getSession()

  if (!session) {
    return Response.json({ error: 'Unauthorized' }, { status: 401 })
  }

  return Response.json({ user: session.user })
}
```

## Middleware

### gatelyMiddleware

Supports two calling styles:

**Direct (recommended):**

```typescript theme={null}
// middleware.ts
import { gatelyMiddleware } from '@gately/nextjs/middleware'
import type { NextRequest } from 'next/server'

export async function middleware(request: NextRequest) {
  return gatelyMiddleware(request, {
    apiKey: process.env.NEXT_PUBLIC_GATELY_API_KEY!,
    protectedRoutes: ['/dashboard', '/settings'],
    publicRoutes: ['/login', '/signup'],
    redirectToLogin: '/login'
  })
}
```

**Factory:**

```typescript theme={null}
import { gatelyMiddleware } from '@gately/nextjs/middleware'

export const middleware = gatelyMiddleware({
  apiKey: process.env.NEXT_PUBLIC_GATELY_API_KEY!,
  protectedRoutes: ['/dashboard'],
  redirectToLogin: '/login'
})
```

### MiddlewareConfig

| Option            | Type       | Description                             |
| ----------------- | ---------- | --------------------------------------- |
| `apiKey`          | `string`   | Your Gately API key                     |
| `protectedRoutes` | `string[]` | Routes that require authentication      |
| `publicRoutes`    | `string[]` | Routes that are always accessible       |
| `redirectToLogin` | `string`   | Where to redirect unauthenticated users |

## Login Page

```tsx theme={null}
// app/login/page.tsx
'use client'
import { useGately } from '@gately/nextjs'
import { useState, useEffect } from 'react'
import { useRouter } from 'next/navigation'

export default function LoginPage() {
  const { login, signup, isAuthenticated, isLoading, error } = useGately()
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')
  const router = useRouter()

  useEffect(() => {
    if (isAuthenticated) router.push('/dashboard')
  }, [isAuthenticated, router])

  const handleLogin = async (e: React.FormEvent) => {
    e.preventDefault()
    await login(email, password)
  }

  return (
    <form onSubmit={handleLogin}>
      <input type="email" value={email} onChange={e => setEmail(e.target.value)} />
      <input type="password" value={password} onChange={e => setPassword(e.target.value)} />
      <button type="submit" disabled={isLoading}>
        {isLoading ? 'Signing in...' : 'Sign In'}
      </button>
      {error && <p>{error.message}</p>}
    </form>
  )
}
```

## Environment Variables

```bash theme={null}
# .env.local
NEXT_PUBLIC_GATELY_API_KEY=your_api_key_here
```

## TypeScript

```typescript theme={null}
import type { User, Session } from '@gately/nextjs'
```

## Troubleshooting

<AccordionGroup>
  <Accordion title="window is not defined">
    `GatelyProvider` must be inside a `'use client'` component. See the Providers setup above — never import it directly in a Server Component.
  </Accordion>

  <Accordion title="useGately is not a function">
    Ensure you're on `@gately/nextjs@1.0.2`. Run:

    ```bash theme={null}
    npm install @gately/nextjs@latest @gately/react@latest
    ```
  </Accordion>

  <Accordion title="Redirect loop in middleware">
    Make sure your login page is in `publicRoutes` and not in `protectedRoutes`.
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="React SDK" icon="react" href="/docs/sdk/react">
    Client-side hooks reference
  </Card>

  <Card title="Node.js SDK" icon="server" href="/docs/sdk/nodejs">
    Backend token verification
  </Card>
</CardGroup>

**Support:** [support@usegately.com](mailto:support@usegately.com) · [Slack Community](https://join.slack.com/t/usegately/shared_invite/zt-3llscjz41-PuVEY5Xu0M2DCi8WEojN0Q)
