npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@freva-org/freva-badge

v2608.0.0-beta.0

Published

The Freva footer badge: a static mark that opens a panel, with a bird that flies in and lands on it.

Downloads

108

Readme

@freva-org/freva-badge

The Freva footer badge, vendored as its optimized runtime. A static mark that opens a panel, with a bird that flies in, lands on the mark and walks along its rim.

This package is the badge's implementation. Nothing outside it draws the badge, animates it, or styles it. A host mounts it and tells it where its assets live; everything else - the markup, the motion, the copy, the CSS - is here.

dist/
  freva-badge.js           the runtime; hand maintained, no build step
  freva-badge-content.js   copy, links, organisations; no logic
  freva-badge.css          all of the badge's styling, scoped under `.fb`
  assets/                  mark, story sheet, motion chunks and manifests

Mounting

window.FrevaBadgeOptions = { assetBase: "/site/_badge/assets/" };
// then load freva-badge-content.js, then freva-badge.js
FrevaBadge.mount(element);

| Option | Meaning | | ----------- | --------------------------------------------------------------------------- | | assetBase | Where assets/ was published. Must end in /. | | quality | "auto" (default) picks 1x or 2x by display density; "standard" pins 1x. |

The loading lifecycle, which is the point of this package

  • about 70 KB of code plus the static mark at page load, and nothing else;
  • the footer story sheet and the flight and walk sprites only once someone hovers, focuses, touches or opens the badge - never before;
  • and the story only plays when the visitor closes the panel. A mark that ran its whole story on every page load was motion nobody asked for;
  • a visitor who asked for reduced motion, or whose browser reports Save-Data, gets the still asset and no sprite sheet at all;
  • drawing surfaces are sized to the animation, allocated on open and released on close; nothing paints while the badge is closed or the document is hidden.

Do not add preload hints for the bridge or ground assets. They would defeat all of the above.

What is not here

masters/, tools/, results/, demo/ and the original PNG atlases are not vendored: they are the inputs to the assets in dist/assets, not something a portal serves. Asset regeneration happens upstream, against the masters archive, and lands here as a new dist/.

Local changes to the vendored runtime

Eight, kept here so a future asset drop does not become a portal change. Each one is a host-integration fix - none changes what the badge draws, how it moves, or what it says:

  1. quality: "standard" in FrevaBadgeOptions, which pins the motion assets to the 1x set instead of choosing by device pixel ratio.
  2. Every selector in the stylesheet is scoped under .fb, the root the runtime already builds. Mechanical, no declaration touched, and load-bearing in both directions: the badge cannot restyle a host, and a host cannot restyle the badge. It is not hypothetical - the Data Browser ships a global .pop { display: none } for its own popovers, which hid this one entirely on any page that mounted it. .fb .pop now states its own display: block for the same reason: scoping raises specificity, but only for properties the badge actually declares, and this was not one of them.
  3. The badge's own typography is stated on .fb rather than inherited, and restated as font-family: inherit on the element types a host stylesheet can name. Scoping stops the badge reaching the host; this is the other direction. The panel's headline is an <h2>, so a portal's h1, h2, h3, h4 rule reached straight into the mark: every size inside the panel is a fraction of --pop-w, so a face with different metrics rewrapped the headline from two lines to four and pushed the organisation strip out of the circle. Measured against the package's own demo page, the panel's computed styles now differ in four places, all of them intended: the asset origin, the shadow colour the badge takes from the page by design, the marquee's animation phase, and an icon-only button's font.
  4. The footer story sheet is loaded straight from its own same-origin URL. Upstream fetched it as bytes and handed CSS an object URL to keep the uncached case at one request; a host with an ordinary img-src 'self' data: refuses a blob: URL, so the sheet silently never became ready and the badge kept its static mark forever. One request either way - the fetch is gone, not moved - and a portal needs no blob: in its policy.
  5. The story sheet moved behind the intent gate, and arriving no longer means playing. Upstream fetched it on an idle callback and played it the moment it landed, so 765 kB arrived on every page load and the mark ran its whole 260-frame story in the corner of every documentation page, unprompted. It is fetched now with the motion - on hover, focus, touch or open - and it plays when the panel closes. The at-rest cost is the 70 kB the lifecycle above claims, and the mark at rest is the still, which is the same artwork: the story's own last frame.
  6. Three host-facing lengths - --fb-ftr-h, --fb-inset and --fb-pop-drop - in place of hard-coded offsets, so the mark lines up with a page's own gutter and the open panel overlaps a footer rather than balancing on top of it.
  7. No scrim. A draft of this integration dimmed the whole portal while the panel was open; a credit line should not read like a modal, and opening it now changes nothing behind it.
  8. About us points at https://freva-org.github.io/.
  9. Three mark layers instead of two, and the resting state is a state. A host can lend the badge an animated mark through FrevaBadgeOptions.liveMark; that is what shows when nobody has touched the badge. Upstream had a one-way door - once the story sheet loaded, the still was hidden for good and the sheet's last frame became the mark - so the story could only ever be the resting state. Now the sheet is shown while the story runs and put away when the bird has landed, and the mark goes back to living. A reduced-motion visitor is never shown either: they keep the package's own still.
  10. --fb-mark-lift, so the disc can stand on the page's bottom edge instead of floating 20px above it. The artwork carries about 3px of clear space below it inside the 158x63 box, which is why the portal sets -3px.
  11. The organisation strip carries real marks: each chip is a link when the organisation has a home, the slot is a white tile rather than a translucent one - most of these logos are dark navy and 20% white over a dark blue panel showed nothing - and the tile is larger, at the cost of tightening the strip's own margins so the panel's copy keeps its air. The duplicate group that makes the marquee seamless stays aria-hidden and unlinked, so nothing is announced or tabbed twice.