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. - Installable PWA (geoclock.world only) โ install the demo as an app (header button on Chrome/Edge; Share โ Add to Home Screen on iOS). A service worker caches everything โ all 24 monthly imagery variants included โ so the map, clocks, markers, and planner work fully offline; only place-name search needs a connection.
- Meeting planner (geoclock.world only) โ a strip under the live
demo's map scores the next 48 h across your markers (green: everyone
in work hours; yellow: everyone awake; red: someone asleep โ worst
participant wins), suggests the best windows, and lets you scrub or
type a time to time-travel the whole map there. Powered by the
card's public
previewNowproperty +resolvedMarkers/tzReadygetters and the bundle-exported helpers fromsrc/meeting-plan.ts. - 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
dayColor: "#ff9933" # optional day/night pair โ this marker recolors
nightColor: "#3da9fc" # live as the terminator crosses its location
markerLabelMode: auto # auto | always | compact | hover
# auto (default): full name+time labels, degrading to
# compact (small time-only, tap for full info) when the
# card renders narrower than ~520px โ phones, narrow
# dashboard columns. always/compact pin either form.
markerColor: "#3da9fc" # default fill for markers without their own color
# โ omit (or unset) to let `--geo-marker-color` win
markerDayColor: "#ff9933" # card-wide day/night defaults; setting either opts
markerNightColor: "#3da9fc" # every marker into day/night mode (per-marker wins)
markerShowDay: true # append weekday after the time (e.g. "12:22 PM Friday")
# Overlays
showClock: true # main clock readout + date (off for embedders
# that draw their own live clock, e.g. screensavers)
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/marker-color.tsโ day/night marker color selection from sun elevation.src/config-utils.tsโ pure config sanitizers (colors, locale, imagery base, numeric guards), unit-tested in isolation.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.
