Next.js
Structure
Section titled “Structure”apps/web/├── app/ # App Router│ ├── (auth)/ # Auth routes (sign-in, sign-up)│ ├── (protected)/ # Authenticated routes│ ├── api/ # API routes│ └── layout.tsx # Root layout├── components/ # React components├── lib/ # Utilities└── next.config.ts # Next.js configRoute Groups
Section titled “Route Groups”Route groups (name) organize routes without affecting URLs:
app/├── (auth)/│ ├── sign-in/page.tsx # /sign-in│ └── sign-up/page.tsx # /sign-up├── (protected)/│ └── dashboard/page.tsx # /dashboard└── page.tsx # /Layouts
Section titled “Layouts”Root Layout
Section titled “Root Layout”export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="en"> <body> <Providers>{children}</Providers> </body> </html> )}Nested Layouts
Section titled “Nested Layouts”// app/(protected)/layout.tsxexport default function ProtectedLayout({ children }: { children: React.ReactNode }) { return ( <AuthGuard> <Sidebar /> <main>{children}</main> </AuthGuard> )}Client Components
Section titled “Client Components”Use "use client" for interactive components:
"use client"
import { useState } from "react"
export function Counter() { const [count, setCount] = useState(0) return <button onClick={() => setCount((c) => c + 1)}>{count}</button>}Server Components
Section titled “Server Components”Default behavior - can fetch data directly:
// app/page.tsx (Server Component by default)export default async function Page() { const data = await fetchData() return <div>{data}</div>}API Routes
Section titled “API Routes”import { NextResponse } from "next/server"
export async function GET() { return NextResponse.json({ message: "Hello" })}
export async function POST(request: Request) { const body = await request.json() return NextResponse.json({ received: body })}Imports
Section titled “Imports”UI Components
Section titled “UI Components”import { Button } from "@repo/ui/components/ui/button"import { Card } from "@repo/ui/components/ui/card"
// Or barrel importimport { Button, Card, Input } from "@repo/ui/components/ui"Utilities
Section titled “Utilities”import { cn } from "@repo/ui/lib/utils"Convex
Section titled “Convex”import { api } from "@repo/backend/convex"import { useMutation, useQuery } from "convex/react"Environment Variables
Section titled “Environment Variables”In .env.local:
NEXT_PUBLIC_CONVEX_URL=https://...CONVEX_DEPLOYMENT=dev:...Access in code:
// Client-side (must have NEXT_PUBLIC_ prefix)const url = process.env.NEXT_PUBLIC_CONVEX_URL
// Server-side onlyconst secret = process.env.API_SECRETCommands
Section titled “Commands”# Developmentturbo dev --filter=web
# Buildturbo build --filter=web
# Type checkturbo check-types --filter=web