diff --git a/scwx-qt/res/icons/scwx-64.png b/scwx-qt/res/icons/scwx-64.png
new file mode 100644
index 00000000..92163b92
Binary files /dev/null and b/scwx-qt/res/icons/scwx-64.png differ
diff --git a/scwx-qt/scwx-qt.qrc b/scwx-qt/scwx-qt.qrc
index 10d8b0a2..bc9e8b7a 100644
--- a/scwx-qt/scwx-qt.qrc
+++ b/scwx-qt/scwx-qt.qrc
@@ -18,6 +18,7 @@
         res/fonts/din1451alt.ttf
         res/fonts/din1451alt_g.ttf
         res/fonts/Inconsolata-Regular.ttf
+        res/icons/scwx-64.png
         res/icons/scwx-256.ico
         res/icons/scwx-256.png
         res/icons/font-awesome-6/angle-down-solid.svg
diff --git a/scwx-qt/source/scwx/qt/main/main.cpp b/scwx-qt/source/scwx/qt/main/main.cpp
index 4c0bdac4..121766c2 100644
--- a/scwx-qt/source/scwx/qt/main/main.cpp
+++ b/scwx-qt/source/scwx/qt/main/main.cpp
@@ -6,6 +6,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -70,6 +71,16 @@ int main(int argc, char* argv[])
    // Initialize application
    scwx::qt::config::RadarSite::Initialize();
    scwx::qt::manager::SettingsManager::Instance().Initialize();
+
+   // Run initial setup if required
+   if (scwx::qt::ui::setup::SetupWizard::IsSetupRequired())
+   {
+      scwx::qt::ui::setup::SetupWizard w;
+      w.show();
+      a.exec();
+   }
+
+   // Run further application initialization
    scwx::qt::manager::ResourceManager::Initialize();
 
    // Run Qt main loop
diff --git a/scwx-qt/source/scwx/qt/ui/setup/finish_page.cpp b/scwx-qt/source/scwx/qt/ui/setup/finish_page.cpp
index 6b86f469..a4d62001 100644
--- a/scwx-qt/source/scwx/qt/ui/setup/finish_page.cpp
+++ b/scwx-qt/source/scwx/qt/ui/setup/finish_page.cpp
@@ -1,5 +1,8 @@
 #include 
 
+#include 
+#include 
+
 namespace scwx
 {
 namespace qt
@@ -14,11 +17,27 @@ class FinishPage::Impl
 public:
    explicit Impl() = default;
    ~Impl()         = default;
+
+   QVBoxLayout* layout_ {nullptr};
+   QLabel*      finishLabel_ {nullptr};
 };
 
 FinishPage::FinishPage(QWidget* parent) :
     QWizardPage(parent), p {std::make_shared()}
 {
+   setTitle(tr("Setup Complete"));
+   setSubTitle(tr("Supercell Wx setup is complete!"));
+
+   p->finishLabel_ =
+      new QLabel(tr("Supercell Wx setup is now complete and ready for use. "
+                    "Additional settings may be configured after startup. For "
+                    "further information, please see the User Manual from the "
+                    "Help menu, or join the Discord server for help."));
+   p->finishLabel_->setWordWrap(true);
+
+   p->layout_ = new QVBoxLayout(this);
+   p->layout_->addWidget(p->finishLabel_);
+   setLayout(p->layout_);
 }
 
 FinishPage::~FinishPage() = default;
diff --git a/scwx-qt/source/scwx/qt/ui/setup/map_page.cpp b/scwx-qt/source/scwx/qt/ui/setup/map_page.cpp
index d586d3fa..e5d9af3b 100644
--- a/scwx-qt/source/scwx/qt/ui/setup/map_page.cpp
+++ b/scwx-qt/source/scwx/qt/ui/setup/map_page.cpp
@@ -19,6 +19,8 @@ public:
 MapPage::MapPage(QWidget* parent) :
     QWizardPage(parent), p {std::make_shared()}
 {
+   setTitle(tr("Map Configuration"));
+   setSubTitle(tr("Configure the Supercell Wx map provider and basic layout."));
 }
 
 MapPage::~MapPage() = default;
diff --git a/scwx-qt/source/scwx/qt/ui/setup/setup_wizard.cpp b/scwx-qt/source/scwx/qt/ui/setup/setup_wizard.cpp
index e2980a4a..f4253e5a 100644
--- a/scwx-qt/source/scwx/qt/ui/setup/setup_wizard.cpp
+++ b/scwx-qt/source/scwx/qt/ui/setup/setup_wizard.cpp
@@ -1,4 +1,11 @@
 #include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
 
 namespace scwx
 {
@@ -19,10 +26,45 @@ public:
 SetupWizard::SetupWizard(QWidget* parent) :
     QWizard(parent), p {std::make_shared()}
 {
+   setWindowTitle(tr("Supercell Wx Setup"));
+   setPixmap(QWizard::LogoPixmap, QPixmap(":/res/icons/scwx-64.png"));
+
+   setOption(QWizard::WizardOption::IndependentPages);
+   setOption(QWizard::WizardOption::NoBackButtonOnStartPage);
+   setOption(QWizard::WizardOption::NoCancelButton);
+   setOption(QWizard::WizardOption::HaveHelpButton);
+
+   setPage(static_cast(Page::Welcome), new WelcomePage(this));
+   setPage(static_cast(Page::Map), new MapPage(this));
+   setPage(static_cast(Page::Finish), new FinishPage(this));
+
+#if !defined(Q_OS_MAC)
+   setWizardStyle(QWizard::WizardStyle::ModernStyle);
+#endif
+
+   connect(this,
+           &QWizard::helpRequested,
+           this,
+           []() {
+              QDesktopServices::openUrl(
+                 QUrl {"https://supercell-wx.readthedocs.io/"});
+           });
 }
 
 SetupWizard::~SetupWizard() = default;
 
+bool SetupWizard::IsSetupRequired()
+{
+   auto& generalSettings = settings::GeneralSettings::Instance();
+
+   std::string mapboxApiKey   = generalSettings.mapbox_api_key().GetValue();
+   std::string maptilerApiKey = generalSettings.maptiler_api_key().GetValue();
+
+   // Setup is required if either API key is empty, or contains a single
+   // character ("?")
+   return (mapboxApiKey.size() <= 1 && maptilerApiKey.size() <= 1);
+}
+
 } // namespace setup
 } // namespace ui
 } // namespace qt
diff --git a/scwx-qt/source/scwx/qt/ui/setup/setup_wizard.hpp b/scwx-qt/source/scwx/qt/ui/setup/setup_wizard.hpp
index ba753d2b..f4c5e9e8 100644
--- a/scwx-qt/source/scwx/qt/ui/setup/setup_wizard.hpp
+++ b/scwx-qt/source/scwx/qt/ui/setup/setup_wizard.hpp
@@ -14,9 +14,18 @@ namespace setup
 class SetupWizard : public QWizard
 {
 public:
+   enum class Page : int
+   {
+      Welcome = 0,
+      Map,
+      Finish
+   };
+
    explicit SetupWizard(QWidget* parent = nullptr);
    ~SetupWizard();
 
+   static bool IsSetupRequired();
+
 private:
    class Impl;
    std::shared_ptr p;
diff --git a/scwx-qt/source/scwx/qt/ui/setup/welcome_page.cpp b/scwx-qt/source/scwx/qt/ui/setup/welcome_page.cpp
index 76708d90..c2857980 100644
--- a/scwx-qt/source/scwx/qt/ui/setup/welcome_page.cpp
+++ b/scwx-qt/source/scwx/qt/ui/setup/welcome_page.cpp
@@ -1,5 +1,8 @@
 #include 
 
+#include 
+#include 
+
 namespace scwx
 {
 namespace qt
@@ -14,11 +17,26 @@ class WelcomePage::Impl
 public:
    explicit Impl() = default;
    ~Impl()         = default;
+
+   QVBoxLayout* layout_ {nullptr};
+   QLabel*      welcomeLabel_ {nullptr};
 };
 
 WelcomePage::WelcomePage(QWidget* parent) :
     QWizardPage(parent), p {std::make_shared()}
 {
+   setTitle(tr("Introduction"));
+   setSubTitle(tr("Welcome to Supercell Wx!"));
+
+   p->welcomeLabel_ =
+      new QLabel(tr("Welcome to Supercell Wx. This wizard will guide you "
+                    "through configuring Supercell Wx for initial use, as well "
+                    "as introduce you to any new features."));
+   p->welcomeLabel_->setWordWrap(true);
+
+   p->layout_ = new QVBoxLayout(this);
+   p->layout_->addWidget(p->welcomeLabel_);
+   setLayout(p->layout_);
 }
 
 WelcomePage::~WelcomePage() = default;