Automate TL;DR posts on X using Hashnode Webhooks and Vercel AI
6 min read
AI has fascinated us since last year, and as developers, we have been using it to automate or simplify tasks that would otherwise take up a lot of our time.
In this article, we will learn how to generate a summary of the technical articles you write on Hashnode, and post it on X.
We covered this in a live webinar. If you prefer a video format, head over to our YouTube channel:
Technologies that will be used to build the solution:
What are Webhooks?
A webhook is a way to automate responses in software. They’re like "event-based APIs." This means when something happens, like a new post created or a specific action, the webhook triggers a response as it’s set up to do. Webhooks are great for real-time communication and can activate actions in other applications based on certain events.
Hashnode's webhook feature lets you get instant notifications for specific events related to your publication. You can set up webhooks to watch for six main events:
Post published
Post deleted
Post updated
Static page published
Static page edited
Static page deleted
Getting started
The application flow is simple: Hashnode webhook fetches article details, sends them to Vercel’s AI SDK to summarize and generate a TL;DR, and then posts it using the X API.
Step 1: Fetching posts from Hashnode
Before we move on to fetching posts from Hashnode, you need to add a webhook and you can do that from the blog dashboard.
The video below shows how you can add it:
Fill in the following details:
Endpoint URL: Should look something like
https://example.com/path
Events: Check the
post_published
box.Secret: Keep it copied, as we will need it for the next steps.
Note: Make sure to create an.env.local
file. You can copy the keys from .env.example file and add the values.
The next step is to write handler for the webhook and verify it.
Why you need to verify your webhooks?
Webhooks are simply REST APIs deployed on your server, making them public. You only want these endpoints to be called by Hashnode when an event like post_published
occurs. You definitely don't want anyone else to call the webhook endpoint and publish a tweet on your behalf.
Every webhook you create comes with a webhook secret that you copied above. Hashnode sends the payload signed with a secret and also send the resulting signature in the headers of the request sent to your webhook endpoint.
To verify your signature, you need to write some logic, and we've got you covered! Click on the link that says Learn how it works, and copy the code block that starts with import crypto from 'crypto';
. You will need to install the crypto
npm package for this to work.
This code comes with a validateSignature
function that can be used like this
const payload = await req.json();
// This is sent by hashnode with header
const signature = req.headers.get('x-hashnode-signature');
// The secret you copied
const webhookSecret = process.env.HASHNODE_WEBHOOK_SECRET;
const { isValid } = validateSignature({
incomingSignatureHeader: signature,
secret: webhookSignature,
});
Now if isValid
is false you can return a 401 Unauthorized
. If true
you can proceed.
Once the webhook is created, we write the code that fetches the post using Hashnode’s GraphQL APIs 👇
export const getPostById = async (postId: string) => {
const response = await fetch('https://gql.hashnode.com', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.HASHNODE_ACCESS_TOKEN}`,
},
body: JSON.stringify({
query: `
query GetPostById {
post(id: "${postId}") {
id
title
url
content {
markdown
}
}
}
`,
})
})
const data = await response.json();
return data.data.post;
}
The getPostById
function sends a POST request to Hashnode's GraphQL API to fetch details of a post by its postId
, including the title, URL, and markdown content. It returns the post data as a JSON object after handling the response.
Step 2: Summarise the fetched article
Now that we have fetched the article details, the next step is to create a summary for it, and for that we will be using the Vercel AI SDK.
First, you need to generate an OpenAI API key and add it to your .env
file.
Then, use the following code to generate the summary:
import { openai } from '@ai-sdk/openai';
import { generateText } from 'ai';
export const generateTLDR = async (content: string) => {
try {
const { text } = await generateText({
model: openai('gpt-4-turbo'),
prompt: `Summarize this article in a concise, engaging TLDR suitable for a tweet. Article content: ${content}`,
temperature: 0.7, // Adjust for creativity; lower values make the output more deterministic
});
return { text: text.trim() };
} catch (error) {
console.error('Exception caught while generating TLDR:', error);
return { error: 'Exception occurred during TLDR generation. Please try again.' } ;
}
}
The generateTLDR
function send the prompt to OpenAI to summarize a given article. The prompt specifically requests a concise and engaging TLDR suitable for a tweet, using the provided article content.
Step 3: Post the generated summary on X
The final step is to use the summary generated by OpenAI to create a post on X.
First, create a Developer account on the X developer platform. Then, create a project and within that project, create an app for free. After creating the app, generate and copy the keys and tokens.
Once that is done, move to your IDE and write the code below to make a post on X:
import { TwitterApi } from 'twitter-api-v2';
const client = new TwitterApi({
appKey: process.env.X_API_KEY!,
appSecret: process.env.X_API_KEY_SECRET!,
accessToken: process.env.X_ACCESS_TOKEN!,
accessSecret: process.env.X_ACCESS_TOKEN_SECRET!,
});
export const tweetThread = async (content: string, postUrl: string) => {
try {
const tweets = [
content,
`Here is the link to the post: ${postUrl}`
];
const response = await client.v2.tweetThread(tweets);
return { success: true, data: response };
} catch (error) {
console.error('Failed to tweet thread:', error);
return { success: false, error: 'Failed to tweet thread. Please check the logs for more details.' };
}
}
We initialize the X API client and define the tweetThread
function, which takes the summary and a post URL as parameters. This function creates a tweet thread containing the summary from the generateTLDR
function (that we generated in Step 2) and a link to the original post (that is fetched in Step 1), then posts it to X.
Resources
With that, you can see how to easily create a workflow using AI and webhooks to help you make social media posts from your articles.
Here are some resources to help you learn more: