Setup completo do projeto com Next.js 14, TypeScript, Tailwind CSS e configuração do App Router para o frontend do Restaurantix.
Nesta aula vamos configurar o ambiente completo para desenvolver o frontend do Restaurantix usando as tecnologias mais modernas.
# Criar projeto Next.js com todas as configurações npx create-next-app@latest restaurantix-frontend \ --typescript \ --tailwind \ --eslint \ --app \ --src-dir \ --import-alias "@/*" # Entrar no diretório cd restaurantix-frontend # Instalar dependências adicionais npm install lucide-react class-variance-authority clsx tailwind-merge
--typescript
Configura TypeScript automaticamente--tailwind
Instala e configura Tailwind CSS--app
Usa o novo App Router (recomendado)--src-dir
Organiza código na pasta src/--import-alias
Configura imports absolutos com @/restaurantix-frontend/ ├── src/ │ ├── app/ # App Router (Next.js 14) │ │ ├── globals.css # Estilos globais │ │ ├── layout.tsx # Layout principal │ │ ├── page.tsx # Página inicial │ │ └── loading.tsx # Loading UI │ ├── components/ # Componentes reutilizáveis │ │ ├── ui/ # Componentes base (shadcn/ui) │ │ └── layout/ # Componentes de layout │ ├── lib/ # Utilitários e configurações │ │ ├── utils.ts # Funções utilitárias │ │ └── api.ts # Cliente da API │ ├── hooks/ # Custom hooks │ ├── store/ # Estado global (Zustand) │ └── types/ # Definições de tipos ├── public/ # Arquivos estáticos ├── tailwind.config.ts # Configuração Tailwind ├── tsconfig.json # Configuração TypeScript └── next.config.js # Configuração Next.js
# Criar estrutura de pastas mkdir -p src/components/ui mkdir -p src/components/layout mkdir -p src/lib mkdir -p src/hooks mkdir -p src/store mkdir -p src/types # Criar arquivos base touch src/lib/utils.ts touch src/lib/api.ts touch src/types/index.ts
import type { Config } from 'tailwindcss' const config: Config = { content: [ './src/pages/**/*.{js,ts,jsx,tsx,mdx}', './src/components/**/*.{js,ts,jsx,tsx,mdx}', './src/app/**/*.{js,ts,jsx,tsx,mdx}', ], theme: { extend: { colors: { border: "hsl(var(--border))", input: "hsl(var(--input))", ring: "hsl(var(--ring))", background: "hsl(var(--background))", foreground: "hsl(var(--foreground))", primary: { DEFAULT: "hsl(var(--primary))", foreground: "hsl(var(--primary-foreground))", }, secondary: { DEFAULT: "hsl(var(--secondary))", foreground: "hsl(var(--secondary-foreground))", }, destructive: { DEFAULT: "hsl(var(--destructive))", foreground: "hsl(var(--destructive-foreground))", }, muted: { DEFAULT: "hsl(var(--muted))", foreground: "hsl(var(--muted-foreground))", }, accent: { DEFAULT: "hsl(var(--accent))", foreground: "hsl(var(--accent-foreground))", }, popover: { DEFAULT: "hsl(var(--popover))", foreground: "hsl(var(--popover-foreground))", }, card: { DEFAULT: "hsl(var(--card))", foreground: "hsl(var(--card-foreground))", }, }, borderRadius: { lg: "var(--radius)", md: "calc(var(--radius) - 2px)", sm: "calc(var(--radius) - 4px)", }, }, }, plugins: [], } export default config
import { type ClassValue, clsx } from "clsx" import { twMerge } from "tailwind-merge" export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } export function formatCurrency(value: number) { return new Intl.NumberFormat('pt-BR', { style: 'currency', currency: 'BRL', }).format(value / 100) } export function formatDate(date: string | Date) { return new Intl.DateTimeFormat('pt-BR', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit', }).format(new Date(date)) }
/** @type {import('next').NextConfig} */ const nextConfig = { experimental: { appDir: true, }, env: { NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3333', }, images: { domains: ['localhost'], }, } module.exports = nextConfig
import type { Metadata } from 'next' import { Inter } from 'next/font/google' import './globals.css' const inter = Inter({ subsets: ['latin'] }) export const metadata: Metadata = { title: 'Restaurantix - Dashboard', description: 'Sistema de gestão para restaurantes', } export default function RootLayout({ children, }: { children: React.ReactNode }) { return ( <html lang="pt-BR"> <body className={inter.className}> <div className="min-h-screen bg-gray-50"> {children} </div> </body> </html> ) }
export default function HomePage() { return ( <div className="container mx-auto px-4 py-8"> <div className="text-center"> <h1 className="text-4xl font-bold text-gray-900 mb-4"> Restaurantix Dashboard </h1> <p className="text-xl text-gray-600 mb-8"> Sistema de gestão para restaurantes </p> <div className="bg-white rounded-lg shadow-lg p-8 max-w-md mx-auto"> <h2 className="text-2xl font-semibold mb-4"> 🚀 Projeto Configurado! </h2> <p className="text-gray-600"> Next.js 14 com App Router, TypeScript e Tailwind CSS estão funcionando perfeitamente. </p> </div> </div> </div> ) }
# Executar em modo desenvolvimento npm run dev # Ou com yarn yarn dev # Ou com pnpm pnpm dev
http://localhost:3000
Agora é sua vez! Complete os seguintes desafios:
Modifique o componente da página inicial para incluir:
Crie um componente Button
em src/components/ui/
:
Crie um arquivo .env.local
com:
NEXT_PUBLIC_API_URL=http://localhost:3333 NEXT_PUBLIC_APP_NAME=Restaurantix
npx create-next-app@latest
sempre