A Link Preview Component for SvelteKit (Part 1)
TL;DR of this article
One of the glories of the Hypertextual medium is the ability to enrich one's messages with links. Indeed, Hyperlinks (to give their proper address) to websites, images, video and such are the very fabric of the Internet, although not without drawbacks.
Sometimes, links may lead to content a reader is already familiar with, or does not wish to consume, and as such it is not surprising that one might wish to provide a preview of the object to which a link pertains.
Sadly, this is not a native faculty possessed by The Internet at large, which may surprise given the common appearance of previews in apps such as Slack:
How, then, are link previews generated?
You might suppose the process involves using a headless browser to take screenshots, or interrogating the HTML to guess the details. Thankfully, this is not the case; often, the required information is supplied via the Open Graph Protocol which
enables any web page to become a rich object in a social graph.
A simple, dependency-free protocol defined under the Open Web Foundation Agreement, Version 0.9, the Open Graph Protocol (henceforth the OGP) allows page authors to mark up specific metadata to help other sites provide information about the linked content.
This, I'm sure you'll agree, is much easier then finangeling a headless browser. Let us make use of it!
The makeup of the Metadata
The OGP is a fairly simple affair, relying on <meta>
tags embedded into the <head>
tag of a response. Which is appropriate, as this is indeed what said tag is for.
<head>
tag is, confusingly, part of the body of a HTTP response.Open Graph describes resources as objects and provides some common properties from which to obtain information. Each property name starts with og:
to indicate it belongs to the Open Graph namespace. Four properties are required, and seven are considered optional (but generally recommended).
Required Properties
og:title
has the object's title as it should be displayed when embedded.og:type
details what type of object this page contains (such as website
or image
).og:image
is a URL to an image which should be used as part of the preview.og:url
provides the canonical URL for the object in question.
This is what the Required Properties might look like for a site detailing Professor Eliza Williams' research into Difference Engine Temperature Compensators:
Optional Properties
Provisions are also made for additional information; Knowledge is Power after all.
og:description
is a one-to-two sentence description of the object in question.og:site_name
gives the name of the larger website an object belongs to, if any.og:locale
indicates which linguistic locale the tags are marked up in.og:locale_alternate
offers an array of other locales available.og:determiner
supplies the word which should fall before this object's title in a sentence ("the", "an" et al).
og:audio
provides a URL to an audio file to 'accompany' this object.og:video
advises a URL to a video file that 'complements' the object.
(Mostly straightforward, although you might be curious why audio files accompany but video files complement, and what, precisely, those verbs are intended to convey. I am also curious; if you know, I beseech you to leave a comment.)
Professor Eliza is a Modern Woman, so her site includes all of the above:
og:locale_alternate
. This is how arrays of data are encoded in the Open Graph protocol. You may find this odd; I agree. And yet.Further Types of Object
The website
type is perhaps the most common object embedded with the OGP, but the protocol includes many other object. These objects, in turn, have their own structured properties, namespaced as og:type_of_object
. For instance, the image
type makes the dimensions of an image available as og:image:width
and og:image:height
.
The full list is available at the source; We shaln't discuss it here in the interests of brevity.
So what shall we build?
Let us build a link preview component for SvelteKit which takes a URL and renders for us a lovely preview of the associated content, using the OGP metadata embedded therein.
For ease of use, we shall use TypeScript to help ensure correct data management. The completed component should be pleasing to the eye and behave well different resolutions.
We shall, at first, restrict ourselves to displaying only the basic metadata; Whilst the support for extra content types is robust, we do not, for the first attempt, need the extra complexity.
We shall also make an assumption which, while unkind, is not unfair. Developers are only human and may, at times, make mistakes, causing them to omit some or all of the required fields. As such, our component will not assume that the provided metadata is correct.
Our Requirements are thus:
Display the basic image along with the title, and provide a link to the canonical URL
Exhibit a responsive, fetching design
Allow for incorrect metadata
Provide developer friendly interface, inc. Typescript.
In future entries, we shall endevour to provide more useful default behaviour; enrich our support for divers content types, and package our component as an installable library which can be distributed at will. Such fancies, however, shall have to wait; For now, our target is a component that will look like the following when used in situ:
That looks rather fetching, don't you think?
Getting Ready.
To begin, I've created a basic SvelteKit site posessing an assortment of pages, each professing a different kind of OpenGraph object. The site uses images from UnSplash as preview images and is otherwise fairly unremarkable.
Having said that, the index will serve as a gallery showing how the finished component will render for diverse types, so it may prove of some interest. You can find it at https://ogcomponentdemo.gentlehacker.codes/ and the source lives at https://github.com/DylanLacey/OGComponentDemo.
Onwards!
In my next missive, we shall implement the basis of our component, and briefly discuss the correct architecture of SvelteKit applications.
Subscribe to my newsletter
Read articles from Dylan Lacey directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Dylan Lacey
Dylan Lacey
I'm a professional Software Developer and Developer Relations Manager. My first love will always be Ruby but I'm writing a lot of JavaScript these days. I specialise in Automated Testing and work at Sauce Labs. I truely believe that crafting Software is how I can best make the world better for its inhabitants, and I love educating and mentoring folks to who'd like to do the same.