Nomad Couple

I’m Indian, and my girlfriend is Polish. We love travelling and we’d like to visit a lot of places, but there are surprisingly few countries that I can visit without a visa. Getting a visa can be tedious. (Quite often, I’ve had to personally visit consulates and submit bank account statements, travel insurance and cover letters along with my visa application form). Finding countries that allow both of us to visit without a visa or obtain a visa on arrival is hard. That’s why it occurred to me to build Nomad Couple, a website that provides information on visa requirements for couples.

Nomad Couple home page

Nomad Couple search results

The site was built as an experiment with Angular2. I set up the repo using angular-cli, a wonderful tool that makes it easy to build an Angular2 site and deploy it on GitHub Pages. Having spent some time in the “Javascript fatigue”-inducing React ecosystem, it’s refreshing to be able to set up a project and get going quickly with angular-cli. (Side note: It looks like Facebook is finally acknowledging how complex it is to get started with a React app by creating its own CLI tool).

At the moment, the site groups countries based on visa requirements and links to WikiVoyage pages. I’d like to provide more information on each country through multiple data sources, the abilitiy to add links and pictures, and a Disqus comments section.

The data for the site was scraped from Wikipedia’s “Visa requirements for X citizens” pages. The source code for the scraper is available here.

Sending emails from Ghost with Nodemailer and SparkPost

While I personally prefer Jekyll to Ghost in the battle of minimalistic CMS platforms, I recently set up a Ghost blog for work and connected the built-in Nodemailer email module with SparkPost, an email service. Here’s how:

  1. Set up a SparkPost account and verify your sending domain.
  2. Go to SparkPost Accounts –> SMTP Relay and copy the host, port and username.
  3. Under Accounts –> API Keys, select the Send via SMTP permission and generate a new API key. The generated API key will be your SMTP password.
  4. Open up your Ghost blog’s config.js, and modify the production section.
  production: {
    url: 'https://example.com/blog',
    mail: {
      from: '"Example.com Blog" <no-reply@example.com>',
      transport: 'SMTP',
      options: {
        host: 'smtp.sparkpostmail.com',
        port: 587,
        auth: {
          user: 'SPARKPOST_SMTP_USERNAME',
          pass: 'SPARKPOST_SMTP_API_KEY'
        }
      }
    },
    database: {
    ....
    }
  }

You can test your configuration by inviting someone to your Ghost installation. The invitee should receive an email from Example.com blog.

Setting up CORS with pre-flight request handling for development use in Node + Express

“Cross-Origin Resource Sharing” (CORS)-related errors are a common occurrence while developing a site with a separate frontend and API backend. While the cors module can set headers and respond to pre-flight requests, I didn’t find any documentation to set it up only in the Node development environment (assuming you don’t want to expose your APIs to requests from multiple domains).

const express = require('express');
const app = express();

if (app.get('env') === 'development') {
  console.log('Enabling CORS');
  app.use(function(req, res, next) {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,PATCH,OPTIONS');
    res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With'); //Add other headers used in your requests

    if ('OPTIONS' == req.method) {
      res.sendStatus(200);
    } else {
      next();
    }
  });
}

//Set up express routes here

This enables CORS for all Express routes and responds to pre-flight OPTIONS requests with HTTP status OK (200) only during development. If you haven’t already set your NODE_ENV to development, you can do so and start your server like so

NODE_ENV=development node index.js

URL Redirection With BrowserSync

I started working on GapSquad’s website recently, and I had to redirect some URL requests in the Gulp+Browsersync dev environment to alternate paths in the project directory (to recreate the behaviour of the nginx production server). This can be done using Browsersync options.

The project structure is organized like this

app
- - - pages
- - - - - - jobs.html
- - - - - - pricing.html
- - - - - - how-it-works.html
- - - index.html

index.html has references to /pricing, /jobs and /how-it-works, all of which are redirected to the corresponding HTML files in the pages directory on the production server using nginx configuration.

I wanted to use Browsersync locally and recreate the behaviour of the server, without rewriting links specifically for the dev environment.

Option 1 - Use a middleware

Browsersync lets you define middleware to manipulate request and response data. I used it to rewrite /pricing to /pages/pricing.html in my Browsersync Gulp task.

browserSync.init({
    server: {
      //Middleware paths are relative to the base directory
      baseDir: 'app'
    },
    middleware: function(req,res,next) {
      if (req.url === '/pricing') {
        req.url = '/pages/pricing.html';
      } else if (req.url === '/how-it-works') {
        req.url = '/pages/how-it-works.html';
      } else if (req.url === '/jobs') {
        req.url = '/pages/jobs.html';
      }
      return next();
    }
  });

When the request URL matches the ones that need to be redirected, I’ve simply replaced the request URL with the file path. You can also use JS regular expressions to match and redirect URLs.

Option 2 - Define server routes

The more straightforward option is to define routes in the server config.

browserSync.init({
    server: {
      baseDir: 'app',
      //Route paths are not relative to the base directory
      routes: {
        '/pricing': 'app/pages/pricing.html',
        '/how-it-works': 'app/pages/how-it-works.html',
        '/jobs': 'app/pages/jobs.html'
      }
    }
  });

Jekyll updates

I’ve been exploring the Jekyll ecosystem over the past couple of weeks, and consider me sold - I really like the simplicity of building a static site with pages, posts and collections. I know that neither Jekyll nor Ghost will dethrone WordPress as the layman’s choice of CMS, but given all of the work coming out of the node.js and Ruby camps, WordPress has got some stiff competition, and deservedly so.

Project Structure

While setting up a new Jekyll 3.0-powered site based on the Lanyon theme wasn’t hard, choosing a project structure that works for me took some time. I wanted my posts to be grouped within folders based on the category name, so I use this structure

  _posts
    - tech
      - 2016-04-14-tech-post-title.md
      - 2016-03-29-another-tech-post-title.md
    - travel
      - 2016-04-10-travel-post-title.md
      - 2016-03-09-another-travel-post-title.md

If you use Octopress, it’s easy to create a new post in a category with this command

   #Create a new post with the title "Post Title"
   #in the "tech" category with the current date
   octopress new post "Post Title" -D tech

To maintain consistency, my _pages folder is organized like this:

   _pages
     - tech
       - index.html
     - travel
       - index.html

To get Jekyll to process these files, I had to add _pages to my include array in _config.yml

include: ["_pages"]

Pagination

I found that I needed Octopress and octopress-paginate to set up paginated categories. I created a new file in _layouts called category-page.html with this content


---
layout: default
---
{% raw %}
<div class="page">
  <h1 class="page-title">{{ page.paginate.category }}
      {% if paginator.page > 1 %}
        - Page {{paginator.page}}
      {% endif %}
  </h1>

  <div class="posts">
    {% assign index = true %}
    {% for post in paginator.posts %}
    {% assign content = post.content %}
    <div class="post">
        <h2 class="post-title">
          <a href="{{ post.url }}">
            {{ post.title }}
          </a>
        </h2>
        <span class="post-date">{{ post.date | date_to_string }}</span>
        {{ post.excerpt }}
    </div>
    {% unless post == paginator.posts.last %}
    	<hr>
    {% endunless %}
    {% endfor %}
  </div>

    <div class="pagination">
      {% if paginator.next_page %}
      <a class="pagination-item older" href="{{paginator.next_page_path}}">Older</a>
      {% else %}
      <span class="pagination-item older">Older</span>
      {% endif %}
      {% if paginator.previous_page %}
      {% if paginator.page == 2 %}
      <a class="pagination-item newer" href="/{{page.paginate.category}}">Newer</a>
      {% else %}
      <a class="pagination-item newer" href="{{paginator.previous_page_path}}">Newer</a>
      {% endif %}
      {% else %}
      <span class="pagination-item newer">Newer</span>
      {% endif %}
    </div>
</div>
{% endraw %}

Setting up a paginated category page is simply a matter of using layout: category-page. For example, this is my _pages/tech/index.html

---
layout: category-page
title: Tech
permalink: "/tech/"
paginate:
  category: "tech"
---

SASS

I’m a big fan of SASS, and I was happy to discover that Jekyll has built-in support for SASS. I’ve also taken to inlining critical CSS (this long and insightful talk by Addy Osmani helped me see the light) and I wanted to set it up for my site. A little bit of Google-fu led me to this gist and this post that solved my problem without having to use Grunt or Gulp.

Deploying to Github Pages

Lastly, since this site is hosted on Github Pages and Github approves a limited set of plugins (Octopress not being one of them), I had to resort to manually building and deploying my site. This can be done by setting up a _deploy.yml according to the specification here and running

   octopress deploy

Warning: Be sure to have a clean working environment by stashing/committing your files before running this command. I accidentally published a bunch of temp posts I’d created to test pagination because they were present (untracked , not stashed or committed) in the _posts folder and they ended up in the resulting Jekyll build. That’s what you get for not reading the manual

Pagespeed insights score for the site: 99/100 on both mobile and desktop