Setting a default Twitter Card Image in Ghost
When I started publishing posts on Ghost, I would start sharing them on my Twitter feed. Immediately I noticed that unless I specifically set an Image on the blog post or specifically set a Twitter Card Image, it would show up with a blank Twitter Card image.
And I'm not the only one...

What bothered me is that I want to publish posts with as little effort as possible. I want to be able to quickly write a post and have it automatically get shared to Twitter and not have to worry about setting specific settings/configs that would take time.
I went down a rabbit hole, because I assumed there was something in the Ghost Theme that I could tweak to make this happen. Unfortunately, it turns out that the logic returning the meta fields in a page are generated dynamically in the source code of Ghost itself.
When the home page is loaded, it will check to see if a Twitter Image is set, and if not default to the Cover Image.
if (_.includes(context, 'home')) {
const imgUrl = settingsCache.get('twitter_image') || settingsCache.get('cover_image');
return (imgUrl && urlUtils.relativeToAbsolute(imgUrl)) || null;
}
core/frontend/meta/twitter_image.js
Unfortunately, for me, the Post logic just checks for a Post specific Twitter Image or a Post specific Feature Image and returns those. However to get the behavior I wanted, I just hacked it to use the same logic as the Home Page if the Twitter or Featured Image are not set.
if (_.includes(context, 'post') || _.includes(context, 'page') || _.includes(context, 'amp')) {
if (contextObject.twitter_image) {
return urlUtils.relativeToAbsolute(contextObject.twitter_image);
} else if (contextObject.feature_image) {
return urlUtils.relativeToAbsolute(contextObject.feature_image);
}
// Fall back to the Twitter or Cover Image
const imgUrl = settingsCache.get('twitter_image') || settingsCache.get('cover_image');
return (imgUrl && urlUtils.relativeToAbsolute(imgUrl)) || null;
}
core/frontend/meta/twitter_image.js
Finally, you can do the same logic in the OG Meta tags for Facebook, LinkedIn, etc by editing the OG Image file with the same fallback.
/core/frontend/meta/og_image.js
I may end up submitting a PR to Ghost for this but my local hacked version seems to be working for now. Try sharing on Twitter to see the default image working or use the following tool that I found handy to preview what it would look like:

"Social Share Preview" in Chrome.