Uplink Protocol
A framework-agnostic protocol for building reusable frontend logic that works across UI frameworks.
Uplink Protocol: Write Once, Use Everywhere
The Uplink Protocol is a comprehensive system for building UI-agnostic logic that can be reused across different frontend frameworks. It solves the problem of duplicating business logic when working with multiple frameworks or migrating between them.
With Uplink, you can write your core functionality once and then use it with React, Vue, Svelte, or plain JavaScript without any rewrites.
Uplink takes a declarative approach to application logic, allowing developers to define controllers, bindings, and events independently of the UI layer. This results in cleaner separation of concerns, improved testability, and enhanced code reuse.
Reusable Controllers
Create standalone logic controllers with state management that can be used with any UI framework.
Reactive Bindings
Powerful reactive state containers with subscription capabilities that automatically sync UI with underlying state.
Adapter System
Seamless integration with different UI frameworks through a flexible adapter system that speaks the native language of each framework.
Event Emitters
Rich event system for communicating between components and handling user interactions across frameworks.
Type Safety
Full TypeScript support with strong typing for controllers, bindings, and events for improved developer experience.
ESM Modules
Modern ECMAScript Module format for better tree-shaking and more efficient loading.
Installation
Install the core package :
1 npm install @uplink-protocol/core
Install along framework-specific adapters you need :
1 npm install @uplink-protocol/react // or /vue or /svelte or /angular
Protocol Architecture
The Uplink Protocol follows a layered architecture designed for maximum flexibility and reusability:
1. Core Protocol Layer
This layer defines the fundamental interfaces and models that make up the foundation of the protocol:
- Controllers: Encapsulate business logic and state management
- Bindings: Reactive state containers with subscription capabilities
- Event Emitters: Communication channels for broadcasting state changes
2. Adapter Layer
The adapter layer bridges the protocol with specific UI frameworks, translating between protocol operations and framework patterns:
- Framework Adapters: Connect controllers to specific UI frameworks
- Adapter Registry: Manages all available adapters
- Controller Adapter: Provides a unified interface for controllers
3. Integration Layer
The top layer provides framework-specific APIs and hooks for a seamless developer experience:
- Framework Hooks: useUplink() for React, Vue composables, etc.
- Integration Utilities: Tools for connecting controllers to framework components
- Component Bindings: Pre-built UI connections for common patterns
Basic Usage
Creating and using controllers with the Uplink Protocol follows a simple pattern:
1import { StandardBinding, EventEmitter } from '@uplink-protocol/core';23class CounterController {4 constructor() {5 // Bindings hold reactive state6 this.bindings = {7 count: new StandardBinding(0),8 isEven: new StandardBinding(true)9 };1011 // Methods define controller behavior12 this.methods = {13 increment: () => {14 const newCount = this.bindings.count.current + 1;15 this.bindings.count.set(newCount);16 this.bindings.isEven.set(newCount % 2 === 0);17 this.events.increment.emit(newCount);18 },1920 decrement: () => {21 const newCount = this.bindings.count.current - 1;22 this.bindings.count.set(newCount);23 this.bindings.isEven.set(newCount % 2 === 0);24 this.events.decrement.emit(newCount);25 },2627 reset: () => {28 this.bindings.count.set(0);29 this.bindings.isEven.set(true);30 }31 };3233 // Events for notifying external systems34 this.events = {35 increment: new EventEmitter(),36 decrement: new EventEmitter()37 };38 }39}
Framework Integration Examples
1import { useUplink } from '@uplink-protocol/react';2import { CounterController } from './counter.controller';3import { useEffect } from 'react';45// Initialize adapter at app entry point6// import { initializeReactAdapter } from '@uplink-protocol/react';7// initializeReactAdapter();89function CounterComponent() {10 // Use the controller with React11 const { state, methods, events } = useUplink(new CounterController());1213 useEffect(() => {14 // Subscribe to events if needed15 const unsubscribe = events.increment.subscribe((count) => {16 console.log(`Counter incremented to ${count}`);17 });1819 return () => unsubscribe();20 }, [events]);2122 return (23 <div>24 <h2>Counter: {state.count}</h2>25 <p>The count is {state.isEven ? 'even' : 'odd'}</p>26 <button onClick={methods.increment}>Increment</button>27 <button onClick={methods.decrement}>Decrement</button>28 <button onClick={methods.reset}>Reset</button>29 </div>30 );31}
Advanced Features
Typed Controllers
When using TypeScript, you can leverage the TypedController interface for strong typing:
1import { TypedController, Binding, EventEmitter, StandardBinding } from '@uplink-protocol/core';23// Define your specific controller types4interface CounterBindings {5 count: Binding<number>;6 isEven: Binding<boolean>;7}89interface CounterMethods {10 increment(): void;11 decrement(): void;12 reset(): void;13}1415interface CounterEvents {16 increment: EventEmitter<number>;17 decrement: EventEmitter<number>;18}1920// Implement with strong typing21class CounterController implements TypedController<CounterBindings, CounterMethods, CounterEvents> {22 // ... implementation23}
Custom Adapters
You can create custom adapters for specific frameworks or use cases:
1import { AdapterInterface, Controller, AdapterRegistry } from '@uplink-protocol/core';23class CustomAdapter implements AdapterInterface {4 readonly name = 'custom-adapter';5 readonly version = '1.0.0';67 initialize(config?: any): void {8 // Initialization logic9 }1011 (controller: Controller, element: HTMLElement): void {12 // Connect controller to the element13 }1415 // Implement other required methods16 // ...17}1819// Register the adapter20const registry = AdapterRegistry.getInstance();21registry.registerAdapter(new CustomAdapter());22registry.setDefaultAdapter('custom-adapter');
Related Documentation
Explore these related documents for more specific implementations and use cases: