Jumpstart docs logo Back to the app

Using Jumpstart Pro iOS & Android with Existing Apps

If you're not using Jumpstart Pro Rails, here are the steps needed to update your web application to work with Jumpstart Pro iOS & Android.

API Endpoints

Your Rails API will be used for authentication and other features.

The host and URL base path are configurable in the iOS / Android app Endpoint configuration. By default, the host is http://localhost:3000 and base API uri is /api/v1. You can change this configuration to match your application's API.

When making requests to the API, you'll want to follow these rules:

  • Include Android (Turbo Native) or iOS (Turbo Native) in the User Agent for all API requests. This tells the API the request came from Turbo Native and should be handled accordingly.
  • Use the Authorization header to authenticate user with an API token

Mobile Views

Some views will need a custom version for Turbo Native. You can use Request Variants to accomplish this.

Hotwire includes a turbo_native_app? helper that checks the User-Agent header for Turbo Native. You can set the request variant for Turbo Native requests using that.

before_action do
  request.variant = :phone if turbo_native_app?
end

The iOS / Android app uses a native header so it feels native. We add a hamburger button to this which triggers a Javascript event using the Turbo Bridge.

In Rails, you'll want to hide your navbar on Turbo Native requests. Use a request variant template for this so you can minimize the HTML used for mobile.

The menu should be hidden, but toggles when the toggle-nav-bar event fires. You can create a simple Stimulus Controller to listen to that event and toggle the navbar visibility.

Turbo Bridge

The Turbo Bridge is how your iOS / Android app and Javascript talk to each other. Add this to your Javascript. We're using Webpacker, but you can probably use this in the asset pipeline as well, it just might take a few small tweaks.

class Bridge {
  // Toggles navbar visibility in browser from Turbo Native
  static toggleNavBar() {
    const event = new CustomEvent("toggle-nav-bar")
    window.dispatchEvent(event)
  }

  // Sends a message to the native app, if active.
  static postMessage(name, data = {}) {
    // iOS
    window.webkit?.messageHandlers?.nativeApp?.postMessage({name, ...data})

    // Android
    window.nativeApp?.postMessage(JSON.stringify({name, ...data}))
  }
}

// Expose this on the window object so TurboNative can interact with it
window.TurboNativeBridge = Bridge
export default Bridge

Authentication

Authentication requires an API endpoint that accepts email and password params.

It should:

  • Respond to POST /api/v1/auth
  • Validate the email and password
  • Sign the user in (with cookies)
  • Find or create an API token for the user
  • Return a 200 OK JSON response with:
    • token - the API token for the iOS / Android device to make API requests

Successful authentication will refresh the currently visible page.

Sign out

Sign out must happen on the iOS / Android app side. That way we can delete the API token, make an API request to remove the NotificationToken, and clear cookies in the WebView.

To intercept the Sign out link in the HTML, use the following Javascript:

import { Controller } from "stimulus"

export default class extends Controller {
  signOut(event) {
    if (this._isTurboNativeApp) {
      event.preventDefault()
      event.stopImmediatePropagation()
      window.TurboNativeBridge.postMessage("signOut")
    }
  }

  get _isTurboNativeApp() {
    return navigator.userAgent.indexOf("Turbo Native") !== -1
  }
}

The API endpoint for Sign out needs to do two things:

  • Respond to DELETE /api/v1/auth
  • Delete the NotificationToken
  • Sign out the current user (removing cookies)
  • Returns a 200 OK response

Update Password

Changing your password is a simple API request

PATCH /api/v1/password

Headers:

  • Authorization - The user's API token

Params:

  • user[current_password] - The user's current password
  • user[password] - The new password
  • user[password_confirmation] - The new password

Returns:

Success - 200 OK

{ success: true }

Failure - 422 Unprocessable Entity

{ error: "Password confirmation did not match" }

Push Notifications

Registering for Push Notifications happens when the user is signed in.

The Backend needs NotificationToken model to store the token and platform for push notifications.

rails g model NotificationToken user:belongs_to platform token

An API endpoint for notification tokens should:

  • Respond to POST /api/v1/notification_tokens
  • Use Authorization header to authenticate user with API token
  • Accept params:
    • token - device notification token
    • platform - platform of device (iOS, Android)
  • Find or create NotificationToken record for user with params
  • Return 200 OK if successful