Source Code

<div class="cst-page">
  <main class="cst-content"><p>&#8593; Page content above the footer</p></main>
  <footer class="cst">
    <div class="cst-inner">
      <div class="cst-top">
        <div class="cst-col">
          <p class="cst-brand">Northline</p>
          <p class="cst-copy">&copy; 2026 Northline Inc.</p>
        </div>
        <ul class="cst-links">
          <li><a href="#">Docs</a></li>
          <li><a href="#">Pricing</a></li>
          <li><a href="#">Privacy</a></li>
          <li><a href="#">Contact</a></li>
        </ul>
      </div>

      <div class="cst-row">
        <a class="cst-changelog" href="#" id="cstChangelogLink">
          <span class="cst-changelog-badge" id="cstVersionBadge">v2.14.0</span>
          <span class="cst-changelog-text">
            <b id="cstChangelogTitle">Loading latest release&hellip;</b>
            <small id="cstChangelogMeta">&nbsp;</small>
          </span>
          <span class="cst-changelog-arrow">&rarr;</span>
        </a>

        <a class="cst-status" href="#" id="cstStatusLink">
          <span class="cst-status-dot" id="cstStatusDot"></span>
          <span id="cstStatusText">Checking status&hellip;</span>
        </a>
      </div>
    </div>
  </footer>
</div>

Changelog & Status Footer — Free HTML CSS JS Snippet

Changelog & Status Footer · Footers · Plain HTML, CSS & JS · Live preview

What's included

Features

Changelog card always reads releases[0] as the single source of truth for "latest"
Status dot computed as the worst state across a services array, not manually asserted
Pulsing green dot only for the healthy "ok" state, static amber/red for degraded/down
Version rendered as a small colored badge pill matching real changelog conventions
Simulated async loading state avoids flashing empty content before data arrives
Both cards are full-card links, ready to point at real changelog and status-page URLs
Responsive layout stacks the two cards vertically on small screens
Zero dependencies, vanilla JavaScript only

About this UI Snippet

Changelog & Status Footer — Latest Release Card with a Computed Status Dot

Screenshot of the Changelog & Status Footer snippet rendered live

Most footers bury "what's new" and "is it working" behind separate pages a visitor rarely clicks. This snippet surfaces both directly in the footer as two compact cards: a changelog card showing the most recent release's version, title, and relative time, and a status card whose colored dot is computed from an actual list of services rather than hand-typed as "All systems operational" and forgotten the next time something breaks.

A changelog card driven by a releases array

The releases array holds objects with version, title, and when. loadChangelog() always reads releases[0] — the array's first entry is the source of truth for "latest," so publishing a new release is just unshifting a new object onto the front of the array rather than editing a separate hardcoded footer string. The version renders as a small colored .cst-changelog-badge pill, matching how release notes are tagged in real changelogs.

Status derived from services, not asserted

computeOverallStatus() walks the services array (each with a name and state of ok, degraded, or down) and returns the worst state found — down beats degraded beats ok. This mirrors how real status pages aggregate: the footer's one-line summary is never manually out of sync with the individual service states, because it is computed from them every time loadStatus() runs.

A pulsing dot only when things are actually fine

.cst-status-dot.ok gets a box-shadow keyframe pulse — the same "alive" visual language used across live-status UI — while .degraded and .down render as flat, non-pulsing amber and red. A pulse implies healthy, ongoing normal operation; a degraded or down state should read as a static, attention-worthy color instead.

Simulated load delay

Both cards start in a loading state ("Loading latest release…", "Checking status…") and populate after a setTimeout, standing in for a real fetch to a changelog API and a status-page API. This avoids the footer flashing empty content before real async data arrives, and gives you an obvious place to swap in fetch() calls.

Two independent link targets

Both cards are full <a> elements pointing at # in the demo — in production, the changelog card should link to the specific release's changelog entry (e.g. /changelog/v2.14.0) and the status card to your public status page (e.g. a hosted Statuspage or Instatus URL), so a curious or worried visitor lands on the right detail page from the footer with one click.

Wiring it to real data

Replace the static releases and services arrays with fetch() calls to your changelog API and status-page API (many status providers expose a JSON summary endpoint), keeping computeOverallStatus() and the render functions unchanged — they already treat the data as external truth, not something to duplicate elsewhere in the footer.

Build with AI

Build, Understand, Optimize, and Extend It With AI

Rather than tracing the worst-of status computation by hand, paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly how computeOverallStatus() picks the worst state across the services array and why that is more reliable than a single hardcoded status string. The same assistant can help you optimize it, for instance asking whether the changelog and status data should be cached with a short revalidation window instead of fetched fresh on every page load. It is also useful for extending the footer: ask it to wire in real fetch() calls to a changelog API and a status-page JSON endpoint, add a small incident history list under the status card, or animate the changelog card when a brand-new release appears since the visitor's last page view. Treat the code less like a finished artifact and more like a starting point for a conversation.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a footer "changelog and status" bar in plain HTML, CSS, and JavaScript, no library.

Requirements:
- A dark footer with brand/link columns above two side-by-side cards: a changelog card and a status card, stacking vertically on narrow screens.
- The changelog card must read its content from a JavaScript array of release objects (version, title, relative time), always displaying the first entry in the array as "latest" — adding a new release should only require adding a new object to the front of the array, not editing separate markup.
- The status card must compute its overall state from a separate JavaScript array of service objects, each with a state of "ok", "degraded", or "down" — the overall status must be the single worst state found across all services (down beats degraded beats ok), not a manually typed string.
- The status dot must pulse via a CSS box-shadow keyframe animation only when the overall computed state is "ok"; degraded and down states must render as flat, non-pulsing amber and red respectively.
- Both cards must start in a loading placeholder state ("Loading latest release…", "Checking status…") and populate after a short simulated delay via setTimeout, standing in for real API calls.
- Both cards must be full clickable link elements ready to point at a real changelog entry URL and a real status-page URL.

Want to tighten it up first? Run this prompt through the AI Prompt Studio to score it across 8 quality dimensions, catch anti-patterns, and tune the wording for Claude, ChatGPT, or Gemini before you paste it in.

Step by step

How to Use

  1. 1
    Paste HTML, CSS, and JSThe footer shows loading placeholders, then populates the changelog and status cards after a short simulated delay.
  2. 2
    Check the changelog cardIt shows the version badge, release title, and relative time of the most recent entry in the releases array.
  3. 3
    Check the status cardThe dot color and label are computed from the worst state found across the services array.
  4. 4
    Add a new releaseIn the JS panel, unshift a new { version, title, when } object onto the front of the releases array.
  5. 5
    Simulate an outageChange any service's state to "degraded" or "down" in the services array and reload to see the dot and label update.
  6. 6
    Wire it to real endpointsReplace the static arrays with fetch() calls to your changelog and status-page APIs.

Real-world uses

Common Use Cases

SaaS product marketing sites
Give visitors a one-glance answer to "is this actively maintained" and "is it working right now" without leaving the page they are on.
Developer tools and API platforms
Pair with a Docs Version Selector Footer so release notes, docs versioning, and live status all live in the same footer region.
Internal admin and ops dashboards
Surface the deploy history and service health directly in the shared app shell footer for a team that checks it constantly.
Teaching derived-state UI patterns
A compact example of computing one summary state (worst-of) from a list, instead of hand-asserting a status that can drift out of sync.
Related: Business Hours Status Footer
See the Business Hours Status Footer for a related computed-status footer pattern worth comparing against this one.
Related: Live Chat Launcher Footer Bar
See the Live Chat Launcher Footer Bar for a related footers pattern worth pairing with this one.

Got questions?

Frequently Asked Questions

The releases array in the JS panel, an array of { version, title, when } objects ordered newest first. loadChangelog() always renders releases[0], so publishing a new entry means adding a new object to the front of the array rather than editing separate footer markup.

computeOverallStatus() loops the services array and returns the single worst state found, using the precedence down > degraded > ok. The status dot color and label are derived from this one computed value, so they can never contradict the individual service states.

A pulsing animation visually implies ongoing healthy activity. Reusing it for a degraded or down state would send a confusing signal, so those states render as flat, non-animated amber or red instead.

Replace the static releases and services arrays with fetch() calls to your changelog API and status-page API (most status-page providers, including self-hosted ones, expose a JSON summary endpoint), keeping the render and computeOverallStatus() functions unchanged.

Yes — add as many { name, state } objects to the services array as needed. computeOverallStatus() already loops the full array regardless of length.

Yes. Keep releases and services as state or fetched data, derive the overall status with the same worst-of logic in a computed/useMemo value, and render the two cards from that derived state.