All notes


Start with React react.

# To install meteorjs:
curl | sh

meteor create simple-todos
cd simple-todos
meteor # Run the app.
# -p, --port
meteor -p 3000

meteor npm install --save react react-dom



The server process will be suspended just before the first statement of server code that would normally execute.

In order to continue execution of server code, use either the web-based Node Inspector or the command-line debugger.

Breakpoints can be set using the debugger keyword, or through the web UI of Node Inspector (“Sources” tab).

The server process debugger will listen for incoming connections from debugging clients, such as node-inspector, on port 5858 by default. To specify a different port use the --debug-port option.

Attach client inspector.

For Chrome DevTools 55+:

Option 1: Open "chrome://inspect" in a Chromium-based browser. Click the Configure button and ensure your target host and port are listed. Then select your Node.js app from the list.
Option 2: Install the Chrome Extension NIM (Node Inspector Manager).

Debugger did not attach after 5 minutes; continuing

try meteor --inspect or meteor --inspect-brk.


meteor mongo

# This opens a console into your app's local development database. Into the prompt, type:
# db.tasks.insert({ text: "Hello world!", createdAt: new Date() });


meteor npm install lodash --save

Why use "meteor npm" instead of just "npm"


When meteor shell is executed in an application directory where a server is already running, it connects to the server and starts an interactive shell for evaluating server-side code.

Import modules

import { CT } from './imports/ct';
CT.findOne(someId); // Success!



Template tags

Double braced template tags

Double-braced template tags, e.g. {{pageTitle}}. When they are within block template tags, most likely they refer to properties of the current item. Or they could refer to template helpers.

{{frob a b c verily=true}}
// calls:
frob(a, b, c,{verily: true}))

Inclusion template tags

Inclusion template tags {{> templateName}. Everything inside "template" tags is compiled into Meteor templates, which can be included inside HTML with {{> templateName}} or referenced in your JavaScript with Template.templateName.

Block template tags

Block template tags, e.g. {{#each}}, {{#each}} and {{#if}}. They let you add logic and data to your views.

Also, the body section can be referenced in your JavaScript with Template.body.

Triple-braced template tags

{{{content}}} - Triple-braced template tags are used to insert raw HTML.


  <div class="container">
      <h1>Todo List</h1>
      <form class="new-task">
        <input type="text" name="text" placeholder="Type to add new tasks" />
      {{#each tasks}}
        {{> task}}
<template name="task">

////////// imports/ui/body.js:

import { Template } from 'meteor/templating';

import { Tasks } from '../api/tasks.js';
import './body.html';

//----- We can pass data into templates from JavaScript code by defining "helpers".
// Method 1: use array.
//  tasks: [
//    { text: 'This is task 1' },
//    { text: 'This is task 2' },
//    { text: 'This is task 3' },
//  ],

// Method 2: use MongoDB:
  tasks() {
    // Show newest tasks at the top
    return Tasks.find({}, { sort: { createdAt: -1 } });
  'submit .new-task'(event) {
    // Prevent default browser form submit
    // Get value from form element
    const target =;
    const text = target.text.value;
    // Insert a task into the collection
      createdAt: new Date(), // current time
    // Clear form
    target.text.value = '';

////////// imports/api/tasks.js

import { Mongo } from 'meteor/mongo';
export const Tasks = new Mongo.Collection('tasks');

////////// server/main.js

import '../imports/api/tasks.js';

////////// client/main.js

import '../imports/ui/body.js';

Template helpers

Server-side calculation

//---------- Template
<template name="analytics">
  {{#with analyticResult}}
    ... Do something ...

//---------- server/main.js
  serverSideComputation: function() {
    var result = {}; = "Hello "; = "World!";
    return result;

//---------- Using the Session{
  analyticResult: function() {
    if (Session.get('someIdentifier') === undefined) {'serverSideComputation', function(err, data) {
        Session.set('someIdentifier', data);
    return Session.get('someIdentifier);

//---------- Using a Reactive Variable = function() {
  this.someIdentifier = new ReactiveVar(false);
  analyticResult: function() {
    if (Template.instance().someIdentifier.get()) === false) {'serverSideComputation', function(err, data) {
    return Template.instance().someIdentifier.get();


Collections collections.

// Common code on client and server declares a DDP-managed Mongo collection.
const Chatrooms = new Mongo.Collection('chatrooms');
const Messages = new Mongo.Collection('messages');

// Return an array of my messages.
const myMessages = Messages.find({ userId: Meteor.userId() }).fetch();
// Create a new message.
Messages.insert({ text: 'Hello, world!' });
// Mark my first message as important.
Messages.update(myMessages[0]._id, { $set: { important: true } });

If you pass a name when you create the collection:

* On the server, a collection with that name is created on a backend Mongo server.
* On the client, a Minimongo instance is created. Minimongo is essentially an in-memory, non-persistent implementation of Mongo in pure JavaScript.
* When you write to the database on the client (insert, update, remove), the command is executed locally immediately, and, simultaneously, it’s sent to the server and executed there too. This happens via stubs, because writes are implemented as methods.

find, findOne

"find" returns a cursor. It does not immediately access the database or return documents.

Cursors provide fetch() to return all matching documents, map() and forEach() to iterate over all matching documents, and observe() and observeChanges() to register callbacks when the set of matching documents changes. Cursors also implement ES2015’s iteration protocols.

Cursors are a reactive data source.

Any change to the collection that changes the documents in a cursor will trigger a recomputation. To disable this behavior, pass {reactive: false} as an option to find.

"findOne" finds the first document that matches the selector, as ordered by "sort" and "skip" options. Returns undefined if no matching document is found.

Equivalent to find(selector, options).fetch()[0] with options.limit = 1.



// Print the titles of the five top-scoring posts.
const topPosts = Posts.find({}, { sort: { score: -1 }, limit: 5 });
let count = 0;
topPosts.forEach((post) => {
  console.log(`Title of post ${count}: ${post.title}`);
  count += 1;

ReactiveVar reactive-var.