Put the live sky on your website

An astronomy club homepage that shows tonight's Moon. A blog sidebar counting down to the next eclipse. A school site with sunrise and sunset for its own courtyard. All of these are one of the recipes below, and every one of them is free.

There are five ways in, cheapest first. They all draw from the same engine, so a widget and a hand-built panel will never disagree.

Recipe 1: two lines of HTML

The classic embed: a link that upgrades itself into a live, sandboxed card. Paste this where the widget should appear:

<a class="cyclecalcs-widget" data-widget="moon" data-theme="auto" data-size="card"
   href="https://www.cyclecalcs.com/moon-phase-calendar.html">Powered by CycleCalcs</a>
<script async src="https://www.cyclecalcs.com/embed.js"></script>

data-widget takes moon, tonight, sun, parade, eclipse, eclipsehere (the next solar eclipse seen from the snippet's place), cosmic, or one of the five observatory widgets, planner, darknights, schedule, targets and upcoming; data-theme is auto, light or dark; data-size is compact, card or wide. Add data-lat, data-lon and data-tz to pin a location and its clock. The observatory widgets also take data-width (280 to 1600 pixels), data-rollover (dawn or noon, when "tonight" turns over), data-nights (7 to 30 for darknights, 3 to 10 for planner), data-scope, data-fov, data-count and data-minalt (targets), data-days and data-count (upcoming), and for planner data-count (0 or 2 to 6 targets, card and wide), data-events (0 to 3) and data-cloudmax (10 to 50, the percent cloud it still calls clear), and data-rules (schedule): your own timed steps as label:event plus or minus whole minutes, such as roof-open:sunset-15,flats-off:nautical-dusk,roof-close:sunrise+5. The embed builder writes the widget, size, theme and your own place, with a live preview, and the widget playground writes these options too and lays out a whole page of them. Add data-place to name your site on the card. If the page never runs scripts, the link still works: that graceful failure is the design.

Recipe 2: the no-iframe moon widget

The newer moon widget renders directly into your page in a shadow root: no iframe, zero layout shift by construction, and it flips the disk for southern-hemisphere visitors when your data-lat is negative.

<a href="https://www.cyclecalcs.com/moon-phase-calendar.html"
   class="cyclecalcs-moon" data-size="card" data-theme="auto"
   data-lat="39.74" data-lon="-104.99" data-place="Denver, Colorado">Tonight's moon, by CycleCalcs</a>
<script async src="https://www.cyclecalcs.com/widget.js"></script>

Recipe 3: WordPress

Self-hosted WordPress: paste either snippet above into a Custom HTML block from an Administrator or Editor account and it works as-is. WordPress removes script and iframe tags when an Author or Contributor saves the block, and on Multisite when anyone but the Super Admin does, so publish it from an account that can post raw HTML.

WordPress.com: the snippets need a paid plan with hosting features turned on, and installing your first plugin turns them on. On the free plan, and on a paid plan before that, WordPress.com removes script and iframe tags alike and keeps only the plain link.

Other hosts that strip script tags but allow iframes can use the plain iframe variant from the embed builder's code panel, which needs no JavaScript at all.

A dedicated plugin, with a [cyclecalcs] shortcode and a Gutenberg block over the same loaders, is built and tested and headed for the plugin directory; the developer hub tracks its status.

Recipe 4: React, Vue, Svelte, or none

The widget ships as a custom element on npm, so it drops into any framework's JSX or template unchanged:

# install
npm install cyclecalcs-widget
import 'cyclecalcs-widget';   // defines <cyclecalcs-widget>
<cyclecalcs-widget widget="moon" size="card" theme="auto"></cyclecalcs-widget>

The package carries the original six widgets. For Eclipse From Here and the observatory widgets, use the Recipe 1 anchor in your template and call window.CycleCalcsWidget.scan() once it is in the page.

Server-side rendering gets widgetMarkup(), which returns the anchor-plus-loader as a string. Single-page apps that inject snippets after navigation can call window.CycleCalcsWidget.scan() for the iframe widgets, or window.CycleCalcsMoon.scan() for the no-iframe moon widget, to mount late arrivals. The scoped alias @cyclecalcs/widget installs the same package.

Recipe 5: roll your own from the API

When a card is too much and you want one sentence in your own typography, call the API from the browser. CORS is open and no key is needed:

<p id="moon-line">Checking the Moon...</p>
<script>
fetch('https://www.cyclecalcs.com/v2/moon')
  .then(function (r) { return r.json(); })
  .then(function (body) {
    document.getElementById('moon-line').textContent =
      'Tonight: ' + body.data.phase.name + ', '
      + body.data.phase.illumination_percent + '% lit.';
  });
</script>

From there the whole endpoint reference is open to you: sunrise for your courtyard (/v2/sun), the next eclipse with visible-from-here (/v2/eclipses), the best observing night of the next two weeks (/v2/dark-window).

House rules and troubleshooting

If your site or app handles photos of the night sky, SkyShare for apps puts names on the Moon, planets and bright stars in them. It is in preview.

Stuck, or found an error in this guide? Contact us at info@cyclecalcs.com.

More build guides