Blog CMS Workflows 7 min read

Ghost Blog Featured Image Fallback Generated from Post Title

Generate a fallback image for Ghost blog posts when feature_image is null using the Ghost Content API and a title-based placeholder URL.

Ghost blog featured imageGhost CMSfeature_image fallbackPlaceholder image APIHeadless Ghost
Ghost Blog Featured Image Fallback Generated from Post Title

Ghost stores the featured image URL in a `feature_image` field on each post. The field is null for any post published without an image — which includes many newsletters, tutorials, and quick notes. Templates that render the field without a null check produce broken-image icons in post cards, headers, and Open Graph meta tags.

The Ghost Content API lets you handle this entirely at the data layer. When `feature_image` is null, substitute a fallback.pics URL built from the post title. The generated image appears immediately and looks like an intentional placeholder rather than a missing asset.

Ghost API

The feature_image field and when it is null

The Ghost Content API returns posts with a `feature_image` field that is either a string URL or `null`. There is no default image in Ghost's data model — the field is simply absent when no image has been set. Ghost's Handlebars helper `{{#if feature_image}}` handles this correctly in native themes, but headless frontends using the JSON API need their own null check.

Ghost also returns `feature_image_alt` and `feature_image_caption`. These are null whenever the image itself is null. Your fallback should either omit these fields or supply a safe default alt text derived from the post title.

Headless setup

Fetching posts with the Ghost Content API

The `@tryghost/content-api` npm package wraps the HTTP API. Each post object includes `feature_image` as a nullable string. Fetch posts with the fields you need and apply fallback logic after the fetch — not inside the component.

For static site builds (Astro, Next.js, Eleventy), compute fallback URLs during the build. For client-side Ghost-powered sites or ISR routes, compute them in the data-fetching layer before passing to components.

Implementation tsx
import GhostContentAPI from '@tryghost/content-api';

const api = new GhostContentAPI({
  url: process.env.GHOST_URL,
  key: process.env.GHOST_CONTENT_API_KEY,
  version: 'v5.0',
});

function ghostPostImage(post: GhostPost): string {
  if (post.feature_image) return post.feature_image;
  const title = encodeURIComponent(post.title);
  return `https://fallback.pics/api/v1/1200x630?text=${title}`;
}

export async function getPosts() {
  const posts = await api.posts.browse({ limit: 'all' });
  return posts.map((post) => ({
    ...post,
    feature_image: ghostPostImage(post),
  }));
}

Thumbnail style

Use the thumbnail route for blog-card style fallbacks

The basic dimension route gives you a solid-color placeholder. The thumbnail route generates a blog-card layout with a title, category label, gradient, and safe-zone decoration. For Ghost blogs where every post should look publication-quality even before photography is ready, the thumbnail route is a better default.

Map Ghost's primary tag to the thumbnail `label` parameter. This gives each post card a category pill that matches the blog's taxonomy, making fallback images look intentional rather than generic.

Implementation tsx
function ghostThumbnailUrl(post: GhostPost): string {
  if (post.feature_image) return post.feature_image;

  const params = new URLSearchParams({
    text: post.title,
    label: post.primary_tag?.name ?? 'Blog',
    style: 'soft',
    theme: 'purple',
  });
  return `https://fallback.pics/api/v1/thumbnail/1200x630?${params}`;
}

Handlebars themes

Fallback in native Ghost Handlebars themes

In a native Ghost Handlebars theme, the `{{feature_image}}` helper outputs nothing when the field is null. You cannot pass it a default value directly. Instead, use a custom helper or a conditional block to output the fallback URL.

Register a custom `featureImageOrFallback` helper in your theme's `helpers.js` file. This is cleaner than duplicating the conditional in every template partial.

Implementation text
{{! In your theme template (e.g. index.hbs, post.hbs) }}
{{#if feature_image}}
  <img src="{{feature_image}}" alt="{{feature_image_alt}}" width="1200" height="630" />
{{else}}
  <img
    src="https://fallback.pics/api/v1/thumbnail/1200x630?text={{encode title}}&label={{primary_tag.name}}&style=soft&theme=purple"
    alt="{{title}}"
    width="1200"
    height="630"
  />
{{/if}}

RSS feed

Feature images in the Ghost RSS feed

Ghost's RSS feed includes `<media:content>` tags for featured images. When `feature_image` is null, the RSS item has no image, which means podcast apps, RSS readers, and feed aggregators show a blank entry. If your Ghost blog is also used as an RSS feed source, the fallback URL should be included in the feed output.

For headless Ghost setups, you control the RSS generation. Include the fallback URL in the feed item's image field. For native Ghost themes, a custom template in `ghost.hbs` or a route configuration is needed to inject fallback URLs into the feed.

Open Graph

Populate og:image for social sharing

Ghost populates `og:image` from `feature_image` automatically in native themes. In headless setups, you are responsible for the meta tags. Apply the same fallback URL to `og:image`, `twitter:image`, and `og:image:secure_url` so shares on LinkedIn, X, and Slack all get a preview image.

Implementation text
<head>
  {/* Next.js / Astro headless Ghost example */}
  <meta property="og:image" content={ghostThumbnailUrl(post)} />
  <meta property="og:image:width" content="1200" />
  <meta property="og:image:height" content="630" />
  <meta name="twitter:card" content="summary_large_image" />
  <meta name="twitter:image" content={ghostThumbnailUrl(post)} />
</head>

Resources

Further reading

The fallback.pics thumbnail route documentation covers all style, theme, and label parameters. For full open graph image strategies, the OG image placeholders guide is a useful reference.

Implementation text
https://fallback.pics/docs/
https://fallback.pics/placeholder-image-api/
https://fallback.pics/blog/generate-blog-thumbnails-from-text/
https://fallback.pics/blog/hubspot-cms-image-fallback/

Key takeaways

What to standardize before shipping

  • Ghost's feature_image field is null when no image is set — check before using as img src or og:image.
  • Compute fallback URLs in the data-fetching layer, not inside components, so every template gets a valid string.
  • Use the thumbnail route with the post title and primary tag label for publication-quality fallback cards.
  • Apply the same fallback URL to Open Graph and Twitter Card meta tags to ensure social previews always render.
  • In native Handlebars themes, use a {{#if feature_image}} block since the helper has no default value parameter.

Production fallback layer

Use fallback.pics anywhere an image URL is accepted.

Start with one deterministic URL and standardize fallback behavior across your design system.

Read the docs