● Em construção R$ 0,00/mês

Construindo o Mundo Nuvem do zero

Como criei este site estático com Astro 6, Tailwind CSS 4, Cloudflare Pages e Supabase — custo zero de hospedagem, PageSpeed verde, pronto para SEO.

CloudflareSupabase AstroTailwind CSSTypeScriptMDXCloudflare PagesCloudflare R2Supabase

O Mundo Nuvem é o próprio caso de uso que ele documenta. Este projeto registra cada decisão técnica, custo e aprendizado da construção do site — para que você possa replicar a mesma arquitetura nos seus projetos.

Custo de hospedagem: R$ 0,00/mês. Usando exclusivamente free tiers que escalam até tráfego real sem cobrar nada.

Decisões de arquitetura

A escolha de stack não foi aleatória. Cada ferramenta foi selecionada com base em três critérios: custo zero no free tier, performance nativa (HTML estático entregue por CDN) e fluxo de desenvolvimento via Git sem painel admin.

Por que Astro e não Next.js ou Gatsby

Astro é o único framework que foi construído para sites de conteúdo desde o início. Ele entrega zero JavaScript por padrão — o que significa que cada página é HTML puro quando não há interatividade necessária. Para um site editorial como o Mundo Nuvem, isso se traduz diretamente em Core Web Vitals verdes sem otimização manual.

Next.js é excelente para aplicações web. Para sites de conteúdo, é excessivo — você importa um runtime de React para renderizar texto estático.

Por que Cloudflare Pages e não Vercel ou Netlify

Cloudflare Pages tem o free tier mais generoso do mercado para sites estáticos: deploys ilimitados, largura de banda ilimitada e CDN com mais de 300 pontos de presença no mundo. A Vercel cobra por largura de banda no plano gratuito a partir de certo volume.

A decisão também abre caminho para usar Cloudflare R2 (armazenamento de assets sem custo de egress) e Cloudflare Pages Functions (serverless para a API de tracking) — tudo no mesmo ecossistema, sem configurar múltiplos provedores.

Por que Supabase apenas para Radar e newsletter

O conteúdo longo (projetos e guias) vive em arquivos MDX no repositório Git. Isso significa:

  • Controle de versão gratuito para cada mudança de conteúdo
  • Fluxo natural de escrita no VSCode com preview em tempo real
  • Zero custo de banco de dados para o conteúdo principal
  • Conteúdo indexável pelo Google desde o primeiro build

O Supabase entra apenas onde o banco de dados faz sentido: notícias do Radar (que mudam o dia todo) e e-mails de newsletter (que precisam de RLS e inserção server-side).

Fase 1 — Base técnica

Inicializando o projeto

bash
npm create astro@latest mundo-nuvem -- --template minimal --typescript strict --no-git

Após a criação, as dependências de produção:

bash
npm install tailwindcss @tailwindcss/vite @astrojs/mdx @astrojs/sitemap @astrojs/rss

Atenção importante: o npm pode instalar Vite 8 como dependência, o que quebra o @tailwindcss/vite 4.x pelo novo bundler Rolldown. A solução é forçar Vite 7 via overrides no package.json:

{
  "overrides": {
    "vite": "~7.3.2"
  }
}

Tailwind CSS 4 — abordagem CSS-first

O Tailwind 4 abandonou o arquivo tailwind.config.js. A configuração agora vive inteira no CSS:

@import "tailwindcss";

@theme {
  --color-mn-bg: #0a0e1a;
  --color-mn-surface: #111827;
  --color-mn-glow: #9bd9ff;
  /* ... demais tokens */
}

E o plugin Vite substitui o antigo @astrojs/tailwind:

// astro.config.mjs
import tailwindcss from '@tailwindcss/vite';

export default defineConfig({
  vite: { plugins: [tailwindcss()] },
});

Content Collections — Astro 6

O Astro 6 migrou para a Content Layer API. O arquivo de configuração das coleções saiu de src/content/config.ts para src/content.config.ts (na raiz do src/).

Cada coleção usa o glob loader:

import { defineCollection, z } from 'astro:content';
import { glob } from 'astro/loaders';

const projetos = defineCollection({
  loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/projetos' }),
  schema: z.object({
    title: z.string(),
    description: z.string().max(160),
    status: z.enum(['planejado', 'em-construcao', 'concluido']),
    provider: z.array(z.string()),
    stack: z.array(z.string()),
    publishedAt: z.coerce.date(),
    monthlyCost: z.string().optional(),
  }),
});

Fase 2 — Conteúdo em Git

Rotas dinâmicas com getStaticPaths

A rota /projetos/[slug].astro usa getStaticPaths para gerar uma página por arquivo MDX:

export async function getStaticPaths() {
  const projetos = await getCollection('projetos');
  return projetos.map(entry => ({
    params: { slug: entry.id },
    props: { entry },
  }));
}

O entry.id na Content Layer API do Astro 6 corresponde ao nome do arquivo sem extensão. Um arquivo construindo-o-mundo-nuvem.mdx gera a rota /projetos/construindo-o-mundo-nuvem.

JSON-LD para projetos: TechArticle + HowTo

O Google usa dados estruturados para entender o tipo de conteúdo. Para tutoriais técnicos, o schema TechArticle combinado com HowTo é o mais semântico:

const schema = [
  {
    '@type': 'TechArticle',
    headline: title,
    author: { '@type': 'Person', name: 'Fábio Silva' },
    // ...
  },
  {
    '@type': 'HowTo',
    name: title,
    step: headings
      .filter(h => h.depth === 2)
      .map((h, i) => ({
        '@type': 'HowToStep',
        position: i + 1,
        name: h.text,
      })),
  },
];

Fase 3 — Supabase + Radar (próxima)

A próxima etapa conecta o banco de dados Supabase para o sistema de notícias do Radar. Os detalhes serão documentados quando a fase for concluída.

Custos reais do projeto

ServiçoPlanoCusto mensal
Cloudflare PagesFreeR$ 0,00
Cloudflare R2Free (10 GB)R$ 0,00
SupabaseFree (500 MB, 50k req/mês)R$ 0,00
Domínio mundonuvem.comRegistro anual~R$ 7,00

Total de infraestrutura: R$ 7,00/mês (apenas o domínio).

Esta é a vantagem concreta do free tier bem escolhido: você escala para dezenas de milhares de pageviews mensais sem pagar nada de hospedagem.

O que aprendi

O maior aprendizado da Fase 1 não foi técnico — foi editorial. O tempo que vai para pensar a arquitetura de informação (quais URLs, quais schemas JSON-LD, como fazer interlinking) é diretamente proporcional ao SEO que você colhe 6 meses depois.

Sites que começam com “vou otimizar SEO depois” raramente otimizam. Construir o Seo.astro como componente obrigatório desde o dia 1 — com title, description, canonical e JSON-LD como props obrigatórias — eliminou esse débito antes que ele existisse.

Continue construindo

Explore outros projetos e guias do Mundo Nuvem: