79
loading...
This website collects cookies to deliver better user experience
target
URL with your own blog post):https://webmention.io/api/mentions.json?target=https://bionicjulia.com/blog/creating-accordion-component-react-typescript-tailwind
links
which is an array of webmentions.{
"links": [
{
"source": "https://brid.gy/repost/twitter/bionicjulia/1396870759675580420/1396870781737619459",
"verified": true,
"verified_date": "2021-06-25T11:26:00+00:00",
"id": 1201134,
"private": false,
"data": {
"author": {
"name": "The Developer Bot",
"url": "https://twitter.com/TheDeveloperBot",
"photo": "https://webmention.io/avatar/pbs.twimg.com/6b9fb9e6c61bfc2e2bf7b938a6720320c16528b25776a2c6ef87915f460fafc6.jpg"
},
"url": "https://twitter.com/TheDeveloperBot/status/1396870781737619459",
"name": null,
"content": "Wrote a blog post on creating a simple accordion component in #reactjs , #typescript and #tailwindcss. 😃 bionicjulia.com/blog/creating-…",
"published": "2021-05-24T16:48:41+00:00",
"published_ts": 1621874921
},
"activity": {
"type": "repost",
"sentence": "The Developer Bot retweeted a tweet https://bionicjulia.com/blog/creating-accordion-component-react-typescript-tailwind",
"sentence_html": "<a href=\"https://twitter.com/TheDeveloperBot\">The Developer Bot</a> retweeted a tweet <a href=\"https://bionicjulia.com/blog/creating-accordion-component-react-typescript-tailwind\">https://bionicjulia.com/blog/creating-accordion-component-react-typescript-tailwind</a>"
},
"target": "https://bionicjulia.com/blog/creating-accordion-component-react-typescript-tailwind"
},
{
"source": "https://brid.gy/repost/twitter/bionicjulia/1396870759675580420/1396870783067058181",
"verified": true,
"verified_date": "2021-06-25T11:25:59+00:00",
"id": 1201132,
"private": false,
"data": {
"author": {
"name": "Friday",
"url": "https://twitter.com/friday_Js_bot",
"photo": "https://webmention.io/avatar/pbs.twimg.com/f5c85fab1b8b41ea6fd3aa9b13a371e45d5a82fbbc3e52e8dbb9ed34eeeeac0c.jpg"
},
"url": "https://twitter.com/friday_Js_bot/status/1396870783067058181",
"name": null,
"content": "Wrote a blog post on creating a simple accordion component in #reactjs , #typescript and #tailwindcss. 😃 bionicjulia.com/blog/creating-…",
"published": "2021-05-24T16:48:41+00:00",
"published_ts": 1621874921
},
"activity": {
"type": "repost",
"sentence": "Friday retweeted a tweet https://bionicjulia.com/blog/creating-accordion-component-react-typescript-tailwind",
"sentence_html": "<a href=\"https://twitter.com/friday_Js_bot\">Friday</a> retweeted a tweet <a href=\"https://bionicjulia.com/blog/creating-accordion-component-react-typescript-tailwind\">https://bionicjulia.com/blog/creating-accordion-component-react-typescript-tailwind</a>"
},
"target": "https://bionicjulia.com/blog/creating-accordion-component-react-typescript-tailwind"
}
//...
]
}
BlogLayout.tsx
. What I want upon this component mounting, is to call the webmention API, pull in the results in JSON format, and assign the results array to a variable. For this, I used the useEffect
and useState
hooks like so:const [mentions, setMentions] = useState<WebMention[]>()
useEffect(() => {
fetch(`https://webmention.io/api/mentions.json?target=https://bionicjulia.com/blog/${slug}`)
.then((response) => response.json())
.then((result) => {
setMentions(result.links)
})
}, [])
slug
. If you're new to NextJS and wondering how to access this parameter, check out my previous post on how I set up my blog Setting up a NextJS Markdown Blog with Typescript . The 1 minute summary is that within your blog post template ([slug].tsx
in my case), you need to pass params.slug
to the getStaticProps
method.WebMention
type.export type WebMention = {
source: string
verified: boolean
verified_date: string
private: boolean
data: {
author: {
name: string
url: string
photo: string
}
url: string
name: string
content: string
published: string
}
activity: {
type: 'link' | 'reply' | 'repost' | 'like'
sentence: string
sentence_html: string
}
target: string
}
BlogLayout.tsx
file, I added this bit of JSX to my return statement:<section>
<h2>Web Mentions</h2>
<p>Tweet about this post and have it show up here!</p>
{mentions?.map((mention) => (
<div className="flex">
<CustomLink href={mention.data.author.url} className="mr-2">
<Image
src={mention.data.author.photo}
alt={mention.data.author.name}
width={25}
height={25}
className="rounded-full border border-lightest-green bg-lightest-green"
/>
</CustomLink>
{(!mention.data.content || mention.activity.type === 'repost') && (
<p>
{mention.data.author.name}{' '}
<CustomLink href={mention.data.url}>{activityMap[mention.activity.type]}</CustomLink> this post.
</p>
)}
{mention.data.content && mention.activity.type !== 'repost' && <p>{mention.data.content}</p>}
</div>
))}
</section>
activityMap
was just my way of displaying the right verb for each activity type.const activityMap = {
link: 'linked to',
reply: 'replied to',
repost: 'retweeted',
like: 'favourited',
}
Image
component to render each webmention's author's picture. As this picture is hosted on webmention.io, I needed to explicitly tell NextJS that this was a recognised host. To do this, amend next.config.js
and add the following:images: {
domains: ['webmention.io'],
},