Criando um Blog com Vue.js, Nuxt e Ghost CMS
Desenvolvendo um blog utilizando Vue.js, Nuxt e consumindo dados do Ghost CMS via API.

Este artigo tem como objetivo relatar o processo de desenvolvimento de um blog utilizando Vue.js, Nuxt e consumindo dados de um CMS via API.
Não farei um passo a passo detalhado de como instalar e utilizar as ferramentas, mas trarei algumas dicas e desafios que enfrentei nesse processo e que poderão servir de referência para quem busca construir um blog.
Ferramentas
Primeiro, irei listar e fazer uma breve descrição das ferramentas e tecnologias utilizadas nesse projeto justificando a escolha de cada uma.
Vue.js
O Vue é um framework progressivo para construção de interfaces de usuário. Construído para ser incrementalmente adotável, sua implementação em páginas já existente é muito simples e direta. Mesmo com essas características o Vue é perfeitamente capaz de executar Single-Page Applications. Sua arquitetura busca combinar as melhoras características do React e do Angular.
Mais informações podem ser encontradas na página do Vue.
Escolhi o Vue principalmente por causa de sua estrutura de Single File Component - que combina html, css e javascript num mesmo arquivo - torna o desenvolvimento dos componentes Vue mais próximo de uma página web tradicional.
Nuxt.js
O Nuxt é um framework que adiciona algumas funcionalidades ao Vue.js, tais como Server Side Redering (SSR) - Renderização do lado do servidor - e Static Site Generation (SSG) - Geração de páginas estáticas.
SSR vs SPA?
Em uma SPA (Single-Page Application) o conteúdo da página é exibido depois que a página é carregada, para o usuário essa estratégia não representa nenhum problema, uma vez que o funcionamento é preservado.
No entanto, para os motores de busca (como Google, Bing etc.) que utilizam robôs para ler as páginas, nem sempre aguardam o conteúdo ser carregado para indexar as páginas, como efeito, para eles, nosso site não possui conteúdo e, portanto não será indexado.
Utilizando Server Side Rendering (SSR) todos os arquivos javascript e CSS são carregados e disponibilizados como arquivos estáticos. Assim quando a página é acessada, ela já está pronta, possibilitando que seu carregamento seja mais rápido e indexável pelos mecanismos de SEO (Search Engine Optimization).
Para um site ou blog público, é desejável que ele exista nos mecanismos de busca, por esse motivo escolhi adotar um framework que implementa SSR. Como estou utilizando Vue como framework javascript, o Nuxt tornou a melhor opção para esse fim.
CMS
Um Content Management System (CMS) - Sistema de gerenciamento de conteúdo - é um software que permite criação, edição e organização de conteúdo de maneira dinâmica. CMSs podem ser divididos em duas categorias:
- Tradicional: onde o conteúdo é disponibilizado pelo próprio software, como um site.
- Headless: nesse tipo de CMS o conteúdo é disponibilizado via API, possibilitando, entre outras, a construção de diferentes tipos de clientes (SPA e App Mobile, por exemplo).
Existem diversas ferramentas excelentes de gerenciamento de conteúdo: WordPress, Prismic, Ghost CMS e outros.
Para essa tarefa escolhi o Ghost CMS por ser gratuito, possuir um editor de texto muito poderoso - ideal para um blog - e por possuir funcionalidades que o classificam, também, como um Headless CMS.
Construção do blog
Dividi o processo de criação do site/blog em 3 etapas:
- Instalação do Ghost
- Criação do Front-End
- Deploy da aplicação
Instalação do Ghost
A documentação oficial do Ghost recomenda que ele seja instalado em um servidor linux com no mínimo 1GB de memória RAM. Por isso optei por executá-lo utilizando docker em um servidor virtual da Oracle.
Para disponibilizar o acesso através de SSL na internet, em conjunto com o Ghost, utilizei o Caddy como servidor web, que também foi instalado via docker.
Para facilitar a inicialização dos containers do CMS e do Caddy, criei um docker-compose com o seguinte código:
version: "3.7"
services:
blog:
image: ghost
restart: unless-stopped
container_name: blog
volumes:
- /caminho/para/content:/var/lib/content:z
ports:
- 2368:2368
expose:
- "2368"
environment:
url: <URL do blog>
proxy:
image: abiosoft/caddy
container_name: proxy
restart: unless-stopped
links:
- "blog:blog"
ports:
- 80:80
- 443:443
volumes:
- /caminho/para/Caddyfile:/etc/Caddyfile:z
- $PWD/.caddy:/root/.caddy:z
Para iniciar os serviços basta executar docker-compose up -d
Criação do Site
A construção do site foi iniciada como um projeto Nuxt tradicional:
npx create-nuxt-app [projeto]
O CLI do create-nuxt-app realiza uma série de perguntas para poder configurar o projeto com as bibliotecas e configurações necessárias. Todos os recursos podem ser adicionados a qualquer momento utilizando o npm ou yarn
. Optei por deixar o CLI configurar o Nuxt apenas com:
- Typescript
- ESLint
- Tailwindcss
Ao término do processo, o projeto ficou com a seguinte estrutura de pastas (todas as pastas principais tem um arquivo README.md
que direciona para a documentação do Nuxt correspondente):
assets
: aqui coloquei todos os arquivos de imagens, css, etc.;components
: todos os componentes Vue ficam nessa pasta, componentes nessa pasta são carregados globalmente e de maneira automática, pelo Nuxt;layouts
: utilizei o layout com apenas um objetivo, aplicar a classe do estado da aplicação (dark ou light) é através dessa classe que o tailwind consegue aplicar as variantes das classes aos componentes filhos;pages
: pasta principal da aplicação, todo arquivo Vue nessa pasta se transformará numa página e terá uma rota associada. O nome do arquivo será utilizado como rota do Nuxt, por exemplo o conteúdo do arquivoblog.vue
será exibido quando a rotahttp://endereco/blog
é acessada;static
: os arquivos nessa pasta são acessíveis diretamente pelo HTML, utilizei principalmente para ofavicon
;store
: nessa pasta fica a configuração do Vuex - o Gerenciador de estados global da aplicação;types
: como utilizei typescript, criei essa pasta com o arquivovue-shim.d.ts
dessa maneira o typescript é capaz de identificar os arquivos.vue
como módulos e consiga aplicar a tipagem e transpilar o código, quando enviarmos para produção, de maneira correta;api
: criei essa pasta para abrigar todos os arquivos que realizem qualquer interação com APIs;nuxt.config.js
: arquivo principal do Nuxt, todos os módulos, plugins e configurações ficam nesse arquivo.
Escolhi o Tailwind como framework CSS por sua possibilidade de compor o design utilizando classes, aplicar variantes das cores (dark mode) além de utilidades cini responsividade e palheta de cores.
Integração com o CMS
Para integrar o site ao CMS, primeiro foi necessário criar uma entrada à API no ghost. Na área administrativa do CMS (http://endereco_do_blog/ghost) acesse:
- o menu integrações;
- crie uma integração personalizada.
- anote as seguintes informações: Content API Key e API URL, que serão utilizadas mais tarde.
Para que o site se comunique com CMS, o Ghost disponibiliza a biblioteca GhostContentAPI @tryghost/content-api
que possui os métodos necessários para consumir os dados do Ghost de maneira simples. Para utilizar criei um arquivo posts.ts
dentro da pasta api
e utilizei o seguinte código para configurar a GhostContentAPI:
import GhostContentAPI from '@tryghost/content-api';
const api = new GhostContentAPI({
url: 'API URL',
key: 'Content API Key',
version: 'v3',
});
Dos métodos que a API nos disponibiliza utilizei apenas dois: api.posts.browse
para listar os posts e api.posts.read
para exibir apenas um artigo.
Os demais métodos podem ser conferidos na documentação.
A listagem de artigos é exibida em duas páginas distintas, portanto, optei por realizar o carregamento dos posts no store. Assim foi possível compartilhar a mesma listagem de posts em duas páginas distintas realizando apenas uma chamada à API.
Deploy
Realizei o deploy da aplicação na plataforma da Vercel por já possuir a estrutura e ferramentas necessárias para hospedagem de uma aplicação Nuxt. O passo a passo para o deploy é tão simples quanto criar um arquivo vercel.json
e pode ser conferido na documentação.
Conclusão
A construção desse blog me permitiu passar por diversos conceitos desde criação de um servidor virtual na nuvem, passando por instalação e configuração de um servidor web, técnicas avançadas de desenvolvimento Front-end, SSR, UI e SEO.
Pretendo continuar o desenvolvimento desse projeto aplicando algumas outras técnicas e funcionalidades, que incluem, dentre outras:
- Cobertura de testes utilizando jest;
- Adicionar paginação na listagem dos posts;
- Possibilidade de inserir comentários nos posts;
- Aplicar estratégias de SEO.
Confira o projeto íntegra: https://github.com/virb30/blog