Skip to content

Next.js Examples ​

Complete examples for using Flowfull Clients with Next.js (App Router and Pages Router).

App Router Setup ​

Root Layout with Provider ​

typescript
// app/layout.tsx
import { PubflowProvider } from '@pubflow/nextjs';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <PubflowProvider
          config={{
            baseUrl: process.env.NEXT_PUBLIC_BACKEND_URL!,
            bridgeBasePath: '/bridge',
            authBasePath: '/auth'
          }}
        >
          {children}
        </PubflowProvider>
      </body>
    </html>
  );
}

Protected Page with SSR ​

typescript
// app/dashboard/page.tsx
import { withPubflowAuthSSR } from '@pubflow/nextjs';

export const getServerSideProps = withPubflowAuthSSR(
  async (context, api, auth, user) => {
    const users = await api.get('/bridge/users?limit=10');
    
    return {
      props: {
        user,
        users
      }
    };
  },
  {
    allowedTypes: ['admin', 'user'],
    loginRedirectPath: '/login'
  }
);

export default function Dashboard({ user, users }: any) {
  return (
    <div>
      <h1>Welcome, {user.name}!</h1>
      <ul>
        {users.data.map((u: any) => (
          <li key={u.id}>{u.name}</li>
        ))}
      </ul>
    </div>
  );
}

API Routes ​

Public API Route ​

typescript
// app/api/users/route.ts
import { withPubflow } from '@pubflow/nextjs';

export const GET = withPubflow(async (req, res, api, auth) => {
  const users = await api.get('/bridge/users');
  return Response.json(users);
});

Protected API Route ​

typescript
// app/api/admin/users/route.ts
import { withPubflowAuth } from '@pubflow/nextjs';

export const GET = withPubflowAuth(
  async (req, res, api, auth, user) => {
    const users = await api.get('/bridge/users');
    return Response.json({ user, users });
  },
  {
    allowedTypes: ['admin']
  }
);

Client Components ​

Login Form ​

typescript
// app/login/page.tsx
'use client';

import { useState } from 'react';
import { useAuth } from '@pubflow/nextjs';
import { useRouter } from 'next/navigation';

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

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    setError('');

    try {
      const result = await login({ email, password });
      
      if (result.success) {
        router.push('/dashboard');
      } else {
        setError(result.error || 'Login failed');
      }
    } catch (err) {
      setError('An error occurred');
    }
  }

  return (
    <div>
      <h1>Login</h1>
      <form onSubmit={handleSubmit}>
        <input
          type="email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
          placeholder="Email"
          required
        />
        <input
          type="password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
          placeholder="Password"
          required
        />
        <button type="submit" disabled={isLoading}>
          {isLoading ? 'Logging in...' : 'Login'}
        </button>
        {error && <div>{error}</div>}
      </form>
    </div>
  );
}

User List with Client-Side Fetching ​

typescript
// app/users/page.tsx
'use client';

import { useBridgeApi, useBridgeQuery } from '@pubflow/nextjs';

interface User {
  id: string;
  name: string;
  email: string;
}

export default function UsersPage() {
  const userService = useBridgeApi<User>({ endpoint: 'users' });
  const { data, isLoading, error } = useBridgeQuery(
    userService,
    'list',
    { limit: 20 }
  );

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;

  return (
    <div>
      <h1>Users</h1>
      <ul>
        {data?.map(user => (
          <li key={user.id}>
            {user.name} - {user.email}
          </li>
        ))}
      </ul>
    </div>
  );
}

Pages Router (Legacy) ​

Protected Page ​

typescript
// pages/dashboard.tsx
import { withPubflowAuthSSR } from '@pubflow/nextjs';

export const getServerSideProps = withPubflowAuthSSR(
  async (context, api, auth, user) => {
    return {
      props: { user }
    };
  }
);

export default function Dashboard({ user }: any) {
  return <h1>Welcome, {user.name}!</h1>;
}

API Route ​

typescript
// pages/api/users.ts
import { withPubflow } from '@pubflow/nextjs';

export default withPubflow(async (req, res, api, auth) => {
  const users = await api.get('/bridge/users');
  res.json(users);
});

Next Steps ​