Remove direct document.head mutations to support SSR compatibility Implement observer pattern to sync SEO state with Nuxt universal plugin Update analytics script to use declarative injection in Nuxt config
60 lines
2.3 KiB
TypeScript
60 lines
2.3 KiB
TypeScript
import { computed, ref } from 'vue';
|
|
import { onLocaleChange } from '../src/i18n';
|
|
import { applyRouteSeo, onSeoChange, resolveRouteSeo, type ResolvedSeoConfig } from '../src/seo';
|
|
|
|
export default defineNuxtPlugin(() => {
|
|
const router = useRouter();
|
|
const dynamicSeo = ref<ResolvedSeoConfig | null>(null);
|
|
const activeSeo = computed(() => dynamicSeo.value ?? resolveRouteSeo(router.currentRoute.value));
|
|
|
|
useHead(() => ({
|
|
title: activeSeo.value.title,
|
|
htmlAttrs: {
|
|
lang: activeSeo.value.locale
|
|
},
|
|
meta: [
|
|
{ key: 'description', name: 'description', content: activeSeo.value.description },
|
|
{ key: 'robots', name: 'robots', content: activeSeo.value.robots },
|
|
{ key: 'twitter-card', name: 'twitter:card', content: 'summary_large_image' },
|
|
{ key: 'twitter-title', name: 'twitter:title', content: activeSeo.value.title },
|
|
{ key: 'twitter-description', name: 'twitter:description', content: activeSeo.value.description },
|
|
{ key: 'twitter-image', name: 'twitter:image', content: activeSeo.value.imageUrl },
|
|
{ key: 'og-site-name', property: 'og:site_name', content: 'Pokopia Wiki' },
|
|
{ key: 'og-type', property: 'og:type', content: 'website' },
|
|
{ key: 'og-title', property: 'og:title', content: activeSeo.value.title },
|
|
{ key: 'og-description', property: 'og:description', content: activeSeo.value.description },
|
|
{ key: 'og-url', property: 'og:url', content: activeSeo.value.canonicalUrl },
|
|
{ key: 'og-image', property: 'og:image', content: activeSeo.value.imageUrl },
|
|
{ key: 'og-locale', property: 'og:locale', content: activeSeo.value.locale === 'en' ? 'en_US' : activeSeo.value.locale.replace('-', '_') }
|
|
],
|
|
link: [{ key: 'canonical', rel: 'canonical', href: activeSeo.value.canonicalUrl }],
|
|
script: [
|
|
{
|
|
key: 'pokopia-structured-data',
|
|
id: 'pokopia-structured-data',
|
|
type: 'application/ld+json',
|
|
children: JSON.stringify(activeSeo.value.structuredData)
|
|
}
|
|
]
|
|
}));
|
|
|
|
if (import.meta.server) {
|
|
return;
|
|
}
|
|
|
|
onSeoChange((seo) => {
|
|
dynamicSeo.value = seo;
|
|
});
|
|
onLocaleChange(() => {
|
|
dynamicSeo.value = null;
|
|
applyRouteSeo(router.currentRoute.value);
|
|
});
|
|
|
|
router.afterEach((to) => {
|
|
dynamicSeo.value = null;
|
|
applyRouteSeo(to);
|
|
});
|
|
|
|
applyRouteSeo(router.currentRoute.value);
|
|
});
|