Syncre is a secure, cross-platform mobile communication application built with React Native and Expo. It focuses on privacy and security through end-to-end encryption for all communications.
- Secure Messaging: End-to-end encrypted one-on-one and group conversations
- User Authentication: Secure user registration, login, and profile management
- Friend System: Search for users, send friend requests, and manage friend lists
- Real-time Communication: WebSocket-based instant message delivery
- Group Chats: Create groups with up to 10 members, with customizable names and avatars
- File Sharing: Send images, videos, documents with chunked upload support for large files
- Scheduled Messages: Schedule messages to be sent at specific times
- Polls: Create and participate in polls within chats
- Push Notifications: Stay updated with new messages and friend requests
- Cross-Platform: Runs on iOS, Android, and Web from a single codebase
- Spotify Integration: Share what you're listening to with friends
- Streaks: Track consecutive days of messaging with friends
- Framework: React Native with Expo
- Language: TypeScript
- Routing: Expo Router for file-based navigation
- State Management: React Context and custom hooks
- Encryption:
tweetnacl- NaCl cryptography library@stablelib/hkdf- HKDF key derivation@stablelib/sha256- SHA-256 hashing@stablelib/xchacha20poly1305- XChaCha20-Poly1305 encryptionexpo-crypto- Expo cryptography utilities
- Storage:
expo-secure-store- Secure storage for sensitive data@react-native-async-storage/async-storage- General persistent storage
- Real-time: WebSockets with custom
WebSocketService - Push Notifications: Expo Notifications
- Media:
expo-image- Image handlingexpo-video- Video playbackexpo-document-picker- File selectionexpo-image-picker- Camera and gallery access
- Linting: ESLint with TypeScript support
This mobile app communicates with the Syncre backend API. For detailed API documentation, see:
- Backend API Documentation - Complete REST API and WebSocket protocol reference
- Mobile API Guide - Mobile-specific API integration guide
Base URL: https://api.syncre.xyz/v1
WebSocket URL: wss://api.syncre.xyz/ws
The app uses two main services for communication:
- ApiService (
services/ApiService.ts) - REST API client - WebSocketService (
services/WebSocketService.ts) - Real-time communication
- Node.js (LTS version recommended, v18+)
- npm or pnpm
- Expo CLI (
npm install -g expo-cli) - Expo Go app on your mobile device (iOS/Android) or Android Studio/Xcode for emulators
-
Clone the repository:
git clone <repository-url> cd Mobile
-
Install dependencies:
npm install # or pnpm install -
Environment Setup: Create a
.envfile in the Mobile directory:EXPO_PUBLIC_API_URL=https://api.syncre.xyz/v1
npm start- Start the development server with Exponpm run android- Run on Android device/emulatornpm run ios- Run on iOS simulator/devicenpm run web- Run in web browsernpm run lint- Lint the codebase using ESLintnpm run build- Create production build for iOS via EAS Buildnpm run real-build- Create release builds for iOS and Android
Mobile/
βββ app/ # Expo Router routes (screens)
β βββ (tabs)/ # Tab-based navigation screens
β β βββ home.tsx # Home/chat list screen
β β βββ friends.tsx # Friends management screen
β β βββ profile.tsx # User profile screen
β β βββ _layout.tsx # Tab navigation layout
β βββ chat/ # Chat screens
β β βββ [id].tsx # Individual chat screen (dynamic route)
β βββ login.tsx # Login screen
β βββ register.tsx # Registration screen
β βββ verify.tsx # Email verification screen
β βββ _layout.tsx # Root layout with providers
βββ components/ # Reusable UI components
β βββ MessageBubble.tsx # Message display component
β βββ ChatList.tsx # Chat list component
β βββ ...
βββ context/ # React context providers
β βββ AuthContext.tsx # Authentication state
β βββ ChatContext.tsx # Chat/messaging state
β βββ ...
βββ hooks/ # Custom React hooks
β βββ useAuth.ts # Authentication hook
β βββ useChat.ts # Chat management hook
β βββ ...
βββ services/ # Core services
β βββ ApiService.ts # REST API client
β βββ WebSocketService.ts # WebSocket communication
β βββ CryptoService.ts # Encryption/decryption
β βββ IdentityService.ts # Identity key management
β βββ ReencryptionService.ts # Message re-encryption
β βββ StorageService.ts # Secure storage wrapper
β βββ ...
βββ types/ # TypeScript type definitions
βββ constants/ # App constants
βββ assets/ # Static assets (images, fonts)
All messages are encrypted end-to-end using the following flow:
- Key Generation: Each device generates an X25519 key pair
- Identity Keys: Users have identity keys encrypted with their password
- Message Encryption: Each message uses a unique ephemeral key
- Envelopes: Encrypted messages are wrapped in "envelopes" for each recipient device
- Backup Envelopes: Additional envelopes encrypted for backup/recovery
- CryptoService - Handles encryption/decryption operations
- IdentityService - Manages identity key pairs
- ReencryptionService - Re-encrypts messages for new devices
The ApiService class provides methods for all API interactions:
// Authentication
const response = await ApiService.post('/auth/login', { email, password });
// Get chats
const chats = await ApiService.get('/chat', token);
// Send message (REST fallback)
await ApiService.post(`/chat/${chatId}/messages`, { content }, token);
// Upload file
const formData = new FormData();
formData.append('file', file);
await ApiService.upload(`/chat/${chatId}/attachments`, formData, token);Real-time messaging via WebSocket:
// Connect and authenticate
await WebSocketService.connect(token);
// Join chat room
WebSocketService.joinChat(chatId, deviceId);
// Send encrypted message
WebSocketService.send({
type: 'chat_message',
chatId,
content: encryptedContent,
envelopes: [...],
backupEnvelopes: [...]
});
// Listen for messages
WebSocketService.addMessageListener((message) => {
console.log('Received:', message);
});- Create a new file in
app/directory (e.g.,app/settings.tsx) - Use Expo Router's file-based routing automatically
- Export a default React component:
// app/settings.tsx
import { View, Text } from 'react-native';
export default function SettingsScreen() {
return (
<View>
<Text>Settings</Text>
</View>
);
}Use the ApiService for REST API calls:
import { ApiService } from '../services/ApiService';
async function fetchData() {
const response = await ApiService.get('/endpoint', token);
if (response.success) {
return response.data;
}
throw new Error(response.error);
}import { CryptoService } from '../services/CryptoService';
// Generate keys
const keyPair = await CryptoService.generateKeyPair();
// Encrypt message
const encrypted = await CryptoService.encryptMessage(plaintext, recipientPublicKey);
// Decrypt message
const decrypted = await CryptoService.decryptMessage(encrypted, privateKey);Run linting to check code quality:
npm run lint# iOS build
npm run build
# iOS and Android builds
npm run real-buildThis project is licensed under the GNU GENERAL PUBLIC LICENSE.
Contributions are welcome! Please ensure:
- Code follows the existing TypeScript patterns
- All new code is properly typed
- ESLint passes without errors
- E2EE security is maintained for any messaging changes
For support, questions, or bug reports:
- Open an issue in the repository
- Contact the development team
- Check the Backend API Documentation for API-related questions
- Backend API Documentation - Complete API reference
- Mobile API Integration Guide - Detailed mobile API usage