Alternar tema

Como criar um blog com Next.js 15 em um fim de semana

Easton editorial illustration: API gateway workstation

Introdução

O Next.js 15 tinha acabado de ser lançado. Eu já havia lido a documentação oficial várias vezes e assistido a muitos tutoriais, mas ainda sentia que tudo ficava na teoria: entendia os conceitos de Server Actions e App Router, porém não sabia como aplicá-los em um projeto real. No fim de semana, resolvi parar de consumir tutoriais e construir algo de verdade: um blog full stack. O projeto envolveu frontend, backend, banco de dados e implantação. Dois dias depois, o blog estava no ar na Vercel, com 96 pontos de desempenho no Lighthouse.

Este texto conta todo o processo. Não é um tutorial que termina depois de copiar e colar código; a ideia é entender por que cada decisão foi tomada e quais armadilhas apareceram. A stack é Next.js 15 + Server Actions + Prisma + PostgreSQL, com código pensado para produção.

Por que escolhi o Next.js 15?

Demorei bastante para decidir a stack.

Quando o Next.js 15 foi lançado, vi gente na comunidade reclamando que havia mais uma atualização e que já não dava para acompanhar. Para ser sincero, também resisti um pouco, porque ainda não dominava completamente a versão 14. Depois de analisar os novos recursos com calma, percebi que a atualização valia a pena.

Server Actions: menos burocracia que API Routes

Ao trabalhar com desenvolvimento full stack, uma das partes mais cansativas era escrever API Routes. Era preciso criar api/posts/route.ts, definir o método POST, tratar o corpo da requisição, devolver a resposta… O mesmo processo se repetia toda vez.

Server Actions mudaram completamente essa dinâmica. Basta adicionar 'use server' antes da função e chamá-la diretamente no componente. Quando vi o recurso pela primeira vez, pensei: “Então agora o código do backend fica no frontend?”. Depois de experimentar, entendi a vantagem.

Antes, para criar um post, eu escrevia algo assim:

// Método antigo: exige a criação de uma API Route
// app/api/posts/route.ts
export async function POST(request: Request) {
  const body = await request.json()
  // Lógica de processamento...
}
// O frontend ainda precisa chamar fetch
const response = await fetch('/api/posts', {
  method: 'POST',
  body: JSON.stringify(data)
})

Agora, basta fazer isto:

// app/actions/post-actions.ts
'use server'
export async function createPost(formData: FormData) {
  const title = formData.get('title')
  const content = formData.get('content')
  // Acesso direto ao banco de dados
  return await prisma.post.create({
    data: { title, content }
  })
}

A chamada no componente é tão simples quanto chamar uma função local. Usando uma comparação cotidiana: antes você precisava ir buscar a comida no restaurante (API Routes); agora ela chega diretamente à sua casa (Server Actions).

Turbopack tornou o desenvolvimento mais de duas vezes mais rápido

No Next.js 15, o Turbopack deixou de ser experimental e passou a ser estável. Segundo os dados oficiais, o servidor local inicia 76,7% mais rápido e as atualizações de código ficam 96,3% mais rápidas. No começo, achei que fossem números de marketing, mas a experiência prática confirmou a diferença.

76,7%
Melhora na velocidade de inicialização do servidor
Dados de testes oficiais
96,3%
Melhora na velocidade de atualização do código
Atualização em tempo real quase instantânea
2 segundos
Tempo de inicialização do projeto
Mais de 30 componentes, antes iniciados em 7–8 segundos, passaram a carregar em menos de 2 segundos

Meu projeto tem pouco mais de 30 componentes. Com Webpack, a inicialização levava 7–8 segundos; com Turbopack, caiu para menos de 2 segundos. Ao alterar o código, a atualização em tempo real é praticamente instantânea. Isso muda bastante a experiência de desenvolvimento.

Por que essa stack é adequada para um blog?

Escolhi Next.js para o blog principalmente por três motivos:

Vantagens nativas de SSR/SSG — SEO é essencial para um blog. A renderização no servidor e a geração estática do Next.js foram feitas para esse tipo de cenário. O crawler do Google recebe o HTML completo, uma vantagem enorme em relação ao React renderizado apenas no cliente.

Segurança de tipos do Prisma — Eu já usei Mongoose com MongoDB e precisava manter as definições de tipos manualmente; qualquer descuido podia introduzir bugs. O Prisma gera tipos TypeScript diretamente a partir do schema e oferece sugestões completas no editor, o que reduz bastante os erros.

Server Actions simplificam o desenvolvimento — Não é mais necessário escrever API Routes, e o volume de código cai pelo menos 30%. Se eu tivesse construído este blog da forma tradicional, provavelmente precisaria criar vários arquivos route.ts adicionais.

Escolha da stack e projeto da arquitetura

Depois de entender os motivos, era hora de definir como construir o projeto.

Minha stack completa

  • Frontend: Next.js 15 + TypeScript + Tailwind CSS
  • Backend: Next.js Server Actions + NextAuth.js
  • Banco de dados: PostgreSQL + Prisma ORM
  • Implantação: Vercel

Talvez você se pergunte por que não usei MongoDB. Eu também considerei essa opção no início, porque o MongoDB é realmente mais flexível. Depois percebi que o Prisma oferece um suporte melhor ao PostgreSQL e que um banco relacional é mais adequado para dados com relações claras, como posts, usuários e comentários.

Estrutura de diretórios

my-blog/
├── app/
│   ├── (auth)/          # Páginas relacionadas à autenticação
│   ├── blog/            # Páginas do blog
│   │   └── [slug]/      # Rota dinâmica
│   ├── dashboard/       # Painel de controle do usuário
│   ├── actions/         # Todas as Server Actions ficam aqui
│   └── api/auth/        # Configuração do NextAuth
├── components/          # Componentes reutilizáveis
├── lib/
│   ├── prisma.ts        # Singleton do Prisma (muito importante!)
│   └── utils.ts         # Funções utilitárias
├── prisma/
│   └── schema.prisma    # Schema do banco de dados
└── public/              # Recursos estáticos

Revisei essa estrutura várias vezes até chegar à versão final. No começo, as Server Actions estavam espalhadas pelos arquivos de página. A manutenção ficou confusa, então criei um diretório actions exclusivo para organizá-las.

Projeto do schema do banco de dados

Cometi um erro grande nessa etapa. A primeira versão era complexa demais: incluí tags, categorias, estatísticas de leitura e várias outras coisas. Na metade da implementação, percebi que não precisava de tantas tabelas e gastei mais meio dia simplificando tudo.

O schema principal ficou assim:

// prisma/schema.prisma
generator client {
  provider = "prisma-client-js"
}
datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}
model User {
  id        String   @id @default(cuid())
  email     String   @unique
  name      String?
  image     String?
  posts     Post[]
  createdAt DateTime @default(now())
}
model Post {
  id          String   @id @default(cuid())
  title       String
  slug        String   @unique
  content     String   @db.Text
  published   Boolean  @default(false)
  authorId    String
  author      User     @relation(fields: [authorId], references: [id])
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt
  @@index([slug])
  @@index([authorId])
}

Observe os dois @@index: eles são essenciais para o desempenho. A listagem do blog consulta posts com frequência pelo slug, enquanto o perfil do usuário filtra por authorId. Com esses índices, as consultas podem ficar várias vezes mais rápidas.

Implementação detalhada dos recursos principais

Com a arquitetura definida, chegou a parte mais interessante: escrever o código.

3.1 Configuração do ambiente e inicialização

Criar um projeto com Next.js 15 é bem simples:

npx create-next-app@latest my-blog
cd my-blog
npm install prisma @prisma/client zod next-auth

Depois de instalar o Prisma, inicialize-o:

npx prisma init

O comando gera prisma/schema.prisma e o arquivo .env. Configure a conexão com o PostgreSQL no .env:

DATABASE_URL="postgresql://username:password@localhost:5432/myblog?schema=public"

No desenvolvimento local, executei o PostgreSQL com Docker usando um único comando:

docker run --name blog-postgres -e POSTGRES_PASSWORD=mypassword -p 5432:5432 -d postgres

3.2 Integração do Prisma com o banco de dados

Depois de configurar o schema, execute a migration:

npx prisma migrate dev --name init

Há uma armadilha importante aqui: o padrão singleton do Prisma Client. Na primeira vez em que implantei na Vercel, esqueci completamente dessa configuração. Depois de meio dia, o site começou a exibir o erro “Too many connections”, e eu cheguei a pensar que estava sofrendo um ataque DDoS.

O ambiente de desenvolvimento do Next.js faz recarregamento em tempo real e cria uma nova instância do Prisma Client a cada recarga. O pool de conexões se esgota rapidamente. A configuração correta é esta:

// lib/prisma.ts
import { PrismaClient } from '@prisma/client'
const globalForPrisma = globalThis as unknown as {
  prisma: PrismaClient | undefined
}
export const prisma = globalForPrisma.prisma ?? new PrismaClient()
if (process.env.NODE_ENV !== 'production') {
  globalForPrisma.prisma = prisma
}

O código parece um pouco complicado, mas garante uma única instância do Prisma no ambiente de desenvolvimento, sem afetar a produção. Vale lembrar: essa é a prática recomendada oficialmente pelo Prisma.

3.3 Server Actions na prática

Criar posts é o recurso central do sistema. Veja como escrever a Server Action:

// app/actions/post-actions.ts
'use server'
import { prisma } from '@/lib/prisma'
import { revalidatePath } from 'next/cache'
import { z } from 'zod'
// Validação de dados com Zod e segurança de tipos
const PostSchema = z.object({
  title: z.string().min(1, 'O título é obrigatório').max(100),
  content: z.string().min(10, 'O conteúdo deve ter pelo menos 10 caracteres'),
  slug: z.string().regex(/^[a-z0-9-]+$/, 'O slug deve conter apenas letras minúsculas, números e hífens')
})
export async function createPost(formData: FormData) {
  // Validação dos dados
  const validatedFields = PostSchema.safeParse({
    title: formData.get('title'),
    content: formData.get('content'),
    slug: formData.get('slug')
  })
  if (!validatedFields.success) {
    return { error: 'Falha na validação dos dados' }
  }
  try {
    const post = await prisma.post.create({
      data: {
        ...validatedFields.data,
        authorId: 'user-id-here' // Em um projeto real, obtenha o valor da session
      }
    })
    // Revalida o cache para exibir o novo post imediatamente
    revalidatePath('/blog')
    return { success: true, post }
  } catch (error) {
    return { error: 'Falha ao criar o post' }
  }
}

Use-a diretamente no componente:

// app/dashboard/new-post/page.tsx
import { createPost } from '@/app/actions/post-actions'
export default function NewPost() {
  return (
    <form action={createPost}>
      <input name="title" placeholder="Título" />
      <textarea name="content" placeholder="Conteúdo" />
      <input name="slug" placeholder="Slug da URL" />
      <button type="submit">Publicar</button>
    </form>
  )
}

Percebeu? Não é necessário usar useState, fetch ou tratar o evento onSubmit. O formulário chama a Server Action diretamente, e o Next.js cuida da serialização, da requisição de rede e do tratamento de erros.

No início, eu também não entendia bem a diferença entre Server Actions e API Routes. Depois ficou claro: Server Actions são como pedir comida e recebê-la em casa; API Routes são como ir buscá-la no restaurante. A primeira opção é prática, enquanto a segunda oferece mais flexibilidade. Na maioria dos casos, Server Actions são suficientes.

3.4 Sistema de autenticação de usuários

Usei NextAuth.js para a autenticação, e a configuração é relativamente simples:

// app/api/auth/[...nextauth]/route.ts
import NextAuth from 'next-auth'
import GitHubProvider from 'next-auth/providers/github'
import { PrismaAdapter } from '@auth/prisma-adapter'
import { prisma } from '@/lib/prisma'
export const authOptions = {
  adapter: PrismaAdapter(prisma),
  providers: [
    GitHubProvider({
      clientId: process.env.GITHUB_ID!,
      clientSecret: process.env.GITHUB_SECRET!
    })
  ]
}
const handler = NextAuth(authOptions)
export { handler as GET, handler as POST }

Para configurar o GitHub OAuth, crie um aplicativo no GitHub Developer Settings e adicione o Client ID e o Secret ao .env. Todo o processo levou 10 minutos, muito menos trabalho do que implementar autenticação JWT por conta própria.

3.5 Estratégia de otimização com SSR/SSG

Essa parte é essencial para o desempenho. Para ser sincero, no início usei SSR (renderização no servidor) em tudo. Depois percebi que consultar o banco a cada acesso à listagem do blog era desnecessário e adotei uma estratégia híbrida.

Listagem do blog — SSG + ISR:

// app/blog/page.tsx
import { prisma } from '@/lib/prisma'
// Regenera uma vez por hora
export const revalidate = 3600
export default async function BlogList() {
  const posts = await prisma.post.findMany({
    where: { published: true },
    orderBy: { createdAt: 'desc' }
  })
  return (
    <div>
      {posts.map(post => (
        <article key={post.id}>
          <h2>{post.title}</h2>
          <p>{post.content.slice(0, 150)}...</p>
        </article>
      ))}
    </div>
  )
}

A página gera HTML estático durante o build e é regenerada automaticamente a cada hora. Quando alguém a acessa, recebe diretamente o arquivo estático, o que torna o carregamento muito rápido.

Página do post — SSR dinâmico:

// app/blog/[slug]/page.tsx
export default async function Post({ params }: { params: { slug: string } }) {
  const post = await prisma.post.findUnique({
    where: { slug: params.slug }
  })
  if (!post) notFound()
  return (
    <article>
      <h1>{post.title}</h1>
      <div dangerouslySetInnerHTML={{ __html: post.content }} />
    </article>
  )
}

Essa página consulta o banco a cada acesso para obter o conteúdo mais recente, uma estratégia adequada para posts atualizados com frequência.

Comparação de desempenho:

~200 ms
Tempo de carregamento de uma página SSG
Geração estática, a opção mais rápida
~800 ms
Tempo de carregamento de uma página SSR
Renderização no servidor, adequada para conteúdo dinâmico
~1.500 ms
Tempo de carregamento com CSR puro
Renderização no cliente, com SEO inferior

A diferença é evidente. É por isso que o Next.js funciona tão bem para blogs: oferece bom SEO e desempenho.

Implantação e otimização

Com o código pronto, chegou a hora mais esperada: colocar o projeto no ar.

Processo de implantação na Vercel

Depois de enviar o código para o GitHub, importei o repositório diretamente na Vercel. A plataforma detectou um projeto Next.js e configurou tudo automaticamente. As únicas definições manuais foram as variáveis de ambiente:

DATABASE_URL="conexão do banco de dados de produção"
GITHUB_ID="OAuth Client ID"
GITHUB_SECRET="OAuth Secret"
NEXTAUTH_URL="https://your-domain.vercel.app"
NEXTAUTH_SECRET="string aleatória"

Para o banco de produção, usei o PostgreSQL gratuito do Supabase, que oferece 500 MB por mês, o suficiente para um blog pessoal.

Depois de clicar em Deploy, o site entrou no ar em cerca de 2 minutos. Na primeira vez em que vi meu domínio funcionando, fiquei alguns segundos olhando para a tela e depois tirei uma captura para compartilhar com os amigos.

Otimizações para produção

A implantação não encerra o trabalho. Ainda há alguns ajustes importantes:

Configuração do pool de conexões do Prisma:

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
  // Obrigatório no ambiente serverless da Vercel
  directUrl = env("DIRECT_URL")
}

Em um ambiente serverless, cada chamada de função pode criar uma nova conexão. Configurar directUrl permite reutilizar o pool.

Otimização de imagens:

import Image from 'next/image'
<Image
  src="/avatar.jpg"
  alt="Avatar do usuário"
  width={100}
  height={100}
  // O Next.js faz a compactação e a otimização automaticamente
/>

O componente Image do Next.js converte as imagens automaticamente para WebP e faz carregamento sob demanda, com uma melhora perceptível no desempenho.

Pontuação final de desempenho:

96 pontos
Desempenho no Lighthouse para desktop
92 no celular, 100 em SEO e desempenho de produção em dois dias, do zero ao site no ar

No Lighthouse, obtive 96 pontos no desktop, 92 no celular e 100 em SEO. Ver esse resultado foi muito gratificante: em dois dias, saí do zero e coloquei no ar um projeto com desempenho de produção.

Próximas extensões e recursos de aprendizagem

O blog ainda está na versão MVP e pode receber vários recursos:

  • Editor Markdown: pode ser integrado com o react-md-editor
  • Sistema de comentários: estou considerando o Giscus, baseado no GitHub Discussions
  • Pesquisa: Algolia ou busca de texto completo com Prisma
  • Modo escuro: fácil de implementar com next-themes

Meu próximo passo é adicionar um editor Markdown para facilitar a escrita dos posts.

Recursos de aprendizagem recomendados:

Na prática, construir uma vez ensina mais do que ler a documentação dez vezes. A teoria é importante, mas é o projeto real que consolida o conhecimento.

Conclusão

Revendo este projeto de fim de semana, estes foram os principais aprendizados:

  1. A capacidade das Server Actions: elas realmente substituem a maioria das API Routes e aumentam bastante a produtividade
  2. A segurança de tipos do Prisma: o suporte completo a TypeScript dá muito mais confiança ao escrever código
  3. A flexibilidade de SSG/SSR: escolher a estratégia de renderização de acordo com o cenário permite equilibrar desempenho e SEO
  4. A simplicidade da implantação na Vercel: do código ao site no ar, o processo levou menos de 5 minutos

Para ser sincero, o maior ganho não foi a tecnologia em si, mas a confiança. Desenvolvimento full stack não é tão inacessível quanto parece; o principal é começar a construir.

Se você também quer criar seu próprio blog, comece agora. Encontrar problemas faz parte do processo: eu também consultei a documentação enquanto programava e precisei resolver muitas armadilhas antes de tudo funcionar. Quando você vê o projeto no ar, o esforço faz sentido.

Espero que este texto ajude você a evitar alguns desses obstáculos. Se tiver dúvidas, deixe um comentário; vou tentar responder.

Quero ver o seu projeto no ar.

Criar um blog pronto para produção com Next.js 15

Processo completo, da configuração do ambiente à implantação, com Server Actions, Prisma e otimizações de SSG/SSR

Estimated time: PT16H

  1. 1

    Step 1: Configuração do ambiente e inicialização do projeto

    Crie um projeto Next.js 15:
  2. 2

    Step 2: Configuração do schema do banco de dados com Prisma

    Defina o schema principal:
  3. 3

    Step 3: Implementação dos recursos principais com Server Actions

    Crie o arquivo de Server Actions:
  4. 4

    Step 4: Configuração do sistema de autenticação

    Instale o NextAuth.js:
  5. 5

    Step 5: Otimização da estratégia de renderização com SSR/SSG

    Use SSG + ISR na listagem do blog: em app/blog/page.tsx, defina export const revalidate = 3600 para regenerar a página a cada hora. Use prisma.post.findMany para consultar os posts publicados e ordene por createdAt em ordem decrescente. A página gera HTML estático durante o build e é regenerada automaticamente a cada hora. Quando alguém a acessa, recebe diretamente o arquivo estático, com carregamento de aproximadamente 200 ms. Use SSR dinâmico na página de cada post: em app/blog/[slug]/page.tsx, consulte o banco a cada acesso para obter o conteúdo mais recente. Use prisma.post.findUnique({ where: { slug: params.slug } }); essa estratégia é adequada para posts atualizados com frequência e leva cerca de 800 ms. Comparação de desempenho: páginas SSG ~200 ms, páginas SSR ~800 ms e CSR puro ~1.500 ms. A diferença é evidente.
  6. 6

    Step 6: Implantação na Vercel e otimização

    Envie o código ao GitHub: faça push do projeto para um repositório do GitHub. Importe o projeto na Vercel: importe o repositório diretamente; ao detectar um projeto Next.js, a Vercel faz a configuração automaticamente. Configure as variáveis de ambiente: adicione DATABASE_URL (conexão do banco de produção), GITHUB_ID, GITHUB_SECRET, NEXTAUTH_URL (https://your-domain.vercel.app) e NEXTAUTH_SECRET (string aleatória) nas configurações do projeto. Para o banco de produção, recomendo o PostgreSQL gratuito do Supabase (500 MB por mês, suficiente para um blog pessoal). Configure o pool de conexões do Prisma: adicione directUrl = env(“DIRECT_URL”) ao datasource em prisma/schema.prisma. Em um ambiente serverless, cada chamada de função pode criar uma nova conexão; directUrl permite reutilizar o pool. Otimize as imagens: use o componente Image do Next.js, que converte automaticamente para WebP e faz carregamento sob demanda, com melhora perceptível no desempenho. Depois de clicar em Deploy, o site entra no ar em cerca de 2 minutos. Pontuação final no Lighthouse: 96 no desktop, 92 no celular e 100 em SEO.

FAQ

Qual é a diferença entre Server Actions e API Routes no Next.js 15? Quando usar cada opção?
Server Actions são como pedir comida e recebê-la em casa; API Routes são como ir buscá-la no restaurante. A primeira opção é prática, enquanto a segunda oferece mais flexibilidade.

Vantagens das Server Actions:
1) Reduzem o volume de código em 30%, sem precisar criar API Routes
2) Podem ser chamadas diretamente no componente, sem useState, fetch nem tratamento do evento onSubmit
3) O Next.js cuida automaticamente da serialização, das requisições de rede e dos erros
4) Oferecem segurança de tipos e permitem usar os tipos do TypeScript diretamente

Exemplo de uso: adicione 'use server' antes da função e chame-a diretamente no componente (<form action={createPost}>).

Vantagens das API Routes:
• São mais flexíveis e permitem tratar lógicas de requisição complexas
• Aceitam middleware
• São adequadas quando é necessário personalizar a resposta HTTP

Na maioria dos casos, Server Actions são suficientes. Use API Routes somente quando precisar de um tratamento HTTP mais complexo.
Quanto o Turbopack melhora o desempenho? Como é a experiência de uso na prática?
No Next.js 15, o Turbopack deixou de ser experimental e se tornou estável.

Dados oficiais:
• Inicialização do servidor local 76,7% mais rápida
• Atualização de código 96,3% mais rápida

Experiência prática:
• Meu projeto tem pouco mais de 30 componentes. Com Webpack, a inicialização levava 7–8 segundos; com Turbopack, caiu para menos de 2 segundos
• Ao alterar o código, a atualização em tempo real é praticamente instantânea
• A diferença na experiência de desenvolvimento é enorme

O Turbopack é escrito em Rust e é muito mais rápido que o Webpack, principalmente em projetos grandes. Se você ainda usa Webpack, vale a pena atualizar para o Next.js 15 e experimentar o Turbopack.
Por que o padrão singleton do Prisma Client é importante? O que acontece sem essa configuração?
O padrão singleton do Prisma Client é uma prática recomendada oficialmente pelo Prisma.

Cenário do problema:
• O ambiente de desenvolvimento do Next.js faz recarregamento em tempo real e cria uma nova instância do Prisma Client a cada recarga
• O pool de conexões se esgota rapidamente e causa o erro "Too many connections"
• Na minha primeira implantação na Vercel, esqueci completamente dessa configuração. Depois de meio dia no ar, o site exibiu esse erro e cheguei a pensar que estava sofrendo um ataque DDoS

Configuração correta:
• Implemente um singleton global em lib/prisma.ts:
const globalForPrisma = globalThis as unknown as { prisma: PrismaClient | undefined };
export const prisma = globalForPrisma.prisma ?? new PrismaClient();
if (process.env.NODE_ENV !== 'production') {
globalForPrisma.prisma = prisma;
}

Esse código garante uma única instância do Prisma no ambiente de desenvolvimento, sem afetar a produção. Vale lembrar: essa é a prática recomendada oficialmente pelo Prisma.
Quais são as diferenças entre SSG, SSR e ISR? Como escolher?
SSG (Static Site Generation):
• Gera HTML estático durante o build e oferece a maior velocidade (~200 ms)
• É adequado para páginas cujo conteúdo muda pouco, como a listagem do blog e a página Sobre

SSR (Server-Side Rendering):
• Gera o HTML no servidor a cada requisição
• É adequado para páginas que precisam de dados em tempo real, como detalhes de posts e perfis de usuários
• O tempo de carregamento é de aproximadamente 800 ms

ISR (Incremental Static Regeneration):
• Combina SSG com regeneração periódica, unindo a velocidade do SSG à flexibilidade do SSR
• É adequado para páginas atualizadas ocasionalmente, como uma listagem do blog regenerada a cada hora

CSR puro (Client-Side Rendering):
• Renderiza no navegador, oferece SEO ruim e leva cerca de 1.500 ms para carregar
• Não é recomendado para blogs

Estratégia de escolha:
• Use SSG + ISR na listagem do blog (export const revalidate = 3600)
• Use SSR dinâmico nas páginas de cada post
• Use SSG puro na página Sobre

Comparação de desempenho: SSG ~200 ms, SSR ~800 ms e CSR puro ~1.500 ms. A diferença é evidente.
Por que escolher PostgreSQL em vez de MongoDB? Como é o suporte do Prisma ao PostgreSQL?
Motivos para escolher PostgreSQL:
1) O suporte do Prisma ao PostgreSQL é melhor, com segurança de tipos, ferramentas de migração e otimização de consultas bem desenvolvidas
2) Um banco relacional é mais adequado para dados com relações claras, como posts, usuários e comentários
3) O PostgreSQL tem recursos avançados de busca de texto completo, úteis para a pesquisa do blog
4) Oferece mais estabilidade em produção e suporte completo a transações

Vantagens do Prisma:
• Ele gera tipos TypeScript diretamente a partir do schema, oferecendo sugestões completas no editor e reduzindo bastante a chance de erros
• Eu já usei Mongoose com MongoDB e precisava manter as definições de tipos manualmente, o que facilitava a introdução de bugs
• A segurança de tipos do Prisma me dá muito mais confiança ao programar

Se você precisa lidar com dados relacionais complexos, PostgreSQL + Prisma é uma ótima combinação.
O que exige atenção ao implantar um projeto Next.js na Vercel? Como otimizar o ambiente de produção?
Processo de implantação na Vercel:
1) Envie o código para o GitHub
2) Importe o repositório do GitHub na Vercel; ao detectar um projeto Next.js, a plataforma faz a configuração automaticamente
3) Configure as variáveis de ambiente (DATABASE_URL, GITHUB_ID, GITHUB_SECRET, NEXTAUTH_URL e NEXTAUTH_SECRET)
4) Clique em Deploy; o site entra no ar em cerca de 2 minutos

Otimizações para produção:

1) Configuração do pool de conexões do Prisma:
• Adicione directUrl = env("DIRECT_URL") ao datasource em prisma/schema.prisma
• Em um ambiente serverless, cada chamada de função pode criar uma nova conexão; configurar directUrl permite reutilizar o pool

2) Otimização de imagens:
• Use o componente Image do Next.js, que converte automaticamente as imagens para WebP e faz carregamento sob demanda, com melhora perceptível no desempenho

3) Para o banco de produção, recomendo o PostgreSQL gratuito do Supabase (500 MB por mês, suficiente para um blog pessoal)

Pontuação final de desempenho:
• No Lighthouse, obtive 96 pontos no desktop, 92 no celular e 100 em SEO
• Ver esse resultado foi muito gratificante: em dois dias, saí do zero e coloquei no ar um projeto com desempenho de produção

15 min de leitura · Publicado em: 24 nov 2025 · Atualizado em: 4 set 2026

Comentários

Entre com GitHub para comentar

Easton BlogEaston Blog