verbesserte Copy
This commit is contained in:
@@ -37,11 +37,11 @@ export default function CTA() {
|
||||
<span className="store-btn-big">{hasIosStoreUrl ? 'App Store' : t.cta.supportLabel}</span>
|
||||
</div>
|
||||
</a>
|
||||
<a
|
||||
href={hasAndroidStoreUrl ? siteConfig.androidPlayStoreUrl : '/support'}
|
||||
className="store-btn"
|
||||
id="cta-googleplay"
|
||||
aria-label="Google Play or contact"
|
||||
<a
|
||||
href={hasAndroidStoreUrl ? siteConfig.androidPlayStoreUrl : '/support'}
|
||||
className="store-btn"
|
||||
id="cta-googleplay"
|
||||
aria-label={hasAndroidStoreUrl ? 'Google Play' : 'Contact support'}
|
||||
>
|
||||
<svg className="store-btn-icon" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
|
||||
<path d="M3.18 23.76c.33.18.7.24 1.08.17L14.84 12 11.17 8.33 3.18 23.76zm17.16-12.38-3.32-1.89-3.78 3.78 3.78 3.78 3.34-1.9c.95-.54.95-1.92-.02-2.77zM2.01 1.11C1.7 1.44 1.5 1.97 1.5 2.67v18.66c0 .7.2 1.23.51 1.56l.08.08L12.16 12v-.22L2.09 1.03l-.08.08zm9.16 10.67 2.67 2.67-10.5 5.97 7.83-8.64z" />
|
||||
|
||||
@@ -9,66 +9,66 @@ const faqs = [
|
||||
question: {
|
||||
en: 'How does GreenLens identify a plant?',
|
||||
de: 'Wie erkennt GreenLens eine Pflanze?',
|
||||
es: '¿Cómo identifica GreenLens una planta?'
|
||||
es: '¿Cómo identifica GreenLens una planta?'
|
||||
},
|
||||
answer: {
|
||||
en: 'GreenLens analyzes the plant photo and combines that with app-side care guidance so you can move from scan to next steps faster.',
|
||||
de: 'GreenLens analysiert das Pflanzenfoto und verbindet das Ergebnis mit Pflegehinweisen in der App, damit du schneller zu klaren nächsten Schritten kommst.',
|
||||
es: 'GreenLens analiza la foto de la planta y combina el resultado con indicaciones de cuidado dentro de la app para que avances más rápido.'
|
||||
en: 'GreenLens analyzes the plant photo and combines that with app-side care guidance so you can move from scan to next steps faster.',
|
||||
de: 'GreenLens analysiert das Pflanzenfoto und verbindet das Ergebnis mit Pflegehinweisen in der App, damit du schneller zu klaren nächsten Schritten kommst.',
|
||||
es: 'GreenLens analiza la foto de la planta y combina el resultado con indicaciones de cuidado dentro de la app para que avances más rápido.'
|
||||
}
|
||||
},
|
||||
{
|
||||
question: {
|
||||
en: 'Is GreenLens free to use?',
|
||||
de: 'Ist GreenLens kostenlos?',
|
||||
es: '¿Es GreenLens gratuito?'
|
||||
es: '¿Es GreenLens gratuito?'
|
||||
},
|
||||
answer: {
|
||||
en: 'GreenLens includes free functionality plus paid options such as subscriptions and credit top-ups for advanced AI features.',
|
||||
de: 'GreenLens bietet kostenlose Funktionen und zusätzlich kostenpflichtige Optionen wie Abos und Credit-Top-ups für erweiterte KI-Funktionen.',
|
||||
es: 'GreenLens incluye funciones gratuitas y también opciones de pago como suscripciones y créditos para funciones de IA más amplias.'
|
||||
en: 'One scan is free without an account, and you get three more after signing up. Beyond that GreenLens Pro is required — monthly or yearly, with current pricing shown in the App Store and cancellation any time in your iPhone settings. Optional credit packs exist for heavy use; you do not need them to start.',
|
||||
de: 'Ein Scan ist gratis, ganz ohne Anmeldung. Nach der Anmeldung bekommst du drei weitere. Danach brauchst du GreenLens Pro — Monats- oder Jahresabo mit den aktuellen Preisen im App Store, jederzeit über die iPhone-Einstellungen kündbar. Optionale Credit-Pakete gibt es für intensive Nutzung; zum Start brauchst du sie nicht.',
|
||||
es: 'Un escaneo es gratis, sin crear cuenta. Tras registrarte recibes tres más. A partir de ahí necesitas GreenLens Pro: suscripción mensual o anual, con los precios actuales en la App Store y cancelación en cualquier momento desde los ajustes del iPhone. Hay paquetes de créditos opcionales para uso intensivo; no los necesitas para empezar.'
|
||||
}
|
||||
},
|
||||
{
|
||||
question: {
|
||||
en: 'Can I use GreenLens offline?',
|
||||
de: 'Kann ich GreenLens offline nutzen?',
|
||||
es: '¿Puedo usar GreenLens sin conexión?'
|
||||
es: '¿Puedo usar GreenLens sin conexión?'
|
||||
},
|
||||
answer: {
|
||||
en: 'Plant identification and health checks require an internet connection. Your saved collection, care notes, and watering reminders are available offline.',
|
||||
de: 'Pflanzenidentifikation und Gesundheitscheck benötigen eine Internetverbindung. Deine gespeicherte Sammlung, Pflegenotizen und Gieß-Erinnerungen sind offline verfügbar.',
|
||||
es: 'La identificación de plantas y el control de salud requieren conexión a internet. Tu colección guardada, notas de cuidado y recordatorios de riego están disponibles sin conexión.'
|
||||
de: 'Pflanzenidentifikation und Gesundheitscheck benötigen eine Internetverbindung. Deine gespeicherte Sammlung, Pflegenotizen und Gieß-Erinnerungen sind offline verfügbar.',
|
||||
es: 'La identificación de plantas y el control de salud requieren conexión a internet. Tu colección guardada, notas de cuidado y recordatorios de riego están disponibles sin conexión.'
|
||||
}
|
||||
},
|
||||
{
|
||||
question: {
|
||||
en: 'What kind of plants can I use GreenLens for?',
|
||||
de: 'Für welche Pflanzen kann ich GreenLens nutzen?',
|
||||
es: '¿Para qué tipo de plantas puedo usar GreenLens?'
|
||||
de: 'Für welche Pflanzen kann ich GreenLens nutzen?',
|
||||
es: '¿Para qué tipo de plantas puedo usar GreenLens?'
|
||||
},
|
||||
answer: {
|
||||
en: 'GreenLens covers 450+ plant species including houseplants, garden plants, and succulents. It is built for everyday plant owners who want identification and care guidance in one place.',
|
||||
de: 'GreenLens umfasst über 450 Pflanzenarten, darunter Zimmerpflanzen, Gartenpflanzen und Sukkulenten. Die App richtet sich an Pflanzenbesitzer, die Identifikation und Pflege an einem Ort wollen.',
|
||||
es: 'GreenLens cubre más de 450 especies de plantas, incluyendo plantas de interior, de jardín y suculentas. Está pensada para quienes quieren identificación y cuidado en un solo lugar.'
|
||||
de: 'GreenLens umfasst über 450 Pflanzenarten, darunter Zimmerpflanzen, Gartenpflanzen und Sukkulenten. Die App richtet sich an Pflanzenbesitzer, die Identifikation und Pflege an einem Ort wollen.',
|
||||
es: 'GreenLens cubre más de 450 especies de plantas, incluyendo plantas de interior, de jardín y suculentas. Está pensada para quienes quieren identificación y cuidado en un solo lugar.'
|
||||
}
|
||||
},
|
||||
{
|
||||
question: {
|
||||
en: 'How do I start my plant collection?',
|
||||
de: 'Wie starte ich meine Pflanzensammlung?',
|
||||
es: '¿Cómo empiezo mi colección de plantas?'
|
||||
es: '¿Cómo empiezo mi colección de plantas?'
|
||||
},
|
||||
answer: {
|
||||
en: 'Start with a scan, review the result, and save the plant to your collection to keep notes, reminders, and follow-up care in one place.',
|
||||
de: 'Starte mit einem Scan, prüfe das Ergebnis und speichere die Pflanze in deiner Sammlung, damit Notizen, Erinnerungen und Pflege an einem Ort bleiben.',
|
||||
es: 'Empieza con un escaneo, revisa el resultado y guarda la planta en tu colección para mantener notas, recordatorios y cuidado en un solo lugar.'
|
||||
de: 'Starte mit einem Scan, prüfe das Ergebnis und speichere die Pflanze in deiner Sammlung, damit Notizen, Erinnerungen und Pflege an einem Ort bleiben.',
|
||||
es: 'Empieza con un escaneo, revisa el resultado y guarda la planta en tu colección para mantener notas, recordatorios y cuidado en un solo lugar.'
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const TEXT = {
|
||||
de: { tag: 'Fragen', h2: ['Häufig gestellte', 'Fragen'], desc: 'Alles, was du über GreenLens und den Einstieg wissen musst.' },
|
||||
de: { tag: 'Fragen', h2: ['Häufig gestellte', 'Fragen'], desc: 'Alles, was du über GreenLens und den Einstieg wissen musst.' },
|
||||
en: { tag: 'Questions', h2: ['Frequently Asked', 'Questions'], desc: 'Everything you need to know about GreenLens and getting started.' },
|
||||
es: { tag: 'Preguntas', h2: ['Preguntas', 'Frecuentes'], desc: 'Todo lo que necesitas saber sobre GreenLens y el inicio.' },
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
SeoComparison,
|
||||
SeoContentSections,
|
||||
SeoBestFit,
|
||||
SeoOfferBlock,
|
||||
SeoFaq,
|
||||
SeoRelated,
|
||||
} from '@/components/seo/SeoSections'
|
||||
@@ -43,18 +44,67 @@ export default function SeoCategoryPage({ profile }: SeoCategoryPageProps) {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'SoftwareApplication',
|
||||
name: siteConfig.name,
|
||||
operatingSystem: 'iOS, Android',
|
||||
operatingSystem: 'iOS',
|
||||
applicationCategory: 'LifestyleApplication',
|
||||
description: profile.directAnswer,
|
||||
...(hasIosStoreUrl && { downloadUrl: siteConfig.iosAppStoreUrl }),
|
||||
// Kein pauschaler Nullpreis: Der Download ist kostenlos, die Nutzung nach
|
||||
// vier Scans nicht. Apple liefert die regionalen Preise selbst aus.
|
||||
offers: {
|
||||
'@type': 'Offer',
|
||||
price: '0',
|
||||
priceCurrency: 'EUR',
|
||||
category: 'Free trial, then subscription',
|
||||
priceSpecification: {
|
||||
'@type': 'PriceSpecification',
|
||||
description:
|
||||
'One scan free without an account, three more after signing up, then a monthly or yearly GreenLens Pro subscription. Current regional pricing is shown in the App Store.',
|
||||
},
|
||||
},
|
||||
}
|
||||
: null
|
||||
|
||||
// HowTo: bevorzugtes Format vieler KI-Antwortsysteme fuer "Wie erkenne ich ..."-Fragen
|
||||
const howToSchema =
|
||||
profile.howToSteps && profile.howToSteps.length > 0
|
||||
? {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'HowTo',
|
||||
name: profile.howToName ?? profile.h1,
|
||||
description: profile.directAnswer,
|
||||
inLanguage: locale,
|
||||
totalTime: 'PT5M',
|
||||
step: profile.howToSteps.map((item, index) => ({
|
||||
'@type': 'HowToStep',
|
||||
position: index + 1,
|
||||
name: item.name,
|
||||
text: item.text,
|
||||
})),
|
||||
}
|
||||
: null
|
||||
|
||||
// WebPage mit Aenderungsdatum, Autor und Sprache — Frische- und E-E-A-T-Signale
|
||||
const webPageSchema = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'WebPage',
|
||||
name: profile.h1,
|
||||
description: profile.metaDescription,
|
||||
url: `${siteConfig.domain}${profile.canonical}`,
|
||||
inLanguage: locale,
|
||||
dateModified: profile.lastUpdatedIso ?? undefined,
|
||||
primaryImageOfPage: profile.heroImage
|
||||
? { '@type': 'ImageObject', url: `${siteConfig.domain}${profile.heroImage}`, caption: profile.heroImageAlt }
|
||||
: undefined,
|
||||
isPartOf: {
|
||||
'@type': 'WebSite',
|
||||
name: siteConfig.name,
|
||||
url: siteConfig.domain,
|
||||
},
|
||||
publisher: {
|
||||
'@type': 'Organization',
|
||||
name: siteConfig.name,
|
||||
url: siteConfig.domain,
|
||||
},
|
||||
}
|
||||
|
||||
const breadcrumbSchema = {
|
||||
'@context': 'https://schema.org',
|
||||
'@type': 'BreadcrumbList',
|
||||
@@ -90,6 +140,16 @@ export default function SeoCategoryPage({ profile }: SeoCategoryPageProps) {
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(breadcrumbSchema) }}
|
||||
/>
|
||||
{howToSchema && (
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(howToSchema) }}
|
||||
/>
|
||||
)}
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(webPageSchema) }}
|
||||
/>
|
||||
|
||||
<SeoNavbar locale={locale} methodologyHref={usesPhotoAnalysis ? '#methodology' : '#comparison'} />
|
||||
|
||||
@@ -111,6 +171,7 @@ export default function SeoCategoryPage({ profile }: SeoCategoryPageProps) {
|
||||
{usesPhotoAnalysis && <SeoMethodology copy={copy} intent={templateIntent} />}
|
||||
<SeoComparison profile={profile} copy={copy} intent={templateIntent} />
|
||||
<SeoBestFit profile={profile} copy={copy} />
|
||||
<SeoOfferBlock profile={profile} />
|
||||
<SeoFaq profile={profile} copy={copy} />
|
||||
<SeoRelated profile={profile} copy={copy} />
|
||||
</main>
|
||||
|
||||
@@ -38,6 +38,20 @@ export function SeoHero({
|
||||
{copy.hero.ctaSecondary}
|
||||
</a>
|
||||
</div>
|
||||
<ul className="mt-6 flex flex-wrap gap-x-5 gap-y-2 seo-fade seo-fade-3">
|
||||
{profile.timeCue && (
|
||||
<li className="flex items-center gap-2 text-sm text-on-surface-variant">
|
||||
<SeoIcon name="check_circle" className="w-4 h-4 shrink-0 text-primary" />
|
||||
<span>{profile.timeCue}</span>
|
||||
</li>
|
||||
)}
|
||||
{copy.hero.trustChips.map((chip) => (
|
||||
<li key={chip} className="flex items-center gap-2 text-sm text-on-surface-variant">
|
||||
<SeoIcon name="check_circle" className="w-4 h-4 shrink-0 text-primary" />
|
||||
<span>{chip}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<div className="mt-12 grid grid-cols-2 gap-6 pt-8 border-t border-surface-container-high seo-fade seo-fade-3">
|
||||
<div>
|
||||
<div className="font-display text-2xl font-semibold text-primary mb-1">{copy.hero.stat1Title}</div>
|
||||
@@ -52,7 +66,11 @@ export function SeoHero({
|
||||
<div className="lg:col-span-6 flex justify-center items-center seo-fade seo-fade-2">
|
||||
<div className="relative w-full max-w-[320px] md:max-w-[380px] h-[550px] md:h-[650px] rounded-3xl overflow-hidden shadow-2xl border-[8px] border-surface-container">
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
<img alt={copy.hero.imageAlt} className="w-full h-full object-cover" src="/hero.jpg" />
|
||||
<img
|
||||
alt={profile.heroImageAlt ?? copy.hero.imageAlt}
|
||||
className="w-full h-full object-cover"
|
||||
src={profile.heroImage ?? '/hero.jpg'}
|
||||
/>
|
||||
<div className="absolute bottom-6 left-1/2 -translate-x-1/2 w-[90%] bg-surface/95 backdrop-blur p-4 rounded-xl border border-surface-container-highest flex items-center gap-3 shadow-xl">
|
||||
<div className="w-1.5 h-8 bg-primary rounded-full"></div>
|
||||
<div>
|
||||
@@ -71,11 +89,9 @@ export function SeoAdvantage({
|
||||
copy,
|
||||
showInsights = false,
|
||||
}: SectionProps & { showInsights?: boolean }) {
|
||||
const reviewedAt = {
|
||||
de: 'Juli 2026',
|
||||
en: 'July 2026',
|
||||
es: 'Julio 2026',
|
||||
}[profile.locale ?? 'en']
|
||||
// Echtes Prüfdatum aus dem Profil. Kein globales Datum — eine Seite, die seit
|
||||
// April unverändert ist, darf kein aktuelleres Datum behaupten.
|
||||
const reviewedAt = profile.lastUpdated
|
||||
|
||||
return (
|
||||
<section className={`max-w-[1200px] mx-auto px-6 py-16 grid grid-cols-1 ${showInsights ? 'lg:grid-cols-3' : ''} gap-12 border-t border-surface-container-high`} id="advantage">
|
||||
@@ -221,6 +237,29 @@ export function SeoContentSections({ profile }: { profile: SeoPageProfile }) {
|
||||
)
|
||||
}
|
||||
|
||||
export function SeoOfferBlock({ profile }: { profile: SeoPageProfile }) {
|
||||
if (!profile.offer) return null
|
||||
|
||||
const { eyebrow, title, body, terms, ctaLabel } = profile.offer
|
||||
|
||||
return (
|
||||
<section className="max-w-[1200px] mx-auto px-6 py-16">
|
||||
<div className="bg-surface rounded-2xl p-8 md:p-12 border border-surface-container-high shadow-sm">
|
||||
<span className="text-xs font-semibold tracking-[0.1em] uppercase text-primary block mb-4">{eyebrow}</span>
|
||||
<h2 className="font-display font-semibold text-2xl md:text-3xl text-primary mb-4 max-w-[26ch]">{title}</h2>
|
||||
<p className="font-body text-on-surface-variant leading-relaxed mb-6 max-w-[60ch]">{body}</p>
|
||||
<a
|
||||
className="inline-flex justify-center items-center px-8 py-3 bg-ink text-white rounded-full font-bold shadow-lg hover:bg-ink-soft transition-colors duration-300"
|
||||
href="#download"
|
||||
>
|
||||
{ctaLabel}
|
||||
</a>
|
||||
<p className="font-body text-sm text-on-surface-variant mt-5 max-w-[60ch]">{terms}</p>
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
export function SeoBestFit({ profile, copy }: SectionProps) {
|
||||
return (
|
||||
<section className="max-w-[1200px] mx-auto px-6 py-16 grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
|
||||
Reference in New Issue
Block a user