Flutter SDK
What you can build
Section titled “What you can build”- Mobile apps with auth — Registration, login, OTP, password reset on iOS and Android
- Real-time chat — Live messaging with presence indicators and message history
- Collaborative features — Shared lists, collaborative editing, live cursors
- Photo/file uploads — Camera capture to CDN with progress tracking
- Live dashboards — Real-time data feeds on mobile and tablet
- Cross-platform apps — Single codebase for iOS, Android, web, and desktop
Install
Section titled “Install”Add to pubspec.yaml:
dependencies: aerostack: ^1.0.0flutter pub getInitialize
Section titled “Initialize”import 'package:aerostack/aerostack.dart';
final client = AerostackClient( projectId: 'your-project-id', apiKey: 'your-public-api-key', baseUrl: 'https://api.aerostack.dev/v1',);Full authentication lifecycle — registration, login, OTP, password reset, and email verification:
// Registerfinal result = await client.auth.register( email: 'jane@example.com', password: 'securePassword123', name: 'Jane Doe',);
if (result.requiresVerification) { // Show "check your email" screen}
// Loginfinal result = await client.auth.login( email: 'jane@example.com', password: 'securePassword123',);final accessToken = result.accessToken;
// Passwordless OTPawait client.auth.sendOtp(email: 'jane@example.com');final result = await client.auth.verifyOtp( email: 'jane@example.com', code: '482916',);
// Get current userfinal user = await client.auth.me(accessToken: accessToken);
// Password resetawait client.auth.requestPasswordReset(email: 'jane@example.com');await client.auth.resetPassword(token: resetToken, newPassword: 'newPassword456');
// Email verificationawait client.auth.verifyEmail(token: verificationToken);
// Logoutawait client.auth.logout(accessToken: accessToken, refreshToken: refreshToken);AuthResult type
Section titled “AuthResult type”class AuthResult { final String? accessToken; final String? refreshToken; final int? expiresAt; final User? user; final bool requiresVerification;}
class User { final String id; final String email; final String? name; final String? avatarUrl; final bool emailVerified; final Map<String, dynamic>? customFields;}Realtime
Section titled “Realtime”Pub/sub channels with presence tracking and message history:
final channel = client.realtime.channel('chat/general');
// Listen for messageschannel.on('message', (payload) { print('New message: ${payload.data}'); setState(() { messages.add(payload.data); });});
// Subscribe to DB changesfinal ordersChannel = client.realtime.channel('orders');ordersChannel.on('INSERT', (payload) { print('New order: ${payload.data}');});
await channel.subscribe();await ordersChannel.subscribe();
// Publish a messagechannel.publish('message', { 'text': 'Hello from Flutter!', 'userId': currentUser.id, 'timestamp': DateTime.now().millisecondsSinceEpoch,});
// Publish with persistence (for message history)channel.publish('message', messageData, persist: true);
// Presence -- track who's onlinechannel.track({ 'userId': currentUser.id, 'name': currentUser.name, 'status': 'online',});
channel.on('presence:join', (payload) { print('${payload.data['name']} joined');});
channel.on('presence:leave', (payload) { print('${payload.data['name']} left');});
// Message historyfinal messages = await channel.getHistory(limit: 50);
// Cleanupchannel.untrack();channel.unsubscribe();Storage
Section titled “Storage”Upload files from the device:
import 'dart:io';
final file = File('/path/to/photo.jpg');
final result = await client.storage.upload( file: file, path: 'avatars/${currentUser.id}.jpg', contentType: 'image/jpeg',);
print(result.url); // CDN URL for the uploaded fileComplete example: chat screen
Section titled “Complete example: chat screen”import 'package:flutter/material.dart';import 'package:aerostack/aerostack.dart';
class ChatScreen extends StatefulWidget { final String roomId; const ChatScreen({required this.roomId});
@override State<ChatScreen> createState() => _ChatScreenState();}
class _ChatScreenState extends State<ChatScreen> { final _controller = TextEditingController(); final _messages = <Map<String, dynamic>>[]; final _online = <String, Map<String, dynamic>>{}; late final channel;
@override void initState() { super.initState(); _initRealtime(); }
Future<void> _initRealtime() async { channel = client.realtime.channel('chat/${widget.roomId}');
// Load history final history = await channel.getHistory(limit: 100); setState(() { _messages.addAll(history.map((h) => h.data)); });
// Track presence channel.track({ 'userId': currentUser.id, 'name': currentUser.name, });
// Listen for new messages channel.on('message', (payload) { setState(() { _messages.add(payload.data); }); });
// Listen for presence changes channel.on('presence:join', (payload) { setState(() { _online[payload.data['userId']] = payload.data; }); });
channel.on('presence:leave', (payload) { setState(() { _online.remove(payload.data['userId']); }); });
await channel.subscribe(); }
void _sendMessage() { if (_controller.text.isEmpty) return;
channel.publish('message', { 'userId': currentUser.id, 'name': currentUser.name, 'text': _controller.text, 'timestamp': DateTime.now().millisecondsSinceEpoch, }, persist: true);
_controller.clear(); }
@override void dispose() { channel.untrack(); channel.unsubscribe(); _controller.dispose(); super.dispose(); }
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Chat (${_online.length} online)'), ), body: Column( children: [ Expanded( child: ListView.builder( itemCount: _messages.length, itemBuilder: (ctx, i) { final msg = _messages[i]; return ListTile( title: Text(msg['name'] ?? 'Unknown'), subtitle: Text(msg['text'] ?? ''), ); }, ), ), Padding( padding: const EdgeInsets.all(8.0), child: Row( children: [ Expanded( child: TextField( controller: _controller, decoration: const InputDecoration(hintText: 'Message...'), ), ), IconButton( icon: const Icon(Icons.send), onPressed: _sendMessage, ), ], ), ), ], ), ); }}Next steps
Section titled “Next steps”- API Reference — Full method listing
- Auth — Detailed authentication patterns
- Realtime — Full guide for pub/sub, presence, and DB change events
- Error Handling — Error types and retry strategies