Tutorial · website-errors · Published 2026-08-16 · 3 min read
Build user facing error pages
User facing error pages: plan on-brand 404, 500 and 503 pages, know the server settings, and ship a good experience during downtimes.
What a good error page does
A good error page keeps the visitor in the site. It explains in one plain sentence what happened, offers the three or four paths the visitor actually uses (home, contact, search), and it does not leak a stack trace. The error page has a job beyond aesthetics: it converts a dead end into a soft landing.
The three statuses that deserve human copy are the ones real visitors see:
| Status | Meaning | Page job |
|---|---|---|
| 404 | That URL does not exist | Offer the real alternatives |
| 500 | The server failed | A back-to-earth message so the visitor retries |
| 503 | The site is down on purpose | Explain it, retry header, no panic |
Map the server handlers
Error pages live at the platform layer so you do not hand-craft an HTML copy per route. On Apache you map them in .htaccess or vhost; on nginx you declare a location that serves the page; on Cloudflare the platform lets you configure a Custom Error Page for specific origin statuses.
error_page 404 /pages/404.html;
error_page 500 502 503 504 /pages/500.html;
location = /pages/404.html { internal; }
location = /pages/500.html { internal; }
Two rules keep this healthy:
- Serve the page at the wrong route name you choose, not by streaming a live CMS template. Error pages must load when the CMS is down, so static HTML with no PHP or database.
- Chain the rules: a 503 for maintenance, a 500 for server faults, and a 404 for the long tail of mistyped URLs all deserve their own copy. Never emit a raw server default for 500.
The layout
Keep your brand, but drop JavaScript. A visitor facing 500 already has a fragile asset pipeline; your fallback page must survive CSS and JS failure.
Worked example (404)
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Page not found | Example</title>
</head>
<body>
<h1>This page has moved or does not exist</h1>
<p>Try one of these instead.</p>
<p><a href="/">Home</a> · <a href="/about/">About</a> · <a href="/contact/">Contact</a></p>
<link rel="stylesheet" href="/style.css">
</body>
</html>
The browser gets the real 404 status (not a 200), so search engines and analytic tools behave correctly. The page then links the visitor to viable destinations without dwelling on the error.
Headline checks
- The server returns the intended status; verify with
curl -sIand read the code, not the content. - The page works with no JS and no network. Empty cache in a private window is the honest test.
- On maintenance, a 503 page that carries real machine state,
Retry-After, is better than a static "building" page. - Do not put email addresses in error pages that spam harvesters crawl.
When to involve a professional
If the platform only lets you change one shared error page (some hosts, some CMS stacks), and you need different pages for 404 vs 503, that is a platform/tier decision, not a copy task. Ask your host for one more status page slot before building custom HTML.
Keep the copy plain and factual on every one of your error pages: the visitor should know it is a real outage, not their connection, and that the team is on it.