Adding (and using) external js libraries to a Ghost theme

Hi All,

Apologies for what seems like a pretty basic question. I’m developing a custom theme and I’m looking to make use of some external libraries to add functionality to my theme.

I have taken the start theme and successfully added that to a local instance of ghost.

In this case I added the typewriter-effect library (see: GitHub - tameemsafi/typewriterjs: A simple yet powerful native javascript plugin for a cool typewriter effect.).

I ran yarn add typewriter-effect and it installed the library and added it as a project dependency. I then thought all I needed to do was start using it. I added a script block to the bottom of a custom page and placed in my typewriter sample animated text instructions. Refreshing the page the console said Reference Error: Typewriter variable not found.

I tried adding the CDN reference to the bottom of the default.hbs area above </body> but that made no difference. I finally added the CDN reference above the other script at the bottom of my custom page and it is currently working.

So my questions are:

  1. If I have installed the package as part of the project why do I need to provide a reference via CDN? I can see I could use CDN instead of the installed package, but shouldn’t it work with the installed package too?

  2. What is the “best practice” for adding in javascript like my typewriter code? Should I include it as a script in assets and then import instead of putting it in inline in the page template?

Many thanks,


I did end up getting it working equally with the included library by placing this in the footer section of the page:

<script src="node_modules/typewriter-effect/dist/core.js"></script>

It feels a bit hacky though. Is there a cleaner way?

Adding the CDN should be enough. The CDN line first; then, you can reference and run the script after. The order is essential.

<script src=""></script>
  var app = document.getElementById('app');
  // ...

The issue here is that if you have more than one library, you will need to include them one by one in the theme template file, and you will end up with many requests.

Also, adding the library from the installed node directory will work. Both ways load the exact file (core.js).

<script src="node_modules/typewriter-effect/dist/core.js"></script>
  var app = document.getElementById('app');
  // ...

In addition to the same previous issue, the issue here is that you will need to include the node_modules directory with your theme final zip file. You only need one file, and you will end up with a huge theme size.

Here is what I do. I use Gulp to include and compile all the third-party libraries plus my theme JS file (/assets/js/app.js), where I run and use these libraries into a single file.


I install the library with npm and save it to the package.js file.

npm i typewriter-effect --save


Add the library to the gulpfile.js file JavaScript task. Here is a simplified example.

  gulp.task('js', function(done) {
    return gulp.src([
      .pipe(rename({suffix: '.min'}))

By running this task, I will have the app.min.js file, which I add to the theme default.hbs file.

<script src='{{ asset 'js/app.min.js' }}'></script>

I have another task to zip the theme, which will exclude the node_modules directory.

gulp.task('zip', function () {
  return gulp.src([
  ], { dot: true })

Here is a complete example of the gulpfile.js.

Thank you Ahmad for your comprehensive answer - I can’t thank you enough! That’s fantastic.

Since I wrote the post I was already thinking I would create corresponding .js files for each .hbs file and place them in assets/js. I’m not sure whether you take a similar approach or you just stick to a single .js file for simplicity.

As an aside came come across your themes in my travels and I love the overall professional feel of them (I particularly like Penang) which lend themselves to professional looking magazine publications.

Once again thank you for your reply. I feel like Ghost is such a great platform and has a nice crossover between ease of use and customisation so I am hoping to stick with it.

1 Like

Yes, I only use one single file that contains everything, thanks to Gulp.

Adding the library file in the theme will require copying and pasting it whenever the library has an update. It’s fine for one or two files but with many libraries or for automating things, Gulp and npm work great for me. With npm, I can update it from the command line, and then Gulp will copy that updated file for me—a way for automating the process and keeping it more simple.

I’m grateful to hear that David, thanks so much!