diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 34347be2..ca2a7f36 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -31,6 +31,7 @@ jobs:
             msvc_version: 2022
             qt_version: 6.5.0
             qt_arch: win64_msvc2019_64
+            qt_modules: qtimageformats
             qt_tools: ''
             conan_arch: x86_64
             conan_compiler: Visual Studio
@@ -46,6 +47,7 @@ jobs:
             compiler: gcc
             qt_version: 6.5.0
             qt_arch: gcc_64
+            qt_modules: qtimageformats
             qt_tools: ''
             conan_arch: x86_64
             conan_compiler: gcc
@@ -74,6 +76,7 @@ jobs:
       with:
         version: ${{ matrix.qt_version }}
         arch: ${{ matrix.qt_arch }}
+        modules: ${{ matrix.qt_modules }}
         tools: ${{ matrix.qt_tools }}
 
     - name: Setup MSVC
diff --git a/.gitmodules b/.gitmodules
index 472835da..7828c19a 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,6 +1,6 @@
 [submodule "external/mapbox-gl-native"]
 	path = external/mapbox-gl-native
-	url = https://github.com/maplibre/maplibre-gl-native.git
+	url = https://github.com/dpaulat/maplibre-gl-native.git
 [submodule "external/cmake-conan"]
 	path = external/cmake-conan
 	url = https://github.com/conan-io/cmake-conan.git
diff --git a/ACKNOWLEDGEMENTS.md b/ACKNOWLEDGEMENTS.md
index 30ec5f63..889246f4 100644
--- a/ACKNOWLEDGEMENTS.md
+++ b/ACKNOWLEDGEMENTS.md
@@ -15,7 +15,7 @@ Supercell Wx uses code from the following dependencies:
 | [bzip2](https://sourceware.org/bzip2/) | [bzip2 and libbzip2 License v1.0.6](https://spdx.org/licenses/bzip2-1.0.6.html) |
 | [cmake-conan](https://github.com/conan-io/cmake-conan) | [MIT License](https://spdx.org/licenses/MIT.html) |
 | [cpr](https://github.com/libcpr/cpr) | [MIT License](https://spdx.org/licenses/MIT.html) |
-| [CSS Color Parser](https://github.com/deanm/css-color-parser-js) | [MIT License](https://spdx.org/licenses/MIT.html) | Ported to C++ for MapLibre GL Native |
+| [CSS Color Parser](https://github.com/deanm/css-color-parser-js) | [MIT License](https://spdx.org/licenses/MIT.html) | Ported to C++ for MapLibre Native |
 | [Date](https://github.com/HowardHinnant/date) | [MIT License](https://spdx.org/licenses/MIT.html) |
 | [Dear ImGui](https://github.com/ocornut/imgui) | [MIT License](https://spdx.org/licenses/MIT.html) |
 | [FreeType](https://freetype.org/) | [Freetype Project License](https://spdx.org/licenses/FTL.html) |
@@ -29,8 +29,8 @@ Supercell Wx uses code from the following dependencies:
 | [libiconv](https://www.gnu.org/software/libiconv/) | [GNU Lesser General Public License v2.1 or later](https://spdx.org/licenses/LGPL-2.1-or-later.html) |
 | [libpng](http://libpng.org/pub/png/libpng.html) | [PNG Reference Library version 2](https://spdx.org/licenses/libpng-2.0.html) |
 | [libxml2](http://xmlsoft.org/) | [MIT License](https://spdx.org/licenses/MIT.html) |
-| [MapLibre GL Native](https://maplibre.org/projects/maplibre-native/) | [BSD 2-Clause "Simplified" License](https://spdx.org/licenses/BSD-2-Clause.html) |
-| [nunicode](https://bitbucket.org/alekseyt/nunicode/src/master/) | [MIT License](https://spdx.org/licenses/MIT.html) | Modified for MapLibre GL Native |
+| [MapLibre Native](https://maplibre.org/projects/maplibre-native/) | [BSD 2-Clause "Simplified" License](https://spdx.org/licenses/BSD-2-Clause.html) |
+| [nunicode](https://bitbucket.org/alekseyt/nunicode/src/master/) | [MIT License](https://spdx.org/licenses/MIT.html) | Modified for MapLibre Native |
 | [OpenSSL](https://www.openssl.org/) | [OpenSSL License](https://spdx.org/licenses/OpenSSL.html) |
 | [Qt](https://www.qt.io/) | [GNU Lesser General Public License v3.0 only](https://spdx.org/licenses/LGPL-3.0-only.html) | Qt Core, Qt GUI, Qt Network, Qt OpenGL, Qt SQL, Qt SVG, Qt Widgets
Additional Licenses: https://doc.qt.io/qt-6/licenses-used-in-qt.html |
 | [spdlog](https://github.com/gabime/spdlog) | [MIT License](https://spdx.org/licenses/MIT.html) |
diff --git a/external/mapbox-gl-native b/external/mapbox-gl-native
index e12c4d6b..fbb06ff5 160000
--- a/external/mapbox-gl-native
+++ b/external/mapbox-gl-native
@@ -1 +1 @@
-Subproject commit e12c4d6be450a163b38548f72e72f4080fc71dbb
+Subproject commit fbb06ff53e74d3a81b434b84fff1a5dfe4b2d3c7
diff --git a/external/mapbox-gl-native.cmake b/external/mapbox-gl-native.cmake
index 910a6849..c48900c1 100644
--- a/external/mapbox-gl-native.cmake
+++ b/external/mapbox-gl-native.cmake
@@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 3.20)
 set(PROJECT_NAME scwx-mbgl)
 
 set(gtest_disable_pthreads ON)
-set(MBGL_WITH_QT ON)
-set(MBGL_QT_WITH_INTERNAL_ICU ON)
+set(MLN_WITH_QT ON)
+set(MLN_QT_WITH_INTERNAL_ICU ON)
 add_subdirectory(mapbox-gl-native)
 
 find_package(ZLIB)
diff --git a/scwx-qt/scwx-qt.cmake b/scwx-qt/scwx-qt.cmake
index 15d09a62..32d900ce 100644
--- a/scwx-qt/scwx-qt.cmake
+++ b/scwx-qt/scwx-qt.cmake
@@ -78,6 +78,7 @@ set(HDR_MAP source/scwx/qt/map/alert_layer.hpp
             source/scwx/qt/map/generic_layer.hpp
             source/scwx/qt/map/layer_wrapper.hpp
             source/scwx/qt/map/map_context.hpp
+            source/scwx/qt/map/map_provider.hpp
             source/scwx/qt/map/map_settings.hpp
             source/scwx/qt/map/map_widget.hpp
             source/scwx/qt/map/overlay_layer.hpp
@@ -89,6 +90,7 @@ set(SRC_MAP source/scwx/qt/map/alert_layer.cpp
             source/scwx/qt/map/generic_layer.cpp
             source/scwx/qt/map/layer_wrapper.cpp
             source/scwx/qt/map/map_context.cpp
+            source/scwx/qt/map/map_provider.cpp
             source/scwx/qt/map/map_widget.cpp
             source/scwx/qt/map/overlay_layer.cpp
             source/scwx/qt/map/radar_product_layer.cpp
diff --git a/scwx-qt/source/scwx/qt/gl/draw/draw_item.cpp b/scwx-qt/source/scwx/qt/gl/draw/draw_item.cpp
index c15b1f6d..b2c92279 100644
--- a/scwx-qt/source/scwx/qt/gl/draw/draw_item.cpp
+++ b/scwx-qt/source/scwx/qt/gl/draw/draw_item.cpp
@@ -58,12 +58,14 @@ void DrawItem::UseDefaultProjection(
 static glm::vec2
 LatLongToScreenCoordinate(const QMapLibreGL::Coordinate& coordinate)
 {
+   static constexpr double RAD2DEG_D = 180.0 / M_PI;
+
    double latitude = std::clamp(
       coordinate.first, -mbgl::util::LATITUDE_MAX, mbgl::util::LATITUDE_MAX);
    glm::vec2 screen {
       mbgl::util::LONGITUDE_MAX + coordinate.second,
       -(mbgl::util::LONGITUDE_MAX -
-        mbgl::util::RAD2DEG_D *
+        RAD2DEG_D *
            std::log(std::tan(M_PI / 4.0 +
                              latitude * M_PI / mbgl::util::DEGREES_MAX)))};
    return screen;
diff --git a/scwx-qt/source/scwx/qt/main/main_window.cpp b/scwx-qt/source/scwx/qt/main/main_window.cpp
index 4b87d60b..3b392f01 100644
--- a/scwx-qt/source/scwx/qt/main/main_window.cpp
+++ b/scwx-qt/source/scwx/qt/main/main_window.cpp
@@ -9,6 +9,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -74,10 +75,18 @@ public:
        elevationButtonsChanged_ {false},
        resizeElevationButtons_ {false}
    {
+      mapProvider_ =
+         map::GetMapProvider(manager::SettingsManager::general_settings()
+                                .map_provider()
+                                .GetValue());
+      const map::MapProviderInfo& mapProviderInfo =
+         map::GetMapProviderInfo(mapProvider_);
+
       std::string appDataPath {
          QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)
             .toStdString()};
-      std::string cacheDbPath {appDataPath + "/mbgl-cache.db"};
+      std::string cacheDbPath {appDataPath + "/" +
+                               mapProviderInfo.cacheDbName_};
 
       if (!std::filesystem::exists(appDataPath))
       {
@@ -89,12 +98,10 @@ public:
          }
       }
 
-      std::string mapboxApiKey = manager::SettingsManager::general_settings()
-                                    .mapbox_api_key()
-                                    .GetValue();
+      std::string mapProviderApiKey = map::GetMapProviderApiKey(mapProvider_);
 
-      settings_.resetToTemplate(QMapLibreGL::Settings::MapboxSettings);
-      settings_.setApiKey(QString {mapboxApiKey.c_str()});
+      settings_.resetToTemplate(mapProviderInfo.settingsTemplate_);
+      settings_.setApiKey(QString {mapProviderApiKey.c_str()});
       settings_.setCacheDatabasePath(QString {cacheDbPath.c_str()});
       settings_.setCacheDatabaseMaximumSize(20 * 1024 * 1024);
    }
@@ -105,6 +112,7 @@ public:
    void ConnectMapSignals();
    void ConnectOtherSignals();
    void HandleFocusChange(QWidget* focused);
+   void PopulateMapStyles();
    void SelectElevation(map::MapWidget* mapWidget, float elevation);
    void SelectRadarProduct(map::MapWidget*           mapWidget,
                            common::RadarProductGroup group,
@@ -113,6 +121,7 @@ public:
    void SetActiveMap(map::MapWidget* mapWidget);
    void UpdateAvailableLevel3Products();
    void UpdateElevationSelection(float elevation);
+   void UpdateMapStyle(const std::string& styleName);
    void UpdateRadarProductSelection(common::RadarProductGroup group,
                                     const std::string&        product);
    void UpdateRadarProductSettings();
@@ -121,6 +130,7 @@ public:
 
    MainWindow*           mainWindow_;
    QMapLibreGL::Settings settings_;
+   map::MapProvider      mapProvider_;
    map::MapWidget*       activeMap_;
 
    ui::Level2ProductsWidget* level2ProductsWidget_;
@@ -245,6 +255,7 @@ MainWindow::MainWindow(QWidget* parent) :
                             0);
    }
 
+   p->PopulateMapStyles();
    p->ConnectMapSignals();
    p->ConnectOtherSignals();
    p->HandleFocusChange(p->activeMap_);
@@ -586,6 +597,11 @@ void MainWindowImpl::ConnectMapSignals()
          },
          Qt::QueuedConnection);
 
+      connect(mapWidget,
+              &map::MapWidget::MapStyleChanged,
+              this,
+              &MainWindowImpl::UpdateMapStyle);
+
       connect(
          mapWidget,
          &map::MapWidget::RadarSweepUpdated,
@@ -624,6 +640,11 @@ void MainWindowImpl::ConnectOtherSignals()
            &QApplication::focusChanged,
            mainWindow_,
            [this](QWidget* /*old*/, QWidget* now) { HandleFocusChange(now); });
+   connect(mainWindow_->ui->mapStyleComboBox,
+           &QComboBox::currentTextChanged,
+           mainWindow_,
+           [&](const QString& text)
+           { activeMap_->SetMapStyle(text.toStdString()); });
    connect(level2ProductsWidget_,
            &ui::Level2ProductsWidget::RadarProductSelected,
            mainWindow_,
@@ -696,6 +717,7 @@ void MainWindowImpl::HandleFocusChange(QWidget* focused)
    {
       SetActiveMap(mapWidget);
       UpdateAvailableLevel3Products();
+      UpdateMapStyle(mapWidget->GetMapStyle());
       UpdateRadarProductSelection(mapWidget->GetRadarProductGroup(),
                                   mapWidget->GetRadarProductName());
       UpdateRadarProductSettings();
@@ -704,6 +726,16 @@ void MainWindowImpl::HandleFocusChange(QWidget* focused)
    }
 }
 
+void MainWindowImpl::PopulateMapStyles()
+{
+   const auto& mapProviderInfo = map::GetMapProviderInfo(mapProvider_);
+   for (const auto& mapStyle : mapProviderInfo.mapStyles_)
+   {
+      mainWindow_->ui->mapStyleComboBox->addItem(
+         QString::fromStdString(mapStyle.name_));
+   }
+}
+
 void MainWindowImpl::SelectElevation(map::MapWidget* mapWidget, float elevation)
 {
    if (mapWidget == activeMap_)
@@ -767,6 +799,16 @@ void MainWindowImpl::UpdateMapParameters(
    }
 }
 
+void MainWindowImpl::UpdateMapStyle(const std::string& styleName)
+{
+   int index = mainWindow_->ui->mapStyleComboBox->findText(
+      QString::fromStdString(styleName));
+   if (index != -1)
+   {
+      mainWindow_->ui->mapStyleComboBox->setCurrentIndex(index);
+   }
+}
+
 void MainWindowImpl::UpdateRadarProductSelection(
    common::RadarProductGroup group, const std::string& product)
 {
diff --git a/scwx-qt/source/scwx/qt/main/main_window.ui b/scwx-qt/source/scwx/qt/main/main_window.ui
index 9a66af52..0d5c5489 100644
--- a/scwx-qt/source/scwx/qt/main/main_window.ui
+++ b/scwx-qt/source/scwx/qt/main/main_window.ui
@@ -184,6 +184,25 @@
        
       
      
+     - 
+      
+       
+        Map Settings
+       
+       
+        - 
+         
+          
+           Map Style
+          
+         
+        +
- 
+         
+        +       
+      
+
- 
       
        
diff --git a/scwx-qt/source/scwx/qt/manager/settings_manager.cpp b/scwx-qt/source/scwx/qt/manager/settings_manager.cpp
index be161245..c11d4f71 100644
--- a/scwx-qt/source/scwx/qt/manager/settings_manager.cpp
+++ b/scwx-qt/source/scwx/qt/manager/settings_manager.cpp
@@ -1,10 +1,12 @@
 #include 
+#include 
 #include 
 #include 
 
 #include 
 #include 
 
+#include 
 #include 
 #include 
 
@@ -23,6 +25,7 @@ static const auto        logger_    = scwx::util::Logger::Create(logPrefix_);
 static boost::json::value ConvertSettingsToJson();
 static void               GenerateDefaultSettings();
 static bool               LoadSettings(const boost::json::object& settingsJson);
+static void               ValidateSettings();
 
 static bool        initialized_ {false};
 static std::string settingsPath_ {};
@@ -46,6 +49,7 @@ void Initialize()
    initialized_  = true;
 
    ReadSettings(settingsPath_);
+   ValidateSettings();
 }
 
 void ReadSettings(const std::string& settingsPath)
@@ -137,6 +141,47 @@ static bool LoadSettings(const boost::json::object& settingsJson)
    return jsonDirty;
 }
 
+static void ValidateSettings()
+{
+   logger_->debug("Validating settings");
+
+   bool settingsChanged = false;
+
+   auto& generalSettings = general_settings();
+
+   // Validate map provider
+   std::string mapProviderName = generalSettings.map_provider().GetValue();
+   std::string mapboxApiKey    = generalSettings.mapbox_api_key().GetValue();
+   std::string maptilerApiKey  = generalSettings.maptiler_api_key().GetValue();
+
+   map::MapProvider mapProvider = map::GetMapProvider(mapProviderName);
+   std::string      mapApiKey   = map::GetMapProviderApiKey(mapProvider);
+
+   if (mapApiKey == "?")
+   {
+      for (map::MapProvider newProvider : map::MapProviderIterator())
+      {
+         if (mapProvider != newProvider &&
+             map::GetMapProviderApiKey(newProvider).size() > 1)
+         {
+            logger_->info(
+               "Setting Map Provider to {} based on API key settings",
+               map::GetMapProviderName(newProvider));
+
+            std::string newProviderName {GetMapProviderName(newProvider)};
+            boost::to_lower(newProviderName);
+            generalSettings.map_provider().SetValue(newProviderName);
+            settingsChanged = true;
+         }
+      }
+   }
+
+   if (settingsChanged)
+   {
+      SaveSettings();
+   }
+}
+
 } // namespace SettingsManager
 } // namespace manager
 } // namespace qt
diff --git a/scwx-qt/source/scwx/qt/map/map_provider.cpp b/scwx-qt/source/scwx/qt/map/map_provider.cpp
new file mode 100644
index 00000000..5850cd79
--- /dev/null
+++ b/scwx-qt/source/scwx/qt/map/map_provider.cpp
@@ -0,0 +1,127 @@
+#include 
+#include 
+
+#include 
+
+#include 
+
+namespace scwx
+{
+namespace qt
+{
+namespace map
+{
+
+static const std::unordered_map mapProviderName_ {
+   {MapProvider::Mapbox, "Mapbox"},
+   {MapProvider::MapTiler, "MapTiler"},
+   {MapProvider::Unknown, "?"}};
+
+// Draw below tunnels, ferries and roads
+static const std::vector mapboxDrawBelow_ {
+   "tunnel.*", "ferry.*", "road.*"};
+
+static const std::unordered_map mapProviderInfo_ {
+   {MapProvider::Mapbox,
+    MapProviderInfo {
+       .mapProvider_ {MapProvider::Mapbox},
+       .cacheDbName_ {"mbgl-cache.db"},
+       .settingsTemplate_ {
+          QMapLibreGL::Settings::SettingsTemplate::MapboxSettings},
+       .mapStyles_ {{.name_ {"Streets"},
+                     .url_ {"mapbox://styles/mapbox/streets-v11"},
+                     .drawBelow_ {mapboxDrawBelow_}},
+                    {.name_ {"Outdoors"},
+                     .url_ {"mapbox://styles/mapbox/outdoors-v11"},
+                     .drawBelow_ {mapboxDrawBelow_}},
+                    {.name_ {"Light"},
+                     .url_ {"mapbox://styles/mapbox/light-v10"},
+                     .drawBelow_ {mapboxDrawBelow_}},
+                    {.name_ {"Dark"},
+                     .url_ {"mapbox://styles/mapbox/dark-v10"},
+                     .drawBelow_ {mapboxDrawBelow_}},
+                    {.name_ {"Satellite"},
+                     .url_ {"mapbox://styles/mapbox/satellite-v9"},
+                     .drawBelow_ {mapboxDrawBelow_}},
+                    {.name_ {"Satellite Streets"},
+                     .url_ {"mapbox://styles/mapbox/satellite-streets-v11"},
+                     .drawBelow_ {mapboxDrawBelow_}}}}},
+   {MapProvider::MapTiler,
+    MapProviderInfo {
+       .mapProvider_ {MapProvider::MapTiler},
+       .cacheDbName_ {"maptiler-cache.db"},
+       .settingsTemplate_ {
+          QMapLibreGL::Settings::SettingsTemplate::MapTilerSettings},
+       .mapStyles_ {{.name_ {"Satellite"},
+                     .url_ {"maptiler://maps/hybrid"},
+                     .drawBelow_ {"tunnel"}},
+                    {.name_ {"Streets"},
+                     .url_ {"maptiler://maps/streets-v2"},
+                     .drawBelow_ {"aeroway"}},
+                    {.name_ {"Basic"},
+                     .url_ {"maptiler://maps/basic-v2"},
+                     .drawBelow_ {"railway_transit_tunnel"}},
+                    {.name_ {"Bright"},
+                     .url_ {"maptiler://maps/bright-v2"},
+                     .drawBelow_ {"ferry"}},
+                    {.name_ {"Outdoor"},
+                     .url_ {"maptiler://maps/outdoor-v2"},
+                     .drawBelow_ {"aeroway_runway"}},
+                    {.name_ {"Topo"},
+                     .url_ {"maptiler://maps/topo-v2"},
+                     .drawBelow_ {"aeroway_runway"}},
+                    {.name_ {"Winter"},
+                     .url_ {"maptiler://maps/winter-v2"},
+                     .drawBelow_ {"aeroway_runway"}}}}},
+   {MapProvider::Unknown, MapProviderInfo {}}};
+
+MapProvider GetMapProvider(const std::string& name)
+{
+   auto result =
+      std::find_if(mapProviderName_.cbegin(),
+                   mapProviderName_.cend(),
+                   [&](const std::pair& pair) -> bool
+                   { return boost::iequals(pair.second, name); });
+
+   if (result != mapProviderName_.cend())
+   {
+      return result->first;
+   }
+   else
+   {
+      return MapProvider::Unknown;
+   }
+}
+
+std::string GetMapProviderName(MapProvider mapProvider)
+{
+   return mapProviderName_.at(mapProvider);
+}
+
+std::string GetMapProviderApiKey(MapProvider mapProvider)
+{
+   switch (mapProvider)
+   {
+   case MapProvider::Mapbox:
+      return manager::SettingsManager::general_settings()
+         .mapbox_api_key()
+         .GetValue();
+
+   case MapProvider::MapTiler:
+      return manager::SettingsManager::general_settings()
+         .maptiler_api_key()
+         .GetValue();
+
+   default:
+      return "?";
+   }
+}
+
+const MapProviderInfo& GetMapProviderInfo(MapProvider mapProvider)
+{
+   return mapProviderInfo_.at(mapProvider);
+}
+
+} // namespace map
+} // namespace qt
+} // namespace scwx
diff --git a/scwx-qt/source/scwx/qt/map/map_provider.hpp b/scwx-qt/source/scwx/qt/map/map_provider.hpp
new file mode 100644
index 00000000..7e6bb491
--- /dev/null
+++ b/scwx-qt/source/scwx/qt/map/map_provider.hpp
@@ -0,0 +1,48 @@
+#pragma once
+
+#include 
+
+#include 
+
+#include 
+
+namespace scwx
+{
+namespace qt
+{
+namespace map
+{
+
+enum class MapProvider
+{
+   Mapbox,
+   MapTiler,
+   Unknown
+};
+typedef scwx::util::
+   Iterator
+      MapProviderIterator;
+
+struct MapStyle
+{
+   std::string              name_;
+   std::string              url_;
+   std::vector drawBelow_;
+};
+
+struct MapProviderInfo
+{
+   MapProvider                             mapProvider_ {MapProvider::Unknown};
+   std::string                             cacheDbName_ {};
+   QMapLibreGL::Settings::SettingsTemplate settingsTemplate_ {};
+   std::vector                   mapStyles_ {};
+};
+
+MapProvider            GetMapProvider(const std::string& name);
+std::string            GetMapProviderName(MapProvider mapProvider);
+std::string            GetMapProviderApiKey(MapProvider mapProvider);
+const MapProviderInfo& GetMapProviderInfo(MapProvider mapProvider);
+
+} // namespace map
+} // namespace qt
+} // namespace scwx
diff --git a/scwx-qt/source/scwx/qt/map/map_widget.cpp b/scwx-qt/source/scwx/qt/map/map_widget.cpp
index 5de29c5e..40eb40f0 100644
--- a/scwx-qt/source/scwx/qt/map/map_widget.cpp
+++ b/scwx-qt/source/scwx/qt/map/map_widget.cpp
@@ -5,6 +5,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -15,6 +16,8 @@
 #include 
 #include 
 
+#include 
+
 #include 
 #include 
 #include 
@@ -39,20 +42,6 @@ namespace map
 static const std::string logPrefix_ = "scwx::qt::map::map_widget";
 static const auto        logger_    = scwx::util::Logger::Create(logPrefix_);
 
-typedef std::pair MapStyle;
-
-// clang-format off
-static const MapStyle streets          { "mapbox://styles/mapbox/streets-v11",           "Streets"};
-static const MapStyle outdoors         { "mapbox://styles/mapbox/outdoors-v11",          "Outdoors"};
-static const MapStyle light            { "mapbox://styles/mapbox/light-v10",             "Light"};
-static const MapStyle dark             { "mapbox://styles/mapbox/dark-v10",              "Dark" };
-static const MapStyle satellite        { "mapbox://styles/mapbox/satellite-v9",          "Satellite" };
-static const MapStyle satelliteStreets { "mapbox://styles/mapbox/satellite-streets-v11", "Satellite Streets" };
-// clang-format on
-
-static const std::array mapboxStyles_ = {
-   {streets, outdoors, light, dark, satellite, satelliteStreets}};
-
 class MapWidgetImpl : public QObject
 {
    Q_OBJECT
@@ -77,6 +66,7 @@ public:
        selectedTime_ {},
        lastPos_(),
        currentStyleIndex_ {0},
+       currentStyle_ {nullptr},
        frameDraws_(0),
        prevLatitude_ {0.0},
        prevLongitude_ {0.0},
@@ -84,9 +74,10 @@ public:
        prevBearing_ {0.0},
        prevPitch_ {0.0}
    {
-      SetRadarSite(scwx::qt::manager::SettingsManager::general_settings()
-                      .default_radar_site()
-                      .GetValue());
+      auto& generalSettings =
+         scwx::qt::manager::SettingsManager::general_settings();
+
+      SetRadarSite(generalSettings.default_radar_site().GetValue());
 
       // Create ImGui Context
       static size_t currentMapId_ {0u};
@@ -97,6 +88,9 @@ public:
       // Initialize ImGui Qt backend
       ImGui_ImplQt_Init();
       ImGui_ImplQt_RegisterWidget(widget_);
+
+      // Set Map Provider Details
+      mapProvider_ = GetMapProvider(generalSettings.map_provider().GetValue());
    }
 
    ~MapWidgetImpl()
@@ -134,6 +128,7 @@ public:
    std::shared_ptr context_;
 
    MapWidget*                        widget_;
+   MapProvider                       mapProvider_;
    QMapLibreGL::Settings             settings_;
    std::shared_ptr map_;
    std::list            layerList_;
@@ -156,8 +151,9 @@ public:
    common::Level2Product                 selectedLevel2Product_;
    std::chrono::system_clock::time_point selectedTime_;
 
-   QPointF lastPos_;
-   uint8_t currentStyleIndex_;
+   QPointF         lastPos_;
+   std::size_t     currentStyleIndex_;
+   const MapStyle* currentStyle_;
 
    uint64_t frameDraws_;
 
@@ -268,6 +264,18 @@ std::vector MapWidget::GetLevel3Products()
    }
 }
 
+std::string MapWidget::GetMapStyle() const
+{
+   if (p->currentStyle_ != nullptr)
+   {
+      return p->currentStyle_->name_;
+   }
+   else
+   {
+      return "?";
+   }
+}
+
 common::RadarProductGroup MapWidget::GetRadarProductGroup() const
 {
    auto radarProductView = p->context_->radar_product_view();
@@ -538,6 +546,32 @@ void MapWidget::SetMapParameters(
    }
 }
 
+void MapWidget::SetMapStyle(const std::string& styleName)
+{
+   const auto& mapProviderInfo = GetMapProviderInfo(p->mapProvider_);
+   auto&       styles          = mapProviderInfo.mapStyles_;
+
+   for (size_t i = 0u; i < styles.size(); ++i)
+   {
+      if (styles[i].name_ == styleName)
+      {
+         p->currentStyleIndex_ = i;
+         p->currentStyle_      = &styles[i];
+
+         logger_->debug("Updating style: {}", styles[i].name_);
+
+         p->map_->setStyleUrl(styles[i].url_.c_str());
+
+         if (++p->currentStyleIndex_ == styles.size())
+         {
+            p->currentStyleIndex_ = 0;
+         }
+
+         break;
+      }
+   }
+}
+
 qreal MapWidget::pixelRatio()
 {
    return devicePixelRatioF();
@@ -545,16 +579,21 @@ qreal MapWidget::pixelRatio()
 
 void MapWidget::changeStyle()
 {
-   auto& styles = mapboxStyles_;
+   const auto& mapProviderInfo = GetMapProviderInfo(p->mapProvider_);
+   auto&       styles          = mapProviderInfo.mapStyles_;
 
-   p->map_->setStyleUrl(styles[p->currentStyleIndex_].first.c_str());
-   setWindowTitle(QString("Mapbox GL: ") +
-                  styles[p->currentStyleIndex_].second.c_str());
+   p->currentStyle_ = &styles[p->currentStyleIndex_];
+
+   logger_->debug("Updating style: {}", styles[p->currentStyleIndex_].name_);
+
+   p->map_->setStyleUrl(styles[p->currentStyleIndex_].url_.c_str());
 
    if (++p->currentStyleIndex_ == styles.size())
    {
       p->currentStyleIndex_ = 0;
    }
+
+   emit MapStyleChanged(p->currentStyle_->name_);
 }
 
 void MapWidget::AddLayers()
@@ -578,15 +617,26 @@ void MapWidget::AddLayers()
       std::shared_ptr radarSite =
          p->radarProductManager_->radar_site();
 
+      const auto& mapStyle = *p->currentStyle_;
+
       std::string before = "ferry";
 
-      for (const QString& layer : p->map_->layerIds())
+      for (const QString& qlayer : p->map_->layerIds())
       {
-         // Draw below tunnels, ferries and roads
-         if (layer.startsWith("tunnel") || layer.startsWith("ferry") ||
-             layer.startsWith("road"))
+         const std::string layer = qlayer.toStdString();
+
+         // Draw below layers defined in map style
+         auto it = std::find_if(mapStyle.drawBelow_.cbegin(),
+                                mapStyle.drawBelow_.cend(),
+                                [&layer](const std::string& styleLayer) -> bool
+                                {
+                                   std::regex re {styleLayer};
+                                   return std::regex_match(layer, re);
+                                });
+
+         if (it != mapStyle.drawBelow_.cend())
          {
-            before = layer.toStdString();
+            before = layer;
             break;
          }
       }
@@ -740,16 +790,8 @@ void MapWidget::initializeGL()
                              p->prevBearing_,
                              p->prevPitch_);
 
-   QString styleUrl = qgetenv("MAPBOX_STYLE_URL");
-   if (styleUrl.isEmpty())
-   {
-      changeStyle();
-   }
-   else
-   {
-      p->map_->setStyleUrl(styleUrl);
-      setWindowTitle(QString("Mapbox GL: ") + styleUrl);
-   }
+   // Update style
+   changeStyle();
 
    connect(p->map_.get(),
            &QMapLibreGL::Map::mapChanged,
diff --git a/scwx-qt/source/scwx/qt/map/map_widget.hpp b/scwx-qt/source/scwx/qt/map/map_widget.hpp
index 104c280f..fbb5746e 100644
--- a/scwx-qt/source/scwx/qt/map/map_widget.hpp
+++ b/scwx-qt/source/scwx/qt/map/map_widget.hpp
@@ -38,6 +38,7 @@ public:
    float                              GetElevation() const;
    std::vector                 GetElevationCuts() const;
    std::vector           GetLevel3Products();
+   std::string                        GetMapStyle() const;
    common::RadarProductGroup          GetRadarProductGroup() const;
    std::string                        GetRadarProductName() const;
    std::shared_ptr GetRadarSite() const;
@@ -98,6 +99,7 @@ public:
                          double zoom,
                          double bearing,
                          double pitch);
+   void SetMapStyle(const std::string& styleName);
 
 private:
    void  changeStyle();
@@ -129,6 +131,7 @@ signals:
                              double zoom,
                              double bearing,
                              double pitch);
+   void MapStyleChanged(const std::string& styleName);
    void RadarSweepUpdated();
 };
 
diff --git a/scwx-qt/source/scwx/qt/map/radar_product_layer.cpp b/scwx-qt/source/scwx/qt/map/radar_product_layer.cpp
index f5310f1e..514b7e5c 100644
--- a/scwx-qt/source/scwx/qt/map/radar_product_layer.cpp
+++ b/scwx-qt/source/scwx/qt/map/radar_product_layer.cpp
@@ -359,12 +359,14 @@ void RadarProductLayer::UpdateColorTable()
 static glm::vec2
 LatLongToScreenCoordinate(const QMapLibreGL::Coordinate& coordinate)
 {
+   static constexpr double RAD2DEG_D = 180.0 / M_PI;
+
    double latitude = std::clamp(
       coordinate.first, -mbgl::util::LATITUDE_MAX, mbgl::util::LATITUDE_MAX);
    glm::vec2 screen {
       mbgl::util::LONGITUDE_MAX + coordinate.second,
       -(mbgl::util::LONGITUDE_MAX -
-        mbgl::util::RAD2DEG_D *
+        RAD2DEG_D *
            std::log(std::tan(M_PI / 4.0 +
                              latitude * M_PI / mbgl::util::DEGREES_MAX)))};
    return screen;
diff --git a/scwx-qt/source/scwx/qt/settings/general_settings.cpp b/scwx-qt/source/scwx/qt/settings/general_settings.cpp
index 55f74a00..19c97f8a 100644
--- a/scwx-qt/source/scwx/qt/settings/general_settings.cpp
+++ b/scwx-qt/source/scwx/qt/settings/general_settings.cpp
@@ -1,5 +1,10 @@
 #include 
 #include 
+#include 
+
+#include 
+
+#include 
 
 namespace scwx
 {
@@ -20,7 +25,9 @@ public:
       fontSizes_.SetDefault({16});
       gridWidth_.SetDefault(1);
       gridHeight_.SetDefault(1);
+      mapProvider_.SetDefault("maptiler");
       mapboxApiKey_.SetDefault("?");
+      maptilerApiKey_.SetDefault("?");
       updateNotificationsEnabled_.SetDefault(true);
 
       fontSizes_.SetElementMinimum(1);
@@ -31,8 +38,29 @@ public:
       gridWidth_.SetMaximum(2);
       gridHeight_.SetMinimum(1);
       gridHeight_.SetMaximum(2);
+      mapProvider_.SetValidator(
+         [](const std::string& value)
+         {
+            for (map::MapProvider mapProvider : map::MapProviderIterator())
+            {
+               // If the value is equal to a lower case map provider name
+               std::string mapProviderName =
+                  map::GetMapProviderName(mapProvider);
+               boost::to_lower(mapProviderName);
+               if (value == mapProviderName)
+               {
+                  // Regard as a match, valid
+                  return true;
+               }
+            }
+
+            // No match found, invalid
+            return false;
+         });
       mapboxApiKey_.SetValidator([](const std::string& value)
                                  { return !value.empty(); });
+      maptilerApiKey_.SetValidator([](const std::string& value)
+                                   { return !value.empty(); });
    }
 
    ~GeneralSettingsImpl() {}
@@ -42,7 +70,9 @@ public:
    SettingsContainer> fontSizes_ {"font_sizes"};
    SettingsVariable               gridWidth_ {"grid_width"};
    SettingsVariable               gridHeight_ {"grid_height"};
+   SettingsVariable                mapProvider_ {"map_provider"};
    SettingsVariable mapboxApiKey_ {"mapbox_api_key"};
+   SettingsVariable maptilerApiKey_ {"maptiler_api_key"};
    SettingsVariable updateNotificationsEnabled_ {"update_notifications"};
 };
 
@@ -54,7 +84,9 @@ GeneralSettings::GeneralSettings() :
                       &p->fontSizes_,
                       &p->gridWidth_,
                       &p->gridHeight_,
+                      &p->mapProvider_,
                       &p->mapboxApiKey_,
+                      &p->maptilerApiKey_,
                       &p->updateNotificationsEnabled_});
    SetDefaults();
 }
@@ -90,11 +122,21 @@ SettingsVariable& GeneralSettings::grid_width() const
    return p->gridWidth_;
 }
 
+SettingsVariable& GeneralSettings::map_provider() const
+{
+   return p->mapProvider_;
+}
+
 SettingsVariable& GeneralSettings::mapbox_api_key() const
 {
    return p->mapboxApiKey_;
 }
 
+SettingsVariable& GeneralSettings::maptiler_api_key() const
+{
+   return p->maptilerApiKey_;
+}
+
 SettingsVariable& GeneralSettings::update_notifications_enabled() const
 {
    return p->updateNotificationsEnabled_;
@@ -107,7 +149,9 @@ bool operator==(const GeneralSettings& lhs, const GeneralSettings& rhs)
            lhs.p->fontSizes_ == rhs.p->fontSizes_ &&
            lhs.p->gridWidth_ == rhs.p->gridWidth_ &&
            lhs.p->gridHeight_ == rhs.p->gridHeight_ &&
+           lhs.p->mapProvider_ == rhs.p->mapProvider_ &&
            lhs.p->mapboxApiKey_ == rhs.p->mapboxApiKey_ &&
+           lhs.p->maptilerApiKey_ == rhs.p->maptilerApiKey_ &&
            lhs.p->updateNotificationsEnabled_ ==
               rhs.p->updateNotificationsEnabled_);
 }
diff --git a/scwx-qt/source/scwx/qt/settings/general_settings.hpp b/scwx-qt/source/scwx/qt/settings/general_settings.hpp
index 48757e28..a565f09e 100644
--- a/scwx-qt/source/scwx/qt/settings/general_settings.hpp
+++ b/scwx-qt/source/scwx/qt/settings/general_settings.hpp
@@ -32,7 +32,9 @@ public:
    SettingsContainer>& font_sizes() const;
    SettingsVariable&               grid_height() const;
    SettingsVariable&               grid_width() const;
+   SettingsVariable&                map_provider() const;
    SettingsVariable&                mapbox_api_key() const;
+   SettingsVariable&                maptiler_api_key() const;
    SettingsVariable& update_notifications_enabled() const;
 
    friend bool operator==(const GeneralSettings& lhs,
diff --git a/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp b/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp
index b8250d7f..5793f6bb 100644
--- a/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp
+++ b/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp
@@ -5,6 +5,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -12,6 +13,7 @@
 #include 
 #include 
 
+#include 
 #include 
 #include 
 #include 
@@ -83,7 +85,9 @@ public:
           &fontSizes_,
           &gridWidth_,
           &gridHeight_,
+          &mapProvider_,
           &mapboxApiKey_,
+          &mapTilerApiKey_,
           &updateNotificationsEnabled_,
           &debugEnabled_}}
    {
@@ -137,7 +141,9 @@ public:
    settings::SettingsInterface> fontSizes_ {};
    settings::SettingsInterface              gridWidth_ {};
    settings::SettingsInterface              gridHeight_ {};
+   settings::SettingsInterface               mapProvider_ {};
    settings::SettingsInterface               mapboxApiKey_ {};
+   settings::SettingsInterface               mapTilerApiKey_ {};
    settings::SettingsInterface updateNotificationsEnabled_ {};
    settings::SettingsInterface debugEnabled_ {};
 
@@ -313,10 +319,46 @@ void SettingsDialogImpl::SetupGeneralTab()
    gridHeight_.SetEditWidget(self_->ui->gridHeightSpinBox);
    gridHeight_.SetResetButton(self_->ui->resetGridHeightButton);
 
+   for (const auto& mapProvider : map::MapProviderIterator())
+   {
+      self_->ui->mapProviderComboBox->addItem(
+         QString::fromStdString(map::GetMapProviderName(mapProvider)));
+   }
+
+   mapProvider_.SetSettingsVariable(generalSettings.map_provider());
+   mapProvider_.SetMapFromValueFunction(
+      [](const std::string& text) -> std::string
+      {
+         for (map::MapProvider mapProvider : map::MapProviderIterator())
+         {
+            if (boost::iequals(text, map::GetMapProviderName(mapProvider)))
+            {
+               // Return map provider label
+               return GetMapProviderName(mapProvider);
+            }
+         }
+
+         // Map provider label not found, return unknown
+         return "?";
+      });
+   mapProvider_.SetMapToValueFunction(
+      [](std::string text) -> std::string
+      {
+         // Convert label to lower case and return
+         boost::to_lower(text);
+         return text;
+      });
+   mapProvider_.SetEditWidget(self_->ui->mapProviderComboBox);
+   mapProvider_.SetResetButton(self_->ui->resetMapProviderButton);
+
    mapboxApiKey_.SetSettingsVariable(generalSettings.mapbox_api_key());
    mapboxApiKey_.SetEditWidget(self_->ui->mapboxApiKeyLineEdit);
    mapboxApiKey_.SetResetButton(self_->ui->resetMapboxApiKeyButton);
 
+   mapTilerApiKey_.SetSettingsVariable(generalSettings.maptiler_api_key());
+   mapTilerApiKey_.SetEditWidget(self_->ui->mapTilerApiKeyLineEdit);
+   mapTilerApiKey_.SetResetButton(self_->ui->resetMapTilerApiKeyButton);
+
    updateNotificationsEnabled_.SetSettingsVariable(
       generalSettings.update_notifications_enabled());
    updateNotificationsEnabled_.SetEditWidget(
diff --git a/scwx-qt/source/scwx/qt/ui/settings_dialog.ui b/scwx-qt/source/scwx/qt/ui/settings_dialog.ui
index f021c230..9a748feb 100644
--- a/scwx-qt/source/scwx/qt/ui/settings_dialog.ui
+++ b/scwx-qt/source/scwx/qt/ui/settings_dialog.ui
@@ -109,43 +109,14 @@
              
               0
              
-             - 
-              
-               
-                Default Radar Site
-               
-              
+             - 
+              
              -
- 
-              
-               
-                Grid Height
-               
-              
-             -
- 
-              
-             -
- 
-              
+             - 
+              
                
                 ...
                
-               
-                
-                 :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg
-               
-              
-             -
- 
-              
-               
-                ...
-               
-               
-                
-                 :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg
-               
               
              
- 
@@ -159,11 +130,41 @@
                
-- 
-              
+             - 
+              
+               
+                ...
+               
+               
+                
+                 :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg
+               
+              
              -
- 
-              
+             - 
+              
+               
+                ...
+               
+               
+                
+                 :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg
+               
+              
+             +
- 
+              
+               
+                Font Sizes
+               
+              
+             +
- 
+              
+               
+                MapTiler API Key
+               
+              
              
- 
               
@@ -176,13 +177,13 @@
                
               
              -
- 
-              
+             - 
+              
              -
- 
-              
+             - 
+              
                
-                Mapbox API Key
+                Grid Height
                
               
              @@ -197,16 +198,36 @@
-- 
-              
+             - 
+              
              -
- 
-              
+             - 
+              
+             +
- 
+              
                
-                Font Sizes
+                ...
+               
+               
+                
+                 :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg
                
               
              +
- 
+              
+             +
- 
+              
+               
+                Mapbox API Key
+               
+              
+             +
- 
+              
+             
- 
               
                
@@ -214,11 +235,32 @@
                
               
              -
- 
-              
+             - 
+              
+               
+                Default Radar Site
+               
+              
+             +
- 
+              
+               
+                Map Provider
+               
+              
+             +
- 
+              
+             +
- 
+              
                
                 ...
                
+               
+                
+                 :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg
+               
               
              diff --git a/test/data b/test/data
index 5b507378..938b0240 160000
--- a/test/data
+++ b/test/data
@@ -1 +1 @@
-Subproject commit 5b5073780fe44e55eb4c33799036683b28ffd2bd
+Subproject commit 938b0240e51aff37530adc679a11d0e65e5e96ce