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

# Next.js App Example

> Complete Next.js application example with logto-authkit

This example demonstrates how to integrate logto-authkit into a Next.js application with both client and server-side authentication.

## Complete Example

<Steps>
  <Step title="Install Dependencies">
    Install logto-authkit and required dependencies:

    ```bash theme={null}
    npm install @ouim/logto-authkit @logto/react
    ```
  </Step>

  <Step title="Create Root Layout">
    Set up the auth provider in your root layout:

    ```tsx app/layout.tsx theme={null}
    import { AuthProvider } from '@ouim/logto-authkit'
    import './globals.css'

    export default function RootLayout({
      children,
    }: {
      children: React.ReactNode
    }) {
      return (
        <html lang="en">
          <body>
            <AuthProvider
              config={{
                endpoint: process.env.NEXT_PUBLIC_LOGTO_ENDPOINT!,
                appId: process.env.NEXT_PUBLIC_LOGTO_APP_ID!,
                resources: [process.env.NEXT_PUBLIC_API_RESOURCE!],
                scopes: ['openid', 'profile', 'email'],
              }}
              callbackUrl={`${process.env.NEXT_PUBLIC_APP_URL}/callback`}
              enablePopupSignIn={true}
            >
              {children}
            </AuthProvider>
          </body>
        </html>
      )
    }
    ```
  </Step>

  <Step title="Create Home Page">
    Build your landing page with authentication:

    ```tsx app/page.tsx theme={null}
    'use client'

    import { useAuth, UserCenter } from '@ouim/logto-authkit'
    import Link from 'next/link'

    export default function Home() {
      const { user, isLoadingUser, signIn } = useAuth()

      return (
        <div className="min-h-screen bg-gradient-to-b from-gray-50 to-gray-100">
          <nav className="bg-white shadow-sm">
            <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
              <div className="flex justify-between h-16">
                <div className="flex items-center">
                  <Link href="/" className="text-xl font-bold text-gray-900">
                    logto-authkit App
                  </Link>
                </div>
                <div className="flex items-center gap-4">
                  {user && (
                    <Link
                      href="/dashboard"
                      className="text-gray-700 hover:text-gray-900"
                    >
                      Dashboard
                    </Link>
                  )}
                  <UserCenter />
                </div>
              </div>
            </div>
          </nav>

          <main className="max-w-7xl mx-auto py-16 px-4 sm:px-6 lg:px-8">
            <div className="text-center">
              <h1 className="text-5xl font-bold text-gray-900 mb-6">
                Welcome to logto-authkit
              </h1>
              <p className="text-xl text-gray-600 mb-8 max-w-2xl mx-auto">
                A simplified authentication solution for Next.js applications.
                Get started with secure, production-ready auth in minutes.
              </p>

              {isLoadingUser ? (
                <div className="flex justify-center">
                  <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600"></div>
                </div>
              ) : user ? (
                <div className="space-y-4">
                  <div className="bg-white rounded-lg shadow-md p-6 max-w-md mx-auto">
                    <p className="text-lg font-semibold text-gray-900 mb-2">
                      Welcome back, {user.name || user.email}!
                    </p>
                    <p className="text-gray-600">
                      You are successfully authenticated.
                    </p>
                  </div>
                  <Link
                    href="/dashboard"
                    className="inline-block bg-blue-600 text-white px-8 py-3 rounded-lg hover:bg-blue-700 font-semibold"
                  >
                    Go to Dashboard
                  </Link>
                </div>
              ) : (
                <div className="space-y-4">
                  <button
                    onClick={() => signIn()}
                    className="bg-blue-600 text-white px-8 py-3 rounded-lg hover:bg-blue-700 font-semibold"
                  >
                    Sign In
                  </button>
                  <p className="text-sm text-gray-500">
                    Sign in to access your personalized dashboard
                  </p>
                </div>
              )}
            </div>
          </main>
        </div>
      )
    }
    ```
  </Step>

  <Step title="Create Protected Dashboard">
    Build a dashboard with automatic authentication protection:

    ```tsx app/dashboard/page.tsx theme={null}
    'use client'

    import { useAuth, UserCenter } from '@ouim/logto-authkit'
    import Link from 'next/link'

    export default function Dashboard() {
      const { user, isLoadingUser } = useAuth({
        middleware: 'auth',
        redirectTo: '/signin',
      })

      if (isLoadingUser) {
        return (
          <div className="flex items-center justify-center min-h-screen">
            <div className="animate-spin rounded-full h-16 w-16 border-b-2 border-blue-600"></div>
          </div>
        )
      }

      return (
        <div className="min-h-screen bg-gray-50">
          <nav className="bg-white shadow-sm">
            <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
              <div className="flex justify-between h-16">
                <div className="flex items-center">
                  <Link href="/" className="text-xl font-bold text-gray-900">
                    logto-authkit App
                  </Link>
                </div>
                <div className="flex items-center">
                  <UserCenter />
                </div>
              </div>
            </div>
          </nav>

          <main className="max-w-7xl mx-auto py-8 px-4 sm:px-6 lg:px-8">
            <div className="mb-8">
              <h1 className="text-3xl font-bold text-gray-900">Dashboard</h1>
              <p className="text-gray-600 mt-2">Welcome to your protected dashboard</p>
            </div>

            <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
              <div className="bg-white rounded-lg shadow p-6">
                <h2 className="text-xl font-semibold mb-4 text-gray-900">
                  User Profile
                </h2>
                <dl className="space-y-3">
                  <div>
                    <dt className="text-sm font-medium text-gray-500">User ID</dt>
                    <dd className="mt-1 text-sm text-gray-900 font-mono">{user?.id}</dd>
                  </div>
                  <div>
                    <dt className="text-sm font-medium text-gray-500">Name</dt>
                    <dd className="mt-1 text-sm text-gray-900">
                      {user?.name || 'Not provided'}
                    </dd>
                  </div>
                  <div>
                    <dt className="text-sm font-medium text-gray-500">Email</dt>
                    <dd className="mt-1 text-sm text-gray-900">
                      {user?.email || 'Not provided'}
                    </dd>
                  </div>
                </dl>
              </div>

              <div className="bg-white rounded-lg shadow p-6">
                <h2 className="text-xl font-semibold mb-4 text-gray-900">
                  Authentication Status
                </h2>
                <div className="space-y-3">
                  <div className="flex items-center">
                    <div className="w-3 h-3 bg-green-500 rounded-full mr-3"></div>
                    <span className="text-sm text-gray-900">Authenticated</span>
                  </div>
                  <p className="text-sm text-gray-600">
                    You have successfully authenticated and can access protected
                    resources.
                  </p>
                  <Link
                    href="/api/user"
                    target="_blank"
                    className="inline-block text-sm text-blue-600 hover:text-blue-800"
                  >
                    View API Response →
                  </Link>
                </div>
              </div>
            </div>
          </main>
        </div>
      )
    }
    ```
  </Step>

  <Step title="Create API Route with Server-Side Auth">
    Add a protected API route using server-side authentication:

    ```ts app/api/user/route.ts theme={null}
    import { NextRequest, NextResponse } from 'next/server'
    import { verifyNextAuth } from '@ouim/logto-authkit/server'

    export async function GET(request: NextRequest) {
      const result = await verifyNextAuth(request, {
        logtoUrl: process.env.LOGTO_ENDPOINT!,
        audience: process.env.LOGTO_API_RESOURCE!,
      })

      if (!result.success) {
        return NextResponse.json(
          { error: result.error },
          { status: 401 }
        )
      }

      // Access authenticated user info
      const { auth } = result

      return NextResponse.json({
        userId: auth.userId,
        isAuthenticated: auth.isAuthenticated,
        payload: auth.payload,
      })
    }
    ```
  </Step>

  <Step title="Add Authentication Pages">
    Create the required callback and sign-in pages:

    <CodeGroup>
      ```tsx app/callback/page.tsx theme={null}
      'use client'

      import { CallbackPage } from '@ouim/logto-authkit'

      export default function Callback() {
        return (
          <CallbackPage
            onSuccess={() => {
              console.log('Authentication successful')
            }}
            onError={(error) => {
              console.error('Authentication failed:', error)
            }}
          />
        )
      }
      ```

      ```tsx app/signin/page.tsx theme={null}
      'use client'

      import { SignInPage } from '@ouim/logto-authkit'

      export default function SignIn() {
        return <SignInPage />
      }
      ```
    </CodeGroup>
  </Step>

  <Step title="Configure Environment Variables">
    Create a `.env.local` file with your Logto configuration:

    ```bash .env.local theme={null}
    NEXT_PUBLIC_LOGTO_ENDPOINT=https://your-tenant.logto.app
    NEXT_PUBLIC_LOGTO_APP_ID=your-app-id
    NEXT_PUBLIC_API_RESOURCE=https://api.yourapp.com
    NEXT_PUBLIC_APP_URL=http://localhost:3000

    # Server-side variables
    LOGTO_ENDPOINT=https://your-tenant.logto.app
    LOGTO_API_RESOURCE=https://api.yourapp.com
    ```
  </Step>
</Steps>

## Server-Side Authentication

logto-authkit supports server-side authentication for API routes and middleware:

<Tabs>
  <Tab title="API Routes">
    ```ts app/api/protected/route.ts theme={null}
    import { NextRequest, NextResponse } from 'next/server'
    import { verifyNextAuth } from '@ouim/logto-authkit/server'

    export async function GET(request: NextRequest) {
      const result = await verifyNextAuth(request, {
        logtoUrl: process.env.LOGTO_ENDPOINT!,
        audience: process.env.LOGTO_API_RESOURCE!,
      })

      if (!result.success) {
        return NextResponse.json(
          { error: 'Unauthorized' },
          { status: 401 }
        )
      }

      return NextResponse.json({
        message: 'Protected data',
        userId: result.auth.userId,
      })
    }
    ```
  </Tab>

  <Tab title="Middleware">
    ```ts middleware.ts theme={null}
    import { NextResponse } from 'next/server'
    import type { NextRequest } from 'next/server'
    import { verifyNextAuth } from '@ouim/logto-authkit/server'

    export async function middleware(request: NextRequest) {
      // Only protect API routes
      if (request.nextUrl.pathname.startsWith('/api/protected')) {
        const result = await verifyNextAuth(request, {
          logtoUrl: process.env.LOGTO_ENDPOINT!,
          audience: process.env.LOGTO_API_RESOURCE!,
        })

        if (!result.success) {
          return NextResponse.json(
            { error: 'Unauthorized' },
            { status: 401 }
          )
        }
      }

      return NextResponse.next()
    }

    export const config = {
      matcher: '/api/protected/:path*',
    }
    ```
  </Tab>
</Tabs>

## Features Demonstrated

* **Next.js App Router**: Full integration with App Router
* **Client-Side Auth**: Protected pages with automatic redirects
* **Server-Side Auth**: Secure API routes with JWT verification
* **Environment Variables**: Proper configuration management
* **Popup Sign-In**: Optional popup-based authentication
* **User Center**: Pre-built UI component for user management

## Running the Example

```bash theme={null}
npm run dev
```

Visit `http://localhost:3000` to see your Next.js app with authentication.

## Next Steps

<CardGroup cols={2}>
  <Card title="Protected Routes" icon="lock" href="/logto-authkit/examples/protected-routes">
    Advanced route protection patterns
  </Card>

  <Card title="Server Integration" icon="server" href="/logto-authkit/server/overview">
    Learn more about server-side auth
  </Card>
</CardGroup>
