diff --git a/app/[locale]/blog/[slug]/page.tsx b/app/[locale]/blog/[slug]/page.tsx
index a7be5101..b3a729cb 100644
--- a/app/[locale]/blog/[slug]/page.tsx
+++ b/app/[locale]/blog/[slug]/page.tsx
@@ -5,6 +5,7 @@ import { MDXRemote } from 'next-mdx-remote/rsc';
import { getPostBySlug, getAdjacentPosts, getReadingTime, getHeadings } from '@/lib/blog';
import { Metadata } from 'next';
import Link from 'next/link';
+import Image from 'next/image';
import PostNavigation from '@/components/blog/PostNavigation';
import PowerCTA from '@/components/blog/PowerCTA';
import TableOfContents from '@/components/blog/TableOfContents';
@@ -77,10 +78,16 @@ export default async function BlogPost({ params }: BlogPostProps) {
{/* Featured Image Header */}
{post.frontmatter.featuredImage ? (
-
+
+
+
{/* Title overlay on image */}
diff --git a/app/[locale]/blog/page.tsx b/app/[locale]/blog/page.tsx
index 75813546..ffaad997 100644
--- a/app/[locale]/blog/page.tsx
+++ b/app/[locale]/blog/page.tsx
@@ -62,7 +62,7 @@ export default async function BlogIndex({ params }: BlogIndexProps) {
{featuredPost && featuredPost.frontmatter.featuredImage && (
<>
{
const envExtension = {
// Project specific overrides or additions
AUTH_COOKIE_NAME: z.string().default('klz_gatekeeper_session'),
+ TARGET: z.string().optional(),
+ NEXT_PUBLIC_TARGET: z.string().optional(),
// Gatekeeper specifics not in base
GATEKEEPER_URL: z.string().url().default('http://gatekeeper:3000'),
diff --git a/lib/imgproxy-loader.ts b/lib/imgproxy-loader.ts
index cddefc52..041f58e4 100644
--- a/lib/imgproxy-loader.ts
+++ b/lib/imgproxy-loader.ts
@@ -23,11 +23,28 @@ export default function imgproxyLoader({
return src;
}
+ // Check if src contains custom gravity query parameter
+ let gravity = 'sm'; // Use smart gravity (content-aware) by default
+ let cleanSrc = src;
+
+ try {
+ // Dummy base needed for relative URLs
+ const url = new URL(src, 'http://localhost');
+ const customGravity = url.searchParams.get('gravity');
+ if (customGravity) {
+ gravity = customGravity;
+ url.searchParams.delete('gravity');
+ cleanSrc = src.startsWith('http') ? url.href : url.pathname + url.search;
+ }
+ } catch (e) {
+ // Fallback if parsing fails
+ }
+
// We use the width provided by Next.js for responsive images
// Height is set to 0 to maintain aspect ratio
- return getImgproxyUrl(src, {
+ return getImgproxyUrl(cleanSrc, {
width,
resizing_type: 'fit',
- gravity: 'sm', // Use smart gravity (content-aware) instead of face detection (requires ML)
+ gravity,
});
}