Compare commits
2 Commits
c2eeeafd56
...
ac1e22017e
| Author | SHA1 | Date | |
|---|---|---|---|
| ac1e22017e | |||
| a503d3e539 |
@@ -15,7 +15,7 @@ export default function GallerySection() {
|
||||
];
|
||||
|
||||
return (
|
||||
<Section className="bg-white text-neutral-dark py-32">
|
||||
<Section className="bg-white text-white py-32">
|
||||
<Container>
|
||||
<Heading level={2} subtitle={t('subtitle')} align="center">
|
||||
{t('title')}
|
||||
|
||||
@@ -19,10 +19,10 @@ export default async function RecentPosts({ locale }: RecentPostsProps) {
|
||||
<Section className="bg-neutral py-16 md:py-24">
|
||||
<Container>
|
||||
<div className="flex flex-col md:flex-row items-start md:items-end justify-between mb-12 md:mb-16 gap-6">
|
||||
<Heading level={2} subtitle={t('latestNews')} className="mb-0">
|
||||
<Heading level={2} subtitle={t('latestNews')} className="mb-0 text-white">
|
||||
{t('allArticles')}
|
||||
</Heading>
|
||||
<Link href={`/${locale}/blog`} className="group flex items-center text-primary font-bold text-base md:text-lg touch-target">
|
||||
<Link href={`/${locale}/blog`} className="group flex items-center text-white font-bold text-base md:text-lg touch-target">
|
||||
{t('allArticles')}
|
||||
<span className="ml-2 transition-transform group-hover:translate-x-2">→</span>
|
||||
</Link>
|
||||
@@ -56,10 +56,10 @@ export default async function RecentPosts({ locale }: RecentPostsProps) {
|
||||
day: 'numeric'
|
||||
})}
|
||||
</div>
|
||||
<h3 className="text-lg md:text-xl font-bold text-primary group-hover:text-accent-dark transition-colors line-clamp-2 mb-4 md:mb-6 leading-tight">
|
||||
<h3 className="text-lg md:text-xl font-bold text-white group-hover:text-accent-dark transition-colors line-clamp-2 mb-4 md:mb-6 leading-tight">
|
||||
{post.frontmatter.title}
|
||||
</h3>
|
||||
<div className="mt-auto flex items-center text-primary font-bold group-hover:underline decoration-2 underline-offset-4">
|
||||
<div className="mt-auto flex items-center text-white font-bold group-hover:underline decoration-2 underline-offset-4">
|
||||
{t('readMore')}
|
||||
<svg className="ml-2 w-5 h-5 transition-transform group-hover:translate-x-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 8l4 4m0 0l-4 4m4-4H3" />
|
||||
|
||||
@@ -6,7 +6,7 @@ export default function WhatWeDo() {
|
||||
const t = useTranslations('Home.whatWeDo');
|
||||
|
||||
return (
|
||||
<Section className="bg-white text-neutral-dark">
|
||||
<Section className="bg-white text-white">
|
||||
<Container>
|
||||
<div className="sticky-narrative-container">
|
||||
<div className="sticky-narrative-sidebar">
|
||||
@@ -33,7 +33,7 @@ export default function WhatWeDo() {
|
||||
</span>
|
||||
<div className="h-px flex-grow bg-neutral-medium" />
|
||||
</div>
|
||||
<h3 className="text-lg md:text-xl font-bold mb-3 md:mb-4 text-saturated group-hover:text-accent-dark transition-colors">{t(`items.${idx}.title`)}</h3>
|
||||
<h3 className="text-lg md:text-xl font-bold mb-3 md:mb-4 text-white group-hover:text-accent-dark transition-colors">{t(`items.${idx}.title`)}</h3>
|
||||
<p className="text-text-secondary text-base md:text-base leading-relaxed">{t(`items.${idx}.description`)}</p>
|
||||
</div>
|
||||
))}
|
||||
|
||||
@@ -6,7 +6,7 @@ export default function WhyChooseUs() {
|
||||
const t = useTranslations('Home.whyChooseUs');
|
||||
|
||||
return (
|
||||
<Section className="bg-neutral-light text-neutral-dark">
|
||||
<Section className="bg-neutral-light text-white">
|
||||
<Container>
|
||||
<div className="grid grid-cols-1 lg:grid-cols-12 gap-16 lg:gap-24">
|
||||
<div className="lg:col-span-4 order-1 lg:order-2">
|
||||
@@ -26,7 +26,7 @@ export default function WhyChooseUs() {
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={3} d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
</div>
|
||||
<span className="font-bold text-saturated text-base md:text-base">{t(`features.${i}`)}</span>
|
||||
<span className="font-bold text-white text-base md:text-base">{t(`features.${i}`)}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
@@ -36,9 +36,9 @@ export default function WhyChooseUs() {
|
||||
{[0, 1, 2, 3].map((idx) => (
|
||||
<div key={idx} className="p-10 bg-white rounded-3xl border border-neutral-medium hover:border-accent transition-all duration-500 hover:shadow-xl group">
|
||||
<div className="w-14 h-14 bg-saturated/10 rounded-2xl flex items-center justify-center mb-8 group-hover:bg-accent transition-colors duration-500">
|
||||
<span className="text-saturated font-bold text-lg group-hover:text-primary-dark">0{idx + 1}</span>
|
||||
<span className="text-white font-bold text-lg group-hover:text-primary-dark">0{idx + 1}</span>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold mb-4 text-saturated">{t(`items.${idx}.title`)}</h3>
|
||||
<h3 className="text-xl font-bold mb-4 text-white">{t(`items.${idx}.title`)}</h3>
|
||||
<p className="text-text-secondary text-base md:text-base leading-relaxed">{t(`items.${idx}.description`)}</p>
|
||||
</div>
|
||||
))}
|
||||
|
||||
@@ -1,13 +1,78 @@
|
||||
import createMiddleware from 'next-intl/middleware';
|
||||
|
||||
export default createMiddleware({
|
||||
import { NextResponse } from 'next/server';
|
||||
import type { NextRequest } from 'next/server';
|
||||
import { getServerAppServices } from '@/lib/services/create-services.server';
|
||||
|
||||
// Create the internationalization middleware
|
||||
const intlMiddleware = createMiddleware({
|
||||
// A list of all locales that are supported
|
||||
locales: ['en', 'de'],
|
||||
|
||||
|
||||
// Used when no locale matches
|
||||
defaultLocale: 'en'
|
||||
});
|
||||
|
||||
|
||||
// Main middleware that logs all requests
|
||||
export default function middleware(request: NextRequest) {
|
||||
const startTime = Date.now();
|
||||
const { method, url, headers } = request;
|
||||
const userAgent = headers.get('user-agent') || 'unknown';
|
||||
const referer = headers.get('referer') || 'none';
|
||||
const ip = headers.get('x-forwarded-for') || headers.get('x-real-ip') || 'unknown';
|
||||
|
||||
// Get logger service
|
||||
const services = getServerAppServices();
|
||||
const logger = services.logger.child({ middleware: 'request-logger' });
|
||||
|
||||
// Log incoming request
|
||||
logger.info('Incoming request', {
|
||||
method,
|
||||
url,
|
||||
userAgent,
|
||||
referer,
|
||||
ip,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
|
||||
try {
|
||||
// Apply internationalization middleware
|
||||
const response = intlMiddleware(request);
|
||||
const duration = Date.now() - startTime;
|
||||
|
||||
// Log successful response
|
||||
logger.info('Request completed', {
|
||||
method,
|
||||
url,
|
||||
status: response.status,
|
||||
duration,
|
||||
userAgent,
|
||||
referer,
|
||||
ip,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
const duration = Date.now() - startTime;
|
||||
|
||||
// Log error
|
||||
logger.error('Request failed', {
|
||||
method,
|
||||
url,
|
||||
duration,
|
||||
userAgent,
|
||||
referer,
|
||||
ip,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
stack: error instanceof Error ? error.stack : undefined,
|
||||
timestamp: new Date().toISOString(),
|
||||
});
|
||||
|
||||
// Re-throw the error to let Next.js handle it
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export const config = {
|
||||
// Match only internationalized pathnames
|
||||
matcher: ['/((?!api|_next|_vercel|.*\\..*).*)', '/', '/(de|en)/:path*']
|
||||
|
||||
Reference in New Issue
Block a user