Skip to content

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 ​