diff --git a/src/components/upload/EntityImageUploader.tsx b/src/components/upload/EntityImageUploader.tsx
index b5cf357f..99087060 100644
--- a/src/components/upload/EntityImageUploader.tsx
+++ b/src/components/upload/EntityImageUploader.tsx
@@ -5,6 +5,7 @@ import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Image as ImageIcon, ImagePlus, X } from 'lucide-react';
import { UppyPhotoUpload } from './UppyPhotoUpload';
+import { getCloudflareImageUrl } from '@/lib/cloudflareImageUtils';
export type ImageType = 'logo' | 'banner' | 'card';
@@ -140,7 +141,15 @@ export function EntityImageUploader({
{hasImage ? (

diff --git a/src/components/upload/UppyPhotoUpload.tsx b/src/components/upload/UppyPhotoUpload.tsx
index b92a0879..e57aead3 100644
--- a/src/components/upload/UppyPhotoUpload.tsx
+++ b/src/components/upload/UppyPhotoUpload.tsx
@@ -142,7 +142,8 @@ export function UppyPhotoUpload({
if (statusResponse.ok) {
const status: UploadSuccessResponse = await statusResponse.json();
if (status.uploaded && status.urls) {
- return status.urls.public;
+ const CLOUDFLARE_ACCOUNT_HASH = import.meta.env.VITE_CLOUDFLARE_ACCOUNT_HASH;
+ return `https://imagedelivery.net/${CLOUDFLARE_ACCOUNT_HASH}/${cloudflareId}/public`;
}
}
diff --git a/src/lib/cloudflareImageUtils.ts b/src/lib/cloudflareImageUtils.ts
new file mode 100644
index 00000000..2e7a12c0
--- /dev/null
+++ b/src/lib/cloudflareImageUtils.ts
@@ -0,0 +1,61 @@
+/**
+ * Cloudflare Images variant utilities
+ * Generates properly formatted URLs for Cloudflare Image variants
+ */
+
+export type CloudflareVariant =
+ | 'avatar'
+ | 'banner'
+ | 'bannermobile'
+ | 'card'
+ | 'cardthumb'
+ | 'logo'
+ | 'public';
+
+const CLOUDFLARE_ACCOUNT_HASH = import.meta.env.VITE_CLOUDFLARE_ACCOUNT_HASH;
+
+/**
+ * Build a Cloudflare image URL with specified variant
+ */
+export function getCloudflareImageUrl(
+ imageId: string | undefined,
+ variant: CloudflareVariant = 'public'
+): string | undefined {
+ if (!imageId) return undefined;
+ return `https://imagedelivery.net/${CLOUDFLARE_ACCOUNT_HASH}/${imageId}/${variant}`;
+}
+
+/**
+ * Generate responsive image srcset for card images
+ * Useful for
![]()
elements
+ */
+export function getCloudflareImageSrcSet(imageId: string | undefined): string | undefined {
+ if (!imageId) return undefined;
+
+ return [
+ `${getCloudflareImageUrl(imageId, 'cardthumb')} 600w`,
+ `${getCloudflareImageUrl(imageId, 'card')} 1200w`,
+ `${getCloudflareImageUrl(imageId, 'public')} 1366w`
+ ].join(', ');
+}
+
+/**
+ * Get responsive banner URLs for mobile and desktop
+ */
+export function getBannerUrls(imageId: string | undefined) {
+ if (!imageId) return { mobile: undefined, desktop: undefined };
+
+ return {
+ mobile: getCloudflareImageUrl(imageId, 'bannermobile'),
+ desktop: getCloudflareImageUrl(imageId, 'banner')
+ };
+}
+
+/**
+ * Extract Cloudflare image ID from various URL formats
+ */
+export function extractCloudflareImageId(url: string): string | null {
+ // Match imagedelivery.net URLs
+ const match = url.match(/imagedelivery\.net\/[^\/]+\/([a-f0-9-]+)\//i);
+ return match ? match[1] : null;
+}
diff --git a/src/lib/imageUploadHelper.ts b/src/lib/imageUploadHelper.ts
index fa97775d..23c2936d 100644
--- a/src/lib/imageUploadHelper.ts
+++ b/src/lib/imageUploadHelper.ts
@@ -60,9 +60,11 @@ export async function uploadPendingImages(images: UploadedImage[]): Promise
{(designer.banner_image_url || designer.banner_image_id) ? (
-

+
+
+
+
) : designer.logo_url ? (
{(manufacturer.banner_image_url || manufacturer.banner_image_id) ? (
-

+
+
+
+
) : manufacturer.logo_url ? (
{(operator.banner_image_url || operator.banner_image_id) ? (
-

+
+
+
+
) : operator.logo_url ? (
{(park.banner_image_url || park.banner_image_id) ? (
-

+
+
+
+
) : (
diff --git a/src/pages/PropertyOwnerDetail.tsx b/src/pages/PropertyOwnerDetail.tsx
index 727f6fdb..8234ffc5 100644
--- a/src/pages/PropertyOwnerDetail.tsx
+++ b/src/pages/PropertyOwnerDetail.tsx
@@ -1,6 +1,7 @@
import { useState, useEffect } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { Header } from '@/components/layout/Header';
+import { getBannerUrls } from '@/lib/cloudflareImageUtils';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { Card, CardContent } from '@/components/ui/card';
@@ -214,11 +215,18 @@ export default function PropertyOwnerDetail() {
{(owner.banner_image_url || owner.banner_image_id) ? (
-

+
+
+
+
) : owner.logo_url ? (
{(ride.banner_image_url || ride.banner_image_id) ? (
-

+
+
+
+
) : (