Como Implementei um Sistema de Comentários Gratuito com GitHub Issues
✨ Ter um sistema de comentários em um blog é essencial para construir uma comunidade e gerar discussões interessantes. Mas hospedar seu próprio banco de dados para comentários pode ser complicado e caro. E se você pudesse usar o GitHub como seu backend de comentários, completamente de graça?
🤔 O Problema dos Comentários
Quando decidi construir este blog em Go, enfrentei o clássico dilema dos comentários:
- WordPress? Exige PHP e um banco de dados.
- Disqus? Gratuito, mas carregado de rastreadores e anúncios.
- Discourse? Poderoso, mas exige hospedagem separada.
- Firebase/Supabase? Começa gratuito, mas pode ficar caro com o crescimento.
Eu queria uma solução que fosse:
- Totalmente gratuita (mesmo com escala)
- Sem hospedagem separada de banco de dados
- Controlada por mim (sem depender de plataformas externas)
- Com moderação simplificada
- Integrável facilmente com minha aplicação Go
💡 A Epifania: GitHub Issues como Sistema de Comentários
Um dia, enquanto navegava pelo GitHub, percebi algo: Issues já são um sistema de comentários completo!
Issue = Post principal
Comentários na Issue = Respostas
E o melhor de tudo: a API do GitHub é gratuita para uso público e já oferece tudo que eu precisava:
- Autenticação (via token de API)
- Armazenamento persistente
- Sistema de notificação por email
- Markdown rico para formatação
- Avatares de usuários
- Moderação (posso fechar/deletar issues)
🛠️ A Arquitetura da Solução
Para implementar esse sistema, criei uma arquitetura simples em Go:
1. Modelo de Dados
// Comment representa um comentário baseado em GitHub Issue
type Comment struct {
ID int `json:"id"`
Body string `json:"body"`
Author string `json:"author"`
AvatarURL string `json:"avatar_url"`
CreatedAt time.Time `json:"created_at"`
PostID string `json:"post_id"`
URL string `json:"url"`
Replies []Reply `json:"replies,omitempty"`
IsAdmin bool `json:"is_admin"`
}
// Reply representa uma resposta a um comentário
type Reply struct {
ID int `json:"id"`
Body string `json:"body"`
Author string `json:"author"`
AvatarURL string `json:"avatar_url"`
CreatedAt time.Time `json:"created_at"`
IsAdmin bool `json:"is_admin"`
}
2. Serviço de Comentários
O coração do sistema é o CommentService
, que interage com a API do GitHub:
type CommentService struct {
Owner string
Repo string
Token string
APIBaseURL string
GithubUser string
}
Este serviço implementa métodos para:
- GetComments(postID string): Busca comentários de um post específico
- CreateComment(request CommentRequest): Cria um novo comentário
- GetReplies(commentID int): Busca respostas de um comentário
- CreateReply(request ReplyRequest): Cria uma resposta a um comentário
3. API REST
Para expor essa funcionalidade para o frontend, implementei endpoints REST:
func (h *CommentHandler) Register(mux chi.Router) {
mux.Route("/api/comments", func(r chi.Router) {
r.Get("/{postID}", h.getComments)
r.Post("/{postID}", h.createComment)
r.Post("/{commentID}/reply", h.createReply)
})
}
4. Integração com GitHub
O segredo está em como usar a API do GitHub para gerenciar comentários:
Como Armazenar Comentários
- Cada comentário é uma Issue no repositório configurado
- Cada post do blog é identificado por uma label ("comment:slug-do-post")
- Comentários aninhados são comentários do GitHub na Issue
Criação de Comentário (Formulário → GitHub Issue)
// Cria uma nova Issue para representar o comentário
issueData := struct {
Title string `json:"title"`
Body string `json:"body"`
Labels []string `json:"labels"`
}{
Title: fmt.Sprintf("Comment by %s", request.Name),
Body: fmt.Sprintf("%s\n\n---\nEmail: %s", request.Body, request.Email),
Labels: []string{"comment:" + request.PostID},
}
// Envia para API do GitHub
url := fmt.Sprintf("%s/repos/%s/%s/issues", s.APIBaseURL, s.Owner, s.Repo)
// ... código para enviar requisição HTTP ...
Recuperação de Comentários (GitHub Issues → Frontend)
// Busca Issues com a label específica do post
url := fmt.Sprintf("%s/repos/%s/%s/issues?labels=comment:%s&state=all",
s.APIBaseURL, s.Owner, s.Repo, postID)
// ... código para processar resposta e criar objetos Comment ...
// Para cada comentário, busca suas respostas
replies, err := s.GetReplies(comment.ID)
if err == nil && len(replies) > 0 {
comment.Replies = replies
}
🎭 Identificação de Administradores
Um detalhe interessante é como identifico comentários do administrador do blog:
// Se NÃO foi criado pelo formulário, é um comentário direto do GitHub feito pelo administrador
isAdmin := !wasCreatedViaForm
Comentários feitos diretamente no GitHub pelo administrador são marcados como "admin", recebendo estilo visual diferenciado na interface.
🚀 Vantagens Desta Abordagem
Usar o GitHub como backend para comentários trouxe várias vantagens:
- Custo zero - GitHub oferece API gratuita para repositórios públicos
- Sem banco de dados - GitHub armazena tudo
- Notificações automáticas - recebo email quando alguém comenta
- Anti-spam integrado - GitHub já tem proteção contra bots
- Backup automático - tudo está no GitHub, sempre seguro
- Moderação fácil - posso gerenciar pelo próprio GitHub
- Markdown nativo - suporte completo à formatação rica
🧠 Aspectos Técnicos Interessantes
A implementação revelou alguns desafios interessantes:
1. Parsing de Comentários
O formato dos comentários do GitHub não é exatamente o que eu precisava para o blog, então tive que fazer parsing cuidadoso:
// Verificamos se o comentário parece ter sido criado pelo formulário do site
wasCreatedViaForm := strings.Contains(issue.Body, "---\nEmail:") &&
strings.HasPrefix(issue.Title, "Comment by ")
// Define o autor com base na origem do comentário
var author string
if wasCreatedViaForm {
// Comentário do formulário: extrai o nome do título "Comment by Nome"
author = strings.TrimPrefix(issue.Title, "Comment by ")
} else {
// Comentário direto do GitHub: usa o nome de usuário do GitHub
author = issue.User.Login
}
2. Gerenciamento de Token
O token de acesso à API do GitHub é sensível, então precisei gerenciá-lo com cuidado:
token := os.Getenv("GITHUB_TOKEN")
if token == "" {
return nil, fmt.Errorf("GITHUB_TOKEN não configurado")
}
3. Estrutura de Respostas Aninhadas
Armazenar e recuperar respostas aninhadas exigiu atenção especial para manter a estrutura:
// Busca respostas para este comentário
replies, err := s.GetReplies(comment.ID)
if err == nil && len(replies) > 0 {
comment.Replies = replies
}
🌐 Experiência do Usuário
Para o usuário final, a experiência é perfeita:
- Formulário simples para adicionar comentários
- Resposta imediata após submissão
- Carregamento rápido de comentários existentes
- Suporte a respostas aninhadas para criar conversas
- Identificação de comentários do autor do blog
🧩 A Natureza Emergente das Conversas
O que me fascina sobre sistemas de comentários é como eles representam um sistema complexo emergente. Cada comentário individual é simples, mas juntos criam uma rede de ideias interconectadas onde:
- Tópicos emergem naturalmente na discussão
- Clusters de ideias se formam em torno de pontos controversos
- Nós centrais (comentários populares) atraem mais respostas
- Propriedades de rede livre de escala aparecem na distribuição de respostas
É como uma rede neural social, onde cada comentário é um neurônio conectando-se a outros para formar um tecido de pensamento coletivo.
🔮 Futuras Melhorias
Algumas ideias para o futuro:
- Autenticação OAuth para comentar diretamente como usuário GitHub
- Reações (curtir, aplaudir) além de comentários
- Notificações para usuários quando receberem respostas
- Visualização de rede para ver a estrutura da conversa
- Análise de sentimento para identificar tópicos polêmicos
🔚 Conclusão
Implementar um sistema de comentários usando GitHub Issues foi uma solução elegante e econômica. Em vez de reinventar a roda ou pagar por serviços, aproveitei a infraestrutura existente do GitHub para criar uma experiência de alta qualidade sem custo.
Esta abordagem demonstra um princípio importante: às vezes, a melhor solução não é construir algo novo, mas conectar sistemas existentes de formas criativas.
E você, já pensou em usar GitHub para algo além de código? Quais outros serviços poderiam ser reimaginados como backends para aplicações web? Deixe seu comentário abaixo!
🎨 O Background Interativo deste Post
Enquanto você lê este artigo, observe o fascinante sistema complexo se desenrolando no background. O que você está vendo é uma rede de comentários emergente - uma visualização interativa de como as ideias se conectam e fluem em um sistema de discussão.
Cada nó colorido representa um comentário, e as linhas entre eles representam respostas ou conexões temáticas. Observe como:
- Clusters de comentários relacionados se formam naturalmente
- Hubs (comentários populares) atraem mais conexões
- Cascatas de informação se propagam quando uma ideia ganha tração
- Novos comentários aparecem e buscam conexões com a conversa existente
Este sistema simula o fenômeno de homofilia (tendência de ideias semelhantes se agruparem) e difusão em rede (como informações se espalham através de conexões sociais).
Interaja com o background:
- Mova o mouse para introduzir novos "comentários" e veja como se integram à rede
- Clique para criar um comentário influente que atrairá mais conexões
- Observe padrões emergentes na formação de comunidades de pensamento
Esta visualização é inspirada pela teoria de redes complexas e pelo conceito de "fitness landscape" em sistemas adaptativos complexos - onde ideias competem, evoluem e se agrupam, criando um ecossistema de pensamento coletivo em constante evolução!