add: more SEO meta
More seometa, better markdown parser
This commit is contained in:
parent
ca3868299c
commit
fa0435efdf
10 changed files with 52 additions and 14 deletions
|
@ -8,8 +8,6 @@
|
|||
|
||||
<script setup>
|
||||
useSeoMeta({
|
||||
title: 'Home',
|
||||
description: 'Headless CMS, Components & APIs by Fiona Urban. Storyblok, FirstSpirit, Nuxt.',
|
||||
author: 'webfussel',
|
||||
robots: 'index, follow',
|
||||
themeColor: '#2a2723',
|
||||
|
|
|
@ -130,7 +130,7 @@ const oneOff : Service[] = [
|
|||
]
|
||||
|
||||
const { data: faq } = await useAsyncData('faq', () => queryCollection('faq').path('/snippets/faq/booking').first())
|
||||
const texts = usePlainFaq(faq.value?.body.value)
|
||||
const texts = generatePlainText<['title']>(faq.value?.body.value)
|
||||
|
||||
if (faq) {
|
||||
useSchemaOrg({
|
||||
|
@ -138,10 +138,10 @@ if (faq) {
|
|||
'@type': 'FAQPage',
|
||||
'mainEntity': texts.map(entity => ({
|
||||
'@type': 'Question',
|
||||
'name': entity.question,
|
||||
'name': entity.meta.title,
|
||||
'acceptedAnswer': {
|
||||
'@type': 'Answer',
|
||||
'text': entity.answer,
|
||||
'text': entity.text,
|
||||
},
|
||||
}))
|
||||
})
|
||||
|
|
|
@ -139,7 +139,7 @@ const flatrate : Service[] =
|
|||
]
|
||||
|
||||
const { data : faq } = await useAsyncData('faq', () => queryCollection('faq').path('/snippets/faq/flatrate').first())
|
||||
const texts = usePlainFaq(faq.value?.body.value)
|
||||
const texts = generatePlainText<['title']>(faq.value?.body.value)
|
||||
|
||||
if (faq) {
|
||||
useSchemaOrg({
|
||||
|
@ -147,10 +147,10 @@ if (faq) {
|
|||
'@type': 'FAQPage',
|
||||
'mainEntity': texts.map(entity => ({
|
||||
'@type': 'Question',
|
||||
'name': entity.question,
|
||||
'name': entity.meta.title,
|
||||
'acceptedAnswer': {
|
||||
'@type': 'Answer',
|
||||
'text': entity.answer,
|
||||
'text': entity.text,
|
||||
},
|
||||
}))
|
||||
})
|
||||
|
|
|
@ -3,3 +3,10 @@
|
|||
<SectionBooking />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
useSeoMeta({
|
||||
title: 'Projektbuchung',
|
||||
description: 'Buche jetzt dein Projekt auf webfussel. Du brauchst eine Schulung in JavaScript, Typescript, HTML, CSS, Vue oder Nuxt? Kein Problem.',
|
||||
})
|
||||
</script>
|
||||
|
|
|
@ -3,3 +3,10 @@
|
|||
<SectionContact />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
useSeoMeta({
|
||||
title: 'Kontakt',
|
||||
description: 'Nimm Kontakt zu webfussel auf. Egal ob über E-Mail oder Social Media - ich freue mich auf deine Nachricht.',
|
||||
})
|
||||
</script>
|
|
@ -3,3 +3,10 @@
|
|||
<SectionFlatrate />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
useSeoMeta({
|
||||
title: 'Flatrate',
|
||||
description: 'Buche webfussel ganz einfach für eine zugesicherte Anzahl Stunden pro Woche. Wenn immer mal wieder was anfällt - vertrau auf Fusselqualität.',
|
||||
})
|
||||
</script>
|
|
@ -14,4 +14,9 @@ useHead({
|
|||
{ rel: 'icon', href: '/favicon.ico', type: 'image/x-icon' },
|
||||
],
|
||||
})
|
||||
|
||||
useSeoMeta({
|
||||
title: 'Home',
|
||||
description: 'Webprojekte und Retainer mit Fusselqualität. Du brauchst eine Website mit CMS? Bock auf Flatrate? webfussel by Fiona Urban',
|
||||
})
|
||||
</script>
|
|
@ -2,4 +2,11 @@
|
|||
<div>
|
||||
<SectionCustomers />
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
useSeoMeta({
|
||||
title: 'Referenzen',
|
||||
description: 'Schau dir dir Projekte von webfussel an. Über persönliche Webseiten, über Schulungen bis hin zu API Projekten.',
|
||||
})
|
||||
</script>
|
|
@ -1,5 +1,12 @@
|
|||
import type { MinimalElement, MinimalNode } from '@nuxt/content'
|
||||
|
||||
type TypedRecord<T extends readonly string[]> = Record<T[number], string>
|
||||
|
||||
type PlainText<T extends string[]> = {
|
||||
meta: TypedRecord<T>
|
||||
text: string
|
||||
}
|
||||
|
||||
const extractText = (element ?: MinimalNode) : string => {
|
||||
if (!element) return ''
|
||||
if (typeof element === 'string') return element
|
||||
|
@ -7,13 +14,13 @@ const extractText = (element ?: MinimalNode) : string => {
|
|||
return nodes?.map((el : MinimalNode) => typeof el === 'string' ? el : extractText(el)).join(' ') ?? ''
|
||||
}
|
||||
|
||||
export const usePlainFaq = (body ?: MinimalNode[]) => {
|
||||
export const generatePlainText = <T extends string[] = []>(body ?: MinimalNode[]) : PlainText<T>[] => {
|
||||
if (!body) return []
|
||||
return body.map(part => {
|
||||
return body.map<PlainText<T>>(part => {
|
||||
const [, meta] = part as MinimalElement
|
||||
return {
|
||||
question: meta.title,
|
||||
answer: extractText(part).replace(/\n/g, ' ')
|
||||
meta : meta as TypedRecord<T>,
|
||||
text: extractText(part).replace(/\n/g, ' ')
|
||||
}
|
||||
})
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue