feat: fix seo for social media previews

This commit is contained in:
limes
2026-08-26 00:00:39 +02:00
parent dd3c084518
commit af17a196bf
22 changed files with 86 additions and 115 deletions

View File

@@ -156,6 +156,7 @@ export default defineNuxtConfig({
{ name: 'application-name', content: 'Pretendo Network' },
{ name: 'msapplication-TileColor', content: '#1b1f3b' },
{ name: 'theme-color', content: '#1b1f3b' },
{ property: 'og:title', content: 'Pretendo Network' },
{
property: 'og:description',
content:

View File

@@ -0,0 +1,36 @@
import type { UseSeoMetaInput } from '@unhead/vue';
export type CustomSeoMetaOptions = UseSeoMetaInput & {
subsection?: string;
};
export default function (args?: CustomSeoMetaOptions) {
let newTitleTemplate = '';
switch (args?.subsection) {
case ('account'): {
newTitleTemplate = 'Account | Pretendo Network';
break;
}
case ('terms'): {
newTitleTemplate = 'Terms | Pretendo Network';
break;
}
case ('blog'): {
newTitleTemplate = 'Blog | Pretendo Network';
break;
}
case ('docs'): {
newTitleTemplate = 'Docs | Pretendo Network';
break;
}
default: {
newTitleTemplate = 'Pretendo Network';
}
}
const newTitle = args?.title ? `${args?.title} | ${newTitleTemplate}` : newTitleTemplate;
useHead({ title: newTitle });
useSeoMeta({ ...args, title: newTitle, ogTitle: newTitle, twitterTitle: newTitle, ogDescription: args?.description, twitterDescription: args?.description, twitterImage: args?.ogImage });
}

View File

@@ -1,9 +1,4 @@
<script setup lang="ts">
useHead({
titleTemplate: (titleChunk) => {
return titleChunk ? `${titleChunk} | Pretendo Network` : 'Pretendo Network';
}
});
</script>
<template>

View File

@@ -3,14 +3,6 @@
const path = useRoute().fullPath;
const isSidebarOpen = ref(false);
useHead({
titleTemplate: (titleChunk) => {
return titleChunk
? `${titleChunk} | Docs | Pretendo Network`
: 'Docs | Pretendo Network';
}
});
</script>
<template>

View File

@@ -48,6 +48,8 @@ const { execute, isLoading } = useAsync({
});
}
});
customSeoMeta({ subsection: 'account', title: 'Forgot password' });
</script>
<template>

View File

@@ -154,9 +154,7 @@ const { execute: executeUnlinkDiscord, isLoading: isLoadingUnlink } = useAsync({
}
});
useHead({
title: `Account`
});
customSeoMeta({ subsection: 'account' });
</script>
<template>

View File

@@ -47,6 +47,8 @@ const { execute, isLoading } = useAsync({
});
}
});
customSeoMeta({ subsection: 'account', title: 'Login' });
</script>
<template>

View File

@@ -15,9 +15,7 @@ definePageMeta({
const { data: profile } = await useApiFetch('/api/auth/me');
useHead({
title: 'Mii Editor | Pretendo Network'
});
customSeoMeta({ subsection: 'account', title: 'Mii Editor' });
const beforeUnload = (e: BeforeUnloadEvent) => {
e?.preventDefault();

View File

@@ -55,6 +55,8 @@ const { execute, isLoading } = useAsync({
});
}
});
customSeoMeta({ subsection: 'account', title: 'Register' });
</script>
<template>

View File

@@ -30,6 +30,8 @@ const { execute, isLoading } = useAsync({
});
}
});
customSeoMeta({ subsection: 'account', title: 'Reset passoword' });
</script>
<template>

View File

@@ -81,10 +81,7 @@ function hasSubscription(priceId: string) {
profile.value?.stripeTier && priceId === profile.value.stripeTier.priceId
);
}
useHead({
title: `Upgrade`
});
customSeoMeta({ subsection: 'account', title: 'Upgrade' });
</script>
<template>

View File

@@ -8,16 +8,11 @@ if (!post.value) {
throw createError({ statusCode: 404, statusMessage: 'Page Not Found' });
}
useHead({
title: `${post.value.title} | Blog`,
meta: [
{ property: 'description', content: post.value.caption },
{ property: 'og:description', content: post.value.caption },
{ property: 'og:image', content: post.value.cover_image },
{ property: 'og:image:alt', content: '' },
{ name: 'twitter:description', content: post.value.caption },
{ name: 'twitter:image', content: post.value.cover_image }
]
customSeoMeta({
subsection: 'blog',
title: post.value.title,
description: post.value.caption,
ogImage: post.value.cover_image
});
</script>

View File

@@ -1,13 +1,12 @@
<script setup lang="ts">
useHead({
title: 'Blog'
});
customSeoMeta({ subsection: 'blog' });
/* eslint-disable vue/no-v-html -- we might wanna avoid this by rewriting the locales to use variables */
const { data: allPosts } = await useAsyncData('blog', () => queryCollection('blog').all());
const posts = computed(() => allPosts.value?.filter(p => !p.path.startsWith('/blog/_')).sort((a, b) => {
return new Date(b.date).getTime() - new Date(a.date).getTime();
}));
</script>
<template>

View File

@@ -7,15 +7,10 @@ const { data: doc } = await useAsyncData(`docs-${slug}`, () => {
if (!doc.value) {
throw createError({ statusCode: 404, statusMessage: 'Page Not Found' });
}
useHead({
title: `${doc.value.title}`,
meta: [
{ property: 'description', content: doc.value.description },
{ property: 'og:description', content: doc.value.description },
{ property: 'og:image:alt', content: '' },
{ name: 'twitter:description', content: doc.value.description }
]
customSeoMeta({
subsection: 'docs',
title: doc.value.title,
description: doc.value.description
});
definePageMeta({

View File

@@ -8,14 +8,10 @@ if (!error.value) {
throw createError({ statusCode: 404, statusMessage: 'Page Not Found' });
}
useHead({
title: `${error.value.code} | Docs`,
meta: [
{ property: 'description', content: error.value.message },
{ property: 'og:description', content: error.value.message },
{ property: 'og:image:alt', content: '' },
{ name: 'twitter:description', content: error.value.message }
]
customSeoMeta({
subsection: 'docs',
title: error.value.code,
description: error.value.message
});
definePageMeta({

View File

@@ -36,25 +36,10 @@ const { data: searchResults } = await useAsyncData(
);
const results = computed(() => searchResults.value ?? []);
useHead({
customSeoMeta({
subsection: 'docs',
title: 'Search',
meta: [
{
name: 'description',
content:
'Got an error code? Find solutions here.'
},
{
name: 'og:description',
content:
'Got an error code? Find solutions here.'
},
{
name: 'twitter:description',
content:
'Got an error code? Find solutions here.'
}
]
description: 'Got an error code? Find solutions here.'
});
definePageMeta({

View File

@@ -1,23 +1,9 @@
<script setup lang="ts">
useHead({
customSeoMeta({
subsection: 'docs',
title: 'Install',
meta: [
{
name: 'description',
content:
'Learn how to set up Pretendo on a variety of consoles and emulators.'
},
{
name: 'og:description',
content:
'Learn how to set up Pretendo on a variety of consoles and emulators.'
},
{
name: 'twitter:description',
content:
'Learn how to set up Pretendo on a variety of consoles and emulators.'
}
]
description: 'Learn how to set up Pretendo on a variety of consoles and emulators.'
});
definePageMeta({

View File

@@ -1,23 +1,9 @@
<script setup lang="ts">
useHead({
meta: [
{
name: 'description',
content:
'Learn how to set up Pretendo on a variety of consoles and emulators.'
},
{
name: 'og:description',
content:
'Learn how to set up Pretendo on a variety of consoles and emulators.'
},
{
name: 'twitter:description',
content:
'Learn how to set up Pretendo on a variety of consoles and emulators.'
}
]
customSeoMeta({
subsection: 'docs',
description: 'Learn how to set up Pretendo on a variety of consoles and emulators.',
ogDescription: 'Learn how to set up Pretendo on a variety of consoles and emulators.'
});
definePageMeta({

View File

@@ -32,6 +32,8 @@ function arraySplit<T>(array: Array<T>, groupCount: number): Array<Array<T>> {
function titleSuffixHandler(path: string) {
return te(path) ? t(path) : null;
}
customSeoMeta();
</script>
<template>

View File

@@ -4,6 +4,7 @@ useHead({
link: [{ rel: 'stylesheet', href: 'https://use.typekit.net/gok5tsu.css' }]
});
customSeoMeta();
</script>
<template>

View File

@@ -1,6 +1,11 @@
<script setup lang="ts">
const { t } = useI18n();
customSeoMeta({
title: t('progressPage.title'),
description: t('progressPage.description')
});
const progress = await useFetch('/api/progress');
const projects = computed(() => progress.data.value?.items ?? []);
const donations = computed(() => progress.data.value?.donations);

View File

@@ -8,14 +8,10 @@ if (!termContent.value) {
throw createError({ statusCode: 404, statusMessage: 'Page Not Found' });
}
useHead({
title: `${termContent.value.title} | Terms`,
meta: [
{ property: 'description', content: termContent.value.description },
{ property: 'og:description', content: termContent.value.description },
{ property: 'og:image:alt', content: '' },
{ name: 'twitter:description', content: termContent.value.description }
]
customSeoMeta({
subsection: 'terms',
title: termContent.value.title,
description: termContent.value.description
});
</script>