#Meteor Chat Project
For OSX:
curl https://install.meteor.com/ | sh
For Windows:
Visit: https://www.meteor.com/install
meteor create meteor-chat
cd meteor-chat
meteor
Visit: http://localhost:3000/
Replace existing content with the following:
<!-- client/main.html -->
<head>
<title>A Simple Meteor Chat App</title>
</head>
// client/main.js
import '../imports/ui/home.js';
Create a new folder called imports. Inside "imports", create a folder called "ui".
<!-- imports/ui/home.html -->
<body>
{{> home}}
</body>
<template name="home">
<p>There is content here</p>
</template>
//imports/ui/home.js
import './home.html';
Template.home.onCreated(function homeOnCreated() {
});
Template.home.helpers({
});
Template.home.events({
});
Add User Accounts:
meteor add accounts-ui accounts-password
<!-- imports/ui/home.html -->
<body>
{{> loginButtons}}
{{> home}}
</body>
<template name="home">
<p>There is content here</p>
</template>
Configure accounts-ui:
Create a file imports/startup/accounts-config.js
//imports/startup/accounts-config.js
import { Accounts } from 'meteor/accounts-base';
Accounts.ui.config({
passwordSignupFields: 'USERNAME_ONLY',
});
//client/main.js
import '../imports/startup/accounts-config.js';
import '../imports/ui/home.js';
//imports/ui/body.js:line1
import { Meteor } from 'meteor/meteor';
Create a user and open the console:
Meteor.userId();
//should return => "J8iYQwkZiKxe9pTLt"
Create a folder called lib
. Put a file inside called collections.js
with the following contents:
Message = new Mongo.Collection('messages');
Create a file called methods
in the server folder
//server/methods.js
Meteor.methods({
'insertMessage': function(text){
Message.insert({
text: text,
user: Meteor.user(),
created_on: new Date().getTime()
});
}
});
Add the form to the page:
<!-- imports/ui/home.html -->
<body>
{{> loginButtons}}
{{> home}}
</body>
<template name="home">
<h1>Current Messages</h1>
<ul id="message-container">
{{#each message}}
<li>{{this.user.username}} - {{this.text}}</li>
{{/each}}
</ul>
{{#if userLoggedIn}}
<h2>Create a message</h2>
<form id="new-msg">
<input name="message" type="text">
<button>Submit</button>
</form>
{{/if}}
</template>
Setup events and helpers:
//imports/ui/home.js
import { Meteor } from 'meteor/meteor';
import './home.html';
Template.home.onRendered(function() {
console.log('created');
});
Template.home.helpers({
'message' : function(){
return Message.find({}, {sort: {created_on: -1}, limit: 10}).fetch().reverse();
},
'userLoggedIn': function(){
return Meteor.user();
}
});
Template.home.events({
"submit #new-msg": function(e){
e.preventDefault();
var message = $("[name='message']").val();
Meteor.call('insertMessage', message);
setTimeout(function(){
$("[name='message']").val('');
}, 100);
}
});
To get materialize setup add these lines to .meteor/packages
:
fourseven:scss
poetic:materialize-scss
Add this line to your client/main.html
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
Rename client/main.css
to client/main.scss
Add these contents:
@import "{poetic:materialize-scss}/sass/components/_color.scss";
$primary-color: color("grey", "darken-4");
@import "{poetic:materialize-scss}/sass/materialize.scss";
main{
padding-top: 50px;
}
.full-w{
width: 100%;
}
Remove accounts-ui
meteor remove accounts-ui
Add meteor user accounts and ironrouter to your .meteor/packages
file.
iron:router
useraccounts:materialize
useraccounts:core
useraccounts:iron-routing
Create your routes:
//lib/router.js
Router.configure({
layoutTemplate: 'masterLayout',
yieldTemplates: {
navbar: {to: 'navbar'},
footer: {to: 'footer'},
}
});
Router.map(function(){
this.route('/', {
path: '/',
template: 'home',
layoutTemplate: 'masterLayout',
});
// Sign In Route
AccountsTemplates.configureRoute('signIn', {
name: 'signIn',
path: '/sign-in',
template: 'signIn',
layoutTemplate: 'masterLayout',
redirect: '/',
});
// Sign Up Route
AccountsTemplates.configureRoute('signUp', {
name: 'signUp',
path: '/sign-up',
template: 'signUp',
layoutTemplate: 'masterLayout',
redirect: '/',
});
// Sign Out Route
this.route('/sign-out', function(){
Meteor.logout(function(err) {
if (err) alert('There was a problem logging you out.');
Router.go("/");
});
Router.go("/");
});
// adjust user fields
AccountsTemplates.removeField('email');
var pwd = AccountsTemplates.removeField('password');
AccountsTemplates.addFields([
{
_id: "username",
type: "text",
displayName: "username",
required: true,
minLength: 5,
},
]);
AccountsTemplates.addField(pwd);
});
Create a layout folder in client/layouts
Create your master layout:
<!-- client/layouts/master_layout -->
<template name="masterLayout">
{{> yield region='navbar'}}
<main>
{{> yield}}
</main>
{{> yield region='footer'}}
</template>
Create your partials for materialize:
Navbar:
//imports/ui/navbar.js
import { Template } from 'meteor/templating'
import { Meteor } from 'meteor/meteor';
import './navbar.html';
Template.navbar.onRendered(function() {
console.log('created');
$(".button-collapse").sideNav();
});
Template.navbar.helpers({
'userLoggedIn': function(){
return Meteor.user();
}
});
<!-- imports/ui/navbar.html -->
<template name="navbar">
<nav>
<div class="container">
<div class="row">
<div class="col s12">
<div class="nav-wrapper">
<a href="/" class="brand-logo">Logo</a>
<a href="#" data-activates="mobile-nav" class="button-collapse"><i class="material-icons">menu</i></a>
<ul class="right hide-on-med-and-down">
{{#if userLoggedIn}}
<li><a href="/sign-out">Sign Out</a></li>
{{else}}
<li><a href="/sign-in">Sign In / Up</a></li>
{{/if}}
</ul>
<ul class="side-nav" id="mobile-nav">
{{#if userLoggedIn}}
<li><a href="/sign-out">Sign Out</a></li>
{{else}}
<li><a href="/sign-in">Sign In / Up</a></li>
{{/if}}
</ul>
</div>
</div>
</div>
</div>
</nav>
</template>
Footer:
//imports/ui/footer.js
import { Template } from 'meteor/templating'
import { Meteor } from 'meteor/meteor';
import './footer.html';
Template.footer.onRendered(function() {
console.log('created');
});
<!-- imports/ui/footer.html -->
<template name="footer">
<footer class="page-footer">
<div class="container">
<div class="row">
<div class="col l6 s12">
<h5 class="white-text">Footer Content</h5>
<p class="grey-text text-lighten-4">You can use rows and columns here to organize your footer content.</p>
</div>
<div class="col l4 offset-l2 s12">
<h5 class="white-text">Links</h5>
<ul>
<li><a class="grey-text text-lighten-3" href="#!">Link 1</a></li>
<li><a class="grey-text text-lighten-3" href="#!">Link 2</a></li>
<li><a class="grey-text text-lighten-3" href="#!">Link 3</a></li>
<li><a class="grey-text text-lighten-3" href="#!">Link 4</a></li>
</ul>
</div>
</div>
</div>
<div class="footer-copyright">
<div class="container">
© 2014 Copyright Text
<a class="grey-text text-lighten-4 right" href="#!">More Links</a>
</div>
</div>
</footer>
</template>
Sign in:
//imports/ui/signin.js
import { Template } from 'meteor/templating'
import { Meteor } from 'meteor/meteor';
import './signin.html';
Template.signIn.onRendered(function() {
console.log('created');
});
Template.signIn.events({
'click #at-signUp': function(){
Router.go('sign-up');
}
});
<!-- imports/ui/signin.html -->
<template name="signIn">
<main class="signinbody">
<div class="container">
<div class="row row-pad">
<div class="col s12 m6 offset-m3 l6 offset-l3 white z-depth-1 login">
{{> atForm state='signIn'}}
</div>
</div>
</div>
</main>
</template>
Sign up:
//imports/ui/signup.js
import { Template } from 'meteor/templating'
import { Meteor } from 'meteor/meteor';
import './signup.html';
Template.signUp.onRendered(function() {
console.log('created');
});
Template.signUp.events({
'click #at-signIn': function(){
Router.go('signin');
}
});
<!-- imports/ui/signup.html -->
<template name="signUp">
<main class="registerbody">
<div class="container">
<div class="row">
<div class="col s12 m6 offset-m3 l6 offset-l3 white z-depth-1 login">
{{> atForm state='signUp'}}
</div>
</div>
</div>
</main>
</template>
Refactor Home:
<template name="home">
<div class="container">
<div class="row">
<div class="col s12">
<h1>Current Messages</h1>
<ul id="message-container">
{{#each message}}
<li>{{this.user.username}} - {{this.text}}</li>
{{/each}}
</ul>
{{#if userLoggedIn}}
<h2>Create a message</h2>
<form id="new-msg">
<div class="input-field col s8">
<input name="message" type="text">
<label for="message">Message</label>
</div>
<div class="input-field col s4">
<button class="btn-large grey darken-4">Submit</button>
</div>
</form>
{{/if}}
</div>
</div>
</div>
</template>
Add Imports to client/main.js
import '../imports/ui/footer.js';
import '../imports/ui/navbar.js';
import '../imports/ui/home.js';
import '../imports/ui/signup.js';
import '../imports/ui/signin.js';
Delete imports/startup/accounts-config.js
###Step 7: Deploy!
Deploy To Heroku
- Set up your app to deploy to heroku with git.
- Set this repository as the buildpack URL:
heroku buildpacks:set https://github.com/AdmitHub/meteor-buildpack-horse.git
- Add the MongoLab addon:
heroku addons:create mongolab
- Set the
ROOT_URL
environment variable. This is required for bundling and running the app. Either define it explicitly, or enable the Dyno Metadata labs addon to default tohttps://<appname>.herokuapp.com
.
heroku config:set ROOT_URL="https://<appname>.herokuapp.com" # or other URL
Once that's done, you can deploy your app using this build pack any time by pushing to heroku:
git push heroku master
For your settings.json
on heroku run this command:
heroku config:add METEOR_SETTINGS="$(cat settings.json)"