diff --git a/packages/astro/src/core/dev/index.ts b/packages/astro/src/core/dev/index.ts
index 756e2a8caa..3774a9995b 100644
--- a/packages/astro/src/core/dev/index.ts
+++ b/packages/astro/src/core/dev/index.ts
@@ -19,7 +19,8 @@ import { collectResources } from '../ssr/html.js';
import { createRouteManifest, matchRoute } from '../ssr/routing.js';
import { createVite } from '../create-vite.js';
import * as msg from './messages.js';
-import { errorTemplate } from './template/error.js';
+import notFoundTemplate from './template/4xx.js';
+import serverErrorTemplate from './template/5xx.js';
export interface DevOptions {
logging: LogOptions;
@@ -303,7 +304,7 @@ export class AstroDevServer {
} catch (err: any) {
this.viteServer.ws.send({ type: 'error', err });
const statusCode = 500;
- const html = errorTemplate({
+ const html = serverErrorTemplate({
statusCode,
title: 'Internal Error',
tabTitle: '500: Error',
@@ -347,7 +348,7 @@ export class AstroDevServer {
}
// if not found, fall back to default template
else {
- html = errorTemplate({ statusCode, title: 'Not found', tabTitle: '404: Not Found', message: pathname });
+ html = notFoundTemplate({ statusCode, title: 'Not found', tabTitle: '404: Not Found', pathname });
}
info(this.logging, 'astro', msg.req({ url: pathname, statusCode, reqTime: performance.now() - reqStart }));
res.writeHead(statusCode, {
diff --git a/packages/astro/src/core/dev/template/4xx.ts b/packages/astro/src/core/dev/template/4xx.ts
new file mode 100644
index 0000000000..99c022963d
--- /dev/null
+++ b/packages/astro/src/core/dev/template/4xx.ts
@@ -0,0 +1,51 @@
+import { encode } from 'html-entities';
+import { baseCSS } from './css.js';
+interface ErrorTemplateOptions {
+ /** a short description of the error */
+ pathname: string;
+ /** HTTP error code */
+ statusCode?: number;
+ /** HTML
*/
+ tabTitle: string;
+ /** page title */
+ title: string;
+}
+
+/** Display all errors */
+export default function template({ title, pathname, statusCode = 404, tabTitle }: ErrorTemplateOptions): string {
+ return `
+
+
+
+ ${tabTitle}
+
+
+
+
+
+ ${statusCode ? `${statusCode}: ` : ''}${title}
+ Path: ${encode(pathname)}
+
+
+ `;
+}
diff --git a/packages/astro/src/core/dev/template/5xx.ts b/packages/astro/src/core/dev/template/5xx.ts
new file mode 100644
index 0000000000..75513ff0dd
--- /dev/null
+++ b/packages/astro/src/core/dev/template/5xx.ts
@@ -0,0 +1,71 @@
+import { encode } from 'html-entities';
+import { baseCSS } from './css.js';
+
+interface ErrorTemplateOptions {
+ /** a short description of the error */
+ message: string;
+ /** information about where the error occurred */
+ stack?: string;
+ /** HTTP error code */
+ statusCode?: number;
+ /** HTML */
+ tabTitle: string;
+ /** page title */
+ title: string;
+ /** show user a URL for more info or action to take */
+ url?: string;
+}
+
+/** Display all errors */
+export default function template({ title, url, message, stack, statusCode, tabTitle }: ErrorTemplateOptions): string {
+ let error = url ? message.replace(url, '') : message;
+ return `
+
+
+
+ ${tabTitle}
+
+
+
+
+
+
+ ${statusCode ? `${statusCode}: ` : ''}${title}
+
+ ${encode(error)}
+ ${url ? `${url}` : ''}
+ ${encode(stack)}
+
+
+ `;
+}
diff --git a/packages/astro/src/core/dev/template/css.ts b/packages/astro/src/core/dev/template/css.ts
new file mode 100644
index 0000000000..87fbfd1b8f
--- /dev/null
+++ b/packages/astro/src/core/dev/template/css.ts
@@ -0,0 +1,50 @@
+/**
+ * CSS is exported as a string so the error pages:
+ * 1. don’t need to resolve a deep internal CSS import
+ * 2. don’t need external dependencies to render (they may be shown because of a dep!)
+ */
+
+// Base CSS: shared CSS among pages
+export const baseCSS = `
+:root {
+ --gray-10: hsl(258, 7%, 10%);
+ --gray-20: hsl(258, 7%, 20%);
+ --gray-30: hsl(258, 7%, 30%);
+ --gray-40: hsl(258, 7%, 40%);
+ --gray-50: hsl(258, 7%, 50%);
+ --gray-60: hsl(258, 7%, 60%);
+ --gray-70: hsl(258, 7%, 70%);
+ --gray-80: hsl(258, 7%, 80%);
+ --gray-90: hsl(258, 7%, 90%);
+ --orange: #ff5d01;
+}
+
+* {
+ box-sizing: border-box;
+}
+
+body {
+ background-color: var(--gray-10);
+ color: var(--gray-80);
+ font-family: monospace;
+ line-height: 1.5;
+ margin: 0;
+}
+
+a {
+ color: var(--orange);
+}
+
+h1 {
+ font-weight: 800;
+ margin-top: 1rem;
+ margin-bottom: 0;
+}
+
+pre {
+ color:;
+ font-size: 1.2em;
+ margin-top: 0;
+ max-width: 60em;
+}
+`;
diff --git a/packages/astro/src/core/dev/template/error.ts b/packages/astro/src/core/dev/template/error.ts
deleted file mode 100644
index 7f611328cd..0000000000
--- a/packages/astro/src/core/dev/template/error.ts
+++ /dev/null
@@ -1,67 +0,0 @@
-import { encode } from 'html-entities';
-
-interface ErrorTemplateOptions {
- /** a short description of the error */
- message: string;
- /** information about where the error occurred */
- stack?: string;
- /** HTTP error code */
- statusCode?: number;
- /** HTML */
- tabTitle: string;
- /** page title */
- title: string;
- /** show user a URL for more info or action to take */
- url?: string;
-}
-
-/** Display internal 404 page (if user didn’t provide one) */
-export function errorTemplate({ title, url, message, stack, statusCode, tabTitle }: ErrorTemplateOptions): string {
- let error = url ? message.replace(url, '') : message;
- return `
-
-
-
- ${tabTitle}
-
-
-
-
- ${statusCode ? `${statusCode} ` : ''}${title}
- ${encode(error)}
- ${url ? `${url}` : ''}
- ${encode(stack)}
-
-
-
-`;
-}