Mobile App

One Flutter app for job seekers and employers: set up, brand and publish

Version: 2.0.0 (website and app)
Stack: Laravel 13 · PHP 8.3+ · MySQL 8 / MariaDB 10.6+ · Flutter 3.44
License: Envato Market (Regular / Extended)
Author: BugBuild Lab · [email protected]

About the App

AppSourceCode/ is one Flutter project that builds one app for Android and iOS. It serves both job seekers and employers: after login the app reads the account type and opens the matching experience. Sign-up offers both a job seeker form and a company form.

Job seekerOnboarding, sign up and login, home feed, search and filters, job details, apply with CV, saved jobs, companies, profile and resume, KYC, notifications, freelance (find work, proposals, contracts, wallet).
EmployerDashboard, post and edit jobs with a rich-text editor, applicants, company profile and map location, subscription checkout, notifications, freelance (post projects, hire, pay).

The app talks to your JobNect website through its API (/api/v10). Everything users see (jobs, settings, logos, onboarding slides, texts and languages) comes from your website, so most changes are made in the admin panel, not in the app code.

Install and configure the website first (Quick Start). The app needs a working site on HTTPS.

Requirements

ToolVersion
Flutter3.44 (stable channel)
DartSDK ^3.12 (comes with Flutter 3.44)
AndroidAndroid Studio with the Android SDK, and JDK 17 or newer (the JDK bundled with Android Studio works). The project uses Gradle 8.12, Android Gradle Plugin 8.9.1 and Kotlin 2.1.0; minimum SDK follows the Flutter default.
iOSA Mac with Xcode and CocoaPods. Deployment target iOS 14.0.
AccountsGoogle Play Console and/or Apple Developer Program to publish

Check your setup with:

flutter --version
flutter doctor

Open and Run

  1. Open the AppSourceCode folder in Android Studio (or VS Code with the Flutter extension).
  2. Get the packages:
    flutter pub get
  3. Start an emulator or connect a phone, then run:
    flutter run

Out of the box the app points at the live demo site, so it runs immediately. Before you build your own version, point it at your site (next section).

Connect the App to Your Site

There is one setting to change: lib/shared/config/app_config.dart.

/// The one setting to change before building: your JobNect website address,
/// without a trailing slash. Applicant and employer screens both use it.
class AppConfig {
  static const String apiHost = 'https://your-domain.com';
}
  • Use your full website address with https:// and no trailing slash.
  • Both the job seeker and the employer parts of the app read this value (through lib/applicant/services/urls.dart and lib/employer/services/urls.dart, which add /api/v10).
  • After changing it, stop the app and run it again (a hot reload does not pick up a changed constant reliably).

Login in the app uses JWT tokens signed with JWT_SECRET from the website’s .env. The web installer creates it. If you change it later, everyone is logged out of the app.

One App, Two Roles

  • Logged-out users see onboarding, login and sign-up. Sign-up has a job seeker form and a company form.
  • At login the website returns the account type. A job seeker lands in the job seeker home; a company lands in the employer dashboard, with its own theme and bottom navigation.
  • The session is remembered: the next launch opens the right experience directly. Logging out returns to the shared login screen.
  • Right-to-left languages (for example Hebrew) switch the whole app layout to RTL.

App Name, Package ID and Bundle ID

App name
PlatformFileValue
Androidandroid/app/src/main/AndroidManifest.xmlandroid:label="JobNect"
iOSios/Runner/Info.plistCFBundleDisplayName (and CFBundleName)
Flutterlib/main.darttitle: 'JobNect'
Android package ID

The app ships with com.bugbuild.jobnect.jobseeker. Use your own before publishing (for example com.yourcompany.jobs); it cannot be changed after the first upload to Google Play.

  1. In android/app/build.gradle.kts change both namespace and applicationId.
  2. Move MainActivity.kt from android/app/src/main/kotlin/com/bugbuild/jobnect/jobseeker/ to a folder that matches the new ID, and change the package line at its top to the same value.
  3. Run flutter clean and build again.
iOS bundle ID

Open ios/Runner.xcworkspace in Xcode, select the Runner target, Signing & Capabilities, and set your Bundle Identifier (it ships as com.bugbuild.jobnect.jobseeker) and your Team.

Map tiles

The employer location map uses OpenStreetMap tiles and identifies the app to the tile server. Replace com.jobnect.employer and jobnect-employer-app with your own package name in lib/employer/widgets/location_map_view.dart and lib/employer/widgets/location_map_picker.dart.

Icons, Splash and Colours

Launcher icon

Android icons are in android/app/src/main/res/mipmap-*/ic_launcher.png; iOS icons in ios/Runner/Assets.xcassets/AppIcon.appiconset. Replace them by hand, or generate all sizes from one 1024 × 1024 PNG with the flutter_launcher_icons package:

# pubspec.yaml
dev_dependencies:
  flutter_launcher_icons: ^0.14.0

flutter_launcher_icons:
  android: true
  ios: true
  image_path: "assets/images/app-icon.png"
  remove_alpha_ios: true
flutter pub get
dart run flutter_launcher_icons
Splash screen
  • The short native launch screen is android/app/src/main/res/drawable-v21/launch_background.xml on Android and ios/Runner/Base.lproj/LaunchScreen.storyboard on iOS.
  • The app’s own splash then shows the App logo, on colour from your website (admin Settings → General Settings, Branding). Change the logo there; no rebuild is needed.
  • The onboarding slides come from App Slider in the admin panel.
Colours and fonts

The main colour is colorPrimary in lib/applicant/utils/app_colors.dart and lib/employer/utils/app_colors.dart. The font (Kumbh Sans) is in assets/fonts/ and declared in pubspec.yaml.

Android Signing

No keystore is included: you create your own. Keep the keystore and its passwords safe; you need the same key for every update on Google Play.

  1. Create a keystore (from the AppSourceCode folder):
    keytool -genkey -v -keystore android/app/upload-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias upload
  2. Create android/key.properties:
    storePassword=your-store-password
    keyPassword=your-key-password
    keyAlias=upload
    storeFile=upload-keystore.jks
    storeFile is relative to android/app/; an absolute path also works.

android/app/build.gradle.kts already reads key.properties. When the file is missing, release builds fall back to the debug key: fine for testing, but Google Play rejects them.

Do not commit key.properties or the .jks file to a public repository.

Build for Android

Set the version in pubspec.yaml first. It ships as version: 2.0.0+3 (name + build number); raise the build number for every upload.

flutter clean
flutter pub get
flutter build apk --release        # build/app/outputs/flutter-apk/app-release.apk
flutter build appbundle --release  # build/app/outputs/bundle/release/app-release.aab

Upload the .aab to Google Play Console. Use the .apk to install directly on phones for testing.

Build for iOS

  1. Install the pods:
    flutter pub get
    cd ios
    pod install
    cd ..
  2. Open ios/Runner.xcworkspace (not the .xcodeproj) in Xcode. In Runner → Signing & Capabilities choose your team and bundle identifier.
  3. Build the archive, either in Xcode with Product → Archive and then Distribute App, or from the terminal:
    flutter build ipa --release
    and upload build/ios/ipa/*.ipa with Transporter or Xcode.

The app asks for camera and photo library access (profile photos, documents). The texts shown to the user are NSCameraUsageDescription and NSPhotoLibraryUsageDescription in ios/Runner/Info.plist; adjust them to describe your use before submitting to the App Store.

App Themes

The app has three looks. You choose one in the admin panel under Website Setup → Themes → Mobile app theme; there is nothing to change in the app code.

ThemeStyle
ClassicThe original teal look: soft cards, rounded buttons, a calm white background.
MomentumMost trending: warm paper background, bold headings, a dark hero card with lime highlights, pill buttons and a floating pill navigation bar.
MeridianProfessional: navy and cobalt, crisp 12 px corners, clean bordered cards and a flat navigation bar.
  • Follow the website theme (the default) gives Momentum and Meridian sites the matching app look; the other website themes use Classic.
  • Every screen follows the chosen colours, fonts, corners, buttons and inputs. Onboarding, sign-in, both home screens, job cards, job details and profile also get their own layout per theme.
  • The app reads the theme from GET /api/v10/settings (app_theme) each time it opens. It starts with the last theme it saw, so there is no flash, and switches as soon as a new one arrives.

To change a theme's colours, edit its palette in lib/shared/theme/app_skin.dart (AppSkin.classic, AppSkin.momentum, AppSkin.meridian).

Troubleshooting

ProblemFix
App shows no data or "connection" errorsCheck AppConfig.apiHost: full https address, no trailing slash. Open https://your-domain.com in the phone browser to confirm the site works there.
Login fails on the app but works on the websiteJWT_SECRET must be set in the website .env; run php artisan optimize:clear after setting it.
Images do not load in the appSet APP_URL in the website .env to the https address and make public/uploads/ readable.
After payment the app does not reopenKeep the jobnect scheme in AndroidManifest.xml and Info.plist (see Payment Return Link). Reinstall the app after changing either file.
Gradle or Kotlin version errorsUse Flutter 3.44 and JDK 17+, then run flutter clean and flutter pub get.
iOS: "Module not found" or pod errorsRun cd ios && pod install --repo-update and open Runner.xcworkspace.
Release APK rejected by Google PlayIt was signed with the debug key: create android/key.properties and the keystore (Android Signing).
Old texts or logo after changing them on the websiteThe app caches settings and texts. Clear the app’s storage or reinstall it.