Compare commits
6 Commits
v2.2.93
...
hotfix/2.2
| Author | SHA1 | Date | |
|---|---|---|---|
| 531e1a49f8 | |||
| 324cfb0ca3 | |||
| 69d2c42ef7 | |||
| 6fb46278e0 | |||
| 73886406a4 | |||
| b2701d6bcd |
@@ -47,14 +47,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
echo "=== System Disk Usage ==="
|
echo "=== System Disk Usage ==="
|
||||||
df -h || true
|
df -h || true
|
||||||
echo "=== Tool Cache Usage ==="
|
|
||||||
du -sh /opt/hostedtoolcache/* || true
|
|
||||||
du -sh /opt/hostedtoolcache/.[!.]* || true
|
|
||||||
echo "Purging old tool caches skipped to prevent runner corruption."
|
echo "Purging old tool caches skipped to prevent runner corruption."
|
||||||
echo "=== Host Disk Usage ==="
|
|
||||||
docker run --rm -v /:/host-root alpine df -h || true
|
|
||||||
echo "=== Host Inode Usage ==="
|
|
||||||
docker run --rm -v /:/host-root alpine df -i || true
|
|
||||||
echo "=== Running Host Containers ==="
|
echo "=== Running Host Containers ==="
|
||||||
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" || true
|
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}" || true
|
||||||
echo "=== Host Docker Info ==="
|
echo "=== Host Docker Info ==="
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import { DynamicMobileBottomNav as MobileBottomNav } from '@/components/layout/D
|
|||||||
|
|
||||||
import { DynamicCorporateBackground as CorporateBackground } from '@/components/decorations/DynamicCorporateBackground';
|
import { DynamicCorporateBackground as CorporateBackground } from '@/components/decorations/DynamicCorporateBackground';
|
||||||
import { DynamicPageTransitionShutter as PageTransitionShutter } from '@/components/providers/DynamicPageTransitionShutter';
|
import { DynamicPageTransitionShutter as PageTransitionShutter } from '@/components/providers/DynamicPageTransitionShutter';
|
||||||
|
import { DynamicFramerMotion as FramerMotionProvider } from '@/components/providers/DynamicFramerMotion';
|
||||||
|
|
||||||
const inter = Inter({
|
const inter = Inter({
|
||||||
subsets: ['latin'],
|
subsets: ['latin'],
|
||||||
@@ -190,26 +191,28 @@ export default async function Layout(props: {
|
|||||||
<body className="relative flex flex-col min-h-screen font-sans antialiased overflow-x-hidden selection:bg-primary/90 selection:text-white" suppressHydrationWarning>
|
<body className="relative flex flex-col min-h-screen font-sans antialiased overflow-x-hidden selection:bg-primary/90 selection:text-white" suppressHydrationWarning>
|
||||||
<NextIntlClientProvider messages={clientMessages} locale={safeLocale}>
|
<NextIntlClientProvider messages={clientMessages} locale={safeLocale}>
|
||||||
<TransitionProvider>
|
<TransitionProvider>
|
||||||
<CorporateBackground />
|
<FramerMotionProvider>
|
||||||
<InitialLoader shouldShowLoader={!hasSeenLoader} />
|
<CorporateBackground />
|
||||||
<PageTransitionShutter />
|
<InitialLoader shouldShowLoader={!hasSeenLoader} />
|
||||||
<SkipLink />
|
<PageTransitionShutter />
|
||||||
<Header navLinks={navLinks} />
|
<SkipLink />
|
||||||
<MobileBottomNav navLinks={navLinks} currentLocale={safeLocale} />
|
<Header navLinks={navLinks} />
|
||||||
|
<MobileBottomNav navLinks={navLinks} currentLocale={safeLocale} />
|
||||||
|
|
||||||
<main
|
<main
|
||||||
id="main-content"
|
id="main-content"
|
||||||
className="flex-grow overflow-visible"
|
className="flex-grow overflow-visible"
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<Footer companyInfo={companyInfo} />
|
<Footer companyInfo={companyInfo} />
|
||||||
<JsonLd />
|
<JsonLd />
|
||||||
<AnalyticsShell />
|
<AnalyticsShell />
|
||||||
|
|
||||||
<FeedbackClientWrapper />
|
<FeedbackClientWrapper />
|
||||||
|
</FramerMotionProvider>
|
||||||
</TransitionProvider>
|
</TransitionProvider>
|
||||||
</NextIntlClientProvider>
|
</NextIntlClientProvider>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -88,34 +88,30 @@
|
|||||||
}
|
}
|
||||||
/* trigger rebuild */
|
/* trigger rebuild */
|
||||||
|
|
||||||
@layer utilities {
|
@keyframes hero-fade-in-up {
|
||||||
@keyframes hero-fade-in-up {
|
from {
|
||||||
from {
|
opacity: 0;
|
||||||
opacity: 0;
|
transform: translateY(30px);
|
||||||
transform: translateY(30px);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
to {
|
||||||
.animate-hero-fade-in-up {
|
opacity: 1;
|
||||||
animation: hero-fade-in-up 0.8s cubic-bezier(0.16, 1, 0.3, 1) forwards;
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@layer utilities {
|
@utility animate-hero-fade-in-up {
|
||||||
@keyframes hero-zoom-out {
|
animation: hero-fade-in-up 0.8s cubic-bezier(0.16, 1, 0.3, 1) forwards;
|
||||||
from {
|
}
|
||||||
transform: scale(1.05);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.animate-hero-zoom-out {
|
@keyframes hero-zoom-out {
|
||||||
animation: hero-zoom-out 1.5s ease-out forwards;
|
from {
|
||||||
|
transform: scale(1.05);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: scale(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@utility animate-hero-zoom-out {
|
||||||
|
animation: hero-zoom-out 1.5s ease-out forwards;
|
||||||
|
}
|
||||||
|
|||||||
@@ -60,26 +60,26 @@ export const HeroSection: React.FC<HeroSectionProps> = (props) => {
|
|||||||
className={`max-w-4xl ${alignment === 'center' ? 'mx-auto' : ''}`}
|
className={`max-w-4xl ${alignment === 'center' ? 'mx-auto' : ''}`}
|
||||||
>
|
>
|
||||||
{badge && (
|
{badge && (
|
||||||
<div className="animate-hero-fade-in-up" style={{ animationDelay: '0.1s', opacity: 0, animationFillMode: 'forwards' }}>
|
<div className="animate-hero-fade-in-up" style={{ animationDelay: '0.1s', animationFillMode: 'both' }}>
|
||||||
<Badge variant="saturated" className="mb-4 md:mb-8 shadow-lg">
|
<Badge variant="saturated" className="mb-4 md:mb-8 shadow-lg">
|
||||||
{badge}
|
{badge}
|
||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="animate-hero-fade-in-up" style={{ animationDelay: badge ? '0.25s' : '0.1s', opacity: 0, animationFillMode: 'forwards' }}>
|
<div className="animate-hero-fade-in-up" style={{ animationDelay: badge ? '0.25s' : '0.1s', animationFillMode: 'both' }}>
|
||||||
<Heading level={1} size="section" variant="white" align={alignment || 'left'} className="mb-4 md:mb-8">
|
<Heading level={1} size="section" variant="white" align={alignment || 'left'} className="mb-4 md:mb-8">
|
||||||
{title}
|
{title}
|
||||||
</Heading>
|
</Heading>
|
||||||
</div>
|
</div>
|
||||||
{subtitle && (
|
{subtitle && (
|
||||||
<div className="animate-hero-fade-in-up" style={{ animationDelay: badge ? '0.4s' : '0.25s', opacity: 0, animationFillMode: 'forwards' }}>
|
<div className="animate-hero-fade-in-up" style={{ animationDelay: badge ? '0.4s' : '0.25s', animationFillMode: 'both' }}>
|
||||||
<p className={`text-lg md:text-2xl text-white/70 font-medium leading-relaxed max-w-2xl ${alignment === 'center' ? 'mx-auto' : ''}`}>
|
<p className={`text-lg md:text-2xl text-white/70 font-medium leading-relaxed max-w-2xl ${alignment === 'center' ? 'mx-auto' : ''}`}>
|
||||||
{subtitle}
|
{subtitle}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{ctaLabel && ctaHref && (
|
{ctaLabel && ctaHref && (
|
||||||
<div className={`mt-8 animate-hero-fade-in-up ${alignment === 'center' ? 'flex flex-wrap justify-center gap-4' : 'flex flex-wrap gap-4'}`} style={{ animationDelay: badge ? '0.55s' : '0.4s', opacity: 0, animationFillMode: 'forwards' }}>
|
<div className={`mt-8 animate-hero-fade-in-up ${alignment === 'center' ? 'flex flex-wrap justify-center gap-4' : 'flex flex-wrap gap-4'}`} style={{ animationDelay: badge ? '0.55s' : '0.4s', animationFillMode: 'both' }}>
|
||||||
<Button
|
<Button
|
||||||
href={ctaHref}
|
href={ctaHref}
|
||||||
variant="accent"
|
variant="accent"
|
||||||
|
|||||||
7
components/providers/DynamicFramerMotion.tsx
Normal file
7
components/providers/DynamicFramerMotion.tsx
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
'use client';
|
||||||
|
import dynamic from 'next/dynamic';
|
||||||
|
|
||||||
|
export const DynamicFramerMotion = dynamic(
|
||||||
|
() => import('./FramerMotionProvider').then((mod) => mod.FramerMotionProvider),
|
||||||
|
{ ssr: true }
|
||||||
|
);
|
||||||
11
components/providers/FramerMotionProvider.tsx
Normal file
11
components/providers/FramerMotionProvider.tsx
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
'use client';
|
||||||
|
import { LazyMotion } from 'framer-motion';
|
||||||
|
const loadFeatures = () => import('@/lib/framer-features').then(res => res.default);
|
||||||
|
|
||||||
|
export function FramerMotionProvider({ children }: { children: React.ReactNode }) {
|
||||||
|
return (
|
||||||
|
<LazyMotion features={loadFeatures} strict>
|
||||||
|
{children}
|
||||||
|
</LazyMotion>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -2,9 +2,6 @@
|
|||||||
|
|
||||||
import React, { createContext, useContext, useState, useCallback, ReactNode, useEffect } from 'react';
|
import React, { createContext, useContext, useState, useCallback, ReactNode, useEffect } from 'react';
|
||||||
import { useRouter, usePathname, useSearchParams } from 'next/navigation';
|
import { useRouter, usePathname, useSearchParams } from 'next/navigation';
|
||||||
import { LazyMotion } from 'framer-motion';
|
|
||||||
|
|
||||||
const loadFeatures = () => import('@/lib/framer-features').then(res => res.default);
|
|
||||||
|
|
||||||
interface TransitionContextType {
|
interface TransitionContextType {
|
||||||
isTransitioning: boolean;
|
isTransitioning: boolean;
|
||||||
@@ -71,9 +68,7 @@ export function TransitionProvider({ children }: { children: ReactNode }) {
|
|||||||
setTransitionMessage={setTransitionMessage}
|
setTransitionMessage={setTransitionMessage}
|
||||||
/>
|
/>
|
||||||
</React.Suspense>
|
</React.Suspense>
|
||||||
<LazyMotion features={loadFeatures}>
|
{children}
|
||||||
{children}
|
|
||||||
</LazyMotion>
|
|
||||||
</TransitionContext.Provider>
|
</TransitionContext.Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ import { join } from 'path';
|
|||||||
* Loads the Inter fonts for use in Satori (Next.js OG Image generation).
|
* Loads the Inter fonts for use in Satori (Next.js OG Image generation).
|
||||||
* Since we are using runtime = 'nodejs', we can read them from the filesystem.
|
* Since we are using runtime = 'nodejs', we can read them from the filesystem.
|
||||||
*/
|
*/
|
||||||
|
let cachedFonts: any[] | null = null;
|
||||||
export async function getOgFonts() {
|
export async function getOgFonts() {
|
||||||
|
if (cachedFonts) return cachedFonts;
|
||||||
const boldFontPath = join(process.cwd(), 'public/fonts/Inter-Bold.woff');
|
const boldFontPath = join(process.cwd(), 'public/fonts/Inter-Bold.woff');
|
||||||
const regularFontPath = join(process.cwd(), 'public/fonts/Inter-Regular.woff');
|
const regularFontPath = join(process.cwd(), 'public/fonts/Inter-Regular.woff');
|
||||||
|
|
||||||
@@ -28,7 +30,7 @@ export async function getOgFonts() {
|
|||||||
`[OG] Fonts loaded successfully (${boldFont.byteLength} and ${regularFont.byteLength} bytes)`,
|
`[OG] Fonts loaded successfully (${boldFont.byteLength} and ${regularFont.byteLength} bytes)`,
|
||||||
);
|
);
|
||||||
|
|
||||||
return [
|
cachedFonts = [
|
||||||
{
|
{
|
||||||
name: 'Inter',
|
name: 'Inter',
|
||||||
data: boldFont,
|
data: boldFont,
|
||||||
@@ -42,28 +44,35 @@ export async function getOgFonts() {
|
|||||||
style: 'normal' as const,
|
style: 'normal' as const,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
return cachedFonts;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`[OG] Failed to load fonts from ${process.cwd()}:`, error);
|
console.error(`[OG] Failed to load fonts from ${process.cwd()}:`, error);
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let cachedBackground: string | null = null;
|
||||||
export function getOgBackground() {
|
export function getOgBackground() {
|
||||||
|
if (cachedBackground) return cachedBackground;
|
||||||
try {
|
try {
|
||||||
const bgPath = join(process.cwd(), 'public/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie-100.jpg');
|
const bgPath = join(process.cwd(), 'public/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie-100.jpg');
|
||||||
const bgBase64 = readFileSync(bgPath, 'base64');
|
const bgBase64 = readFileSync(bgPath, 'base64');
|
||||||
return `data:image/jpeg;base64,${bgBase64}`;
|
cachedBackground = `data:image/jpeg;base64,${bgBase64}`;
|
||||||
|
return cachedBackground;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[OG] Failed to load background', err);
|
console.error('[OG] Failed to load background', err);
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let cachedLogo: string | null = null;
|
||||||
export function getOgLogo() {
|
export function getOgLogo() {
|
||||||
|
if (cachedLogo) return cachedLogo;
|
||||||
try {
|
try {
|
||||||
const logoPath = join(process.cwd(), 'public/assets/logo-white.png');
|
const logoPath = join(process.cwd(), 'public/assets/logo-white.png');
|
||||||
const logoBase64 = readFileSync(logoPath, 'base64');
|
const logoBase64 = readFileSync(logoPath, 'base64');
|
||||||
return `data:image/png;base64,${logoBase64}`;
|
cachedLogo = `data:image/png;base64,${logoBase64}`;
|
||||||
|
return cachedLogo;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[OG] Failed to load logo', err);
|
console.error('[OG] Failed to load logo', err);
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|||||||
@@ -139,7 +139,7 @@
|
|||||||
"prepare": "husky",
|
"prepare": "husky",
|
||||||
"preinstall": "npx only-allow pnpm"
|
"preinstall": "npx only-allow pnpm"
|
||||||
},
|
},
|
||||||
"version": "2.2.93",
|
"version": "2.4.24",
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
"onlyBuiltDependencies": [
|
"onlyBuiltDependencies": [
|
||||||
"@parcel/watcher",
|
"@parcel/watcher",
|
||||||
|
|||||||
Reference in New Issue
Block a user