eSellify Documentation

Complete setup and deployment guide for the eSellify classifieds platform.

v1.4 · Flutter + Firebase

About eSellify

eSellify is an online classifieds platform — like OLX, Gumtree, or Craigslist — built end-to-end with Flutter and Firebase. Buyers and sellers post free or paid listings with photos, categories, location, and price; chat directly inside the app; and discover ads near them. The platform ships as a mobile app (Android & iOS), a customer web app, an admin panel, Cloud Functions for email/notifications, and a marketing landing page. Subscriptions, featured ads, and watermarks are built in and fully configurable from the admin panel.

📱
Platforms
Android, iOS & Web
🔧
Stack
Flutter + Firebase
📧
Support Email
📞
WhatsApp

What's Included

Live Demo

⚙️
Admin Panel
🌐
Landing Page
🤖
Android App
🍎
iOS App
📝 Demo Credentials

Admin Panel: admin@esellify.com / 123456

Before starting the setup, make sure you have the following tools and accounts ready.

⚠ External Services & Costs

eSellify uses third-party services billed separately by their providers: Firebase (Blaze pay-as-you-go beyond the free tier), Google Maps Platform (billed after the free monthly credit), OpenAI (per-token API pricing for AI content generation), and payment gateways (per-transaction fees, own merchant accounts). AdMob is free to integrate (it pays you). These costs are not included in the item price — review each provider's pricing before launching commercially.

Required Software

Software Version Required For
Flutter SDK 3.11+ (latest stable) Building all apps
Android Studio Latest Android build & emulator
Xcode (macOS only) 15.0+ iOS build & simulator
Node.js 22.x Cloud Functions & database import
Firebase CLI Latest Deploy Firebase services
Google Cloud SDK Latest Storage CORS configuration
Git Latest Version control
CocoaPods (macOS only) Latest iOS dependency management

Required Accounts

Important
  • Firebase Blaze plan (pay-as-you-go) is required for Cloud Functions and some auth features. Free tier limits cover most small projects.
  • iOS development & Sign in with Apple require macOS with Xcode. Building iOS on Windows is not supported.

The complete setup takes about 1–2 hours. Follow each step in order.

⚠️ Read First

You received the Flutter source code — not a ready-to-upload website. You must (1) set up Firebase, (2) build the app, and (3) upload only the build output. The raw lib/ source cannot be uploaded directly to a web server.

The complete, ordered installation walkthrough. Follow the steps in this order — they match the numbered steps in the left menu, and each links to its detailed section.

Phase 1 — Environment

  1. Install the Flutter SDK and run flutter doctor until clean — Step 1.
  2. Unzip the package: customer/, customer_web/, admin_panel/, function/, landing-page/, documentation/.

Phase 2 — Firebase Backend

  1. Create the project and register the apps — Create Project.
  2. Enable sign-in methods — Authentication.
  3. Create Firestore, import starter data, deploy indexes — Firestore Database.
  4. Enable Storage + CORS — Storage & CORS.
  5. Deploy Cloud Functions (Node.js 22) — Cloud Functions.

Phase 3 — Configure & Build the Apps

  1. Set your app name, logo, package/bundle id and Maps key — Step 3.
  2. Android: SHA keys, release signing, build APK/AAB — Step 4.
  3. iOS: bundle id, capabilities, APNS, build & TestFlight — Step 5.
  4. Web: run and deploy Customer Web + Admin Panel — Step 6.

Phase 4 — Go Live

  1. Publish the landing page — Step 7.
  2. Configure push notifications — Step 8.
  3. Enable payments, ads, OpenAI and SMTP from the Admin Panel — Step 9.
  4. Enable your languages — Step 10.
Stuck?

Check Troubleshooting — common setup errors are listed with exact fixes.

Install Flutter SDK on your machine. Choose your operating system below.

Windows

System Requirements
Step 1: Download Flutter SDK
Step 2: Add Flutter to System PATH
  1. Open Start Menu, search for "Environment Variables", click "Edit the system environment variables".
  2. Click Environment Variables.
  3. Under User variables, select Path and click Edit.
  4. Click New and add: C:\src\flutter\bin
  5. Click OK to save and close all dialogs. Restart your terminal.
Step 3: Install Android Studio
Step 4: Create an Android Emulator
  1. Open Android Studio.
  2. Go to Tools → Device Manager (or AVD Manager on older versions).
  3. Click Create Device, pick a phone profile, choose a recent system image (API 33+), and finish.
Step 5: Verify Installation
flutter doctor

Resolve any red marks before continuing. Accept Android licenses if prompted:

flutter doctor --android-licenses

macOS

System Requirements
Step 1: Download Flutter SDK
Step 2: Add Flutter to PATH

Edit your shell profile (~/.zshrc for zsh or ~/.bashrc for bash):

export PATH="$PATH:$HOME/development/flutter/bin"

Reload the shell:

source ~/.zshrc
Step 3: Install Xcode
sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
sudo xcodebuild -runFirstLaunch
Step 4: Install CocoaPods
sudo gem install cocoapods
Step 5: Install Android Studio (Optional, for Android)

If you also need Android, install Android Studio + Flutter / Dart plugins, same as the Windows steps.

Step 6: Verify Installation
flutter doctor

You should see green checkmarks for Flutter, Xcode, and (if installed) Android toolchain.

Firebase powers authentication, the database, storage, push notifications, and Cloud Functions. Set it up before building any of the apps.

1. Create a Firebase Project

  1. Go to Firebase Console and sign in with a Google account.
  2. Click Add project, give it a name (e.g. eSellify-Prod), and accept the terms.
  3. Enable Google Analytics (recommended) and finish creating the project.
  4. In Project Settings → General, upgrade to the Blaze (pay-as-you-go) plan. This is required for Cloud Functions and some auth methods.

Install Firebase CLI & FlutterFire CLI

npm install -g firebase-tools
dart pub global activate flutterfire_cli

Login & Configure Each App

Login once:

firebase login

Then, in each of customer/, customer_web/, and admin_panel/, run:

flutter pub get
flutterfire configure

Select your Firebase project when prompted. This generates lib/firebase_options.dart and downloads google-services.json (Android) and GoogleService-Info.plist (iOS).

2. Authentication

In Firebase Console → Authentication → Sign-in method, enable each provider you want:

Phone Authentication
  1. Click Phone → Enable.
  2. Add test phone numbers (optional, but useful for development): e.g., +91 9876543210 with code 123456.
  3. Save.
Google Sign-In
  1. Click Google → Enable.
  2. Set the project support email.
  3. Save.
Apple Sign-In
  1. Click Apple → Enable.
  2. You'll need an Apple Developer account — configuration is covered in the iOS Capabilities section below.
Authorized Domains (for Web)

Under the Settings tab of Authentication, add your web app's domain (e.g. esellify.yourdomain.com) to Authorized domains.

3. Firestore Database

Create the Database
  1. In Firebase Console → Firestore DatabaseCreate database.
  2. Choose production mode (we'll add security rules later).
  3. Pick a location close to your users (this cannot be changed later).
Import Pre-built Collections

The project ships with starter Firestore data (categories, languages, settings). To import:

  1. Generate a service account key: Firebase Console → Project Settings → Service Accounts → Generate new private key.
  2. Save the file as serviceAccountKey.json in the database import folder.
  3. Run the import:
cd database_import
npm install
node import.js
Deploy Indexes

The project's Firestore indexes are defined in firestore.indexes.json. Deploy them so queries are fast:

firebase deploy --only firestore:indexes

4. Storage & CORS

Enable Storage
  1. Firebase Console → StorageGet started.
  2. Choose production mode and pick a location (same region as Firestore is fine).
Storage Security Rules

Replace the default rules with the following (requires login to upload/read):

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth != null;
    }
  }
}
Configure CORS (required for Customer Web)

The web app needs CORS configured on the Storage bucket to upload images. Install the Google Cloud SDK, then:

  1. Create a file cors.json:
[
  {
    "origin": ["*"],
    "method": ["GET", "POST", "PUT", "DELETE", "HEAD"],
    "responseHeader": ["Content-Type", "Authorization"],
    "maxAgeSeconds": 3600
  }
]
  1. Apply it to your bucket (replace YOUR_PROJECT_ID):
gsutil cors set cors.json gs://YOUR_PROJECT_ID.appspot.com
  1. Verify:
gsutil cors get gs://YOUR_PROJECT_ID.appspot.com

5. Cloud Functions

Cloud Functions handle SMTP/email and notification fan-out. Deploy them once:

cd function/functions
npm install
firebase deploy --only functions

To deploy a single function:

firebase deploy --only functions:sendTransactionalEmail

To view logs:

firebase functions:log
💡 Node.js Version

Cloud Functions in this project run on Node.js 22. Your local Node version must match. Check with node --version.

Customize the app's name, logo, package ID, and API keys for your brand.

Package Name (Android) & Bundle ID (iOS)

Android Package Name

Edit android/app/build.gradle:

defaultConfig {
    applicationId "com.yourcompany.esellify"
    // ...
}

Also update android/app/src/main/AndroidManifest.xml — the package attribute.

iOS Bundle Identifier
  1. Open ios/Runner.xcworkspace in Xcode.
  2. Select the Runner target.
  3. Under General → Identity, set Bundle Identifier to com.yourcompany.esellify.
  4. Make sure the Bundle ID is registered in your Apple Developer account.
⚠️ Important

Set the package name / bundle ID before connecting Firebase. The next step (Connect Firebase) registers each app using these IDs, so they must be final first.

Connect Firebase to Each App

Do this after setting the Android package name and iOS bundle ID above — flutterfire configure registers each app in Firebase using those IDs, so they must be final first. eSellify has three Flutter apps that all talk to the same Firebase project: the mobile Customer App (customer/), the Customer Web app (customer_web/), and the Admin Panel (admin_panel/). Run flutterfire configure once per folder so each gets its own lib/firebase_options.dart.

Prerequisites (run once)
npm install -g firebase-tools
dart pub global activate flutterfire_cli
firebase login

firebase login opens a browser window to authenticate with your Google account.

1. Customer App (Mobile — Android & iOS)
cd customer
flutter pub get
flutterfire configure --project=YOUR_PROJECT_ID

When asked which platforms to support, select android and ios:

? Which platforms should your configuration support?
  (*) android    <-- select
  (*) ios        <-- select
  ( ) macos
  ( ) web
  ( ) windows

Use the arrow keys and Space to toggle, then press Enter. This generates customer/lib/firebase_options.dart and downloads google-services.json (Android) and GoogleService-Info.plist (iOS).

2. Customer Web (Web only)
cd customer_web
flutter pub get
flutterfire configure --project=YOUR_PROJECT_ID

Select web only:

? Which platforms should your configuration support?
  ( ) android
  ( ) ios
  ( ) macos
  (*) web        <-- select ONLY this
  ( ) windows
⚠️ Keep the web keys in sync

Flutter reads customer_web/lib/firebase_options.dart, while the JS SDK in web/index.html and the background service worker firebase-messaging-sw.js read their own copies. All three must use the same Firebase web config, or you will get authentication errors or silent FCM failures.

3. Admin Panel (Web only)
cd admin_panel
flutter pub get
flutterfire configure --project=YOUR_PROJECT_ID

Select web only (same as Customer Web). When asked “firebase_options.dart already exists. Do you want to override it?”, type yes. Setup is complete when you see “Firebase configuration file lib/firebase_options.dart generated successfully.”

⚠️ Same project, three apps

Run the command in all three folders but always choose the same Firebase project when prompted, so the mobile app, web app and admin panel share one backend (users, ads, chat, subscriptions, etc.).

Google Maps API Key

Required for location features (map view, address picker).

Generate the Key
  1. Go to Google Cloud Console.
  2. Select your Firebase project (it's already linked).
  3. Enable these APIs: Maps SDK for Android, Maps SDK for iOS, Maps JavaScript API, Geocoding API, Places API.
  4. Create an API key under APIs & Services → Credentials.
  5. Restrict the key by platform (Android package name + SHA-1, iOS bundle ID, HTTP referrer for web).
Add to Android

In android/app/src/main/AndroidManifest.xml:

<meta-data
    android:name="com.google.android.geo.API_KEY"
    android:value="YOUR_ANDROID_MAPS_KEY"/>
Add to iOS

In ios/Runner/AppDelegate.swift:

import GoogleMaps

GMSServices.provideAPIKey("YOUR_IOS_MAPS_KEY")
Add to Web

In web/index.html (head section):

<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_WEB_MAPS_KEY&libraries=places"></script>

SHA-1 & SHA-256 Keys

Required for Google Sign-In and Firebase phone authentication on Android.

Generate the Keys
cd android
./gradlew signingReport

On Windows: gradlew signingReport

You'll see output like:

SHA1: AB:CD:EF:...:01:23
SHA-256: AB:CD:EF:...:01:23
Add to Firebase
  1. Firebase Console → Project Settings → Your apps → Android app.
  2. Click Add fingerprint.
  3. Paste SHA-1, then add another for SHA-256.
  4. Re-download google-services.json and replace the one in android/app/.

Release Signing

For production builds, you need a release keystore (not the debug one).

Generate a Keystore
keytool -genkey -v -keystore ~/upload-keystore.jks \
  -keyalg RSA -keysize 2048 -validity 10000 -alias upload

Remember the keystore password — you'll need it for every release.

Create key.properties

Create android/key.properties (DO NOT commit to Git):

storePassword=YOUR_KEYSTORE_PASSWORD
keyPassword=YOUR_KEY_PASSWORD
keyAlias=upload
storeFile=/Users/yourname/upload-keystore.jks
Configure build.gradle

The project's android/app/build.gradle is already configured to use key.properties for release signing.

Get Release SHA-1 / SHA-256
keytool -list -v -keystore ~/upload-keystore.jks -alias upload

Add the release SHA-1 and SHA-256 to Firebase (same as debug keys above).

Build APK / AAB

APK (for direct install / testing)
cd customer
flutter build apk --release

Output: build/app/outputs/flutter-apk/app-release.apk

AAB (for Google Play Store)
flutter build appbundle --release

Output: build/app/outputs/bundle/release/app-release.aab

Upload the AAB to the Google Play Console.

The most detailed setup section — iOS has the strictest signing and capability requirements. Follow each step in order.

iOS Prerequisites

Install iOS Dependencies
cd customer/ios
pod install

If you see CocoaPods errors, try:

pod repo update
pod install --repo-update

Bundle ID & Signing Team

Step 1: Register a Bundle ID
  1. Go to Apple Developer → Identifiers.
  2. Click + to create a new identifier.
  3. Select App IDs → App.
  4. Description: e.g. "eSellify Customer".
  5. Bundle ID: Explicitcom.yourcompany.esellify (must be globally unique).
  6. Under Capabilities, enable: Push Notifications, Sign in with Apple, Associated Domains (if using deep links).
  7. Save.
Step 2: Set Bundle ID in Xcode
  1. Open customer/ios/Runner.xcworkspace in Xcode.
  2. Select the Runner project, then the Runner target.
  3. Under General → Identity, set Bundle Identifier to match the one you registered.
  4. Set Display Name to "eSellify" (or your brand name).
  5. Set Version (e.g. 1.4.0) and Build (e.g. 1).
Step 3: Select Signing Team
  1. Under Signing & Capabilities tab, check Automatically manage signing.
  2. Select your Team (your Apple Developer account).
  3. Xcode will automatically create a provisioning profile.

Capabilities

Enable these capabilities in Xcode → Signing & Capabilities tab → + Capability:

Push Notifications

Add the Push Notifications capability. Xcode generates a .entitlements file automatically.

Background Modes

Add Background Modes and enable:

Sign in with Apple
  1. Add Sign in with Apple capability.
  2. In Apple Developer Portal → Identifiers, edit your App ID and confirm Sign in with Apple is enabled.
  3. In Firebase Console → Authentication → Sign-in method → Apple, enable it.
  4. Add your Bundle ID as the Services ID in Firebase (for web/Android) and configure the redirect URL.
Associated Domains (Optional)

For universal links (deep linking from web URLs), add Associated Domains with:

applinks:yourdomain.com

APNS Authentication Key (Push Notifications)

iOS push notifications via Firebase need an Apple Push Notification Service (APNS) key.

Step 1: Generate APNS Key
  1. Go to Apple Developer → Keys.
  2. Click + to create a new key.
  3. Name it (e.g. "APNS for eSellify").
  4. Enable Apple Push Notifications service (APNs).
  5. Continue → Register.
  6. Download the .p8 file — you can only download it once! Save it securely.
  7. Note the Key ID and your Team ID (top right of the page).
Step 2: Upload Key to Firebase
  1. Firebase Console → Project Settings → Cloud Messaging.
  2. Under Apple app configuration, click Upload next to APNs Authentication Key.
  3. Upload the .p8 file.
  4. Enter the Key ID and Team ID.
  5. Save.

Info.plist Permissions

iOS requires explicit usage descriptions for each permission. Open ios/Runner/Info.plist in Xcode (or as XML) and ensure these keys are present:

<key>NSCameraUsageDescription</key>
<string>eSellify uses your camera to take photos of items you want to sell.</string>

<key>NSPhotoLibraryUsageDescription</key>
<string>eSellify uses your photo library to add photos to your listings.</string>

<key>NSPhotoLibraryAddUsageDescription</key>
<string>eSellify saves photos to your photo library.</string>

<key>NSLocationWhenInUseUsageDescription</key>
<string>eSellify uses your location to show ads near you.</string>

<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>eSellify uses your location to show ads near you.</string>

<key>NSMicrophoneUsageDescription</key>
<string>eSellify uses your microphone for voice messages in chat.</string>

<key>NSContactsUsageDescription</key>
<string>eSellify uses your contacts to help you find friends.</string>

Also confirm these app transport keys are present:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

Build & Archive

Run on Simulator
cd customer
flutter run

Pick an iOS simulator from the device dropdown.

Run on Real Device
  1. Connect your iPhone via USB.
  2. Trust the computer on the device.
  3. In Xcode, select your device from the device dropdown.
  4. Run: flutter run
  5. On the device, go to Settings → General → VPN & Device Management and trust your developer certificate.
Release Build (Archive)
cd customer
flutter build ios --release

Then in Xcode:

  1. Open ios/Runner.xcworkspace.
  2. Select Any iOS Device (arm64) as the destination (top bar).
  3. Go to Product → Archive.
  4. Wait for the archive to build (~5–10 minutes).
  5. The Organizer window opens with your archive.

TestFlight Distribution

Use TestFlight for internal testing before public release.

Step 1: Create App in App Store Connect
  1. Go to App Store Connect.
  2. Click My Apps → +New App.
  3. Platform: iOS, Bundle ID: pick the one you registered, SKU: any unique string.
  4. Create.
Step 2: Upload Archive
  1. In Xcode Organizer, select your archive.
  2. Click Distribute AppApp Store ConnectUpload.
  3. Use default options (let Xcode manage signing).
  4. Wait for upload to complete (~5–15 minutes).
Step 3: Add Testers
  1. In App Store Connect → your app → TestFlight tab.
  2. Wait for the build to finish processing (~10–30 minutes).
  3. Once ready, add testers (internal team or external by email/group).
  4. For external testers, you need to submit for a brief Apple review (~24 hours).

App Store Submission

Prepare Store Listing

In App Store Connect → your app → App Store tab, fill in:

Submit for Review
  1. Select the build you uploaded from TestFlight.
  2. Fill in App Review Information — demo account credentials, contact info.
  3. Click Submit for Review.
  4. Review usually takes 24–72 hours.
💡 Common Rejection Reasons
  • Missing Privacy Policy URL
  • Demo account not working
  • Crashes on launch (test on real device first)
  • Missing Info.plist permission strings
  • Sign in with Apple not offered alongside other social logins

eSellify ships with two Flutter web apps: the Customer Web for buyers/sellers, and the Admin Panel for moderation.

Customer Web

Path: customer_web/

Changing Application Name (Customer Web)

1. Update HTML Title & Meta
<title>Your New App Name</title>
<meta name="description" content="Your short app description">
<meta name="apple-mobile-web-app-title" content="Your App Name">
2. Update PWA Manifest
{
    "name": "Your App Name",
    "short_name": "AppShort",
    "description": "Your app description",
    "theme_color": "#3068FF",
    ...
}

Configure Firebase for Customer Web

Customer Web needs Firebase credentials in three places. All three must use the same web app from your Firebase project.

1. Get Your Firebase Web Config
2. Update web/index.html
window.firebaseConfig = {
    apiKey: "YOUR_API_KEY",
    authDomain: "YOUR_PROJECT.firebaseapp.com",
    projectId: "YOUR_PROJECT_ID",
    storageBucket: "YOUR_PROJECT.firebasestorage.app",
    messagingSenderId: "YOUR_SENDER_ID",
    appId: "YOUR_APP_ID",
    measurementId: "YOUR_MEASUREMENT_ID"
};
3. Update web/firebase-messaging-sw.js
4. Update lib/firebase_options.dart
static const FirebaseOptions web = FirebaseOptions(
    apiKey: 'YOUR_API_KEY',
    appId: 'YOUR_APP_ID',
    messagingSenderId: 'YOUR_SENDER_ID',
    projectId: 'YOUR_PROJECT_ID',
    authDomain: 'YOUR_PROJECT.firebaseapp.com',
    storageBucket: 'YOUR_PROJECT.firebasestorage.app',
    measurementId: 'YOUR_MEASUREMENT_ID',
);
All three must match

Flutter reads from firebase_options.dart, while the JS SDK in index.html and the background service worker firebase-messaging-sw.js read their own copies. If the three are not identical you will get authentication errors or silent FCM failures.

Alternatively, you can let the FlutterFire CLI generate lib/firebase_options.dart for you:

cd customer_web
flutter pub get
flutterfire configure

Select your Firebase project and choose the Web platform — you'll still need to update web/index.html and web/firebase-messaging-sw.js by hand.

Google Maps API Key (Customer Web)

Customer Web uses Google Maps for the location picker, address selection, and ad-detail map embed. If you already created a Google Maps API key for your admin panel or mobile app, you can reuse it — just make sure the key has the Maps JavaScript API and Places API enabled and is not restricted to a different referrer.

1. Enable Required APIs
2. Add Your API Key to web/index.html
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places"></script>
3. Restrict the Key (Recommended)
Run Locally
flutter run -d chrome

Admin Panel

Path: admin_panel/

Configure Firebase
cd admin_panel
flutter pub get
flutterfire configure
Run Locally
flutter run -d chrome
Default Admin Login

After importing the database, login with:

Change this password immediately from the admin profile after first login.

Build & Deploy

Build for Production
cd admin_panel        # or customer_web
flutter build web --release

Output: build/web/ — this is what you deploy.

Deploy to Firebase Hosting
firebase login
firebase init hosting

When prompted:

Then:

firebase deploy --only hosting
Deploy to Other Hosts

You can also upload the build/web/ folder contents to any static host: Hostinger, Netlify, Vercel, GitHub Pages, AWS S3, etc.

Landing Page Setting

One config, all pages

Firebase credentials for the Landing Page are now stored in one shared file: landing-page/firebase-config.js. This single file is automatically used by index.html, privacy-policy.html, and terms-and-conditions.html — so you only need to update your credentials in one place.

1. Open the Shared Firebase Config File
// landing-page/firebase-config.js
var firebaseConfig = {
    apiKey: "YOUR_API_KEY",
    authDomain: "YOUR_AUTH_DOMAIN",
    projectId: "YOUR_PROJECT_ID",
    storageBucket: "YOUR_STORAGE_BUCKET",
    messagingSenderId: "YOUR_MESSAGING_SENDER_ID",
    appId: "YOUR_APP_ID",
    measurementId: "YOUR_MEASUREMENT_ID"
};
2. Get Firebase Credentials
No Web App shown?

If no Web App is listed, click Add app → select the Web icon (</>) → enter a nickname → click Register app. The firebaseConfig will then appear.

3. Replace the Config
⚠️ Do not add firebase.initializeApp() to individual HTML files

The shared firebase-config.js already calls firebase.initializeApp() and exposes window.db for every page. Duplicating the init call inside index.html or any other HTML file will cause a "Firebase App named '[DEFAULT]' already exists" error.

Navigation Path: Firebase Console → ⚙ Gear Icon → Project Settings → General tab → Your apps → Web app → SDK setup and configuration → Copy firebaseConfig → Paste into landing-page/firebase-config.js

Deploying to Hostinger / Shared Hosting

This section applies to Admin Panel and Customer Web when hosted on Hostinger, cPanel, or any shared Apache / LiteSpeed hosting. It fixes the three most common problems: changes not reflecting after re-upload, direct URLs returning 404, and blank white pages.

Upload the build, not the source

You can only upload a compiled build to shared hosting. Set up Firebase, run flutter build web --release, and upload the contents of the build/web/ folder — uploading the project source code will not work.

⚠️ Why changes don't reflect after upload
  • Flutter's service worker (flutter_service_worker.js) aggressively caches the old build. Visitors keep seeing the old version until the cache is busted.
  • Hostinger's LiteSpeed cache caches index.html at the server level.
  • Browser caching of main.dart.js and other assets.
1. Add an .htaccess file to your web folder

Create a file named .htaccess inside your project's web/ folder (so Flutter copies it into build/web/ on every build) with the following contents:

# --- SPA route rewrite ---
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /
    RewriteRule ^index\.html$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.html [L]
</IfModule>

# --- Never cache index.html and service worker ---
<IfModule mod_headers.c>
    <FilesMatch "^(index\.html|flutter_service_worker\.js|flutter_bootstrap\.js|manifest\.json)$">
        Header set Cache-Control "no-store, no-cache, must-revalidate, max-age=0"
        Header set Pragma "no-cache"
        Header set Expires "0"
    </FilesMatch>

    # Long cache for hashed static assets
    <FilesMatch "\.(js|wasm|woff2?|ttf|otf|png|jpg|jpeg|gif|svg|ico)$">
        Header set Cache-Control "public, max-age=31536000, immutable"
    </FilesMatch>
</IfModule>

# --- Gzip compression ---
<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/html text/plain text/css text/javascript application/javascript application/json application/xml image/svg+xml font/ttf font/otf application/wasm
</IfModule>

# --- Correct MIME types (fixes blank pages) ---
<IfModule mod_mime.c>
    AddType application/wasm .wasm
    AddType application/javascript .js
    AddType application/manifest+json .webmanifest
</IfModule>

# --- Disable LiteSpeed cache for entry files ---
<IfModule LiteSpeed>
    <FilesMatch "^(index\.html|flutter_service_worker\.js|flutter_bootstrap\.js|manifest\.json)$">
        CacheDisable public
    </FilesMatch>
</IfModule>

ErrorDocument 404 /index.html

This project already ships with this file at admin_panel/web/.htaccess and customer_web/web/.htaccess — any build will carry it into build/web/ automatically.

2. Build the release bundle
flutter clean
flutter pub get
flutter build web --release
3. Upload to Hostinger
Make hidden files visible in Hostinger File Manager

By default the File Manager hides dotfiles. Click the gear icon (settings) in the top-right of File Manager and enable "Show hidden files" so you can see and upload .htaccess.

4. Purge Hostinger's LiteSpeed cache
5. Force-refresh your browser

Even with the new .htaccess, any visitor who already loaded the old service worker still has it installed. The first visit after your upload may still show the old version. To verify immediately:

6. Verify the deploy
Common Hostinger-specific issues

Blank white page after upload

Direct URLs (e.g. /ad-listing-detail) return 404

Old version keeps loading

Push notifications use Firebase Cloud Messaging (FCM). Setup differs slightly per platform.

Android

Works automatically once Firebase is configured and the app is signed.

iOS

Requires the APNS key uploaded to Firebase — see iOS APNS setup above.

Notification Setup for Web

1. Add Notification Key in Admin Panel
2. Configure firebase-messaging-sw.js

The service worker that receives background pushes is set up in the Web Setup section. See Configure Firebase for Customer Web → step 3 for the full firebase-messaging-sw.js instructions and code template — that file is mandatory for web push.

3. VAPID Key
  1. In Firebase Console → Project Settings → Cloud Messaging → Web configuration, generate a VAPID key pair.
  2. Copy the VAPID public key.
  3. Paste it into your customer_web's notification service config.

Service Account JSON (for Cloud Functions notifications)

The project sends notifications via FCM REST API using a service account:

  1. Firebase Console → Project Settings → Service Accounts → Generate new private key.
  2. Upload the JSON to your Storage bucket or a secure URL.
  3. Set the URL in Admin Panel → Notification Settings → Service Account URL.
  4. Set the Sender ID (Project Number from Firebase) in the same panel.

Most features are configured at runtime from the Admin Panel. No code changes needed.

Payment Gateways

Configure in Admin Panel → Payment Settings. Supported gateways:

You can enable multiple gateways simultaneously and let users choose at checkout.

Google Ads (AdMob & AdX)

Show banner, interstitial, and native ads on mobile, and GPT banner on web.

  1. Create an AdMob account at admob.google.com.
  2. Create an app and ad units (banner, interstitial, native).
  3. In Admin Panel → Advertisement Settings, paste the App IDs and ad unit IDs.
  4. Toggle ads on/off at runtime from the same panel.
Replace the AdMob App ID in the native files (required)

Ad unit IDs come from the Admin Panel, but the AdMob App ID is compiled into each platform. Replace the shipped ID with your own App ID in both files:

Important

If the App ID is missing or malformed the app crashes on launch (Google Mobile Ads SDK requirement). Use your real ID of the form ca-app-pub-XXXXXXXXXXXXXXXX~YYYYYYYYYY.

AI Content Generation (OpenAI)

Sellers can auto-fill ad title, description, price, and category from a product photo using OpenAI Vision.

  1. Get an API key at platform.openai.com.
  2. In Admin Panel → OpenAI Settings, paste the key.
  3. Choose the model (e.g. gpt-4o-mini for cost-effective image analysis).
  4. Toggle the feature on.

SMTP / Email

Transactional emails (welcome, ad approved, password reset) use SMTP via Cloud Functions.

  1. In Admin Panel → SMTP Settings, fill in:
    • SMTP Host (e.g. smtp.gmail.com)
    • SMTP Port (587 for STARTTLS, 465 for SSL)
    • Username (your email)
    • Password (app-specific password if using Gmail)
    • Encryption (SSL or TLS)
  2. Click Send Test Email to verify.
  3. Customize email templates in Admin Panel → Email Templates.

eSellify ships with 14 languages: English, Hindi, Arabic, Spanish, French, Portuguese, Chinese, Russian, Turkish, German, Japanese, Korean, Indonesian, Italian.

Add a New Language

  1. Add the language in Admin PanelLanguagesAdd Language. Set the code (e.g. de), name, and active status.
  2. Create the translation file at customer/lib/languages/app_xx.dart (and the same path in customer_web/). Copy app_en.dart as a template and translate the values.
  3. Register the language in customer/lib/app/services/localization_service.dart:
    import 'package:eSellify/languages/app_xx.dart';
    // ...
    'xx': xxXX,  // add to the keys() map
  4. Add to supported locales:
    const Locale('xx'),  // your new language
  5. Add the display name for the language selector UI.

Use Translated Strings in Code

Use the .tr extension on any string:

Text("Welcome".tr)
Text("Hello, @name".trParams({"name": userName}))

eSellify is serverless: the Customer app, Customer Web, and Admin Panel talk directly to Firebase (Auth, Firestore, Storage, FCM), while function/ contains the Cloud Functions used for transactional email and notification fan-out.

Key Firestore Collections

CollectionPurpose
customersUser profiles, FCM tokens, status.
adsProduct listings — title, price, images, category, seller, status.
category / custom_fieldsCategory tree and the dynamic form fields per category.
subscription_packagesPaid seller plans.
feature_sectionsHome-screen content blocks managed from the Admin Panel.
chat_roomsBuyer–seller chat threads and messages.
favouritesUsers' saved ads.
settings / currencies / languages / email_templateRuntime configuration managed from the Admin Panel.

Code Structure (GetX)

Adding a New Field or Feature

  1. Add the field to the model in lib/app/models/ (with a safe default) in each app that uses it.
  2. Add read/write methods in lib/app/services/ (copy an existing method as a template).
  3. New collection? Register its name in collection_name.dart in each app.
  4. If admins must manage it, add a module under admin_panel/lib/app/modules/.
  5. If a query filters on multiple fields, create the composite index Firestore suggests in its console error link.
Cloud Functions

Email and notification logic lives in function/functions/ (Node.js 22). After editing, redeploy with firebase deploy --only functions.

App won't build — Firebase errors
iOS Pod install fails
cd ios
pod deintegrate
rm -rf Pods Podfile.lock
pod install --repo-update
Android: Google Sign-In fails / Phone OTP not received
iOS: Push notifications not delivered
Web: Images don't upload (CORS error)
Cloud Functions deployment fails
Q: Is a paid Firebase plan required?

Yes — the Blaze (pay-as-you-go) plan is required for Cloud Functions and some auth features. Free tier limits are generous; most small projects pay only a few dollars per month.

Q: Can I run iOS without a Mac?

No. iOS development requires macOS with Xcode. There are paid cloud Mac services (MacStadium, AWS EC2 Mac) if you don't own a Mac.

Q: Do I need an Apple Developer account for testing?

You can run on a personal device with a free Apple ID, but the app expires after 7 days. For TestFlight and App Store, you need the $99/year paid Apple Developer Program.

Q: Which payment gateways are supported?

Stripe, Razorpay, PayPal, Flutterwave, and Paystack. Configure in Admin Panel → Payment Settings.

Q: Can I change the app name, logo, and theme colors without rebuilding?

Yes — most branding is configurable at runtime from Admin Panel → App Settings. Changes sync in real-time to all customer apps. The launcher icon and bundle ID still require a rebuild.

Q: How do I add a new language?

See the Localization section. In short: add the language in Admin Panel, create the app_xx.dart file, and register it in LocalizationService.

Q: How do I contact support?

Want to pull future eSellify releases into your own customised project without losing the changes you've made? The cleanest path is to keep your project under Git and treat each new release as another branch you merge in. The notes below cover what to prepare, what to expect, and where our support scope ends.

Note
  1. Take a complete backup of your project before applying any update — we cannot recover changes lost during a merge.
  2. Apply the same procedure separately for each application folder shipped in the package: customer/, customer_web/, admin_panel/, and function/.
  3. Don't edit your application package name, bundle ID, or version metadata directly during the merge — these are tied to your release builds on Play Store / App Store and changing them will break in-place updates for existing users.
Warning

Manual updates to eSellify require working knowledge of Flutter and Firebase. Always back up your project and validate every change in a staging Firebase environment before deploying to production. We can't be held responsible for issues or data loss caused by manual updates — refer to the official Flutter and Firebase documentation when in doubt.

Note — Support Scope

Per Envato's standard support policy, installation, configuration, customisation, and upgrade work are not included in free item support. Free support covers only bugs or errors in the originally delivered code.

The steps on this page are provided as informational guidelines to help you self-serve when bringing a customised project up to the latest release.

Please don't open support tickets for issues encountered during the upgrade process — these fall outside the scope of free item support.

Upgrade via GitHub Desktop — Step by Step

Use GitHub Desktop to keep your customised project on a private branch and merge each new eSellify release into it without losing your changes. Follow the steps below in order.

Step 1 — Download and install GitHub Desktop

  1. Open https://desktop.github.com/ and download the installer for your OS (Windows or macOS).
  2. Run the installer and complete the standard setup.
  3. Launch GitHub Desktop.
  4. GitHub Desktop installed and launched

Step 2 — Sign in to GitHub

  1. On first launch GitHub Desktop prompts you to sign in. Click Sign in to GitHub.com.
  2. Complete the browser-based sign-in flow and return to GitHub Desktop. Confirm your name and email on the configure-git screen and click Finish.
  3. GitHub Desktop sign-in screen

Step 3 — Open the “Add” menu

  1. Click the Current repository dropdown at the top-left.
  2. In the panel that opens, click the Add dropdown at the top-right.
  3. Current repository dropdown with Add menu open

Step 4 — Create a new repository

  1. From the Add dropdown, choose Create new repository…
  2. Create new repository option

Step 5 — Fill in the repository form

  1. Name: e.g. esellify-customised.
  2. Local path: browse to the folder that contains your existing eSellify project.
  3. Leave the other options at their defaults and click Create repository.
  4. Create a new repository form filled in

Step 6 — Commit your existing project as the baseline

  1. GitHub Desktop lists every file in your project under Changes.
  2. Type a commit summary — for example Initial commit — my customised v1.3 build.
  3. Click Commit to main.
  4. Initial commit on main

Step 7 — Publish the repository to GitHub

  1. Click Publish repository at the top of the window.
  2. Tick Keep this code private.
  3. Click Publish Repository.
  4. Publish repository dialog with private ticked

Step 8 — Create a v1.4.0 branch

  1. Click Current branchNew branch.
  2. Name it v1.4.0 and click Create branch.
  3. Confirm you are now on the v1.4.0 branch (shown in the top bar).
  4. Create branch dialog with v1.4.0

Step 9 — Download the latest eSellify release

  1. Open your CodeCanyon Downloads page.
  2. Download the eSellify v1.4.0 package and extract it to a temporary folder — do not extract it over your existing project.

Step 10 — Replace the code folders on the v1.4.0 branch

  1. Make sure the v1.4.0 branch is still active in GitHub Desktop.
  2. From the extracted v1.4.0 package, copy these folders into your project, replacing the existing ones:
    • customer/lib/
    • customer_web/lib/
    • admin_panel/lib/
    • function/functions/
  3. Leave everything else untouched — branding, Firebase config files, signing keystore, and platform projects.
  4. Replacing lib folders from v1.4.0 package

Step 11 — Commit the v1.4.0 changes

  1. Switch back to GitHub Desktop — the updated files appear under Changes.
  2. Enter the commit summary Upgrade to v1.4.0.
  3. Click Commit to v1.4.0.
  4. Commit v1.4.0 changes

Step 12 — Push the v1.4.0 branch to GitHub

  1. Click Push origin at the top of the window.
  2. Wait for the push to complete.
  3. Push origin to upload v1.4.0 branch

Step 13 — Merge v1.4.0 into main

  1. Switch Current branch back to main.
  2. From the top menu choose BranchMerge into current branch…
  3. Select v1.4.0 and click Create a merge commit.
  4. Merge v1.4.0 into main

Step 14 — Resolve conflicts (if any)

  1. If GitHub Desktop reports conflicts, click Open in your editor.
  2. In each conflicted file, look for the markers <<<<<<<, =======, >>>>>>> and keep the correct lines.
  3. Save each file and return to GitHub Desktop — the conflict count drops as files are resolved.
  4. When the count reaches zero, click Continue merge, then Push origin.
  5. Resolve merge conflicts

Step 15 — Apply the changes to your real project

  1. Open GitHub Desktop's History tab and review each commit from the v1.4.0 merge.
  2. For every change, open the file in your editor side-by-side with your real project.
  3. Copy the changes one by one and paste them into your real project.

Manual Upgrade — Replace the lib Folder

If you'd rather skip Git entirely, you can upgrade by replacing the lib/ folder of each app with the one from the new release. This is faster but loses any customisation you made inside lib/, so review the diff before overwriting.

Important note

While replacing the lib folder manually, do not overwrite firebase_options.dart. Keep your existing Firebase configuration file.

  1. Take a complete backup of your existing project folder (zip the whole thing).
  2. Open your CodeCanyon Downloads page and download the latest eSellify package. Extract it to a temporary folder — do not extract it over your existing project.
  3. In the extracted package, locate the lib/ folder inside each app:
    • customer/lib/
    • customer_web/lib/
    • admin_panel/lib/
  4. In your existing project, delete the corresponding lib/ folder for the app you're upgrading — but first back up your existing lib/firebase_options.dart file (you'll restore it in the next step).
  5. Copy the new lib/ folder from the extracted package into the same location in your project.
  6. Restore your own lib/firebase_options.dart over the one shipped in the new release. This file is generated by flutterfire configure against your Firebase project — if you overwrite it with the sample one from the release, your apps will connect to the wrong Firebase.
  7. Re-apply any other customisations you previously made inside lib/ (branding constants, custom screens, etc.) on top of the new files.
  8. Open pubspec.yaml in each app and compare it with the new release. Add any new dependencies introduced in the latest version.
  9. From each app folder, refresh dependencies:
    flutter clean
    flutter pub get
    On macOS, also run pod install --repo-update inside customer/ios.
  10. Build and run each app to confirm the upgrade works alongside your customisations.
Warning

The manual method overwrites every file inside lib/. Any changes you made there will be lost unless you re-apply them after the copy. If you've heavily customised lib/, prefer the GitHub Desktop method above — it merges your changes with the new release rather than replacing them.

Version 1.4.0 June 25, 2026 Latest
  • Improved overall app performance and stability.
  • Added “See More / See Less” functionality for long ad descriptions.
  • Introduced dynamic watermark support with Admin Panel configuration and real-time sync across Customer App & Web.
  • Added Follow / Unfollow functionality for sellers.
  • Implemented image zoom in / zoom out for full-size image previews.
  • Added option to enable or disable subscription plans from the Admin Panel.
  • Fixed location permission handling and improved the location access flow in Customer Web.
  • Fixed issue preventing users from deleting their own products in Customer Web and added a confirmation dialog.
  • Fixed mobile number validation issues.
  • Fixed Customer Web login issue.
  • Resolved minor bugs and improved overall user experience.
Version 1.3 May 23, 2026
  • Send Test Email — added functionality for SMTP/email configuration testing.
  • Ad Details screen — created a dedicated Ad Details screen in the Admin Panel.
  • Job Category flow — implemented the complete Job Category flow, including job applications visibility in the customer app.
  • Job Applications in Admin — added functionality to view users' job applications in the Admin Panel.
  • Dependency upgrades — upgraded project dependencies/packages to the latest compatible versions.
  • Bug fixes & stability — fixed minor bugs and improved overall app performance and stability.
Version 1.2 May 12, 2026
  • Google AdMob & AdX integration — banner, interstitial and native ads on mobile, GPT banner on web, configured from a new admin panel.
  • Safety Tips feature — admin-managed buyer-safety reminders shown in a bottom sheet before contacting a seller.
  • AI-generated ad content — OpenAI Vision auto-fills title, description, price, category and custom fields from uploaded product photos.
Version 1.1 April 18, 2026
  • Completed full conversion of the mobile application into a high-performance web version.
  • Introduced web-based paginated ad listings with precise distance-based filtering.
  • Upgraded to Flutter 3.41.6 for improved compatibility.
  • Updated all project dependencies to their latest stable versions.
  • Refined the web platform with critical bug fixes and enhanced navigation performance.
  • Optimized the web experience with proximity-sorted ads and smooth paginated browsing.
Version 1.0 April 11, 2026
  • Initial Release.