diff --git a/app/controllers/api/v1/meetings_controller.rb b/app/controllers/api/v1/meetings_controller.rb
index ef823e0705ac12c8875c64b795d0fa189155b4bb..3b5126fac55eb43fd4c5691d6a348abe84bb66d9 100644
--- a/app/controllers/api/v1/meetings_controller.rb
+++ b/app/controllers/api/v1/meetings_controller.rb
@@ -29,7 +29,7 @@ module Api
       # Starts a BigBlueButton meetings and joins in the meeting starter
       def start
         begin
-          MeetingStarter.new(room: @room, base_url: root_url, current_user:, provider: current_provider).call
+          MeetingStarter.new(room: @room, base_url: request.base_url, current_user:, provider: current_provider).call
         rescue BigBlueButton::BigBlueButtonException => e
           return render_error status: :bad_request unless e.key == 'idNotUnique'
         end
@@ -68,7 +68,7 @@ module Api
 
         if !data[:status] && settings['glAnyoneCanStart'] == 'true' # Meeting isnt running and anyoneCanStart setting is enabled
           begin
-            MeetingStarter.new(room: @room, base_url: root_url, current_user:, provider: current_provider).call
+            MeetingStarter.new(room: @room, base_url: request.base_url, current_user:, provider: current_provider).call
           rescue BigBlueButton::BigBlueButtonException => e
             return render_error status: :bad_request unless e.key == 'idNotUnique'
           end
diff --git a/app/controllers/api/v1/site_settings_controller.rb b/app/controllers/api/v1/site_settings_controller.rb
index 8bf06d0d5f88d99a6547797747b802b4ac67ba75..ecbd9472841b6c11d76908b10507a92b1738448b 100644
--- a/app/controllers/api/v1/site_settings_controller.rb
+++ b/app/controllers/api/v1/site_settings_controller.rb
@@ -25,17 +25,9 @@ module Api
       # GET /api/v1/site_settings
       # Returns the values of 1 or multiple site_settings that are not forbidden to access
       def index
-        settings = {}
         return render_error status: :forbidden if forbidden_settings(params[:names])
 
-        if params[:names].is_a?(Array)
-          params[:names].each do |name|
-            settings[name] = SettingGetter.new(setting_name: name, provider: current_provider).call
-          end
-        else
-          # return the value directly
-          settings = SettingGetter.new(setting_name: params[:names], provider: current_provider).call
-        end
+        settings = SettingGetter.new(setting_name: params[:names], provider: current_provider).call
 
         render_data data: settings, status: :ok
       end
diff --git a/app/javascript/channels/consumer.jsx b/app/javascript/channels/consumer.jsx
index 99123c203e60384c772ba2ff53c692c47d2c6129..e1d523c541e515489274ffb3ded92673eacd645e 100644
--- a/app/javascript/channels/consumer.jsx
+++ b/app/javascript/channels/consumer.jsx
@@ -19,4 +19,4 @@
 
 import { createConsumer } from '@rails/actioncable';
 
-export default createConsumer();
+export default createConsumer(`${process.env.RELATIVE_URL_ROOT}/cable`);
diff --git a/app/javascript/hooks/queries/users/useUser.jsx b/app/javascript/hooks/queries/users/useUser.jsx
index 64f22960a1a74d411ffc12f1d2cd2c332f0b4c8c..54c460bb6ec045bc3e940aef348518c726edee4c 100644
--- a/app/javascript/hooks/queries/users/useUser.jsx
+++ b/app/javascript/hooks/queries/users/useUser.jsx
@@ -15,11 +15,11 @@
 // with Greenlight; if not, see <http://www.gnu.org/licenses/>.
 
 import { useQuery } from 'react-query';
-import axios from 'axios';
+import axios from '../../../helpers/Axios';
 
 export default function useUser(userId) {
   return useQuery(
     ['getUser', userId],
-    () => axios.get(`/api/v1/users/${userId}.json`).then((resp) => resp.data.data),
+    () => axios.get(`/users/${userId}.json`).then((resp) => resp.data.data),
   );
 }
diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb
index 2df77808caf637c086904fcfe6aaed0ded5c98e8..3e00b6fc0288fe6ea5a4d617adc4235c478006c4 100644
--- a/app/mailers/user_mailer.rb
+++ b/app/mailers/user_mailer.rb
@@ -55,8 +55,7 @@ class UserMailer < ApplicationMailer
   end
 
   def branding
-    branding_hash = SiteSetting.includes(:setting).where(provider: @provider, settings: { name: %w[PrimaryColor BrandingImage] })
-                               .pluck(:name, :value).to_h
+    branding_hash = SettingGetter.new(setting_name: %w[PrimaryColor BrandingImage], provider: @provider).call
     @brand_image = ActionController::Base.helpers.image_url(branding_hash['BrandingImage'], host: @base_url)
     @brand_color = branding_hash['PrimaryColor']
   end
diff --git a/app/services/meeting_starter.rb b/app/services/meeting_starter.rb
index e576082c42815a9fb71cb425a65b736da194fa6b..4575aef490104541fb1ba2d999907a2182748224 100644
--- a/app/services/meeting_starter.rb
+++ b/app/services/meeting_starter.rb
@@ -56,7 +56,7 @@ class MeetingStarter
   private
 
   def computed_options(access_code:)
-    room_url = File.join(@base_url, '/rooms/', @room.friendly_id, '/join')
+    room_url = "#{root_url(host: @base_url)}rooms/#{@room.friendly_id}/join"
     moderator_message = "#{I18n.t('meeting.moderator_message')}<br>#{room_url}"
     moderator_message += "<br>#{I18n.t('meeting.access_code', code: access_code)}" if access_code.present?
     {
diff --git a/app/services/setting_getter.rb b/app/services/setting_getter.rb
index 4c5f435279c069c0cbac6661268756efd4d2c389..fda7f838d17ed18aad8186b2d9e6192cb9b069af 100644
--- a/app/services/setting_getter.rb
+++ b/app/services/setting_getter.rb
@@ -20,40 +20,51 @@ class SettingGetter
   include Rails.application.routes.url_helpers
 
   def initialize(setting_name:, provider:)
-    @setting_name = setting_name
+    @setting_name = Array(setting_name)
     @provider = provider
   end
 
   def call
-    setting = SiteSetting.joins(:setting)
-                         .find_by(
-                           provider: @provider,
-                           setting: { name: @setting_name }
-                         )
-
-    value = if @setting_name == 'BrandingImage'
-              if setting.image.attached?
-                rails_blob_path setting.image, only_path: true
-              else
-                ActionController::Base.helpers.image_path('bbb_logo.png')
-              end
-            else
-              setting&.value
-            end
-
-    transform_value(value)
+    # Fetch the site settings records while eager loading their respective settings ↓
+    site_settings = SiteSetting.includes(:setting)
+                               .where(
+                                 provider: @provider,
+                                 setting: { name: @setting_name }
+                               )
+
+    # Pessimist check: Pass only if all provided names were found ↓
+    return nil unless @setting_name.size == site_settings.size
+
+    site_settings_hash = {}
+
+    # In memory prepare the result hash ↓
+    site_settings.map do |site_setting|
+      site_settings_hash[site_setting.setting.name] = transform_value(site_setting)
+    end
+
+    # If there's only one setting is being fetched no need for a hash ↓
+    return site_settings_hash.values.first if site_settings_hash.size == 1
+
+    # A Hash<setting_name => parsed_value> is returned otherwise ↓
+    site_settings_hash
   end
 
   private
 
-  def transform_value(value)
-    case value
+  def transform_value(site_setting)
+    if site_setting.setting.name == 'BrandingImage'
+      return rails_blob_path site_setting.image, only_path: true if site_setting.image.attached?
+
+      return ActionController::Base.helpers.image_path('bbb_logo.png')
+    end
+
+    case site_setting.value
     when 'true'
       true
     when 'false'
       false
     else
-      value
+      site_setting.value
     end
   end
 end
diff --git a/config/application.rb b/config/application.rb
index 3c50cf78dd0e35bf58af3f2cf6287965d153861d..71810992cd800f9f8f6fa70ccf98ed2b407594fb 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -66,6 +66,8 @@ module Greenlight
 
     config.bigbluebutton_secret = ENV.fetch('BIGBLUEBUTTON_SECRET', '8cd8ef52e8e101574e400365b55e11a6')
 
-    config.relative_url_root = ENV.fetch('RELATIVE_URL_ROOT', '/')
+    # Fetch 'RELATIVE_URL_ROOT' ENV variable value while removing any trailing slashes.
+    config.relative_url_root = ENV.fetch('RELATIVE_URL_ROOT', nil)&.sub(%r{/*\z}, '')
+    config.relative_url_root = '/' if config.relative_url_root.blank?
   end
 end
diff --git a/esbuild.dev.mjs b/esbuild.dev.mjs
index fb48838beefd311402906e954b0f88d8fc68e767..83a11e9c472b876c4856a566910efa56fee0ad75 100644
--- a/esbuild.dev.mjs
+++ b/esbuild.dev.mjs
@@ -1,6 +1,7 @@
 import * as esbuild from 'esbuild';
 
-const relativeUrlRoot = (process.env.RELATIVE_URL_ROOT || '').replace(/\/$/, '');
+// Fetch 'RELATIVE_URL_ROOT' ENV variable value while removing any trailing slashes.
+const relativeUrlRoot = (process.env.RELATIVE_URL_ROOT || '').replace(/\/*$/, '');
 
 await esbuild.build({
   entryPoints: ['app/javascript/main.jsx'],
diff --git a/esbuild.mjs b/esbuild.mjs
index 7b76ffbfb799e8e9fa693ba2b66eb7392dd5a5cb..8a6589592045c2b7c5d8eb351b7d93bc2e83f5ba 100644
--- a/esbuild.mjs
+++ b/esbuild.mjs
@@ -1,6 +1,7 @@
 import * as esbuild from 'esbuild';
 
-const relativeUrlRoot = (process.env.RELATIVE_URL_ROOT || '').replace(/\/$/, '');
+// Fetch 'RELATIVE_URL_ROOT' ENV variable value while removing any trailing slashes.
+const relativeUrlRoot = (process.env.RELATIVE_URL_ROOT || '').replace(/\/*$/, '');
 
 await esbuild.build({
   entryPoints: ['app/javascript/main.jsx'],
diff --git a/spec/controllers/meetings_controller_spec.rb b/spec/controllers/meetings_controller_spec.rb
index 66827d384e74abbe173e07f5e55f44e29fa55958..21230bb1246bb58557c403d9154524308e7c69a6 100644
--- a/spec/controllers/meetings_controller_spec.rb
+++ b/spec/controllers/meetings_controller_spec.rb
@@ -41,7 +41,7 @@ RSpec.describe Api::V1::MeetingsController, type: :controller do
 
   describe '#start' do
     it 'makes a call to the MeetingStarter service with the right values and returns the join url' do
-      expect(MeetingStarter).to receive(:new).with(room:, base_url: root_url, current_user: user, provider: 'greenlight').and_call_original
+      expect(MeetingStarter).to receive(:new).with(room:, base_url: request.base_url, current_user: user, provider: 'greenlight').and_call_original
       expect_any_instance_of(MeetingStarter).to receive(:call)
       expect_any_instance_of(BigBlueButtonApi).to receive(:join_meeting).with(room:, name: user.name, avatar_url: nil, role: 'Moderator')
 
@@ -343,7 +343,7 @@ RSpec.describe Api::V1::MeetingsController, type: :controller do
 
         allow_any_instance_of(BigBlueButtonApi).to receive(:meeting_running?).and_return(false)
 
-        expect(MeetingStarter).to receive(:new).with(room:, base_url: root_url, current_user: user, provider: 'greenlight').and_call_original
+        expect(MeetingStarter).to receive(:new).with(room:, base_url: request.base_url, current_user: user, provider: 'greenlight').and_call_original
         expect_any_instance_of(MeetingStarter).to receive(:call)
 
         post :status, params: { friendly_id: room.friendly_id, name: user.name }
diff --git a/spec/controllers/site_settings_controller_spec.rb b/spec/controllers/site_settings_controller_spec.rb
index f049573d126deac4fc50d27bd83712fd88a22de5..8b2faf14692df01d95c14be9013269ba16de9a10 100644
--- a/spec/controllers/site_settings_controller_spec.rb
+++ b/spec/controllers/site_settings_controller_spec.rb
@@ -38,15 +38,13 @@ RSpec.describe Api::V1::SiteSettingsController, type: :controller do
     end
 
     it 'calls SettingGetter and returns multiple values' do
-      expect(SettingGetter).to receive(:new).with(setting_name: 'SettingName', provider: 'greenlight').and_call_original
-      expect(SettingGetter).to receive(:new).with(setting_name: 'SettingName2', provider: 'greenlight').and_call_original
-      allow_any_instance_of(SettingGetter).to receive(:call).and_return('false')
+      expect(SettingGetter).to receive(:new).with(setting_name: %w[Uno Dos Tres], provider: 'greenlight').and_call_original
+      allow_any_instance_of(SettingGetter).to receive(:call).and_return({ 'Uno' => 1, 'Dos' => 2, 'Tres' => 3 })
 
-      get :index, params: { names: %w[SettingName SettingName2] }
+      get :index, params: { names: %w[Uno Dos Tres] }
 
       expect(response).to have_http_status(:ok)
-      expect(JSON.parse(response.body)['data']['SettingName']).to eq('false')
-      expect(JSON.parse(response.body)['data']['SettingName2']).to eq('false')
+      expect(JSON.parse(response.body)['data']).to eq({ 'Uno' => 1, 'Dos' => 2, 'Tres' => 3 })
     end
 
     it 'returns forbidden if trying to access a forbidden setting' do