Files
Postiz-android/artifacts/postiz-mobile
billisdead 0696f5663e
Release APK / build (push) Has been cancelled
feat: multi-images, media library, + fix HTML in notifications
Multi-images (compose):
- Replace single imageUri with mediaItems: MediaItem[] (local | uploaded)
- allowsMultipleSelection: true, selectionLimit up to 4 total
- Each picked image is resized to max 1920px before upload
- Thumbnail row with individual × remove buttons
- uploaded badge (cloud icon) on library/prefill images
- buildMediaPayload() uploads local items, passes uploaded items as-is

Media Library:
- New MediaLibraryModal component — full-screen modal
- Fetches GET /media from Postiz instance
- 3-column grid with multi-select (capped at remaining slots)
- Selected items added to compose media pool

Notifications:
- Strip HTML from notification body text

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 17:09:08 +02:00
..

PostizMobile

React Native (Expo) mobile app to control a self-hosted Postiz instance from Android.

Build is fully local — no expo.dev account or EAS cloud required.


Features

Screen Description
Calendar Monthly view with color dots per day (indigo = scheduled, green = published, red = error). Tap a day post to copy or edit it.
Posts Filtered list (All / Queue / Published / Draft / Error) with post counts, sort toggle (newest/oldest, persisted), pull-to-refresh, swipe left to delete, swipe right to reschedule.
Compose Text editor with per-network character limit, channel picker, date/time picker, gallery image pick + upload, publish now or schedule. Local draft save/restore.
Settings API key and base URL, connection test, secure storage. 401 auto-redirect to Settings.
Notifications Local alerts when a post transitions to PUBLISHED or ERROR (polling every 15 min).

Theme: forced dark. Auth: API key in expo-secure-store, never hardcoded.


Prerequisites

Tool Version
Node.js 20 LTS
pnpm 10+
Java (JDK) 1724 (Java 25+ not yet supported by Gradle 8)
Android SDK see below

No expo.dev account needed for builds.


Development

Install dependencies

git clone https://github.com/pirona/postiz-android.git
cd postiz-android
pnpm install

Start dev server (Expo Go)

pnpm --filter @workspace/postiz-mobile run dev

Scan the QR code with Expo Go on Android to preview the app live.


Building an APK (local, no EAS)

First-time setup

1. Java 21 LTS

Gradle 8 requires Java ≤ 24. If the system Java is 25+ (Fedora 44), install Temurin 21 locally:

wget -O /tmp/jdk21.tar.gz \
  "https://github.com/adoptium/temurin21-binaries/releases/download/jdk-21.0.7%2B6/OpenJDK21U-jdk_x64_linux_hotspot_21.0.7_6.tar.gz"
mkdir -p ~/jdk21 && tar -xzf /tmp/jdk21.tar.gz -C ~/jdk21 --strip-components=1

build-apk.sh will use ~/jdk21 automatically if the system Java is ≥ 25.

2. Android SDK

cd artifacts/postiz-mobile
./install-android-sdk.sh

Add to ~/.bashrc or ~/.zshrc:

export ANDROID_HOME="$HOME/android-sdk"
export PATH="$PATH:$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools:$ANDROID_HOME/build-tools/35.0.0"

2. Signing keystore

The release keystore is stored at ~/.config/postiz-mobile/postiz-mobile.jks (not in the repo).

To export it from EAS (one-time):

cd artifacts/postiz-mobile
eas credentials --platform android
# → Keystore: Manage everything → Download existing keystore
# Note the key alias and passwords shown during export

3. Signing credentials

cp ~/.config/postiz-mobile/signing.env.example ~/.config/postiz-mobile/signing.env
$EDITOR ~/.config/postiz-mobile/signing.env

Fill in:

KEYSTORE_PATH="$HOME/.config/postiz-mobile/postiz-mobile.jks"
KEYSTORE_ALIAS="<alias shown during export>"
KEYSTORE_STORE_PASSWORD="<store password>"
KEYSTORE_KEY_PASSWORD="<key password>"

Build

cd artifacts/postiz-mobile
./build-apk.sh           # → dist/postiz-mobile-YYYYMMDD-HHMM.apk
./build-apk.sh --aab     # → dist/postiz-mobile-YYYYMMDD-HHMM.aab  (Play Store)

The script runs expo prebuild, patches android/app/build.gradle for release signing, runs Gradle, copies the artifact to dist/, then wipes the credentials from gradle.properties.

Install on device

adb install dist/postiz-mobile-*.apk

How the build works

build-apk.sh
  ├── source ~/.config/postiz-mobile/signing.env
  ├── expo prebuild --platform android --clean
  │     └── generates android/ from app.json + plugins
  ├── python3 patch: injects release signingConfig into build.gradle
  ├── append MYAPP_UPLOAD_* to gradle.properties
  ├── ./gradlew assembleRelease (or bundleRelease)
  ├── wipe signing block from gradle.properties
  └── copy APK → dist/

The android/ directory is not committed (gitignored). It is regenerated on each build.


App configuration

On first launch, go to Settings:

  1. Base URL: https://your-postiz-instance/api/public/v1
  2. API Key: generated in Postiz → Settings → API Keys
  3. Tap Test Connection, then Save Settings

The key is encrypted locally via expo-secure-store and never sent to third parties.


Architecture

artifacts/postiz-mobile/
├── app/
│   ├── _layout.tsx              # Root layout: providers, fonts, 401 handler
│   └── (tabs)/
│       ├── _layout.tsx          # Tab bar
│       ├── index.tsx            # Calendar screen
│       ├── posts.tsx            # Post list screen
│       ├── compose.tsx          # Compose screen
│       └── settings.tsx         # Settings screen
├── components/
│   ├── ChannelChip.tsx          # Channel selector chip
│   ├── ErrorBoundary.tsx
│   ├── PostCard.tsx             # Swipe-to-delete / swipe-to-reschedule
│   └── StatusBadge.tsx
├── context/
│   └── PostizContext.tsx        # axios client + SecureStore + 401 interceptor
├── hooks/
│   ├── useColors.ts
│   └── useNotifications.ts     # Permission + polling + local notifications
├── lib/
│   └── extractError.ts         # Shared axios/fetch error formatter
├── build-apk.sh                # Local build script
└── install-android-sdk.sh      # One-time Android SDK bootstrap

Key dependencies

Package Role
expo-router File-based navigation
axios Postiz API HTTP client
expo-secure-store Encrypted key storage
react-native-calendars Calendar view
@react-native-community/datetimepicker Date/time picker
expo-image-picker Gallery access
expo-notifications Local status notifications
@tanstack/react-query API cache + refetch

Postiz API

Method Endpoint Usage
GET /integrations List channels
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)

Troubleshooting

"Not Configured" on all screens → Settings tab → enter API key and URL → Test Connection.

"Connection failed" → URL must end with /api/public/v1 — check Postiz is reachable.

No notifications → Accept permissions on first launch. Polling runs every 15 min.

Build fails at Gradle → Make sure ANDROID_HOME is set and ./gradlew is executable (chmod +x android/gradlew).

expo prebuild fails → Run pnpm install from the repo root first.