Help us shape the future of Go! Take the 2026 Go Developer Survey

embisto

package module
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Oct 20, 2026 License: MIT Imports: 16 Imported by: 0

README

embisto

Link previews you host yourself. Give embisto a URL; get the title, description, image, icon and player a client needs to draw a card.

CI Go Reference

The card above is embisto's own format=html, ready for an iframe or an email.

Quickstart

Run the server and ask it about a page:

docker run --rm -p 8080:8080 ghcr.io/pantafive/embisto:main
curl 'localhost:8080/v1/preview?url=https://go.dev/blog/'
{
  "url": "https://go.dev/blog/",
  "canonical_url": "https://go.dev/blog/",
  "type": "link",
  "title": "The Go Blog - The Go Programming Language",
  "icon": {"url": "https://go.dev/images/favicon-gopher-plain.png", "width": 180, "height": 180},
  "image": {"url": "https://go.dev/doc/gopher/gopher5logo.jpg", "width": 1262, "height": 733},
  "sources": ["opengraph", "twitter", "html"]
}

Shortened: the full card also lists every picture and link the page names. See the HTTP API.

Or use it as a Go library:

go get github.com/pantafive/embisto
core := embisto.New(embisto.Defaults())

result, err := core.Extract(ctx, card.Request{URL: "https://go.dev/blog/"})
if err != nil {
	log.Fatal(card.CodeOf(err)) // invalid_url, blocked_url, fetch_failed, timeout, not_found, …
}
fmt.Println(result.Preview.Title)

Features

  • Reads what pages say: oEmbed, Open Graph, Twitter Cards, JSON-LD and plain HTML, merged field by field.
  • Knows the hard sites: YouTube, X, Reddit and TikTok providers, honest cards for login walls, and every site on the oembed.com list.
  • Answers in the format you need: the JSON card, plain text, a self-contained HTML card, Iframely-compatible /iframely and /oembed, or your own template.
  • Serves thumbnails: signed, resized JPEG, PNG and WebP copies of a card's pictures, so clients never load them from other sites (details).
  • Caches by the origin's rules: keeps a card as long as its page allows, makes one fetch for many identical requests, and shares the cache between instances through Redis or Valkey.
  • Safe with URLs from strangers: refuses private addresses at connect time, and caps sizes, time and memory (details). It has no API keys or rate limits of its own; a public instance needs them in front of it.
  • Easy to run: a single static binary or a multi-arch image, Prometheus metrics, OpenAPI at /openapi.json with a reference at /docs, and a debug page that shows how a card was made.

Documentation

These pages describe main, which can be ahead of the latest release: CHANGELOG.md lists what is not released yet, and a release's own pages are in its tag.

License

MIT © Mikhail Solomenik

The binary also holds Go's standard library, the modules embisto imports and the oembed.com provider list. Their notices are in THIRD_PARTY_NOTICES, next to the binary in a release archive and in /usr/share/doc/embisto/ in the image; go run ./scripts/notices writes them for a checkout.

Documentation

Overview

Package embisto turns a URL into the data for a link preview: title, description, image, icon, video and the provider's embed HTML.

A preview goes through a fixed pipeline: fetch the page, run the generic sources over it, ask the site provider that knows its address, merge their facts field by field, enrich the result. New builds the pipeline from Options, which start from Defaults. The Core it returns is a card.Extractor, as is every layer around it, such as the cache in package cache, so layers stack in any order:

core := embisto.New(embisto.Defaults())
previews := cache.New(core, cache.NewMemory(64<<20, nil), cache.Options{TTL: time.Hour, FailureTTL: time.Minute})
result, err := previews.Extract(ctx, card.Request{URL: "https://github.com"})

The modules of each stage are in their own packages: site providers in sites, output formats in render, with Iframely's shapes in iframely, and thumbnails in thumbnails. The contract they share is package card.

Index

Constants

This section is empty.

Variables

View Source
var Version = versionOf(release, debug.ReadBuildInfo)

Version is the library's release, without its v: the one the build stamped with -ldflags "-X github.com/pantafive/embisto.release=…", else the module's version in the build, else devel.

Functions

func NewFetcher

func NewFetcher(opts Options) card.Fetcher

NewFetcher is the client the options configure, which refuses addresses that are not public; a fetcher of your own can wrap it, such as to record or to route through a proxy.

Types

type Core

type Core struct {
	// contains filtered or unexported fields
}

Core is the pipeline. It keeps nothing between previews but what Options.HomePages stores.

func New

func New(opts Options) *Core

New builds the pipeline.

func (*Core) Extract

func (c *Core) Extract(ctx context.Context, req card.Request) (card.Result, error)

Extract makes the preview of the request's URL. It fails with a *card.Error, or with the context's error when the caller gave up; a module that panics fails its preview as internal, never the program.

func (*Core) Purge

func (c *Core) Purge(ctx context.Context, req card.Request) (int, error)

Purge forgets what the core remembers of the URL's site: what its home page says.

type Observer

type Observer interface {
	// Fetched is one request a stage made, with its outcome: ok, a card code, or canceled. The stage is page, or the
	// name of the source, provider or enricher that asked.
	Fetched(stage, outcome string, took time.Duration)
	// Matched is a provider asked about a URL it knows.
	Matched(provider string)
	// Made is a card made afresh, with its class (full, partial, minimal, wall or error) and the provider that shaped
	// it, or generic.
	Made(class, source string)
}

Observer hears what the pipeline does, for metrics. It is told names and codes, never URLs.

type Options

type Options struct {
	// Timeout bounds one preview, every request it makes included.
	Timeout time.Duration
	// MaxBodySize is the most bytes read of one response; a larger one fails with too_large.
	MaxBodySize  int64
	MaxRedirects int
	UserAgent    string
	// DefaultAcceptLanguage is the Accept-Language a page is asked in, unless a request names its own language; sites
	// otherwise answer in the language of wherever the server runs.
	DefaultAcceptLanguage string
	// AllowedNetworks are reachable although not public, for a deployment that previews its own intranet.
	AllowedNetworks []netip.Prefix
	// Fetcher replaces the client the fields above configure, and with it the guard against non-public addresses.
	Fetcher card.Fetcher
	Sources []card.Source
	// HomePages remembers what each site's home page says, so that a description or a picture a site puts on every
	// page is not taken for one page's own. Nil reads no home page. A store shared between instances shares what
	// they learn; purging a URL forgets its site.
	HomePages cache.Store
	// Providers know particular sites and are asked first, in order: the first that knows a URL is the only one asked.
	Providers []card.Provider
	// Fallbacks are asked only about a URL no provider knows, such as the provider for every site on the oEmbed
	// list; so a provider added to Providers always wins over them.
	Fallbacks []card.Provider
	Enrichers []card.Enricher
	// Log hears about sources and providers that failed; the preview goes on without them. Nil logs nothing.
	Log *slog.Logger
	// Observer hears what the pipeline does, for metrics; nil hears nothing.
	Observer Observer
}

Options configure the pipeline. A zero number takes its default; a nil list takes the default modules, an empty one runs none.

func Defaults

func Defaults() Options

Defaults are the options embisto ships with; the home pages are kept in this process's memory.

Directories

Path Synopsis
Package cache keeps previews: a layer around any card.Extractor, and the stores it keeps them in, in the process or shared between instances through Redis.
Package cache keeps previews: a layer around any card.Extractor, and the stores it keeps them in, in the process or shared between instances through Redis.
Package card is the contract between embisto and its modules: the preview a client draws, the parsed page, the facts a source finds on it, and the interfaces of every stage of the pipeline.
Package card is the contract between embisto and its modules: the preview a client draws, the parsed page, the facts a source finds on it, and the interfaces of every stage of the pipeline.
cmd
embisto command
Command embisto serves link previews over HTTP.
Command embisto serves link previews over HTTP.
Package docs carries embisto's documentation, so a site can render the pages of the version it builds against.
Package docs carries embisto's documentation, so a site can render the pages of the version it builds against.
Package iframely answers in the formats of Iframely's API, so a client of Iframely can switch to embisto by changing the address: the response with links grouped by rel, and the shape of a failure.
Package iframely answers in the formats of Iframely's API, so a client of Iframely can switch to embisto by changing the address: the response with links grouped by rel, and the shape of a failure.
internal
api
Package api is the HTTP surface of the library: huma routes, the problem+json error shape and request ids.
Package api is the HTTP surface of the library: huma routes, the problem+json error shape and request ids.
assemble
Package assemble merges what the sources found into one preview, field by field, by a table of priorities.
Package assemble merges what the sources found into one preview, field by field, by a table of priorities.
debug
Package debug serves a page that shows how a preview was made: the card, every fetch, source, provider and enricher with its time and outcome, which source won each field and why, and the card's thumbnails.
Package debug serves a page that shows how a preview was made: the card, every fetch, source, provider and enricher with its time and outcome, which source won each field and why, and the card's thumbnails.
fetch
Package fetch is the only code that goes to the network: an HTTP client that refuses addresses which are not public, checked on every connection it opens, so neither a redirect nor a DNS answer that changes between lookups reaches the host's own network.
Package fetch is the only code that goes to the network: an HTTP client that refuses addresses which are not public, checked on every connection it opens, so neither a redirect nor a DNS answer that changes between lookups reaches the host's own network.
fixture
Package fixture records what a preview fetched and replays it without the network, so a page saved once stays a test of the whole pipeline.
Package fixture records what a preview fetched and replays it without the network, so a page saved once stays a test of the whole pipeline.
homepage
Package homepage learns what a site says of every page from what its home page says: a description or a picture the home page shares with an item's page is the site's, not the item's.
Package homepage learns what a site says of every page from what its home page says: a description or a picture the home page shares with an item's page is the site's, not the item's.
imagesize
Package imagesize measures a preview's pictures from the first bytes of their files, so a client can lay a card out before the pictures arrive.
Package imagesize measures a preview's pictures from the first bytes of their files, so a client can lay a card out before the pictures arrive.
jpegheader
Package jpegheader reads what a JPEG's markers state before its first scan, beyond the size image.DecodeConfig gives: how the frame is coded, and which way up the picture is shown.
Package jpegheader reads what a JPEG's markers state before its first scan, beyond the size image.DecodeConfig gives: how the frame is coded, and which way up the picture is shown.
logging
Package logging writes JSON logs through slog and carries per-request attributes on the context.
Package logging writes JSON logs through slog and carries per-request attributes on the context.
metrics
Package metrics counts what the server does for Prometheus.
Package metrics counts what the server does for Prometheus.
oembed
Package oembed reads oEmbed: the endpoint a page links to, or the one the oembed.com provider list names for a URL.
Package oembed reads oEmbed: the endpoint a page links to, or the one the oembed.com provider list names for a URL.
page
Package page reads a fetched HTML page into a card.Page, and tells a wall from the item it stands in for.
Package page reads a fetched HTML page into a card.Page, and tells a wall from the item it stands in for.
pipeline
Package pipeline makes a preview: fetch the page, run the generic sources over it, ask the site provider that knows it, merge their facts, enrich the result.
Package pipeline makes a preview: fetch the page, run the generic sources over it, ask the site provider that knows it, merge their facts, enrich the result.
quality
Package quality classes a card by how good it came out, from the client's side.
Package quality classes a card by how good it came out, from the client's side.
settings
Package settings reads the server's configuration from the environment.
Package settings reads the server's configuration from the environment.
sources
Package sources holds the generic sources, which read any page whatever its site: Open Graph, Twitter Cards, plain HTML and JSON-LD.
Package sources holds the generic sources, which read any page whatever its site: Open Graph, Twitter Cards, plain HTML and JSON-LD.
target
Package target reads the URL and language of a request as the pipeline does, so that a cache keys equal requests written differently alike.
Package target reads the URL and language of a request as the pipeline does, so that a cache keys equal requests written differently alike.
trace
Package trace records what the pipeline did for one preview, step by step, for the debug page.
Package trace records what the pipeline did for one preview, step by step, for the debug page.
valkeytest
Package valkeytest starts a Valkey container for tests of the shared cache.
Package valkeytest starts a Valkey container for tests of the shared cache.
Package render holds the output formats a preview is written in.
Package render holds the output formats a preview is written in.
scripts
iframely-compare command
Command iframely-compare asks a running Iframely and a running embisto about the same URLs and reports where their answers differ in status, in the fields they carry, in the groups of their links and in their meta values.
Command iframely-compare asks a running Iframely and a running embisto about the same URLs and reports where their answers differ in status, in the fields they carry, in the groups of their links and in their meta values.
notices command
Command notices writes the license notices of the code built into embisto's server besides its own: the Go standard library's, each linked module's, and the NOTICE an embisto package keeps for a file it embeds from others.
Command notices writes the license notices of the code built into embisto's server besides its own: the Go standard library's, each linked module's, and the NOTICE an embisto package keeps for a file it embeds from others.
Package sites holds the site providers: each knows one site, or a family of them, and outranks the generic sources there.
Package sites holds the site providers: each knows one site, or a family of them, and outranks the generic sources there.
Package thumbnails serves the pictures of a preview through embisto, resized and re-encoded: sources that expire or refuse hotlinking stay viewable, clients never reveal their address to other sites and download no more pixels than they show.
Package thumbnails serves the pictures of a preview through embisto, resized and re-encoded: sources that expire or refuse hotlinking stay viewable, clients never reveal their address to other sites and download no more pixels than they show.

Jump to

Keyboard shortcuts

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