main
  1---
  2import { Font } from "astro:assets";
  3import { getIntlayer, type Locale } from "intlayer";
  4import Footer from "@/components/Footer.astro";
  5import Header from "@/components/Header.astro";
  6import { DEFAULT_LOCALE, SITE_CONFIG } from "@/config";
  7import {
  8  getLocaleFeedUrl,
  9  getPathWithoutLocale,
 10  getRelativeLocaleUrl,
 11  url,
 12} from "@/utils/url.ts";
 13
 14import "sanitize.css/sanitize.css";
 15import "@/styles/global.scss";
 16
 17interface Props {
 18  title?: string;
 19  author?: string;
 20  description?: string;
 21  availableLocales?: Locale[];
 22  ogType?: "website" | "article";
 23}
 24
 25const locale = Astro.currentLocale;
 26const globalI18n = getIntlayer("global", locale);
 27
 28const {
 29  title = SITE_CONFIG.title,
 30  author = SITE_CONFIG.author,
 31  description = globalI18n.description,
 32  availableLocales = SITE_CONFIG.locales,
 33  ogType = "website",
 34} = Astro.props;
 35
 36const pageLocales = SITE_CONFIG.locales.filter((candidate) =>
 37  availableLocales.includes(candidate),
 38);
 39
 40if (!pageLocales.includes(DEFAULT_LOCALE)) {
 41  throw new Error(
 42    `Page ${Astro.url.pathname} must be built for the default locale "${DEFAULT_LOCALE}".`,
 43  );
 44}
 45
 46const getAbsoluteLocaleUrl = (path: string, locale: Locale) =>
 47  new URL(getRelativeLocaleUrl(path, locale), Astro.site).toString();
 48---
 49
 50<!doctype html>
 51<html lang={locale}>
 52  <head>
 53    <meta charset="utf-8">
 54    <meta name="viewport" content="width=device-width">
 55    <meta name="generator" content={Astro.generator}>
 56
 57    <link rel="icon" type="image/svg+xml" href="/favicon.svg">
 58    <link rel="icon" href="/favicon.ico">
 59    <link rel="sitemap" href="/sitemap-index.xml">
 60    <link
 61      rel="alternate"
 62      type="application/atom+xml"
 63      hreflang={locale ?? DEFAULT_LOCALE}
 64      title="Atom Feed"
 65      href={getLocaleFeedUrl(locale ?? DEFAULT_LOCALE)}
 66    >
 67    <link
 68      rel="alternate"
 69      type="application/atom+xml"
 70      title="Atom Feed"
 71      href={url("/feed.atom")}
 72    >
 73
 74    <title>{title}</title>
 75    <meta name="title" content={title}>
 76    <meta name="description" content={description}>
 77    <meta name="author" content={author}>
 78
 79    {pageLocales.map((target) => (
 80      <link
 81        rel="alternate"
 82        hreflang={target}
 83        href={getAbsoluteLocaleUrl(
 84          getPathWithoutLocale(Astro.url.pathname),
 85          target,
 86        )}
 87      >
 88    ))}
 89    <link
 90      rel="alternate"
 91      hreflang="x-default"
 92      href={getAbsoluteLocaleUrl(
 93        getPathWithoutLocale(Astro.url.pathname),
 94        DEFAULT_LOCALE,
 95      )}
 96    >
 97
 98    <meta property="og:url" content={Astro.url}>
 99    <meta property="og:site_name" content={SITE_CONFIG.title}>
100    <meta property="og:title" content={title}>
101    <meta property="og:description" content={description}>
102    <meta property="og:locale" content={locale}>
103    <meta property="og:type" content={ogType}>
104
105    <meta name="robots" content="noindex, nofollow">
106
107    <Font cssVariable="--font-stix-two-math" />
108  </head>
109  <body>
110    <Header availableLocales={pageLocales} />
111    <main>
112      <slot />
113    </main>
114    <Footer />
115  </body>
116</html>
117
118<style lang="scss" is:global>
119body {
120  min-height: 100dvh;
121  max-width: 67rem;
122  margin-inline: auto;
123  padding-inline: 1rem;
124  display: flex;
125  flex-direction: column;
126
127  > main {
128    flex: 1;
129  }
130}
131</style>