PromptFork

Next.js 15 App Router page with streaming, caching, and server data

Scaffold a production App Router page: Server Component data fetching, Suspense streaming for instant TTFB, correct cache strategy (fetch cache vs unstable_cache vs revalidatePath), loading/error boundaries, and generateMetadata — with the non-obvious patterns most tutorials skip.

Open in Studio
Prompt
You are a senior Next.js 15 engineer who optimizes for both DX and Core Web Vitals. Create a new route at `app/[ROUTE]/page.tsx` for a TypeScript App Router project.

Requirements:
- The page is a Server Component. Fetch data from [API/DATA SOURCE] directly in the component body — no client-side useEffect. Type the response with an explicit interface (no `any`, no `as` casts).
- Wrap the slow/data-dependent section in `<Suspense fallback={<Loading />}>` so the shell streams instantly (PPR-ready). If the page has independent data needs (e.g., sidebar + main), fetch them in parallel server components inside separate Suspense boundaries — do NOT waterfall.
- Add sibling files: `loading.tsx` (skeleton matching the real layout, not a spinner) and `error.tsx` (with a `reset` button that calls `reset()` from the error boundary props).
- Export `generateMetadata` that derives a real title and description from the fetched data.

Caching — choose the RIGHT layer and explain your choice:
| Strategy | When to use |
|---|---|
| `fetch(..., { next: { revalidate: 60 } })` | External API, time-based freshness is fine |
| `unstable_cache(fn, [keys], { revalidate, tags })` | DB queries or non-fetch data sources that need tag-based invalidation via `revalidateTag()` |
| `revalidatePath('/route')` | On-demand revalidation after a mutation (Server Action) |
| No cache / `{ cache: 'no-store' }` | User-specific data (behind auth) that must never be shared |

Apply the correct strategy for [API/DATA SOURCE] and add a comment explaining why.

- If any part requires interactivity, extract it into its own `'use client'` child component. Keep the client surface minimal.
- If a modal or sidebar makes sense, show how to use a Parallel Route (`@modal/default.tsx`) intercepted via `(.)` so it overlays without a full navigation.

Return the full contents of each file in separate fenced code blocks. After the code, add a 3-line note: (1) the caching strategy you chose and why, (2) what would change if this data were user-specific, (3) one thing to watch for when deploying to Vercel vs self-hosted.
Source
promptfork seed
License
CC-BY-4.0
Published
6/23/2026

More prompts you might like

Tailwind analytics dashboard with animated stat cards, dark mode, and skeleton loading

Production-grade dashboard layout: KPI cards with counting animations and trend sparklines, a chart area, activity table — all with dark mode, skeleton loading states, and responsive breakpoints defined to the pixel.

New

Supabase RLS: owner-write, public-read policies for a table

Generate correct, non-recursive RLS policies so anyone reads published rows and only owners edit their own.

New

Stripe webhook handler with signature verify + idempotency

Production-ready Stripe webhook route that verifies the signature and processes events exactly once.

New

.cursorrules for a strict TypeScript + React codebase

A tuned .cursorrules file that keeps Cursor's agent on-convention: strict types, no dead code, match existing patterns.

New

Refactor a React component into clean custom hooks

Extract stateful logic from a bloated component into typed, testable custom hooks.

New

Diagnose and fix a slow SQL query using EXPLAIN ANALYZE like a DBA

Paste a slow query and get a root-cause diagnosis, targeted index/rewrite fixes, and a before/after query plan — with specific pattern detection for N+1s, implicit casts, and composite index gaps.

New