How to make Ghost CMS host with Vercel


Setting Up Ghost CMS with Vercel: The Headless Approach
Ghost CMS is a powerful content management system built on Node.js that offers an excellent writing experience and robust features for publishers. Many developers want to combine Ghost's content management capabilities with Vercel's deployment platform. However, there's an important architectural consideration to understand first.
Understanding the Compatibility Challenge
Vercel is designed primarily for frontend applications, static websites, and serverless functions. It does not support running Docker instances or traditional backend servers. Ghost CMS, on the other hand, requires a full Node.js backend server environment with database connections.
Because of this fundamental difference, you cannot directly host Ghost CMS on Vercel. Instead, the recommended approach is to use Ghost as a "headless CMS" and deploy only your frontend on Vercel.
The Headless CMS Solution
The headless approach separates your content management (Ghost) from your frontend presentation layer (Next.js on Vercel). Here's how to implement this architecture:
Host Ghost CMS separately on a platform that supports backend servers
Create a Next.js frontend to consume Ghost's Content API
Deploy the frontend to Vercel
Let's break down each step in detail.
Step 1: Set Up Ghost CMS on a Compatible Platform
You have several options for hosting Ghost:
Option A: DigitalOcean
# Example setup on a DigitalOcean Droplet
sudo apt-get update
sudo apt-get upgrade -y
sudo apt-get install nginx mysql-server -y
sudo npm install ghost-cli@latest -g
ghost install
After installation, your Ghost CMS will be available at your droplet's IP address.
Option B: Render
Render offers a straightforward deployment process for Ghost:
Fork the render-examples/ghost repo on GitHub
Create a new Web Service on Render pointing to your forked repo
Set the Environment to Docker
Option C: Ghost(Pro)
Ghost's official managed hosting is another option, though it comes with some limitations for headless implementations:
Portal is not available for subscription management
"View in Browser" links will lead to ghost.io
You won't benefit from Ghost(Pro)'s CDN
Step 2: Create a Next.js Frontend Application
Once your Ghost CMS is running, create a Next.js application to display your content:
# Create a new Next.js app
npx create-next-app ghost-next-vercel
cd ghost-next-vercel
# Install the Ghost Content API package
npm install @tryghost/content-api
Set up the Ghost API client in your project:
// lib/ghost.js
import GhostContentAPI from '@tryghost/content-api';
const api = new GhostContentAPI({
url: process.env.NEXT_PUBLIC_GHOST_API_URL,
key: process.env.NEXT_PUBLIC_GHOST_CONTENT_API_KEY,
version: "v5.0"
});
export async function getPosts() {
return await api.posts
.browse({ limit: "all", include: 'tags,authors' })
.catch(err => {
console.error(err);
throw new Error('Failed to fetch posts');
});
}
Create a page to display posts:
// pages/posts.js
import { getPosts } from '../lib/ghost';
export async function getStaticProps() {
const posts = await getPosts();
return {
props: { posts },
revalidate: 60 // Incremental Static Regeneration
};
}
function Posts({ posts }) {
return (
<div>
{posts.map(post => (
<div key={post.id}>
<h2>{post.title}</h2>
<div dangerouslySetInnerHTML={{ __html: post.html }} />
</div>
))}
</div>
);
}
export default Posts;
Step 3: Configure Environment Variables
Create a .env.local
file in your Next.js project root:
NEXT_PUBLIC_GHOST_API_URL=https://your-ghost-site.com
NEXT_PUBLIC_GHOST_CONTENT_API_KEY=your_content_api_key
To get these values:
Log into your Ghost admin panel at
https://your-ghost-site.com/ghost
Go to Settings → Integrations → Add custom integration
Copy the Content API Key and API URL
Step 4: Deploy the Frontend to Vercel
Push your Next.js project to GitHub
Connect to Vercel and import your repository
Add the environment variables in the Vercel dashboard
Deploy your site
Vercel will automatically detect your Next.js project and set up the appropriate build configuration.
Existing Solutions and Templates
To fast-track your development, consider these pre-built solutions:
next-cms-ghost: A production-ready solution that combines Next.js and Ghost, supporting features like dark mode, responsive design, and SEO optimization.
Vercel's Ghost CMS Example: Vercel maintains an official example showing Ghost CMS integration with Next.js.
npx create-next-app --example cms-ghost cms-ghost-app
Configuring Ghost for Headless Use
When using Ghost as a headless CMS, you should configure it appropriately:
Enable private mode in Ghost settings to prevent content duplication
This adds password protection and sets
<meta name="robots" content="noindex" />
so search engines only index your frontend
Important Considerations
When implementing a headless Ghost setup, keep in mind:
You'll need to rebuild many features that come with Ghost's default frontend, including:
Tag and author archives
Sitemaps for SEO
Open Graph structured data
Google AMP support
Custom routing and pagination
Make sure to set up proper DNS records if you're using subdomains:
Create an A record in your DNS settings pointing to your Ghost server
For example, add a record for
cms.yourdomain.com
pointing to your Ghost server IP
Need professional assistance?
If you're looking to implement a headless Ghost CMS solution with a Next.js frontend on Vercel but don't have the technical expertise, consider reaching out to Tenten. Our team specializes in modern web development stacks including headless CMS implementations. We can help you set up an optimized architecture that leverages the best of both Ghost and Vercel to create a lightning-fast website with excellent content management.
Book a free meeting at https://tenten.co/contact to discuss how we can transform your content publishing workflow with a custom Ghost and Vercel integration.
I have a Ghost CMS theme, what are the best way to use AI coding tool like Cursor to turn it into Next.js support theme and make it integrate with Ghost CMS Headless on Vercel
Transforming Handlebars Ghost Themes into Next.js with AI-Powered Conversion
Converting traditional Ghost CMS themes to modern Next.js implementations requires bridging the gap between server-rendered Handlebars templates and React's component-based architecture. This process becomes significantly more efficient when leveraging AI tools like Cursor, which can accelerate code translation and system integration. Here's how to approach this transformation while maintaining Ghost's content management strengths and Vercel's deployment advantages.
Architectural Shift: From Monolithic to Headless
Traditional Ghost themes operate as tightly coupled systems where templates directly render server-side content. In contrast, a headless approach separates content management from presentation:
// Traditional Ghost data binding
{{#post}}
<h1>{{title}}</h1>
<div>{{content}}</div>
{{/post}}
// Next.js implementation
export async function getStaticProps() {
const post = await api.posts.read({ slug: params.slug });
return { props: { post } };
}
function PostPage({ post }) {
return (
<article>
<h1>{post.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.html }} />
</article>
);
}
Cursor's AI capabilities excel at recognizing these structural patterns, offering automatic conversion suggestions through its ⌘ + K
shortcut. The AI can map Handlebars helpers to React hooks and suggest appropriate data fetching strategies.
Automated Template Conversion Workflow
File Structure Translation
default.hbs
→_app.js
(Next.js root layout)post.hbs
→pages/posts/[slug].js
(Dynamic route)Partials become React components in
/components
Helper Function Conversion Handlebars helpers transform into reusable React hooks:
// Original Handlebars helper
{{#has tag="featured"}}
<div class="featured-badge"></div>
{{/has}}
// AI-generated React component
function FeaturedBadge({ tags }) {
return tags.includes('featured') ? <div className="featured-badge" /> : null;
}
- Data Fetching Layer Cursor can automatically generate TypeScript interfaces for Ghost API responses:
interface GhostPost {
id: string;
title: string;
slug: string;
html: string;
featured: boolean;
tags: GhostTag[];
}
AI-Assisted Development Patterns
Cursor's deep context awareness enables sophisticated refactoring:
Cross-File References When modifying a post template, Cursor automatically updates related components like featured post cards and archive listings.
API Integration The AI suggests optimal data fetching strategies based on Next.js features:
// Static Generation with ISR
export async function getStaticPaths() {
const posts = await api.posts.browse({ limit: 'all' });
const paths = posts.map(post => ({ params: { slug: post.slug } }));
return { paths, fallback: 'blocking' };
}
- Performance Optimization Cursor proposes modern Next.js patterns:
// Dynamic OG Image Generation
export const generateMetadata = async ({ params }) => {
const post = await api.posts.read({ slug: params.slug });
return {
openGraph: {
images: [{
url: `/api/og?title=${encodeURIComponent(post.title)}`,
width: 1200,
height: 630
}]
}
};
};
Vercel-Specific Configuration
When deploying to Vercel, consider these AI-generated optimizations:
- Incremental Static Regeneration
// pages/posts/[slug].js
export const getStaticProps = async ({ params }) => {
const post = await api.posts.read({ slug: params.slug });
return {
props: { post },
revalidate: 3600 // Refresh every hour
};
};
- Edge Network Caching
// next.config.js
module.exports = {
experimental: {
isrMemoryCacheSize: 0,
workerThreads: false,
cpus: 1
},
headers: async () => [
{
source: '/:path*',
headers: [
{ key: 'x-vercel-cache', value: 'HIT' }
]
}
]
};
Maintaining Ghost CMS Features
Preserve key Ghost functionality through Next.js implementations:
Ghost Feature | Next.js Equivalent |
Tag Archives | Dynamic routes /tags/[slug].js |
Author Pages | pages/authors/[slug].js |
Content Filtering | GraphQL API queries |
Member Subscriptions | NextAuth.js integration |
Search | Algolia InstantSearch |
Cursor helps maintain feature parity by analyzing Ghost's documentation and suggesting appropriate modern alternatives.
Migration Checklist with AI Assistance
Content Audit
Use Cursor to generate content type diagrams
Automatically map relationships between posts, tags, and authors
Style Conversion
AI-assisted CSS-in-JS conversion
Automated responsive design adjustments
SEO Preservation
Automatic meta tag migration
Structured data generation
Performance Baseline
Lighthouse score comparison
Bundle size optimization
Continuous Integration Strategy
Implement AI-powered quality checks:
# .github/workflows/ci.yml
name: AI Code Review
on: [pull_request]
jobs:
ai-review:
runs-on: ubuntu-latest
steps:
- uses: cursor-ai/code-reviewer@v2
with:
strictness: high
check-for:
- ghost-compatibility
- vercel-optimization
- accessibility
This workflow leverages Cursor's API to ensure ongoing compatibility with both Ghost CMS and Vercel deployment requirements.
Final Implementation Considerations
When executing this migration, balance automation with manual oversight:
Preserve Content Integrity
Maintain post IDs and slugs
Implement 301 redirects for changed URLs
Progressive Enhancement
Phase migration by content sections
A/B test critical user journeys
Monitoring
Implement RUM (Real User Monitoring)
Track CMS API response times
For teams needing expert guidance, Tenten offers specialized Ghost-to-Next.js migration services. Our AI-augmented development process ensures seamless transitions with performance guarantees. Book a free consultation at tenten.co/contact to discuss your headless CMS strategy.
What are the best practices for using Cursor AI to convert a Ghost CMS theme to Next.js
Optimizing Ghost-to-Next.js Theme Conversion with Cursor AI: Expert Strategies
Converting Ghost CMS themes to Next.js requires merging template engine translation with modern React patterns. Cursor AI accelerates this process through intelligent code transformation and context-aware refactoring. Here's how to maximize efficiency while maintaining compatibility with Ghost's Content API and Vercel's deployment requirements.
Architectural Blueprint for Conversion
Traditional Ghost themes use Handlebars templating with server-side rendering, while Next.js employs React components with hybrid rendering capabilities. The conversion process involves:
// Ghost template structure
{{! post.hbs }}
<article class="post">
<h1>{{title}}</h1>
<div class="content">{{content}}</div>
</article>
// Next.js equivalent
export default function Post({ post }) {
return (
<article className="post">
<h1>{post.title}</h1>
<div dangerouslySetInnerHTML={{ __html: post.html }} />
</article>
);
}
Cursor's AI excels at recognizing these structural patterns through its deep code analysis capabilities. Enable YOLO mode (⌘ + K
) to allow automated test execution and build error correction during conversion.
Context Management Best Practices
Project-Specific Rules File Create
.cursorrules
in your project root:# .cursorrules - Prefer TypeScript over JavaScript - Use Next.js 14 App Router conventions - Follow Ghost Content API v5 specifications - Enforce strict ESLint rules - Maintain Handlebars-to-JSX conversion patterns
This guides Cursor's suggestions while preserving project consistency.
Dynamic Context Loading Use Cursor's
/ Reference Open Editors
command to maintain focus on active conversion files. Keep only these tabs open:Current Handlebars template
Corresponding React component
Ghost API utility file
Next.js route configuration
Automated Template Conversion Workflow
Component Generation Convert Ghost partials (
partials/
) to React components using Cursor's bulk processing:# Convert navigation partial cursor convert partials/navigation.hbs components/Navigation.tsx --pattern handlebars-to-react
Cursor automatically:
Replaces Handlebars syntax with JSX
Converts helpers to React hooks
Maps Ghost context to TypeScript interfaces
Route System Migration Transform Ghost's routing logic to Next.js dynamic routes:
// pages/posts/[slug].js export async function getStaticPaths() { const posts = await api.posts.browse({ limit: 'all' }); return { paths: posts.map(post => ({ params: { slug: post.slug } })), fallback: 'blocking' }; }
Use Cursor's AI chat to handle complex cases like:
Tag-based routing
Author archive pages
Pagination systems
Performance Optimization Techniques
Incremental Static Regeneration Configure ISR with Ghost's webhooks:
// next.config.js module.exports = { experimental: { isrMemoryCacheSize: 50, isrFlushToDisk: true } };
Set up content update detection:
// pages/api/revalidate.js export default async function handler(req, res) { if (req.headers['x-ghost-event'] === 'post.published') { await res.revalidate(`/posts/${req.body.post.current.slug}`); } return res.status(200).end(); }
Cursor's AI-assisted debugging helps resolve cache invalidation issues.
Bundle Analysis Use Cursor's integrated tools to:
Generate dependency graphs (
cursor analyze-deps
)Visualize component trees
Identify unused Handlebars helpers
Suggest code splitting opportunities
Content API Integration Patterns
Type-Safe Query Building Generate TypeScript types from Ghost API responses:
// types/ghost.d.ts declare module '@tryghost/content-api' { interface Post { id: string; title: string; html: string; excerpt: string; primary_author: Author; tags: Tag[]; } }
Cursor's AI type inference maintains type safety during conversion.
Batch Request Optimization Implement parallel fetching with error handling:
export async function getStaticProps() { try { const [posts, settings] = await Promise.all([ api.posts.browse({ limit: 10 }), api.settings.fetch() ]); return { props: { posts, settings } }; } catch (error) { return { notFound: true }; } }
Use Cursor's code completion to handle API edge cases.
Visual Regression Prevention
Snapshot Testing Configure Jest with Cursor-generated tests:
// __tests__/PostComponent.js test('matches Handlebars output snapshot', async () => { const post = await getSamplePost(); const { container } = render(<Post post={post} />); expect(container).toMatchSnapshot(); });
CSS Conversion Transform Ghost's CSS to CSS-in-JS with Cursor's style migrator:
cursor convert assets/css/screen.css styles/global.js --pattern css-to-js
Maintains responsive breakpoints and theme variables.
Continuous Integration Setup
Implement AI-powered quality gates:
# .github/workflows/ci.yml
name: AI-Assisted Conversion Check
on: [pull_request]
jobs:
conversion-qa:
runs-on: ubuntu-latest
steps:
- uses: cursor-ai/theme-converter@v3
with:
source-dir: 'ghost-theme'
target-dir: 'src'
rules-file: '.cursorrules'
This workflow automatically:
Compares template coverage
Verifies API integration
Checks visual consistency
Post-Conversion Maintenance
Automated Documentation Use Cursor's AI documentation generator:
cursor docs generate --format typedoc --output docs/
Performance Monitoring Set up real-user metrics with Cursor's analytics integration:
// pages/_app.js export function reportWebVitals(metric) { cursor.analytics.track('Web Vitals', metric); }
For teams needing expert guidance in complex migrations, Tenten offers specialized Ghost-to-Next.js conversion services. Our AI-augmented workflow ensures pixel-perfect theme conversions with optimized Vercel deployments. Schedule a free consultation at tenten.co/contact to modernize your content platform.
How do I set up YOLO mode in Cursor AI for theme conversions
Answer (Auto):
Optimizing Cursor's YOLO Mode for Ghost-to-Next.js Conversions
YOLO mode in Cursor AI revolutionizes theme migration by automating repetitive tasks while maintaining developer oversight. Here's how to configure it effectively:
Enabling & Configuring YOLO Mode
Activation:
Open Settings (
⌘/Ctrl + Shift + J
)Navigate to Features → Composer
Enable Allow Composer to run commands automatically
Security Configuration:
# .cursor/config.yml
security:
permissions:
files:
read: ['ghost-theme/**/*', 'next-app/src/**/*']
write: ['next-app/src/**/*']
commands:
allowed: ['npm', 'git', 'next', 'ghost-api']
restricted: ['rm', 'sudo']
Workflow Automation Strategy
Template Conversion Pipeline:
Automatic Handlebars → JSX translation
Batch partials conversion with:
cursor convert ghost-theme/partials/*.hbs -o next-app/components/ --pattern handlebars-to-react
Auto-generated TypeScript interfaces for Ghost API responses
Smart Command Allowlist:
// Allowed operations for theme conversion
const ALLOWED_COMMANDS = [
'npm install @tryghost/content-api',
'next build',
'git add components/',
'ghost-api validate'
];
Iterative Development Setup
Context-Aware Processing:
Maintain active editors for:
Current Handlebars template
Corresponding React component
API utility file
Next.js route config
Build & Test Automation:
# Automated conversion workflow
cursor --yolo --prompt "Convert post.hbs to Next.js dynamic route with ISR" \
--input ghost-theme/post.hbs \
--output next-app/pages/posts/[slug].tsx \
--test "npm run build && npm test"
Safety & Monitoring
Real-Time Oversight:
Use integrated terminal watcher:
cursor monitor --log-level verbose --filter "command|error"
Configure automatic snapshots before major operations
Rollback Protocol:
Automatic git commits every 5 successful changes
Quick-revert hotkey (
⌘/Ctrl + ]
)
Advanced Configuration Tips
- Bypass Tool Call Limits:
// .cursor/override.json
{
"experimental": {
"toolCallLimit": 100,
"autoContinueOnLimit": true
}
}
Performance Optimization:
Enable filesystem cache:
cursor config set cache.enabled true cursor config set cache.ttl 3600
For teams needing enterprise-grade Ghost migrations, Tenten offers AI-accelerated conversion services with guaranteed Lighthouse score improvements. Book a free architecture review to streamline your theme modernization process.
Subscribe to my newsletter
Read articles from Erik Chen directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
