Skip to content

Build Your Own Client

Want to use Flowfull with a framework or language we don't officially support? You can build your own client!

Why Build Your Own?

You might want to build a custom Flowfull Client if:

  • You're using a framework we don't support (Vue, Svelte, Angular, etc.)
  • You're building for a different platform (Flutter, native iOS/Android, desktop apps)
  • You need custom functionality or optimizations
  • You want to contribute to the Pubflow ecosystem

Two Approaches

The easiest way is to build an adapter on top of @pubflow/core, which provides all the platform-agnostic functionality.

Advantages:

  • ✅ All core functionality already implemented
  • ✅ Consistent API across platforms
  • ✅ Automatic updates and bug fixes
  • ✅ TypeScript support out of the box

What you need to implement:

  • Storage adapter for your platform
  • Framework-specific hooks/composables/services
  • Optional: UI components

2. Build from Scratch

Build a completely custom client that communicates directly with Flowfull backend.

Advantages:

  • ✅ Full control over implementation
  • ✅ Can optimize for specific use cases
  • ✅ No dependencies on @pubflow/core

What you need to implement:

  • HTTP client with authentication
  • Session management
  • Storage layer
  • Bridge API integration
  • All business logic

Using @pubflow/core

Step 1: Install Core

bash
npm install @pubflow/core

Step 2: Create Storage Adapter

Implement the StorageAdapter interface for your platform:

typescript
import { StorageAdapter } from '@pubflow/core';

export class MyPlatformStorageAdapter implements StorageAdapter {
  async getItem(key: string): Promise<string | null> {
    // Implement platform-specific storage read
    return await myPlatform.storage.get(key);
  }

  async setItem(key: string, value: string): Promise<void> {
    // Implement platform-specific storage write
    await myPlatform.storage.set(key, value);
  }

  async removeItem(key: string): Promise<void> {
    // Implement platform-specific storage delete
    await myPlatform.storage.remove(key);
  }

  async clear(): Promise<void> {
    // Implement platform-specific storage clear
    await myPlatform.storage.clear();
  }
}

Step 3: Create Framework Integration

Example: Vue 3 Composable

typescript
// composables/usePubflow.ts
import { ref, computed } from 'vue';
import { ApiClient, AuthService, BridgeApiService } from '@pubflow/core';
import { MyPlatformStorageAdapter } from './storage';

const storage = new MyPlatformStorageAdapter();
const apiClient = new ApiClient({
  baseUrl: import.meta.env.VITE_BACKEND_URL,
  storage
});
const authService = new AuthService({
  baseUrl: import.meta.env.VITE_BACKEND_URL,
  storage
});

export function useAuth() {
  const user = ref(null);
  const isAuthenticated = computed(() => !!user.value);
  const isLoading = ref(false);

  async function login(credentials: { email: string; password: string }) {
    isLoading.value = true;
    try {
      const result = await authService.login(credentials);
      if (result.success) {
        user.value = result.user;
      }
      return result;
    } finally {
      isLoading.value = false;
    }
  }

  async function logout() {
    await authService.logout();
    user.value = null;
  }

  return {
    user,
    isAuthenticated,
    isLoading,
    login,
    logout
  };
}

export function useBridgeApi<T>(endpoint: string) {
  return new BridgeApiService<T>(apiClient, { endpoint });
}

Example: Svelte Store

typescript
// stores/pubflow.ts
import { writable, derived } from 'svelte/store';
import { ApiClient, AuthService } from '@pubflow/core';
import { MyPlatformStorageAdapter } from './storage';

const storage = new MyPlatformStorageAdapter();
const authService = new AuthService({
  baseUrl: import.meta.env.VITE_BACKEND_URL,
  storage
});

function createAuthStore() {
  const { subscribe, set, update } = writable({
    user: null,
    isLoading: false
  });

  return {
    subscribe,
    login: async (credentials: any) => {
      update(state => ({ ...state, isLoading: true }));
      const result = await authService.login(credentials);
      if (result.success) {
        set({ user: result.user, isLoading: false });
      }
      return result;
    },
    logout: async () => {
      await authService.logout();
      set({ user: null, isLoading: false });
    }
  };
}

export const auth = createAuthStore();
export const isAuthenticated = derived(auth, $auth => !!$auth.user);

Example: Angular Service

typescript
// services/pubflow.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { ApiClient, AuthService, User } from '@pubflow/core';
import { MyPlatformStorageAdapter } from './storage';

@Injectable({
  providedIn: 'root'
})
export class PubflowService {
  private storage = new MyPlatformStorageAdapter();
  private authService: AuthService;
  private userSubject = new BehaviorSubject<User | null>(null);
  
  public user$ = this.userSubject.asObservable();
  public isAuthenticated$ = this.user$.pipe(
    map(user => !!user)
  );

  constructor() {
    this.authService = new AuthService({
      baseUrl: environment.backendUrl,
      storage: this.storage
    });
  }

  async login(credentials: { email: string; password: string }) {
    const result = await this.authService.login(credentials);
    if (result.success) {
      this.userSubject.next(result.user);
    }
    return result;
  }

  async logout() {
    await this.authService.logout();
    this.userSubject.next(null);
  }
}

Building from Scratch

If you're building from scratch, you need to implement the Flowfull protocol.

Authentication Flow

  1. Login: POST /auth/login
json
{
  "email": "user@example.com",
  "password": "password123"
}

Response:

json
{
  "success": true,
  "user": { "id": "...", "email": "...", "name": "..." },
  "session_id": "..."
}
  1. Store session_id in secure storage

  2. Make authenticated requests with X-Session-Id header

Bridge API

All data operations go through the Bridge API:

  • List: GET /bridge/{endpoint}?page=1&limit=20
  • Get: GET /bridge/{endpoint}/{id}
  • Search: GET /bridge/{endpoint}/search?q=query
  • Create: POST /bridge/{endpoint}
  • Update: PUT /bridge/{endpoint}/{id}
  • Delete: DELETE /bridge/{endpoint}/{id}

Community Contributions

We welcome community-built adapters! If you build a Flowfull Client for a new platform:

  1. Open Source: Publish your adapter as open source
  2. Documentation: Include clear documentation and examples
  3. Submit: Contact us at support@pubflow.com to get it listed
  4. Maintain: Keep it updated with core changes

Naming Convention

Use the naming pattern: @pubflow/{platform} or pubflow-{platform}

Examples:

  • @pubflow/vue
  • @pubflow/svelte
  • @pubflow/angular
  • pubflow-flutter
  • pubflow-swift

🤝 Community Contributions

We welcome and encourage community contributions to the Pubflow ecosystem! Whether you're building a new client library, improving documentation, or sharing examples, your contributions help make Pubflow better for everyone.

How to Contribute

1. Build Client Libraries

Create adapters for new platforms and frameworks:

  • Desktop frameworks (Electron, Tauri)
  • Mobile frameworks (Flutter, Swift, Kotlin)
  • Web frameworks (Vue, Svelte, Angular, Solid)
  • Backend frameworks (Python, Go, Rust, PHP)

2. Improve Documentation

Help us make our docs better:

  • Fix typos and clarify explanations
  • Add more examples and use cases
  • Translate documentation to other languages
  • Create video tutorials and guides

3. Share Examples

Show the community how you use Pubflow:

  • Real-world application examples
  • Integration patterns and best practices
  • Starter templates for specific use cases
  • Code snippets and recipes

4. Report Issues & Suggest Features

Help us improve:

  • Report bugs and issues
  • Suggest new features
  • Share feedback on developer experience
  • Request new integrations

Contributing to GitHub

All Pubflow libraries and documentation are open source and available on GitHub:

Official Repositories:

How to Contribute:

  1. Fork the repository you want to contribute to
  2. Create a feature branch: git checkout -b feature/my-contribution
  3. Make your changes with clear, descriptive commits
  4. Test thoroughly to ensure everything works
  5. Submit a Pull Request with a detailed description
  6. Respond to feedback from maintainers

Contribution Guidelines

When contributing, please:

Follow existing code style and conventions ✅ Write clear commit messages describing your changes ✅ Add tests for new features or bug fixes ✅ Update documentation for API changes ✅ Keep PRs focused on a single feature or fix ✅ Be respectful and collaborative in discussions

Community Packages

If you create a community package:

  1. Publish to npm with clear documentation
  2. Use naming convention: @pubflow/{platform} or pubflow-{platform}
  3. Add MIT or similar license for open source
  4. Contact us at support@pubflow.com to get it listed in our docs
  5. Maintain compatibility with core package updates

Recognition

We value our contributors! All contributors will be:

  • Listed in our documentation
  • Credited in release notes
  • Featured in our community showcase
  • Invited to our contributors' Discord channel

Get Help

Need help contributing?


Next Steps

Ready to contribute? We can't wait to see what you build! 🚀