General Guide: See Global LCP Guide for universal concepts and fixes.
What is LCP?
Largest Contentful Paint measures when the largest content element becomes visible. Google recommends LCP under 2.5 seconds. Cosmic (formerly Cosmic JS) is a headless CMS, so LCP depends on your frontend framework's rendering strategy, Cosmic API response times, and how you handle media from Cosmic's Imgix-powered CDN.
Cosmic-Specific LCP Causes
- Client-side API fetching -- if your frontend fetches Cosmic objects in the browser, LCP waits for JS + API call + render
- Unoptimized Imgix URLs -- Cosmic serves media through Imgix CDN but most implementations use default URLs without transform parameters
- Large API payloads -- fetching full Object metadata and content when only title and thumbnail are needed
- Frontend hydration delay -- React/Next.js/Gatsby SPA hydration adds 500-2000ms before LCP content appears
- No caching layer -- API responses fetched fresh on every request without edge caching
Fixes
1. Use SSG/SSR with Cosmic SDK
Fetch content at build time or server-side to eliminate the client-side API waterfall:
// Next.js with Cosmic SDK -- getStaticProps for SSG
import { createBucketClient } from '@cosmicjs/sdk';
const cosmic = createBucketClient({
bucketSlug: process.env.COSMIC_BUCKET_SLUG,
readKey: process.env.COSMIC_READ_KEY,
});
export async function getStaticProps() {
const { object } = await cosmic.objects.findOne({
type: 'pages',
slug: 'home',
}).props('title,slug,metadata.hero_image,metadata.hero_title');
return {
props: { page: object },
revalidate: 60, // ISR: revalidate every 60 seconds
};
}
2. Use Imgix Transforms on Cosmic Media
Cosmic serves all media through Imgix CDN. Append transform parameters to optimize delivery:
// Cosmic Imgix URL optimization helper
function optimizeCosmicImage(imgixUrl, { width = 800, quality = 80, format = 'auto' } = {}) {
if (!imgixUrl) return '';
const separator = imgixUrl.includes('?') ? '&' : '?';
return `${imgixUrl}${separator}w=${width}&q=${quality}&auto=format,compress&fit=crop`;
}
// React component with responsive images
function HeroImage({ imageUrl, alt }) {
return (
<img
src={optimizeCosmicImage(imageUrl, { width: 1920 })}
srcSet={`
${optimizeCosmicImage(imageUrl, { width: 640 })} 640w,
${optimizeCosmicImage(imageUrl, { width: 1024 })} 1024w,
${optimizeCosmicImage(imageUrl, { width: 1920 })} 1920w
`}
sizes="100vw"
width="1920"
height="600"
alt={alt || ''}
loading="eager"
fetchPriority="high"
/>
);
}
Key Imgix parameters for Cosmic images:
w=800-- width constraintq=80-- quality (80 is good balance)auto=format,compress-- auto-selects WebP/AVIF and applies compressionfit=crop-- crops to exact dimensionsblur=200-- useful for low-quality image placeholder (LQIP) technique
3. Reduce API Payload with Props Selection
Use Cosmic SDK's .props() method to request only needed fields:
// BAD: Fetch full objects with all metadata
const { objects } = await cosmic.objects.find({ type: 'posts' });
// GOOD: Fetch only what you need
const { objects } = await cosmic.objects
.find({ type: 'posts' })
.props('title,slug,metadata.thumbnail,metadata.excerpt,created_at')
.limit(10);
4. Preload LCP Image
// Next.js -- preload hero image in document head
import Head from 'next/head';
function PageHead({ heroImage }) {
return (
<Head>
<link rel="preconnect" href="https://imgix.cosmicjs.com" />
{heroImage && (
<link
rel="preload"
as="image"
href={optimizeCosmicImage(heroImage, { width: 1920 })}
type="image/webp"
/>
)}
</Head>
);
}
5. Cache API Responses at the Edge
For SSR deployments, cache Cosmic API responses to reduce TTFB:
// Edge-cached API wrapper
const CACHE_TTL = 300; // 5 minutes
async function getCachedObject(type, slug) {
const cacheKey = `cosmic:${type}:${slug}`;
// Check edge cache (e.g., Vercel Edge Config, Cloudflare KV)
const cached = await edgeCache.get(cacheKey);
if (cached) return JSON.parse(cached);
const { object } = await cosmic.objects.findOne({ type, slug });
await edgeCache.set(cacheKey, JSON.stringify(object), { ttl: CACHE_TTL });
return object;
}
Measuring LCP on Cosmic
- Cosmic Dashboard -- check API usage under Settings > API to monitor response times
- Chrome DevTools Network tab -- filter for
api.cosmicjs.comrequests to see payload sizes and response times - Compare SSG vs CSR -- test the same page built statically vs. fetched client-side to quantify the difference
- Test key page types: landing pages (hero images), blog listings (many thumbnails), and individual posts (featured images)
Analytics Script Impact
Cosmic is headless, so analytics loading depends on your frontend:
- Next.js -- use
next/scriptwithstrategy="afterInteractive"for GTM/GA - Gatsby -- use
gatsby-plugin-google-gtagwhich handles async loading - Astro -- place analytics in
<script>tags withis:inlineordefer