StartupBus 2013 Day 5: Finals

On the final day of the StartupBus 2013, Americas hackathon competition, the judges had to choose two teams out of the six. Then, out of those two, they would pick one winner and one runner up.

On the final day of the StartupBus 2013, Americas hackathon competition, the judges had to choose two teams out of the six. Then, out of those two, they would pick one winner and one runner up.

Team GhostPost.io at StartupBus 2013
Team GhostPost.io at StartupBus 2013

Here are the six finalists from the previous day (to read more about that day and semi-finals go to my post: StartupBus 2013: Day 4, Semi-Finals):

  1. Grassroots.io (SF): kick-starter for activism campaigns (e.g., FixTheDMCA.org)
  2. GhostPost.io (SF): anonymous chat
  3. uSupply.me (Mexico): marketplace for construction industry
  4. NextChaptr (Chicago): book publisher with a kick-starter model
  5. CareerMob (NYC): website that helps military professionals find their civilian career
  6. Cloudspotting (Mexico): draw on photos of clouds
Team Grassroots.io at StartupBus 2013
Team Grassroots.io at StartupBus 2013

Everybody else was allowed to sleep in till 10am. An unheard of luxury, which came in handy for people who didn’t sleep well for the past week and went partying on the previous night in downtown San Antonio.

Then our pack rode shuttle buses to the same place at Rackspace HQ. We weren’t very lucky because our driver got lost, took narrow back roads, and drove in circles really slowly (more on this later).

StartupBus 2013 hacking
StartupBus 2013 hacking

The pitches of almost all of the finalists improved greatly. I especially liked how much improved Grassroots.io’s pitch (I wasn’t able to find the video but here is the GoAnimate clip). Unfortunately, I couldn’t say the same about the Cloudspotting or GhostPost teams’ pitches. They just weren’t able to replicate the success of the previous night. :-( It felt like the fun aspect of the crowd cheering and support wasn’t there. Maybe the audience wasn’t surprised any more?!

After some deliberation Robert Scoble, the famous racker evangelist, announced the runner up: NextChaprt; and the winner: CareerMob! The latter decision was unexpected for a lot of people (you could see it on their faces), and many complained that CareerMob doesn’t have anything live (even a website), and has no business model whatsoever. I guess the charisma of the Air Force lieutenant made the pitch and the whole idea sound reassuring. :-)

Famous Briefskate.com prototype
Famous Briefskate.com prototype

It was time to wrap up and go to South by South West (SxSW) interactive festival in Austin, Texas. Sadly for our West Coast team and other random people who joined our bus, we had the same driver that we had in the morning. We got lost a few times again, took the longest detours back to the hotel and around Austin airport and its military base. When somebody finally gave Google Maps to the drive, we arrived to the Austin Convention Center. This marked the final stop of the bus part of StartupBus 2013 adventure. Virtually all of us pledged not to ride any type of buses for at least a few months. :-)

GhostPost.io infront of the judges
GhostPost.io infront of the judges

Photos by Ruben Lemmens

Intro to Express.js: Simple REST API app with Monk and MongoDB

After looking at Google Analytics stats I’ve realized that there is a demand for short Node.js tutorial and quick start guides. This is an introduction to probably the most popular (as of April 2013) Node.js framework Express.js.

Why?

After looking at Google Analytics stats I’ve realized that there is a demand for short Node.js tutorial and quick start guides. This is an introduction to probably the most popular (as of April 2013) Node.js framework Express.js.

Express.js — Node.js framework
Express.js — Node.js framework

mongoui

This app is a start of mongoui project. A phpMyAdmin counterpart for MongoDB written in Node.js. The goal is to provide a module with a nice web admin user interface. It will be something like Parse.com, Firebase.com, MongoHQ or MongoLab has but without trying it to any particular service. Why do we have to type db.users.findOne({'_id':ObjectId('...')}) any time we want to look up the user information? The alternative of MongoHub mac app is nice (and free) but clunky to use and not web based.

REST API app with Express.js and Monk

Ruby enthusiasts like to compare Express to Sinatra framework. It’s similarly flexible in the way how developers can build there apps. Application routes are set up in a similar manner, i.e., app.get('/products/:id', showProduct);. Currently Express.js is at version number 3.1. In addition to Express we’ll use Monk module.

We’ll use Node Package Manager which is usually come with a Node.js installation. If you don’t have it already you can get it at npmjs.org.

Create a new folder and NPM configuration file, package.json, in it with the following content:

{
  "name": "mongoui",
  "version": "0.0.1",
  "engines": {
    "node": ">= v0.6"
  },
  "dependencies": {
    "mongodb":"1.2.14",
    "monk": "0.7.1",
    "express": "3.1.0"
  }
}

Now run npm install to download and install modules into node_module folder. If everything went okay you’ll see bunch of folders in node_modules folders. All the code for our application will be in one file, index.js, to keep it simple stupid:

var mongo = require('mongodb');
var express = require('express');
var monk = require('monk');
var db =  monk('localhost:27017/test');
var app = new express();

app.use(express.static(__dirname + '/public'));
app.get('/',function(req,res){
  db.driver.admin.listDatabases(function(e,dbs){
      res.json(dbs);
  });
});
app.get('/collections',function(req,res){
  db.driver.collectionNames(function(e,names){
    res.json(names);
  })
});
app.get('/collections/:name',function(req,res){
  var collection = db.get(req.params.name);
  collection.find({},{limit:20},function(e,docs){
    res.json(docs);
  })
});
app.listen(3000)

Let break down the code piece by piece. Module declaration:

var mongo = require('mongodb');
var express = require('express');
var monk = require('monk');

Database and Express application instantiation:

var db =  monk('localhost:27017/test');
var app = new express();

Tell Express application to load and server static files (if there any) from public folder:

app.use(express.static(__dirname + '/public'));

Home page, a.k.a. root route, set up:

app.get('/',function(req,res){
  db.driver.admin.listDatabases(function(e,dbs){
      res.json(dbs);
  });
});

get() function just takes two parameters: string and function. The string can have slashes and colons, for example product/:id. The function must have two parapemets request and response. Request has all the information like query string parameters, session, headers and response is an object to with we output the results. In this case we do it by calling res.json() function. db.driver.admin.listDatabases() as you might guess give us a list of databases in async manner.

Two other routes are set up in a similar manner with get() function:

app.get('/collections',function(req,res){
  db.driver.collectionNames(function(e,names){
    res.json(names);
  })
});
app.get('/collections/:name',function(req,res){
  var collection = db.get(req.params.name);
  collection.find({},{limit:20},function(e,docs){
    res.json(docs);
  })
});

Express conveniently supports other HTTP verbs like post and update. In the case of setting up a post route we write this:

app.post('product/:id',function(req,res) {...});

Express also has support for middeware. Middleware is just a request function handler with three parameters: request, response, and next. For example:

app.post('product/:id', authenticateUser, validateProduct, addProduct);

function authenticateUser(req,res, next) {
  //check req.session for authentication
  next();
}

function validateProduct (req, res, next) {
   //validate submitted data
   next();
}

function addProduct (req, res) {
  //save data to database
}

validateProduct and authenticateProduct are middleware. They are usually put into separate file (or files) in a big projects.

Another way to set up middle ware in Express application is to use use() function. For example earlier we did this for static assets:

app.use(express.static(__dirname + '/public'));

We can also do it for error handlers:

app.use(errorHandler);

Assuming you have mongoDB installed this app will connect to it (localhost:27017) and display collection name and items in collections. To start mongo server:

$ mongod

to run app (keep the mongod terminal window open):

$ node .

or

$ node index.js

To see the app working, open http://localhost:3000 in Chrome with JSONViewer extension (to render JSON nicely).

Tom Hanks' The Polar Express
Tom Hanks’ The Polar Express

Paste and Match Style on Mac OS X

Of course there are alternative combinations to ⌘ + V to Past and Match style but they differ from application to application and hard to use even if you can remember them.

If you don’t like the default behavior in Mac OS X which paste text with its styles there is a way to fix it! I personally find it very annoying when I press command + V (⌘+V) and text is pasted with all the formatting from the original source. Suddenly my beautifully picked font in an email or an Evernote note is ruined. Email looks like a decorated Christmas tree.

Paste and Match Style Mac OS X Shortcut
Paste and Match Style Mac OS X Shortcut

Of course there are alternative combinations to ⌘ + V to Paste and Match style but they differ from application to application and hard to use even if you can remember them.

Go to you System Preferences, click on Keyboard Shortcuts, pick Application Shortcuts and add applications (or make an “All Applications” rule): http://cl.ly/image/2j0Y283a3W1N

StartupBus 2013: Day 4, Semi Finals

The competition was set up that there would be one winner and one runner up from the pitch competition, two winners from the alumni bus (NYC) and two winners from the score competition. They selected six out of twelve teams for the finals…

On day four of our StartupBus hackathon we arrived in San Antonio, Texas. Unlike on the previous days, we settled in a nice Four Points by Sheraton hotel. The West Coast bus came first, then right after us came the bus from Mexico City, representing the whole country of Mexico. Despite being exhausted, buspreneurs filled the hotel lobby with loud voices and cheers in English and Spanish. In a few hours, the rest of the buses arrived:

  • Chicago representing the Midwest,
  • Tampa representing the Southeast,
  • New York City representing the East Coast,
  • Alumni bus from NYC representing people who participated in the previous years competitions.

Because semi-finals and finals were supposed to take place on the next day, after the dinner pretty much all the teams kept on working till late at night.
The next day, after breakfast in the hotel, we (over 150 StartupBus participants) were transported to the Rackspace HQ, a.k.a. The Mothership. It is situated in San Antonio, and was just a short ride from the hotel. Although our driver managed to get lost due to roads blocked by construction. The Rackspace HQ building is a huge box-like structure resembling a shopping mall. It is surrounded by parking lots and construction (they moved here recently) in a suburban area. We were met like rockstars, but were told not to explore anything outside of the huge hangar-like room. Knowing that most hackers disrespect any rules, Rackspace management wisely put lots of employees and security guards around us. The lunch food was subpar. Elias Bizannes (the founder of StartupBus) and other judges listened to each of more than 40 teams pitch individually. Here is a list of the teams:

StartupBus 2013 North Americacs
StartupBus 2013 North Americacs: facebook.com/startupbus
  • AdventureCo.de
  • BriefSkate
  • CareerMob
  • Chromatix
  • Cloudspotting
  • Coderswb
  • Deliverish
  • DrunkSpotting*
  • Dry Erase Web
  • Emplify
  • Eventee
  • ExVersion
  • Fitchallenge
  • FlightShuffle
  • Friends Judging Friends
  • GhostPost.io
  • Gifdme
  • Grassroots.io
  • InstaLodger (alumni)
  • Jobber.io
  • MyBestRx (alumni)
  • NextChaptr
  • Nomscription
  • Ovrviews
  • Payvine
  • Portioned
  • Producers
  • Readin.gs
  • RepCheck (alumni)
  • SkillMeUp
  • Storedrobe
  • TagSet
  • Thumbtrotter
  • uSupply.me
  • Wrong Credit Score
  • Yaank (alumni)

More information on each team is available at StartupBus.com LeaderBoard.

  • DrunkSpotting was formed after the main competition on the way from San Antonio to Austin.

The judges looked at a few criteria such as working prototypes (or the lack thereof) and team commitment, and chose twelve teams. Here is the list of the finalists and the descriptions of their projects/startups:

  1. CareerMob (NYC): website that helps military professionals to find their civilian career
  2. Usupply.me (Mexico): marketplace for construction industry)
  3. NextChaptr (Chicago): book publisher with a kick starter model
  4. Grassroots.io (SF): kick starter for activism campaigns (e.g., [FixTheDMCA.org]http://www.fixthedmca.org/)
  5. GhostPost (SF): anonymous chat
  6. Coders with out borders (SF): code for a good cause/experience
  7. Deliverish (NYC): marketplace for delivery tasks
  8. Portioned (Chicago): single portion food delivery
  9. Readin.gs (NYC): curated book recommendation and store service
  10. Cloudspotting (Mexico): draw on photos of clouds
  11. Exversion (NYC): GitHub for data
  12. Gifdme (Chicago): animated way to share emotions via GIFs.

Next, those twelve teams pitched on-stage to Robert Scoble of Rackspace, Nicholas Longo of CoffeeCup software and GeekDome, and other judges from sponsors such as Elance and Rackspace. That was probably the most entertaining part of the whole competition! GhostPost and Cloudspotting had killer presentations. The former had a live anonymous chat on huge screens with all the unfiltered messages from the audience shown in real-time. GhostPost grabbed everybody’s attention when Elias read a Cease and Desist email, and people fell in love with GhostPost’s beautifully crafted PAC-MAN-like avatars. The latter team spokesperson can easily perform stand-up comedy: e.g., he said that Cloudspotting is not the first company to make money on clouds (Google, Rackspace, Dropbox). To appreciate the joke, you need to know that Cloudspotting allows users to draw on pictures of clouds and share their creations. :-)

The competition was set up that there would be one winner and one runner up from the pitch competition, two winners from the alumni bus (NYC) and two winners from the score competition. They selected six out of twelve teams for the finals:

  1. Grassroots.io
  2. NextChaptr
  3. CareerMob
  4. GhostPost
  5. Cloudspotting
  6. Usupply.me

Tired but relieved (for most of the people the competition was over), we went on to celebrate. The six finalists kept on working for the second sleepless night.

Read more about the finals and the conclusion summary in my next blog post.

Look at social story on Storify storify.com/azat_co/startupbus-and-sxsw.

Rapid Prototyping with JS Update v0.4

Why Backbone.js? Because a lot of people expressed desire to use it but being a framework Backbone has a learning curve. Not a steep one like Rails but still it takes time to master and learn Backbone. The new chapter “Intro to Backbone.js” will show readers how to:

  • Create Backbone architecture from scratch
  • Construct proper architecture with Routes
  • Use Collections
  • Apply Templates in Subviews
  • Split code into multiple JS files
  • Organize code into modules with AMD and Require.js
  • Optimize code for production with r.js library

Link to the new copy of Rapid Prototyping with JS at https://leanpub.com/rapid-prototyping-with-js.

Rapid Prototyping with JS: Agile JavaScript Developement
Rapid Prototyping with JS: Agile JavaScript Developement

TL;DR

Here is a list of the update for Rapid Prototyping with JS v0.4:

  • Brand new chapter: Intro to Backbone.js
  • Re-structured table of contents (chapters and parts)
  • Extended list of resources for further reading
  • Fixed code formatting and highlighting
  • Fixed grammar, style and typos mistakes
  • Brand new book cover optimized for ebook format
  • Reduced size of ebook (faster download)
  • Inspirational quotes in each chapter
  • Updated “Basics” chapter
  • New headline “Agile JavaScript Development”
  • Extended list of ways to reach us (Twitter, Facebook, Storify, etc.)

LeanPub Updates

LeanPub changed their purchasing. Now it’s even better for readers. Anybody can “return” the book they didn’t like within 45 days and get a full refund. Word return is in double quotes because all content is Digital Right Management (DRM) free. Does it mean that somebody can buy and download a book, get their money back, but keep the copy? Yes, but they will get bad karma for that! And not like a bad karma on Hacker News but a real bad karma. Everybody else deservers authors and publishers trust and respect.

Backbone.js

Why Backbone.js? Because a lot of people expressed desire to use it but being a framework Backbone has a learning curve. Not a steep one like Rails but still it takes time to master and learn Backbone. The new chapter “Intro to Backbone.js” will show readers how to:

  • Create Backbone architecture from scratch
  • Construct proper architecture with Routes
  • Use Collections
  • Apply Templates in Subviews
  • Split code into multiple JS files
  • Organize code into modules with AMD and Require.js
  • Optimize code for production with r.js library

Write and follow @RPJSbook.

Test-Driven Development in Node.js With Mocha

Don’t waste time writing tests for throwaway scripts, but please adapt the habit of Test-Driven Development for the main code base. With a little time spent in the beginning, you and your team will save time later and have confidence when rolling out new releases. Test Driven Development is a really really really good thing.

Who needs Test-Driven Development?

Imagine that you need to implement a complex feature on top of an existing interface, e.g., a ‘like’ button on a comment. Without tests you’ll have to manually create a user, log in, create a post, create a different user, log in with a different user and like the post. Tiresome? What if you’ll need to do it 10 or 20 times to find and fix some nasty bug? What if your feature breaks existing functionality, but you notice it 6 months after the release because there was no test!

Mocha: simple, flexible, fun
Mocha: simple, flexible, fun

Don’t waste time writing tests for throwaway scripts, but please adapt the habit of Test-Driven Development for the main code base. With a little time spent in the beginning, you and your team will save time later and have confidence when rolling out new releases. Test Driven Development is a really really really good thing.

Quick Start Guide

Follow this quick guide to set up your Test-Driven Development process in Node.js with Mocha.

Install Mocha globally by executing this command:

$ sudo npm install -g mocha

We’ll also use two libraries, Superagent and expect.js by LeanBoost. To install them fire up npm commands in your project folder like this:

$ npm install superagent
$ npm install expect.js   

Open a new file with .js extension and type:

var request = require('superagent');
var expect = require('expect.js');

So far we’ve included two libraries. The structure of the test suite going to look like this:

describe('Suite one', function(){
  it(function(done){
  ...
  });
  it(function(done){
  ...
  });
});
describe('Suite two', function(){
  it(function(done){
  ...
  });
});

Inside of this closure we can write request to our server which should be running at localhost:8080:

...
it (function(done){
  request.post('localhost:8080').end(function(res){
    //TODO check that response is okay
  });
});
...

Expect will give us handy functions to check any condition we can think of:

...
expect(res).to.exist;
expect(res.status).to.equal(200);
expect(res.body).to.contain('world');
...

Lastly, we need to add done() call to notify Mocha that asynchronous test has finished its work. And the full code of our first test looks like this:

var request = require('superagent');
var expect = require('expect.js');
  
describe('Suite one', function(){
 it (function(done){
   request.post('localhost:8080').end(function(res){
    expect(res).to.exist;
    expect(res.status).to.equal(200);
    expect(res.body).to.contain('world');
    done();
   });
  });
});

If we want to get fancy, we can add before and beforeEach hooks which will, according to their names, execute once before the test (or suite) or each time before the test (or suite):

before(function(){
  //TODO seed the database
});
describe('suite one ',function(){
  beforeEach(function(){
    //todo log in test user
  });
  it('test one', function(done){
  ...
  });
});

Note that before and beforeEach can be placed inside or outside of describe construction.

To run our test simply execute:

$ mocha test.js

To use different report type:

$ mocha test.js -R list
$ mocha test.js -R spec

Asynchronicity in Node.js

One of the biggest advantages of using Node.js over Python or Ruby is that Node has a non-blocking I/O mechanism. To illustrate this let me use an example of a line in a Starbucks coffeeshop. Let’s pretend that each person standing in line for a drink is a task, and everything behind the counter — cashier, register, barista — is a server or server application. When we order a cup of regular drip coffee, like Pike, or hot tea, like Earl Grey, the barista makes it. While the whole line waits while that drink is made, and the person is charged the appropriate amount…

Non-Blocking I/O

One of the biggest advantages of using Node.js over Python or Ruby is that Node has a non-blocking I/O mechanism. To illustrate this, let me use an example of a line in a Starbucks coffee shop. Let’s pretend that each person standing in line for a drink is a task, and everything behind the counter — cashier, register, barista — is a server or server application. When we order a cup of regular drip coffee, like Pike, or hot tea, like Earl Grey, the barista makes it. The whole line waits while that drink is made, and the person is charged the appropriate amount.

Asynchronicity in Node.js
Asynchronicity in Node.js

Of course, we know that these kinds of drinks are easy to make; just pour the liquid and it’s done. But what about those fancy choco-mocha-frappe-latte-soy-decafs? What if everybody in line decides to order these time-consuming drinks? The line will be held up by each order, and it will grow longer and longer. The manager of the coffee shop will have to add more registers and put more baristas to work (or even stand behind the register him/herself). This is not good, right? But this is how virtually all server-side technologies work, except Node. Node is like a real Starbucks. When you order something, the barista yells the order to the other employee, and you leave the register. Another person gives their order while you wait for your state-of-the-art eye-opener in a paper cup. The line moves, the processes are executed asynchronously and without blocking the queue by waiting.

This is why Node.js blows everything else away (except maybe low-level C/C++) in terms of performance and scalability. With Node, you just don’t need that many CPUs and servers to handle the load.

Asynchronous Way of Coding

Asynchronicity requires a different way of thinking for programmers familiar with Python, PHP, C or Ruby. It’s easy to introduce a bug unintentionally by forgetting to end the execution of the code with a proper return expression.

Here is a simple example illustrating this scenario:

var test = function (callback) {
  return callback();  
  console.log('test') //shouldn't be printed
}

var test2 = function(callback){
  callback();
  console.log('test2') //printed 3rd
}

test(function(){
  console.log('callback1') //printed first
  test2(function(){
  console.log('callback2') //printed 2nd
  })
});

If we don’t use return callback() and just use callback() our string test2 will be printed (test is not printed).

callback1
callback2
tes2

For fun I’ve added a setTimeout() delay for the callback2 string, and now the order has changed:

var test = function (callback) {
  return callback();  
  console.log('test') //shouldn't be printed
}

var test2 = function(callback){
  callback();
  console.log('test2') //printed 2nd
}

test(function(){
  console.log('callback1') //printed first
  test2(function(){
    setTimeout(function(){
      console.log('callback2') //printed 3rd
    },100)
  })
});

Prints:

callback1
tes2
callback2

The last example illustrates that the two functions are independent of each other and run in parallel. The faster function will finish sooner than the slower one. Going back to our Starbucks examples, you might get your drink faster than the other person who was in front of you in the line. Better for people, and better for programs! :-)

Startupbus Day 3: Texas

Our west coast bus was the first to arrive to San Antonio. Mexico City bus followed shortly and the lobby filled with sleep deprived 20 and 30 year-olds. Buses from Chicago, NYC and Tampa are arriving to Four Point as well. Teams plan to pull all-nighters to present tomorrow their startups at Rackspace for the semi-finals.

Today we finished the biggest leg of our trip, San Francisco, CA — San Antonio, TX.

Giant chili pepper, Las Cruses, NM
Giant chili pepper, Las Cruses, NM

We took photos with a giant chili pepper, drove by the Mexico border in El Paso, ate at K-Bob steak house, and arrived at Four Point by Sheraton in San Antonio, TX. There wasn’t anything out of ordinary on the bus. Teams worked hard last night trying to launch their MVPs. Many thanks go to our driver Joe for driving us safely and comfortably.

Our west coast bus was the first to arrive to San Antonio. Mexico City bus followed shortly and the lobby filled with sleep deprived 20 and 30 year-olds. Buses from Chicago, NYC and Tampa are arriving to Four Point as well. Teams plan to pull all-nighters to present tomorrow their startups at Rackspace for the semi-finals.

StartupBus Day 2: Arizona

The journey continues. We entered and crossed Arizona stopping for a late lunch in Tucson near University of Arizona campus. The weather was nice and everybody got a chance to stretch legs and grab quality food.

The journey continues. We entered and crossed Arizona stopping for a late lunch in Tucson near University of Arizona campus. The weather was nice and everybody got a chance to stretch legs and grab quality food.

StartupBus and SxSW

StartupBus is a national hackathon on the way to SxSW in Austin, TX. I’m participating with West Coast/SF team, there are buses from NYC, NY, Chicago, Tampa, FL and Mexico City, Mexico.

Storified by Azat· Mon, Mar 04 2013 16:47:39

Coders Without Border’s Open letter to Developer community. http://www.coderswb.com #StartupBus #WestCoast… http://fb.me/1CTtOY9O6Prateek Gupta
Open Letter to developer communitystartupbus.com , travelling from San Francisco to SXSW, Austin, TX at 70 miles per hour, through the Arizona desert with intermittent wi-…
Arizona: more than just old people, old dinosaur sculptures too #startupbus http://instagr.am/p/WdHoTFObh5/Craig Cannon
65 mph on a bus or 9 mph on a skateboard. #StartupBus #StartupBusSE http://yfrog.com/esr6asyjStartupBus Florida
No stop til’ NOLA. #StartupBus #StartupBusSE http://yfrog.com/h2czoyqfjStartupBus Florida
Check out the awesome #startupbus promo video from @nowthisnews about @thestartupbus – more coverage to come soon! http://jmg.im/W0J9vRTheStartupBus
This year’s @TheStartupBus website is now live; check out the live updating map, and explore! http://americas.startupbus.com/ #startupbusMikeCaprio(╯°□°)╯︵┻┻
Mobile hacking with @Verizon #LTE #MiFi http://speedtest.net/result/2551036993.png CC @TheStartupBusAzat Mardanov
Random guy wants to come on the @TheStartupBus. Here’s his audition. And yes, that is a tree on our bus http://pic.twitter.com/pRYQQIFHN2adam peruta
Our conductor, Ray, on @thestartupbus has been keeping us on track and motivated! http://pic.twitter.com/c5JRB5JQTqElance
Bus window whiteboards on the #startupbus @TheStartupBus http://pic.twitter.com/OzRyxyYfrPLate Labs
Stay for the night @thestartupbus (at San Diego Downtown Lodge) — http://path.com/p/1rhLMKAzat Mardanov
Burning midnight oil on @thestartupbus http://vine.co/v/bHWKwTJ213KAzat Mardanov
http://Coderswb.com @katescisel http://vine.co/v/bHWmrnYrmVBAzat Mardanov
Stephan got left, we returned and picked him up with beer http://vine.co/v/bHBUtJQm1L1Azat Mardanov
Falon takes the stage @thestartupbus http://vine.co/v/bXlXgOwZa1xAzat Mardanov
Departing @thestartupbus http://vine.co/v/bXlvME0hJJmAzat Mardanov
Coffee at the cycle place CC @thestartupbus http://vine.co/v/bXlMAdHwBuUAzat Mardanov
The bus driver on @thestartupbus stopped to help a lady change her tire. What a guy! http://pic.twitter.com/LklDDDPRoYElance
@elance @thestartupbus #startupbus #killinit #youkno #wego #cantstop #dontquit #killinitinthecode http://pic.twitter.com/MPGe2tgId2Ray Land
Thanks a lot @Astreets for the feedback on @GhostPostApp at @TheStartupBusStefan Broda
@justinisaf @gsvitak @davidykay @gregdrm DOINNNN WERKKKKKK! On @TheStartupBus #startupbus @EliasBiz on the beatz http://pic.twitter.com/UtD9ftIQOFRay Land
Constantly supporting innovation and entrepreneurs – @LaunchpadLA housing the @TheStartupBus http://pic.twitter.com/sFhj4kkgEkMeredith Birchfield
We on the @TheStartupBus. It’s name is Fred. Or Snufulupugus, depending who you ask. #startupbuschi http://pic.twitter.com/z36C3GhGT9Zachary Price
Late start for the alumni @TheStartupBus. But our conductor ray is leading us forward http://pic.twitter.com/WEo1R92mdjadam peruta
The bus is ready #westcoast #first @TheStartupBus http://pic.twitter.com/Ez0kmqjC3uAzat Mardanov
Startup Bus is Not a Joke | Web App LogWhen my co-worker heard about StartupBus for the first time he thought that it was a joke. How crazy is to put yourself on a bus with str…
Good luck to anybody gearing up to get on @TheStartupBus this week. Red Bull, and a power strip. You’re welcome.Adam Kerpelman
@thestartupbus kickoff party #startupbus (at @ffvc) [pic]: http://4sq.com/ZOqa7DJonathan Gottfried
Headed to @ffvc for the #StartupBus NYC kickoff very soon. @TheStartupBusCurtis Kline
going to pack for @TheStartupBus SF in an hour. Any #pro tips? Send them my way. #please #6DayTrip #flyingbackPrateek Gupta
Buspreneur @foursquare badge!!!! @TheStartupBus http://pic.twitter.com/nR5UVrBJ0xMikeCaprio(╯°□°)╯︵┻┻
photoPath
Getting ready for @thestartupbus and #SxSW #leanstartup #RPJS [pic] — http://path.com/p/17pfToAzat Mardanov
Hey hackers/designers, don’t miss the ride of your life on @TheStartupBus departing March 3 – apply today at http://bit.ly/nytmbusTheStartupBus
Stocking up NYC team with Vitamin Water.
Thanks @vitaminwater!! “@jonmarkgo An endless supply of @vitaminwater for @TheStartupBus NYC. Oh man I’m excited! http://pic.twitter.com/sqcU4zSejS”MikeCaprio(╯°□°)╯︵┻┻
And with Kind snacks.
Just got our final delicious food delivery for @TheStartupBus from @kindsnacks – thanks! http://pic.twitter.com/aIq36Z2PVYJonathan Gottfried
Thank you @pretzelcrisps for making @TheStartupBus NYC so much more delicious! http://pic.twitter.com/muvwIGeU5ZJonathan Gottfried
I’m pregaming @TheStartupBus with Dane! http://pic.twitter.com/Ki8uWU1Ic5Jonathan Gottfried
Wondering how to prepare for @TheStartupBus? Here’s a list of suggested items to bring on the trip! https://plus.google.com/114275248428793781779/posts/cNh6YLnCH83MikeCaprio(╯°□°)╯︵┻┻
Riding @TheStartupBus again this year out of Tampa.Joe DeSetto
Mexican teams have 3 days to conceive, build and launch companies at 60mph @TheStartupBus @StartupBusMX Cc. @l1452¿Cintli?
Holy crap. I’m on @TheStartupBus. Cannot wait to meet some people and code like a mofo.Rui
Excited some new gear came in before I left for @thestartupbus http://pic.twitter.com/7FoDSOD3cmJosh Seefried
StartupBus 2013 Promises More Excitement, Bigger Surprises http://bit.ly/15RcxZv via @TheStartupBusAzat Mardanov
NYC team is getting all exited as well.
@azat_co @thestartupbus Yeah! I’m on the NYC #StartupBus. You??Erica Swallow
West Coast team got some nice stuff thanks to @prtkgpt.
@prtkgpt @jonmarkgo @TheStartupBus @GranolaLab @michiamoalice Try Eat24 because you know what they say…once you try us, after ya love us!Eat24
@jonmarkgo @thestartupbus @granolalab @michiamoalice Haha! We got @eat24 on our side. #BeatThatPrateek Gupta
StartupBusWe’re building an entrepreneurial ecosystem through unique experiences and inspirational connections. Our vision is to empower the people…

To the story-tellers, it starts with an Australian and a pub (fun story). To the people watching, it’s a annual competition that brings out tribal-like rivalries. But to anyone part of the experience, it’s a personal challenge with a lifelong impact.

StartupBus has a long term vision to encourage the creation of successful startups that improve our world. We do that, not by building startup’s directly but developing a global community of some of the smartest people in technology, bonded by one of the most intense learning experiences they will ever go through.

GhostPost Twitter account was blocked because they were tweeting to random people too frequently.

Coders Without Borders (coderswb.com) launched their website and PR campaign. They’ve got over 200 likes on the MSFT BizPark Facebook post!

Grassroots.io is also making good progress. Their campaign against making cell phone unlocking illegal is gaining momentum with over 115,000 signed-up.

Tonight we’ve stayed in Americas Best Value Inn in Las Cruces, NM. The hotel hosts are very hospitable. They made a special sign for us, arranged for mid-night snacks and drove Falon and Ruben to Sonic to get us dinner! Such an upgrade with a swimming pool and gym over our last night’s downtown San Diego motel.

We use GroupMe for text messaging buspreneurs, it’s an amazing tool.

Checkout our photos and tweets at storify.com/azat_co/startupbus-and-sxsw.

StartupBus Day 1

We’ve started at Falon’s house in San Francisco, CA, got awesome coffee in a cycling shop and pitched all the way till the stop at Walmart in Los Banos, CA. We broke into team and got supplies (neck pillows, fruits and booze) and left without one buspreneur!

We’ve started at Falon’s house in San Francisco, CA, got awesome coffee in a cycling shop and pitched all the way till the stop at Walmart in Los Banos, CA. We broke into team and got supplies (neck pillows, fruits and booze) and left without one buspreneur!

Next stop was at LaunchPad LA in San Diego’s beautiful Santa Monica. There were mentor sessions and pizza.

At 9pm were made it to San Diego and stopped at Downtown Lodge motel.

So far we have three team on the bus:

  • Grassroots — kick starter for kickstarters.
  • Coderswb (without borders) — teach coding for an experience.
  • GhostPost — anonymous geo-chat.

Thanks to 24eat for the dinner!

Startup Bus is Not a Joke

When my co-worker heard about StartupBus for the first time he thought that it was a joke. How crazy is to put yourself on a bus with strangers and try to hack together functional prototype without reliable Internet, time, outside help. But StartupBus is not a joke! Although it might have started as one in 2010. The main reason is to present something good and valuable to other people at SxSW in Ausitn, TX. You would be surprised how much can be accomplished in a close quarters riding a bus at 60mph. Here are the finalists

Storify story is at storify.com/azat_co/startupbus-and-sxsw.

When my co-worker heard about StartupBus for the first time he thought that it was a joke. How crazy is to put yourself on a bus with strangers and try to hack together functional prototype without reliable Internet, time, outside help. But StartupBus is not a joke! Although it might have started as one in 2010. The main reason is to present something good and valuable to other people at SxSW in Ausitn, TX. You would be surprised how much can be accomplished in a close quarters riding a bus at 60mph. Here are the finalists

StartupBus 2013
StartupBus 2013

Last year I was offered to join the New Orleans Startupbus team, but I decided not to go because Gizmo was about to finish 500 Startup accelerator program and it required my presence in Mountain View, CA. This year I’m going with a West Coast team and we’re departing tomorrow morning, March 3rd, from Fillmore in San Francisco, CA. There are three other buses going from NYC, NY, Mexico City, Mexico, Chicago, IL and Tampa, FL. We’ll have only 72 hours to form teams, take our idea to prototypes, test them on real customers and market the product. We got supplies from sponsors (24eat, Kind, VitaminWater, etc.) and media coverage from Venturebeat — Epic hack trip: Be one of 50 to join me on the Startup Bus.

Cerealize startup whose team was on SF bus won last year’s competition. So pressure is on our West Coast bus to defend the title. :-) The other 2012 finalists and StartupBus TV.

Here is our very intense schedule:

  1. Sunday, 3/3: SF -> San Diego
    We will be leaving SF on Sunday 3/3, stay in San Diego for the night.
  2. Monday, 3/4: San Diego -> New Mexico
    On Monday 3/4 we will drive through Arizona to New Mexico where we will spend the night.
  3. Tuesday, 3/5: New Mexico -> San Antonio
    On Tuesday 3/5 we will end up in San Antonio for the night.
  4. Wednesday, 3/6: San Antonio Semifinals
    Semifinals will be Wed 3/6 in San Antonio where we will spend the night.
  5. Thursday, 3/7: San Antonio -> Austin
    On Thursday, 3/7 everyone will be shuttled to Austin where semi-finalists will have time to prepare for Grand Finals.
  6. Friday, 3/8: Austin Grand Finals
    Grand Finals will be in Austin on Friday 3/8.

I’ll try to blog once a day about major events, help team with technical implementation and engineering. For live coverage, I also created Storify story — storify.com/azat_co/startupbus-and-sxsw, and will be adding the most interesting tweets, Instagram photos and vine videos.

Home and End Shortcuts in Terminal

I like my shortcuts to be consistent across the most used applications: Chrome, Sublime Text 2 and iTerm. This way I don’t have to think about what application I’m in, and I can just hit the buttons.

TL;DR

Here are the shortcuts that will work in Terminal app.

Home: control + A

End: control + E

Next Word: esc, then f

Previous word: esc, then b

Why Bother

I like my shortcuts to be consistent across the most used applications: Chrome, Sublime Text 2 and iTerm. This way I don’t have to think about what application I’m in, and I can just hit the buttons.

I’ve set tab switch to option+command+left and option+command+right, home to command+left, and end to command+right and previous word to option+left, and next word to option+right. These shortcuts for the most part mimic the default behavior in Sublime Text 2 and other editors.

iTerm

iTerm is a better alternative to Terminal app on Mac OS X. You can get it at iterm2.com.

Home and End Shortcuts in iTerm
Home and End Shortcuts in iTerm

Go to your iTerm and open preferences from the menu (iTerm-> Preferences) or by using command + , or ⌘ + , shortcuts. Open Profiles tab and click on Keys for the Default profile.

To set home — that is, to jump to the beginning of a line — press command+left and then select ‘Send Hex Code’ and enter value 001.

Repeat the same thing for end substituting shortcut with command+right and hex with 005.

To set up previous word shortcut, press down option+left and then select ‘Send Escape Sequence’ and enter b. For the next word option+right shortcut, enter f.

Related posts:

I don’t know why Terminal and iTerm by default have broken shortcuts. Maybe there is some history to it, but it seems like I’m not the only person who has encountered (and/or fixed) the issue:

Cheat Sheets for Web Development

Web development usually involves a large number of languages each with its own syntax, keywords, special sauce and magic tricks. Here is a collection of web development cheat sheets, in no particular order, which I’ve amassed by browsing the Internet over many years of web development

Cheat sheets are great ways to organize frequently used information and keep it handy. I used cheat sheets for learning and memorizing during my crams at school, and use them now for reference.

Cheat sheet for Web Development
Cheat sheet for Web Development

Web development usually involves a large number of languages each with its own syntax, keywords, special sauce and magic tricks.
Here is a collection of web development cheat sheets, in no particular order, which I’ve amassed by browsing the Internet over many years of web development. They cover the following topics:

  • jQuery
  • CSS3
  • Git
  • Heroku
  • HTML5
  • Linux Command Line
  • Mod reWrite
  • CoffeeScript
  • JavaScript
  • CSS2
  • JavaScript DOM
  • Mac Glyphs
  • Node.js
  • PHP
  • RGB Hex
  • Sublime Text 2
  • SEO
  • WordPress

Get zip archive at http://www.webapplog.com/wp-content/uploads/web-dev-cheat-sheets.zip.

Full list of the files:


jquery12_colorcharge.png
cdiehl_firefox.pdf
CSS Help Sheet outlined.pdf
css-cheat-sheet-v2.pdf
css-cheat-sheet.pdf
CSS3 Help Sheet outlined.pdf
css3-cheat-sheet.pdf
dan-schmidt_jquery-utility-functions-type-testing.pdf
danielschmitz_jquery-mobile.pdf
davechild_css2.pdf
davechild_html-character-entities.pdf
davechild_javascript.pdf
davechild_linux-command-line.pdf
davechild_mod-rewrite.pdf
davechild_regular-expressions.pdf
dimitrios_coffeescript-cheat-sheet.pdf
gelicia_sublime-text-2-shortcuts-verbose-mac.pdf
Git_Cheat_Sheet_grey.pdf
heroku_cheatsheet.pdf
HTML Help Sheet 02.pdf
html5-cheat-sheet.pdf
i3quest_jquery.pdf
javascript_refererence.pdf
javascript-cheat-sheet-v1.pdf
JavaScript-DOM-Cheatsheet.pdf
javascriptcheatsheet.pdf
jQuery-1_3-Visual-Cheat-Sheet.pdf
Mac_Glyphs_All.pdf
Node Help Sheet.pdf
PHP Help Sheet 01.pdf
pyro19d_javascript.pdf
rgb-hex-cheat-sheet-v1.pdf
salesforce_git_developer_cheatsheet.pdf
samcollett_git.pdf
sanoj_web-programming.pdf
SEO_Web_Developer_Cheat_Sheet.pdf
skrobul_sublime-text-2-linux.pdf
WordPress-Help-Sheet.pdf
Help Sheets.zip

Android to iOS or Why Guy Kawasaki Is Wrong

I jumped on the smartphone train a little bit later than most of my type (early adopters, geeks, etc.) because I didn’t like Apple, Inc. and its products. And I also had this notion that each device should do its own distinct function well rather than try to be a Swiss Army knife of gizmos.

I know that many of you perceive Guy Kawasaki as some sort of genius and visionary. Indeed, he’s published 11 (eleven!) books, worked with Steve Jobs, and has strong opinions. Not that long ago, I attended his talk at TheNextWeb event where he was promoting his new book APE: Author, Publisher and Entrepreneur. The book is about self-publishing woes. Although his tips and APE have come in very handy for my lean-pub edition of Rapid Prototyping with JS, I somewhat disagreed with Guy’s casual remarks about two Google products: Google Plus and Android. Mr.Kawasaki said that Google Plus is to Facebook, what Apple was to Windows: not many people use it, it’s better and everybody thinks it’ll die soon. :-) Then the acclaimed author half-jokingly said: “Android is for real men”. Seriously?! Here is my story of going from a hard-core Android user to an iOS fan in less than a year.


Guy Kawasaki about Android at TheNextWeb

I jumped on the smartphone train a little bit later than most of my type (early adopters, geeks, etc.) because I didn’t like Apple, Inc. and its products. And I also had this notion that each device should do its own distinct function well rather than try to be a Swiss Army knife of gizmos. For example, taking pictures with a photo camera, listening to music on an MP3 player, voice calls with a dumbcell phone, taking notes on a PDA and waking up to an alarm clock. ;-) Of course, my conservatism started to fade away as hardware and software improved. Slowly I’ve noticed that I’m watching videos on my 4“ MP3 player, reading books on my Dell Axim X51 and using an alarm clock ”app" in my Nokia cell phone.

I guess it was time for my first real smartphone. I’ve already used many Google web application so I went with T-Mobile’s myTouch 3G with Android 1.6. The device was slow and buggy like hell. The phone was unusable to the point that I had to root it, and to install an aftermarket firmware CyanogenMod to make the experience at least somewhat bearable. Despite all of that, what I’ve come to realize is that I really needed a smartphone in my life (surprise, surprise!). Boy, I was wrong when I thought that if I had a computer at home and one at work, then I didn’t need yet another one in my pocket. ;-)

Then, a few iterations of Android OS and a few devices later — I had an entry-level LG Optimus One and a gorgeous 4.5" display Samsung Infuse 4G — I really started to appreciate:

  • Seamless integration with my everyday apps: GMail, Google Docs, Calendar, Reader and Maps.
  • Abundance of free apps.
  • Customization done by device manufacturers and those I can do by using widgets and aftermarket firmware.

It wasn’t always roses and butterflies. Here are some of the problems I experienced using Android-powered devices (I also had a 7" Samsung tablet):

  • No Instagram-like hip apps when they’re already available at Apple App Store.
  • Phone barely lasted one day, despite multiple replacements and having an extended battery.
  • Constant “Force close” (analog of a blue window of death on Windows PCs) and the need to restart the device.

Nevertheless, I was blissful in my ignorance which was totally destroyed by my switch to Max OS X from Windows XP/7. The reason for this was that I had to sync data using 3rd party apps and adapt to new behaviors. I wasn’t happy. Because when I’m not happy I usually find way to fix it. :-) The perfect timing of iPhone 5 and sluggishness of Android 2.3 (I had over 100 apps installed) made the pre-order of iPhone 5 64Gb a no-brainer.

Things that I’ve come to enjoy and appreciate since then:

  • iPhotos, Photo Steam and Photo Roll are a simple and robust way to sync photos across Macs, iPads and iPhones. Also, seamless integration with iCloud and iTunes makes my life easier.
  • iPhone 5 battery life is amazing, on a typical day I use only 30–40% of a charge which means I can go for about two days without recharging.
  • iMessage/Messages is a superb feature with allows me to take conversations I’ve started on iPhone or iPad to my MacBook or vice versa.
  • Retina displays on both iPad and iPhone 5 are feasts for my eyes.
  • Last but not least, LTE is lightning fast compared to the fake 4G standard of HSPA+.

Again as with Win vs Mac, iPhone doesn’t make me think about unnecessary things like updating to a custom flavor of OS or about solving synching issues.

I know that Guy Kawasaki plays hockey, which is no doubt a manly recreation, but I think that he was wrong about Android. In my humble opinion, Android is similar to Windows because:

  • Android OS is loosely integrated with hardware (except for Google Nexus produced by HTC).
  • Google has a licensing revenue model which is similar to Microsoft selling a copy of Windows. By the way, Google licenses Android for $10 per device.
  • Android devices are very fragmented; there are dozens of companies, each with its own modified version of Android, and even with apps and entertainment stores, e.g., Samsung Hub.

All of these make apps development slower and introduce more challenges for developers while being less appealing products for end-users. As with Windows, the main advantage of the Android platform is its lower price and growing army of users!

Switching from Windows to Max OS X

I’ve been a Microsoft Windows user for the most of my professional career. It all changed a year ago when I moved to Mountain View, California to participate in 500 Startups program, a summary of my experience in my blog post 15 things I learned from 500 Startups (aka Fail Factory). So far Max OS X is a best tool for me and I highly recommend to make a switch if you’re still on Windows.

I’ve been a Microsoft Windows user for the most of my professional career. It all changed a year ago when I moved to Mountain View, California to participate in 500 Startups program, a summary of my experience in my blog post 15 things I learned from 500 Startups (aka Fail Factory).

People in Silicon Valley, especially developers and engineers, virtually all use Mac OS X or some flavor of Linux. But peer pressure wasn’t in itself enough for me to make a switch. After all those years I’d have amassed a set of tools and habits as well as assumptions about Mac OS X and Apple. Therefore I never owned any Apply device, even an iPod or iPhone, and thought of them as overpriced and limited gadgets. At that time we were using Ruby on Rails and I often stumbled upon some weirdness here and there within my setup. Very soon I’d discovered that Ruby on Rails just wasn’t meant to be run on Windows machines by design :-( The thing is that 37signals (company behind RoR) and other power contributors to Ruby on Rails are Apple users, as a consequence when they build a new gem or release a new version of core framework they do it for Mac OS X first. Then for Linux because the difference is minimal (Mac OS X is a Unix-based system, hence the X). A very few Ruby on Rails Windows enthusiasts are vastly outnumbered and that’s why it’s harder to find latest libraries, solutions and answers to specific questions (which there are many).

As always, the fear of a pain from switching is bigger than the pain itself. In a month or so I learned all the trackpad tricks, most of the shortcuts and installed the best developers tools (most of which are not free but they’re way better than free alternatives on Windows). Another great factor is a quality of the hardware: the keyboard, battery, charger (I have MacBook Air), etc. is superb! The look and feel of Mac OS X itself is not very different from some Linux distribution like Ubuntu but OS X has two huge advantages:

  1. All the drivers will work out of the box and with future OS updates; I often had discovered that either a microphone or a some other periferieal device is not working after installing Linux on my laptop;
  2. It has nice small but very convenient features.

A year after the switching I’ve sold all my Windows machines and I work, run errand and entertain myself solely on 13’’ MacBook Air. Recently I even was brave enough to install 240Gb Aura OWC SSD instead of a stock 128Gb SSD drive, it took an hour of cloning and 15 minutes of working with a tiny screwdriver :-)

So far Max OS X is a best tool for me and I highly recommend to make a switch if you’re still on Windows. The investment in Mac OS X machine has high ROI. It’s essential if you want to be an a bleeding edge of technology (Ruby on Rails, Node.js, etc.). As an added bonus, MacBook can simplify and organize your life better leading to a higher productivity, less stress (no worries about the brand, color, shape when the time for an upgrade comes, because I’ll just get the latest MacBook with the maximum everything) and a zen-like life :-)

Decreasing 64-bit Tweet ID in JavaScript

JavaScript is only able to handle integers up to 53-bit in size, here is a script to decrease tweet ID which is a 64-bit number in JavaScript without libraries or recursion, to use with max_id or since_id in Twitter API

As some of you might know, JavaScript is only able to handle integers up to 53-bit in size. This post, Working with large integers in JavaScript (which is a part of Numbers series) does a great job at explaining general concepts on dealing with large numbers in JS.

64-bit Tweet ID is "rounded" in JS
64-bit Tweet ID is “rounded” in JS

I had to do some research on the topic when I was re-writing some JavaScript code responsible for handling Twitter search in Storify editor: we had tweet duplicates in results! In this article, Working with Timelines, Twitter official documentation says:

Environments where a Tweet ID cannot be represented as an integer with 64 bits of precision (such as JavaScript) should skip this step.

So true, because id and id_str fields in a Twitter API response were different. Apparently, JavaScript engine just “rounds” inappropriately large numbers. :-( The task was complicated by the fact that I needed to subtract 1 from the last tweet’s ID to prevent its reappearance in a second search response. After the subtraction I could have easily passed the value to max_id parameter of Twitter API.

I’ve come across different solutions, but decided to write my own function which is simple to understand and not heavy on resources. Here is a script to decrease tweet ID which is a 64-bit number in JavaScript without libraries or recursion, to use with max_id or since_id in Twitter API:

function decStrNum (n) {
    n = n.toString();
    var result=n;
    var i=n.length-1;
    while (i>-1) {
      if (n[i]==="0") {
        result=result.substring(0,i)+"9"+result.substring(i+1);
        i --;
      }
      else {
        result=result.substring(0,i)+(parseInt(n[i],10)-1).toString()+result.substring(i+1);
        return result;
      }
    }
    return result;
}

To check if it works, you can run these logs:

console.log("290904187124985850");
console.log(decStrNum("290904187124985850"));
console.log("290904187124985851");
console.log(decStrNum("290904187124985851"));
console.log("290904187124985800");
console.log(decStrNum("290904187124985800"));
console.log("000000000000000001");
console.log(decStrNum("0000000000000000001"));

Alternative solution which I’ve found in a StackOverflow question was suggested by Bob Lauer, but it involves recursion and IMHO is more complicated:

function decrementHugeNumberBy1(n) {
    // make sure s is a string, as we can't do math on numbers over a certain size
    n = n.toString();
    var allButLast = n.substr(0, n.length - 1);
    var lastNumber = n.substr(n.length - 1);

    if (lastNumber === "0") {
        return decrementHugeNumberBy1(allButLast) + "9";
    }
    else {      
        var finalResult = allButLast + (parseInt(lastNumber, 10) - 1).toString();
        return trimLeft(finalResult, "0");
    }
}

function trimLeft(s, c) {
    var i = 0;
    while (i < s.length && s[i] === c) {
        i++;
    }

    return s.substring(i);
}

Now, if you’re the type of person who likes to shoot sparrows with a howitzer, there are full-blown libraries to handle operations on large numbers in JavaScript; just to name a few: BigInteger, js-numbers and javascript-bignum.

MongoDB migration with Node and Monk

Recently one of our top users complained that their Storify account is unaccessible. We’ve checked the production database and it appeared to be that the account might have been compromised and maliciously deleted by somebody using user’s account credentials. Thanks for a great MongoHQ service we had a backup database in less than 15 minutes.

Recently one of our top users complained that their Storify account was unaccessible. We’ve checked the production database and it appeares to be that the account might have been compromised and maliciously deleted by somebody using user’s account credentials. Thanks to a great MongoHQ service, we had a backup database in less than 15 minutes.
There were two options to proceed with the migration:

  1. Mongo shell script
  2. Node.js program

Because Storify user account deletion involves deletion of all related objects — identities, relationships (followers, subscriptions), likes, stories — we’ve decided to proceed with the latter option. It worked perfectly, and here is a simplified version which you can use as a boilerplate for MongoDB migration (also at gist.github.com/4516139).

Restoring MongoDB Records
Restoring MongoDB Records

Let’s load all the modules we need: Monk, Progress, Async, and MongoDB:

var async = require('async');
var ProgressBar = require('progress');
var monk = require('monk');
var ObjectId=require('mongodb').ObjectID;

By the way, made by LeanBoost, Monk is a tiny layer that provides simple yet substantial usability improvements for MongoDB usage within Node.JS.

Monk takes connection string in the following format:

username:password@dbhost:port/database

So we can create the following objects:

var dest = monk('localhost:27017/storify_localhost');
var backup = monk('localhost:27017/storify_backup');

We need to know the object ID which we want to restore:

var userId = ObjectId(YOUR-OBJECT-ID); 

This is a handy restore function which we can reuse to restore objects from related collections by specifying query (for more on MongoDB queries go to post Querying 20M-Record MongoDB Collection. To call it, just pass a name of the collection as a string, e.g., "stories" and a query which associates objects from this collection with your main object, e.g., {userId:user.id}. The progress bar is needed to show us nice visuals in the terminal.

var restore = function(collection, query, callback){
  console.info('restoring from ' + collection);
  var q = query;
  backup.get(collection).count(q, function(e, n) {
    console.log('found '+n+' '+collection);
    if (e) console.error(e);
    var bar = new ProgressBar('[:bar] :current/:total :percent :etas', { total: n-1, width: 40 })
    var tick = function(e) {
      if (e) {
        console.error(e);
        bar.tick();
      }
      else {
        bar.tick();
      }
      if (bar.complete) {
        console.log();
        console.log('restoring '+collection+' is completed');
        callback();                
      }
    };
    if (n>0){
      console.log('adding '+ n+ ' '+collection);
      backup.get(collection).find(q, { stream: true }).each(function(element) {
        dest.get(collection).insert(element, tick);
      });        
    } else {
      callback();
    }
  });
}

Now we can use async to call the restore function mentioned above:

async.series({
  restoreUser: function(callback){   // import user element
    backup.get('users').find({_id:userId}, { stream: true, limit: 1 }).each(function(user) {
      dest.get('users').insert(user, function(e){
        if (e) {
          console.log(e);
        }
        else {
          console.log('resored user: '+ user.username);
        }
        callback();
      });
    });
  },

  restoreIdentity: function(callback){  
    restore('identities',{
      userid:userId
    }, callback);
  },

  restoreStories: function(callback){
    restore('stories', {authorid:userId}, callback);
  }

  }, function(e) {
  console.log();
  console.log('restoring is completed!');
  process.exit(1);
});

The full code is available at gist.github.com/4516139 and here:

var async = require('async');
var ProgressBar = require('progress');
var monk = require('monk');
var ms = require('ms');
var ObjectId=require('mongodb').ObjectID;

var dest = monk('localhost:27017/storify_localhost');
var backup = monk('localhost:27017/storify_backup');

var userId = ObjectId(YOUR-OBJECT-ID); // monk should have auto casting but we need it for queries

var restore = function(collection, query, callback){
  console.info('restoring from ' + collection);
  var q = query;
  backup.get(collection).count(q, function(e, n) {
    console.log('found '+n+' '+collection);
    if (e) console.error(e);
    var bar = new ProgressBar('[:bar] :current/:total :percent :etas', { total: n-1, width: 40 })
    var tick = function(e) {
      if (e) {
        console.error(e);
        bar.tick();
      }
      else {
        bar.tick();
      }
      if (bar.complete) {
        console.log();
        console.log('restoring '+collection+' is completed');
        callback();                
      }
    };
    if (n>0){
      console.log('adding '+ n+ ' '+collection);
      backup.get(collection).find(q, { stream: true }).each(function(element) {
        dest.get(collection).insert(element, tick);
      });        
    } else {
      callback();
    }
  });
}

async.series({
  restoreUser: function(callback){   // import user element
    backup.get('users').find({_id:userId}, { stream: true, limit: 1 }).each(function(user) {
      dest.get('users').insert(user, function(e){
        if (e) {
          console.log(e);
        }
        else {
          console.log('resored user: '+ user.username);
        }
        callback();
      });
    });
  },

  restoreIdentity: function(callback){  
    restore('identities',{
      userid:userId
    }, callback);
  },

  restoreStories: function(callback){
    restore('stories', {authorid:userId}, callback);
  }

  }, function(e) {
  console.log();
  console.log('restoring is completed!');
  process.exit(1);
});
           

To launch it, run npm install/update and change hard-coded database values.

Sample of Rapid Prototyping with JS

Free sample chapter of Rapid Prototyping with JS which is a hands-on book which introduces you to rapid software prototyping using the latest cutting-edge web and mobile technologies including NodeJS, MongoDB, BackboneJS, Twitter Bootstrap, LESS, jQuery, Parse.com, Heroku and others.

Rapid Prototyping with JS is a hands-on book which introduces you to rapid software prototyping using the latest cutting-edge web and mobile technologies including NodeJS, MongoDB, BackboneJS, Twitter Bootstrap, LESS, jQuery, Parse.com, Heroku and others.

Rapid Prototyping with JS

Here is a free sample, first chapter — Introduction, of Rapid Prototyping with JS. You can also get a free PDF from LeanPub and explore code examples at github.com/azat-co/rpjs. To buy a full version in PDF, Mobi/Kindle and ePub/iPad formats go to leanpub.com/rapid-prototyping-with-js.

Introduction

Rapid Prototyping with JS is a hands-on book which introduces you to rapid software prototyping using the latest cutting-edge web and mobile technologies including Node.js, MongoDB, Twitter Bootstrap, LESS, jQuery, Parse.com, Heroku and others.

Who This Book is For

The book is designed for advanced-beginner and intermediate level web and mobile developers: somebody who has just started programming and somebody who is an expert in other languages like Ruby on Rails, PHP, and Java and wants to learn JavaScript and Node.js.

Rapid Prototyping with JS, as you can tell from the name, is about taking your idea to a functional prototype in the form of a web or a mobile application as fast as possible. This thinking adheres to the Lean Startup methodology; therefore, this book would be more valuable to startup founders, but big companies’ employees might also find it useful, especially if they plan to add new skills to their resume.

Prerequisite

Mac OS X or UNIX/Linux systems are highly recommended for this book’s examples and for web development in general, although it’s still possible to hack your way on a Windows-based system.

Some cloud services require users’ credit/debit card information even for free accounts.

What to Expect

Expect a lot of coding and not much of a theory. All the theory we cover is directly related to some of the practical aspects and essential for better understanding of technologies and specific approaches in dealing with them, e.g., JSONP and cross-domain calls.

In addition to coding examples, the book covers virtually all setup and deployment step-by-step.

You’ll learn on the example of Message Board web/mobile applications starting with front-end components. There are a few versions of these applications, but by the end we’ll put front-end and back-end together and deploy to production environment. The Message Board application contains all the necessary components typical for a basic web app, and will give you enough confidence to continue developing on your own, apply for a job/promotion or build a startup!

This is a digital version of the book, so most of the links are hidden just like on any other web page, e.g., jQuery instead of http://jquery.com. The content of the book has local hyperlinks which allow you to jump to any section.

All the source code for examples used in this book is available in the book as well as in a public GitHub repository github.com/azat-co/rpjs. You can also download files as a ZIP archive or use Git to pull them. More on how to install and use Git will be covered later in the book. The source code files, folder structure and deployment files are supposed to work locally and/or remotely on PaaS solutions, i.e., Windows Azure and Heroku, with minor or no modifications.

Notation

This is what source code blocks look like:

var object = {};
object.name = "Bob";

Terminal commands have a similar look but start with dollar sign, $:

$ git push origin heroku
$ cd /etc/
$ ls 

Inline filenames, path/folder names, quotes and special words/names are italicized while command names, e.g., mongod, and emphasized words, e.g., Note, are bold.

Web Basics

Overview

The bigger picture of web and mobile application development consists of the following steps:

  1. User types a URL or follows a link in her browser (aka client);
  2. Browser makes HTTP request to the server;
  3. Server processes the request, and if there’re any parameters in a query string and/or body of the request takes them into account;
  4. Server updates/gets/transforms data in the database;
  5. Server responds with HTTP response containing data in HTML, JSON or other formats;
  6. Browser receives HTTP response;
  7. Browser renders HTTP response to the user in HTML or any other format, e.g., JPEG, XML, JSON.

Mobile applications act in the same manner as regular websites, only instead of a browser there might be a native app. Other minor differences include: data transfer limitation due to carrier bandwidth, smaller screens, and the more efficient use of the local storage.

There are a few approaches to mobile development, each with its own advantages and disadvantages:

  • Native iOS, Android, Blackberry apps build with Objective-C and Java;
  • Native apps build with JavaScript in Appcelerator and then complied into native Objective-C or Java;
  • Mobile websites tailored for smaller screens with responsive design, CSS frameworks like Twitter Bootstrap or Foundation, regular CSS or different templates;
  • HTML5 apps which consists of HTML, CSS and JavaScript, and are usually build with frameworks like Sencha Touch, Trigger.io, JO, and then wrapped into native app with PhoneGap.

Hyper Text Markup Language

Hyper Text Markup Language, or HTML, is not a programming language in itself. It is a set of markup tags which describes the content and presents it in a structured and formatted way. HTML tags consist of a tag name inside of the angle brackets (<>). In most cases tags surround the content with the end tag having forward slash before the tag name.

In this example each line is an HTML element:

<h2>Overview of HTML</h2>
<div>HTML is a ...</div>
<link rel="stylesheet" type="text/css" href="style.css" />

The HTML document itself is an element of html tag and all other elements are children of that html tag:

<!DOCTYPE html>
<html lang="en">
  <head>
    <link rel="stylesheet" type="text/css" href="style.css" />
  </head>
  <body>
    <h2>Overview of HTML</h2>
    <p>HTML is a ...</p>
  </body>
</html>

There are different flavors and versions of HTML, e.g., DHTML, XHTML 1.0, XHTML 1.1, XHTML 2, HTML 4, HTML 5. This article does a good job of explaining the differences — Misunderstanding Markup: XHTML 2/HTML 5 Comic Strip.

More information is available at Wikipedia and w3schools.

Cascading Style Sheets

Cascading Style Sheets, or CSS, is a way to format and present content. An HTML document can have several stylesheets with the tag link as in previous examples or style tag:

<style>
  body {
  padding-top: 60px; /* 60px to make some space */
  }
</style>

Each HTML element can have id and class attribute:

<div id="main" class="large">Lorem ipsum dolor sit amet,  Duis sit amet neque eu.</div>

In CSS we access elements by their id, class, tag name and in some edge cases by parent-child relationship or element attribute value:

p {
  color:#999999;
}
div#main {
  padding-bottom:2em;
  padding-top:3em;
}
.large {
  font-size:14pt;
}
body > div {
  display:none;         
}
input[name="email"] {
  width:150px;
}

More information for further reading is available at Wikipedia and w3schools.

CSS3 is an upgrade to CSS which includes new ways of doing things such as rounded corners, borders and gradients, which were possible in regular CSS only with the help of PNG/GIF images and by using other tricks.

For more information refer to CSS3.info, w3school
and CSS3 vs CSS comparison article on Smashing.

JavaScript

JavaScript was started in 1995 at Netscape as LiveScript. It has the same relationship with Java as a hamster and a ham :)
It is used for both client and server side development as well as in desktop applications.

There is a script tag to use JavaScript in the HTML document:

<script type="text/javascript" language="javascript>
  alert("Hello world!");
  //simple alert dialog window
</script>

Usually it a good idea to separate JavaScript code from HTML; in this example we include app.js file:

<script src="js/app.js" type="text/javascript" language="javascript" />

Here are the main types of JavaScript objects/classes:

  • Array object, e.g., var arr = ["apple", "orange", 'kiwi"];
  • Boolean primitive object, e.g., var bool = true;
  • Date object, e.g., var d = new Date();
  • Math object, e.g., var x = Math.floor(3.4890);
  • Number primitive object, e.g., var num = 1;
  • String primitive object, e.g., var str = "some string";
  • RegExp object, e.g., var pattern = /[A-Z]+/;
  • Global properties and functions, e.g., NaN
  • Browser objects, e.g., window.location = 'http://google.com';
  • DOM objects, e.g., var table = document.createElement('table');

Full JavaScript and DOM objects and classes reference with examples are available at w3school.

Typical syntax for function declaration:

function Sum(a,b) {
  var sum = a+b;
  return sum;
}
console.log(Sum(1,2));

Functions in JavaScript are first-class citizens due to functional programming nature of the language. Therefore functions can be used as other variables/objects; for example, functions can be passed to other functions as arguments:

var f = function (str1){
  return function(str2){
  return str1+' '+str2;
  };
};
var a = f('hello');
var b = f('goodbye');
console.log((a('Catty'));
console.log((b('Doggy'));

JavaScript has a loose/weak typing, as opposed to strong typing in languages like C and Java, which makes JavaScript a better programming language for prototyping.

More information about browser-run JavaScript is available at Wikipedia and w3schools.

Agile Methodologies

Agile software development methodology evolved due to the fact that traditional methods, like Waterfall, weren’t good enough in situations of high unpredictability, i.e., when the solution is unknown. Agile methodology includes Scrum/Sprint, Test-Driven Development, Continuous Deployment, Paired Programming and other practical techniques many of which were borrowed from Extreme Programming.

Scrum

In regard to the management, Agile methodology uses Scrum approach. More about Scrum can be read at:

Scrum methodology is a sequence of short cycles, and each cycle is called sprint. One sprint usually lasts from one to two weeks. Sprint starts and ends with sprint planning meeting where new tasks can be assigned to team members. New tasks cannot be added to the sprint in progress; they can be added only at the sprint meetings.

An essential part of the Scrum methodology is the daily scrum meeting, hence the name. Each scrum is a 5–15 minutes long meeting which is often conducted in the hallways. On scrum meetings each team member answers three questions:

  1. What have you done since yesterday?
  2. What are you going to do today?
  3. Do you need anything from other team members?

Flexibility makes Agile an improvement over Waterfall methodology, especially in situations of high uncertainty, i.e., startups.

Advantage of Scrum methodology: effective where it is hard to plan ahead of the time, and also in situations where a feedback loop is used as a main decision-making authority.

Test-Driven Development

Test-Driven Development, or TDD, consists of following steps:

  1. Write failing automated test cases for new feature/task or enhancement by using assertions that are either true or false.
  2. Write code to successfully pass the test cases.
  3. Refactor code if needed, and add functionality while keeping the test cases passed.
  4. Repeat until the task is complete.

Advantages of Test-Driven Development:

  • fewer bugs/defects,
  • more efficient codebase,
  • provides programmers with confidence that code works and doesn’t break old functionality.

Continuous Deployment

Continuous Deployment, or CD, is the set of techniques to rapidly deliver new features, bug fixes, and enhancements to the customers. CD includes automated testing and automated deployment. By utilizing Continuous Deployment the manual overheard is decreased, and the feedback loop time is minimized. Basically, the faster developer can get the feedback from the customers, the sooner the product can pivot, which leads to more advantages over the competition. Many startups deploy multiple times in a single day in comparison to the 6–12 month release cycle which is still typical for corporations and big companies.

One of the most popular solutions for CD is Continuous Integration server Jenkins.

Advantages of Continuous Deployment approach: decreases feedback loop time and manual labor overhead.

Pair Programming

Pair Programming is a technique when two developers work together on one machine. One of the developers is a driver and the other is observer. The driver writes the code and the observer watches it, assists, and makes suggestions. Then they switch the roles. The driver has a more tactical role of focusing on the current task. In contrast, the observer has a more strategic role overseeing “the bigger picture,” and the ways to improve the codebase and to make it more efficient.

Advantages of Paired Programming:

  • Pair attributes to shorter and more efficient codebase, and introduces fewer bugs and defects.
  • As an added bonus, knowledge is passed along programmers as they work together. However, situations of conflicts between developers are possible.

Node.js

Node.js is an event-driven asynchronous I/O server-side technology for building scalable and efficient web servers. Node.js consists of Google’s V8 JavaScript engine.

The purpose and use of Node.js is similar to Twisted for Python and EventMachine for Ruby. The JavaScript implementation of Node was the third one after attempts at using the Ruby and C++ programming languages.

Node.js is not in itself a framework like Ruby on Rails; it’s more comparable to the pair PHP+Apache. Here are some of Node.js frameworks: Express, Meteor, Tower.js, Railsway JS, Geddy, Derby.

Advantages of using NodeJS:

  • Developers have high chances of familiarity with JavaScript due to its status as a de facto standard of the application development for web and mobile.
  • One language for front-end and back-end development speeds up coding process. A developer’s brain doesn’t have to switch between different syntaxes. The learning of methods and classes goes faster.
  • With NodeJS, you could prototype quickly and go to market to do your customer development and customer acquisition early. This is an important competitive advantage over the other companies, which use less agile technologies, e.g., PHP and MySQL.
  • NodeJS is build to support real-time applications by utilizing web-sockets.

For more information go to Wikipedia, Nodejs.org, and articles on ReadWrite and O’Reilly.

NoSQL and MongoDB

MongoDB, from huMONGOus, is a high-performance no-relationship database for huge data. NoSQL concept came out when traditional Relational Database Management Systems, or RDBMS, were unable to meet the challenges of huge amounts of data.

Advantages of using MongoDB:

  • Scalable due to distributed nature: multiple servers and data centers could have redundant data.
  • High-performance: MongoDB is very effective for storing and retrieving data, not the relationship between elements.
  • Key-value store is ideal for prototyping because it doesn’t require one to know the schema and there is no need for a fixed data model.

Cloud Computing

Could computing consists of:

  • Infrastructure as s Service (IaaS), e.g., Rackspace, Amazon Web Services;
  • Platform as a Service (PaaS), e.g., Heroku, Windows Azure;
  • Software as a Service (SaaS), e.g., Google Apps, Salesforce.com.

Cloud application platforms provide:

  • scalability, e.g., spawn new instances in a matter of minutes;
  • easy deployment, e.g., to push to Heroku you can just use $ git push;
  • pay-as-you-go plan: add or remove memory and disk space based on demands;
  • usually there is no need to install and configure databases, app servers, packages, etc.;
  • security and support.

PaaS are ideal for prototyping, building minimal viable products (MVP) and for early stage startups in general.

Here is the list of most popular PaaS solutions:

HTTP Requests and Responses

Each HTTP Request and Response consists of the following components:

  1. Header: information about encoding, length of the body, origin, content type, etc.;
  2. Body: content, usually parameters or data which is passed to the server or sent back to a client;

In addition, HTTP Request contains:

  • Method: There are several methods; the most common are GET, POST, PUT, DELETE.
  • URL: host, port, path;
  • Query string, i.e., everything after a question mark in the URL.

RESTful API

RESTful (REpresentational State Transfer) API became popular due to the demand in distributed systems where each transaction needs to include enough information about the state of the client. In a sense this standard is stateless because no information about the clients’ state is stored on the server, thus making it possible for each request to be served by a different system.

Distinct characteristics of RESTful API:

  • Has better scalability support due to the fact that different components can be independently deployed to different servers;
  • Replaced Simple Object Access Protocol (SOAP) because of the simpler verb and noun structure;
  • Utilizes HTTP methods: GET, POST, DELETE, PUT, OPTIONS etc.

Here is an example of simple Create, Read, Update and Delete (CRUD) REST API for Message Collection:

Method URL Meaning
GET /messages.json Return list of messages in JSON format
PUT /messages.json Update/replace all messages and return status/error in JSON
POST /messages.json Create new message and return its id in JSON format
GET /messages/{id}.json Return message with id {id} in JSON format
PUT /messages/{id}.json Update/replace message with id {id}, if {id} message doesn’t exists create it
DELETE /messages/{id}.json Delete message with id {id}, return status/error in JSON format

REST is not a protocol; it is an architecture in the sense that it’s more flexible than SOAP, which is a protocol. Therefore, REST API URLs could look like /messages/list.html or /messages/list.xml in case we want to support these formats.

PUT and DELETE are idempotent methods, which means that if the server receives two or more similar requests, the end result will be the same.

GET is nullipotent and POST is not idempotent and might affect state and cause side-effects.

Further reading on REST API at Wikipedia and A Brief Introduction to REST article.

My Social Media Policies

Social media is developing rapidly. Only 5–10 years ago our lives and communications didn’t spin around Facebook, Twitter, Instagram and Path. I consider myself being somewhere in the middle of the adoption curve because two years ago I had less than 200 Facebook friends and no Twitter or Instagram accounts. Nevertheless, I find social networks greatly enhancing my life and allowing me to communicate better and more efficient with the people who are on these networks.

Social media is developing rapidly. Only 5–10 years ago our lives and communications didn’t spin around Facebook, Twitter, Instagram and Path. I consider myself being somewhere in the middle of the adoption curve because two years ago I had less than 200 Facebook friends and no Twitter or Instagram accounts. Nevertheless, I find social networks greatly enhancing my life and allowing me to communicate better and more efficient with the people who are on these networks.

Social Media
Social Media

Facebook

I request to be friends with any person I’ve met in real life. This is my way of introducing myself. I rarely friend people I’ve never met in real life.

Twitter

I follow all my friends and any interesting company or person.

Instagram

I post my own photos and almost none of them depict any of my friends.

Google Plus

I put in my circles and follow all of my friends and some of the people with whom we’ve exchanged emails.

LinkedIn

I connect to anybody with whom we’ve exchanged communication means.

Foursquare and Path

I follow my real friends and don’t let strangers for geosecurity reasons.

Pinterest

I follow random people mainly based on contents of their boards.

Here, in the Silicon Valley and San Francisco, it’s often easy to forget that there’re some people who are not on social networks yet. Saying that, I think it would be a hard thing for me to be a real friend with somebody who doesn’t have a Facebook account — it’s just weird!

Wintersmith — Node.js static site generator

This past weekend was a very productive one for me, because I’ve started to work on and released my book’s one-page website —rapidprototypingwithjs.com. I’ve used Wintersmith to learn something new and to ship fast. Wintersmith is a Node.js static site generator. It greatly impressed me with flexibility and ease of development. In addition I could stick to my favorite tools such as Markdown, Jade and Underscore.

This past weekend was a very productive one for me, because I’ve started to work on and released my book’s one-page website —rapidprototypingwithjs.com. I’ve used Wintersmith to learn something new and to ship fast. Wintersmith is a Node.js static site generator. It greatly impressed me with flexibility and ease of development. In addition I could stick to my favorite tools such as Markdown, Jade and Underscore.

Wintersmith is a Node.js static site generator

Why Static Site Generators

Here is a good article on why using a static site generator is a good idea in general, An Introduction to Static Site Generators. It basically boils down to a few main things:

Templates

You can use template engine such as Jade. Jade uses whitespaces to structure nested elements and its syntax is similar to Ruby on Rail’s Haml markup.

Markdown

I’ve copied markdown text from my book’s Introduction chapter and used it without any modifications. Wintersmith comes with marked parser by default. More on why Markdown is great in my old post, Markdown Goodness.

Simple Deployment

Everything is HTML, CSS and JavaScript so you just upload the files with FTP client, e.g., Transmit by Panic or Cyberduck.

Basic Hosting

Due to the fact that any static web server will work well, there is no need for Heroku or Nodejitsu PaaS solutions, or even PHP/MySQL hosting.

Performance

There are no database calls, no server-side API calls, no CPU/RAM overhead.

Flexibility

Wintersmith allows for different plugins for contents and templates and you can even write you own plugin.

Getting Started with Wintersmith

There is a quick getting started guide on github.com/jnordberg/wintersmith.

To install Wintersmith globally, run NPM with -g and sudo:

$ sudo npm install wintersmith -g

Then run to use default blog template:

$ wintersmith new <path>

or for empty site:

$ wintersmith new <path> -template basic

or use a shortcut:

$ wintersmith new <path> -T basic

Similar to Ruby on Rails scaffolding Wintersmith will generate a basic skeleton with contents and templates folders. To preview a website, run these commands:

$ cd <path>
$ wintersmith preview
$ open http://localhost:8080

Most of the changes will be updates automatically in the preview mode except for the config.json file.

Images, CSS, JavaScript and other files go into contents folder.
Wintersmith generator has the following logic:

  1. looks for *.md files in contents folder,
  2. reads metadata such as template name,
  3. processes *.jade templates per metadate in *.md files.

When you’re done with your static site, just run:

$ wintersmith build

Other Static Site Generators

Here are some of the other Node.js static site generators:

More detailed overview of these static site generators is available in the post, Node Based Static Site Generators.

For other languages and frameworks like Rails and PHP take a look at Static Site Generators by GitHub Watcher Count and the “mother of all site generator lists”.