diff --git a/src/lib/components/ui/ArticleCard.svelte b/src/lib/components/ui/ArticleCard.svelte index f889501..1e2c39b 100644 --- a/src/lib/components/ui/ArticleCard.svelte +++ b/src/lib/components/ui/ArticleCard.svelte @@ -2,6 +2,7 @@ import type { ArticleMetadata } from '$lib/types/article'; import { slide } from 'svelte/transition'; import Badge from './badge/badge.svelte'; + import { optimizeCloudinaryUrl } from '$lib/utils/optimise-cloudinary'; const { article }: { article: ArticleMetadata } = $props(); @@ -13,7 +14,14 @@ style={`background-color: ${article.isSponsored ? article.sponsorColor : 'transparent'}; color: ${article.isSponsored ? article.sponsorTextColor : 'inherit'};`} >
- {article.title} + {article.title}
diff --git a/src/lib/components/ui/ArticleSpotlight.svelte b/src/lib/components/ui/ArticleSpotlight.svelte index c3a9124..fa21e34 100644 --- a/src/lib/components/ui/ArticleSpotlight.svelte +++ b/src/lib/components/ui/ArticleSpotlight.svelte @@ -1,13 +1,25 @@
- {article.title} + {article.title}
diff --git a/src/lib/utils/optimise-cloudinary.ts b/src/lib/utils/optimise-cloudinary.ts new file mode 100644 index 0000000..6b93c33 --- /dev/null +++ b/src/lib/utils/optimise-cloudinary.ts @@ -0,0 +1,63 @@ +type ImageType = 'card' | 'spotlight' | 'hero'; + +interface TransformOptions { + width?: number; + height?: number; + type?: ImageType; + dpr?: number; +} + +const TRANSFORM_PRESETS: Record = { + card: 'w_464,h_464,c_fill,ar_1:1,g_center,q_auto,f_auto', + spotlight: 'w_640,h_475,c_fill,f_auto,q_auto', + hero: 'w_720,h_542,c_fill,g_auto,fl_progressive,q_auto:best,f_auto' +}; + +export function optimizeCloudinaryUrl(url: string, options: TransformOptions = {}): string { + if (!url || !url.includes('cloudinary.com')) return url; + + let baseUrl: string; + let path: string; + + const uploadIndex = url.lastIndexOf('/upload/'); + const coverImageIndex = url.lastIndexOf('/coverImage/'); + + if (uploadIndex !== -1) { + baseUrl = url.substring(0, uploadIndex + '/upload'.length); + path = url.substring(uploadIndex + '/upload/'.length); + } else if (coverImageIndex !== -1) { + baseUrl = url.substring(0, coverImageIndex); + path = url.substring(coverImageIndex + '/coverImage/'.length); + } else { + return url; + } + + if (!path) return url; + + const transformParams: string[] = []; + + if (options.type && options.type in TRANSFORM_PRESETS) { + transformParams.push(TRANSFORM_PRESETS[options.type]); + } else if (options.width && options.height) { + transformParams.push(`w_${options.width},h_${options.height},c_fill,g_center`); + } else { + transformParams.push(TRANSFORM_PRESETS.card); + } + + if (options.dpr) { + const sanitizedDpr = Math.max(1, Math.min(Math.abs(options.dpr), 3)); + transformParams.push(`dpr_${sanitizedDpr.toFixed(1)}`); + } + + const pathPrefix = url.includes('/upload/') ? '' : 'coverImage/'; + return `${baseUrl}/${transformParams.join(',')}/${pathPrefix}${path}`; +} + +export const optimizeSpotlightImage = (url: string) => + optimizeCloudinaryUrl(url, { type: 'spotlight' }); + +export const optimizeHeroImage = (url: string, dpr = 1) => + optimizeCloudinaryUrl(url, { + type: 'hero', + dpr + }); \ No newline at end of file diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index b3c9938..f480442 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -8,6 +8,10 @@ import BaseHead from '$lib/components/server/BaseHead.svelte'; import Button from '$lib/components/ui/button/button.svelte'; import { Mail } from 'lucide-svelte'; + import { optimizeCloudinaryUrl, optimizeHeroImage } from '$lib/utils/optimise-cloudinary'; + + const heroImage = + 'https://res.cloudinary.com/dc2iz5j1c/image/upload/v1734510500/hero_choeao.webp'; const { data }: { data: PageData } = $props(); const articles = $derived(data.articles); @@ -32,11 +36,37 @@ State of the art research on Ethereum and the broader crypto ecosystem - Hero illustration + + + + Hero illustration +
diff --git a/static/hero.png b/static/hero.png deleted file mode 100644 index 0f7032f..0000000 Binary files a/static/hero.png and /dev/null differ