ogimage

package
v0.2.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 3, 2026 License: AGPL-3.0 Imports: 18 Imported by: 0

Documentation

Overview

Package ogimage renders the Open Graph preview card for a published usage overview: a 1200x630 PNG a link unfurler (Slack, Discord, iMessage, and the like) shows when someone shares a /u/<username> link. It is a self-contained, pure-Go raster render in the house style (the machinist's bench: a deep violet-graphite ground, a lilac activity grid, and machined mono figures), so the binary stays free of a headless browser or any Node toolchain.

The card carries a simplified copy of the overview's activity heatmap (the same trailing-year calendar of daily token intensity, drawn as flat lilac cells), plus the two headline figures a shared link most wants to convey: the total tokens and the session count over the default window.

Index

Constants

View Source
const (
	LandingHeadline = "Know what your agents actually did."
	LandingSubline  = "Every Claude Code, Codex, and pi session in one searchable, priced history."
)

LandingHeadline and LandingSubline are the canonical homepage copy, written down once here. The card draws them, and the httpapi root handler builds the landing page's og:title and og:description from them, so those surfaces follow a copy edit by construction. The templ hero (landing.templ) cannot import this package from a template, so a reconciliation test in the web package pins its h1 to LandingHeadline instead: an edit that lands in only one place fails that test rather than shipping a homepage, meta tags, and preview card that say different things.

View Source
const (
	Width  = 1200
	Height = 630
)

The card is the standard Open Graph size. 1200x630 (1.91:1) is what every major unfurler crops to, so rendering at that exact size avoids a re-crop that would clip the grid or the figures.

Variables

View Source
var ErrReparseInProgress = errors.New("ogimage: reparse in progress, skipping render")

ErrReparseInProgress is returned by Generate when a reparse is (or was) running across its analytics read, so no card is stored. It is a skip, not a failure: the image handler serves the last good card if it holds one, else 404s, and a fetch after the reparse finishes renders the card once the projection is whole.

Functions

func DefaultSince

func DefaultSince(now time.Time) time.Time

DefaultSince is the lower bound of the card's analytics window, measured back from now. It is deliberately identical to web.RangeSince(web.DefaultRange, now) (the public overview's default trailing-year window), so the card's figures reconcile exactly with the page a visitor lands on. The web view package is not imported here (the renderer stays free of the templ layer); the equality is pinned by a reconciliation test in the httpapi package, which imports both. The handler advertises the card only on that same default window, so a page shown under a narrower ?range never unfurls a mismatched year total.

func DefaultUntil

func DefaultUntil(now time.Time) time.Time

DefaultUntil is the exclusive upper bound of the card's analytics window: the start of tomorrow (UTC), so the figures cover exactly the days the heatmap draws (the grid stops at today) and a future-dated event inflates neither. The public overview handler applies the same bound to its live analytics, so the page a card is advertised beside computes its totals over the identical window.

func Generate

func Generate(ctx context.Context, st *store.Store, u store.User, now time.Time) ([]byte, error)

Generate renders the preview card for one account's published overview, stores it in the cache, and returns the encoded PNG so the caller can serve the very bytes it just rendered without a second read. It queries the same windowed, user-scoped analytics the public page renders from, so the card's heatmap and figures match the page. It is the one render+store path the on-demand image handler goes through (on a cache miss or a stale card), so a cached card and a freshly served one cannot drift.

The analytics come from AnalyticsSnapshot, which reads them as a single consistent snapshot pinned so it cannot straddle a reparse: if a reparse is rewriting the projection when the snapshot is taken, it reports not-ok and Generate returns ErrReparseInProgress without storing anything, so a half-rebuilt aggregate is never cached. Coordinating in the store read (rather than a pre-check in the caller) keeps the on-demand path correct by construction. The image handler then serves the last good card if it holds one, and a later fetch renders the card once the projection is whole.

The window is bounded on both sides: Since is the default trailing year, and Until is the end of the current UTC day, so the headline and caption cover exactly the days the heatmap draws (the grid stops at today) rather than folding a future-dated event into the total that no visible cell shows.

now fixes the analytics window and the heatmap's trailing edge; the caller passes the wall clock (tests pass a fixed instant).

func Landing added in v0.2.3

func Landing() ([]byte, error)

Landing renders the homepage preview card and returns the encoded PNG. It is memoized: the card is static per binary, so the first call renders and every later call returns the same bytes with no rework. The error is memoized too, so a font-load failure surfaces on every call rather than being retried.

func Render

func Render(username string, a store.Analytics, now time.Time) ([]byte, error)

Render draws the overview card for one account and returns the encoded PNG. The heatmap and the two figures are scoped to whatever the analytics carry (the caller queries the default trailing-year window, so the card matches the page a visitor first lands on). now fixes the grid's trailing edge, injected so the render is deterministic under test.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL