├── .gitignore ├── .prettierrc ├── README.md ├── app ├── favicon.ico ├── layout.tsx ├── not-found.tsx ├── opengraph-image.png ├── page.tsx ├── styles.tsx └── twitter-image.png ├── components ├── add-to-cart.tsx ├── byline.tsx ├── cart-count-context.tsx ├── cart-count.tsx ├── header.tsx ├── next-logo.tsx ├── ping.tsx ├── pricing.tsx ├── product-best-seller.tsx ├── product-card.tsx ├── product-currency-symbol.tsx ├── product-deal.tsx ├── product-estimated-arrival.tsx ├── product-lightening-deal.tsx ├── product-low-stock-warning.tsx ├── product-price.tsx ├── product-rating.tsx ├── product-review-card.tsx ├── product-split-payments.tsx ├── product-used-price.tsx ├── recommended-products.tsx ├── reviews.tsx ├── sidebar.tsx ├── single-product.tsx └── vercel-logo.tsx ├── lib └── delay.ts ├── next-env.d.ts ├── next.config.js ├── package.json ├── pnpm-lock.yaml ├── postcss.config.js ├── public ├── alexander-andrews-brAkTCdnhW8-unsplash.jpg ├── eniko-kis-KsLPTsYaqIQ-unsplash.jpg ├── grid.svg ├── guillaume-coupy-6HuoHgK7FN8-unsplash.jpg ├── nextjs-icon-light-background.png ├── patrick-OIFgeLnjwrM-unsplash.jpg ├── prince-akachi-LWkFHEGpleE-unsplash.jpg └── yoann-siloine-_T4w3JDm6ug-unsplash.jpg ├── tailwind.config.ts ├── tsconfig.json └── types ├── product.d.ts └── review.d.ts /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | /.yarn 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | .pnpm-debug.log* 28 | 29 | # local env files 30 | .env* 31 | !.env*.example 32 | 33 | # vercel 34 | .vercel 35 | 36 | # typescript 37 | *.tsbuildinfo 38 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Next.js Partial Prerendering 2 | 3 | This is a demo of [Next.js](https://nextjs.org) using [Partial Prerendering](https://nextjs.org/docs/app/api-reference/next-config-js/ppr). 4 | 5 | This template uses the new Next.js [App Router](https://nextjs.org/docs/app). This includes support for enhanced layouts, colocation of components, tests, and styles, component-level data fetching, and more. 6 | 7 | It also uses the experimental Partial Prerendering feature available in Next.js 14. Partial Prerendering combines ultra-quick static edge delivery with fully dynamic capabilities and we believe it has the potential to [become the default rendering model for web applications](https://vercel.com/blog/partial-prerendering-with-next-js-creating-a-new-default-rendering-model), bringing together the best of static site generation and dynamic delivery. 8 | 9 | > ⚠️ Please note that PPR is an experimental technology that is not recommended for production. You may run into some DX issues, especially on larger code bases. 10 | 11 | ## How it works 12 | 13 | The index route `/` uses Partial Prerendering through: 14 | 15 | 1. Enabling the experimental flag in `next.config.js`. 16 | 17 | ```js 18 | experimental: { 19 | ppr: true, 20 | }, 21 | ``` 22 | 23 | 2. Using `` to wrap Dynamic content. 24 | -------------------------------------------------------------------------------- /app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vercel-labs/next-partial-prerendering/89a7ef8ca8804dc0d49c72199970a7c548d66b9c/app/favicon.ico -------------------------------------------------------------------------------- /app/layout.tsx: -------------------------------------------------------------------------------- 1 | import { CartCountProvider } from "#/components/cart-count-context"; 2 | import { Header } from "#/components/header"; 3 | import { Sidebar } from "#/components/sidebar"; 4 | import { Metadata } from "next"; 5 | import { GlobalStyles } from "./styles"; 6 | 7 | export const metadata: Metadata = { 8 | metadataBase: new URL("https://partialprerendering.com"), 9 | title: "Next.js Partial Prerendering", 10 | description: "A demo of Next.js using Partial Prerendering.", 11 | openGraph: { 12 | title: "Next.js Partial Prerendering", 13 | description: "A demo of Next.js using Partial Prerendering.", 14 | }, 15 | twitter: { 16 | card: "summary_large_image", 17 | }, 18 | }; 19 | 20 | export default function RootLayout({ 21 | children, 22 | }: { 23 | children: React.ReactNode; 24 | }) { 25 | return ( 26 | 27 | 28 | 29 | 30 | 31 | 32 |
33 |
34 |
35 |
36 | 37 |
38 |
39 | 40 | {children} 41 |
42 |
43 |
44 |
45 |
46 |
47 | 48 | 49 | ); 50 | } 51 | -------------------------------------------------------------------------------- /app/not-found.tsx: -------------------------------------------------------------------------------- 1 | export default function NotFound() { 2 | return ( 3 |
4 |

Not Found

5 |

Could not find requested resource

6 |
7 | ); 8 | } 9 | -------------------------------------------------------------------------------- /app/opengraph-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vercel-labs/next-partial-prerendering/89a7ef8ca8804dc0d49c72199970a7c548d66b9c/app/opengraph-image.png -------------------------------------------------------------------------------- /app/page.tsx: -------------------------------------------------------------------------------- 1 | import { Suspense } from 'react'; 2 | import { 3 | RecommendedProducts, 4 | RecommendedProductsSkeleton, 5 | } from '#/components/recommended-products'; 6 | import { Reviews, ReviewsSkeleton } from '#/components/reviews'; 7 | import { SingleProduct } from '#/components/single-product'; 8 | import { Ping } from '#/components/ping'; 9 | 10 | export default function Page() { 11 | return ( 12 |
13 | 14 | 15 | 16 | 17 | }> 18 | 19 | 20 | 21 | 22 | 23 | }> 24 | 25 | 26 |
27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /app/styles.tsx: -------------------------------------------------------------------------------- 1 | export function GlobalStyles() { 2 | return ( 3 |