This project is built with Next.js 15 using the App Router architecture, which provides a modern, file-based routing system with built-in support for Server Components and Server Actions.
By default, all components in Next.js 15 are Server Components. They run on the server and have access to backend resources.Example fromsrc/app/page.tsx:9-24:
export default async function page() { if (!process.env.BACKEND_URL) { return <p>Backend URL not found</p>; } let data; try { const response = await fetch(`${process.env.BACKEND_URL}/time-left`, { method: "GET", }); data = await response.json(); if (response.status != 200) { <div className="h-screen grid place-items-center"> <h1 className="font-bold text-4xl">Backend Cannot Be Accessed</h1> </div>; } } catch (e) { // Error handling... }}
Client Components are marked with "use client" directive and run in the browser. They’re needed for interactivity.Example fromsrc/components/CreateMessageForm.tsx:1-25:
"use client";import { useActionState, useEffect } from "react";import createMessage from "@/lib/actions/message/createMessage";export default function MessageUpdateForm({ people }: { people: People[] }) { const [createState, createAction, createIsPending] = useActionState( createMessage, {} ); useEffect(() => { if (createState.success) { toast.success("Message created successfully", { richColors: true, }); } }, [createState]); return ( <form action={createAction} className="space-y-3 flex flex-col"> {/* Form fields */} </form> );}
Client Components cannot directly access server-only APIs like environment variables or databases. Use Server Actions to bridge this gap.