# PostizMobile React Native (Expo) mobile app to control a self-hosted **Postiz** instance from your Android or iOS device. --- ## Table of Contents 1. [Features](#features) 2. [Prerequisites](#prerequisites) 3. [Installation & Development](#installation--development) 4. [App Configuration](#app-configuration) 5. [Project Architecture](#project-architecture) 6. [Postiz API](#postiz-api) 7. [Android APK Build (EAS)](#android-apk-build-eas) 8. [iOS Build (Expo Launch)](#ios-build-expo-launch) 9. [Pushing Changes to Gitea](#pushing-changes-to-gitea) 10. [Environment Variables & Secrets](#environment-variables--secrets) 11. [Troubleshooting](#troubleshooting) --- ## Features | Screen | Description | |--------|-------------| | **Calendar** | Monthly view with color dots per day (indigo = scheduled, green = published, red = error). Tap a day to see its posts. | | **Posts** | Filtered list (All / Queue / Published / Draft / Error) with pull-to-refresh and swipe left to delete. | | **Compose** | Text editor, channel picker, date/time picker, gallery image import + upload, publish now or schedule. | | **Settings** | API key and base URL input, connection test, secure storage (SecureStore). | | **Notifications** | Automatic local alerts when a post transitions to PUBLISHED or ERROR (polling every 15 minutes). | **Theme**: forced dark (`userInterfaceStyle: dark`). **Authentication**: API key stored in `expo-secure-store`, never hardcoded. --- ## Prerequisites | Tool | Minimum version | |------|----------------| | Node.js | 20 LTS | | pnpm | 10+ | | Expo Go (phone) | SDK 54 compatible | | EAS account (for APK) | free on expo.dev | ```bash npm install -g pnpm npm install -g eas-cli ``` --- ## Installation & Development ### 1. Clone the repository ```bash git clone ssh://gitea@homegit.gyozamancave.fr:2222/billisdead/Postiz-android.git cd Postiz-android ``` ### 2. Install dependencies ```bash pnpm install ``` ### 3. Start the development server ```bash pnpm --filter @workspace/postiz-mobile run dev ``` The terminal displays a QR code. Scan it with **Expo Go** (Android) or the **Camera** app (iOS) to see the app live. ### 4. Open in the browser (web preview) ``` http://localhost: ``` The port is dynamically assigned by the Replit environment. --- ## App Configuration On first launch, the **Settings** screen is shown because no key is configured yet. 1. **Base URL**: `https://your-postiz-instance.fr/public/v1` 2. **API Key**: generated from your Postiz instance → *Settings → API Keys* 3. Tap **Test Connection** to validate 4. Tap **Save Settings** The key is encrypted and stored locally via `expo-secure-store`. It is never sent to a third-party service. --- ## Project Architecture ``` artifacts/postiz-mobile/ ├── app/ │ ├── _layout.tsx # Root layout : providers, fonts, notifications │ └── (tabs)/ │ ├── _layout.tsx # Tab bar (NativeTabs iOS 26+ / Tabs classique) │ ├── index.tsx # Écran Calendrier │ ├── posts.tsx # Écran Liste des posts │ ├── compose.tsx # Écran Composer │ └── settings.tsx # Écran Paramètres ├── components/ │ ├── ChannelChip.tsx # Chip de sélection de canal │ ├── ErrorBoundary.tsx # Gestionnaire d'erreurs global │ ├── PostCard.tsx # Carte post avec swipe-to-delete │ └── StatusBadge.tsx # Badge QUEUE / PUBLISHED / ERROR / DRAFT ├── constants/ │ └── colors.ts # Palette dark theme ├── context/ │ └── PostizContext.tsx # Client axios + SecureStore (apiKey, baseUrl) ├── hooks/ │ ├── useColors.ts # Tokens couleur selon le thème │ └── useNotifications.ts # Permissions + polling + notifications locales ├── assets/ │ └── images/ │ └── icon.png # Icône générée par IA └── app.json # Config Expo (permissions, plugins, thème) ``` ### Main dependencies | Package | Usage | |---------|-------| | `expo-router` | File-based navigation | | `axios` | HTTP client for the Postiz API | | `expo-secure-store` | Encrypted API key storage | | `react-native-calendars` | Monthly calendar view | | `@react-native-community/datetimepicker` | Date/time picker in Compose | | `expo-image-picker` | Gallery photo access | | `expo-notifications` | Local status notifications | | `expo-task-manager` | Background task for polling | | `@tanstack/react-query` | API data cache and refetch | --- ## Postiz API Base URL configured by the user (e.g. `https://postiz.example.com/public/v1`). | Method | Endpoint | Usage | |--------|----------|-------| | `GET` | `/integrations` | List channels (Twitter, LinkedIn, etc.) | | `GET` | `/posts?startDate=&endDate=` | Posts over a date range | | `POST` | `/posts` | Create / schedule a post | | `DELETE` | `/posts/:id` | Delete a post | | `POST` | `/upload` | Upload an image (multipart) | ### POST /posts payload example ```json { "type": "schedule", "date": "2025-01-15T10:00:00.000Z", "content": [ { "content": "Mon super post 🚀", "image": [{ "id": "upload-id", "path": "/uploads/photo.jpg" }] } ], "integrations": ["integration-id-twitter", "integration-id-linkedin"] } ``` To publish immediately, use `"type": "now"`. --- ## Android APK Build (EAS) > **Prerequisites**: free account on [expo.dev](https://expo.dev) and `eas-cli` installed. ### 1. Log in to EAS ```bash npx eas login ``` ### 2. Initialize EAS in the project ```bash cd artifacts/postiz-mobile npx eas init ``` This generates a `projectId` in `app.json`. ### 3. EAS configuration file > **Already included in the repository**: `artifacts/postiz-mobile/eas.json` is present, you can skip this step. To recreate it manually: ```json { "cli": { "version": ">= 16.0.0" }, "build": { "preview": { "android": { "buildType": "apk" } }, "production": { "android": { "buildType": "app-bundle" } } }, "submit": { "production": {} } } ``` ### 4. Start the APK build ```bash # APK de test (sideload) npx eas build --platform android --profile preview # AAB pour le Play Store npx eas build --platform android --profile production ``` The build runs in the EAS cloud (~10-15 min). At the end, EAS displays a **download link** and a **QR code** to retrieve the `.apk` file. ### 5. Install the APK on your phone ```bash # Via adb adb install postiz-mobile.apk # Ou scannez le QR code affiché par EAS ``` ### 6. Publish the APK as a Gitea Release Once the `.apk` is downloaded from EAS, attach it to a Gitea release to make it available directly from the repository: 1. Go to `https://homegit.gyozamancave.fr/billisdead/Postiz-android/releases` 2. Click **New Release** 3. Choose a tag (e.g. `v1.0.0`) and a title 4. Drag and drop the `.apk` file into the attachments area 5. Click **Publish Release** The APK will then be downloadable directly from the Gitea repository page. ### Declared Android permissions ```xml READ_EXTERNAL_STORAGE WRITE_EXTERNAL_STORAGE READ_MEDIA_IMAGES RECEIVE_BOOT_COMPLETED VIBRATE ``` --- ## iOS Build (Expo Launch) > Available only via **Replit Expo Launch** (automated App Store submission). 1. In Replit, click the **Publish** button 2. Select **Expo Launch** 3. Follow the wizard (Apple Developer account required) **Note**: Google Play publishing is not yet supported by Expo Launch — use EAS for Android. --- ## Pushing Changes to Gitea The remote repository is: `ssh://gitea@homegit.gyozamancave.fr:2222/billisdead/Postiz-android.git` The SSH key used is stored in the `GITEA_SSH_KEY` environment variable (on the Replit side). ### Push from your local machine ```bash # Ajouter le remote (une seule fois) git remote add gitea ssh://gitea@homegit.gyozamancave.fr:2222/billisdead/Postiz-android.git # Pousser git push gitea main ``` Make sure your public SSH key is added in Gitea → *User Settings → SSH / GPG Keys*. ### Push from Replit (via script) From Replit, direct `git push` commands are restricted. Use the bundle script: ```bash # Créer le bundle git bundle create /tmp/postiz.bundle main # Cloner le bundle et pousser git clone /tmp/postiz.bundle /tmp/repo_push cd /tmp/repo_push git remote add gitea ssh://gitea@homegit.gyozamancave.fr:2222/billisdead/Postiz-android.git GIT_SSH_COMMAND="ssh -i ~/.ssh/id_ed25519 -o StrictHostKeyChecking=no -p 2222" \ git push --force gitea main ``` --- ## Environment Variables & Secrets | Variable | Storage | Description | |----------|---------|-------------| | `GITEA_SSH_KEY` | Replit Secrets (shared) | Private SSH key for pushing to Gitea | | `SESSION_SECRET` | Replit Secrets | Session secret (API server) | App-side variables (Postiz API key, URL) are **entered by the user** in the Settings screen and stored in `expo-secure-store` — they never pass through the source code. --- ## Troubleshooting ### The app shows "Not Configured" on all screens → Go to the **Settings** tab, enter your API key and URL, then tap **Test Connection**. ### "Connection failed" in Settings - Check that the URL ends with `/public/v1` - Check that the API key is valid (generated in Postiz → API Keys) - Check that your Postiz instance is accessible from the internet ### No notifications received - Accept notification permissions on first launch - Polling runs every 15 minutes — wait for a full cycle - On Android, check that the app's notifications are not disabled in system settings ### Metro error "module not found" ```bash pnpm install # Puis redémarrer le workflow Expo ``` ### Calendar does not load posts - Check that the Postiz API supports `startDate` / `endDate` parameters on `GET /posts` - Check network logs: in Expo Go, shake the device → *Open Debugger* ### EAS build fails ```bash # Vérifier la version Expo npx expo --version # Vérifier la cohérence des packages npx expo install --check ``` --- ## Contributing 1. Fork on Gitea: `https://homegit.gyozamancave.fr/billisdead/Postiz-android` 2. Create a feature branch: `git checkout -b feature/my-feature` 3. Commit your changes 4. Push and open a Pull Request --- *Generated with ❤️ on Replit — PostizMobile v1.0.0*