fix: critical perf & security — rate limiting, DB indexes, N+1 query, image lazy loading

- Add in-memory rate limiter (src/lib/rateLimit.ts) to public registration endpoints
- Add DB migration #9 with 8 performance indexes on booking/registration tables
- Fix N+1 query in getUpcomingReminders() — single IN() query instead of per-title
- Add loading="lazy" to all non-hero images (MasterClasses, News, Classes, Team)
- Add sizes attribute to Classes images for better responsive loading

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-19 13:55:49 +03:00
parent 4e766d6957
commit 127990e532
9 changed files with 127 additions and 5 deletions

View File

@@ -53,6 +53,8 @@ export function Classes({ data: classes }: ClassesProps) {
src={item.images[0]}
alt={item.name}
fill
loading="lazy"
sizes="(min-width: 1024px) 60vw, 100vw"
className="object-cover"
/>
{/* Gradient overlay */}

View File

@@ -98,6 +98,7 @@ function MasterClassCard({
src={item.image}
alt={item.title}
fill
loading="lazy"
sizes="(min-width: 1024px) 33vw, (min-width: 640px) 50vw, 100vw"
className="object-cover transition-transform duration-700 group-hover:scale-110"
/>

View File

@@ -42,6 +42,7 @@ function FeaturedArticle({
src={item.image}
alt={item.title}
fill
loading="lazy"
sizes="(min-width: 768px) 80vw, 100vw"
className="object-cover transition-transform duration-700 group-hover:scale-105"
/>
@@ -84,6 +85,7 @@ function CompactArticle({
src={item.image}
alt={item.title}
fill
loading="lazy"
sizes="112px"
className="object-cover transition-transform duration-500 group-hover:scale-105"
/>

View File

@@ -222,6 +222,7 @@ export function TeamCarousel({ members, activeIndex, onActiveChange }: TeamCarou
src={m.image}
alt={m.name}
fill
loading="lazy"
sizes="280px"
className="object-cover"
draggable={false}