The beginning of our online shop
Throughout the book we will be developing an e-commerce website to help us understand the core concepts of advanced Meteor web development. Let's begin by creating a new project:
meteor create online_shop
The must-have packages
Atmospherejs.com has always been the "go to" website to find packages. Here you will find thousands of packages produced by the community for free. There are a handful of packages that we absolutely need to install to make our website function properly.
First, we install the languages:
meteor add coffeescript meteor add mquandalle:jade meteor add mquandalle:stylus meteor add less
Next, the router and functions that will help us with SEO and routing:
meteor add kadira:flow-router meteor add kadira:blaze-layout meteor add meteorhacks:fast-render meteor add nimble:restivus meteor add yasinuslu:blaze-meta meteor add dfischer:prerenderio meteor add wizonesolutions:canonical
Note
WARNING: Do not run Meteor yet! Canonical could mess up your project unless you have it set up correctly.
We will need a couple of packages as well to help us manage publishers:
meteor add lepozepo:publish-with-relations meteor add tmeasday:publish-counts meteor add meteorhacks:aggregate meteor add http meteor add meteorhacks:unblock
These next packages will extend Meteor's functions:
meteor add xorax:multiple-callbacks meteor add aldeed:collection2 meteor add aldeed:autoform meteor add fastclick meteor add reactive-var meteor add alanning:roles meteor add accounts-password
meteor add u2622:persistent-session meteor add ongoworks:security
We will need these packages to properly manage time:
meteor add momentjs:moment meteor add mrt:moment-timezone
For the last set, we'll be using a couple of additional packages that will make the design process much faster:
meteor add kyleking:customizable-bootstrap-stylus meteor add raix:handlebar-helpers meteor add fortawesome:fontawesome meteor add percolate:momentum
We need to remove some packages for security too:
meteor remove autopublish meteor remove insecure
All of these packages will be explained in more detail throughout the book, but all of these are must-haves. The first package that we need to explain is the wizonesolutions:canonical
package. This package makes sure that all incoming traffic is routed to your ROOT_URL
, so it is particularly useful when you want all the traffic to go to your SSL site. The first thing that we need to do before running Meteor is set up canonical to run only in the production environment.
Create /server/canonical.coffee
, and add this code:
#/server/canonical.coffee
if process.env.NODE_ENV is "development" or process.env.ROOT_URL.indexOf("meteor.com") > -1
Meteor.startup ->
process.env.PACKAGE_CANONICAL_DISABLE = true
This code snippet effectively sets your PACKAGE_CANONICAL_DISABLE
environment variable to make sure that canonical is inactive while you are developing.
What are environment variables? These variables are defined within the scope of the deployment, and they make sure that the project knows information before the build finishes on the server. Information such as what database to use, which domains to use, and other setup information can usually be found in these variables. We will cover this information in the final chapter.
File structure
A proper file structure is tremendously important in Meteor. We have found that the best way to work is with functional top-level modules. This means that every folder is a micro-service, and therefore can act on its own. This allows for a lot of modularity in the project, and it's very easy for others to understand what it is that you are trying to accomplish. In this section, we will cover this file structure and Meteor's special folders.
Let's look at a sample web application folder structure:
/online_shop /online_shop/cart /online_shop/cart/cart_route.coffee #RUNS ON CLIENT AND SERVER /online_shop/cart/client /online_shop/cart/client/cart_view.jade #RUNS ON CLIENT ONLY /online_shop/cart/client/cart_controller.coffee /online_shop/cart/client/cart.styl /online_shop/cart/server /online_shop/cart/server/cart_publisher.coffee #RUNS ON SERVER ONLY /online_shop/cart/server/cart_methods.coffee
In this folder structure, cart
is the micro-service, and it is composed of a route, view, controller, and publisher. The files placed under a /client
directory will be published to the client and will only run on the client. The files placed under a /server
directory will only run and be accessible on the server. If a file is placed in none of these directories, then the file will run on both the client and server. The expected structure goes like this:
/project_folder /project_folder/_globals ./client/<global support function files> ./server/<global support function files> ./lib/collections/<collection>/<file> ./lib/collections/<collection>/server/<permissions file> /project_folder/router ./client/layouts/<layout file> ./lib/<configuration file> ./lib/<middleware file> /project_folder/<module> ./<route file> ./client/<template file> ./client/<logic file> ./client/<styles file> ./server/<publishers file> ./server/<methods file>
It's important to note that the /lib
directory will always run before any other code does. Let's place our canonical file under the /_globals/canonical/server
directory.
Let's create our first module: the router. Create the /router/client/layout.jade
directory, and we will only have one layout throughout the project. Now let's code our layout:
//- LAYOUT.JADE
head
title Online Shop
meta(charset="utf-8")
//- Allow saving to homescreen
meta(name="apple-mobile-web-app-capable" content="yes")
//- Do not try to detect phone numbers
meta(name="format-detection" content="telephone=no")
//- Make it mobile friendly
meta(name="viewport" content="user-scalable=no, initial- scale=1.0, maximum-scale=1.0")
body
template(name="layout")
+Template.dynamic(template=nav)
+Template.dynamic(template=content)
Here, we have introduced the Template.dynamic
component. This component may be used to render other templates dynamically by changing the value of a variable to the name of the template we want to render. We decided to use two variables—nav
and content
— that are controlled by the router. So, basically, the content
variable will be changing to different strings that are equal to the names of our templates.
We will create our landing
module in the next chapter to learn not only how to use the router but also how to properly subscribe to data.