diff --git a/app/assets/javascripts/discourse/app/pre-initializers/discourse-bootstrap.js b/app/assets/javascripts/discourse/app/pre-initializers/discourse-bootstrap.js
index 1b7fde0127c..3cc3b0f1415 100644
--- a/app/assets/javascripts/discourse/app/pre-initializers/discourse-bootstrap.js
+++ b/app/assets/javascripts/discourse/app/pre-initializers/discourse-bootstrap.js
@@ -84,11 +84,7 @@ export default {
         'link[media="(prefers-color-scheme: dark)"]'
       ).length > 0;
 
-    session.darkColorScheme =
-      !window.matchMedia("(prefers-color-scheme: dark)").matches &&
-      getComputedStyle(document.documentElement)
-        .getPropertyValue("--scheme-type")
-        .trim() === "dark";
+    session.defaultColorSchemeIsDark = setupData.colorSchemeIsDark === "true";
 
     session.highlightJsPath = setupData.highlightJsPath;
     session.svgSpritePath = setupData.svgSpritePath;
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 3d9523b063e..d4fe2de92b2 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -463,6 +463,10 @@ module ApplicationHelper
     result.html_safe
   end
 
+  def dark_color_scheme?
+    ColorScheme.find_by_id(scheme_id)&.is_dark?
+  end
+
   def preloaded_json
     return '{}' if @preloaded.blank?
     @preloaded.transform_values { |value| escape_unicode(value) }.to_json
@@ -485,6 +489,7 @@ module ApplicationHelper
       highlight_js_path: HighlightJs.path,
       svg_sprite_path: SvgSprite.path(theme_ids),
       enable_js_error_reporting: GlobalSetting.enable_js_error_reporting,
+      color_scheme_is_dark: dark_color_scheme?
     }
 
     if Rails.env.development?
diff --git a/app/models/color_scheme.rb b/app/models/color_scheme.rb
index 29788581781..4dbdde5061b 100644
--- a/app/models/color_scheme.rb
+++ b/app/models/color_scheme.rb
@@ -296,6 +296,18 @@ class ColorScheme < ActiveRecord::Base
     end
   end
 
+  def is_dark?
+    primary_b = brightness(colors_by_name["primary"].hex)
+    secondary_b = brightness(colors_by_name["secondary"].hex)
+
+    primary_b > secondary_b
+  end
+
+  # Equivalent to dc-color-brightness() in variables.scss
+  def brightness(color)
+    rgb = color.scan(/../).map { |c| c.to_i(16) }
+    (rgb[0].to_i * 299 + rgb[1].to_i * 587 + rgb[2].to_i * 114) / 1000.0
+  end
 end
 
 # == Schema Information
diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb
index 33b23e5fa75..257acb53c37 100644
--- a/spec/helpers/application_helper_spec.rb
+++ b/spec/helpers/application_helper_spec.rb
@@ -401,4 +401,17 @@ describe ApplicationHelper do
 
     end
   end
+
+  describe "dark_color_scheme?" do
+    it 'returns nil for the base color scheme' do
+      expect(helper.dark_color_scheme?).to eq(nil)
+    end
+
+    it 'works correctly for a dark scheme' do
+      dark_theme = Theme.where(name: "Dark").first
+      helper.request.env[:resolved_theme_ids] = [dark_theme.id]
+
+      expect(helper.dark_color_scheme?).to eq(true)
+    end
+  end
 end
diff --git a/spec/models/color_scheme_spec.rb b/spec/models/color_scheme_spec.rb
index fe2dd608feb..7035f06b44c 100644
--- a/spec/models/color_scheme_spec.rb
+++ b/spec/models/color_scheme_spec.rb
@@ -86,4 +86,15 @@ describe ColorScheme do
       end
     end
   end
+
+  describe "is_dark?" do
+    it "works as expected" do
+      scheme = ColorScheme.create_from_base(name: 'Tester')
+      ColorSchemeRevisor.revise(scheme, colors: [{ name: 'primary', hex: '333333' }, { name: 'secondary', hex: 'DDDDDD' }])
+      expect(scheme.is_dark?).to eq(false)
+
+      ColorSchemeRevisor.revise(scheme, colors: [{ name: 'primary', hex: 'F8F8F8' }, { name: 'secondary', hex: '232323' }])
+      expect(scheme.is_dark?).to eq(true)
+    end
+  end
 end