Skip to content

Commit 60e9a58

Browse files
authored
[cdn] Add descriptive home pages and timeout test route to custom err… (#1388)
### Description Making the home pages descriptive and adding a testable error route ### Demo URL https://custom-error-pages-public-dir.vercel.app/ https://custom-error-pages-app-dir.vercel.app/ ### Type of Change - [ ] New Example - [x] Example updates (Bug fixes, new features, etc.) - [ ] Other (changes to the codebase, but not to examples) ### New Example Checklist - [ ] 🛫 `npm run new-example` was used to create the example - [x] 📚 The template wasn't used but I carefuly read the [Adding a new example](https://github.com/vercel/examples#adding-a-new-example) steps and implemented them in the example - [ ] 📱 Is it responsive? Are mobile and tablets considered?
1 parent cf1f3bc commit 60e9a58

File tree

6 files changed

+206
-76
lines changed

6 files changed

+206
-76
lines changed

cdn/custom-error-pages-app-dir/app/page.tsx

Lines changed: 72 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,56 +3,90 @@ import Image from "next/image";
33
export default function Home() {
44
return (
55
<div className="flex min-h-screen items-center justify-center bg-zinc-50 font-sans dark:bg-black">
6-
<main className="flex min-h-screen w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black sm:items-start">
6+
<main className="flex min-h-screen w-full max-w-3xl flex-col items-center justify-between py-16 px-8 bg-white dark:bg-black sm:items-start sm:px-16 sm:py-24">
77
<Image
88
className="dark:invert"
9-
src="/next.svg"
10-
alt="Next.js logo"
11-
width={100}
12-
height={20}
9+
src="/vercel.svg"
10+
alt="Vercel logo"
11+
width={120}
12+
height={28}
1313
priority
1414
/>
1515
<div className="flex flex-col items-center gap-6 text-center sm:items-start sm:text-left">
16-
<h1 className="max-w-xs text-3xl font-semibold leading-10 tracking-tight text-black dark:text-zinc-50">
17-
To get started, edit the page.tsx file.
16+
<h1 className="max-w-lg text-3xl font-semibold leading-10 tracking-tight text-black dark:text-zinc-50">
17+
Custom Error Pages with App Router
1818
</h1>
19-
<p className="max-w-md text-lg leading-8 text-zinc-600 dark:text-zinc-400">
20-
Looking for a starting point or more instructions? Head over to{" "}
21-
<a
22-
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
23-
className="font-medium text-zinc-950 dark:text-zinc-50"
24-
>
25-
Templates
26-
</a>{" "}
27-
or the{" "}
28-
<a
29-
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
30-
className="font-medium text-zinc-950 dark:text-zinc-50"
31-
>
32-
Learning
33-
</a>{" "}
34-
center.
19+
<p className="max-w-lg text-base leading-7 text-zinc-600 dark:text-zinc-400">
20+
This example demonstrates how to create custom error pages using
21+
Next.js App Router conventions. Replace Vercel&apos;s default
22+
platform error pages with your own branded experience for errors
23+
like function timeouts or throttling.
3524
</p>
25+
<div className="max-w-lg text-base leading-7 text-zinc-600 dark:text-zinc-400">
26+
<p className="font-medium text-zinc-800 dark:text-zinc-200">
27+
How it works:
28+
</p>
29+
<ul className="mt-2 list-disc pl-5 space-y-1">
30+
<li>
31+
Create error pages at <code className="text-sm bg-zinc-100 dark:bg-zinc-800 px-1.5 py-0.5 rounded">app/500/page.tsx</code> and{" "}
32+
<code className="text-sm bg-zinc-100 dark:bg-zinc-800 px-1.5 py-0.5 rounded">app/504/page.tsx</code>
33+
</li>
34+
<li>
35+
Vercel automatically detects and serves these for platform
36+
errors
37+
</li>
38+
<li>
39+
The 500 page acts as a fallback for all unhandled error codes
40+
</li>
41+
</ul>
42+
</div>
43+
<div className="max-w-lg text-base leading-7 text-zinc-600 dark:text-zinc-400">
44+
<p className="font-medium text-zinc-800 dark:text-zinc-200">
45+
Template tokens:
46+
</p>
47+
<ul className="mt-2 list-disc pl-5 space-y-1">
48+
<li>
49+
<code className="text-sm bg-zinc-100 dark:bg-zinc-800 px-1.5 py-0.5 rounded">::vercel:REQUEST_ID::</code> - Unique request identifier
50+
</li>
51+
<li>
52+
<code className="text-sm bg-zinc-100 dark:bg-zinc-800 px-1.5 py-0.5 rounded">::vercel:ERROR_CODE::</code> - Error type (e.g.,
53+
FUNCTION_INVOCATION_TIMEOUT)
54+
</li>
55+
</ul>
56+
</div>
57+
<div className="max-w-lg text-base leading-7 text-zinc-600 dark:text-zinc-400">
58+
<p className="font-medium text-zinc-800 dark:text-zinc-200">
59+
Try it out:
60+
</p>
61+
<p className="mt-2">
62+
Click &quot;Trigger Timeout&quot; to trigger a function timeout and see
63+
the custom error page in action. The page is configured to timeout
64+
after 3 seconds.
65+
</p>
66+
</div>
3667
</div>
37-
<div className="flex flex-col gap-4 text-base font-medium sm:flex-row">
68+
<div className="flex flex-col gap-4 text-base font-medium sm:flex-row sm:flex-wrap">
3869
<a
39-
className="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-foreground px-5 text-background transition-colors hover:bg-[#383838] dark:hover:bg-[#ccc] md:w-[158px]"
40-
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
41-
target="_blank"
42-
rel="noopener noreferrer"
70+
className="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-foreground px-5 text-background transition-colors hover:bg-[#383838] dark:hover:bg-[#ccc] sm:w-auto"
71+
href="/slow-page"
72+
>
73+
Trigger Timeout
74+
</a>
75+
<a
76+
className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] sm:w-auto"
77+
href="/500"
78+
>
79+
View 500 Page
80+
</a>
81+
<a
82+
className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] sm:w-auto"
83+
href="/504"
4384
>
44-
<Image
45-
className="dark:invert"
46-
src="/vercel.svg"
47-
alt="Vercel logomark"
48-
width={16}
49-
height={16}
50-
/>
51-
Deploy Now
85+
View 504 Page
5286
</a>
5387
<a
54-
className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] md:w-[158px]"
55-
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
88+
className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] sm:w-auto"
89+
href="https://vercel.com/docs/custom-error-pages"
5690
target="_blank"
5791
rel="noopener noreferrer"
5892
>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Force dynamic rendering so the sleep happens on each request
2+
export const dynamic = "force-dynamic";
3+
4+
function sleep(ms: number) {
5+
return new Promise((resolve) => setTimeout(resolve, ms));
6+
}
7+
8+
export default async function SlowPage() {
9+
// Sleep for 60 seconds - this will trigger a timeout since maxDuration is 3s
10+
await sleep(60000);
11+
12+
return (
13+
<div className="flex min-h-screen flex-col items-center justify-center px-6 py-24 bg-gray-50">
14+
<div className="text-center">
15+
<h1 className="text-3xl font-bold tracking-tight text-gray-900">
16+
Slow Page
17+
</h1>
18+
<p className="mt-6 text-base leading-7 text-gray-600">
19+
If you see this, the page did not timeout (waited 60 seconds).
20+
</p>
21+
</div>
22+
</div>
23+
);
24+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"functions": {
3+
"app/slow-page/page.tsx": {
4+
"maxDuration": 3
5+
}
6+
}
7+
}

cdn/custom-error-pages-public-dir/app/page.tsx

Lines changed: 72 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,56 +3,90 @@ import Image from "next/image";
33
export default function Home() {
44
return (
55
<div className="flex min-h-screen items-center justify-center bg-zinc-50 font-sans dark:bg-black">
6-
<main className="flex min-h-screen w-full max-w-3xl flex-col items-center justify-between py-32 px-16 bg-white dark:bg-black sm:items-start">
6+
<main className="flex min-h-screen w-full max-w-3xl flex-col items-center justify-between py-16 px-8 bg-white dark:bg-black sm:items-start sm:px-16 sm:py-24">
77
<Image
88
className="dark:invert"
9-
src="/next.svg"
10-
alt="Next.js logo"
11-
width={100}
12-
height={20}
9+
src="/vercel.svg"
10+
alt="Vercel logo"
11+
width={120}
12+
height={28}
1313
priority
1414
/>
1515
<div className="flex flex-col items-center gap-6 text-center sm:items-start sm:text-left">
16-
<h1 className="max-w-xs text-3xl font-semibold leading-10 tracking-tight text-black dark:text-zinc-50">
17-
To get started, edit the page.tsx file.
16+
<h1 className="max-w-lg text-3xl font-semibold leading-10 tracking-tight text-black dark:text-zinc-50">
17+
Custom Error Pages with Public Directory
1818
</h1>
19-
<p className="max-w-md text-lg leading-8 text-zinc-600 dark:text-zinc-400">
20-
Looking for a starting point or more instructions? Head over to{" "}
21-
<a
22-
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
23-
className="font-medium text-zinc-950 dark:text-zinc-50"
24-
>
25-
Templates
26-
</a>{" "}
27-
or the{" "}
28-
<a
29-
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
30-
className="font-medium text-zinc-950 dark:text-zinc-50"
31-
>
32-
Learning
33-
</a>{" "}
34-
center.
19+
<p className="max-w-lg text-base leading-7 text-zinc-600 dark:text-zinc-400">
20+
This example demonstrates how to create custom error pages using
21+
static HTML files in the public directory. Replace Vercel&apos;s
22+
default platform error pages with your own branded experience for
23+
errors like function timeouts or throttling.
3524
</p>
25+
<div className="max-w-lg text-base leading-7 text-zinc-600 dark:text-zinc-400">
26+
<p className="font-medium text-zinc-800 dark:text-zinc-200">
27+
How it works:
28+
</p>
29+
<ul className="mt-2 list-disc pl-5 space-y-1">
30+
<li>
31+
Add static HTML files at <code className="text-sm bg-zinc-100 dark:bg-zinc-800 px-1.5 py-0.5 rounded">public/500.html</code> and{" "}
32+
<code className="text-sm bg-zinc-100 dark:bg-zinc-800 px-1.5 py-0.5 rounded">public/504.html</code>
33+
</li>
34+
<li>
35+
Vercel automatically detects and serves these for platform
36+
errors
37+
</li>
38+
<li>
39+
The 500 page acts as a fallback for all unhandled error codes
40+
</li>
41+
</ul>
42+
</div>
43+
<div className="max-w-lg text-base leading-7 text-zinc-600 dark:text-zinc-400">
44+
<p className="font-medium text-zinc-800 dark:text-zinc-200">
45+
Template tokens:
46+
</p>
47+
<ul className="mt-2 list-disc pl-5 space-y-1">
48+
<li>
49+
<code className="text-sm bg-zinc-100 dark:bg-zinc-800 px-1.5 py-0.5 rounded">::vercel:REQUEST_ID::</code> - Unique request identifier
50+
</li>
51+
<li>
52+
<code className="text-sm bg-zinc-100 dark:bg-zinc-800 px-1.5 py-0.5 rounded">::vercel:ERROR_CODE::</code> - Error type (e.g.,
53+
FUNCTION_INVOCATION_TIMEOUT)
54+
</li>
55+
</ul>
56+
</div>
57+
<div className="max-w-lg text-base leading-7 text-zinc-600 dark:text-zinc-400">
58+
<p className="font-medium text-zinc-800 dark:text-zinc-200">
59+
Try it out:
60+
</p>
61+
<p className="mt-2">
62+
Click &quot;Trigger Timeout&quot; to trigger a function timeout and see
63+
the custom error page in action. The page is configured to timeout
64+
after 3 seconds.
65+
</p>
66+
</div>
3667
</div>
37-
<div className="flex flex-col gap-4 text-base font-medium sm:flex-row">
68+
<div className="flex flex-col gap-4 text-base font-medium sm:flex-row sm:flex-wrap">
3869
<a
39-
className="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-foreground px-5 text-background transition-colors hover:bg-[#383838] dark:hover:bg-[#ccc] md:w-[158px]"
40-
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
41-
target="_blank"
42-
rel="noopener noreferrer"
70+
className="flex h-12 w-full items-center justify-center gap-2 rounded-full bg-foreground px-5 text-background transition-colors hover:bg-[#383838] dark:hover:bg-[#ccc] sm:w-auto"
71+
href="/slow-page"
72+
>
73+
Trigger Timeout
74+
</a>
75+
<a
76+
className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] sm:w-auto"
77+
href="/500.html"
78+
>
79+
View 500 Page
80+
</a>
81+
<a
82+
className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] sm:w-auto"
83+
href="/504.html"
4384
>
44-
<Image
45-
className="dark:invert"
46-
src="/vercel.svg"
47-
alt="Vercel logomark"
48-
width={16}
49-
height={16}
50-
/>
51-
Deploy Now
85+
View 504 Page
5286
</a>
5387
<a
54-
className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] md:w-[158px]"
55-
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
88+
className="flex h-12 w-full items-center justify-center rounded-full border border-solid border-black/[.08] px-5 transition-colors hover:border-transparent hover:bg-black/[.04] dark:border-white/[.145] dark:hover:bg-[#1a1a1a] sm:w-auto"
89+
href="https://vercel.com/docs/custom-error-pages"
5690
target="_blank"
5791
rel="noopener noreferrer"
5892
>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Force dynamic rendering so the sleep happens on each request
2+
export const dynamic = "force-dynamic";
3+
4+
function sleep(ms: number) {
5+
return new Promise((resolve) => setTimeout(resolve, ms));
6+
}
7+
8+
export default async function SlowPage() {
9+
// Sleep for 60 seconds - this will trigger a timeout since maxDuration is 3s
10+
await sleep(60000);
11+
12+
return (
13+
<div className="flex min-h-screen flex-col items-center justify-center px-6 py-24 bg-gray-50">
14+
<div className="text-center">
15+
<h1 className="text-3xl font-bold tracking-tight text-gray-900">
16+
Slow Page
17+
</h1>
18+
<p className="mt-6 text-base leading-7 text-gray-600">
19+
If you see this, the page did not timeout (waited 60 seconds).
20+
</p>
21+
</div>
22+
</div>
23+
);
24+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"functions": {
3+
"app/slow-page/page.tsx": {
4+
"maxDuration": 3
5+
}
6+
}
7+
}

0 commit comments

Comments
 (0)