Domine a integração entre Next.js 14 e Shadcn/UI. Aprenda App Router, Server Components, SSR e técnicas avançadas de performance.
A combinação perfeita para aplicações React modernas. Server Components, App Router e componentes UI profissionais em um só lugar.
A stack mais poderosa para React em 2025. Next.js 14 oferece performance extrema com App Router, enquanto Shadcn/UI fornece componentes prontos para produção.
85% das empresas Fortune 500 usam Next.js para aplicações React. Combinado com Shadcn/UI, você tem a stack mais produtiva e performática do mercado.
Zero JavaScript no cliente para componentes estáticos. Performance máxima e SEO perfeito.
Roteamento baseado em arquivos com layouts aninhados e loading states automáticos.
Integração nativa com componentes otimizados para Server e Client Components.
Renderização no servidor por padrão. Componentes Shadcn/UI funcionam perfeitamente com RSC.
Turbopack + Shadcn/UI resulta em builds 10x mais rápidos e bundle size 60% menor.
SSR + SSG automático com componentes UI acessíveis e semânticos por padrão.
Fetch no servidor com cache automático. Componentes recebem dados diretamente.
Type safety completo entre Server Components, Client Components e props Shadcn/UI.
Vercel integration com edge functions e componentes otimizados para CDN global.
Configuração completa em 10 minutos. Do zero até uma aplicação pronta para produção.
Configuração correta garante máxima performance. App Router + Shadcn/UI configurados adequadamente resultam em aplicações que carregam em menos de 1 segundo.
Use create-next-app com App Router para aproveitar todas as funcionalidades do Next.js 14.
Shadcn/UI se integra perfeitamente com Next.js 14 e App Router.
✔ Would you like to use TypeScript (recommended)? … yes ✔ Which style would you like to use? › Default ✔ Which color would you like to use as base color? › Slate ✔ Where is your global CSS file? … src/app/globals.css ✔ Would you like to use CSS variables for colors? … yes ✔ Where is your tailwind.config.js located? … tailwind.config.ts ✔ Configure the import alias for components? … src/components ✔ Configure the import alias for utils? … src/lib/utils
Otimize a integração entre App Router e componentes Shadcn/UI.
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import './globals.css'
import { ThemeProvider } from '@/components/theme-provider'
import { Toaster } from '@/components/ui/toaster'
const inter = Inter({ subsets: ['latin'] })
export const metadata: Metadata = {
title: 'Minha App Next.js + Shadcn/UI',
description: 'Aplicação moderna com Next.js 14 e Shadcn/UI'
}
export default function RootLayout({
children
}: {
children: React.ReactNode
}) {
return (
<html lang="pt-BR" suppressHydrationWarning>
<body className={inter.className}>
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
{children}
<Toaster />
</ThemeProvider>
</body>
</html>
)
}"use client"
import * as React from "react"
import { ThemeProvider as NextThemesProvider } from "next-themes"
import { type ThemeProviderProps } from "next-themes/dist/types"
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
return <NextThemesProvider {...props}>{children}</NextThemesProvider>
}ThemeProvider deve ser Client Component ("use client") porque usa hooks do next-themes.
Padrões reais de produção usando Server Components, Client Components e data fetching otimizado.
Estes padrões são usados por empresas como Vercel, Linear e Supabase. Aprenda com código real que escala para milhões de usuários.
// app/blog/page.tsx - Server Component
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import Link from 'next/link'
// Fetch com cache automático
async function getPosts() {
const res = await fetch('https://api.example.com/posts', {
next: { revalidate: 3600 } // Cache por 1 hora
})
if (!res.ok) {
throw new Error('Failed to fetch posts')
}
return res.json()
}
export default async function BlogPage() {
// Data fetching no servidor
const posts = await getPosts()
return (
<div className="container mx-auto py-8">
<div className="mb-8">
<h1 className="text-4xl font-bold mb-2">Blog</h1>
<p className="text-muted-foreground">
Artigos sobre desenvolvimento web
</p>
</div>
<div className="grid gap-6 md:grid-cols-2 lg:grid-cols-3">
{posts.map((post: any) => (
<Card key={post.id} className="hover:shadow-lg transition-shadow">
<CardHeader>
<div className="flex items-center gap-2 mb-2">
<Badge variant="secondary">{post.category}</Badge>
<span className="text-sm text-muted-foreground">
{new Date(post.date).toLocaleDateString('pt-BR')}
</span>
</div>
<CardTitle className="line-clamp-2">{post.title}</CardTitle>
</CardHeader>
<CardContent>
<p className="text-muted-foreground mb-4 line-clamp-3">
{post.excerpt}
</p>
<Button asChild variant="outline" className="w-full">
<Link href={`/blog/${post.slug}`}>
Ler artigo
</Link>
</Button>
</CardContent>
</Card>
))}
</div>
</div>
)
}"use client"
import { useState } from 'react'
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import * as z from 'zod'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { useToast } from '@/components/ui/use-toast'
const formSchema = z.object({
email: z.string().email('Email inválido'),
message: z.string().min(10, 'Mensagem deve ter pelo menos 10 caracteres')
})
type FormData = z.infer<typeof formSchema>
export function ContactForm() {
const [isLoading, setIsLoading] = useState(false)
const { toast } = useToast()
const {
register,
handleSubmit,
formState: { errors },
reset
} = useForm<FormData>({
resolver: zodResolver(formSchema)
})
const onSubmit = async (data: FormData) => {
setIsLoading(true)
try {
const response = await fetch('/api/contact', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
})
if (response.ok) {
toast({
title: 'Sucesso!',
description: 'Mensagem enviada com sucesso.'
})
reset()
} else {
throw new Error('Erro ao enviar mensagem')
}
} catch (error) {
toast({
title: 'Erro',
description: 'Falha ao enviar mensagem. Tente novamente.',
variant: 'destructive'
})
} finally {
setIsLoading(false)
}
}
return (
<Card className="w-full max-w-md mx-auto">
<CardHeader>
<CardTitle>Entre em Contato</CardTitle>
</CardHeader>
<CardContent>
<form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
<div>
<Label htmlFor="email">Email</Label>
<Input
id="email"
type="email"
{...register('email')}
className={errors.email ? 'border-red-500' : ''}
/>
{errors.email && (
<p className="text-sm text-red-500 mt-1">
{errors.email.message}
</p>
)}
</div>
<div>
<Label htmlFor="message">Mensagem</Label>
<textarea
id="message"
{...register('message')}
className={`flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 ${errors.message ? 'border-red-500' : ''}`}
/>
{errors.message && (
<p className="text-sm text-red-500 mt-1">
{errors.message.message}
</p>
)}
</div>
<Button type="submit" className="w-full" disabled={isLoading}>
{isLoading ? 'Enviando...' : 'Enviar Mensagem'}
</Button>
</form>
</CardContent>
</Card>
)
}Otimizações avançadas para máxima performance em produção.
10x mais rápido que Webpack em desenvolvimento.
import Image from 'next/image'
<Image
src="/hero.jpg"
alt="Hero image"
width={800}
height={400}
priority // Above fold
placeholder="blur"
blurDataURL="data:image/jpeg;base64,..."
/>Deploy global em 30+ regiões automaticamente.
{
"buildCommand": "next build",
"outputDirectory": ".next",
"framework": "nextjs",
"regions": ["iad1", "sfo1"],
"headers": [
{
"source": "/(.*)",
"headers": [
{
"key": "X-Frame-Options",
"value": "DENY"
}
]
}
]
}