From 1aa2187944dde4419e523f0087139f5a21efd826 Mon Sep 17 00:00:00 2001 From: Chris Swithinbank Date: Thu, 22 Jun 2023 18:22:54 +0200 Subject: Support custom 404 pages (#226) Co-authored-by: Josh Pollara <75546+joshpollara@users.noreply.github.com> --- .changeset/tiny-sheep-raise.md | 5 ++ docs/src/content/docs/404.md | 13 +++ docs/src/content/docs/guides/customization.mdx | 29 +++++++ packages/starlight/404.astro | 83 +++++++----------- packages/starlight/components/EmptyMarkdown.md | 0 packages/starlight/index.astro | 113 +----------------------- packages/starlight/layout/Page.astro | 116 +++++++++++++++++++++++++ packages/starlight/schemas/i18n.ts | 4 + packages/starlight/translations/de.json | 3 +- packages/starlight/translations/en.json | 3 +- packages/starlight/translations/es.json | 3 +- packages/starlight/translations/fr.json | 3 +- packages/starlight/translations/it.json | 3 +- packages/starlight/translations/ja.json | 3 +- packages/starlight/translations/pt.json | 3 +- 15 files changed, 216 insertions(+), 168 deletions(-) create mode 100644 .changeset/tiny-sheep-raise.md create mode 100644 docs/src/content/docs/404.md create mode 100644 packages/starlight/components/EmptyMarkdown.md create mode 100644 packages/starlight/layout/Page.astro diff --git a/.changeset/tiny-sheep-raise.md b/.changeset/tiny-sheep-raise.md new file mode 100644 index 00000000..07dfedd6 --- /dev/null +++ b/.changeset/tiny-sheep-raise.md @@ -0,0 +1,5 @@ +--- +"@astrojs/starlight": minor +--- + +Add support for custom 404 pages. diff --git a/docs/src/content/docs/404.md b/docs/src/content/docs/404.md new file mode 100644 index 00000000..6772acfb --- /dev/null +++ b/docs/src/content/docs/404.md @@ -0,0 +1,13 @@ +--- +title: Not found +template: splash +editUrl: false +hero: + title: '404' + tagline: Houston, we have a problem. We couldn’t find that page.
Check the URL or try using the search bar. + actions: + - text: Go home + icon: right-arrow + link: / + variant: primary +--- diff --git a/docs/src/content/docs/guides/customization.mdx b/docs/src/content/docs/guides/customization.mdx index d7d3e5bd..b39c6815 100644 --- a/docs/src/content/docs/guides/customization.mdx +++ b/docs/src/content/docs/guides/customization.mdx @@ -236,6 +236,35 @@ export default defineConfig({ }); ``` +## Custom 404 page + +Starlight sites display a simple 404 page by default. +You can customize this by adding a `404.md` (or `404.mdx`) file to your `src/content/docs/` directory: + + + +- src/ + - content/ + - docs/ + - **404.md** + - index.md +- astro.config.mjs + + + +You can use all of Starlight’s page layout and customization techniques in your 404 page. For example, the default 404 page uses the [`splash` template](#page-layout) and [`hero`](/reference/frontmatter/#hero) component in frontmatter: + +```md +--- +title: '404' +template: splash +editUrl: false +hero: + title: '404' + tagline: Page not found. Check the URL or try using the search bar. +--- +``` + ## Custom CSS styles Customize the styles applied to your Starlight site by providing additional CSS files to modify or extend Starlight’s default styles. diff --git a/packages/starlight/404.astro b/packages/starlight/404.astro index 46cf5189..ecd95447 100644 --- a/packages/starlight/404.astro +++ b/packages/starlight/404.astro @@ -1,58 +1,39 @@ --- +import { getEntry } from 'astro:content'; import config from 'virtual:starlight/user-config'; -import { pathWithBase } from './utils/base'; +import EmptyContent from './components/EmptyMarkdown.md'; +import Page from './layout/Page.astro'; +import type { StarlightDocsEntry } from './utils/routing'; +import { useTranslations } from './utils/translations'; -// Built-in CSS styles. -import './style/props.css'; -import './style/reset.css'; -import './style/shiki.css'; -import './style/util.css'; - -// Layout -import PageFrame from './layout/PageFrame.astro'; - -// Components -import Header from './components/Header.astro'; -import MarkdownContent from './components/MarkdownContent.astro'; -import ThemeProvider from './components/ThemeProvider.astro'; -import SkipLink from './components/SkipLink.astro'; +const { lang = 'en', dir = 'ltr', locale } = config.defaultLocale || {}; +const entryMeta = { dir, lang, locale }; +const t = useTranslations(locale); -// Important that this is the last import so it can override built-in styles. -import 'virtual:starlight/user-css'; +const fallbackEntry: StarlightDocsEntry = { + slug: '404', + id: '404.md' as StarlightDocsEntry['id'], + body: '', + collection: 'docs', + data: { + title: '404', + template: 'splash', + editUrl: false, + head: [], + hero: { tagline: t('404.text'), actions: [] }, + }, + render: async () => ({ + Content: EmptyContent, + headings: [], + remarkPluginFrontmatter: {}, + }), +}; -const { lang = 'en', dir = 'ltr', locale } = config.defaultLocale || {}; +const userEntry = await getEntry('docs', '404'); +const entry = userEntry || fallbackEntry; +const { Content, headings } = await entry.render(); --- - - - - - Not found - - - - - -
-
- -

404

-

Houston, we have a problem.

-

- We couldn’t find that link. Check the address or - head back home. -

-
-
- - - - - + + + diff --git a/packages/starlight/components/EmptyMarkdown.md b/packages/starlight/components/EmptyMarkdown.md new file mode 100644 index 00000000..e69de29b diff --git a/packages/starlight/index.astro b/packages/starlight/index.astro index 6b5193aa..65c19d85 100644 --- a/packages/starlight/index.astro +++ b/packages/starlight/index.astro @@ -1,122 +1,15 @@ --- import type { InferGetStaticPropsType } from 'astro'; -import config from 'virtual:starlight/user-config'; - -import { getSidebar } from './utils/navigation'; import { paths } from './utils/routing'; -// Built-in CSS styles. -import './style/props.css'; -import './style/reset.css'; -import './style/shiki.css'; -import './style/util.css'; - -// Components — can override built-in CSS, but not user CSS. -import ContentPanel from './components/ContentPanel.astro'; -import FallbackContentNotice from './components/FallbackContentNotice.astro'; -import HeadSEO from './components/HeadSEO.astro'; -import Header from './components/Header.astro'; -import Footer from './components/Footer.astro'; -import MarkdownContent from './components/MarkdownContent.astro'; -import RightSidebar from './components/RightSidebar.astro'; -import Sidebar from './components/Sidebar.astro'; -import SkipLink from './components/SkipLink.astro'; -import ThemeProvider from './components/ThemeProvider.astro'; -import PageFrame from './layout/PageFrame.astro'; -import TwoColumnContent from './layout/TwoColumnContent.astro'; -import Hero from './components/Hero.astro'; - -// Remark component CSS (needs to override `MarkdownContent.astro`) -import './style/asides.css'; - -// Important that this is the last import so it can override built-in styles. -import 'virtual:starlight/user-css'; +import Page from './layout/Page.astro'; export async function getStaticPaths() { return paths; } type Props = InferGetStaticPropsType; - -const { dir, entry, entryMeta, isFallback, lang, locale } = Astro.props; -const { Content, headings } = await entry.render(); -const sidebar = getSidebar(Astro.url.pathname, locale); - -const hasSidebar = entry.data.template !== 'splash'; -const tocConfig = !hasSidebar - ? false - : entry.data.tableOfContents !== undefined - ? entry.data.tableOfContents - : config.tableOfContents; -const hasToC = Boolean(tocConfig); -const hasHero = Boolean(entry.data.hero); +const { Content, headings } = await Astro.props.entry.render(); --- - - - - - - - - - -
- {hasSidebar && } - - -
- {/* TODO: Revisit how this logic flows. */} - {entry.data.hero ? ( - - - - - ) : ( - -

- {entry.data.title} -

- {isFallback && } -
- - -
- - )} -
-
- - - + diff --git a/packages/starlight/layout/Page.astro b/packages/starlight/layout/Page.astro new file mode 100644 index 00000000..b09abe8c --- /dev/null +++ b/packages/starlight/layout/Page.astro @@ -0,0 +1,116 @@ +--- +import config from 'virtual:starlight/user-config'; +import type { MarkdownHeading } from 'astro'; +import { getSidebar } from '../utils/navigation'; +import type { Route } from '../utils/routing'; + +// Built-in CSS styles. +import '../style/props.css'; +import '../style/reset.css'; +import '../style/shiki.css'; +import '../style/util.css'; + +// Components — can override built-in CSS, but not user CSS. +import ContentPanel from '../components/ContentPanel.astro'; +import FallbackContentNotice from '../components/FallbackContentNotice.astro'; +import Footer from '../components/Footer.astro'; +import HeadSEO from '../components/HeadSEO.astro'; +import Header from '../components/Header.astro'; +import Hero from '../components/Hero.astro'; +import MarkdownContent from '../components/MarkdownContent.astro'; +import RightSidebar from '../components/RightSidebar.astro'; +import Sidebar from '../components/Sidebar.astro'; +import SkipLink from '../components/SkipLink.astro'; +import ThemeProvider from '../components/ThemeProvider.astro'; +import PageFrame from '../layout/PageFrame.astro'; +import TwoColumnContent from '../layout/TwoColumnContent.astro'; + +// Remark component CSS (needs to override `MarkdownContent.astro`) +import '../style/asides.css'; + +// Important that this is the last import so it can override built-in styles. +import 'virtual:starlight/user-css'; + +type Props = Route & { headings: MarkdownHeading[] }; + +const { dir, entry, entryMeta, headings, isFallback, lang, locale } = Astro.props; +const sidebar = getSidebar(Astro.url.pathname, locale); + +const hasSidebar = entry.data.template !== 'splash'; +const tocConfig = !hasSidebar + ? false + : entry.data.tableOfContents !== undefined + ? entry.data.tableOfContents + : config.tableOfContents; +const hasToC = Boolean(tocConfig); +const hasHero = Boolean(entry.data.hero); +--- + + + + + + + + + + +
+ {hasSidebar && } + + +
+ {/* TODO: Revisit how this logic flows. */} + {entry.data.hero ? ( + + + + + ) : ( + +

+ {entry.data.title} +

+ {isFallback && } +
+ + +
+
+ + + \ No newline at end of file diff --git a/packages/starlight/schemas/i18n.ts b/packages/starlight/schemas/i18n.ts index be0aea70..4bac4bec 100644 --- a/packages/starlight/schemas/i18n.ts +++ b/packages/starlight/schemas/i18n.ts @@ -98,6 +98,10 @@ function starlightI18nSchema() { .describe( 'Label shown on the “next page” pagination arrow in the page footer.' ), + + '404.text': z + .string() + .describe('Text shown on Starlight’s default 404 page'), }) .partial(); } diff --git a/packages/starlight/translations/de.json b/packages/starlight/translations/de.json index fee8b961..da82f791 100644 --- a/packages/starlight/translations/de.json +++ b/packages/starlight/translations/de.json @@ -17,5 +17,6 @@ "page.editLink": "Seite bearbeiten", "page.lastUpdated": "Zuletzt bearbeitet:", "page.previousLink": "Vorherige Seite", - "page.nextLink": "Nächste Seite" + "page.nextLink": "Nächste Seite", + "404.text": "Seite nicht gefunden. Überprüfe die URL oder nutze die Suchleiste." } diff --git a/packages/starlight/translations/en.json b/packages/starlight/translations/en.json index 4bf800a5..5bc396b2 100644 --- a/packages/starlight/translations/en.json +++ b/packages/starlight/translations/en.json @@ -17,5 +17,6 @@ "page.editLink": "Edit page", "page.lastUpdated": "Last updated:", "page.previousLink": "Previous", - "page.nextLink": "Next" + "page.nextLink": "Next", + "404.text": "Page not found. Check the URL or try using the search bar." } diff --git a/packages/starlight/translations/es.json b/packages/starlight/translations/es.json index e03ae58d..8adbe302 100644 --- a/packages/starlight/translations/es.json +++ b/packages/starlight/translations/es.json @@ -17,5 +17,6 @@ "page.editLink": "Edita esta página", "page.lastUpdated": "Última actualización:", "page.previousLink": "Página anterior", - "page.nextLink": "Siguiente página" + "page.nextLink": "Siguiente página", + "404.text": "Página no encontrada. Verifique la URL o intente usar la barra de búsqueda." } diff --git a/packages/starlight/translations/fr.json b/packages/starlight/translations/fr.json index a1c437b7..345cb05c 100644 --- a/packages/starlight/translations/fr.json +++ b/packages/starlight/translations/fr.json @@ -17,5 +17,6 @@ "page.editLink": "Editer la page", "page.lastUpdated": "Dernière mise à jour :", "page.previousLink": "Précédent", - "page.nextLink": "Suivant" + "page.nextLink": "Suivant", + "404.text": "Page non trouvée. Vérifiez l'URL ou essayez d'utiliser la barre de recherche." } diff --git a/packages/starlight/translations/it.json b/packages/starlight/translations/it.json index b9991267..0560fb90 100644 --- a/packages/starlight/translations/it.json +++ b/packages/starlight/translations/it.json @@ -17,5 +17,6 @@ "page.editLink": "Modifica pagina", "page.lastUpdated": "Ultimo aggiornamento:", "page.previousLink": "Indietro", - "page.nextLink": "Avanti" + "page.nextLink": "Avanti", + "404.text": "Pagina non trovata. Verifica l'URL o prova a utilizzare la barra di ricerca." } diff --git a/packages/starlight/translations/ja.json b/packages/starlight/translations/ja.json index 75e2b06e..1f199b48 100644 --- a/packages/starlight/translations/ja.json +++ b/packages/starlight/translations/ja.json @@ -17,5 +17,6 @@ "page.editLink": "ページを編集", "page.lastUpdated": "最終更新日:", "page.previousLink": "前へ", - "page.nextLink": "次へ" + "page.nextLink": "次へ", + "404.text": "ページが見つかりません。 URL を確認するか、検索バーを使用してみてください。" } diff --git a/packages/starlight/translations/pt.json b/packages/starlight/translations/pt.json index 17908cd1..2b379035 100644 --- a/packages/starlight/translations/pt.json +++ b/packages/starlight/translations/pt.json @@ -17,5 +17,6 @@ "page.editLink": "Editar página", "page.lastUpdated": "Última atualização:", "page.previousLink": "Anterior", - "page.nextLink": "Próximo" + "page.nextLink": "Próximo", + "404.text": "Página não encontrada. Verifique o URL ou tente usar a barra de pesquisa." } -- cgit