How to make Ghost CMS host with Vercel

Erik ChenErik Chen
13 min read

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:

  1. Host Ghost CMS separately on a platform that supports backend servers

  2. Create a Next.js frontend to consume Ghost's Content API

  3. 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:

  1. Fork the render-examples/ghost repo on GitHub

  2. Create a new Web Service on Render pointing to your forked repo

  3. 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:

  1. Log into your Ghost admin panel at https://your-ghost-site.com/ghost

  2. Go to Settings → Integrations → Add custom integration

  3. Copy the Content API Key and API URL

Step 4: Deploy the Frontend to Vercel

  1. Push your Next.js project to GitHub

  2. Connect to Vercel and import your repository

  3. Add the environment variables in the Vercel dashboard

  4. 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:

  1. next-cms-ghost: A production-ready solution that combines Next.js and Ghost, supporting features like dark mode, responsive design, and SEO optimization.

  2. 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:

  1. Enable private mode in Ghost settings to prevent content duplication

  2. 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:

  1. 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

  2. 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

  1. File Structure Translation

    • default.hbs_app.js (Next.js root layout)

    • post.hbspages/posts/[slug].js (Dynamic route)

    • Partials become React components in /components

  2. 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;
}
  1. 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:

  1. Cross-File References When modifying a post template, Cursor automatically updates related components like featured post cards and archive listings.

  2. 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' };
}
  1. 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:

  1. 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
  };
};
  1. 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 FeatureNext.js Equivalent
Tag ArchivesDynamic routes /tags/[slug].js
Author Pagespages/authors/[slug].js
Content FilteringGraphQL API queries
Member SubscriptionsNextAuth.js integration
SearchAlgolia InstantSearch

Cursor helps maintain feature parity by analyzing Ghost's documentation and suggesting appropriate modern alternatives.

Migration Checklist with AI Assistance

  1. Content Audit

    • Use Cursor to generate content type diagrams

    • Automatically map relationships between posts, tags, and authors

  2. Style Conversion

    • AI-assisted CSS-in-JS conversion

    • Automated responsive design adjustments

  3. SEO Preservation

    • Automatic meta tag migration

    • Structured data generation

  4. 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:

  1. Preserve Content Integrity

    • Maintain post IDs and slugs

    • Implement 301 redirects for changed URLs

  2. Progressive Enhancement

    • Phase migration by content sections

    • A/B test critical user journeys

  3. 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

  1. 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.

  2. 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

  1. 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

  2. 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

  1. 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.

  2. 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

  1. 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.

  2. 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

  1. 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();
     });
    
  2. 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

  1. Automated Documentation Use Cursor's AI documentation generator:

     cursor docs generate --format typedoc --output docs/
    
  2. 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

  1. Activation:

    • Open Settings (⌘/Ctrl + Shift + J)

    • Navigate to Features → Composer

    • Enable Allow Composer to run commands automatically

  2. 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

  1. 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

  2. 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

  1. Context-Aware Processing:

    • Maintain active editors for:

      • Current Handlebars template

      • Corresponding React component

      • API utility file

      • Next.js route config

  2. 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

  1. Real-Time Oversight:

    • Use integrated terminal watcher:

        cursor monitor --log-level verbose --filter "command|error"
      
    • Configure automatic snapshots before major operations

  2. Rollback Protocol:

    • Automatic git commits every 5 successful changes

    • Quick-revert hotkey (⌘/Ctrl + ])

Advanced Configuration Tips

  1. Bypass Tool Call Limits:
// .cursor/override.json
{
  "experimental": {
    "toolCallLimit": 100,
    "autoContinueOnLimit": true
  }
}
  1. 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.

0
Subscribe to my newsletter

Read articles from Erik Chen directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Erik Chen
Erik Chen