Skip to main content

Dark Mode Visitor Map Troubleshooting

Problem Background

The homepage uses a third-party ClustrMaps visitor map component on the left side. The React function in the current code is still called MapMyVisitorsWidget, but it actually loads https://clustrmaps.com/map_v2.js. In dark mode, the internal DOM class names it generates are also clustrmaps-map / clustrmaps-map-container.

Light mode works fine, but in dark mode these problems appeared consistently:

  • The map showed only ocean and a few visitor dots; landmasses were nearly invisible.
  • Visible layering between the outer container, inner map area, and ocean background.
  • Green visitor dots were not clearly visible in dark mode.
  • The requirement was to fix dark mode only; light mode should stay unchanged.

On the surface this looks like a simple color adjustment, but further investigation proved the root cause was not just color values.

Initial Symptoms

User feedback was focused:

  • Land is invisible in dark mode.
  • The problem persists after refresh.
  • Light mode has no issues.

This pattern strongly suggests the problem is not in the global theme switching logic, but in this third-party component's own dark rendering path.

If it were a global theme or page layout issue, light mode would usually be affected too. Since light mode was always fine, the investigation narrowed to the component itself.

Round 1: Rule Out Local Style Overrides

First, I checked the homepage-related files:

  • src/pages/index.js
  • src/pages/index.module.css

I focused on several risk areas:

  • Any filter applied to the map
  • Any color inversion, brightness, or contrast processing on the map
  • Any global SVG styles accidentally affecting internal nodes of the third-party map

Results:

  • Local styles were mainly just border-radius, border, background, and shadow.
  • No filters that would directly hide the land.
  • No obvious global style conflicts found.

Conclusion from this round: the problem did not look like "our CSS is covering the map". It looked more like the third-party map component itself was failing to render land consistently in dark mode.

Round 2: Confirm What the Third-Party Script Parameters Actually Control

The homepage component switches between light and dark modes by toggling script URL parameters:

  • cl
  • co
  • ct
  • cmo
  • cmn

Initial guesses:

  • cl maps to land
  • co maps to ocean

But you cannot rely on naming alone, since third-party services may not work intuitively.

So I switched to directly reading the third-party script source code and generated output to verify.

Round 3: Read the Third-Party Map Script Source

By fetching the third-party map script source, I found that this component does not draw a complete world map with a single SVG layer. It uses two layers.

The first layer is the background layer.

The script generates a background image URL based on parameters, in a format like:

//.../generated_content/backs/bg-w_320-co_xxxxxx-cl_xxxxxx.png

This means:

  • co and cl first generate a base PNG image
  • This image handles the bottom layer of ocean and land

The second layer is the dynamic layer.

The script then asynchronously requests widget_call_home.js, and uses jvectormap on top to draw:

  • Map interaction layer
  • Visitor dots
  • Labels and statistics

Key conclusion:

Land visibility does not depend solely on whether the top SVG layer exists. It depends more on whether the bottom background image loads reliably, and whether there is enough contrast between land and ocean.

This also explains what the user saw: the top-layer visitor dots still appeared, but once the bottom land layer became unstable, the visual result was an image with only ocean and a few dots.

Round 4: Verify the Real Function of cl and co

To avoid judging based on variable names alone, I fetched the third-party generated background image and compared the color results.

Final confirmation:

  • cl does control land color
  • co does control ocean color

This step ruled out the possibility of "parameters understood backwards".

The land invisibility was not caused by swapping ocean and land colors. It was caused by two deeper issues compounding:

  • Dark color schemes lack sufficient contrast on small maps
  • The component relies too heavily on remotely generated base images from the third party

Why Simply Changing Colors Was Not Enough

I tried several different dark parameter sets, including:

  • Lighter land color
  • Darker ocean color
  • Brighter text color
  • More prominent visitor dot colors

These changes improved appearance but could not fully solve the problem.

Three reasons:

  • The problem persisted after user refresh, so it was not a one-time state residue
  • The third-party base image came from remote dynamic generation, so behavior was not fully controllable
  • Even if the parameters were theoretically reasonable, you could not guarantee consistent results on the client side every time

So as long as you keep depending on the third-party remote base image, this problem stays in a "should work in theory, but actually unstable" state.

Final Solution: Localize the Dark Mode Land Layer

The final approach was more stable.

Keep the dynamic parts handled by the third-party component:

  • Visitor dots
  • Statistics text
  • Interaction layer

Only localize the dark mode bottom map background.

After doing this:

  • Whether land displays no longer depends on the real-time behavior of the third-party remote base image
  • Light mode is completely untouched
  • Third-party dynamic data is preserved

The new local resource:

  • https://picture.nevergpdzy.cn/img_for_Typora/mapmyvisitors-dark-bg.png

This filename follows the original name from early troubleshooting; it is just a static background resource. The live script entry still points to clustrmaps.com/map_v2.js.

The corresponding style handling is in:

  • src/pages/index.module.css

The core idea here is to shrink the unstable dependency and keep only the truly valuable dynamic capabilities of the third-party component.

Additional Fix: Theme Switch Residue

Beyond the base image itself, another potential risk is that the third-party script may not fully rebuild when switching between light and dark themes.

So in the homepage component, I added extra handling to remount the visitor map on theme switch.

Related file:

  • src/pages/index.js

The purpose:

  • When switching from light to dark, the third-party script reinitializes
  • Avoid reusing leftover DOM and stale state from the previous theme

Visual Polish: Unifying the Map With the Site's Dark Style

After restoring land visibility, the problem shifted from "feature broken" to "visuals not cohesive enough".

The user then provided two key aesthetic feedback points:

  • Ocean color was inconsistent with the inner and outer container colors
  • Green visitor dots were not clear enough

So I did two more rounds of polish.

Unifying Ocean and Container Colors

Extracted the dark mode ocean color into a unified variable:

--dark-map-sea: #1c2836;

Both the outer container and inner map container use the same ocean background color. Visually, it no longer looks like two separate boxes; instead the map appears naturally embedded in the side card.

Improving Visitor Dot Visibility

Further optimizations for dark mode visitor dots:

  • Historical visitor dots switched to a cleaner mint green
  • Recent visitor dots use a clearer warm red
  • Dot outlines made brighter
  • Added a subtle glow to prevent dots from looking dull against the dark ocean

After these adjustments, dots are easier to see whether they fall on ocean or land.

Why This Solution Is More Reliable

The value of the final solution is not just "it looks good now", but that it is more controllable from an engineering perspective.

Four key points:

  • The unstable dependency was reduced; the third-party remote base image no longer determines whether land is visible
  • Risk is confined to dark mode; light mode stays as-is
  • The problem was decomposed into layers; background and dynamic layers have clearer responsibilities
  • For future fine-tuning, you only need to modify local styles and dark parameters

Key Files Involved

  • package.json
  • package-lock.json
  • src/pages/index.js
  • src/pages/index.module.css
  • https://picture.nevergpdzy.cn/img_for_Typora/mapmyvisitors-dark-bg.png

Verification

After completing the changes, I ran:

npm run build

The build passed, confirming:

  • The homepage map component code packages correctly
  • Local image resource paths are valid
  • The Docusaurus build was not broken by this change

Final Takeaway

The key issue was not "colors were wrong". If you treat it as a plain color tuning problem from the start, you get stuck in trial-and-error parameter tweaking.

The effective fix path is:

  • First understand how the third-party component actually renders the map
  • Identify the responsibility differences between the base image layer and the dynamic layer
  • Localize the most unstable dark base image layer
  • Then do color unification and readability polish

What you end up with is not a lucky color tweak, but a fix backed by evidence, with a clear analysis path, that can be maintained going forward.