Quem nunca precisou criar um site rápido, com dados de estrutura repetidas, mas achou que adicionar um banco de dados e toda lógica para comunicação seria demais?
Geradores de sites estáticos são opções rápidas e hoje em dia é possível colocar um no ar em minutos. Porém quando precisamos fazer modificações constantes no conteúdo do site torna-se difícil fazê-lo sem modificar o código. No meu caso, precisava dividir as responsabilidades de fazer modificações nos dados do site com uma pessoa não técnica mas que já estava habituada com planilhas online.
Nesse texto conto como usei o Google Sheets como um backend para o meu site estático, com deploy no Netlify e atualizações periódicas com o Github Actions. Para rodar esse projeto você precisará de uma conta Google e uma conta no GitHub (com ambas você poderá logar também no Netlify) e, claro, um projeto Hugo local com um template já configurado. Veja um guia rápido de como iniciar aqui (em inglês). Os comandos serão executados na pasta do site (projeto Hugo).
O site para o bazar
Única programadora envolvida na organização de um bazar, eu precisava encontrar uma forma de manter o site atualizado de maneira rápida sem que significasse modificações no repositório. Para mim o Hugo é a ferramenta tratando-se de geração de sites estáticos mas dessa vez tinha alguns requisitos diferentes do que costumo a ter. Eu precisava:
- Exibir os produtos que ainda estão disponíveis (ou seja, esconder os que foram pagos ou estão reservados)
- Atualizar informações dos produtos, como preço, foto e descrição
- Não ter custo para manter o site no ar
Uma coisa muito legal sobre os dias de hoje é que muitos produtos são disponibilizados de maneira gratuita para projetos menores. Me aproveitei disso para juntar os que mais uso em uma coisa só que cumprisse todos os requisitos.
Google Sheets
A partir de qualquer conta do Google é possível criar documentos online. O Google Sheets é um software de gestão de planilhas online. A partir dele, é possível criar, compartilhar com outras pessoas e publicar planilhas.
Para criar uma nova planilha, com sua conta do Google, acesse sheet.new. Depois de adicionado o conteúdo, acesse Arquivo > Publicar na Web. Escolha o formato CSV e a aba que deseja publicar. Ao clicar em publicar, será gerado um link parecido com este:
https://docs.google.com/spreadsheets/d/e/<sheet_id>/pub?gid=0&single=true&output=csv
Pronto. De volta ao ambiente onde está nosso projeto, vamos criar uma variável de ambiente chamada SHEET_URL
. Dessa forma não expomos a URL do nosso CSV no nosso código. Mais tarde vamos configurá-la também no GitHub.
Hugo Data Templates
Um dos geradores de sites estáticos mais populares da atualidade é o Hugo, desenvolvido em Go. Além de ser muito rápido, o Hugo tem uma comunidade ativa e muitas funcionalidades, variando de suporte a funções customizadas a processamento de JavaScript e arquivos SASS e SCSS.
Uma funcionalidade interessante para quem quer criar um site rápido a partir de uma fonte de dados, seja um arquivo ou uma URL, é o Data Templates. É possível gerar uma página com dados de um arquivo local ou de uma URL, nos formatos JSON, CSV e YAML. Dito isso… por que não gerar um site estático a partir de um CSV online? Continuamos daqui assumindo que você já tem um site com Hugo configurado.
Com o Data Templates é possível gerar uma página a partir de entradas em um arquivo local (na pasta data
a ser criada na raiz do projeto) ou de uma URL. Repare que é uma página e não múltiplas páginas. Mas para contornar esse problema você pode criar um script para gerar essas páginas utilizando archetypes (esqueletos para postagens). Esse assunto vai ficar pra uma próxima! :)
No meu caso, eu queria gerar várias miniaturas a partir do conteúdo da minha planilha - caso perfeito para o Data Templates. Um site com Hugo tem layouts pré-definidos; o arquivo list.html
, por exemplo, exibe uma lista de miniaturas das postagens. Para utilizar os dados da planilha em uma lista de miniaturas modifiquei o layout do arquivo list.html
. Com o Hugo, essa é a maneira de sobrescrever o layout de um template: basta adicionar na pasta layouts
o arquivo desejado seguindo a mesma estrutura e padrão do template utilizado.
Agora vem o pulo do gato: eu queria manter algumas publicações que eu já tinha em markdown e também gerar miniaturas a partir do CSV. Por isso mantive a estrutura inicial do arquivo e abaixo adicionei uma estrutura muito parecida que iria gerar o conteúdo que gostaria.
Para conectar com o CSV online precisava ler a variável de ambiente (que contém a URL) e então usar a função getCSV
oferecida pelo Hugo. Essa função vai acessar a URL ou arquivo local e disponibilizá-lo. Basta passarmos como argumento o separador (em meu caso vírgula ","
) e a URL. O retorno é o índice e conteúdo da linha. Simples assim.
{{ $url := getenv "SHEET_URL" }}
{{ range $i, $row := getCSV "," $url }}
Para acessar o conteúdo das colunas basta utilizar a função index
. Exemplo:
{{ $item := index $row 1 }}
{{ $estado := index $row 2 }}
{{ $tempo_de_uso := index $row 3 }}
{{ $preco := index $row 4 }}
Isso significa que todas as vezes que essa página for acessada o Hugo vai buscar informações nessa URL? Não. Isso significa que sempre que o site for gerado essa URL será acessada e, a partir dos dados dela, a página list.html
será criada. Veremos mais a frente como forçar a atualização dos dados.
Imagens
Bom, e o que fazer quando queremos adicionar imagens?
Continuando no mesmo espírito de atualizar o conteúdo do site sem depender de modificações no repositório, adotei o Google Photos como ferramenta para armazenar as imagens. Ao abrir uma imagem, basta clicar com o botão direito e em seguida clicar em “Copiar endereço da imagem”. Essa é a URL pública da imagem, que pode ser adicionada também a sua planilha. Link de exemplo para uma imagem que está no Google Photos aqui.
Ao ler a imagem da planilha você terá um link público para ela. Então basta adicionar no código HTML de list.html
.
{{ $imagem_capa := index $row 7 }}
{{ $instagram := index $row 8 }}
{{ if $imagem_capa }}
<a href="{{ $instagram }}" title="{{ $item }}" class="box-masonry-image with-hover-overlay with-hover-icon">
<img src="{{ $imagem_capa }}" alt="{{ $item }}" class="img-responsive">
</a>
{{ end }}
Nessa imagem os itens “Como Funciona” e “Doe você também” são novas postagens e as demais são apenas miniaturas vindas da planilha online.
Netlify
Frequentemente vejo pelo Twitter alguém falando “Como não inventaram algo como Netlify antes?”.
No Netlify você pode hospedar o seu site estático gratuitamente. Além disso, ele tem integração com o Github - ou seja: o código caiu na sua branch principal e já vai pro ar. A integração não se resume apenas isso: caso você crie pull requests terá a sua disposição um site com um preview das modificações que você está propondo. Massa demais, não?
Já não posso esconder que adoro o serviço mas tem mais uma funcionalidade que torna o Netlify uma peça importante no uso de planilhas online como backend de um site estático: build webhooks. Apenas acessando uma URL podemos iniciar um novo deploy para o Netlify. Isso significa que, para todas as vezes que quisermos gerar novamente o nosso site, podemos fazê-lo apenas acessar uma URL.
Existem limites no plano gratuito para uso mas eu imagino que sejam mais que suficientes para pequenos projetos:
Banda: 100GB por mês
Tempo de execução para gerar o site completo: 300 minutos /mês
Sites ilimitados
Para deployar o seu site para o Netlify basta logar com sua conta e conectar o repositório no GitHub. Além disso, você pode fazer customizações com um arquivo netlify.toml
no site seu Hugo. Veja mais sobre a integração do Hugo com o Netlify aqui. Uma vez que o repositório tenha sido conectado você já pode ter acesso aos Build Webhooks. Vamos pegar o endereço do Webhook para deploy - já já vamos copiá-lo para a variável de ambiente NETLIFY_DEPLOY_HOOK
.
Antes do grand finale… Vamos configurar as variáveis de ambiente no GitHub
Precisamos configurar duas variáveis de ambiente para fazer tudo funcionar: SHEET_URL
e NETLIFY_DEPLOY_HOOK
. Para isso basta ir para as configurações do seu repositório e clicar em Secrets > New secret. Após adicioná-las, elas estarão disponíveis em todos os deploys.
GitHub Actions
Já sabemos como acessar dados de uma planilha online dentro do Hugo, onde fazer o deploy do site gratuitamente e como iniciar um build para gerar um novo site. O que falta? Agendar momentos para nova geração do site (a não ser que você queira ficar acessando uma URL horrorosa todas as vezes).
O GitHub Actions é a mais nova ferramenta de CI queridinha dos desenvolvedores (de acordo com meu instituto de pesquisas nada enviesado). Como GitHub Actions você pode ter uma ferramenta de integração contínua, execução de testes, release de versões, em diferentes sistemas operacionais, e muito mais no seu GitHub.
Uma funcionalidade massa do GitHub Actions é o agendamento: tudo o que nós precisávamos. Para isso, bastou criar um novo workflow :
name: Trigger Netlify Build
on:
schedule:
# At the end of every day
- cron: '0 0 * * *'
jobs:
build:
name: Request Netlify Webhook
runs-on: ubuntu-latest
steps:
- name: Request deploy to Netlify
env:
NETLIFY_DEPLOY_HOOK: ${{ secrets.NETLIFY_DEPLOY_HOOK }}
run: curl -X POST -d {} "$NETLIFY_DEPLOY_HOOK"
Com ele, agendamos uma nova geração do site e deploy no Netlify para o final de cada dia fazendo apenas um POST para o hook do Netlify responsável pelo deploy. Simples assim.
Por hoje é só, pessoal
Usar Data Templates foi algo que sempre quis fazer; é uma funcionalidade muito legal e que provavelmente irá evoluir para a geração completa de sites estáticos através de fontes online em breve. Espero que você tenha gostado desse texto e te seja útil em algum momento! Todo o código está disponível aqui.
Infelizmente a oportunidade de explorar essa funcionalidade chegou quando a minha irmã faleceu após lutar contra um câncer. Nós tentamos continuar o legado dela em ajudar pessoas com esse bazar. Se você quiser saber como ajudar a instituições de câncer de Feira de Santana ou conhecer um pouco mais sobre essa iniciativa, acesse www.bazardogirassol.com.br.
Descansa em paz, Mila. 🌻
comments powered by Disqus