📋 Table of Contents
- Um aplicativo de gerenciamento de tarefas full-stack: Next.js 15 App Router, PostgreSQL via Neon (sem servidor), Prisma ORM, Server Actions (sem rotas de API separadas para mutações), Auth.js v5 GitHub OAuth, implantado no Vercel.
- 📋 Copiar
- Crie um banco de dados gratuito em
- 📋 Copiar
- Os componentes do App Router são componentes de servidor por padrão — eles são executados no servidor e podem consultar diretamente o banco de dados:
- As ações do servidor substituem as rotas da API para envios de formulários e mutações:
- 📋 Copiar
- 📋 Copiar
- Limitação de taxa
- O que é Next.js 15?
- Configuração do projeto: Next.js 15 + TypeScript
- Banco de dados: PostgreSQL com Neon + Prisma
- Modelos de dados
- Componentes do servidor e busca de dados
- Ações do servidor para mutações
- Autenticação com Auth.js v5
- Implantando no Vercel
- Lista de verificação de produção
- Perguntas frequentes
- O que estamos construindo
Um aplicativo de gerenciamento de tarefas full-stack: Next.js 15 App Router, PostgreSQL via Neon (sem servidor), Prisma ORM, Server Actions (sem rotas de API separadas para mutações), Auth.js v5 GitHub OAuth, implantado no Vercel.
Configuração do Projeto
📋 Copiar
npx create-next-app@latest taskapp \
--typescript --tailwind --eslint --app --src-dir --import-alias "@/*"
cd taskapp
Crie um banco de dados gratuito em
néon.tecnologia. Então:📋 Copiar
npm install prisma @prisma/client
npx prisma init
:.env.local📋 Copiar
DATABASE_URL="postgresql://user:pass@ep-xxx.us-east-2.aws.neon.tech/neondb?sslmode=require"
NEXTAUTH_SECRET="your-random-secret-here"
GITHUB_CLIENT_ID="your-github-oauth-app-id"
GITHUB_CLIENT_SECRET="your-github-oauth-app-secret"
📋 Copiar
// prisma/schema.prisma
model User {
id String @id @default(cuid())
email String @unique
name String?
createdAt DateTime @default(now())
tasks Task[]
}
model Task {
id String @id @default(cuid())
title String
status TaskStatus @default(PENDING)
priority Priority @default(MEDIUM)
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([userId])
}
enum TaskStatus { PENDING IN_PROGRESS COMPLETED CANCELLED }
enum Priority { LOW MEDIUM HIGH URGENT }
npx prisma migrate dev --name init
npx prisma generate
// src/lib/db.ts
import { PrismaClient } from '@prisma/client';
const globalForPrisma = globalThis as unknown as { prisma: PrismaClient };
export const db = globalForPrisma.prisma ?? new PrismaClient();
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = db;
Os componentes do App Router são componentes de servidor por padrão — eles são executados no servidor e podem consultar diretamente o banco de dados:
📋 Copiar
// src/app/dashboard/page.tsx (Server Component)
import { db } from '@/lib/db';
import { auth } from '@/lib/auth';
import { redirect } from 'next/navigation';
export default async function DashboardPage() {
const session = await auth();
if (!session?.user) redirect('/');
const tasks = await db.task.findMany({
where: { userId: session.user.id, status: { not: 'CANCELLED' } },
orderBy: [{ priority: 'desc' }, { createdAt: 'desc' }],
take: 50,
});
return (
<main className="container mx-auto p-6">
<h1>My Tasks</h1>
{tasks.map(task => <TaskCard key={task.id} task={task} />)}
</main>
);
}
Ações do servidor para mutações
As ações do servidor substituem as rotas da API para envios de formulários e mutações:
📋 Copiar
// src/actions/tasks.ts
'use server';
import { db } from '@/lib/db';
import { auth } from '@/lib/auth';
import { revalidatePath } from 'next/cache';
import { z } from 'zod';
const Schema = z.object({
title: z.string().min(1).max(200),
priority: z.enum(['LOW','MEDIUM','HIGH','URGENT']).default('MEDIUM'),
});
export async function createTask(formData: FormData) {
const session = await auth();
if (!session?.user?.id) throw new Error('Unauthorized');
const parsed = Schema.safeParse({
title: formData.get('title'),
priority: formData.get('priority') || 'MEDIUM',
});
if (!parsed.success) return { error: parsed.error.flatten().fieldErrors };
await db.task.create({ data: { ...parsed.data, userId: session.user.id } });
revalidatePath('/dashboard');
return { success: true };
}
call invalida o cache Next.js para essa rota, acionando uma nova renderização do servidor com novos dados.revalidatePathAutenticação com Auth.js v5
📋 Copiar
npm install next-auth@beta @auth/prisma-adapter
// src/lib/auth.ts
import NextAuth from 'next-auth';
import GitHub from 'next-auth/providers/github';
import { PrismaAdapter } from '@auth/prisma-adapter';
import { db } from './db';
export const { auth, handlers, signIn, signOut } = NextAuth({
adapter: PrismaAdapter(db),
providers: [GitHub({ clientId: process.env.GITHUB_CLIENT_ID!, clientSecret: process.env.GITHUB_CLIENT_SECRET! })],
session: { strategy: 'database' },
callbacks: { session: ({ session, user }) => ({ ...session, user: { ...session.user, id: user.id } }) }
});
→ exportarsrc/app/api/auth/[...nextauth]/route.ts.handlers as GET, handlers as POSTImplantando no Vercel
📋 Copiar
# Install Vercel CLI and deploy
npm install -g vercel
vercel
# Set environment variables
vercel env add DATABASE_URL
vercel env add NEXTAUTH_SECRET
vercel env add GITHUB_CLIENT_ID
vercel env add GITHUB_CLIENT_SECRET
vercel --prod
e executehttps://your-app.vercel.app/api/auth/callback/github.npx prisma migrate deployLista de verificação de produção
Limitação de taxa
- — Upstash Ratelimit em ações do servidor e rotas de APILimites de erro
- – adicionararquivos para substitutos graciosos
error.tsxCarregando estados - – adicionarpara esqueletos de Suspense
loading.tsxValidação de entrada - — sempre use Zod nas ações do servidorPool de conexões
- – adicionarpara URL Neon
?pgbouncer=true&connection_limit=1Cabeçalhos de segurança - — adicionar viacabeçalhos()
next.config.ts🔧 Pronto para enviar?
Next.js 15 + PostgreSQL é a pilha full-stack dominante em 2026. Explorar
por que o TypeScript é essencialpara aplicativos Next.js maiores e masterpadrões assíncronos/aguardadospara componentes e ações do servidor.Perguntas Frequentes
O que é Next.js 15?
Next.js mais recente: Turbopack estável (5× mais rápido), React 19 necessário, APIs de solicitação assíncrona, ações de servidor aprimoradas. App Router é o padrão daqui para frente.
Roteador de aplicativos ou roteador de páginas em 2026?
App Router para todos os novos projetos. O Pages Router funciona, mas não possui novos recursos.
Qual banco de dados usar com Next.js?
PostgreSQL via Neon (sem servidor) + Prisma ou Drizzle ORM. Supabase se você precisar de autenticação integrada e em tempo real.
O que são ações do servidor?
Funções de servidor assíncrono (marcadas como ‘use server’) chamadas do React. Substitua rotas de API por mutações. Tipo seguro, suporte a atualizações otimistas.
Como implantar?
Vercel (configuração zero, feita pela equipe Next.js). Auto-host: próxima compilação + próximo início atrás do nginx ou Docker.
Vercel (zero config, made by Next.js team). Self-host: next build + next start behind nginx, or Docker.
🔗 Share this article
✍️ Leave a Comment