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
1. Use @pubflow/core (Recommended)
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
npm install @pubflow/coreStep 2: Create Storage Adapter
Implement the StorageAdapter interface for your platform:
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
// 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
// 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
// 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
- Login:
POST /auth/login
{
"email": "user@example.com",
"password": "password123"
}Response:
{
"success": true,
"user": { "id": "...", "email": "...", "name": "..." },
"session_id": "..."
}Store session_id in secure storage
Make authenticated requests with
X-Session-Idheader
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:
- Open Source: Publish your adapter as open source
- Documentation: Include clear documentation and examples
- Submit: Contact us at support@pubflow.com to get it listed
- Maintain: Keep it updated with core changes
Naming Convention
Use the naming pattern: @pubflow/{platform} or pubflow-{platform}
Examples:
@pubflow/vue@pubflow/svelte@pubflow/angularpubflow-flutterpubflow-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:
- Flowfull Clients: github.com/pubflow/flowfull-clients
- Documentation: github.com/pubflow/docs
- Starter Kits:
- TanStack Start: github.com/pubflow/flowfull-client
- React Native Expo: github.com/pubflow/create-pubflow-rn
How to Contribute:
- Fork the repository you want to contribute to
- Create a feature branch:
git checkout -b feature/my-contribution - Make your changes with clear, descriptive commits
- Test thoroughly to ensure everything works
- Submit a Pull Request with a detailed description
- 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:
- Publish to npm with clear documentation
- Use naming convention:
@pubflow/{platform}orpubflow-{platform} - Add MIT or similar license for open source
- Contact us at support@pubflow.com to get it listed in our docs
- 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?
- Email: support@pubflow.com
- GitHub Discussions: Ask questions and share ideas
- Documentation: Check our API Reference and Examples
Next Steps
- API Reference - Core API reference
- @pubflow/core Documentation - Core package docs
- Examples - See existing implementations
- Starter Kits - Production-ready templates
Ready to contribute? We can't wait to see what you build! 🚀