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" } ] } ] }