Real-World Applications ​
Examples of complete applications and common patterns built with Flowfull Clients.
E-Commerce Platform ​
A full-featured e-commerce platform with product catalog, shopping cart, and checkout.
Features:
- User authentication and profiles
- Product browsing with search and filters
- Shopping cart management
- Order processing and history
- Admin dashboard for inventory
Tech Stack:
- Next.js 14 (App Router)
- @pubflow/nextjs
- Stripe for payments
- Tailwind CSS
Key Implementation:
typescript
// app/products/page.tsx
'use client';
import { useBridgeApi, useBridgeQuery } from '@pubflow/nextjs';
export default function ProductsPage() {
const productService = useBridgeApi({ endpoint: 'products' });
const { data: products, isLoading } = useBridgeQuery(
productService,
'list',
{ limit: 20, orderBy: 'name' }
);
return (
<div className="grid grid-cols-4 gap-4">
{products?.map(product => (
<ProductCard key={product.id} product={product} />
))}
</div>
);
}
// app/api/checkout/route.ts
import { withPubflowAuth } from '@pubflow/nextjs';
export const POST = withPubflowAuth(async (req, res, api, auth, user) => {
const { cartItems } = await req.json();
// Create order
const order = await api.post('/bridge/orders', {
userId: user.id,
items: cartItems,
total: calculateTotal(cartItems)
});
return Response.json({ success: true, order });
});Task Management App ​
A collaborative task management application with teams and projects.
Features:
- User authentication and team management
- Project and task creation
- Real-time collaboration
- File attachments
- Activity timeline
Tech Stack:
- React (Vite)
- @pubflow/react
- React Router
- React DnD for drag-and-drop
Key Implementation:
typescript
// pages/Projects.tsx
import { useBridgeApi, useBridgeQuery, useBridgeMutation } from '@pubflow/react';
function ProjectBoard() {
const taskService = useBridgeApi({ endpoint: 'tasks' });
const { data: tasks, refetch } = useBridgeQuery(
taskService,
'list',
{ projectId: currentProject.id }
);
const { mutate: updateTask } = useBridgeMutation(taskService, 'update');
async function handleTaskMove(taskId: string, newStatus: string) {
await updateTask({
id: taskId,
data: { status: newStatus }
});
refetch();
}
return (
<div className="kanban-board">
<Column status="todo" tasks={tasks?.filter(t => t.status === 'todo')} />
<Column status="in-progress" tasks={tasks?.filter(t => t.status === 'in-progress')} />
<Column status="done" tasks={tasks?.filter(t => t.status === 'done')} />
</div>
);
}Social Media App ​
A mobile social media application with posts, comments, and user profiles.
Features:
- User authentication and profiles
- Create and share posts with images
- Like and comment system
- Follow/unfollow users
- Activity feed
- Offline support
Tech Stack:
- React Native (Expo)
- @pubflow/react-native
- React Navigation
- Expo Image Picker
Key Implementation:
typescript
// screens/FeedScreen.tsx
import { useBridgeApi, useBridgeQuery, useBridgeMutation } from '@pubflow/react-native';
import { RefreshControl, FlatList } from 'react-native';
export default function FeedScreen() {
const postService = useBridgeApi({ endpoint: 'posts' });
const { data: posts, isLoading, refetch } = useBridgeQuery(
postService,
'list',
{ limit: 20, orderBy: 'createdAt', orderDir: 'desc' }
);
const { mutate: likePost } = useBridgeMutation(
useBridgeApi({ endpoint: 'likes' }),
'create'
);
async function handleLike(postId: string) {
await likePost({ data: { postId } });
refetch();
}
return (
<FlatList
data={posts || []}
renderItem={({ item }) => (
<PostCard post={item} onLike={() => handleLike(item.id)} />
)}
refreshControl={
<RefreshControl refreshing={isLoading} onRefresh={refetch} />
}
/>
);
}
// screens/CreatePostScreen.tsx
import { useBridgeMutation } from '@pubflow/react-native';
import * as ImagePicker from 'expo-image-picker';
export default function CreatePostScreen({ navigation }: any) {
const [content, setContent] = useState('');
const [image, setImage] = useState<string | null>(null);
const postService = useBridgeApi({ endpoint: 'posts' });
const { mutate: createPost, isLoading } = useBridgeMutation(
postService,
'create'
);
async function handleSubmit() {
await createPost({
data: { content, image }
});
navigation.goBack();
}
return (
<View>
<TextInput
value={content}
onChangeText={setContent}
placeholder="What's on your mind?"
multiline
/>
<Button title="Add Image" onPress={pickImage} />
<Button title="Post" onPress={handleSubmit} disabled={isLoading} />
</View>
);
}Blog Platform ​
A content management system for blogging with rich text editing.
Features:
- User authentication (authors, editors, admins)
- Rich text editor for posts
- Categories and tags
- Comments system
- SEO optimization with SSR
Tech Stack:
- Next.js 14 (App Router)
- @pubflow/nextjs
- MDX Editor
- Tailwind CSS
Key Implementation:
typescript
// app/blog/[slug]/page.tsx
import { withPubflowSSR } from '@pubflow/nextjs';
export const getServerSideProps = withPubflowSSR(
async (context, api, auth) => {
const { slug } = context.params;
const post = await api.get(`/bridge/posts/${slug}`);
const comments = await api.get(`/bridge/comments?postId=${post.id}`);
return {
props: { post, comments }
};
}
);
export default function BlogPost({ post, comments }: any) {
return (
<article>
<h1>{post.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.content }} />
<CommentSection comments={comments} postId={post.id} />
</article>
);
}
// app/admin/posts/new/page.tsx
'use client';
import { useBridgeMutation } from '@pubflow/nextjs';
import dynamic from 'next/dynamic';
const MDXEditor = dynamic(() => import('@mdxeditor/editor'), { ssr: false });
export default function NewPost() {
const [content, setContent] = useState('');
const postService = useBridgeApi({ endpoint: 'posts' });
const { mutate: createPost } = useBridgeMutation(postService, 'create');
async function handlePublish() {
await createPost({
data: {
title,
content,
status: 'published'
}
});
}
return (
<div>
<input type="text" placeholder="Title" />
<MDXEditor markdown={content} onChange={setContent} />
<button onClick={handlePublish}>Publish</button>
</div>
);
}Common Patterns ​
Multi-Instance Setup ​
Applications connecting to multiple backends:
typescript
<PubflowProvider
instances={[
{
id: 'main',
baseUrl: 'https://api.example.com',
bridgeBasePath: '/bridge'
},
{
id: 'analytics',
baseUrl: 'https://analytics.example.com',
bridgeBasePath: '/data-api'
}
]}
defaultInstance="main"
>
<App />
</PubflowProvider>Role-Based Access Control ​
typescript
import { useAuth, BridgeView } from '@pubflow/react';
function AdminPanel() {
return (
<BridgeView
allowedTypes={['admin', 'superadmin']}
fallback={<AccessDenied />}
>
<AdminContent />
</BridgeView>
);
}
// Or with routing
function Navigation() {
const { user } = useAuth();
if (user?.userType === 'admin') {
return <AdminNavigator />;
}
return <UserNavigator />;
}Infinite Scroll ​
typescript
import { useState, useEffect } from 'react';
import { useBridgeApi, useBridgeQuery } from '@pubflow/react';
function InfiniteList() {
const [page, setPage] = useState(1);
const [allItems, setAllItems] = useState([]);
const itemService = useBridgeApi({ endpoint: 'items' });
const { data, meta } = useBridgeQuery(
itemService,
'list',
{ page, limit: 20 }
);
useEffect(() => {
if (data) {
setAllItems(prev => [...prev, ...data]);
}
}, [data]);
return (
<div>
{allItems.map(item => <ItemCard key={item.id} item={item} />)}
{meta?.hasMore && (
<button onClick={() => setPage(p => p + 1)}>Load More</button>
)}
</div>
);
}Search with Debouncing ​
typescript
import { useState, useEffect } from 'react';
import { useBridgeApi, useBridgeQuery } from '@pubflow/react';
function SearchBar() {
const [query, setQuery] = useState('');
const [debouncedQuery, setDebouncedQuery] = useState('');
useEffect(() => {
const timer = setTimeout(() => setDebouncedQuery(query), 300);
return () => clearTimeout(timer);
}, [query]);
const searchService = useBridgeApi({ endpoint: 'products' });
const { data: results } = useBridgeQuery(
searchService,
'search',
{ q: debouncedQuery, limit: 10 },
{ isPaused: () => !debouncedQuery }
);
return (
<div>
<input
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Search..."
/>
{results?.map(item => <SearchResult key={item.id} item={item} />)}
</div>
);
}Optimistic Updates ​
typescript
import { useBridgeMutation } from '@pubflow/react-native';
import { mutate } from 'swr';
function LikeButton({ postId, initialLikes }: any) {
const [likes, setLikes] = useState(initialLikes);
const likeService = useBridgeApi({ endpoint: 'likes' });
const { mutate: createLike } = useBridgeMutation(likeService, 'create');
async function handleLike() {
// Optimistic update
setLikes(likes + 1);
try {
await createLike({ data: { postId } });
// Invalidate cache
mutate('/bridge/posts');
} catch (error) {
// Revert on error
setLikes(likes);
}
}
return <button onClick={handleLike}>{likes} likes</button>;
}Next Steps ​
- Advanced: Multi-Instance - Multi-instance configuration
- Advanced: Offline Support - Offline functionality
- Advanced: Performance - Performance optimization
- Build Your Own Client - Create custom clients