diff --git a/assets/fonts/Assistant-Regular.ttf b/assets/fonts/ttf/Assistant-Regular.ttf
similarity index 100%
rename from assets/fonts/Assistant-Regular.ttf
rename to assets/fonts/ttf/Assistant-Regular.ttf
diff --git a/assets/fonts/ColabThi.otf b/assets/fonts/ttf/ColabThi.otf
similarity index 100%
rename from assets/fonts/ColabThi.otf
rename to assets/fonts/ttf/ColabThi.otf
diff --git a/assets/fonts/Comfortaa-Bold.ttf b/assets/fonts/ttf/Comfortaa-Bold.ttf
similarity index 100%
rename from assets/fonts/Comfortaa-Bold.ttf
rename to assets/fonts/ttf/Comfortaa-Bold.ttf
diff --git a/assets/fonts/Comfortaa-Light.ttf b/assets/fonts/ttf/Comfortaa-Light.ttf
similarity index 100%
rename from assets/fonts/Comfortaa-Light.ttf
rename to assets/fonts/ttf/Comfortaa-Light.ttf
diff --git a/assets/fonts/Comfortaa-Regular.ttf b/assets/fonts/ttf/Comfortaa-Regular.ttf
similarity index 100%
rename from assets/fonts/Comfortaa-Regular.ttf
rename to assets/fonts/ttf/Comfortaa-Regular.ttf
diff --git a/assets/fonts/JMH_Typewriter.ttf b/assets/fonts/ttf/JMH_Typewriter.ttf
similarity index 100%
rename from assets/fonts/JMH_Typewriter.ttf
rename to assets/fonts/ttf/JMH_Typewriter.ttf
diff --git a/assets/fonts/woff2/ColabThi.woff2 b/assets/fonts/woff2/ColabThi.woff2
new file mode 100644
index 0000000..2600540
Binary files /dev/null and b/assets/fonts/woff2/ColabThi.woff2 differ
diff --git a/assets/fonts/woff2/Comfortaa-Bold.woff2 b/assets/fonts/woff2/Comfortaa-Bold.woff2
new file mode 100644
index 0000000..8da8fd1
Binary files /dev/null and b/assets/fonts/woff2/Comfortaa-Bold.woff2 differ
diff --git a/assets/fonts/woff2/Comfortaa-Light.woff2 b/assets/fonts/woff2/Comfortaa-Light.woff2
new file mode 100644
index 0000000..5046e51
Binary files /dev/null and b/assets/fonts/woff2/Comfortaa-Light.woff2 differ
diff --git a/assets/fonts/woff2/Comfortaa-Regular.woff2 b/assets/fonts/woff2/Comfortaa-Regular.woff2
new file mode 100644
index 0000000..7aa1902
Binary files /dev/null and b/assets/fonts/woff2/Comfortaa-Regular.woff2 differ
diff --git a/assets/fonts/woff2/Montserrat-Light.woff2 b/assets/fonts/woff2/Montserrat-Light.woff2
new file mode 100644
index 0000000..932d0b2
Binary files /dev/null and b/assets/fonts/woff2/Montserrat-Light.woff2 differ
diff --git a/assets/fonts/woff2/Montserrat-Medium.woff2 b/assets/fonts/woff2/Montserrat-Medium.woff2
new file mode 100644
index 0000000..510a2d0
Binary files /dev/null and b/assets/fonts/woff2/Montserrat-Medium.woff2 differ
diff --git a/assets/styles/main.sass b/assets/styles/main.sass
index 064389e..bc35a7f 100644
--- a/assets/styles/main.sass
+++ b/assets/styles/main.sass
@@ -16,35 +16,35 @@ $breakPointXXL: 1400px
@font-face
font-family: 'Mainfont'
- src: url('@/assets/fonts/montserrat/Montserrat-Light.otf') format("opentype")
+ src: url('@/assets/fonts/woff2/Montserrat-Light.woff2') format("woff2")
font-weight: normal
font-style: normal
font-display: swap
@font-face
font-family: 'Mainfont-Bold'
- src: url('@/assets/fonts/montserrat/Montserrat-Medium.otf') format("opentype")
+ src: url('@/assets/fonts/woff2/Montserrat-Medium.woff2') format("woff2")
font-weight: normal
font-style: normal
font-display: swap
@font-face
font-family: 'Comfortaa'
- src: url('@/assets/fonts/Comfortaa-Light.ttf') format("truetype")
+ src: url('@/assets/fonts/woff2/Comfortaa-Light.woff2') format("woff2")
font-weight: normal
font-style: normal
font-display: swap
@font-face
font-family: 'Comfortaa-Bold'
- src: url('@/assets/fonts/Comfortaa-Bold.ttf') format("truetype")
+ src: url('@/assets/fonts/woff2/Comfortaa-Bold.woff2') format("woff2")
font-weight: normal
font-style: normal
font-display: swap
@font-face
font-family: 'Typewriter'
- src: url('@/assets/fonts/JMH_Typewriter.ttf') format("truetype")
+ src: url('@/assets/fonts/woff2/JMH_Typewriter.woff2') format("woff2")
font-weight: normal
font-style: normal
font-display: swap
diff --git a/components/ContactForm.vue b/components/ContactForm.vue
index bde909f..80afcba 100644
--- a/components/ContactForm.vue
+++ b/components/ContactForm.vue
@@ -27,10 +27,12 @@
@@ -40,18 +42,22 @@ {{ companyinfo.phone }}
- {{ companyinfo.company }}
{{ companyinfo.street }}
{{ companyinfo.postalcode }} {{ companyinfo.city }}
-
{{ $t('contactForm.yourcontactperson') }} Sabrina Hennrich
-
+ {{ companyinfo.company }}
{{ companyinfo.street }}
{{ companyinfo.postalcode }} {{ companyinfo.city }}
+
{{ $t('contactForm.yourcontactperson') }} Sabrina Hennrich
+{{ companyinfo?.contact }}
+{{ companyinfo?.contact }}
{{ companyinfo?.street }}
{{ companyinfo?.postalcode }}
@@ -176,16 +176,21 @@ footer
margin-bottom: 0.2rem
margin-top: .2rem
+ i
+ font-size: .8rem
a
- cursor: pointer
- color: white
- font-weight: bold
- border-bottom: 0
+ cursor: pointer
+ color: white
+ font-weight: bold
+ border-bottom: 0
- &:hover
- box-shadow: 0 0 20px 0 rgba($primaryColor, .3)
- background-color: rgba($primaryColor, .2)
- border-radius: 4px
+ &:hover
+ box-shadow: 0 0 20px 0 rgba($primaryColor, .3)
+ background-color: rgba($primaryColor, .2)
+ border-radius: 4px
+
+ &.router-link-active
+ color: lighten($pink, 15%) !important
.logo
width: 10rem !important
diff --git a/composables/usePageMeta.ts b/composables/usePageMeta.ts
index 85ef0ad..1198277 100644
--- a/composables/usePageMeta.ts
+++ b/composables/usePageMeta.ts
@@ -1,39 +1,105 @@
-// composables/usePageMeta.ts
import { watch, computed } from 'vue'
import { useRoute } from 'vue-router'
import { useMainStore } from '@/stores/main'
import { useHead } from '@unhead/vue'
+import { storeToRefs } from 'pinia'
+// Importiere die Seiten-Routen
+import { i18nPages } from '../i18n/i18n-pages' // relativ zu deinem Composable-Pfad anpassen!
export function usePageMeta () {
const route = useRoute()
const mainStore = useMainStore()
+ const { companyinfo } = storeToRefs(mainStore)
- // ► Der aktuelle Page-Eintrag als computed
const currentPage = computed(() => mainStore.getPageByLink(route.path))
- // ► Reagiere auf Route- oder Store-Änderungen
watch(
- () => currentPage.value, // Quelle
- (page) => { // Callback
- if (!page) return
+ () => currentPage.value,
+ (page) => {
+ if (!page || !companyinfo.value) return
- const metaTitle = page.SEO?.pageTitle ?? 'Standard Title'
- const metaDescription = page.SEO?.seoDescription ?? 'Standard Description'
- const metaImage = page.SEO?.seoImage?.url ?? '/default-image.jpg'
+ const metaTitle = page.SEO?.pageTitle ?? 'digimedialoop'
+ const metaDescription = page.SEO?.seoDescription ?? 'Webdesign und Webentwicklung'
+ const metaImage = page.SEO?.seoImage?.url ?? 'https://strapi.digimedialoop.de/uploads/DML_Logo_grey_2024_c51210b70c.svg'
+
+ // Canonical URL
+ const config = useRuntimeConfig()
+ const canonical = `${config.public.appUrl}${route.path}`
+
+ // Robots Meta Tag
+ const robotsContent = route.path === '/danke' ? 'noindex, nofollow' : 'index, follow'
+
+ // Prüfe, ob Route Home oder References in allen Sprachen ist
+ const isHomePage = Object.values(i18nPages.index).includes(route.path)
+ const isReferencesPage = Object.values(i18nPages.references).includes(route.path)
+
+ // Basis LocalBusiness JSON-LD
+ const baseJsonLd = {
+ '@context': 'https://schema.org',
+ '@type': 'LocalBusiness',
+ name: companyinfo.value.company,
+ image: metaImage,
+ url: config.public.appUrl,
+ telephone: companyinfo.value.phone,
+ email: companyinfo.value.email,
+ address: {
+ '@type': 'PostalAddress',
+ streetAddress: companyinfo.value.street,
+ addressLocality: companyinfo.value.city,
+ postalCode: companyinfo.value.postalcode,
+ addressCountry: 'DE'
+ },
+ openingHoursSpecification: [
+ {
+ '@type': 'OpeningHoursSpecification',
+ dayOfWeek: ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
+ opens: '09:00',
+ closes: '17:00'
+ }
+ ]
+ }
+
+ // Falls Home oder References: ergänze das Rating (2 Bewertungen mit 5 Sternen)
+ let jsonLd = undefined
+ if (isHomePage || isReferencesPage) {
+ jsonLd = {
+ ...baseJsonLd,
+ aggregateRating: {
+ '@type': 'AggregateRating',
+ ratingValue: '5',
+ reviewCount: '2'
+ }
+ }
+ } else if (isHomePage) {
+ // Nur LocalBusiness ohne Rating z.B.
+ jsonLd = baseJsonLd
+ }
useHead({
title: metaTitle,
meta: [
- { name: 'description', content: metaDescription },
- { property: 'og:title', content: metaTitle },
- { property: 'og:description', content: metaDescription },
- { property: 'og:image', content: metaImage },
- { name: 'twitter:title', content: metaTitle },
- { name: 'twitter:description', content: metaDescription },
- { name: 'twitter:image', content: metaImage }
- ]
+ { name: 'description', content: metaDescription },
+ { name: 'robots', content: robotsContent },
+ { property: 'og:title', content: metaTitle },
+ { property: 'og:description', content: metaDescription },
+ { property: 'og:image', content: metaImage },
+ { name: 'twitter:title', content: metaTitle },
+ { name: 'twitter:description', content: metaDescription },
+ { name: 'twitter:image', content: metaImage }
+ ],
+ link: [
+ { rel: 'canonical', href: canonical }
+ ],
+ script: jsonLd
+ ? [
+ {
+ type: 'application/ld+json',
+ children: JSON.stringify(jsonLd)
+ }
+ ]
+ : []
})
},
- { immediate: true } // Sofort beim ersten Aufruf ausführen
+ { immediate: true }
)
}
diff --git a/i18n/i18n-pages.ts b/i18n/i18n-pages.ts
new file mode 100644
index 0000000..9cd506a
--- /dev/null
+++ b/i18n/i18n-pages.ts
@@ -0,0 +1,66 @@
+export const i18nPages = {
+ index: {
+ de: '/',
+ en: '/home',
+ fr: '/accueil',
+ it: '/home',
+ es: '/inicio',
+ tr: '/anasayfa'
+ },
+ webagency: {
+ de: '/webagentur',
+ en: '/webagency',
+ fr: '/agence-web',
+ it: '/agenzia-web',
+ es: '/agencia-web',
+ tr: '/web-ajansi'
+ },
+ services: {
+ de: '/leistungen',
+ en: '/services',
+ fr: '/services',
+ it: '/servizi',
+ es: '/servicios',
+ tr: '/hizmetler'
+ },
+ references: {
+ de: '/referenzen',
+ en: '/references',
+ fr: '/références',
+ it: '/referenze',
+ es: '/referencias',
+ tr: '/referanslar'
+ },
+ imprint: {
+ de: '/impressum',
+ en: '/imprint',
+ fr: '/mentions-legales',
+ it: '/note-legali',
+ es: '/aviso-legal',
+ tr: '/künye'
+ },
+ privacy: {
+ de: '/datenschutz',
+ en: '/privacy',
+ fr: '/confidentialite',
+ it: '/privacy',
+ es: '/privacidad',
+ tr: '/gizlilik'
+ },
+ terms: {
+ de: '/agb',
+ en: '/terms',
+ fr: '/conditions',
+ it: '/termini',
+ es: '/condiciones',
+ tr: '/kosullar'
+ },
+ magazin: {
+ de: '/wissenswertes',
+ en: '/magazine',
+ fr: '/magazine',
+ it: '/magazine',
+ es: '/revista',
+ tr: '/dergi'
+ }
+}
\ No newline at end of file
diff --git a/i18n/locales/de.json b/i18n/locales/de.json
index 538b53b..ae844ad 100644
--- a/i18n/locales/de.json
+++ b/i18n/locales/de.json
@@ -51,10 +51,10 @@
"heroBox": {
"h1": "Ihre Agentur für individuelles Webdesign und professionelle Webentwicklung",
"h2": "Modulare Webseiten mit modernsten Technologien",
- "h3": "So ist Ihre Website schnell, effizient und zukunftssicher!"
+ "h3": "Höchste Performanz - schnell, effizient und zukunftssicher!"
},
"solution": {
- "title": "Websites, die mehr können: Performance, Freiheit & KI-Power für Ihr Business",
+ "title": "Webseiten, die mehr können: Performance, Freiheit & KI-Power",
"teaser": "Wir entwickeln maßgeschneiderte Webseiten mit JAMstack-Technologie, die perfekt auf Ihr Business abgestimmt sind und als leistungsstarkes Marketing- und Vertriebsinstrument für Ihren Erfolg sorgen.",
"text": "Durch die klare Trennung von Inhalt und Technik, unter Verwendung eines headless Content-Management-Systems, entstehen wartungsfreundliche, suchmaschinenoptimierte Lösungen, die nicht nur langfristig skalierbar sind, sondern auch Ihrem Marketing-Team die Arbeit erleichtern. Inhalte lassen sich ohne technische Hürden pflegen, neue Funktionen flexibel integrieren – ganz ohne Plugin-Chaos oder Eingriffe ins Live-System. Dank sauberer semantischer Struktur sind unsere Lösungen zudem optimal auf AI-gestützte Suchsysteme vorbereitet und ermöglichen die einfache Integration in KI-gestützte Operator-Workflows.",
"buttonText": "Erfahren Sie mehr über Headless CMS"
diff --git a/nuxt.config.ts b/nuxt.config.ts
index a3583de..ff532e8 100644
--- a/nuxt.config.ts
+++ b/nuxt.config.ts
@@ -1,4 +1,17 @@
import { defineNuxtConfig } from 'nuxt/config'
+import { i18nPages } from './i18n/i18n-pages'
+
+// Hilfsfunktion, um Objekt mit locales auf reine Strings zu mappen
+function flattenPages(pagesObj: Record{{ $t('home.heroBox.h1') }}
@@ -76,7 +77,7 @@ class="pinkBtn" role="button"