Let's look at how the DEV.to API can be used to embed a list of your recent posts. We'll also sort them by their positive reactions! All it takes is a splash of client-side JavaScript. The API is not released yet, is not documented, and will likely change but I'll keep this post up to date.
Here's an test page which uses the tiny library we'll be writing. We'll be creating a plain list to keep things extendable. You can also skip straight to the repository to check out the final code.
How easy is the DEV API to use?
Easy. The articles route is https://dev.to/api/articles?username=$user
. Originally, I experimented with getting more than the latest 30 posts, which is the default. This can be done by adding &page=$pageNum
— but requesting multiple pages introduces a delay. Since it's impossible to know the number of pages of posts, you need to keep going until you hit an empty page. A late-loading list doesn't make for great UX.
Let's start by using the Fetch API to make a request from the user's browser.
fetch(`https://dev.to/api/articles?username=healeycodes`).then(function (response) {// Parse it as JSONreturn response.json();}).then(function (posts) {// An array of postsconsole.log(posts);})
Looking good. Let's neaten this up with some JSDoc comments so the code is more accessible. We'll also wrap it in a function.
/*** Get a DEV user's post objects.* Only fetches previously 30 posts. Using `&page=X` is too slow.* @param {string} username - DEV username, e.g. 'ben'.* @returns {array} User's post objects.*/function getPosts(username) {// Assume that `api` is defined as a constantreturn fetch(`${api}/articles?username=${username}`).then(function (response) {return response.json();}).then(function (posts) {// Sort the array in place with a compare functionreturn posts.sort((a, b) => b.positive_reactions_count - a.positive_reactions_count);});}
A list of 30 posts is maybe a bit much. We'll cut it down later. For now, notice how we sorted the array in place with a compareFunction. We used a shorthand version. Compare functions are typically written by returning -1
, 1
, or 0
when comparing the two parameters. However, all that matters is that the compare function is consistent.
We want to create a simple list that can be styled with CSS. Sensible class names might be dev-feed-list
and dev-feed-item
. We'll need an element to attach this list to as well so that should be an argument that our library takes. With JavaScript, we can add classes, and create lists and attach them on the fly like this:
// An unordered listconst list = document.createElement('ul');// A list itemconst item = document.createElement('li');item.classList.add('dev-feed-item');item.innerText = 'I am a list item.';// Let's create a relation between themlist.appendChild(item);// Now between the list and the document, rendering the list// body -> ul -> lidocument.body.appendChild(list);
Let's create a function that builds the elements that will make up our embedded list. We'll use the getPosts
function from earlier to get our sorted array of posts.
/*** Creates a DEV feed of posts.* @constructor* @param {Element} elem - Place list of posts inside this element.* @param {string} username - DEV username, e.g. 'ben'.* @param {number} numberOfPosts - Number of posts to list.*/function createFeed(elem, username, numberOfPosts = 5) {const feed = document.createElement('ul');feed.classList.add('dev-feed-list');getPosts(username)// With our posts array.then(function (posts) {posts.length = numberOfPosts;posts.forEach(function (post) {// We create an element for each itemconst item = document.createElement('li');item.classList.add('dev-feed-item');// As well as a link for users to click throughconst link = document.createElement('a');link.href = post.url;link.innerText = post.title;// ul -> li -> aitem.appendChild(link);feed.appendChild(item);});// Attach the list of posts, rendering itelem.appendChild(feed);});}
If we bundle this all together as a script, we can generate lists by calling createFeed(element, username, numberOfPosts)
where element
is the container for the list and username
is a valid DEV user, and numberOfPosts
is the number of posts we want to render.
By allowing a custom number of posts to be fetched, as well as using sensible CSS classes, our library is extensible and can be used as a tiny module!