Revision vor Kundenübergabe: Plausibilität, SEO, A11y, OpenPanel
This commit is contained in:
@@ -24,7 +24,6 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@calcom/embed-react": "^1.5.3",
|
"@calcom/embed-react": "^1.5.3",
|
||||||
"@fontsource-variable/nunito-sans": "^5.3.0",
|
|
||||||
"@fontsource-variable/public-sans": "^5.3.0",
|
"@fontsource-variable/public-sans": "^5.3.0",
|
||||||
"@openpanel/web": "^1.4.1",
|
"@openpanel/web": "^1.4.1",
|
||||||
"@tailwindcss/vite": "^4.1.18",
|
"@tailwindcss/vite": "^4.1.18",
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 486 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.9 MiB |
Binary file not shown.
|
Before Width: | Height: | Size: 790 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.3 MiB |
@@ -38,7 +38,7 @@ export function AppShell({ session, nav, children }: AppShellProps) {
|
|||||||
<div className="mx-auto flex max-w-6xl items-center justify-between gap-4 px-4 py-2 md:px-6">
|
<div className="mx-auto flex max-w-6xl items-center justify-between gap-4 px-4 py-2 md:px-6">
|
||||||
<p className="flex items-center gap-2 text-sm">
|
<p className="flex items-center gap-2 text-sm">
|
||||||
<UserCog className="size-4" />
|
<UserCog className="size-4" />
|
||||||
Du bist als <strong>{session.user.name}</strong> ({session.user.email}) eingeloggt.
|
Sie sind als <strong>{session.user.name}</strong> ({session.user.email}) eingeloggt.
|
||||||
</p>
|
</p>
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export const Footer = () => {
|
|||||||
<p className="max-w-xl text-(--sea-ink-soft) sm:text-lg">
|
<p className="max-w-xl text-(--sea-ink-soft) sm:text-lg">
|
||||||
Buchen Sie sich einen Termin direkt online - 30 Minuten,
|
Buchen Sie sich einen Termin direkt online - 30 Minuten,
|
||||||
kostenlos, keine Warteschleifen. Wenn Sie lieber telefonieren,
|
kostenlos, keine Warteschleifen. Wenn Sie lieber telefonieren,
|
||||||
melde ich mich innerhalb eines Werktags zurück.
|
melden wir uns innerhalb eines Werktags zurück.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col gap-3 sm:flex-row lg:flex-col">
|
<div className="flex flex-col gap-3 sm:flex-row lg:flex-col">
|
||||||
|
|||||||
@@ -14,12 +14,12 @@ const steps = [
|
|||||||
{
|
{
|
||||||
icon: Wrench,
|
icon: Wrench,
|
||||||
title: "Umsetzung",
|
title: "Umsetzung",
|
||||||
text: "Ich baue Ihre Seite. Zwischenstände zeige ich Ihnen regelmäßig, Anpassungen sind normaler Teil des Prozesses.",
|
text: "Wir bauen Ihre Seite. Zwischenstände zeigen wir Ihnen regelmäßig, Anpassungen sind normaler Teil des Prozesses.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: Rocket,
|
icon: Rocket,
|
||||||
title: "Übergabe",
|
title: "Übergabe",
|
||||||
text: "Sie bekommen Ihre neue Webseite, wir helfen Ihnen mit Ihrem Hosting-Anbieter oder betreuen Sie in einem unserer Betreuung und Hosting-Tarif.",
|
text: "Sie bekommen Ihre neue Webseite. Auf Wunsch übernehmen wir den Betrieb in einem unserer Betreuungs- und Hosting-Tarife oder helfen bei der Übergabe an Ihren Hosting-Anbieter.",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ export const Process = () => {
|
|||||||
return (
|
return (
|
||||||
<section id="ablauf" className="mx-auto max-w-6xl px-4 py-16 md:px-6 md:py-24">
|
<section id="ablauf" className="mx-auto max-w-6xl px-4 py-16 md:px-6 md:py-24">
|
||||||
<div className="mx-auto max-w-2xl text-center">
|
<div className="mx-auto max-w-2xl text-center">
|
||||||
<span className="island-kicker">So arbeite ich</span>
|
<span className="island-kicker">So arbeiten wir</span>
|
||||||
<h2 className="mt-3 font-heading text-3xl font-bold leading-tight tracking-tight text-(--sea-ink) sm:text-4xl">
|
<h2 className="mt-3 font-heading text-3xl font-bold leading-tight tracking-tight text-(--sea-ink) sm:text-4xl">
|
||||||
In vier Schritten zur neuen Webseite
|
In vier Schritten zur neuen Webseite
|
||||||
</h2>
|
</h2>
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export const Services = () => {
|
|||||||
Finden Sie sich wieder?
|
Finden Sie sich wieder?
|
||||||
</h2>
|
</h2>
|
||||||
<p className="mt-4 text-(--sea-ink-soft) sm:text-lg">
|
<p className="mt-4 text-(--sea-ink-soft) sm:text-lg">
|
||||||
Meine Kunden verbindet eines: Sie sind Meister ihres Fachs -
|
Unsere Kunden verbindet eines: Sie sind Meister ihres Fachs -
|
||||||
und wollen sich nicht mit ihrer Webseite herumärgern.
|
und wollen sich nicht mit ihrer Webseite herumärgern.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -79,20 +79,22 @@ export const Route = createRootRouteWithContext<RouterAppContext>()({
|
|||||||
content:
|
content:
|
||||||
'Handgemachte Webseiten – blitzschnell, sicher und individuell.',
|
'Handgemachte Webseiten – blitzschnell, sicher und individuell.',
|
||||||
},
|
},
|
||||||
{ property: 'og:image', content: 'https://webkulisse.de/img/og-cover.png' },
|
// Übergangslösung: Logo als Preview-Bild. Wird ersetzt, sobald ein
|
||||||
{ property: 'og:image:width', content: '1200' },
|
// dediziertes 1200×630-Cover vorliegt (og:image:width/height dann anpassen).
|
||||||
{ property: 'og:image:height', content: '630' },
|
{ property: 'og:image', content: 'https://webkulisse.de/img/logo.png' },
|
||||||
{ property: 'og:image:alt', content: 'webkulisse – Webdesign für Handwerk, Praxis & Therapie' },
|
{ property: 'og:image:width', content: '690' },
|
||||||
|
{ property: 'og:image:height', content: '520' },
|
||||||
|
{ property: 'og:image:alt', content: 'webkulisse – Logo' },
|
||||||
{ property: 'og:url', content: 'https://webkulisse.de/' },
|
{ property: 'og:url', content: 'https://webkulisse.de/' },
|
||||||
// Twitter/X Card
|
// Twitter/X Card
|
||||||
{ name: 'twitter:card', content: 'summary_large_image' },
|
{ name: 'twitter:card', content: 'summary' },
|
||||||
{ name: 'twitter:title', content: 'webkulisse' },
|
{ name: 'twitter:title', content: 'webkulisse' },
|
||||||
{
|
{
|
||||||
name: 'twitter:description',
|
name: 'twitter:description',
|
||||||
content:
|
content:
|
||||||
'Handgemachte Webseiten – blitzschnell, sicher und individuell.',
|
'Handgemachte Webseiten – blitzschnell, sicher und individuell.',
|
||||||
},
|
},
|
||||||
{ name: 'twitter:image', content: 'https://webkulisse.de/img/og-cover.png' },
|
{ name: 'twitter:image', content: 'https://webkulisse.de/img/logo.png' },
|
||||||
],
|
],
|
||||||
links: [
|
links: [
|
||||||
{ rel: 'stylesheet', href: appCss },
|
{ rel: 'stylesheet', href: appCss },
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ const structuredData = {
|
|||||||
'Handgemachte Webseiten für Handwerk, Praxis und Therapie in Bayern – schnell, sicher und persönlich betreut.',
|
'Handgemachte Webseiten für Handwerk, Praxis und Therapie in Bayern – schnell, sicher und persönlich betreut.',
|
||||||
url: 'https://webkulisse.de/',
|
url: 'https://webkulisse.de/',
|
||||||
logo: 'https://webkulisse.de/img/logo.png',
|
logo: 'https://webkulisse.de/img/logo.png',
|
||||||
image: 'https://webkulisse.de/img/og-cover.png',
|
image: 'https://webkulisse.de/img/logo.png',
|
||||||
telephone: '+49 171 8084830',
|
telephone: '+49 171 8084830',
|
||||||
email: 'info@webkulisse.de',
|
email: 'info@webkulisse.de',
|
||||||
priceRange: '€€',
|
priceRange: '€€',
|
||||||
|
|||||||
@@ -41,9 +41,9 @@ function LoginPage() {
|
|||||||
if (code === 'INVALID_EMAIL_OR_PASSWORD') {
|
if (code === 'INVALID_EMAIL_OR_PASSWORD') {
|
||||||
setError('E-Mail oder Passwort ist falsch.')
|
setError('E-Mail oder Passwort ist falsch.')
|
||||||
} else if (code === 'INVALID_EMAIL') {
|
} else if (code === 'INVALID_EMAIL') {
|
||||||
setError('Bitte eine gueltige E-Mail-Adresse eingeben.')
|
setError('Bitte geben Sie eine gültige E-Mail-Adresse ein.')
|
||||||
} else if (code === 'USER_BANNED') {
|
} else if (code === 'USER_BANNED') {
|
||||||
setError('Dieser Zugang ist gesperrt. Bitte kontaktiere uns.')
|
setError('Dieser Zugang ist gesperrt. Bitte kontaktieren Sie uns.')
|
||||||
} else {
|
} else {
|
||||||
setError(res.error.message ?? 'Anmeldung fehlgeschlagen.')
|
setError(res.error.message ?? 'Anmeldung fehlgeschlagen.')
|
||||||
}
|
}
|
||||||
@@ -70,7 +70,7 @@ function LoginPage() {
|
|||||||
Kundenlogin
|
Kundenlogin
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-sm text-muted-foreground">
|
<p className="text-sm text-muted-foreground">
|
||||||
Melde dich mit deinen Zugangsdaten an.
|
Melden Sie sich mit Ihren Zugangsdaten an.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -120,7 +120,7 @@ function LoginPage() {
|
|||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<p className="text-center text-xs text-muted-foreground">
|
<p className="text-center text-xs text-muted-foreground">
|
||||||
Kein Konto? Neue Zugaenge legt dein Ansprechpartner bei webkulisse an.
|
Kein Konto? Neue Zugänge legt Ihr Ansprechpartner bei webkulisse an.
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
@import 'tailwindcss';
|
@import 'tailwindcss';
|
||||||
@import 'tw-animate-css';
|
@import 'tw-animate-css';
|
||||||
@import "shadcn/tailwind.css";
|
@import "shadcn/tailwind.css";
|
||||||
@import "@fontsource-variable/nunito-sans";
|
|
||||||
@import "@fontsource-variable/public-sans";
|
@import "@fontsource-variable/public-sans";
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
@@ -261,10 +260,6 @@ pre code {
|
|||||||
margin-inline: auto;
|
margin-inline: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.display-title {
|
|
||||||
font-family: 'Fraunces', Georgia, serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
.island-shell {
|
.island-shell {
|
||||||
border: 1px solid var(--line);
|
border: 1px solid var(--line);
|
||||||
background: linear-gradient(165deg, var(--surface-strong), var(--surface));
|
background: linear-gradient(165deg, var(--surface-strong), var(--surface));
|
||||||
@@ -419,82 +414,3 @@ img {
|
|||||||
@apply font-sans;
|
@apply font-sans;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Theme Toggle */
|
|
||||||
.theme-toggle {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.theme-toggle__label {
|
|
||||||
/* Groesse ueber diese zwei Variablen steuern -- alles andere wird berechnet.
|
|
||||||
Overriden per Style-Attribut, Elternklasse, oder Utility (--tta-size: ...). */
|
|
||||||
--tta-size: 2em; /* Hoehe des Switches — ggf. an euren size(10)-Wert anpassen */
|
|
||||||
--tta-ratio: 2; /* Breite = Hoehe × Ratio (2 = Pill 2:1) */
|
|
||||||
|
|
||||||
/* Abgeleitete Werte -- nicht ueberschreiben. */
|
|
||||||
--tta-width: calc(var(--tta-size) * var(--tta-ratio));
|
|
||||||
--tta-pad: calc(var(--tta-size) * 0.1);
|
|
||||||
--tta-knob: calc(var(--tta-size) - var(--tta-pad) * 2);
|
|
||||||
--tta-icon: calc(var(--tta-size) * 0.6);
|
|
||||||
--tta-travel: calc(var(--tta-width) - var(--tta-knob) - var(--tta-pad) * 2);
|
|
||||||
|
|
||||||
width: var(--tta-width);
|
|
||||||
height: var(--tta-size);
|
|
||||||
position: relative;
|
|
||||||
display: block;
|
|
||||||
background: white;
|
|
||||||
border-radius: var(--tta-size);
|
|
||||||
box-shadow: inset 0 5px 15px rgba(0, 0, 0, 0.4),
|
|
||||||
inset 0 -5px 15px rgba(0, 0, 0, 0.4);
|
|
||||||
cursor: pointer;
|
|
||||||
transition: background-color 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-toggle__label::after {
|
|
||||||
content: '';
|
|
||||||
width: var(--tta-knob);
|
|
||||||
height: var(--tta-knob);
|
|
||||||
position: absolute;
|
|
||||||
top: var(--tta-pad);
|
|
||||||
left: var(--tta-pad);
|
|
||||||
background: linear-gradient(180deg, #ffcc89, #d8860b);
|
|
||||||
border-radius: var(--tta-knob);
|
|
||||||
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
|
|
||||||
transition: transform 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-toggle__label svg {
|
|
||||||
position: absolute;
|
|
||||||
width: var(--tta-icon);
|
|
||||||
top: calc((var(--tta-size) - var(--tta-icon)) / 2);
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Icon-Positionierung symmetrisch: mittig im jeweiligen "Knubbel-Slot". */
|
|
||||||
.theme-toggle__sun {
|
|
||||||
left: calc(var(--tta-pad) + (var(--tta-knob) - var(--tta-icon)) / 2);
|
|
||||||
fill: gold;
|
|
||||||
transition: fill 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-toggle__moon {
|
|
||||||
right: calc(var(--tta-pad) + (var(--tta-knob) - var(--tta-icon)) / 2);
|
|
||||||
fill: dimgray;
|
|
||||||
transition: fill 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-toggle:checked + .theme-toggle__label {
|
|
||||||
background: #242424;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-toggle:checked + .theme-toggle__label::after {
|
|
||||||
transform: translateX(var(--tta-travel));
|
|
||||||
background: linear-gradient(180deg, #777, #3a3a3a);
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-toggle:checked + .theme-toggle__label .theme-toggle__sun {
|
|
||||||
fill: dimgray;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-toggle:checked + .theme-toggle__label .theme-toggle__moon {
|
|
||||||
fill: deepskyblue;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user