Implementing unfurling URLs in Sanity
Want to add those nice-looking link previews you get when you share a link on Medium or Twitter? Then this article is for you!
The concept of unfurling links – that is, showing a link with a preview image, the title of the page and a short description – is becoming a pretty popular feature on lots of sites these days. But how can you add it to your Sanity blog?
In this article, we will show you a quick and easy way to add this neat little feature in no time at all!
Create a custom block type
First, we need to add a new custom type to our document schema. It's pretty straight forward - with a single URL prop:
export default {
type: "object",
name: "unfurledUrl",
title: "Unfurled URL",
fields: [
{
name: "url",
type: "url",
description: "The URL to unfurl",
validation: (Rule) => Rule.required(),
},
],
};
Next, you need to add this to your block type field (like the content field of your blog post type):
// Example
const portableTextSchema = {
name: "portableText",
type: "array",
title: "Post body",
of: [
{ type: 'block' },
{ type: "unfurledUrl", icon: FiLink2 },
]
}
You can now add links to your content - but they won't show up like they should just yet.
Adding OpenGraph Ninja
Unfurling URLs is pretty straight forward. You make a request to the page, parse the response, and select some of the metadata tags. Some pages add something called "open graph" metadata, which makes these previews even better!
We could implement this ourselves, but let's just use a small service that does this for us - OpenGraph Ninja. Hei
Full disclosure – I made and maintain OpenGraph Ninja – so I'm obviously super biased over how great this tool is. But give it a try before you discard it completely!
OpenGraph Ninja even comes with a handy ready-made React library, which makes using this service a breeze. Let's start using it right inside of Sanity!
Navigate to your studio, and install the OpenGraph Ninja dependency:
npm install @opengraphninja/react
Next, let's add a preview component to our unfurl schema definition!
import { PreviewLink } from "@opengraphninja/react";
import "@opengraphninja/react/styles.css?raw";
export default {
type: "object",
name: "unfurledUrl",
title: "Unfurled URL",
fields: [
{
name: "url",
type: "url",
description: "The URL to unfurl",
validation: (Rule) => Rule.required(),
},
],
preview: {
select: {
href: "url",
},
component: (props) => (
<PreviewLink href={props.value.href} />
),
},
};
That's a few changes, so let's go through them one by one. First we import the PreviewLink component and its required CSS styles. You can of course write your own styles if you want, but let's leave that as an exercise to the reader.
Oh, and note that you have to add ?raw to the end of the style import - that's a Sanity-specific thing you can read more about here.
We've also added a preview
section, where we pass in the preview component, and pass in the url as a prop. Now we get a real nice-looking preview in our editor, too!
Showing it to our users
Unfortunately, even with all this work, our users won't know a thing – so let's add some support for our new custom unfurler.
Now, this next part depends on what kind of technology you're using on your end. In this guide, we'll assume you're using the @sanity/block-content-to-react
package. Let's visit your imaginary features/PortableText.jsx
file:
import React from 'react';
import { BlockContent } from '@sanity/block-content-to-react';
import { PreviewLink } from '@opengraphninja/react';
import '@opengraphninja/react/styles.css';
const serializers = {
// your other serializers
unfurledUrl: (props) => (
<PreviewLink href={props.node.url} />
)
};
export const PortableText = (props) => {
return (
<BlockContent
blocks={props.blocks}
serializers={serializers}
/>
);
}
All we're really adding here, is the way we deserialize the unfurledUrl
content type. We're using the same preview component here, but you might want to create your own implementation with the provided usePreviewData
hook instead.
Either way, the result is sure to look amazing. Here's a link to bekk.christmas:
Improve your own links!
Now you've seen the quick and easy way to implement unfurling of links. We cheated a bit, by using a (free) service and its provided React SDK, but you can implement something pretty similar yourself if you have the time.
This article was actually written while implementing this functionality for this website, so rest assured it's built on real world experience!
I hope you enjoyed this article - and if you did, give opengraph.ninja a chance!