A Home Assistant Lovelace card that turns one of your dashboards into a live world clock, modeled on the Geochron® style (no affiliation). NASA Blue Marble (day) and Black Marble (night) imagery, a real day/night terminator computed from solar geometry, and DST-aware hover popups for every IANA time zone on the planet.
🌍 Live demo: https://geoclock.world
🧩 Chrome new-tab extension: a standalone, fully-offline build of the same
card that replaces your new-tab page — see chrome-extension/.
- World map — NASA Blue Marble + Black Marble imagery, with the live day/night boundary recomputed from the subsolar point. 24 daylight composites (start + mid of each month, sampled from NASA SVS daily frames) swap automatically through the year so vegetation and snow cover follow the seasons.
- Twilight glow — warm sunrise/sunset rim along the terminator, screen- blended over the day side.
- Hour band — 25 column meridians at every 15° of longitude, with the current local hour highlighted at noon and midnight.
- Time-zone overlay:
- 25 visible 15° offset bands across the globe.
- 419 IANA polygons sitting invisibly on top — hover (or tap on mobile) and a popup shows DST-aware live time, the long zone name (EDT vs EST auto-switches), the current offset, the IANA tzid, the local date (handy when the remote zone has rolled to a different day), and the hovered region outlines itself for visual feedback.
- Time and date follow the browser's locale (24-hour vs AM/PM, weekday/month language).
- Open ocean / Antarctic strips with no IANA polygon fall through to the offset band's popup.
- Centering modes —
sun(default, subsolar point — the daylit hemisphere stays in the middle and the map slowly drifts),home(your HA-configured longitude),longitude(any numeric value), orentity(follow a zone / person / device-tracker entity). All non-sunmodes fall back to Greenwich (lon=0°) with a console warning when their data isn't available — so a misconfigured mode looks visibly different fromsuninstead of silently behaving the same. - Home marker — optional dot at your HA-configured location that tracks the map's drift, with an opt-in label + current local time beneath it.
- Location markers — pin any list of HA entities (zones, persons,
device-trackers) on the map; each shows the entity's label and the
current local time at that zone (DST-aware, looked up from its
longitude/latitude). Labels are always-visible by default; flip to
hover-only if you'd rather keep the map tidy. The weekday is
appended to the time so a marker on the far side of the planet
whose date has rolled over is obvious at a glance — toggle off if
you want time-only. Per-marker color, or a card-wide default that
themes can override via
--geo-marker-color. - Main-clock time source — the wall-clock readout can read from
your HA location (default), the viewing device, or any HA entity
with a longitude/latitude. (Breaking change in v0.2.0: pre-0.2.0
cards behaved as if the source was the viewing device. Set
mainTimeSource: deviceto keep the old behavior.) - Time scrubbing — freeze the clock at any UTC moment via
now: …for screenshots or to preview the look at, say, the December solstice. - Visual editor — opens automatically when adding the card; advanced visual knobs collapse into an expansion panel so the form stays clean.
- Tunable — twilight band size, glow color/opacity, day brightness, night contrast, time-zone line color, all via card config or CSS variables.
- Cheap — clock readout ticks every second; the map only recomputes when the subsolar point would have moved ≥ 0.5 px on a 4K display (≈ every 10.5 s). When the card is off-screen or the browser tab is backgrounded the timer drops to a 30-minute cadence; refreshes immediately when the card becomes visible again.
-
Click the badge above (it deep-links to your HA instance) — or manually go HACS → ⋮ → Custom repositories → add
https://github.com/jpettitt/geo-clock-card, category Lovelace. -
Install Geo Clock Card from HACS.
-
Refresh the browser. HACS adds the resource for you; otherwise: Settings → Dashboards → ⋮ → Resources → add
/hacsfiles/geo-clock-card/geo-clock-card.jsas a JavaScript Module. -
Add a card to your dashboard:
type: custom:geo-clock-card
-
Clone the repo and build:
git clone https://github.com/jpettitt/geo-clock-card cd geo-clock-card npm install npm run fetch-assets # downloads NASA imagery + IANA TZ polygons npm run build
-
Copy the entire
dist/directory into your Home Assistant config:<config>/www/community/geo-clock-card/ geo-clock-card.js blue-marble-*-2048.jpg black-marble-2048.jpg timezones.json timezones-iana.json -
Add the resource: Settings → Dashboards → ⋮ → Resources →
/local/community/geo-clock-card/geo-clock-card.js, type JavaScript Module. -
Add the card with
type: custom:geo-clock-card.
A visual editor opens automatically when you add the card from the Lovelace picker. Every option is also settable in YAML:
type: custom:geo-clock-card
# Map centering — sun (default) | home | longitude | entity
center: sun
centerLongitude: -119 # required when center: longitude. -180..180.
centerEntity: zone.home # required when center: entity. Must expose a longitude attribute.
showHomeMarker: false # render a dot at hass.config.latitude/longitude
showHomeMarkerLabel: false # also show home name + current local time under the dot
# Imagery + atmosphere (under "Advanced visual settings" in the editor)
dayBrightness: 1.15 # CSS brightness() on the day layer (0.5..2.0)
nightContrast: 1.0 # CSS contrast() on the night layer (0.5..3.0)
twilightDegrees: 8 # half-band of the day/night fade, sun-elevation degrees (1..18)
twilightColor: "#463701" # hex / rgb / rgba / hsl / named color
twilightOpacity: 0.26 # 0..1
timezoneLineColor: "rgba(255, 255, 255, 0.18)" # any CSS color string
# Time
updateInterval: 1 # seconds between clock-readout ticks (1..600).
# The map repaints on a separate auto-throttled timer;
# both drop to 30 minutes when the card is off-screen.
now: "2024-12-21T09:21:00Z" # freeze the clock at this moment (omit for live)
# Main-clock time source — home (default) | device | entity
# - 'home' reads hass.config.time_zone (the HA-configured zone)
# - 'device' uses the viewing browser's zone (pre-0.2.0 behavior)
# - 'entity' picks the IANA zone of an HA entity's lat/lon
mainTimeSource: home
mainTimeEntity: zone.work # required when mainTimeSource: entity
# Location markers — list of HA entities to pin on the map.
# Each entity must expose numeric `latitude` and `longitude` attributes.
markers:
- entity: zone.work
label: Office # optional — defaults to the entity's friendly_name
color: "#3da9fc" # optional — defaults to markerColor
- entity: person.alice
markerLabelMode: always # always | hover
markerColor: "#3da9fc" # default fill for markers without their own color
# — omit (or unset) to let `--geo-marker-color` win
markerShowDay: true # append weekday after the time (e.g. "12:22 PM Friday")
# Overlays
showTimezoneBand: true # hour-of-day numbers across the top
showTimezoneBoundaries: true # IANA hover/identify popup hit layer
showTimezoneRegions: true # 15° offset rectangle bands (defaults to
# showTimezoneBoundaries; set independently to
# show the bands as chrome without the popup)
showTimezonePopup: true # live-time popup on hover/tap
showUTC: true # UTC time below the local clock
# Localization (optional; defaults to the browser/runtime locale)
locale: "" # BCP-47 tag, e.g. "fr-FR" or "ja-JP".
# Governs the popup's localized timezone
# name, the clock readout, marker times, and
# the 12/24-hour choice. Empty = follow the
# viewer's browser language.
# Bundle resolution (rarely needed; not exposed in the visual editor)
imageryBase: "" # override the assets URL (e.g. host on a CDN)sun(default) — centered on the current subsolar longitude. The map drifts westward as the sun moves; the daylit hemisphere stays in the middle.home— centered onhass.config.longitude. Falls back to Greenwich (0°) with aconsole.warnif HA hasn't reported a longitude.longitude— centered on a numericcenterLongitudevalue. Falls back to Greenwich (0°) if the value is missing or non-numeric.entity— centered on the longitude attribute of an HA entity. Works withzone.*,person.*, and mostdevice_tracker.*entities. Falls back to Greenwich (0°) if the entity is missing or has no numeric longitude.
The Greenwich fallback is deliberate — it's visually distinct from sun
mode so a misconfiguration doesn't silently look right. Watch the browser
console for a one-off warn line that names the broken field.
The card respects HA dashboard themes via custom-element CSS variables. Drop
these in your theme YAML (or use card-mod) to override without touching the
card config:
geo-clock-card:
--geo-day-brightness: 1.2
--geo-night-contrast: 1.0
--geo-twilight-color: "#5a4a1a"
--geo-twilight-opacity: 0.3
--geo-tz-bg: rgba(8, 14, 28, 0.85)
--geo-tz-noon: "#ffd866"
--geo-tz-mid: "#6ab0ff"
--geo-tz-line: rgba(255, 255, 255, 0.18)
--geo-home-marker: var(--accent-color, "#ff7a3d")
--geo-marker-color: "#3da9fc"Most of these have a matching named config option (e.g. dayBrightness
→ --geo-day-brightness); set in YAML when you're tweaking a single
card, or in a theme when you want every dashboard's geo-clock to match.
| Layer | Source | Resolution |
|---|---|---|
| Day (Blue Marble) | NASA SVS dataset 3523, daily frames interpolating monthly Blue Marble Next Generation composites | 2048 × 1024 JPEG, 24 frames (start + mid of each month) |
| Night (Black Marble) | NASA "Earth at Night" 2012 composite | 2048 × 1024 JPEG |
| Time-zone offsets | Generated as 25 × 15° rectangle bands | 8 KB GeoJSON |
| Time-zone IANA | timezone-boundary-builder 2026b, simplified to 1% retention | ~960 KB GeoJSON |
npm install
npm run fetch-assets # one-time: pulls + resizes imagery, downloads + simplifies TZ data
npm test # vitest — solar math, projection, polygon, IANA helpers
npm run build # rollup → dist/geo-clock-card.js + copies assets
npm run dev # rollup --watchA standalone preview lives at dev/index.html. Run a static
server from the repo root (python3 -m http.server 8765) and open
http://localhost:8765/dev/index.html. The preview gives you sliders for
twilight band, day brightness, night contrast, twilight color/opacity,
center mode, time-scrubbing with solstice/equinox presets, etc.
src/sun.ts— subsolar point + sun-elevation math (USNO low-precision formulas).src/terminator.ts— terminator polygon and curve, parameterized by center longitude.src/projection.ts— equirectangular projection with arbitrary center.src/timezones.ts— offset overlay (25 rectangle bands + popup data).src/timezones-iana.ts— IANA polygon hit-testing layer + DST-awareIntl.DateTimeFormatwrapper.src/timezone-band.ts— top-of-map hour band + tick lines.src/day-image.ts— picks the right monthly daylight image for a given date.src/geo-clock-card.ts— the Lit element that wires it all together.src/geo-clock-card-editor.ts— visual config editor (HAha-textfield/ha-switch/ha-formfield/ha-selector/ha-expansion-panel, plus native<select>for the centering / time-source / marker-mode dropdowns whereha-selectwas unreliable). AwaitsloadCardHelpers()before rendering so the entity selectors register correctly. Lazy-loaded by the card viagetConfigElement()and bundled inline.
The original design notes are in DESIGN.md.
MIT for the code. NASA imagery is public domain. timezone-boundary-builder data is ODbL.
Geochron® is a registered trademark of Geochron Enterprises Inc.; this project is not affiliated with or endorsed by them.
