ZinklyChat Docs
✦ Messenger Client

ZinklyChat Documentation

ZinklyChat is the Flutter messenger client for ZinklySocial. This guide covers everything you need to install it, point it at your own backend, wire up Firebase push notifications, brand it as your own, build release binaries, and publish to the Google Play Store and Apple App Store.

Get started API reference Publish to stores
Overview

What's in the box

ZinklyChat is a standalone Flutter app — chat, groups, calls, stories, VIP and a marketplace-style shop — built to talk to a ZinklySocial-compatible backend over REST and WebSockets. The distribution zip ships clean: no live server URL, no real Firebase project, no signing key. You provide those.

ZinklyChat Flutter app Your backend REST · /api/v1 WebSocket broadcast Firebase Cloud Messaging App Stores Play · App Store baseUrl / wsHost device tokens push notifications flutter build → signed artifact → store

Stack

Flutter, Riverpod, GoRouter, Dio, Firebase Cloud Messaging.

Backend

Any ZinklySocial-compatible REST + WebSocket API (see API reference).

Ownership

No Zinkly credentials are baked in — everything below is yours to fill in.

Before you start

Requirements

Flutter SDK

Flutter 3.x / Dart ≥3.2. Run flutter doctor to confirm your toolchain.

Android Studio

For the Android SDK, an emulator, and building the .aab/.apk.

Xcode (macOS only)

Required to build and sign the iOS app. An Apple Developer account is needed to publish.

A Firebase project

Free tier is enough — used only for push notifications (FCM).

Getting started

Installation

  1. Unzip the projectExtract ZinklyChat.zip anywhere on your machine.
  2. Install dependencies
    cd ZinklyChat
    flutter pub get
  3. Configure your backend URL and Firebase — see Backend URL & app info and Firebase & notifications below. The app runs without Firebase configured, but pushes won't work until you do.
  4. Run it
    flutter run

The zip has no .git history and isn't tied to any Zinkly account — treat it as your own project from the moment you unzip it.

Point it at your own stack

Backend URL & app info

Everything the app needs to know about your install lives in one file: lib/constants/api_constants.dart

class ApiConstants {
  static const String baseUrl   = 'https://YourZinklyMediaURL/api/v1';
  static const String wsHost    = 'YourZinklyMediaURL';
  static const int    wsPort    = 443;
  static const String reverbKey = 'YourReverbAppKey';
  // ...
}
ConstantUsed for
baseUrlAll REST API calls (auth, conversations, messages, calls, VIP…)
wsHostWebSocket connection for realtime messages, typing, presence
webBaseUrlDerived automatically from wsHost — used only by the in-app VIP checkout WebView
reverbKeyYour backend's Reverb/Pusher-protocol broadcasting app key — see below

Your backend runs Laravel Reverb (a self-hosted, Pusher-protocol-compatible WebSocket server), which has its own app key — found in Laravel's config/broadcasting.php under reverb.key, or your BROADCAST_REVERB_APP_KEY/PUSHER_APP_KEY env var. Put that value in reverbKey above. Without it, the realtime connection won't authenticate — the app still works over plain REST, but new messages/typing/presence won't update live until the user manually refreshes.

App identity

Also in the same file, the AppConstants class:

class AppConstants {
  static const String appName   = 'ZinklyChat';
  static const String appScheme = 'zinklymessenger'; // deep-link / URL scheme
}

Update appName if you're renaming the app. If you change appScheme, also update the matching scheme in android/app/src/main/AndroidManifest.xml and ios/Runner/Info.plist so deep links keep working.

Push notifications

Firebase setup

ZinklyChat ships with placeholder Firebase config files so the project still builds out of the box. Replace them with your own before you ship, or pushes silently won't arrive (the app catches the failure and keeps working otherwise).

  1. Create a Firebase projectGo to console.firebase.google.com → Add project.
  2. Register your Android appPackage name: zinkly.chat (or whatever you set it to — see Branding). Download google-services.json and replace:
    android/app/google-services.json
  3. Register your iOS appBundle ID: com.zinkly.zinklyMessenger (or your own). Download GoogleService-Info.plist and replace:
    ios/Runner/GoogleService-Info.plist
  4. Or automate both at once
    dart pub global activate flutterfire_cli
    flutterfire configure
    This detects your Firebase project and writes both platform config files for you.
  5. Enable Cloud MessagingIn the Firebase console, under Project settings → Cloud Messaging, make sure the API is enabled. No extra server key setup is needed on the client side.

How it's wired in code

  • lib/main.dart calls Firebase.initializeApp() at startup, wrapped in a try/catch — a missing/placeholder config won't crash the app.
  • lib/services/fcm_service.dart requests notification permission, gets the device token, and listens for foreground/background/tapped messages.
  • The device token is sent to your backend via POST {baseUrl}/device-tokens (see API reference) — your backend is what actually sends the pushes through Firebase's server SDK when a new message/call/notification happens.

Your backend also needs its own Firebase server credentials (a service-account key) to send pushes — that's separate from the client config above and is configured on the ZinklyMedia/backend side, not in this Flutter app.

Backend contract

API reference

Every endpoint the app calls is declared in lib/constants/api_constants.dart as a relative path appended to baseUrl. Your backend must implement these routes for the matching feature to work.

Core groups

AreaExamples
Auth/auth/login, /auth/register, /auth/logout
Conversations & messages/conversations, /conversations/{id}/messages
Groups/groups, /conversations/{id}/members
Calls/calls, /conversations/{id}/call/token
Stories/stories, /stories/{id}/view
Social/users/{username}/follow, /blocked-users
VIP / payments/vip/packages, /vip/{id}/paypal/create
Push/device-tokens
Support/support/tickets, /support/categories

Realtime events (new messages, typing, presence) arrive over the WebSocket at wsHost, authenticated via authEndpoint (/api/v1/broadcasting/auth) — a Laravel Echo/Pusher-protocol style broadcast auth handshake.

The full, authoritative list of ~70 endpoints is in the ApiConstants class itself — open lib/constants/api_constants.dart and read top to bottom; every route the app can call is right there in one place.

Make it yours

Branding & icons

App icon

Drop your artwork into assets/icons/app_icon.png, then run:

flutter pub run flutter_launcher_icons

Splash screen

Replace assets/icons/splash_logo.png, then run:

dart run flutter_native_splash:create

Display name

AppConstants.appName, plus android:label in AndroidManifest.xml and CFBundleDisplayName in Info.plist.

Bundle / package ID

applicationId in android/app/build.gradle.kts and PRODUCT_BUNDLE_IDENTIFIER in the Xcode project.

Staying current

Updating ZinklyChat

This distribution is a plain zip, not a git remote, so "updating" means dropping a newer ZinklyChat release on top of your customized copy without losing your own settings.

  1. Before updatingNote down (or diff) the files you customized: api_constants.dart, both Firebase config files, key.properties, app icon/splash assets, and any bundle-ID changes.
  2. Put the project under version controlIf you haven't already, git init and commit your customized copy first — this makes re-applying your changes after an update a normal git diff/merge instead of manual copy-paste.
  3. Drop in the new releaseCopy the new zip's files over yours, except the files you customized in step 1.
  4. Re-run setup
    flutter pub get
    dart run build_runner build --delete-conflicting-outputs
    (the second command regenerates the *.g.dart/*.freezed.dart files if any models changed).
  5. Re-testLaunch the app and confirm your backend URL and push notifications still work.
Release artifacts

Building for release

Android

  1. Generate an upload keystore (once — keep this file and its password forever, every future update must be signed with it):
    keytool -genkey -v -keystore upload-keystore.jks \
      -keyalg RSA -keysize 2048 -validity 10000 -alias upload
    Put it at android/app/keystore/upload-keystore.jks.
  2. Point the build at itCopy android/key.properties.example to android/key.properties and fill in the real storePassword, keyPassword, keyAlias, storeFile.
  3. Build the App Bundle (what Google Play wants):
    flutter build appbundle --release
    Output: build/app/outputs/bundle/release/app-release.aab

iOS

  1. Open the workspace
    open ios/Runner.xcworkspace
  2. Set your teamIn Xcode → Runner target → Signing & Capabilities, select your Apple Developer Team. No team is pre-configured in the zip.
  3. Build & archive
    flutter build ipa --release
    Output: build/ios/ipa/*.ipa, ready to upload via Transporter or Xcode Organizer.
Source + assets your config, icon, keys flutter build appbundle / ipa Signed artifact .aab / .ipa Google Play Console App Store Connect
Ship it

Publishing to the stores

Once you have a signed .aab and/or .ipa from the previous section, here's the store-side checklist.

Android

Google Play Store

  1. Create a developer accountOne-time $25 fee at play.google.com/console.
  2. Create the app listingPlay Console → Create app — name, default language, app/game, free/paid.
  3. Fill in store presenceScreenshots, feature graphic, short/full description, app icon, privacy policy URL, content rating questionnaire, target audience, data safety form.
  4. Upload your buildProduction (or an internal/closed testing track first) → Create new release → upload the .aab from build/app/outputs/bundle/release/.
  5. Submit for reviewGoogle's review typically takes anywhere from a few hours to a few days for a first submission.

Test on the internal testing track first — it skips full review and lets you sanity-check the signed build on a real device before going public.

iOS

Apple App Store

  1. Enroll in the Apple Developer Program$99/year at developer.apple.com/programs.
  2. Register the appApp Store Connect → My Apps → + — bundle ID must match PRODUCT_BUNDLE_IDENTIFIER in Xcode.
  3. Upload the buildUse Xcode Organizer or the standalone Transporter app to upload the .ipa from build/ios/ipa/.
  4. Fill in the listingScreenshots (per device size), description, keywords, privacy policy URL, App Privacy details (what data the app collects), age rating.
  5. TestFlight first (recommended)Once uploaded, the build is available to TestFlight testers immediately — no review needed for internal testers.
  6. Submit for reviewApple's review is typically 24–48 hours. Make sure the review notes include a working test account if login is required.

Apple reviewers will test push notifications, calls, and account creation end-to-end — make sure your backend URL in api_constants.dart points at a live, reachable server before submitting, not a placeholder or local address.

Common issues

Troubleshooting

SymptomLikely cause
App builds but can't log in / load chatsbaseUrl/wsHost in api_constants.dart still points at a placeholder or unreachable host
Push notifications never arrivePlaceholder Firebase config files still in place, or your backend lacks its own Firebase server credentials
Android release build fails to signandroid/key.properties missing or pointing at the wrong keystore path
Play Store rejects the uploadUploaded a debug-signed .apk instead of a release-signed .aab
Xcode build fails to signNo Apple Developer Team selected under Signing & Capabilities