## Summary - add the localized evaluation-readiness route pair at `/evaluierung` and `/en/evaluation` with a shared page component - wire homepage, platform, trust, review-pack, use-case, footer, and locale-switcher discovery paths into the new evaluation surface - add smoke coverage plus full Spec Kit artifacts for the evaluation, procurement, and rollout readiness feature ## Validation - `corepack pnpm --filter @tenantatlas/website build` - `WEBSITE_PORT=4322 corepack pnpm --filter @tenantatlas/website test tests/smoke/public-routes.spec.ts` - `WEBSITE_PORT=4323 corepack pnpm --filter @tenantatlas/website test tests/smoke/interaction.spec.ts` Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #408
148 lines
5.0 KiB
Plaintext
148 lines
5.0 KiB
Plaintext
---
|
|
import { getImage } from 'astro:assets';
|
|
import { OG, SEO, SITE } from '@data/constants';
|
|
import faviconSvgSrc from '@images/icon.svg';
|
|
import faviconSrc from '@images/icon.png';
|
|
import {
|
|
getLocaleFromPath,
|
|
isLocale,
|
|
localeOg,
|
|
localizedPath,
|
|
localizeRoutePath,
|
|
stripLocalePrefix,
|
|
type Locale,
|
|
} from '@/i18n';
|
|
|
|
// Default properties for the Meta component. These values are used if props are not provided.
|
|
// 'meta' sets a default description meta tag to describe the page content.
|
|
// 'structuredData' defines default structured data in JSON-LD format to enhance search engine understanding of the page (for SEO purposes).
|
|
const defaultProps = {
|
|
meta: SITE.description,
|
|
structuredData: SEO.structuredData,
|
|
customDescription: null,
|
|
customOgTitle: null,
|
|
};
|
|
|
|
// Extract props with default values assigned from defaultProps. Values can be overridden when the component is used.
|
|
// For example:
|
|
// <MainLayout title="Custom Title" meta="Custom description." />
|
|
const {
|
|
meta = defaultProps.meta,
|
|
structuredData = defaultProps.structuredData,
|
|
customDescription = defaultProps.customDescription,
|
|
customOgTitle = defaultProps.customOgTitle,
|
|
locale: rawLocale = getLocaleFromPath(Astro.url.pathname),
|
|
} = Astro.props;
|
|
|
|
const locale: Locale = isLocale(rawLocale) ? rawLocale : 'de';
|
|
|
|
// Use custom description if provided, otherwise use default meta
|
|
const description = customDescription || meta;
|
|
// Use custom OG title if provided, otherwise use default OG title
|
|
const ogTitle = customOgTitle || OG.title;
|
|
const ogDescription = customDescription || OG.description;
|
|
|
|
// Define the metadata for your website and individual pages
|
|
const siteURL = `${Astro.site}`; // Set the website URL in astro.config.mjs
|
|
const author = SITE.author;
|
|
const cleanPath = stripLocalePrefix(Astro.url.pathname);
|
|
const canonical = new URL(
|
|
localizedPath(cleanPath, locale),
|
|
Astro.site || Astro.url.origin
|
|
).href;
|
|
const socialImageRes = await getImage({
|
|
src: OG.image,
|
|
width: 1200,
|
|
height: 600,
|
|
format: 'png',
|
|
});
|
|
const socialImage = new URL(socialImageRes.src, Astro.site || Astro.url.origin)
|
|
.href;
|
|
const twitterDomain = new URL(siteURL).hostname;
|
|
|
|
const alternateLocales: Locale[] = ['de', 'en'];
|
|
|
|
// Generate and optimize the favicon images
|
|
const faviconSvg = await getImage({
|
|
src: faviconSvgSrc,
|
|
format: 'svg',
|
|
});
|
|
|
|
const appleTouchIcon = await getImage({
|
|
src: faviconSrc,
|
|
width: 180,
|
|
height: 180,
|
|
format: 'png',
|
|
});
|
|
---
|
|
|
|
{
|
|
/* Inject structured data into the page if provided. This data is formatted as JSON-LD, a method recommended by Google for structured data pass:
|
|
https://developers.google.com/search/docs/advanced/structured-data/intro-structured-data */
|
|
}{
|
|
structuredData && (
|
|
<script
|
|
type="application/ld+json"
|
|
set:html={JSON.stringify(structuredData)}
|
|
/>
|
|
)
|
|
}
|
|
{/* Define the character set, description, author, and viewport settings */}
|
|
<meta charset="utf-8" />
|
|
<meta content={description} name="description" />
|
|
<meta name="web_author" content={author} />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
|
<link rel="canonical" href={canonical} />
|
|
{
|
|
alternateLocales.map(lang => {
|
|
const href = new URL(
|
|
localizeRoutePath(cleanPath, locale, lang),
|
|
Astro.site || Astro.url.origin
|
|
).href;
|
|
return <link rel="alternate" hreflang={lang} href={href} />;
|
|
})
|
|
}
|
|
<link
|
|
rel="alternate"
|
|
hreflang="x-default"
|
|
href={new URL(
|
|
localizeRoutePath(cleanPath, locale, 'de'),
|
|
Astro.site || Astro.url.origin
|
|
).href}
|
|
/>
|
|
|
|
{/* Facebook Meta Tags */}
|
|
<meta property="og:locale" content={localeOg[locale]} />
|
|
<meta property="og:url" content={canonical} />
|
|
<meta property="og:type" content="website" />
|
|
<meta property="og:title" content={ogTitle} />
|
|
<meta property="og:site_name" content={SITE.title} />
|
|
<meta property="og:description" content={ogDescription} />
|
|
<meta property="og:image" content={socialImage} />
|
|
<meta content="1200" property="og:image:width" />
|
|
<meta content="600" property="og:image:height" />
|
|
<meta content="image/png" property="og:image:type" />
|
|
|
|
{/* Twitter Meta Tags */}
|
|
<meta name="twitter:card" content="summary_large_image" />
|
|
<meta property="twitter:domain" content={twitterDomain} />
|
|
<meta property="twitter:url" content={canonical} />
|
|
<meta name="twitter:title" content={ogTitle} />
|
|
<meta name="twitter:description" content={ogDescription} />
|
|
<meta name="twitter:image" content={socialImage} />
|
|
|
|
{/* Links to the webmanifest and sitemap */}
|
|
<link rel="manifest" href="/manifest.json" />
|
|
{/* https://docs.astro.build/en/guides/integrations-guide/sitemap/ */}
|
|
<link rel="sitemap" href="/sitemap-index.xml" />
|
|
|
|
{/* Links for favicons */}
|
|
<link href="/favicon.ico" rel="icon" sizes="any" type="image/x-icon" />
|
|
<link href={faviconSvg.src} rel="icon" type="image/svg+xml" sizes="any" />
|
|
<meta name="mobile-web-app-capable" content="yes" />
|
|
<link href={appleTouchIcon.src} rel="apple-touch-icon" />
|
|
<link href={appleTouchIcon.src} rel="shortcut icon" />
|
|
{/* Set theme color */}
|
|
<meta name="theme-color" content="#facc15" />
|