Getting Started
Get up and running with Flowfull Clients in minutes. This guide will walk you through installation, setup, and your first API call.
🚀 Fastest Way to Start
Want to skip the setup? Use our Official Starter Kits - production-ready templates with everything configured:
- TanStack Start (React): github.com/pubflow/flowfull-client
- React Native Expo: github.com/pubflow/create-pubflow-rn
Prerequisites
Before you begin, make sure you have:
- Node.js 18+ installed
- A Flowfull backend deployed and running (Create one)
- Flowless authentication configured in your backend (Setup Flowless)
- Basic knowledge of React, React Native, or Next.js
📋 Backend Required
Flowfull Clients are frontend libraries that need a Flowfull backend to connect to. You have two options:
Use a Starter Kit (Recommended) - Pre-configured frontend with example backend connection
- TanStack Start - React frontend starter
- React Native Expo - Mobile frontend starter
- Both connect to Flowless (pubflow.com) for authentication
Build from Scratch - Create your complete stack:
- Step 1: Create Flowless Instance - Authentication backend (managed service)
- Step 2: Build Flowfull Backend - Your custom backend with business logic (using flowfull-node)
- Step 3: Install Flowfull Clients (this guide) - Your frontend that consumes your Flowfull backend
Architecture: Frontend (Flowfull Clients) → Backend (Flowfull) → Auth (Flowless)
💳 Need Payments?
Add payment processing with Bridge Payments - Works seamlessly with Flowfull Clients!
Choose Your Framework
Select the guide that matches your project:
npm install @pubflow/core @pubflow/react swrnpm install @pubflow/core @pubflow/react-native swr
npm install @react-native-async-storage/async-storagenpm install @pubflow/core @pubflow/nextjs swrQuick Start: React
1. Setup Provider
Wrap your app with PubflowProvider:
// src/App.tsx
import { PubflowProvider } from '@pubflow/react';
function App() {
return (
<PubflowProvider url="https://your-backend.com">
<YourApp />
</PubflowProvider>
);
}2. Add Authentication
Create a login component:
// src/components/Login.tsx
import { useAuth } from '@pubflow/react';
import { useState } from 'react';
export function Login() {
const { login, isLoading } = useAuth();
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
try {
await login({ email, password });
// User is now logged in!
} catch (error) {
console.error('Login failed:', error);
}
};
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value.toLowerCase())}
placeholder="Email"
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
/>
<button type="submit" disabled={isLoading}>
{isLoading ? 'Logging in...' : 'Login'}
</button>
</form>
);
}3. Fetch Data
Use useBridgeQuery to fetch data from your backend:
// src/components/UserList.tsx
import { useBridgeQuery } from '@pubflow/react';
export function UserList() {
const { data, error, isLoading } = useBridgeQuery('/api/users');
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<ul>
{data.map((user: any) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}4. Create Data
Use useBridgeMutation to create or update data:
// src/components/CreateUser.tsx
import { useBridgeMutation } from '@pubflow/react';
import { useState } from 'react';
export function CreateUser() {
const { trigger, isMutating } = useBridgeMutation('/api/users', 'POST');
const [name, setName] = useState('');
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
try {
const newUser = await trigger({ name });
console.log('User created:', newUser);
setName('');
} catch (error) {
console.error('Failed to create user:', error);
}
};
return (
<form onSubmit={handleSubmit}>
<input
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Name"
/>
<button type="submit" disabled={isMutating}>
{isMutating ? 'Creating...' : 'Create User'}
</button>
</form>
);
}Quick Start: React Native
1. Setup Provider
// App.tsx
import { PubflowProvider } from '@pubflow/react-native';
import { SafeAreaView } from 'react-native';
export default function App() {
return (
<PubflowProvider url="https://your-backend.com">
<SafeAreaView style={{ flex: 1 }}>
<YourApp />
</SafeAreaView>
</PubflowProvider>
);
}2. Add Authentication
// screens/LoginScreen.tsx
import { useAuth } from '@pubflow/react-native';
import { useState } from 'react';
import { View, TextInput, Button, Text } from 'react-native';
export function LoginScreen() {
const { login, isLoading, error } = useAuth();
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const handleLogin = async () => {
try {
await login({ email: email.toLowerCase(), password });
} catch (err) {
console.error('Login failed:', err);
}
};
return (
<View style={{ padding: 20 }}>
<TextInput
value={email}
onChangeText={(text) => setEmail(text.toLowerCase())}
placeholder="Email"
keyboardType="email-address"
autoCapitalize="none"
/>
<TextInput
value={password}
onChangeText={setPassword}
placeholder="Password"
secureTextEntry
/>
{error && <Text style={{ color: 'red' }}>{error.message}</Text>}
<Button
title={isLoading ? 'Logging in...' : 'Login'}
onPress={handleLogin}
disabled={isLoading}
/>
</View>
);
}Quick Start: Next.js
1. Setup Provider (Client Component)
// app/providers.tsx
'use client';
import { PubflowProvider } from '@pubflow/nextjs';
export function Providers({ children }: { children: React.ReactNode }) {
return (
<PubflowProvider url={process.env.NEXT_PUBLIC_BACKEND_URL!}>
{children}
</PubflowProvider>
);
}// app/layout.tsx
import { Providers } from './providers';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<Providers>{children}</Providers>
</body>
</html>
);
}2. Add Authentication
// app/login/page.tsx
'use client';
import { useAuth } from '@pubflow/nextjs';
import { useState } from 'react';
import { useRouter } from 'next/navigation';
export default function LoginPage() {
const { login, isLoading } = useAuth();
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const router = useRouter();
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
try {
await login({ email: email.toLowerCase(), password });
router.push('/dashboard');
} catch (error) {
console.error('Login failed:', error);
}
};
return (
<form onSubmit={handleSubmit}>
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value.toLowerCase())}
placeholder="Email"
/>
<input
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder="Password"
/>
<button type="submit" disabled={isLoading}>
{isLoading ? 'Logging in...' : 'Login'}
</button>
</form>
);
}3. Server-Side Authentication
// app/dashboard/page.tsx
import { withPubflowAuthSSR } from '@pubflow/nextjs';
export default withPubflowAuthSSR(
async function DashboardPage({ user }) {
return (
<div>
<h1>Welcome, {user.name}!</h1>
<p>Email: {user.email}</p>
</div>
);
},
{
redirectTo: '/login',
}
);4. API Routes with Authentication
// app/api/users/route.ts
import { withPubflow } from '@pubflow/nextjs';
export const GET = withPubflow(async (req, { user }) => {
// user is automatically available if authenticated
if (!user) {
return Response.json({ error: 'Unauthorized' }, { status: 401 });
}
// Your logic here
return Response.json({ users: [] });
});Environment Variables
Create a .env.local file in your project root:
VITE_BACKEND_URL=https://your-backend.comEXPO_PUBLIC_BACKEND_URL=https://your-backend.comNEXT_PUBLIC_BACKEND_URL=https://your-backend.comConfiguration Options
The PubflowProvider accepts several configuration options:
<PubflowProvider
url="https://your-backend.com"
instanceId="default" // Optional: for multi-instance support
onAuthError={(error) => { // Optional: handle auth errors
console.error('Auth error:', error);
}}
onSessionExpired={() => { // Optional: handle session expiration
console.log('Session expired');
}}
>
<App />
</PubflowProvider>Next Steps
Now that you have the basics working, explore more features:
- Authentication Guide - Learn about registration, social auth, and session management
- API Calls Guide - Master the Bridge API for CRUD operations
- Forms Guide - Use pre-built form components with validation
- Data Fetching Guide - Advanced SWR patterns and caching
- TypeScript Guide - Get the most out of TypeScript support
Common Patterns
Protected Routes
import { useAuth } from '@pubflow/react';
import { Navigate } from 'react-router-dom';
function ProtectedRoute({ children }: { children: React.ReactNode }) {
const { isAuthenticated, isLoading } = useAuth();
if (isLoading) return <div>Loading...</div>;
if (!isAuthenticated) return <Navigate to="/login" />;
return <>{children}</>;
}Logout Button
import { useAuth } from '@pubflow/react';
function LogoutButton() {
const { logout, user } = useAuth();
return (
<div>
<span>Welcome, {user?.name}</span>
<button onClick={logout}>Logout</button>
</div>
);
}Error Handling
import { useBridgeQuery } from '@pubflow/react';
function UserProfile({ userId }: { userId: string }) {
const { data, error, isLoading } = useBridgeQuery(`/api/users/${userId}`);
if (isLoading) return <div>Loading...</div>;
if (error) {
return (
<div>
<h3>Error loading user</h3>
<p>{error.message}</p>
<button onClick={() => window.location.reload()}>Retry</button>
</div>
);
}
return <div>{data.name}</div>;
}Troubleshooting
CORS Issues
If you're getting CORS errors, make sure your Flowfull backend has CORS configured:
// In your Flowfull backend
app.use(cors({
origin: ['http://localhost:3000', 'https://your-frontend.com'],
credentials: true,
}));Session Not Persisting
Make sure you're using the correct storage adapter for your platform:
- React: LocalStorage (automatic)
- React Native: AsyncStorage (install
@react-native-async-storage/async-storage) - Next.js: Cookies (automatic)
TypeScript Errors
If you're getting TypeScript errors, make sure you have the latest type definitions:
npm install --save-dev @types/react @types/nodeNeed Help?
- 📚 Full Documentation - Complete guides and API reference
- 💬 GitHub Discussions - Ask questions
- 🐛 Report Issues - Found a bug?
- 🤖 LLM Docs - AI-friendly quick reference (full version)