avatarEmil Hein

Summary

The context describes a process to create a portfolio from Medium posts using Vue 3 and Serverless.

Abstract

The context explains how to create a portfolio that displays Medium posts outside of Medium, which is not a trivial task but can be achieved. The process involves two main components: a reliable way of getting the post data for any given profile and a frontend to display a list of all the posts. The post data is retrieved using a mini-version of the Medium API that is created by wrapping the Medium API using Node.js. This API is deployed with the serverless framework, which provides an endpoint to retrieve all the posts. The frontend is created using Vue, where a store is used to fetch the data from the API and a component is used to display each post.

Bullet points

  • The goal is to create a portfolio that displays Medium posts outside of Medium.
  • The process involves two main components: getting the post data and creating a frontend to display the posts.
  • The post data is retrieved using a mini-version of the Medium API that is created by wrapping the Medium API using Node.js.
  • The mini-version of the Medium API is deployed with the serverless framework, which provides an endpoint to retrieve all the posts.
  • The frontend is created using Vue, where a store is used to fetch the data from the API.
  • A component is used to display each post, which includes the post's title, subtitle, tags, preview image, etc.
  • The full repo for the project can be found on GitHub.

Create a portfolio from your Medium posts — with Vue 3 and Serverless

Creating a portfolio that displays your medium posts outside of Medium is not trivial, but also not impossible. Let's see how we can do it

Portfolio page with Medium posts data

I’ve wanted to show my posts in a portfolio format outside of Medium for a long time. Now I have the time and here are the results. To make this work, we need two basic components.

  1. A reliable way of getting the post data for any given profile (MEDIUM-HARD)
  2. A frontend to display a list of all the posts. This is done in Vue, but any front end will do. (EASY)

1. The “Medium API”

Since the official Medium API does not provide an endpoint to retrieve all the basic information about one's posts, we have to be creative here. Looking through the Network tab I found that the Medium website is using a GraphQL endpoint to retrieve its data. Since all the information on a user's profile is public, I created a mini-version of the Medium API that can be used to get all the basic information about a user's posts. This is mainly the title, subtitle, tags, preview image, etc…

Wrapping the Medium API using Node.js ended up looking like this

This is deployed with the serverless framework, which gives me my endpoint to retrieve all my posts. The repo can be found here.

2. The front end

As the frontend framework I chose Vue, but it really could be anything. It’s a fairly simple project since all we have to do is get the data from our API and then display a list of all the data.

To fetch the data from our API in my Vue app, I chose to do it in the store (Pinia)

import { defineStore } from 'pinia'
import { ref } from 'vue'

export const usePostsStore = defineStore('posts', () => {
    const posts = ref([])
    const getPosts = async () => {
        const data = await fetch('https://iwa1uk4vy8.execute-api.us-east-1.amazonaws.com/dev/posts')
        const toJson = await data.json()
        console.log('Got ', toJson.length, ' posts');
        posts.value = toJson.sort((a, b) => b.firstPublishedAt - a.firstPublishedAt)
    }
    // Runs the very first time the store is used. i.e., when the store is initialized.
    getPosts()
    return { posts }
})

The component to show each post looks like this:

<template>
  <div class="card">
    <div class="card__header">
      <slot name="icon"></slot>
    </div>
    <div class="card__body">
      <h4>
        <slot name="heading"></slot>
      </h4>
      <p>
        <slot></slot>
      </p>
    </div>
    <div class="card__footer">
      <div class="user">
        <div class="user__info">
          <small>
            <slot name="length"></slot>
          </small>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
img {
  max-width: 100%;
  display: block;
  object-fit: cover;
}

.card {
  display: flex;
  flex-direction: column;
  width: clamp(20rem, calc(20rem + 2vw), 22rem);
  overflow: hidden;
  box-shadow: 0 0.1rem 1rem rgba(0, 0, 0, 0.1);
  border-radius: 1em;
  background: #ece9e6;
  background: linear-gradient(to right, #ffffff, #ece9e6);
}

.card:hover {
  transform: translateY(-5px) scale(1.005) translateZ(0);
  box-shadow: 0 24px 36px rgba(0, 0, 0, 0.11), 0 24px 46px var(--box-shadow-color);
  cursor: pointer;
}

.card__body {
  padding: 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.card__body h4 {
  font-size: 1.5rem;
  text-transform: capitalize;
}

.card__footer {
  display: flex;
  padding: 1rem;
  margin-top: auto;
}

.user {
  display: flex;
  gap: 0.5rem;
}

.user__image {
  border-radius: 50%;
}

.user__info > small {
  color: #666;
}
</style>

The full repo can be found here

Deployment

Deployment of the API is simple. Run the command sls deploy and, hurray! You have an endpoint!

Deployment of the frontend can also be fitted to your preferences. I chose to use my GitHub pages. All I have to do is build my project and deploy the result into my GitHub pages project.

Result here →

Example of the portfolio

Show your work

You might also like:

Stackademic

Thank you for reading until the end. Before you go:

Medium
API
Vuejs
Programming
Blog
Recommended from ReadMedium