What do you want to learn?
Skip to main content
Meteor.js Fundamentals for Single Page Applications
by John Sonmez
In this course, you'll learn about the Meteor platform and how to create a single page application using it.
Start CourseBookmarkAdd to Channel
Table of contents
Hi, this is John Sonmez from Pluralsight, and welcome to this course on Meteor Fundamentals for Single Page Applications. In this course, we'll be exploring the open source platform for building single page web applications, called Meteor. Meteor is still in the preview version at the time of recording this course, but it has the potential to make a big impact on the way we develop web applications, as you'll see in this course. When I first saw Meteor, I was very impressed by how easy it was to use, to create a real-time web application that didn't require me to think so much about the differences between the client and server. By the end of this course, you'll learn the basics of Meteor and how it works, and how to create a complete web application in Meteor, and how to deploy that application.
Who This Course is For
What This Course Will Cover
So let's take a moment to talk about what we're going to actually cover in this course, and we're going to start off in the first module that you're watching now, where we will talk about the basics of Meteor; what exactly is Meteor, how does Meteor work at a very high level? And then we'll also see how to create a basic Meteor application. We'll get set up with Meteor, which is very simple, and we'll create a simple ‘Hello World!' application using Meteor. Then in Module 2, we'll dive deep into the details of Meteor. It's really important to understand exactly what's happening inside of Meteor, so that you can better design your applications and you're not always wondering how things are going to work. Once we understand the deep details of Meteor, we won't have to visit them very often after that, because we'll know that what's happening in the background is going to work and we'll understand the principles behind it. So we'll be dissolving some of the "magic" behind Meteor and we'll also see how a real Meteor application works as we observe it inside of the Chrome Developer Tools Window. Then in Module 3, we're going to start creating our application. We will be building a basic Meteor application and we'll be hitting on some of the key concepts of the Meteor application, starting with things like templates and then getting into collections and even publishing, which is the heart of the Live updates that happen inside of Meteor. In Module 4, we'll extend our app and we'll build some more functionality onto it, including some user accounts, and we'll be working with things like sessions and computations, which also will help us to be able to create a more fully-functional application using the platform. Then finally in Module 5, we're going to go a little bit beyond Meteor and we're going to see how to get Meteor set up on different platforms, as well as how to deploy the application that we've created. There's a few different options for deploying and we'll cover those in this module. We'll also look at some package management and an open source tool that we can use to actually get other Meteor packages and different modules that we can add on to Meteor.
What is A Spa
What is A Meteor
Technologies in Meteor
Let's talk about some of the technologies that make up Meteor. It's important to understand what technologies make up Meteor, because if you do have to troubleshoot something inside of Meteor, you want to know at least what you're dealing with, and also, you may want to actually swap out different parts of Meteor. And it turns out that Meteor actually allows you to change your database or your templating engine. So for example, if you don't want to use MongoDB, you can use a different database; and if you don't want to use Handlebars, you could use a different templating engine.
Meteor actually has a few different versions; two that are officially supported and one that is not officially supported. Meteor is officially supported on both Mac and Linux, but it's not officially supported on Windows, although there is an officially supported version for Windows that is supposed to be coming shortly after the 1.0 release of Meteor, at least it's on the schedule. Now if you use Mac or Linux, you can immediately get the newest version of Meteor, since it's officially supported there and have access to all the capabilities of Meteor, but if you want to use the Windows version, which works pretty well, it might just be a little bit behind. So let's talk a little bit more about the Windows version of Meteor, because that's what we're going to be using, at least for the start of this course. Since there's really not a huge difference between the Windows version and it's probably a little bit easier for most people watching this course to get the Windows version set up, we're just going to start there, but feel free to use the Linux or Mac version if you want to as you follow along with this course. Now there's a few different choices for getting Meteor working on Windows; many of them involve a virtualized machine, which you're welcome to use as well, but we're just going to use the unofficial version of Meteor, which is just a little bit behind the latest released version of Meteor. The only other drawback to using the Windows version of Meteor that's unofficially supported right now is that we don't have access to the Meteorite application, which basically wraps Meteor and adds a package management system that allows us to get open source community contributed packages from a library called Atmosphere. But don't worry, we will cover both Meteorite and Atmosphere. We'll just be doing that at the very last module in this course when we actually use the Linux or Mac version of Meteor. For now, though, with what we're going to be learning about the basics of Meteor, we don't need to worry about that and the Windows version will work just fine. I'm going to show you how to get that set up next.
Setting up Meteor
Okay, so I'm at the meteor.com website, this is the main site for Meteor, and here, if you do want to use the Linux or Mac version and I just want to show you real quick, if you click on the Documentation, it is super easy. You just do a curl and then you just do ‘meteor create myapp' and then you can go in there and you can run Meteor right from there. This is basically all you need to do to get Meteor installed. Now, if you're using the Windows version, which we're going to be using for the most part of this course, you can just go to win.meteor.com, and here you can find a couple of downloads. We're just going to choose the ‘Latest Meteor for Windows', this exe bootstrap, but you can also download the MSI installer if you want, but I'm just going to choose this ‘Latest Meteor for Windows' and you can see that it just gives me an exe that I can run. And when I run this exe, it'll get Meteor set up, and you can see here on my machine that I already have Meteor installed, so it's actually running the Meteor command, which it wants me to be in a Meteor Directory in order to be able to run this. So, we can see now that Meteor is working, and on your machine when you run this, you should see an install script flash by and then Meteor will be set up and ready to run. It's pretty simple.
Okay, so once you have Meteor installed, all you need to do is basically type ‘meteor' to start using it. Now Meteor has this command line interface that allows us to do a lot of what we need to do as far as setting up Meteor and creating new projects just by using this Meteor command. In fact, you should be able to type meteor and you should see this following output here. If you don't, you might have a problem because the exe on Windows should have set up Meteor in your path. You might have to reopen your Command Window if you had already installed it from the Command Window. Now let's go ahead and go to whatever directory you're going to create your Meteor application in and we'll just create a very simple ‘Hello World!' application. So I'm just going to go into here, into WIP, and then I'm going to go into meteor, and then inside here, I'm just going to do ‘meteor create' and then whatever I want to call my application, so let's call this HelloMeteor. Now, you can see that it's created a directory called HelloMeteor, so we can actually cd into here. And then if we type meteor, it's running our application, and you can see it's running by default on localhost port 3000, so all I have to do is go to localhost:3000, and this is my Meteor application. You can see it doesn't really do much at this point, but I already have an application that's being served up by Meteor.
Looking at Hello Meteor
Well that's it for this first introductory module on Meteor. Hopefully by now you have a good idea of what Meteor is and what Meteor is about and some of the technologies that make up Meteor. And we've seen just how easy it is to create a Meteor application, as we've created our first Meteor application with the HelloMeteor default application just by running a simple command. Now everything we do from this point forward won't be quite that simple, but creating web applications with Meteor is a lot simpler than using many other frameworks and technologies you may be used to. Now up next, we'll be diving a little bit deeper into Meteor and seeing how exactly Meteor works and how the magic that is Meteor happens. We'll also explore some of the demos and example projects that come with Meteor itself and see how those work inside of the Chrome browser, as we use the Chrome Developer Tools to analyze what's happening behind the scenes. Thanks for joining me and take care.
Hi, this is John Sonmez from Pluralsight, and in this module, we'll be diving a bit deeper into Meteor, as we learn exactly how Meteor works. Probably the biggest challenge you'll find in developing an application with Meteor is having enough faith in how Meteor works to be able to let go of some of the control you might be used to in developing an application and let Meteor do much of the hard work for you. We have to demystify a big portion of the magic of Meteor in order to understand how best to use it. In this module, we'll take a look at how exactly Meteor works. We'll start with the basics and talk about how Meteor actually manages to synchronize data almost seamlessly between different clients connected to the same application. We'll also look at the project structure of a Meteor application and take an in-depth look at Meteor in action, as we watch the data going back and forth, using the Chrome Developer Tools. By the end of this module, you should have a good understanding of how Meteor works and be ready to build an application using the technology.
Looking at An Example
So let's actually take a look at Meteor in action, just so we can see what Meteor can do with a very, very simple application. So I actually have an example application that you can get from Meteor directly that sort of ships with Meteor and the Meteor Tool and we'll look at a couple more of these later on, but this basic application is a leaderboard application, and I have two windows open, two different Chrome windows, and you'll notice here I can select a person and then I can click this ‘Give 5 points'. And watch the other window when I click this. So you can see here that it's actually updating very, very fast in almost real-time, pretty much in real-time, and it's synchronizing between the two. So, for example, if I ‘Give 5 points' here, you can see that these are changing as well. So, either way, this communication is happening back and forth, and this is one of those things that seems like magic, especially when you see how simple this application is. Let's take a quick look at this actual application and then we'll discuss how this is working.
Looking at The Code
It's not Magic
Obviously, you didn't really think that Meteor was magic. Well, if you did, don't worry, I won't tell anyone. When I first saw Meteor in action, I thought there had to be some kind of magic going on. But anyway, everything that Meteor does is already possible with other technologies. The big difference, and one of the main reasons why I like Meteor so much, is that Meteor takes these fantastic things and pushes them to the background so you don't have to think about them so much. In that regard, they sort of act like magic. In the new few slides, we'll take a look at the three main areas of magic in Meteor; communication between the browser and server, data synchronization between many clients, and updating of HTML live in the browser without manual DOM manipulations.
How Meteor Works
How Meteor Works Synchronization
Okay, so now you know how Meteor apps running in the browser are able to communicate with the server in real time. But, how do Meteor apps communicate with each other? The magic here is a Publish/Subscribe model of messaging that you may have seen before if you've used a technology like Microsoft Message Queue, or JMX, or any number of other implementations of messaging. What happens to make this work is that each client will subscribe to some events that happen to data on the server. Let's say you have a bunch of customers stored in your database on the server, well, each client could subscribe to be notified when that customer data changes. Then, one of the clients ends up changing the customer data. The Meteor Server sends a Change Data over to all the subscribed clients and they update their display to reflect the new data. It's surprisingly simple how all this works.
How Meteor Works Updating
Meteor app Structure
Okay, so now let's take a look at a couple of the demo applications from Meteor so we can get an idea of the Meteor capabilities and then we'll actually use one of these demo applications to really look inside Meteor and see the data going back and forth when we're manipulating data inside of a Meteor app. So if you go to meteor.com and then you click Examples, you can see there's four main examples here that I'd recommend that you check out and play around with the code some, just to get familiar with Meteor, because it's so easy to get these things set up. So, all you have to do is basically just call this ‘meteor create', and then ‘--example', and then, in this case for example, you would do ‘leaderboard', and then you can see like for parties, it's just ‘--example parties', and then todos, we have one as well. So let's take a look at a couple of these. We've already seen leaderboard, but let's go ahead and take a look at, we're just going to go to the todos and the wordplay, since those are some interesting applications, let's do that next.
Getting The ToDos Example
Okay, so I'm here in the directory that I created for my Meteor application and I'm just going to type here, ‘meteor create --example todos', and this will go ahead and create that example and you can see, it's real simple to get started with this, we just cd into todos and then we just run Meteor. And we have this example running, so if I go and open up my web browser, and then I go to 127.0.0.1.3000, it will take me to this Todos app, and then here you can see that we've got a pretty good Todo application that you can sort by the different Todo Lists, you can check things off of the list, you can delete something from the list, you can change the tags, so pretty good amount of functionality here, and let's take a quick look at the code behind this next.
Okay, then I went ahead and did the same thing and I got the wordplay application, this example application, and I'm just going to start this by running Meteor inside the wordplay directory. And then let's go ahead and open up a browser window and we'll just check this out real quick. So, if I go to the Port on my localhost, Port 3000, I can type in my name and then click this ‘Play solo', and now I'm supposed to find words in here, and I don't really see many words, here's one, IN, so I can hit Submit and I get some points for that, and you can see how this works here. If you try to type in a letter, it'll show you where that letter is. It's got a decent amount of functionality, a countdown clock. So, you can play around with this example app; in fact, I'd encourage you to play around with all the example apps and just get a feel for how Meteor works. But, now let's take a look and see what's going on behind-the-scenes with these type of example applications and just with the Meteor app in general, but before we do that, we do need to talk a little bit more about that protocol that's being used between the client and server to communicate.
Meteor uses a protocol called DDP, or Distributed Data Protocol, to communicate between the clients and server. The protocol allows for doing two things; first, publishing and subscribing, and second, remote procedure calls. Once a DDP connection is established, the client can subscribe to some data on the server by sending a subscribe command and the server can publish changes to the clients as well. A client can also use DDP to make a remote procedure call to the server and get back a response from it. DDP is actually pretty easy to read, because it sends the data via EJSON, which is just a JSON implementation that supports a few more types. Let's take a look at this communication in action next.
DDP In Action
Okay, now I've got two browser windows open here with our Leaderboard application and we're going to use this to see exactly how this communication works between the different clients and the server, so we can see this real-time in action and see what data's being sent. Now, I do have to caution you; if you want to use WebSockets, (you'll notice that I don't have localhost here, I have 127.0.0.1, which is pretty much the same thing as localhost), there's a bit of a problem if you have IPV6 on your network, or your PC, which I do, it won't work unless you use the actual IPV4 address. So, localhost would normally go to the IPV6 version, which doesn't quite work right now with Meteor, so just make sure that you type in this if you want to use the WebSockets. Otherwise, it'll actually default to the XHR, or the SockJS implementation, which uses polling. So let's go ahead and open up our Chrome Developer Tools, I'm going to open this up on both windows, and I'm going to go to Network, and then from here we want to go to WebSockets. So this is actually a little bit difficult to read, so what I'm going to do is expand this, I'm going to click on the WebSockets, and then I'm going to reload this page, and you can see that it then opens up this Socket connection. I'm going to click on this and then click on Frames. And already you can see some data, let's go ahead and put this one back, and then let's do the same thing with this other side. We're just going to go over here and go to Network, and then WebSockets, and then let's reload this so we can see the initial connection happen, and then we're on the Frames here. So now, what we should see is any data that's coming across here. So, let's say I click on Grace Hopper, and then I click this ‘Give 5 points'. And you can see it updated here and I can do this again, and so now it's at 90, and I have to click here to see, and we can look at both sides of this. If you look on the one side, what ended up happening was that you can see that we sent some message data, we basically sent this method, players/update, and then some parameters, and it passed in some id here. And then, this basically did an update to that specific player, it didn't increment by 5 points. Then we got back a result and then we actually got back a message that said that that data had changed for that player, the score field had changed, and then it basically ended up doing an update here. Automatically, Meteor was able to detect that. Then we sent another message when we updated the score again and the same thing happened again, the same occurrence. So you can sort of read this data here, and you can see that this data is coming across from our client to the server. Now, if we look at the other side here where we're not sending data, we're just displaying the results, you can see something similar. The only difference here is that you're not seeing us actually send data, because we never changed anything here; you're just seeing these added and changed notifications that are coming across. Really these two changed ones are the ones that happened. We see that the score changed from 85 to 90, it went ahead and updated this once to 85, and then once to 90. And then if we did something on this side, we would of course see that the changes start from here. So, you can see that already updated there when I did the ‘Give 5 points', then you click on here, and you can see what's happened here. And there's also a little bit of data that's just being sent to keep this connection open, kind of like a ping here, you notice this every once in a while. But that's the basic way that this is all happening. So, hopefully this demystifies things a little bit here. Remember that we're using this Publish and Subscribe mechanism in order to make this happen, so both of these clients, when the page loads up, they're subscribing to this data here, which we'll talk about in the next module that's called a Collection. And then, whenever there's a change, the server is going to push this out. So, what's happening when we change the data is we're sending the server some information, we're making a method call that changes that data that says ‘increment this value by 5'. It, in turn, responds back by publishing out an updater, letting us know both of our clients that the data has changed, and then Meteor is able to use the Template Engine and the data that it got back in order to replace this portion of the HTML that has the score here for this person with the new HTML that represents the new score.
Okay, by now you should have a pretty good understanding of how Meteor works and the basics of the structure of a Meteor application. You're probably ready to get started building a real application using Meteor, though. Don't worry. Up next, we'll be doing just that. In the next module, we'll start building our Protein Tracker application and learn some of the basics, like how to use collections and templates. Thanks for joining me, and take care.
Creating Our App
Hi, this is John Sonmez from Pluralsight, and in this module we'll be creating our first real Meteor application. Now that we have a good understanding of what exactly Meteor is and how it works, it's time to build something with it. In this module, I'm going to take you through a step-by-step process of building a pretty simple Meteor application. And along the way, we'll learn about three important concepts in Meteor; templating, collections, and publishing. We'll learn how to apply each of these concepts as we use them to create our application. By the end of this module, you should be able to use these concepts to build your own simple Meteor application.
What we are Going to Build
If you've watched some of my other Pluralsight courses, you're probably familiar with the Protein Tracker application. I like to use this simple example because it's easy to understand and can be used to utilize some of the basic features of a platform like Meteor. The idea behind the Protein Tracker application is pretty simple. It's just an application that a user can use to track how much protein they consume in a day versus their goal. In our first version of this application, we'll only have a single user, and that user will be able to enter an amount that gets added to their total for the day. We'll also track a history of the entries that user makes. Later on, we'll extend this application to add more functionality, but for now this will help us to understand the basics of Meteor.
Breaking it Down
Before we jump right into coding the application, let's break things down a bit so we can understand how we are going to build our application. I always find it useful to break a seemingly large task into small steps to make it more clear what needs to be done and the effort it will take. Our first step will be to create a new Meteor project. We've already done this before so this step should be pretty easy. Then, we'll create the UI, but we'll create it as plain hard-coded HTML. We'll do this so that we don't end up trying to create the UI at the same time as we're trying to deal with templates and other parts of the application. Once we have our UI created, we'll figure out the best way to divide up the UI into parts that will serve as templates. We'll use some hard-coded values to fill in the values for these templates at first. Then, we'll use collections to actually represent the data that will populate the templates we created. We'll create a collection that will hold user data and another collection for the history of the user. Next, we'll add the ability to actually add protein using the Amount field and Add Protein button by hooking that button up to increment the total value in our collection of the user data. And finally, we'll remove a feature called auto-publishing that's useful for helping us quickly get our app running, but can be a big performance problem in a real production application.
Creating The Project
Okay, so the first thing we need to do is to create our project. Now this is pretty simple to do; all we have to do is run ‘meteor create' and then we'll name our project, and let's call this project ProteinTracker. So now you can see that we have our new app created, so we should be able to cd into ProteinTracker, and then if we just run meteor, it should set up Meteor server on our Port 3000 on the localhost, and we should be able to connect to this. So let's go ahead and just verify that this does work. So if we go to, and I'm going to put in that 127 address to make sure that I've got WebSockets working, then we can see we're at ‘Hello World!' and we've got our ‘Welcome to ProteinTracker' . And when we Click, it is getting that pressed. So now, we will need to create our actually user interface for our ProteinTracker application.
Creating The UI
Creating The First Templates
Adding more Templating
Populating User Data Template
Populating History Template
Okay, so our next is to get this other template working. So we have our history, it should display the ‘Last 5 Entries'. Remember, we're actually looping through history items here, so this each is going to be for whatever we end up returning back, which will, in our case, it'll be an array of historyItems. And then we're going to get the properties from here. It's going to work very similar to how we had user, except user was just a single object, here this will be an array of objects. So we can do the same thing, we're just going to go in here and then we're going to say Template. and remember the name of this template is history, and then we're going to say helpers, and then we're going to pass into here an object. And on this object, we're going to have a property called historyItem and this is going to return a function, and this function will have our historyItems. So, I'm going to go ahead and just copy this to save us a bit of time here. And all I'm doing is I'm just creating an array here using literal values. Let me go ahead and format this, make things a little bit easier to read. And so you can see, inside this array I just have a bunch of anonymous objects that have a date and a value. And so with that, we should be able to populate this data. So we're going just return back that array, we're just going to say ‘return historyItems'. And then when I Save this, you should see this data populate, and you can see it's populating right there. So again, real quick, same exact thing here. We have our template, it's named history, so that means that we're going to be doing Template.history. Then we have our helpers, and then we have historyItem here, we're doing an each on historyItem. So, we have a property here called historyItem, it's returning a function, this function is setting up the data, and then returning that data, pretty simple.
One central concept in Meteor is Collections. Collections represent data that is used in our Meteor application. If you come from the relational database world, you might think of Collections in a similar way as you think of tables. In Meteor, a Collection is a data structure that Meteor knows how to synchronize between the client and server. In our application, we'll be creating a collection of users and a collection of history items for a user. We'll store that data in our MongoDB instance, but we'll be able to access that collection data from both the server and the client. Meteor handles collection data in a special way to make it very easy for us to do this.
Adding A User Collection
Okay, at this point we have hard-coded data that we're returning back to populate our templates, but we don't want to just return hard-coded data. We want to use some real data, we want to get the data from a database, eventually we want to make it so the user can enter the data or manipulate the data themselves, but the next step is to push this down one layer deeper. So we're still going to be somewhat hard coding the data, but we're going to be using collections so that we're going to be getting this data from the database. And again, I like to take this approach where I'm pushing the data down each layer instead of starting at the beginning trying to get everything working together. So, what we're going to do is we're going to start off by creating a collection for our users and we're just going to have one user for now, but eventually we'll make it so this application could use multiple users. So we're going to create a variable here and we're going to do this at the global scope and this is going to be necessary in order to build accesses from multiple places. This is really the convention that you should use when you're creating collections in Meteor. Notice that this is outside the isClient and the isServer, so this is going to run on the client and the server, which you need to do because it needs to be initialized on both sides. So we're going to say new Meteor.Collection, and then we're going to name this collection, and we're just going to call this one users. So now we have a collection to work with, and again, this is going to be represented in the database as a MongoDB collection as some users documents. So now that we have this collection, we're going to want to populate this collection with some initial data. So what I'm going to do is I'm basically going to check to see when our Meteor Server starts, when our Meteor code starts on the server-side. I'm going to say if(Users.find), this is how we search a collection, it's just a MongoDB command basically for finding some data in the database. So, we're going to say (Users.find().count() === 0). So, if there's no users currently in our database, then let's go ahead and add some dummy data, we'll add a user. So we'll just do Users.insert, and again I'm executing a MongoDB command when I'm doing this insert. I'm just doing an insert like you would with MongoDB. If you're not familiar with MongoDB, that's okay; you can do some research later on if you're going to use Meteor a lot, you're probably going to want to learn some about that database in order to really maximize your usage of Meteor. But you can just follow along for now and it's pretty straightforward. So, I'm going to insert an object that has a total of let's say 120, and a goal of 200. I'll go ahead and Save this and we'll make sure we add our semicolon there. Oaky, so now we'll definitely have some data in our database. I'm going to go ahead and make it so we can see what's going on here. You can see our old data is still showing up, even after I've saved this, because we haven't changed this helper, but now what I can do is instead of returning this hard-coded user inside of this function, what I can do is I can search the MongoDB essentially. I can basically get out of our user's collection, the first user. So I'm going to do this return Users.findOne, that's going to give us the very first user. We're only going to have one in there right now, we're just going to count on there only being one. I'm going to save this, and nothing's happened at this point. Occasionally you have to go and check over on your server and see if it's stopped. Sometimes it seems like maybe it's just a Windows version, but there is a problem where it will stop on you, so you might have to restart your server, but that's pretty easy. So I've went ahead and restarted this, and now you can see that this actually updated, the Total is 120, the Goal is 200. And that object exists inside of the client. So, for example, I can do Users.find, let's say find or findOne. And if I execute this, I'm going to get back the result, which is going to be that user. Notice that it's given an id automatically. We're going to use this a little bit later on, but we have access to this. We could even insert users here, or insert data directly. This is a useful way to work with your Meteor application is you can basically insert your data and try things out because you can manipulate that MongoDB directly from the client using that minimongo API we talked about earlier.
Adding A History Collection
Okay, so now let's go ahead and do the same thing with history. We're just going to create our collection called History = new Meteor.Collection, and we'll call this history. And then we're going to insert some dummy data just like we did before. So, we'll say if, and this time we're going to look for our history. So, instead of Users.find, we're going to say History, and then inside here, we can go ahead and do an insert, so we can say History.insert and then we can go ahead and insert some data. So we want to have a value, so let's just make the value say 50, and then we want a date, which we're going to do a new Date().toTimeString, and then we'll go ahead and add couple of these inserts. So we can make a value 30 and let's say 10. And then what we want to do here is just replace this code. So, now we can just do return History.find, which will go ahead and return back all of our history, if I save this. Okay, so now you can see that we have our data, we have our three items showing up here. And so now at this point, we do have hard-coded data still, but we are getting our data using the collections API and we are just hard coding this into our database at startup. So, now we've pushed things all the way down and we're ready to take things to the next level and actually make our Add Protein button here work.
Making add Protein Work
Finishing add Protein
Now we're not quite done yet, right, so we're updating the User, but we need to insert a historyItem. So let's do History.insert and we're going to add a historyItem every time, so we're going to say value is equal to amount and then we're going to set the date equal to new Date().toTimeString. And then we're actually going to do one last thing, which we're not going to utilize at this point, but we want to track the userId because we want to know what user actually did this, or added an amount. We only have one user in our system right now, but we need to make sure our data is complete, because at some point if we have multiple users, we need to know which history belongs to which user. So we're just going to put in the this._id to keep track of that as well. Now I'll go ahead and Save this. And now if we enter an amount, you can see that it's showing up here. The sort order looks a little bit wrong though, so let's go ahead and fix that, and we probably only want the ‘Last 5 Entries'. So, the way that we can do that is we can just change this find on our history and we're going to add a couple of parameters here. This first object is filter criteria, we're not filtering based on anything. Next, we're going to set up our sort and we're going to sort on date and we're going to do -1 to say what direction that we're sorting. And then we're going to say what our limit is, we're going to say the limit is 5, that's going to make sure we only get 5 entries. So I went ahead and Saved this and now you can see that there's just 5 entries and our newest entries are appearing on top.
Up until this point, we've been using a feature called auto-publish that has made the collections we have on the server and client's synchronize with each other automatically. If we change some data on the server, the client would instantly see the changes and vice-versa. Meteor does this by using a publish and subscribe model that we talked about earlier, and using auto-publish, it automatically adds some logic to our collections to publish themselves in their entirety when they change. But, while this auto-publishing may be convenient, because we always have all the data we need accessible from our client, it isn't very efficient and can represent a security problem. We don't necessarily want to sync our entire MongoDB with all its data to every client connected to our application. Instead, we can turn off auto-publish and manually decide what collection data gets published and manually subscribe to that data in our client's. This is a bit more work, but it gives us much more control over our data.
Turning off AutoPublish
So up to this point, we've been auto-publishing our data. So as we had mentioned before, we've basically been taking our entire MongoDB and copying it to each client. That's why we could see all the data from each client; whenever we change anything on one, it showed up on the others. Now we still want this functionality, but we want to have control over this data. Right now it's not a big deal, we don't have much data in our database, but when we have a lot of data and we have different user's data, we will care more about this, especially if you can imagine, we don't want to necessarily send all of the history details for a particular user to every other user. So the way that we're going to do this is we're going to turn off auto-publish and we can do this in our application by doing ‘meteor remove autopublish', so now it says autopublish: removed. So now if I start up Meteor, you'll notice that our application is not quite going to work. In fact, we're missing all of our data here, our templates are not working because we don't have any data to operate on. If we type in Users.find, we get back our collection, but let's do a .count on it, and it actually has nothing in it. Same thing if we do History.find().count, we've got no historyItems. So we need to manually set up our publishing and subscribing for the data that we want.
Now this isn't very difficult to do; all we have to do is publish our data manually at this point, which is really simple to do. We're going to publish from the server. So what we're going to do is, inside of our isServer code, we're going to set up our publishing. So, I'm just going to go ahead and put some code right in here and we're just going to do Meteor.publish and we can give this a name of the data that we're going to publish, we're going to call this allUsers. And then we give a function that actually is going to do the publishing. So, in this case, we're just going to return Users.find, that'll be all of our users. Okay, and we're going to do the same thing for our history; I'm just going to copy and paste this and modify this to be allHistory, and we could actually publish just a portion of the history. Like I said before, we might want to take in a userId and just publish the history for a particular user, but for now we're just going to publish it all, so we're just going to do History.find. So all of that data is going to be synced over, and we need to subscribe to this data. So, let's go back to our client-side and then we're just going to set up some subscriptions. So on the client, we just want to say Meteor.subscribe and then we're going to subscribe to both of those channels, so we had one called allUsers and I'll go ahead and Save. And then we'll do Meteor.subscribe and this one is called allHistory and I'll Save. Now we're not seeing our data update because Meteor is not running, so let me go ahead and run Meteor real quick. And now you can see all our data is back; we are manually publishing and subscribing to this data. And so if we add entries, our functionality still works, but this is much better. Instead of passing all that data back, we are basically passing back just the data we want. In our case, it's still all the data because we have set this up to manually do that, but we're not using auto-publish anymore, and this is going to be critical, like I said, if you can imagine, if you have a really big database, you have a lot of data, you don't want to send all that data to the client, especially if there's sensitive data in there.
Congratulations, we've created our first real application using Meteor. Hopefully, you found this whole experience wasn't very hard at all. Meteor does a large amount of work for us and helps us to blur the lines between client-code and server-code, which I find to be a bit of a relief, but we aren't done yet. We've only really scratched the surface of what Meteor can do. Up next, we'll expand our Protein Tracker application as we add a few more features, and along the way, learn about some more important concepts in Meteor. Thanks for joining me and take care.
Extending Our App
Hi, this is John Sonmez from Pluralsight and in this module we'll be extending our Protein Tracker app in Meteor to add some additional capabilities as we further our knowledge of the Meteor platform. So far, our app is pretty neat, but it isn't really that impressive. We can add protein and see the amounts updated in real time on multiple browsers, but we're missing the ability for a user to log into the application and we haven't really thought much about security. In this module, I'll take you through the process of building out our application with a bit more functionality and we'll hit on more of the key concepts in Meteor, like the built-in account support, Sessions, Computations, Latency support, and Meteor Server Methods. By the end of this module, you should have all the tools you need to build a real Meteor application and have a good idea of the capabilities the Meteor platform provides.
What we are Going to Build
Breaking it Down
Let's break down the steps of what we're going to do in this module as we build more features onto our application and explore more of Meteor. First, we'll add the ability to log into the application. This is actually pretty easy to do by itself; Meteor gives us a really easy way to add login capabilities and even use Google Authentication without us having to do hardly anything. Then, we'll need to switch our user information to a new collection we'll call protein data. Before we were managing the one user we had ourselves, but since we'll be relying on Meteor's Accounts framework for our users, we'll want to repurpose our user's collection to just contain protein data for that user. Once we have these two things done, we'll have the ability for multiple users to log into our application and be able to store their data separately. Next, we'll tackle the problem of saving the amount that was entered last so that we can repopulate the field when the app is reloaded by the server or user logs in or out. We'll do that by using Meteor's Session capabilities. Then, we'll add some debugging support for logins, as we explore the powerful Computations capability in Meteor that allows us to write code that automatically re-runs when data changes. And up until this point, we've been executing most of our logic on the client itself. This can be insecure and poses a potential problem if someone enters bad data. We'll use Meteor Server methods to move the actual adding of protein to the server where it probably belongs anyway. Then, we'll take a quick look at Latency Support as we add some experimental data to simulate how we could handle real latency situations in an application. And finally, we'll add another button to our application to subtract some protein and we'll use permissions to add some security around it to prevent user totals from going negative.
One of the most impressive things I've seen about Meteor so far is how easy it is to add the ability for users to log in to an application. This is such a basic requirement of most applications, yet I find myself time and time again scratching my head, trying to figure out how best to add user account support to a new application. With Meteor, it's very easy; all we have to do is add one package for the user interface support, which will give us the ability to add a functioning Login button to our HTML using a template and an authentication package, which we can use to add support for this standard user name and password or authentication. Or better yet, get automatic support for all of the third party authentication mechanisms you see here. In our app, I'll be showing you how to add support for logging in with a Google account, but you can easily support a different third-party authentication mechanism, like Twitter or Facebook, just by using a different package.
Adding Accounts Support
The first thing that we're going to do to add our login support is we're going to add two packages to our Meteor application. I've got a command-line console open here and you can see I've done a ‘meteor list' command inside our ProteinTracker app, and here you can see a couple of the packages that we're going to add. First we're going to add this accounts-ui, which is simple templates to add login widgets to an app, which is what we're going to want, and then we're going to use accounts-google, which will give us login service for Google accounts. So, in order to do this, remember we're just going to do ‘meteor add' and we can just say accounts-ui. And you can see that it went ahead and added that to our app, and then we're going to do ‘meteor add accounts-Google', and now that's added to our application as well. So now we have the capabilities, we just have to utilize them.
Fixing A Conflict
Okay, now when you restart your application, we're going to go ahead and do that here, we're going to just say ‘meteor', you'll probably see an error and this error basically says that users/insert is already defined, a method named users/insert. The problem here is that actually the accounts package ends up using the user's collection, it has its own user's collection. So, this is actually pretty easy to fix. If we just go into our code here, what we can do for now is we can change the name of this collection; instead of users, we're just going to call this protein_data and we're actually going to convert this over later, but for now we're just going to change the name. I went ahead and saved this and you can see as soon as I saved this, it said ‘Meteor server restarted' and so we should be up and running. We can test this out by opening up a new browser window and just going to our application, and you can see our application is here and it does work. So, now we need to actually add a Login button, so we're just going to add it right here.
Adding The Login Button
Okay, are you ready to add a Login button to our application? I've got our side-by-side window here, so we can see what's happening when we do this. Now this is a little bit difficult so make sure you stay with me here. Put down your IPad and pay attention, unless you're watching the video on the IPad. So, what we're going to do is we're just going to put in here two curly braces, we're going to type in loginButtons, and then end it with two curly braces, and then save our file. And there you go, we have the Login button. Now we still have to configure this and one really neat thing about Meteor is that it allows us to configure this with this button. So this will actually turn into a Login button once our configuration is created for logging in through Google, but before we do that, let's do one other thing. Let's make it so that this data does not show up unless user's logged in. So the way that we're going to do that is we're just going to use our templating engine and we're just going to do #if and we're going to use this current user. This is a variable that is set if there is a user logged in. So, if there's not a user logged in, it's not going to be set so we can just do a /if here, and let's go ahead and format this file. (Typing) And I'm just going to go ahead and indent that here. So, now I'm going to go ahead and Save this. And now you can see that everything disappears because we're not logged in, but once we login, this should all appear again. So now the next step is that we're going to configure this with Google.
Adding Google Authentication
Renaming to Protein Data
Okay, so now the next thing that we're going to want to do is we're going to want to convert this over so that we're actually associating our Google account, or our logged-in account, with the data that we're going to be displaying. Right now, our application just has one user. The user's not related to the logged-in user and it's just displaying the data for that user. So, for example, if I log in with another account, which I'll show you in a little bit here, it would have this same data, it would update that data, but we don't want that. We want our data for our Protein Tracker application to actually be associated with the user. So, we're actually going to get rid of our user's collection, and to be more precise, we're going to be repurposing this. So, what we're going to do is we're going to call this ProteinData instead, we've already changed the collection name here, but let's go ahead and change this everywhere else. And this is just going to represent the data portion; it's not going to represent the user itself since we're using that account's API for the user itself, but this is going to be the data associated with this user. So we're basically going to have for every user account, an instance of this ProteinData inside this collection that's going to be tied to that user account. So, let's go ahead and go through here and I'm just going to search for Users, and what we want to do is we what to replace that with ProteinData. We want to find all the instances here and let's call this allProteinData. And then, we're not going to need any of this code to run at server startup, because we're going to not need the fake data anymore, so I'm just going to go ahead and get rid of this here and then this other block as well. Now let's go ahead and fix this subscribe also; instead of allUsers, we call this allProteinData. So we're going to make sure that we subscribe to the correct channel.
Adding new Protein Data
Associating History with A User
Now we're not done quite yet because we still have to make sure that the History data is going to be associated properly with our user. So, for example, if we use our application right now and I just ‘Add Protein', it's going to add to the Total, but it's not going to add any history because we're doing that filter on the history, it's not associated with the userId. So, this is actually pretty easy as well. We don't even have to really change this part in our update because we're updating based on this._id, and if you're curious how this works, what's happening is with our ‘with here' in our template, this #with user, we're actually using the ID inside there. This is the context in which this is operating. So, when we have the click on here on this event that this is able to get the ID from there. So that's going to update fine, that's okay because that is the actual ProteinData object, but our history, right now we're inserting an amount, we're inserting a date, that all seems good, but our userId was this._id because we're using the ID of the user when we had the users collection, but we don't want to use that anymore. What we want to do instead is we want to use the ID of the actual user itself. Now we could technically use this._id and do the filtering on that, but that makes things a lot more complicated. We should just have it all working off of this single key, just the actual userId for Meteor. So, the way that we can do that is we can just change this, instead of doing this _id, we can use that userId again. So now I'm going to go ahead and Save this, and we'll go ahead and go to our application now and let's add some protein. And now you can see that we are getting the history, it is updating. Now there is one small issue here still with the history itself. We are doing our filtering here. Now we don't have to change this if we don't want to, but if you think about it, at least the limit part, like the sort makes sense to do on the client, but this limiting part we should probably be doing on the server because what if we have a 1000 history items. We're only displaying five, so why send them all to the client. So you've got to think about these kind of things when you're building the application. So let's go down here and let's change this just a little bit. What we're going to do is we have our filter and then we're not actually going to add a sort, so we're going to leave that one blank, but we do want to add a limit. And so let's test this out just a little bit here and see if there's any more issues. Okay, so remember I said that we didn't have to do the sort on the server side? I sort of lied a little bit; it depends on what data you're dealing with and how you're dealing with this data. Since we're using a limit here, what's happening is we're getting randomly five items from the server, it's limiting on that, but it didn't sort them ahead of time. So we're sorting what we got from the server, which is probably not what we want. So, let's just fix this as well. What we're going to do is we're going to add a sort on our actual server as well, so we're just going to add this sort capability here, and now we should get our data sorted properly. And so now if I enter some data, let's enter let's say a 2, we're seeing that show up at the top. So we've got the sort in both places here because it does make sense to sort it on the client, but it also makes sense to sort it before we limit it on the server as well.
Testing Multiple Users
Sessions in Meteor operate a little differently than what you might be used to if you use Sessions in an ASP.NET or Java web application. Sessions in Meteor aren't designed to persist data during a single use of a browser, but instead are designed to persist data globally during the use of a Meteor application loaded on a single page. This means if you navigate to a different page, your session data is lost, but it also means that if Meteor updates the HTML or code of your application without reloading the entire page, you can still use the session data. Using Sessions, we can create applications that are able to have their code in UI completely changed while retaining the user's state information and data. This allows us to do a live upgrade of a Meteor application while the user is logged in, pretty cool. Sessions in Meteor are also reactive. This means that if we use data from a session in a template and the session data changes, the UI will automatically update to reflect the change, also pretty cool.
Adding Session Support
Up until this point, we've been relying on Meteor automatically updating our user interface when data, like our user or history collection data changes, but sometimes we might want to have this similar kind of auto updating functionality in our code. We can directly access the framework that Meteor uses to do this kind of updating while using computations. A Meteor computation is just some code that's rerun automatically when one or more of its dependencies change, so long as the dependencies are reactive objects, like collections or session data. We can use computations to write code that depends on data and automatically reruns when that data changes. In our app, we'll just use this to send some log messages when a user logs in or logs out, but anywhere you would want to monitor data for changes, and templates aren't going to work, computations are a good solution.
Adding A Computation
Okay, so let's go ahead and add a dependency that's basically just going log out to the console when a user logs in or logs out. And the way that we do this is we're going to use this Deps.autorun, and here we can pass in a function that's going to be automatically run when any of its dependencies, as long as they're reactive objects, change. So, we can just add a function and then what we're going to do is we're going to say, if(Meteor.user), that'll give us our Meteor user, so if there is a Meteor user that's logged in. Then we're going to do console.log and we'll say "User logged in". And then, we're going to do Meteor.user.profile.name, that's going to give us the actual user name. Then, we'll put in else and we'll say else console.log("User logged out"). We'll go ahead and save this, and now what's going to happen is this Meteor user is a reactive object, and so if it changes, the status of this changes, so there is a user, there isn't a user, it's going to rerun this function and so it's going to behave differently whenever a user's logged in versus when they're logged out. And even if their profile name changed, it would also rerun, but that's not likely to happen. So let's go ahead and go into our application and remember we're logged into the console here, so you can already see a couple of debug messages, but I'm going to go ahead and ‘Sign Out' and we get this User logged out, then I'm going to ‘Sign in', and we get this ‘User logged in: John Sonmez'. So this seems like pretty simple functionality, and we use this in a fairly simple way, but this is pretty amazing when you think about it. We didn't have to write code specifically to respond to a user logging in or logging out. If we look at our code, what happened was, since we've put this in this Deps.autorun and we have this Meteor.user, it's automatically detecting, ‘Hey, I'm dependent on the value of this', and if this changes, then I need to rerun this code. So this is really a powerful concept. If you've used the observer pattern, or the observable pattern, you're probably already familiar with this to some degree, but you've had to implement that logic yourself, but because Meteor is handling all of this for us, it's just a simple way to basically monitor changes and automatically run code and that's really one of the key things that Meteor is built off of. Our templates are using this capability and we have the capability to manually add this to our application as well.
Creating A Meteor Method
Okay, so let's go ahead and change it so that this functionality that we have, that is adding an amount, is going to use a Meteor method. So the first thing we're going to do is we're going to create our Meteor method, and I'm going to create it outside of this ‘if (Meteor.isClient)' or this ‘if server code' because we need this Meteor method to exist on both sides. And we're going to talk about this a little bit more later, but it's basically going to be executed by both the client and the server. Then the server is going to tell the client what actually happened, which might actually conflict with the client data, so it might overwrite that data, and this is really going to come into play when we start talking about latency. But for now, let's just create a simple method; we're just going to do Meteor.methods and then we're going to pass in an object, and within this object we can declare our method. So, we're going to make one called addProtein, and then here, we're going to say that this is a function, and it's going to take an amount as a parameter. That's all we're going to need because we can detect the userId ourselves. And then inside here, what we're going to do is we're going to call ProteinData.Update. In fact, let's just go ahead and take our code because it's going to be very similar to what we're doing already, and we're going to do our update and our insert. We'll leave this Session setting here because that really is part of the client of clicking the button, it doesn't really have to do with the data, we don't really need to secure that. So, let's go ahead and Paste this in here and let's fix this squiggly, and what we're going to do now is we do need to change this a little bit. We were using this this._id because we had the context, remember, in our template with this ‘with' here and this addAmount, but we don't have that anymore. Instead, what we can do though is we can just do an update based on a userId, so we can say, just like we did with the filter, userId: this.userId. We're essentially applying a filter here just like you would do an update statement in SQL and you say where, we're essentially saying, ‘where userId equals this.userId'. And remember, this userId gives us the userId of the currently logged-in user. So, that should do our update, and then our insert into History is already using that, this.userId.
Calling The Meteor Method
Okay, so let's revisit that latency that I talked about before. I'm just going to Copy and Paste some code that's going to save us a little bit of time and I'm going to explain exactly how this is going to work. So, I'm going to go into our Meteor method, and inside here, before we do anything, I'm going to add this code. What this code is going to do is it's going to figure out if it's running on the client or if it's running on the server, and the way it does this is we use this isSimulation. So, if we are running on the client, isSimulation will be true because, remember, this latency compensation, what it's doing is when we're running this method on the client, we're doing a simulation, we're trying to predict what the server's going to say so that they don't have to wait. So it seems like Meteor apps always update automatically, and hopefully the server's going to give us the same result and nothing's going to change and the user will never know that we actually had to make a call to the server. But, when we're running on the server, this isSimulation is going to be false, so it gives us this ability to do something slightly different on the server versus the client. And I've put in some code here, so if not isSimulation, so if we're running on the server, then I'm using this node fibers/future, which is basically just a way to set a timeout or to basically set a delay. It's like asleep, we're just going to sleep for essentially 5 seconds here, and then we're going to go ahead and go. And in fact, I'll set this delay to be about 3 seconds just to make it a little bit faster on video. Now, if we're not isSimulation, we're going to change the amount, we're going to fudge the amount and make it 500, no matter what it was it's going to be 500. So, what this will allow us to do is that when we run this on the client, it's immediately going to update the UI as if the answer was 500, because we'll be running in Simulation so it'll hit this else block, but then it's going to make a call down to the server. The server's going to run the same code, it's going end up having to wait for 3 seconds, and then it's going to actually give us the real answer where it didn't change the amount, the real amount. So then, the server's going to send us back its result and we're going to say, Oh wait a minute, the server says we're wrong, let's update to what the server says. So let's go ahead and test this out, we'll just go ahead and open up our application. Okay, let's say we enter an amount like 5. I'm going to click ‘Add Protein' and you can see that it says 500 and our Total went up to 623, and then automatically the server came back and corrected that. Let's watch that again. So I'm going to Add 10, and we've got 500 showing up in the history, and then 628 for the Total, and the server came back and fixed that. So there's a lot of different ways that you could use this functionality. You could basically make it so that you show some kind of a message to the client, letting them know that you're getting the data from the server; you can just go ahead and predict what the data's going to be; you can have a different result or have some kind of indicator, maybe if you're posting a message, maybe it could say Invalidated, and then when it comes back from the server, it could say Validated. There's a lot of ways you can use this, but it's really neat because it allows you to make your application respond instantaneously, even if it's having to go back to the server, which is something I haven't really seen before and I really like the way that this is implemented. So think about this if you want to make your app really responsive of using this capability.
Adding A Minus Button
Okay, so the last thing we're going to do is we're going to take a quick look at some basic, basic permissions and we're going to do this by actually adding another button to our application. So we're just going to add this button that's going to allow the user to do a quick subtract. And I'm going to Copy some of this code to save us some time. So, we're just going to put in a new button, it's going to be called quickSubtract, and it is going to have a value of -100, so it's just going to say -100 on it. And the idea would be, oops, I didn't really mean to add that protein or I want to just subtract 100. You could use this for whatever purpose you want, I'm just going to use this to demonstrate our ability to check the security because we're going to run this code on the client as opposed to addAmount, which we made run on the server. Now one quick thing before we get into any of the security, is the security applies to the client. You need to remember this because, for example, if we try to add security in our addAmount, it wouldn't work because the Meteor platform assumes that if the code runs on the server, it's already validated and it's okay. It doesn't do any kind of security checks other than what you put in place, but if it runs on the client, it will check against these security rules. And remember, by default, we're allowing all operations. So I'm actually going to put in some security that's going to not allow all operations and we'll see how to do that next. So, what we want to do is to go ahead and implement this quickSubtract real quick and I'm just going to Copy and Paste this code, so we're going to put this in our Template.userDetails events. Right here where we have this addAmount, I'm just going to put a comma, and now we're going to add another event handler for this quickSubtract, and let's go ahead and add our bracket. Oaky, so now we have quickSubtract and we have this preventDefault in here, and we're just doing ProteinData.update and we're just incrementing the total by -100. So, we can run this code as is, and let's just check this out to see if this works. We can just click this and it subtracted by 100, and I can go into the negatives here, but now let's go ahead and prevent it from going into the negative. We'll wait for this to come back and we're in the positive, so now we're going to add some very simple security to deny the action if it takes us to the negative.
Adding A Deny
Okay, so now we've built out our Protein Tracker application and covered most of the major features of the Meteor platform in APIs. We can now create Meteor applications that allow for users to log in, we can manipulate data for the application, and we can use templates and reactive objects to automatically change our UI when data changes, but there is still more we can do. We haven't seen how to deploy our application yet and we haven't utilized the community-contributed projects we can find on the Atmosphere Repository. Up next, I'll take you through the process of deploying your Meteor application, installing Meteor on a Mac instead of a PC, and using Meteorite to get third-party libraries and extend our application. Thanks for joining me and take care.
Deploying in Meteor is both easy and difficult. Let me explain. We can deploy directly to Meteor's own servers, which allow us to freely host an app for test purposes with a single, simple command, but if we want to deploy Meteor to our own server, we have to do a little bit of work to package the application and make sure we have all the prerequisites installed. Not extremely difficult, but not nearly as streamline as the Meteor Server Route, and hopefully this will change in the future. I'll be showing you how to do both next. First, we'll deploy to the Meteor Servers, then we'll deploy our application to a Linux machine in the cloud running on DigitalOcean, a cloud provider that I like to use.
Deploying to Meteor
Okay, so now we're going to start off by deploying our Meteor application to the Meteor Server. And this is the easier way to do the deployment, we can actually put our application right on the Meteor Servers and we can use this for test purposes, but I wouldn't recommend that you do it for more than test purposes because you'll probably get in trouble and they'll probable delete your application if a lot of users start using it and taking up a lot of bandwidth, since it is free. Now, one thing we'll need to do before we do this is we're going to need to get rid of the code that was in this not isSimulation. If we leave this in here, we'll get an error, because we can't really utilize a package, a Node package on the fly inside of Meteor in production. It's insecure and so we'll get an error here. So, but we don't really need this code, that was just a delay. You can leave this amount = 500 in this code if you want, and if we have some kind of latency issue, you'll actually be able to see this flash up to 500 real quick before the server updates it. Now the other thing we need to do is, remember, we talked about the permissions and we said that, by default, when we're developing in Meteor, we're in an insecure mode, meaning that all operations on the MongoDB were allowed from the client. Now when we go to production, it's not going to be an insecure mode, we're going to have to explicitly allow whatever we want. And if you notice here, remember we're doing this insert, we've got this insert that's still happening on the client-side, this ProteinData.insert to insert new data. So this is going to be denied if we don't add an allow. So what we're going to do is we're going to add a security declaration, we're going to say ProteinData.allow, instead of deny. And here we can do the same type of format, we're just going to say, we're going to allow an insert, and then we specify the function that determines whether it's allowed. It's going to take a userId and then the data, and then we're going to just check if(data.userId == userId) of the user trying to do this, then we're going to return true, yeah it's allowed. Otherwise, we're going to return false, no it's not allowed. So let's go ahead and save that. And then what we're going to do is we're just going to do ‘meteor deploy' and then we're going to say proteintracker.meteor.com. Now you can use whatever name you want here, this is the free hosting on Meteor's platform. You can also use your own domain name; you just have to set the DNS record to go to origin, not meteor.com. We're just going to make this work at proteintracker.meteor.com though. So, I'm just going to go ahead and run this and this should end up packaging our application, it'll do this Bundling step, and then it will upload it and run it. Okay, so now our app is being served from proteintracker.meteor.com.
Testing The app on Meteor
Okay, so let's go ahead and test this out; we're just going to go to proteintracker.meteor.com, and you can see we need to configure our Google Login. I went ahead and already created a new Client ID that has the proteintracker.meteor.com address here, you can see here, so I just need to add the Client ID and then the secret. And now if we Save this, we should be able to run our app. So, I'm signed in, I can go ahead and Add some protein, and you can see that 500 flashing up there real quick, but then the server comes back with a response pretty quickly and updates this. So this is working, all of our functionality seems to be working as well. We've got our data saved and then our -100 is actually not going to work, even if I were to put in a positive 100, because we never allowed it. We have that deny in there, but we'd have to add an allow for that if we wanted to get that to work, and that's a good test to go ahead and try out on your own to see if you can get this -100 button working. You could do it one of either two ways; you could either create an allow for it or you could move it down to a server call, which might actually be a better way, just use a Meteor method.
Creating The Server
Okay, so we finished up the easy deploy, but now we're going to do the more difficult deploy, which is we're going to deploy to a Linux server in the cloud. Now I'm in my DigitalOcean account. If you want to sign up for an account, you can go to digitalocean.com and then you can sign up there, it's pretty affordable. I really like DigitalOcean because it just gives you the ability to create a Linux server in the cloud very easily and you can only pay for what you use. So, for example, if you create a Droplet, which is a Linux machine, and then you just use a few hours, you'll only get charged by the hour of time. So, I'm going to go ahead and Create a new Droplet, and I'm going to call this MeteorBox. And then I'm just going to choose this smallest size, you can see this is less than a penny an hour, so that's pretty neat. It's not really going to cost us much to test this out. I'm just going to choose New York and let's get the latest version of Ubuntu. And we're just going to go ahead and Create our Droplet. So this takes a little while to do and you'll get a root password that you can use to log in. Okay, so now we have our box, and if you want to connect to this using something like Putty, you can. I'm just going to keep things simple for this demonstration and we're going to access this from the console directly here from the website. And so, I'm just going to go ahead and login with root, and then I'm going to put in the Password that was emailed to me. Okay, so I'm signed into the Box and now we're going to have to do some installations in order to get everything set up to be able to deploy to this Box.
Setting up The Linux Machine
So I'm just signed in as root; you probably don't want to use a Linux machine as root, but we're going to do it for this demonstration to keep things easier. If you aren't signed in as root, you probably need to do this pseudo command, but we can just get away with doing a regular command, so we're just going to do apt-get install, and we're going to install MongoDB. So, we're going to say mongodb and then we'll say yes. So now we should have MongoDB installed and then the next thing that we're going to need is we're going to need Node.js, and the way that we're going to do this is we're going to get the earlier version of Node.js, because Node.js tends to update before Meteor, so we don't want to break things inside of Meteor by using a newer version of Node.js. So, we're just going to do a couple of commands here. We're going to do add-apt-repository, and you may have a problem with this, so before we do this, let's do one command that's going to make sure that we have our add-apt-repository command. And this command is apt-get install software-properties-common. And you might already have this, so you might not need to do this, but to be sure let's go ahead and take this one step at a time. And then the next thing that we're going to do is we're going to go ahead and do our add-apt-repository and then we're going to say ppa:chris-lea/node.js-legacy and this will give us the repository for the legacy version of Node.js. So let's go ahead and add this. And now, what we're going to do is we're going to do an apt-get update to make sure we have everything for our apt-get command. Okay, so we should have the latest information from that repository, and so now at this point we're going to go ahead and install Node.js, so we're just going do apt-get install node.js. And this will install Node.js and we can also do an apt-get install npm just to make sure we have the Node Package Manager as well. Okay, so now we have all the prerequisites installed on our Linux Box.
Getting The Project
Now the next thing I'm going to do is I'm actually going to zip up our application and I'm going to drop it in Dropbox folder so that we can get it easily from that machine. There's a lot of different ways you could do this, but I'm going to basically take our Protein Tracker and I'm just going to take the entire zip of this and I'm going to Copy this to a Dropbox Public folder. And so I'm going to grab the link for this, so I'm going to Copy this public link. And it'll take a second for this to upload to Dropbox, but once it does, I'm going to use this wget command and I'm going to get that link. Okay, so now if we use wget, we should be able to get that file and it'll just get copied locally, this is just a quick way to get a file without having to use FTP. You could use FTP if you want to, but this is a little bit quicker. So now if we do an ls, we can see we have our ProteinTracker.zip and I can just do unzip ProteinTracker.zip. Now the reason why I'm doing this, if we take a look here, is because we actually are going to do our packaging of our app on the Linux machine. Now if you had a Linux machine that you were developing on, you could actually package it and just send up the package file and then just run it from there, but because we're running on a different architecture, we do need to make sure that we package it with the correct version of Node for that particular architecture. So it's a lot easier to just go ahead and take the whole project and move it up.
Installing Meteor on Linux
Okay, so the next step we're going to do is we're going to actually install Meteor on this machine, so we're just going to do a curl https:// and then we're just going to do install.meteor.com. pipe to /bin/sh. And so this will actually install Meteor, and now we have Meteor, so we should be able to just type Meteor and we're going to go ahead and cd into that ProteinTracker directory. And we're just going to run Meteor from here to test things out first, so we want to make sure that this is actually working. We're running this in Development mode so it's running on Port 3000, so I'm just going to take this IP address and let's make sure that's still running, and let's Paste this in here. (Typing) And we need to make sure we're on Port 3000. So you can see our app is up here and it's actually using our other database. So we're going to have a little bit of a problem because it's not going to connect to localhost 3000, but we're okay because we have Meteor running on our port. So let's go ahead and close down Meteor, and now we actually want to get the Production version running. So we're going to need to bundle our app and then actually launch this with Node.
Deploying to Digital Ocean
Okay, so now what we're going to do is from inside our directory, we're just going to do ‘meteor bundle', that's going to bundle up our app, and we're going to tell it to put it at /bundle.tgz. And it'll be back one directory from here. And this is basically going to turn our app into a Node application. Oaky, so now that it's bundled, we're going to back one directory. Now we can see this bundle.tgz and we're going to un-tar this, so we're just going to say tar --zxvf, and then specify our bundle. This will extract everything. So now we're going to go ahead and run this. So what we're going to do is we're going to type PORT=80 for the port number and then we're going to set up the MONGO_URL. We're just setting up environment variables here, so we're going to set this to mongodb://localhost: and the default port is 27017. And then we're going to say our app name, which will be ProteinTracker, so we'll have our own MongoDB instance there. And then we want to do node bundle/main.js. So let's go ahead and run this and you can see it says it's listening, so now we can test this out. I'm just going to go ahead and Copy this address and Paste here. And you can see our application is running. And there is one small issue, this button doesn't work, but the reason why, if we look at our console and you'll want to check this for errors, is that it's saying that our ROOT URL isn't set in the server environment. So, we can fix that real quick. Let's just go ahead and go in there and we're going to stop this, and with our run here, we're going to add one more environment variable. So, before we run our Node command, let's go ahead and add a ROOT URL. And I wanted to point this out because this is somewhat confusing. If you look online for documentation, you'll probably find some places where the ROOT URL's not being specified. So we're just going to do http and then we'll need our address, which will be 126.96.36.199, and then node bundle/main.js. And now this should work, it's listening again. And if we go in here and reload this, so now you can see, when we go to our page here, we don't have an error in our console anymore. We can reload our page, no error, and we can click this and we can configure this. So we're not going to go through the process of configuring it on here, it's the same exact as we did on the Meteor Server and we did locally, but go ahead and test that out and make sure that it works. And that's how you get this set up on your own server. A few steps here, but not too many, and it's definitely something that is doable if you're trying to get a Meteor application up. I'd recommend testing things out on the meteor deploy first because that's a lot easier though.
Okay, so next we're actually going to install Meteor on a Mac and we're actually going to install Meteorite as well. So I'm on my Mac and I've opened up a terminal window. I already have Git installed, you want to make sure that you do have Git installed; if you don't, you can just do a search for Git, go to the home page, and then the install is pretty straightforward. Right after you install Git, you may need to re-launch the terminal window so that you can actually use Git, because Meteorite is going to utilize Git. So what we're going to do, first of all, is we're just going to get Meteor installed, and this is actually pretty simple, it's the same exact command that we did on our Linux Box. So we're just going to do curl and then https:// and then install.meteor.com and pipe this to /bin/sh. So that's going to install Meteor for us and what we're actually going to be doing is, next we're going to install Meteorite, which is that package manager that'll allow us to access packages from Atmosphere. And we'll talk about that a little bit more in a second here. And we'll also be installing the router package with Meteorite so that we can add routing to our application. Okay, so we've just about gotten Meteor installed here and now we're ready to move on.
Meteorite is a version manager and package manager for Meteor that makes it easy to run different versions of Meteor and use packages from the Atmosphere Package Repository. We haven't been able to use Meteorite so far because we've been doing things on Windows, and Meteorite doesn't run there, but now that we have Meteor installed on a Mac, we can install Meteorite and use it to get additional packages from Atmosphere. It turns out Meteorite is pretty easy to install. All we have to do is use the Node Package Manager and we can do it with a single command, NPM install-g Meteorite. We also need get installed in order to make use of Meteorite, since it uses get to get the packages we install with it.
Okay, so we've mentioned Atmosphere a few times, but we haven't actually talked about what it is. So, I figured the best way to talk about Atmosphere was to just show you what it looks like. So if you go to atmosphere.meteor.com, you'll find that there's an app out here that is actually a Meteor app, because notice this is at meteor.com, and inside here it has all of the community-created packages. And you'll find quite a few different packages here; if you look through this list, there are quite a few in here, a lot of stuff. So you're going to find pretty much anything that you're going to need. Even though Meteor's not that old, it almost seems like the packages here are more mature than Meteor itself. So, you can search these packages; for example, we were going to use a routing package. So if I look for router here, you can see that there is this Reactive Router, there's iron-router, there's a few different routers that you can use in here. You can find all kinds of stuff. If you search for html5, you can find things like bootstrap, popcorn, all kinds of stuff, even chartjs in here. So all you have to do to install one of these is just use that MRT add and then the package name, and once you do that, you'll get that package added to your Meteor application automatically. Just like with Meteor itself where we did ‘meteor add' and then the package name, you can get a package that is one of the official packages for Meteor, but if you just have Meteorite installed and do MRT and then add and then the package name, you'll install that. And there is some instructions here that tell you how to get this set up and just give you an example. This ‘mrt add moment', you can also specify the version if you want a specific version.
So, now we have Meteor installed and now we need to install Meteorite. Now in order to install Meteorite, you just have to do a pseudo and then you should be able to do npm install-g meteorite. And this is going to use the Node Package Manager to get Meteorite, because Meteorite is a Node Package. And then Meteorite is actually going to wrap Meteor. So now we could actually do mrt and we're basically running Meteor through the Meteorite command. So I'm in my Dropbox folder and inside here I have another folder called WIP and then inside here I have our ProteinTracker application. So if I go in there, I can actually do mrt, and that will run Meteor from this. So you can see it's running on localhost port 3000. And I can open up my Chrome window and just go to localhost port 3000 here, and you can see that we've got Protein Tracker and I can Sign in to the app and it's got the data that we already had because, remember, this is a Dropbox folder so it's sharing that data.
Now while we're here on the Mac side, what I'm going to do is I'm actually going install the router into our application. So I'm going to stop our application and I'm just going to do mrt add router. And this is going to use get; if you get an error here that says it can't check something out, it might be because you're missing get, but now you can see that it has gotten router, and it's gotten all the dependencies for router, you can see that router actually depends on this page js-ie support and this HTML5-History-API. So it's installed everything and so now it is in our application, we can run our app, and we can use the router capability.
Okay, so let's go ahead and add another route here to go to our Settings page. So, what we're going to do is we're just going to make a very simple settings screen and you can fill in the rest as an exercise. I'm just going to create a new Template here and I'm going to give it the name settings. And then we'll end this template tag. (Typing) And then inside here, it's going to be really simple. All we're going to do is just have an h2 and we'll say settings and then we'll end the h2. And here you could actually put the Goal, this is a good exercise, make it so that they can change the Goal. For now I'm just going to leave this blank and you can fill that in. And then I'm going to add an href, I'm going to do