diff --git a/.gitignore b/.gitignore index 7102b4e..ff4813e 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ site/public/api-meta/ site/public/api-catalog.json site/public/docs-markdown/ site/public/sitemap.xml +site/public/feed.xml ############### # OS / IDE diff --git a/site/app/composables/usePageSeo.ts b/site/app/composables/usePageSeo.ts index e1ed9bf..d818244 100644 --- a/site/app/composables/usePageSeo.ts +++ b/site/app/composables/usePageSeo.ts @@ -12,6 +12,8 @@ type PageSeoOptions = { title?: MaybeRefOrGetter description?: MaybeRefOrGetter image?: MaybeRefOrGetter + /** Article last-updated day as YYYY-MM-DD (adds Open Graph modified_time). */ + modifiedTime?: MaybeRefOrGetter } export function usePageSeo(options: PageSeoOptions = {}) { @@ -22,23 +24,38 @@ export function usePageSeo(options: PageSeoOptions = {}) { const description = computed(() => toValue(options.description) ?? DEFAULT_DESCRIPTION) const image = computed(() => `${siteUrl}${toValue(options.image) ?? DEFAULT_OG_IMAGE}`) const url = computed(() => `${siteUrl}${route.path}`) + const modifiedTime = computed(() => { + const day = toValue(options.modifiedTime) + return day ? `${day}T00:00:00.000Z` : undefined + }) useHead({ title, - meta: computed(() => [ - { name: 'description', content: description.value, tagPriority: seoTagPriority }, - { property: 'og:site_name', content: 'AutoFixture', tagPriority: seoTagPriority }, - { property: 'og:type', content: 'website', tagPriority: seoTagPriority }, - { property: 'og:title', content: title.value, tagPriority: seoTagPriority }, - { property: 'og:description', content: description.value, tagPriority: seoTagPriority }, - { property: 'og:image', content: image.value, tagPriority: seoTagPriority }, - { property: 'og:image:width', content: OG_IMAGE_WIDTH, tagPriority: seoTagPriority }, - { property: 'og:image:height', content: OG_IMAGE_HEIGHT, tagPriority: seoTagPriority }, - { property: 'og:url', content: url.value, tagPriority: seoTagPriority }, - { name: 'twitter:card', content: 'summary_large_image', tagPriority: seoTagPriority }, - { name: 'twitter:title', content: title.value, tagPriority: seoTagPriority }, - { name: 'twitter:description', content: description.value, tagPriority: seoTagPriority }, - { name: 'twitter:image', content: image.value, tagPriority: seoTagPriority }, - ]), + meta: computed(() => { + const tags = [ + { name: 'description', content: description.value, tagPriority: seoTagPriority }, + { property: 'og:site_name', content: 'AutoFixture', tagPriority: seoTagPriority }, + { property: 'og:type', content: 'website', tagPriority: seoTagPriority }, + { property: 'og:title', content: title.value, tagPriority: seoTagPriority }, + { property: 'og:description', content: description.value, tagPriority: seoTagPriority }, + { property: 'og:image', content: image.value, tagPriority: seoTagPriority }, + { property: 'og:image:width', content: OG_IMAGE_WIDTH, tagPriority: seoTagPriority }, + { property: 'og:image:height', content: OG_IMAGE_HEIGHT, tagPriority: seoTagPriority }, + { property: 'og:url', content: url.value, tagPriority: seoTagPriority }, + { name: 'twitter:card', content: 'summary_large_image', tagPriority: seoTagPriority }, + { name: 'twitter:title', content: title.value, tagPriority: seoTagPriority }, + { name: 'twitter:description', content: description.value, tagPriority: seoTagPriority }, + { name: 'twitter:image', content: image.value, tagPriority: seoTagPriority }, + ] + + if (modifiedTime.value) { + tags.push( + { property: 'article:modified_time', content: modifiedTime.value, tagPriority: seoTagPriority }, + { property: 'og:updated_time', content: modifiedTime.value, tagPriority: seoTagPriority }, + ) + } + + return tags + }), }) } diff --git a/site/app/pages/docs/[...slug].vue b/site/app/pages/docs/[...slug].vue index 51b34ea..5f74f7a 100644 --- a/site/app/pages/docs/[...slug].vue +++ b/site/app/pages/docs/[...slug].vue @@ -1,4 +1,6 @@