AEAl-Andalus⺢Experience
Sign in · Join
AEAl-Andalus⺢Experience
ProjectsGalleryAboutArticlesDashboardAPI
© 2026 — Modular content systems☕buy me a coffee
Framework Study Guide
ChaptersCardsLegendRoadmapRoute Map
Chapters
00 · Root Layout01 · Server Page (page.tsx)01a · Special Files (not-found, error, loading)02 · Client Component (UI & Interaction)02a · Client Boundaries & Islands03 · Entity Actions (actions/*.ts)04 · Server Actions ("use server")05 · Context Provider (context/*.tsx)06 · API Route (app/(api)/<entity>/route.ts)07 · TypeScript + Prisma08 · Entity-First Feature Design09 · Deployment, Docker & Cloud10 · Next 16 + Prisma 7 Upgrade11 · Prisma 7 (SQLite-first, App Router)12 · TypeORM (Entities + Migrations)13 · Drizzle ORM (SQL-first)11 · CSS, Mobile-First Flex, Tailwind12 · Libraries, Accelerators & Production Shortcuts14 · Next.js 16: cache, PPR, proxy, AI
→ cards/01-server-action

Chapter

01 · Server Page (page.tsx)

Read-only orchestration: fetch via get*, enforce visibility, pass promises to UI.

Mental Model

  • Server Pages are read-only conductors; they assemble data, enforce visibility, hand off to UI.
  • Not smart, not mutable, not domain owners.
  • Use entity get* actions; prefer promise-passing for Suspense/streaming.

File Classification

Layer: Route entry / orchestration
Component: Server Component
Runtime: Server
Prisma: ❌ Never
Server Actions: ❌ (no mutations)
API Routes: ❌ Never
Suspense Prep: ✅ Yes

Should Do

  • Read data via entity actions (get*).
  • Coordinate multiple entities (read-only).
  • Enforce visibility/permissions (light gatekeeping).
  • Pass data or promises to client components; prepare Suspense.

Should Not (and where it belongs)

  • Prisma queries → put them in entity actions.
  • Mutations → server actions or API routes for external callers.
  • Business rules → domain/entity layer, not in page.tsx.
  • Internal API calls → call actions directly; skip fetch("/api/...").

Canonical Example

import { getProjects } from "./actions/getProjects";
import ProjectsClient from "./components/ProjectsClient";

export default async function ProjectsPage() {
const projectsPromise = getProjects(); // promise for Suspense
return <ProjectsClient projectsPromise={projectsPromise} />;
}

Colour-Coded Miniature

import { getProjects } from "./actions/getProjects";
import ProjectsClient from "./components/ProjectsClient";

export default async function ProjectsPage() {
const projectsPromise = getProjects(); // promise for Suspense
return <ProjectsClient projectsPromise={projectsPromise} />;
}

Quick Rules

  • Server Pages are read-only; no mutations.
  • Call get* actions only; never Prisma here.
  • Pass promises when possible (Suspense-friendly).
  • Gatekeep visibility/auth lightly; defer domain rules to entities.