I wanted to recreate an existing ObjectiveC app I had using Meteor, but there was one problem: the app has two versions, a paid and a lite version.

mobile-config.js

I was thinking of just using Meteor.settings and adjusting my mobile-config.js like this:

if(Meteor.settings.paid) {
 App.icons({
 ‘iphone’: ‘resources/paid/Icon-60.png’,
 ‘iphone_2x’: ‘resources/paid/Icon-60@2x.png’,
 ‘iphone_3x’: ‘resources/paid/Icon-60@3x.png’,
 ‘ipad’: ‘resources/paid/Icon-76.png’,
 ‘ipad_2x’: ‘resources/paid/Icon-76@2x.png’
 });
} else {
  App.icons({
    'iphone': 'resources/free/Icon-60.png',
    'iphone_2x': 'resources/free/Icon-60@2x.png',
    'iphone_3x': 'resources/free/Icon-60@3x.png',
    'ipad': 'resources/free/Icon-76.png',
    'ipad_2x': 'resources/free/Icon-76@2x.png'
  });
}

However, this does not work. Meteor.settings is not available when building your app.

Enter environmental variables. By setting one, you can control the build phase! So to build your two targets you can …

SV_VARIANT=paid meteor build --server your-server.com --mobile-settings settings.json ../build/paid/
SV_VARIANT=free meteor build --server your-other-server.com --mobile-settings settingsfree.json ../build/free/

Meteor.settings

As you can see I specify two different settings files when building. These files contain a variable that defines whether it’s the free or the paid version.

{
    "free": true
}

In my templates I use two simple helpers to enable or disable various parts of the application.

Handlebars.registerHelper('isFree', function () {
  return Meteor.settings.public.free;
});
Handlebars.registerHelper('isPaid', function () {
  return !Meteor.settings.public.free;
});

Example:

{{#if isPaid}}
  {{> ionTab title="Bookmarks" path="bookmarks" iconOff="ios-bookmarks-outline" iconOn="ios-bookmarks"}}
  {{> ionTab title="Landmarks" path="countries" iconOff="ios-flame-outline" iconOn="ios-flame"}}
{{else}}
  {{> ionTab title="Premium" path="premium" iconOff="ios-heart-outline" iconOn="ios-heart"}}
{{/if}}

Two servers

One thing that still bothers me with this approach is that I need two servers to run the app. Meteor will auto-update the mobile clients Meteor.settings with those specified on the running server. I tried retrieving the app name with a Cordova plugin but it wouldn’t work.

If anyone knows a way to make this better, please respond in the comments.

Automating things with NPM

Too bad you can’t extend the Meteor CLI to run custom tasks. To build and deploy my two versions of the app I tapped into the power of NPM.

With a package.json file in the root directory of your project you can add custom commands (thanks Differential).

My package.json:

{
  "name": "streetview",
  "scripts": {
    "clean": "rm -rf ../build/",
    "clean-free": "rm -rf ../build/free/",
    "clean-paid": "rm -rf ../build/paid/",
    "build-ios": "SV_VARIANT=paid meteor build --server paid-server.com --mobile-settings settings.json ../build/paid/",
    "build-ios-free": "SV_VARIANT=free meteor build --server free-server.com --mobile-settings settings-free.json ../build/free/",
    "deploy": "modulus deploy -p streetview",
    "deploy-free": "modulus deploy -p streetview-free"
  }
}

This allows me to type and be on my way to the app store:

npm run build-ios
npm run build-ios-free
npm run deploy
npm run deploy-free

A little bit of advertising

You can download the paid version of my app here and the free versionhere.

(There’s something wrong with the App Store cache at the moment, sometimes it still downloads the old version of the free version and tells you that there’s an update available … strange)