Criando uma página pessoal com a API do dev.to e VueJS
Salustiano Muniz
Posted on September 2, 2022
Estava há muito tempo querendo fazer uma página pessoal pra usar de portifólio e também como blog de tecnologia, e depois de estudar várias soluções, descobri que o dev.to tem uma API que possibilita a consulta dos dados do usuário assim como seus artigos. Com isso na mão, me animei a fazer uma aplicação em Vue que lesse esses dados
A API
Inicialmente cheguei neste artigo que demonstrava como consumir a API da plataforma, com exemplo em PHP.
How to use the dev.to API!
𝐍𝐚𝐭𝐚𝐥𝐢𝐞 𝐝𝐞 𝐖𝐞𝐞𝐫𝐝 ・ Jun 7 '20 ・ 2 min read
No artigo, tem um link para um outro que mostra vários endpoints que você pode consultar pra obter os dados que deseja. Pesquisando um pouco mais, cheguei à documentação oficial.
E com isso, cheguei nos 2 endpoints que precisava:
Vue
Tendo a API e os endpoints, o próximo passo foi buscar esses dados dentro do site, pra depois exibir do jeito que eu queria.
Consumindo a API
O primeiro passo foi criar um método pra centralizar as requisições à api, que fiz com axios
import axios, {AxiosInstance} from "axios";
const http: AxiosInstance = axios.create({
baseURL: "https://dev.to/api/",
headers: {
'Accept': "application/json",
'Content-Type': 'application/json'
}
})
export default http;
Depois disso, criei serviços distindos para fazer a consulta aos endpoints.
O service pra receber artigos:
import http from "@/http";
export const getArticles = () => http.get('articles', {
params: {
username: 'stsmuniz'
}
})
E o service para receber o perfil
import http from "@/http";
export const getProfile = () => http.get('users/by_username', {
params: {
url: 'stsmuniz'
}
})
Com os services criados, agora podemos usar no site
Exibindo o perfil
Antes de mais nada, é necessário fazer a consulta efetivamente. Como usei composition api, usei o método onBeforeMount
pra buscar os dados antes de renderizar a página.
setup() {
const profile = ref()
onBeforeMount(() => {
getProfile()
.then(res => profile.value = res.data)
})
....
return {
profile
}
})
E na página vai o componente que "monta" o perfil
<ProfileComponent profile="profile" v-if="profile"/>
<i class="fa-solid fa-spinner fa-spin-pulse" v-else></i>
O ProfileComponent
é o componente que recebe as informações do perfil e "monta" o perfil na tela.
<template>
<div class="profile">
<img class="profile-picture" :alt="profile.username" :src="profile.profile_image">
<h1>{{profile.name}}</h1>
<p class="description" v-html="profile.summary.replace('\n', '<br />')"></p>
<p><i class="fa-solid fa-location-dot"></i> {{profile.location}}</p>
</div>
</template>
<script lang="ts">
import {defineComponent} from "vue";
export default defineComponent({
name: "ProfileComponent",
props: {
profile: {
required: true
}
},
})
</script>
E com isso conseguimos fazer o perfil ser renderizado na tela. O próximo passo é fazer o mesmo processo para os artigos
Exibindo os artigos
A primeira coisa aqui é criar a view para exibir os artigos, que chamei aqui de Blog. No setup há a chamada para a API pelo service ArticleService, com o
<template>
<div class="home" v-if="articles">
<h1>Blog</h1>
<ArticleList :articles="articles"/>
</div>
<i class="fa-solid fa-spinner fa-spin-pulse" v-else></i>
</template>
<script lang="ts">
import {defineComponent, onMounted, ref} from 'vue';
import {getArticles} from "@/service/ArticleService";
import ArticleList from '@/components/ArticleList.vue';
export default defineComponent({
name: 'BlogView',
components: {
ArticleList,
},
setup() {
const articles = ref()
onMounted(() => {
document.title = 'Blog'
})
getArticles()
.then(res => articles.value = res.data)
return {
articles
}
}
});
</script>
O ArticleList
é um componente container que, basicamente, organiza o container pra lista de artigos
<template>
<div class="container">
<ArticleItem v-for="article in articles" :article="article" :key="article.id" />
</div>
</template>
<script>
import {defineComponent} from 'vue';
import ArticleItem from "@/components/ArticleItem";
export default defineComponent({
name: 'ArticleList',
components: {ArticleItem},
props: {
articles: {
required: true
}
}
});
</script>
E por fim, o componente ArticleItem
organiza as informações no template pra fazer a exibição
<template>
<article>
<a :href="article.url"
:title="article.title"
target="_blank">
<img class="responsive"
:src="article.cover_image"
:alt="article.title" />
</a>
<div class="article-data">
<h1>
<a :href="article.url"
:title="article.title"
target="_blank">
{{ article.title }}
</a>
</h1>
<p class="article-description">{{article.description}}</p>
<p class="publish-date">
<i class="fa-solid fa-calendar"></i> <DateFormatter :date="article.published_at" />
</p>
</div>
</article>
</template>
<script>
import DateFormatter from "./DateFormatter";
import {defineComponent} from "vue";
export default defineComponent({
name: "ArticleItem",
components: {DateFormatter},
props: {
article: {
required: true
}
}
})
</script>
Como eu queria exibir a data no formato dd/mm/yyyy
, criei o componente DateFormatter
pra tratar a string que vem no formato ISO.
Deploy
Dei uma fuçada e acabei encontrando um artigo interessante que explica bem como fazer o deploy:
Se você for usar esse método, tome cuidado com o nome da branch principal no arquivo gh-pages-deploy.js
. No artigo ela está sendo chamada como master
.
Fechando
Com isso, mais a estrutura básica do vue e alguma estilização, pode se ter um site simples com informações básicas vindas do seu perfil do dev.to e uma página com link para seus artigos mais recentes.
Pretendo criar um repositório aberto pra compartilhar o que fiz aqui e deixar fácil pra qualquer pessoa com perfil aqui também ter sua página pessoal, assim como a minha
Obrigado por acompanhar até aqui e nos vemos na próxima 👋
Posted on September 2, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.