Jonathan Bennett

Building Adaptive Layouts with Hotwire Native

I’m building a Hotwire Native app with two distinct layouts:

  1. A single navigation controller for guests.
  2. A tab bar for signed-in users.

The key challenge is determining on the client side whether a user is signed in. Thanks to Hotwire Native’s shared process pool, which shares cookies across windows and network requests, we can achieve this by querying the server and adapting the layout dynamically.


Step 1: Server-Side Endpoint

We’ll create an endpoint to check the user’s session status:

# config/routes.rb
Rails.application.routes.draw do
  # …
  resource :session_test, only: :show
end

# app/controllers/session_tests_controller.rb
class SessionTestsController < ApplicationController
  allow_unauthenticated_access

  def show
	if authenticated? # or current_user etc
	  head :ok
	else
	  head :unauthorized
	end
  end
end

The endpoint responds with 401 Unauthorized for guests and 200 OK for signed-in users.


Step 2: Client-Side Implementation

In your native code, query the endpoint and dynamically adjust the view stack:

// SceneDelegate.swift
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
  func scene(_ scene: UIScene, willConnectTo session: UISceneSession, 
			 options connectionOptions: UIScene.ConnectionOptions) {
	window?.rootViewController = loadingScreenStack() // Initial loading screen
	checkSession()
  }

  func checkSession() {
	let session = URLSession.shared
	let request = URLRequest(url: URL(string: "https://website.com/session_test")!)
	let task = session.dataTask(with: request) { data, response, error in
	  guard let response else { return }
	  let httpResponse = response as! HTTPURLResponse
	  let signedIn = httpResponse.statusCode == 200

	  DispatchQueue.main.async {
		if signedIn {
		  window?.rootViewController = signedInStack()
		} else {
		  window?.rootViewController = guestStack()
		}
	  }
	}
	task.resume()
  }
}

How It Works

  1. Initial Screen: The app shows a loading screen while determining the user’s session status.
  2. Server Query: The client makes a request to the /session_test endpoint.
  3. Response Handling:
    • If the response status is 200, the app presents the signed-in user’s stack.
    • If it’s 401, the app displays the guest stack.

This approach ensures a seamless experience by dynamically tailoring the app layout based on user authentication status.