FIX: seo
This commit is contained in:
parent
7252e464bb
commit
b23306b9d3
10 changed files with 73 additions and 84 deletions
69
app.vue
69
app.vue
|
@ -1,63 +1,28 @@
|
||||||
<template>
|
<template>
|
||||||
<section>
|
<section>
|
||||||
|
<NuxtLayout>
|
||||||
<NuxtPage />
|
<NuxtPage />
|
||||||
|
</NuxtLayout>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
const tags = [
|
useSeoMeta({
|
||||||
'webfussel',
|
|
||||||
'web',
|
|
||||||
'fussel',
|
|
||||||
'webentwicklung',
|
|
||||||
'webentwickler',
|
|
||||||
'vue',
|
|
||||||
'nuxt',
|
|
||||||
'javascript',
|
|
||||||
'typescript',
|
|
||||||
'scss',
|
|
||||||
'css',
|
|
||||||
'html',
|
|
||||||
'karlsruhe',
|
|
||||||
'freelance',
|
|
||||||
'freelancer',
|
|
||||||
'freiberuflich',
|
|
||||||
'remote',
|
|
||||||
'home office',
|
|
||||||
'api',
|
|
||||||
'components'
|
|
||||||
]
|
|
||||||
|
|
||||||
useHead({
|
|
||||||
title: 'webfussel | mehr Fussel im Web',
|
title: 'webfussel | mehr Fussel im Web',
|
||||||
htmlAttrs: {
|
description: 'Du brauchst was fürs Web? Komponenten, APIs oder Fullstack? Kein Ding.',
|
||||||
lang: 'de'
|
author: 'webfussel',
|
||||||
},
|
robots: 'index, follow',
|
||||||
meta: [
|
themeColor: '#2a2723',
|
||||||
{
|
ogTitle: 'webfussel | mehr Fussel im Web',
|
||||||
name: 'description',
|
ogDescription: 'Du brauchst was fürs Web? Komponenten, APIs oder Fullstack? Kein Ding.',
|
||||||
content: 'webfussel ist eine Webentwicklerin aus Baden-Württemberg. Sie entwickelt Komponenten, Applikationen und APIs.'
|
ogImage: '/img/og.webp',
|
||||||
},
|
ogImageAlt: 'Das webfussel Logo auf einem dunklen Hintergrund',
|
||||||
{
|
ogUrl: 'https://webfussel.de',
|
||||||
name: 'keywords',
|
twitterTitle: 'webfussel | mehr Fussel im Web',
|
||||||
content: tags.join(',')
|
twitterDescription: 'Du brauchst was fürs Web? Komponenten, APIs oder Fullstack? Kein Ding.',
|
||||||
},
|
twitterImage: '/img/og.webp',
|
||||||
{
|
twitterImageAlt: 'Das webfussel Logo auf einem dunklen Hintergrund',
|
||||||
name: 'author',
|
twitterUrl: 'https://webfussel.de',
|
||||||
content: 'webfussel'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'robots',
|
|
||||||
content: 'index, follow'
|
|
||||||
},
|
|
||||||
],
|
|
||||||
link: [
|
|
||||||
{ rel: 'preload', href: '/img/profile_big.webp', type: 'image/webp' },
|
|
||||||
{ rel: 'preload', href: '/img/profile_small.webp', type: 'image/webp' },
|
|
||||||
{ rel: 'preload', as: 'font', href: '/opensans.woff2', type: 'font/woff2' },
|
|
||||||
{ rel: 'preload', as: 'font', href: '/roboto_con_bold.woff2', type: 'font/woff2' },
|
|
||||||
{ rel: 'preload', as: 'font', href: '/roboto_con_reg.woff2', type: 'font/woff2' },
|
|
||||||
]
|
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -3,22 +3,41 @@
|
||||||
<template>
|
<template>
|
||||||
<footer class="Footer flex-col default-gap">
|
<footer class="Footer flex-col default-gap">
|
||||||
<ul class="sitemap default-gap">
|
<ul class="sitemap default-gap">
|
||||||
<li><a :href="`${mainPage ? '/' : ''}#intro`">Über mich</a></li>
|
<li v-for="{ label, ...rest} in nav" :key="label">
|
||||||
<li><a :href="`${mainPage ? '/' : ''}#skills`">Meine Expertise</a></li>
|
<NuxtLink v-bind="rest">{{label}}</NuxtLink>
|
||||||
<li><a :href="`${mainPage ? '/' : ''}#customers`">Kunden & Projekte</a></li>
|
</li>
|
||||||
<li><a :href="`${mainPage ? '/' : ''}#services`">Services</a></li>
|
|
||||||
<li><a :href="`${mainPage ? '/' : ''}#network`">Mein Netzwerk</a></li>
|
|
||||||
<li><a href="/imp">Impressum</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
<p>Natürlich ohne Cookies und Tracker.</p>
|
<p>Natürlich ohne Cookies und Tracker.</p>
|
||||||
<p>© 2024 by <a href="https://webfussel.de">webfussel</a></p>
|
<p>© 2024 by <a href="https://webfussel.de">webfussel</a></p>
|
||||||
</footer>
|
</footer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script lang="ts" setup>
|
||||||
type Props = {
|
const nav = [
|
||||||
mainPage ?: boolean
|
{
|
||||||
|
to: `/#intro`,
|
||||||
|
label: 'Über mich',
|
||||||
|
'aria-label': 'Link dieser Seite: Über mich'
|
||||||
|
}, {
|
||||||
|
to: `/#skills`,
|
||||||
|
label: 'Meine Expertise',
|
||||||
|
'aria-label': 'Link dieser Seite: Meine Expertis'
|
||||||
|
}, {
|
||||||
|
to: `/#customers`,
|
||||||
|
label: 'Kunden',
|
||||||
|
'aria-label': 'Link dieser Seite: Kunden'
|
||||||
|
}, {
|
||||||
|
to: `/#services`,
|
||||||
|
label: 'Services',
|
||||||
|
'aria-label': 'Link dieser Seite: Services'
|
||||||
|
}, {
|
||||||
|
to: `/#network`,
|
||||||
|
label: 'Mein Netzwerk',
|
||||||
|
'aria-label': 'Link dieser Seite: Mein Netzwerk'
|
||||||
|
}, {
|
||||||
|
to: '/imp',
|
||||||
|
label: 'Impressum',
|
||||||
|
'aria-label': 'Link dieser Seite: Impressum'
|
||||||
}
|
}
|
||||||
|
]
|
||||||
defineProps<Props>()
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
<nav>
|
<nav>
|
||||||
<ul class="main-nav">
|
<ul class="main-nav">
|
||||||
<li v-for="({label, ...rest}) in nav" :key="label" @click="isBurgerOpen = false">
|
<li v-for="({label, ...rest}) in nav" :key="label" @click="isBurgerOpen = false">
|
||||||
<a v-bind="rest">{{ label }}</a>
|
<NuxtLink v-bind="rest">{{ label }}</NuxtLink>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="socials">
|
<ul class="socials">
|
||||||
|
@ -49,12 +49,6 @@
|
||||||
import LinkedInIcon from 'iconoir/icons/regular/linkedin.svg'
|
import LinkedInIcon from 'iconoir/icons/regular/linkedin.svg'
|
||||||
import MastodonIcon from 'iconoir/icons/regular/mastodon.svg'
|
import MastodonIcon from 'iconoir/icons/regular/mastodon.svg'
|
||||||
|
|
||||||
type Props = {
|
|
||||||
mainPage ?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
const { mainPage } = defineProps<Props>()
|
|
||||||
|
|
||||||
let observer: IntersectionObserver
|
let observer: IntersectionObserver
|
||||||
const header = ref<HTMLElement | null>(null)
|
const header = ref<HTMLElement | null>(null)
|
||||||
const headerWrapper = ref<HTMLElement | null>(null)
|
const headerWrapper = ref<HTMLElement | null>(null)
|
||||||
|
@ -67,15 +61,15 @@ const burgerLabel = computed(() => isBurgerOpen.value ? burgerCloseLabel : burge
|
||||||
|
|
||||||
const nav = [
|
const nav = [
|
||||||
{
|
{
|
||||||
href: `${mainPage ? '/' : ''}#intro`,
|
to: `/#intro`,
|
||||||
label: 'Über mich',
|
label: 'Über mich',
|
||||||
'aria-label': 'Link dieser Seite: About'
|
'aria-label': 'Link dieser Seite: Über mich'
|
||||||
}, {
|
}, {
|
||||||
href: `${mainPage ? '/' : ''}#customers`,
|
to: `/#customers`,
|
||||||
label: 'Kunden',
|
label: 'Kunden',
|
||||||
'aria-label': 'Link dieser Seite: Kunden'
|
'aria-label': 'Link dieser Seite: Kunden'
|
||||||
}, {
|
}, {
|
||||||
href: `${mainPage ? '/' : ''}#services`,
|
to: `/#services`,
|
||||||
label: 'Services',
|
label: 'Services',
|
||||||
'aria-label': 'Link dieser Seite: Services'
|
'aria-label': 'Link dieser Seite: Services'
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
|
|
||||||
& img {
|
& img {
|
||||||
border: 4px solid var(--color-orange);
|
outline: 4px solid var(--color-orange);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
width: 150px;
|
width: 150px;
|
||||||
height: 150px;
|
height: 150px;
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
.network-list {
|
.network-list {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
|
padding-top: 4px;
|
||||||
|
|
||||||
& .scroll-container {
|
& .scroll-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
5
layouts/default.vue
Normal file
5
layouts/default.vue
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<template>
|
||||||
|
<Header />
|
||||||
|
<slot />
|
||||||
|
<Footer />
|
||||||
|
</template>
|
|
@ -11,5 +11,16 @@ export default defineNuxtConfig({
|
||||||
'/': { prerender: true },
|
'/': { prerender: true },
|
||||||
'/imp': { prerender: true },
|
'/imp': { prerender: true },
|
||||||
},
|
},
|
||||||
devtools: { enabled: false }
|
app: {
|
||||||
|
head: {
|
||||||
|
htmlAttrs: { lang: 'de' },
|
||||||
|
link: [
|
||||||
|
{ rel: 'preload', as: 'image', href: '/img/profile_big.webp', type: 'image/webp' },
|
||||||
|
{ rel: 'preload', as: 'image', href: '/img/profile_small.webp', type: 'image/webp' },
|
||||||
|
{ rel: 'preload', as: 'font', href: '/opensans.woff2', type: 'font/woff2' },
|
||||||
|
{ rel: 'preload', as: 'font', href: '/roboto_con_bold.woff2', type: 'font/woff2' },
|
||||||
|
{ rel: 'preload', as: 'font', href: '/roboto_con_reg.woff2', type: 'font/woff2' },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,12 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<Header />
|
|
||||||
<Intro />
|
<Intro />
|
||||||
<Skills />
|
<Skills />
|
||||||
<Customers />
|
<Customers />
|
||||||
<Services />
|
<Services />
|
||||||
<Footer />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup></script>
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<Header :main-page="true" />
|
|
||||||
<section class="Imp flex-col default-gap content full">
|
<section class="Imp flex-col default-gap content full">
|
||||||
<div>
|
<div>
|
||||||
<h3>Angaben gemäß § 5 TMG</h3>
|
<h3>Angaben gemäß § 5 TMG</h3>
|
||||||
|
@ -57,6 +56,5 @@
|
||||||
|
|
||||||
<p>Quelle: <a href="https://www.e-recht24.de">e-recht24.de</a></p>
|
<p>Quelle: <a href="https://www.e-recht24.de">e-recht24.de</a></p>
|
||||||
</section>
|
</section>
|
||||||
<Footer :main-page="true" />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
BIN
public/img/og.webp
Normal file
BIN
public/img/og.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 47 KiB |
Loading…
Add table
Add a link
Reference in a new issue