DevToolbox: uma coleção de ferramentas para desenvolvedores feita com Next.js 15
Uma coleção de ferramentas para desenvolvedores construída com Next.js 15 App Router: formatadores, codificadores, geradores e conversores em um só lugar.
Este blog foi construído com Astro 5 no edge da Cloudflare, usando D1 como banco SQLite, Workers AI para geração de conteúdo e MinIO para armazenamento de imagens — tudo com custo zero.
Queria um blog pessoal com painel de administração próprio — sem depender do WordPress, Ghost ou qualquer CMS externo. O desafio: rodar tudo no plano gratuito da Cloudflare, sem servidor dedicado.
A solução: Astro 5 no edge da Cloudflare com D1 como banco de dados e Workers AI para funcionalidades de inteligência artificial.
O Astro tem uma proposta diferente dos outros frameworks: zero JavaScript por padrão. As páginas do blog são HTML puro geradas no servidor — sem React, sem Vue, sem bundle pesado chegando no browser.
Isso importa muito para SEO e performance. O Lighthouse do blog está consistentemente acima de 95 em todas as métricas.
O Astro usa o conceito de Islands — ilhas de interatividade em um oceano de HTML estático. Os formulários, botões de IA e o editor de markdown são "ilhas" que carregam JavaScript só quando necessário.
---
// Código do servidor — roda só no build/request
import { getDb, posts } from '../lib/db';
const allPosts = await getDb(Astro.locals.runtime.env.DB)
.select().from(posts).all();
---
<!-- HTML puro, zero JS -->
{allPosts.map(post => (
<article>
<h2>{post.title}</h2>
</article>
))}
Framework: Astro 5 (SSR no edge)
Adapter: @astrojs/cloudflare v12
Banco: Cloudflare D1 (SQLite na edge) + Drizzle ORM
Auth: GitHub OAuth via Arctic v2
IA: Cloudflare Workers AI (Llama 3 8B)
Storage: MinIO self-hosted via @aws-sdk/client-s3
Estilo: Tailwind CSS 4
Deploy: Cloudflare Pages (gratuito)
O acesso ao admin é protegido por GitHub OAuth com allowlist: só o usuário configurado em ADMIN_GITHUB_USERNAME consegue entrar. Qualquer outra conta GitHub recebe 403.
O D1 é o banco de dados serverless da Cloudflare — SQLite rodando na mesma edge que processa as requisições. Latência baixíssima, sem cold start de conexão TCP.
Uso o Drizzle ORM para type-safety:
import { drizzle } from 'drizzle-orm/d1';
import * as schema from './schema';
export function getDb(d1: D1Database) {
return drizzle(d1, { schema });
}
O blog usa meu servidor MinIO self-hosted para armazenar imagens — uma alternativa ao Cloudflare R2 para quem já tem infraestrutura própria.
A integração usa o @aws-sdk/client-s3 com forcePathStyle: true (necessário para MinIO):
const client = new S3Client({
endpoint: env.MINIO_ENDPOINT,
credentials: {
accessKeyId: env.MINIO_ACCESS_KEY,
secretAccessKey: env.MINIO_SECRET_KEY,
},
forcePathStyle: true,
});
| Serviço | Plano | Custo |
|---|---|---|
| Cloudflare Pages | Free | R$ 0 |
| Cloudflare D1 | Free (5GB, 5M leituras/dia) | R$ 0 |
| Cloudflare Workers AI | Free (10k neurons/dia) | R$ 0 |
| MinIO | Self-hosted no meu servidor | R$ 0 extra |
Total: R$ 0/mês para um blog com IA, upload de imagens e painel admin completo.
O código está disponível no GitHub: github.com/thiago-tap/site_cms
Sinta-se livre para usar como base para o seu próprio blog!
Receba novos posts diretamente no seu email.
Uma coleção de ferramentas para desenvolvedores construída com Next.js 15 App Router: formatadores, codificadores, geradores e conversores em um só lugar.
Um gerenciador de snippets de código construído com SvelteKit 2 e Svelte 5, explorando a nova API de reatividade chamada Runes.