How to duplicate post/page in Ghost CMS

I recently began exploring the Ghost blogging platform. Its design is exquisitely crafted and truly remarkable, making it the best of its kind. Unfortunately, its features are rather limited.

How to duplicate post/page in Ghost CMS
Ghost CMS - admin panel

So how to duplicate or clone whole post/page? Answer to this question is simple - you can't. It is not possible. Ghost lack some of standard features for better content management. I was quite pissed off about this recently when I migrated my whole website from Cloudflare pages to Ghost.

Problem arise even more when you attempt to achieve some more advanced layout. Ghost in sake of simplicity doesn't allow multi column layout. Fortunately we can use editor's HTML cards where we put extra <div>'s with custom styling and we are good to go.

Ok now you achieved more advanced layout in your posts or pages, and you would like to make another post/page with same layout. Now you need to copy all HTML cards one by one from previous post/page and avoid any mistake. One would come up with idea to have simple button in admin panel, where you can just clone whole post/page. Simple - just click and you have exact copy saved as unpublished draft.
But big nope. Such button does not exist in Ghost version 5.

Fortunately I made one. This solution would be valid for people who self-host Ghost. I'm afraid that Ghost(pro) users doesn't have access to all underlying Ghost files. Check the demo video below:

How can I make it works in my Ghost instance?

I wrote simple Javascript code which can be embedded into right html file and it is done. Question is if that will work, because I had chance to test it only on 2 Ghost instances. So treat is as beta version for now.

I am hosting that javascript file on global CDN. So everything you need to do is put it into right file.

Isn't it dangerous? I don't know you.

Yeah you are probably right. It could be malicious and steal your session cookie and I would get access into your Ghost instance. That's all valid concerns, but I am not that kind of guy. Ask my close cirles on twitter. I should probably make it as open-source project. I might do it. Or I can send you source code for investigation.

Ok I will try, what should I do, how can I install it?

  1. Copy/paste my code from CDN.
  2. Find Ghost admin index file and insert script inside.
  3. Restart your Ghost instance.

You will need this code snippet:

<script src="https://ravn.b-cdn.net/ghost_duplicate_v1.2.js"></script>

Now we need to find admin index.html file. Log in into your server. I assume you are using Ghost on Ubuntu.

So we need to "cd" into our project. Mine looks like this.

cd /var/www/ghost_tomravn
Navigate into your Ghost instance folder.

Now go into current -> core -> built -> admin. Whole path on my server looks like this. You will find index.html inside admin folder. That is place where you need to put my script.

cd /var/www/ghost_tomravn/current/core/built/admin
Full path to admin index.html

Now we need to edit that index.html file. It does not matter how you do it. I am using "mcedit" for file edits on linux servers.

mcedit index.html
File edit using mcedit
paste my script as last one under Ghost admin scripts.

Last step is restart your Ghost instance. Simply write this command in your terminal.

ghost restart

Ok log into your Ghost admin and you should see new button next to your edit button. I tested it on newest Ghost version 5. So I don't know if that will work on older versions of Ghost. If you need any help or you have questions,  don't hesitate to contact me.

How does it work?

Basically I am checking if url after (#) hashtag is posts or pages. When url match I am selecting all edit buttons. Edit buttons have attribute with post id or page id.
I am creating new button on the fly and append it next to edit buttons.
When you click on new duplicate button, it query Ghost API for post or page with correct ID. I extract some info like title, mobileDoc, image and page-template into new variable. Then I query Ghost API again, with POST request. This POST request create new post or page automatically. And that's it.