Using pre-made themes with Meteor

If you want to build Meteor applications with style and you are like me, then good luck. I am the worst person in the world when it comes to (web) design. Thanks to the wonderful Bootstrap framework I can at least produce an ok look given my limited skills. But sometimes this is not enough. Especially when I do not have the resources to work with a dedicated designer I like to shop for a pre-made theme and use this as a starting point. But how to integrate it with Meteor?

The idea

Imagine you want to start building a nice app using Meteor. But it should be more polished than an average Bootstrap site. You can grab great themes from sites like Bootswatch, WrapBootstrap, or Theme-Forest. Usually they are a couple of bucks. If you plan to impress someone with your new Meteor app it might pay off to invest these $6 for some HTML instead of a cup of coffee. For the sake of argument I’ll limit this short intro to Bootstrap only, but it can be easily applied to any other framework or template. If using Bootstrap just be sure to include it into Meteor the right way.

The file structure

Let’s have a look at the proposed file structures for Meteor projects:

There are two locations that are dedicated to your site’s appearence:

  • /public – which serves static content such as fonts and images
  • /client/stylesheets – which holds all CSS/Less styling information

Since Meteor does some magical things it has a pre-defined behavior for certain folder names. Content in /public will not be compiled and sent to the browser directly, files inside the /client folder (and below, of course) are not executed on the server. This creates some restrictions on naming and organizing your files. Unfortunately most existing themes will not be created around any Meteor requirements, they typically have structures like this:

Depending on the source of your HTML template and the preferences of its creator you will find directory names like

  • /images or /img and /fonts – which serves all static content such as fonts and images
  • /styles or /css or /less or something completely different – which holds all CSS/Less/styling information

As you can see there is almost no overlap and chances that any HTML template will directly pluggable into a Meteor project are smaller than winning the lottery. Therefore we need to migrate files.

Unfortunately inside some of the style files we will typically find references to other style files or images. As soon as we start to move files around, these references are going to break, so brace yourself for some dirty work!

Integrating a pre-made template into Meteor

If you’re still using an old-school CSS design you may to take the easier route for integration of existing themes in Meteor and save yourself a step. Less on the other hand is much more powerful, but also requires a little more work. There are also some helpful questions on Stackoverflow about multiple less files. You need to decide for yourself whether you plan on using a CSS-based version or the Less-version. Don’t mix both together, either use css or less files when dealing with a pre-made template/theme!

I created a typical app structure for my new Meteor project and grabbed an existing theme named Unicorn. I now have a directory structure similar to this:

├── client
│   ├── stylesheets
│   │   └── unicorn
│   ├── unicorn-js
│   └── views
├── packages
│   ├── less-bootstrap-3
│   └── less-fontawesome-4
├── public
│   ├── fonts
│   └── img
│       ├── demo
│       └── jquery-ui
└── server

Static Resources

First, I go ahead and move all static resources (that means all non-text files like images and fonts) to the /public folder. It’s as simple as moving or copying some files to your app. That will probably mean you create some subfolders in /public, and that is perfectly ok.
Hint:/public will eventually become the site root folder from the browser’s perspective, so using sub-folders to organize files is highly recommended!

CSS files

Copying the CSS files is the easy part. It doesn’t really matter where exactly you put them, but I suggest you place them all in /client/stylesheets. That way you don’t have to worry about file formats, but stick to semantics. Things will work nicely, even if you put all files in a /client/css folder. Using a subfolder for this theme I make it easier to switch between different themes later on, so I place all my style information in /client/stylesheets/unicorn.

The next step is cleaning the file references. Inside your CSS files you oftentimes find url(). In 99% of the cases they will be broken after the copying. Hence, we need to adjust them to point to the correct (static) file locations in /public. Mostly you need to replace any amount of dots and slashes before an actual folder name to simply root (or /) like that:

 #sidebar > ul > li.active > a {
  background: url("../img/menu-active.png") no-repeat scroll right center transparent !important;
}

becomes

 #sidebar > ul > li.active > a {
  background: url("/img/menu-active.png") no-repeat scroll right center transparent !important;
}

Less files

Copying the less files to your Meteor project is the same as for CSS files. Additionally we probably need to change the name of all your less files. As a built in service Meteor compiles all your less-styles automatically for you, so that it effectively breaks in scenarios with multiple files, mixins, and lots of scattered variables. To regain control over what happens we need to prevent Meteor from doing its magic through the art of file renaming.

Remember that you should have added the less package using $ meteor add less.

Renaming less files

Rename all *.less files to *.less.import (on OS X I like to use NameChanger, but you can also use sed). Now we need to tell Meteor specifically which files to import (and in consequence compile to browser-understandable style information).

Importing essential files

If you followed Manuel’s way of integrating Bootstrap you already have a file that takes care of importing various styles: /client/stylesheets/style.less. It defines a couple of imports, which you can and should reduce even further and adjust for your specific template. In my case, Unicorn already includes both Bootstrap and font-awesome, so I can solely rely on importing three less files from the theme instead of any Meteor packages:

// Import theme relevant less files
@import "unicorn/utilities.import.less";
@import "unicorn/bootstrap.import.less";
@import "unicorn/unicorn.import.less";

Typically if you buy a theme online you will not be required to include Bootstrap separately. That means you do not want to include any Meteor Bootstrap packages although it is certainly helpful when dealing with including the required JavaScript files (see below).

There are several possible pitfalls, one of which I came across with Unicorn was that it uses font-awesome. It wasn’t specified in any of the stylesheets in the less format, so I had to copy over the corresponding font-awesome.css file (and of course adjust the location of the font files).

Adjusting references

Since we changed all file names also all internal references should be changed. It is safe to assume you can perform a simple search for .less and replace it with .import.less inside all your less files. Most text editors allow you to do this (multi-file search) or you can – again – use sed. Also adjust all references for images and fonts according to the instructions above for CSS files.

Since less files allow you to use variables sometimes templates define a location for images or fonts in a variable. That makes it especially easy to adjust your theme for your Meteor app.

JavaScript files

Here’s where things can become really ugly. Most modern HTML themes make use of a large number of JavaScript libraries and include dozens, sometimes even more of these .js files. Integrating them can become extremely tedious because of the way Meteor works. There is hardly any one-size-fits-all approach to integrating all the scripting files, but I can tell you a couple of things I have learned when integrating existing themes.

Some JavaScript libraries rely on stuff other libraries do – think jQuery modules. How do we ensure that a specific file is loaded before another? And how to determine what the correct load order is? Most flexible would be to create your own theme package, but we’re only looking for a small prototype (in this article). This will most likely be part of a future article on themes and Meteor.

Also note all JavaScript is required on all pages – scripts for Google Maps integration or processing Paypal payments are probably better only loaded conditionally. One approach could be yepnope.js. I’ll investigate further on possible alternatives and suggestions

Templates

Dealing with other people’s code is hard. Dealing with HTML code from a purchased theme can be anything from ok to an absolute pain. I found it very helpful to start integrating a new design by providing multiple templates, usually based around the divs of a design. Therefore while still in the integration phase my main template looks like this:

  <title>Theme integration test</title>


    <div id="wrapper">
      {{> pagehead}}
          {{> pagenav}}
          {{> sidebar}}
          {{> pagecontent}}
          {{> pagefoot}}
  </div>

By slicing things up very complex pages become so much easier to handle. As you progress it makes sense to deviate a bit from this simplistic approach, for example by declaring an element’s width on the parent level (again, this comes from Manuel’s guide on how to use Bootstrap).

Adding attributes to body

In case your design has some attributes to the body tag you have to perform one more task. It’s not possible in Meteor to supply any attributes to body by default. Fret not! JavaScript to the rescue – you can simply apply the missing attributes in the form of a Meteor startup function such as:

 Meteor.startup(function() {
   $('body').attr('data-color', 'grey');
   $('body').attr('class', 'flat');
});

This code should go inside any .js file inside your client folder. It will attach the two attributes data-color (with a value of grey) and class (value is flat) to your document’s body.

Conclusion

Adding a pre-made template or theme to your Meteor project will allow you to get started quickly with much more style. Even if you’re working with a design off the shelves it is entirely possible to fit it into your Meteor app with only a reasonable amount of work.

But even if it may be quite useful for a quick prototype, eventually you should rewrite your HTML and styles to be more aligned with Meteor. However, by doing that you will lose the ability to update to newer version of the template used.

Let me know how you approach the integration of existing templates into your Meteor projects and I’ll take it into account for a future article on best practices on making Meteor apps pretty.

Author image
Blogging since 2003 about life, tech, yoga. Passionate about the details and eager to know more. Systems theory meets empathy.
Bochum. Germany.
top