miniapp-sdk - SDK for Mini-Apps
SDK that provides APIs for mini-apps to communicate with the host app through the bridge protocol.
Installation
pnpm add @54vie/miniapp-sdk
Quick Start
import {
useHostAuth,
useHostDevice,
storage,
analytics,
} from '@54vie/miniapp-sdk';
function MiniApp() {
const { user, isAuthenticated } = useHostAuth();
const { deviceInfo } = useHostDevice();
useEffect(() => {
analytics.screen('MiniAppHome');
}, []);
if (!isAuthenticated) {
return <LoginPrompt />;
}
return <MainContent user={user} />;
}
Authentication
useHostAuth
import { useHostAuth } from '@54vie/miniapp-sdk';
function ProfileScreen() {
const {
user, // Current user object
isAuthenticated, // Boolean
isLoading, // Loading state
accessToken, // JWT token for API calls
requestLogin, // Trigger host login flow
checkPermission, // Check specific permission
} = useHostAuth();
if (!isAuthenticated) {
return (
<View>
<Text>Please login to continue</Text>
<Button onPress={requestLogin}>Login</Button>
</View>
);
}
return (
<View>
<Text>Welcome, {user.name}!</Text>
<Text>Email: {user.email}</Text>
</View>
);
}
API with Auth
import { useHostAuth, api } from '@54vie/miniapp-sdk';
function OrderList() {
const { accessToken } = useHostAuth();
const fetchOrders = async () => {
// Token is automatically injected by the bridge
const orders = await api.get('/orders');
return orders;
};
}
Storage
import { storage } from '@54vie/miniapp-sdk';
// Get value
const value = await storage.get('my-key');
// Set value
await storage.set('my-key', { data: 'value' });
// Remove
await storage.remove('my-key');
// Clear all (within mini-app scope)
await storage.clear();
Storage Scope
Each mini-app has its own isolated storage namespace. Data from one mini-app cannot be accessed by another.
Device Information
useHostDevice
import { useHostDevice } from '@54vie/miniapp-sdk';
function MyComponent() {
const {
model, // "iPhone 15 Pro"
brand, // "Apple"
os, // "ios" | "android"
osVersion, // "17.0"
appVersion, // "1.0.0"
isEmulator, // Boolean
isTablet, // Boolean
} = useHostDevice();
return (
<Text>Running on {brand} {model}</Text>
);
}
Direct Access
import { device } from '@54vie/miniapp-sdk';
const info = await device.getInfo();
const deviceId = await device.getDeviceId();
const isEmulator = await device.isEmulator();
Network Status
import { useHostNetwork, network } from '@54vie/miniapp-sdk';
// Hook
function MyComponent() {
const {
isOnline,
isWifi,
isCellular,
connectionType, // 'wifi' | 'cellular' | 'none'
} = useHostNetwork();
if (!isOnline) {
return <OfflineMessage />;
}
}
// Direct
const isOnline = await network.isOnline();
const type = await network.getConnectionType();
Analytics
import { analytics } from '@54vie/miniapp-sdk';
// Track event
analytics.track('button_clicked', {
button_name: 'checkout',
product_id: '123',
});
// Track screen
analytics.screen('ProductDetail', {
product_id: '123',
});
Attribution
All events from mini-apps are automatically attributed to the mini-app ID for analytics purposes.
Push Notifications
import { useHostPush, push } from '@54vie/miniapp-sdk';
// Hook
function NotificationSettings() {
const {
hasPermission,
token,
requestPermission,
} = useHostPush();
if (!hasPermission) {
return (
<Button onPress={requestPermission}>
Enable Notifications
</Button>
);
}
}
// Direct
const token = await push.getToken();
await push.subscribeToTopic('promotions');
await push.scheduleNotification({
title: 'Reminder',
body: 'Your order is ready!',
scheduledAt: new Date(Date.now() + 3600000),
});
Location
import { useHostLocation, location } from '@54vie/miniapp-sdk';
// Hook
function NearbyStores() {
const {
currentLocation,
isLoading,
error,
hasPermission,
requestPermission,
} = useHostLocation();
if (!hasPermission) {
return <Button onPress={requestPermission}>Allow Location</Button>;
}
if (isLoading) return <Loading />;
return <StoreList location={currentLocation} />;
}
// Direct
const position = await location.getCurrentPosition();
const address = await location.reverseGeocode(position.latitude, position.longitude);
const places = await location.searchPlaces('coffee shop', position);
Media
import { media } from '@54vie/miniapp-sdk';
// Take photo
const photo = await media.takePhoto({
quality: 'high',
cameraType: 'back',
});
// Pick from gallery
const images = await media.pickImage({
multiple: true,
maxSelection: 5,
});
// Crop image
const cropped = await media.cropImage(photo.uri, {
width: 300,
height: 300,
aspectRatio: 1,
});
// Resize
const resized = await media.resizeImage(photo.uri, {
width: 800,
quality: 0.8,
});
UI Services
Toast
import { ui } from '@54vie/miniapp-sdk';
ui.showToast({
message: 'Saved successfully!',
type: 'success',
});
ui.showToast({
message: 'Something went wrong',
type: 'error',
});
Alert
import { ui } from '@54vie/miniapp-sdk';
const result = await ui.showAlert({
title: 'Confirm',
message: 'Are you sure you want to delete?',
buttons: [
{ text: 'Cancel', style: 'cancel' },
{ text: 'Delete', style: 'destructive' },
],
});
if (result === 1) {
// User pressed Delete
}
Action Sheet
import { ui } from '@54vie/miniapp-sdk';
const result = await ui.showActionSheet({
title: 'Choose action',
options: [
{ label: 'Share', icon: 'share' },
{ label: 'Edit', icon: 'edit' },
{ label: 'Delete', icon: 'trash', destructive: true },
],
cancelLabel: 'Cancel',
});
Haptics
import { haptics } from '@54vie/miniapp-sdk';
// Impact feedback
haptics.impact('light'); // light, medium, heavy
haptics.impact('medium');
// Notification feedback
haptics.notification('success'); // success, warning, error
// Selection feedback
haptics.selection();
Clipboard
import { clipboard } from '@54vie/miniapp-sdk';
// Copy
await clipboard.setString('Hello World');
// Paste
const text = await clipboard.getString();
// Check
const hasContent = await clipboard.hasString();
Share
import { share } from '@54vie/miniapp-sdk';
// Share text
await share.text({
message: 'Check out this product!',
url: 'https://54vie.vn/product/123',
title: 'Share Product',
});
// Share image
await share.image({
imageUrl: 'file:///path/to/image.jpg',
message: 'My photo',
});
Navigation
import { navigation } from '@54vie/miniapp-sdk';
// Navigate to host screen
navigation.navigate('Wallet');
// Go back
navigation.goBack();
// Open another mini-app
navigation.openMiniApp('com.54vie.booking', {
serviceId: '123',
});
API Requests
import { api } from '@54vie/miniapp-sdk';
// Requests are proxied through host with auth
const products = await api.get('/products');
const order = await api.post('/orders', orderData);
Rate Limiting
API requests from mini-apps are subject to rate limiting. Default is 100 requests per minute.
Permissions
Mini-apps must declare required permissions in manifest.json:
{
"appId": "com.54vie.shopping",
"name": "Shopping",
"permissions": [
"storage",
"analytics",
"push",
"location",
"camera"
]
}
Check permission at runtime:
import { useHostAuth } from '@54vie/miniapp-sdk';
function CameraFeature() {
const { checkPermission, requestPermission } = useHostAuth();
const handleCamera = async () => {
const hasPermission = await checkPermission('camera');
if (!hasPermission) {
const granted = await requestPermission('camera', 'Need camera for scanning');
if (!granted) return;
}
// Use camera
};
}