Forge v2.7 Migration Guide

header-image Forge v2.7 Migration Guide

This article provides information to assist users in migrating Trigger.IO Forge apps from v2.6.x of the platform to v2.7.x.


If your application is currently built against v2.6.x of the Forge platform it is important that you migrate to v2.7.x so that your application will continue to run on the latest Android “Pie” and iOS 12 releases.

There is in-depth information below but the major changes you need to be aware of are:

  1. The API’s for our topbar and display module have been overhauled in order to consolidate all statusbar-specific API methods and configuration keys into the forge.display namespace.
  2. The API’s for Camera and Microphone capture have been moved out of the file module and into the capture module.
  3. Support for Android Adaptive Icons.
  4. Support for Android Display Cutouts.
  5. Our httpd module now features SSL support.
  6. Modules that need to be updated to the latest versions are:
    • display
    • file
    • capture
    • httpd
    • icons
    • tabbar
    • tabs
    • topbar
    • permissions
    • geolocation
    • contact
    • calendar
    • parse

The full changelog for this release can be found in the Release Notes.

Let’s take a detailed look at the steps needed to update your app for Forge Platform v2.7.

Step 1: update to 2.7.1

Edit your app’s src/config.json file and set:

Step 2: update modules

Edit your app’s src/config.json file and, for the modules you use, update as follows:


  • update to "version": "2.9"


  • Add the capture module to your project if you are using the file module to capture photos or video.


  • update to "version": "2.12"


  • Update to "version": "2.11"
  • Update for new config & API’s


  • Update to "version": "2.23"
  • Update API’s if you are using the file module to capture photos or video.


  • update to "version": "2.8"


  • Update to "version": "0.9"
  • It’s no longer necessary to use forge.httpd.normalize() if you are using the httpd module.


  • Update to "version": "2.9"
  • Add adaptive icons for Android


  • Update to "version": "2.7"


  • Update to "version": "2.23"


  • Update to "version": "2.15"


  • update to "version": "2.19"


  • update to "version": "2.0"

Step 3: Update topbar and display configurations and API usage

We’ve consolidated all configuration and API’s related to app native status bar elements into the display module.

Migrate configuration: display and topbar

All app native status bar configuration can now be done via the display module.

The new format looks like this:

For example, if you previously set the status bar style via the topbar module:

…you would move the configuration to with a value of light_content.

Migrate API usage: forge.topbar.setStatusBarStyle()

The forge.topbar.setStatusBarStyle() API method has been moved to forge.display.setStatusBarStyle() and the argument has been changed to one of default or light_content.

So, for example if you had:

…you would rewrite it as:

Migrate API usage: forge.file.getImage() and forge.file.getVideo()

Apple are tightening their review criteria to reject apps that request device permissions which are not directly related to the functionality of an app.

Not everyone using the file module needs access to the device camera and microphone so this has made it necessary for us to move those functions to a new module called capture.

If you are currently using the forge.file.getImage() and forge.file.getVideo() API’s to capture new photos or videos you will therefore need to migrate to the new capture module.

Luckily this is as easy as:

  1. add the capture module to your app
  2. rename all usages of forge.file.getImage( ... ) to forge.capture.getImage( ... ).
  3. rename all usages of forge.file.getVideo( ... ) to forge.capture.getVideo( ... ).

Optional: Add adaptive icons for Android

Adaptive icons are not strictly compulsory as Android will still use the legacy icons:

The icon on the left is an example of how legacy icons will be rendered on a device with adaptive icon display support whereas the icon on the right shows what an adaptive icon would look like.

The primary difference between the two icon formats is that adaptive icons include a “safe zone” around the icon image which allows the device to crop the image to any custom mask shapes in use by the device.

For more information on using adaptive icons please see the icons module documentation.

Optional: Configure display cutout behavior for Android

To accommodate the rounded corners and display cutouts that are quickly becoming pervasive in the smartphone market Android “Pie” has added three new window layout modes to control how your app content is displayed on devices with non-uniform displays.

To set the particular mode used by your app you will need to edit your app’s src/config.json file and add a configuration entry for as follows:

Where value can be one of:


always: Your app will be automatically adjusted to always lie within the “safe” area of the device and will never extend into any of the cutout areas.


short_edges: Content renders into the cutout area while in portrait mode, but content is letterboxed while in landscape mode. It is your responsibility to ensure that your app does not render content over any of the cutout


never: Your app content will extend into the cutout area on the short edge of the display in both portrait and landscape, regardless of whether the system bars or hidden or visible. It is your responsibility to ensure that
your app does not render content over any of the cutout areas.

Optional: Adjust your app layout to account for display cutouts

If you are using one of never or short_edges for the adjust_content_insets mode you will need to know the dimensions of the cutout area so you can adjust your layout accordingly.

There are currently two methods available to do this:

The first is to use the special safe-area-inset-* CSS environment variable being rolled out in the newest versions of the Chrome WebView. For more information see the Chrome 69 Beta: CSS tricks, and more blog post and scroll down to the “Display cutouts” section.

If the CSS method does not work for you, you can also use the forge.layout.getSafeAreaInsets(success, error) API call to do something along the following lines during your app’s startup:

Optional: Configure httpd for SSL

Some apps hosting complex content (e.g. iframes containing content served via https) may run afoul of WebView mixed content security policies.

To solve this problem we now support the configuration of a SSL certificate for the httpd module that will allow you to serve your app content via https://.

What you will need to do:

  1. Generate a self-signed SSL certificate for localhost. The website has a nice overview

  2. Convert your SSL certificate to PKCS #12 (.p12) format format and set a password when prompted:

  3. Copy your localhost.p12 certificate file to your app’s src/ directory.

  4. Edit your app’s src/config.json file and edit the httpd module configuration:


Please don’t hesitate to join us on the Forge 2.7 Community Forum Topic if you have any questions around the update process or run into any difficulties! Forge v2.6 Migration Guide

header-image Forge v2.6 Migration Guide

This year we’ve tried something different by synchronizing the next major Forge update with both the latest Android “Oreo” and iOS 11 releases.

In future we’ll continue to synchronize both our Android and iOS updates to Apple’s annual release cadence. This will see a new major version released every year in the first few weeks of September.

What this means for our customers is that, here on out, you will be able to rely on us to follow a predictable release cycle.

Being able to schedule the testing & updates for your apps well in advance and on both operating systems concurrently will reduce your costs considerably while increasing everyone’s happiness.

A reason to smile :-)

We’re also happy to announce that the latest Android and iOS releases have far less changes this year affecting Trigger.IO apps directly.

We’ll go into more detail below but the major changes you need to be aware of are:

  • iOS now requires a 1024x1024 pixel Marketing Icon.
  • A number of modules will need to be updated to the latest versions: display, file, icons, launchimage, notification, parse, platform, request, tabbar, tabs, topbar and tribr_multi_image_select.
  • Google have restricted some Android WebView API’s from working with content served directly off the device filesystem. This may require your app to use the httpd module.
  • The iPhone-X features rounded corners and a “notch” which can complicate page layout on iOS.
  • The minimum Android version supported is now: Android API Level 14.
  • The minimum iOS version supported is now: iOS 9.3
  • The proprietary facebook module has been deprecated in favour of a standards-based OAuth 2.0 solution.
  • The crosswalk build target has been updated to: 23.53.589.4 (Please note that Intel have announced they will no longer be maintaining the project so this is in all likelihood the final update the target will receive.)

The best part of the improved backwards compatibility achieved by Apple & Google this year is that we got to spend more time on new features we think you’ll love and give you even more reasons to smile!

These include:

  • Experimental support for iOS WKWebView. (For real this time!)
  • Experimental support for JavaScript ES6 Promises.
  • A complete overhaul of the forge.request module with full HTTP/2 & SNI support and better compatibility with Android 4.x devices.
  • A new module, forge.fs, which provides a full device filesystem API and file picker that is no longer limited to images & videos.
  • A new module, forge.oauth, which provides an “OAuth 2.0 for Native Apps” implementation.

We’ll be releasing detailed tutorials for each of the new modules in the upcoming weeks.

For now, let’s take a detailed look at the steps needed to update your app for Forge Platform v2.6.

Step 1: update to 2.6.3

Edit your app’s src/config.json file and set:

Step 2: update modules

Edit your app’s src/config.json file and, for the modules you use, update as follows:


  • Update to "version": "2.8"


  • Update to "version": "2.18"


  • Update to "version": "2.8"
  • Add a new 1024×1024 marketing icon for ios:


  • Update to "version": "2.13"


  • Update to "version": "2.5"


  • Update to "version": "2.8"


  • Update to "version": "2.17"


  • Update to "version": "2.3"


  • Update to "version": "2.10"
  • While every effort has been made to ensure backwards compatibility it is possible that you may run into some subtle differences in behaviour. If you do run into any issues please get hold of us on!


  • Update to "version": "2.6"


  • Update to "version": "2.18"


  • Update to "version": "2.13"


  • Update to "version": "1.4"

Optional: configure content inset behavior on the iPhone-X

To accommodate the rounded corners and “notch” of the iPhone-X Apple have introduced the idea of so-called “safe areas”.

By default Forge apps will limit the accessible portion of your app’s web view to the following area defined by the notch and corners:

iPhone-X Safe Area

To give your app full access to the full extent of the webview you will need set the content insets as follows:

Optional: enable httpd module

Historically Forge apps have served their content directly from the device filesystem using the file:// scheme.

Over time this has created more and more problems as Google or Apple continue to introduce restrictions targeting the http:// and https:// schemes without considering their impact on other RFC 1630 URL types.

With the latest version of Android “Oreo” 8.0 (API level 26) we’ve identified the following features that are directly impacted by this:

  • WebSockets
  • IndexedDB

If your app uses one or more of these features you will need to enable the httpd module for your app.

Edit your app’s src/config.json file to give Forge access to http://localhost/* URL’s:

…and then add the httpd module:

It is unlikely that this trend will reverse so in the future we will be compiling the httpd module in by default and deprecating support for loading content directly from the device filesystem.

You can find more information on this community forum thread: Issues with IndexedDB & WebSockets on Android

Optional: replace facebook module with oauth module

If you are currently using the facebook module, this will be the hardest part of the migration.

The steps involved boil down to:

  1. Remove the facebook module from your app.
  2. Add the oauth module to your app.
  3. Configure the oauth module’s providers section with your Facebook credentials.
  4. Set up a static web page to handle the OAuth redirect call from Facebook.
  5. Replace any Facebook module API calls with calls to the Facebook REST API’s and the share module.

We’ll be releasing an in-depth guide over the next few weeks but, for the very brave, we have an example on the module documentation page.

Finally, if you’re in a hurry and don’t want to wait, please reach out to us on We’ll be happy to answer your questions and provide assistance with migration.

Optional: enable experimental support for iOS WKWebView

With iOS 11 Apple have finally addressed the many long-standing issues preventing WKWebView from being a full replacement for UIWebView.

You can enable experimental WKWebView support for your app by editing your app’s src/config.json file:

If your app makes use of XHR requests (e.g. for Ajax or dynamic script includes) you will also need to add the httpd module as Apple have restricted WKWebView to only allow XHR requests from CORS-configured endpoints. See the Optional: enable httpd module section above for instructions.

The WKWebView features required to integrate fully with Forge are only available on iOS 11 devices so the default behavior is to automatically fall back to UIWebView on earlier iOS devices.

You can force WKWebView to be used on older iOS devices as well by adding the following flags configuration:

Please note that some Forge features can not be supported in this configuration.

Amongst other issues, you will find that you are unable to embed content from your device’s asset stores in your app.

Optional: enable experimental support for JavaScript ES6 Promises

Open your app’s src/config.json file and add a new top-level section as follows:

Now you can finally replace this:

…with this:

Yay! 😄

We’ve bundled a Polyfill for backwards-compatibility so this should also work on older Android and iOS versions.

For more info, check out: “JavaScript Promises: an Introduction”


New Android and iOS releases are always a little stressful. Please don’t hesitate to join us on the Forge 2.6 Community Forum Topic if you have any questions around the update process or run into any difficulties!

Outage Postmortem – 18th October 2016



Starting on Friday, the 14th of October 2016, we experienced a succession of increasingly severe network failures which culminated in a near total service outage by 01h30 UTC on Tuesday the 18th.

As a result many of our customers were unable to access the Trigger.IO website, Toolkit or Build servers during this time.

The failure first became visible on Friday afternoon when we received a support email from a customer who was unable to perform builds. At the time our monitoring system showed no problems and the customer replied to my initial queries that the problem had resolved itself.

I was puzzled but ended up writing the incident off as a brief routing problem on the wider Internet and did not think about it again until the emails started flooding in late Monday night.

At this point in time our monitoring system was still reporting 100% uptime and I had no difficulty accessing any of our infrastructure from the office.

This was about to change.

At 01h30 UTC I observed a rapid rise in the failover graph followed by most of the individual server monitors turning red.

By 3h00 UTC we discovered that a network router responsible for one of our server instances had failed and we took that region offline.

Recovery was almost immediate but we still had no clear picture of what had happened or the full extent of downtime experienced by our customers.


  • We were contacted by 12 different customers who experienced an outage during this period.
  • The shortest period reported was 1 hour starting around 02h00 UTC.
  • The longest period reported is an estimate of 3-4 days starting late Saturday or early Sunday.
  • 5 of the affected customers are based in California, USA.
  • 3 of the affected customers are baed in other parts of the USA.
  • 1 of the affected customers is based in Germany.
  • 3 of the affected customers are based in the United Kingdom.

What Happened?

1) For an unknown period of time a network router in the West Coast, USA data center region has been experiencing intermittent hardware failures.

2) Specifically, the router’s BGP table was experiencing corruption which prevented it from routing traffic originating from some regions of the Internet.

3) Around Friday the router’s rate of failure started to increase and by 01h30 UTC on Tuesday morning it was going through a rapid cycle of failures and recoveries.

4) This caused our failover system to start receiving conflicting information about server availability resulting in a cascade of increasingly rapid switchovers of traffic between server regions and ultimately leading to a global service outage.

5) Because our monitoring system was not on a network affected by the router in question we were only able to detect the failure by the time we experienced a global outage.

6) Because our monitoring system checked for host uptime rather than individual API endpoint availability we were unable to monitor metrics that could have helped us identify routing failures earlier.

A big thank you to all the Trigger.IO customers who provided information that helped us to reconstruct what happened.


The following steps have been taken to ensure this does not happen again:

1) The faulty router hardware has been replaced.

2) We’ve added API availability checks to our failover system in addition to host checks.

3) We’ve amended our failover system to take a hysteresis factor into account before performing switch overs.

4) We’ve deployed a second monitoring service, not hosted on our infrastructure provider’s networks, that monitors our API endpoints from multiple international regions.

I know you rely on Trigger.IO to get work done and I’m sorry for the time you lost while we were down.

Having good uptime in the past is a bad reason for not paying more attention to the hard lessons other companies in our field have already learnt.

If you have any questions about the outage or would like to talk about what happened please get hold of me directly on

All the best,


General Manager @ Trigger.IO Forge v2.5 and iOS 10 Migration Guide

header-image Forge v2.5 and iOS 10 Migration Guide

Hey Trigger peeps!

The iOS 10 launch is upon us and it’s time to release the next major Forge platform update.

Every year Apple blesses us with some changes and, being a conscientious cross-platform framework provider, we do our best to minimize the impact on your team.

The shift is usually transparent but this year a few fundamentals have changed and will require a bit of work to get your app ready for iOS 10:

  • iOS 10 now requires app permission dialogs to display a short usage description explaining why it requires access to device features such as the camera, contacts and calendar.
  • iOS LaunchImages are no longer organized according to device screen resolution. Instead, they are now assigned to size classes. This is good news as it means that the number of separate image files required for iOS have gone down from 13 to only 4.
  • Apple are getting serious about App Transport Security (ATS) and, as of 01 January 2017, its use will be mandatory for all App Store submissions. If you are using the request module and your backend infrastructure is still running HTTP or not configured to modern SSL standards your app will be affected.

Let’s take a quick look at each of these and the steps you will need to take to update your app for Forge Platform v2.5.x.

Module upgrades for iOS 10

If you are using any of the following modules you will need to make sure they are on the latest version:

Module Min Version Notes
calendar 2.8 Requires a usage_description entry
contact 2.10 Requires a usage_description entry
file 2.12 Requires a usage_description entry
tribr_multi_image_select 1.3 Requires a usage_description entry
launchimage 2.10 Requires new launch images
request 2.8 Requires App Transport Security (ATS) configuration
icons 2.7 Requires an iPad Pro icon (167x167px)
barcode 2.5 No app changes required

Add usage descriptions to your module configuration

iOS 10 requires app permission dialogs to display a short usage description explaining why it requires access to device features such as the camera, contacts and calendar:

The affected modules are:

  • calendar – Requires a usage description for Calendars access.
  • contact – Requires a usage description for Contacts access.
  • file – Requires a usage description for Camera, Microphone and Photo Library access.
  • tribr_multi_image_select – Requires a usage description for Photo Library access.

To configure the usage description for each of the modules you can fill in the usage_description field in the config section of src/config.json or the module configuration page in the Toolkit.

For example, to configure the calendar module you can either edit your app’s src/config.json file directly:

…or you can access the configuration through the Toolkit:

Toolkit Configuration

Please note that trying to your app on iOS 10 without a usage description will result in your app exiting immediately when its API methods are invoked!

iOS LaunchImage Size Classes

Apple introduced the concept of adaptive layout in iOS 8 already but, as hybrid devs, we haven’t really been affected as it only applied to native user interfaces.

With the release of iOS 10 however Apple are now requiring the use of Storyboards for App launch screens which means that the old system of having a different launch image for each device pixel resolution falls away.

Instead, there are now only four launch images, one for each Size Class defined in Apple’s adaptive layout framework.

When you App launches, iOS will select the corresponding launch image for the Size Class corresponding to the type of device running the app and its orientation.

Step 1: Upgrade the launchimage module to v2.10

Please make a note of the settings for your Android launchimage configuration before updating!

With the breaking changes for iOS we took the opportunity to do a long-needed re-organization of the module configuration schema and give the properties for Android their own section.

Step 2: Generate new launch images for each size class

The concept of size classes can be somewhat confusing at first but we can get away with only needing to remember that there are four size classes and they are applied as follows:

Size Class Device Landscape Portrait Image Size
width: Compact height: Compact iPhone x 1334 x 750px
width: Compact height: Regular iPhone, iPhone Plus x 1080 x 1920px
width: Regular height: Compact iPhone Plus x 1920 x 1080px
width: Regular height: Regular iPad x x 2732 x 2048px

Step 3: Configure the launchimage module

Finally, to configure the launchimage module you can either use the Toolkit or simply edit your app’s src/config.json file to look something like:

For more information please see the launchimage module documentation.

App Transport Security (ATS)

In a nutshell, App Transport Security (ATS) is a requirement that all iOS App communication with remote servers via the request module use the HTTPS protocol and conform to the following minimum requirements:

  • Encrypted using AES-128 or better.
  • SHA-2 for certificates with either a 2048 bit or greater RSA key, or a 256 bit or greater Elliptic-Curve (ECC) key.
  • Tansport Layer Security (TLS) protocol must be v1.2 or greater.
  • All connection ciphers must be using forward secrecy.

This only applies to communication via the request module. Network access from the iOS WebView is still exempt from ATS.

Step 1: Upgrade the request module to v2.8

If you are already using HTTPS conforming to Apple’s security requirements for all communication with your backend infrastructure this is all you’ll have to do.

If you are still relying on HTTP for communication with backend infrastructure you will want to read the next steps!

Step 2: Disable ATS for development

Unless you are ready to roll-out SSL across your backend by this afternoon you’ll probably want a way to disable ATS during development.

Please be aware that submitting any iOS App built with this setting enabled to the App Store after 1 January 2017 will result in immediate rejection.

To disable ATS you can either edit your app’s src/config.json file:

…or modify the configuration via the Toolkit:


Step 3: Make a plan to upgrade your backend infrastructure to HTTPS

The most common obstacle to upgrading server infrastructure is that the cost & difficulty of getting set up with SSL certificates can be a major barrier for projects.

If this is the case for your project we’d like to recommend you check out Let’s Encrypt. Let’s Encrypt is a free, automated Certificate Authority that operates with support from a large number of sponsors such as Mozilla, the EFF, Chrome and Cisco.

The next most common obstacle to upgrading to SSL is that sometimes we rely on servers that are not under our direct control.

For these cases Apple have communicated that they will allow some temporary exceptions to smooth the transition, but the rules moving forward are strict:

  • Most exceptions will need to be justified to Apple. This will likely lead to delays during the approval process and may end with your app being rejected.
  • NSExceptionRequiresForwardSecrecy will not require a justification for now. If used, this exception will be granted automatic approval. This is likely to change in future as forward secrecy becomes more widely spread.
  • NSExceptionAllowsInsecureHTTPLoads and NSExceptionMinimumTLSVersion will all require a reasonable justification for use.

Step 4: Configure ATS Exceptions (optional)

ATS Exceptions can be configured in the Toolkit via the “Configure iOS ATS” section of the request module configuration:


The fields should be self-explanatory but for more information you can read the request module documentation.

Don’t forget to re-enable ATS once you’ve configured any exceptions!

If you want to edit your app’s src/config.json file directly you may find the syntax is a little more obscure:

The format is an array of objects each with a domain and a set of one or more keys such as NSThirdPartyExceptionAllowsInsecureHTTPLoads that can be set to true for each kind of exception you want to add.

The example above corresponds to the Toolkit screenshot and it requests the following exceptions for all requests to the domain

  • Override ATS for HTTP requests to, a domain we do not control. If we did control this domain we’d have used the NSExceptionAllowsInsecureHTTPLoads key instead.
  • Override the Forward Secrecy requirement for any HTTPS requests to

You can find a full list of all the supported keys in Apple’s documentation.

Switch Your App To Forge v2.5

If you’ve come this far your app should be ready for testing on the iOS 10 and there are just two more steps you’ll need to take:

Step 1: Install Xcode 8

If you haven’t already got it, grab the Xcode 8 GM Seed from the Apple Developer Site and install it into your /Applications directory.

Step 2: Change your App’s Platform Version

Open your app’s src/config.json file, locate the platform_version key and set it to v2.5.1:

…and you should be ready to go!


You can keep track of further releases and known issues for this Release on the Platform Release Notes page.

If have questions or run into issues please check out the Forge v2.5 Platform Topic on the community forum.

Have fun!

Changes at HQ

Dear customers,

Many of you will be familiar with our company history but here’s a brief synopsis for those who have joined us more recently:

2011: Amir Nathoo and James Brady start with the mission to make it possible for web developers to build native mobile apps using HTML5.

2012: becomes publically available for the first time and the team grows to include Connor, Tim and myself.

2013: Amir & James make the difficult decision to step back from the day-to-day running of the business.

2014: I take on the role of General Manager and make a promise to support our customers and ensure the long-term availibility of the service.

2015: The service shows positive month-on-month growth and we announce v2.4 of the Platform, featuring Crosswalk support.

Today, I’m extremely excited to announce another historic is changing ownership!

I have come to an agreement with Amir&James to purchase and have incorporated a new entity “Trigger Corp, Inc.” that will provide ongoing development and support of the service.

What does this mean?

There will be no changes to the availability of the service, subscription plans or customer support.

My promise to you remains unchanged and I will continue to make decisions that place our customers and the long-term availaiblity of the service first.

Where the impact of this change will be felt most is in the long run.

The service is no longer beholden to the priorities of external investors and is now wholly free to evolve according to the needs of our customers.

How this evolution proceeds is something I look forward to discovering with you in the years ahead!

The fine print

We’ve updated the following legal notices:

Our Terms Of Service:

Our License Agreement:

Our Privacy Policy:

Whereas these agreements were previously with WebMynd Inc., they have now been transferred to Trigger Corp, Inc.

Trigger Corp, Inc. is a Delaware corporation and a wholly owned subsidiary of Zazpi (Pty) Ltd, Reg no: 2014/064494, a South African limited liability company with offices at:

35 Cockburn Rd

Glencairn Heights

Cape Town

South Africa 7975

No other changes have been made.

What’s next?

Earlier this year I promised that we’ll be providing an alternative to StackOverflow for community support and communication.

We’re live right now at: and I hope you will join me there if you have any questions regarding the ownership change.

I’m also available via email at if you have any questions or would like to set up a Skype call.

Finally, I’d like to thank Amir, James, Connor, Tim, David and the many good people who have worked with us over the years for the immense contribution they’ve made to the business and wish them the very best in their present and future endaevours.

All the best,

Antoine van Gelder
Software Engineer @

Open Source Spotlight: ngForge


Heya TriggerFolk!

This week we’re going to be taking a look at a great Open Source project started by user Andres Olave:

ngForge provides a set of idiomatic AngularJS wrappers for the
Forge modules that allow for easy & clean integration with Google’s AngularJS framework.

Here, in his own words, is Andres to tell you all about it…

An Introduction to ngForge

Angular & Trigger.IO are a great combination for developing mobile apps. Using either iOS or Crosswalk for Android it’s possible to build hybrid mobile apps we could only dream of in the past few years.

ngForge is a set of Angular wrappers for Forge modules with the aim to:

  1. Seemlessly switch between mobile & browser implementations
  2. Provide a AngularJS friendly experience:
    • Dependency Injection not globals.
    • Promises not callbacks.
    • $http API equivalency for the request module.
  3. Provide a basis for use in modern JS development:
    • Use the browser as the primary development environment – because there are many commonplace, well supported, free tools.
    • Don’t require builds in the browser environment.
    • Be optimised for standard JS build tools: Grunt, Gulp, etc.
  4. Allow services to be configured & reconfigured on the fly in browser mode.

How it works

Using AngularJS emphasises the use of dependency injection. The typical use is to inject services into controllers, or the Angular’s $http service into services.

Let’s say you are building a web app with a service that has a saveLocally method:

With ngForge you can now instead use $forgePrefs which delegates to the forge.prefs module when running as a mobile app, and to localStorage when running in a browser.

For example, we can inject it into any service implemented in Angular:

This way AngularJS allows us to implement the service before it provides the $forgePrefs service and ngForge can detect whether it is running in a mobile environment or a browser.

  • if it’s a mobile environment ngForge delegates all service calls to the module.
  • if it’s a browser environment ngForge:
    • returns mock data – for example $forgeContacts returns mock data.
    • and/or implements a mock version of the module – for example $forgePrefs delegates to localStorage in browser mode.

In fact even if ngForge doesn’t mock out a method, it is still able to delegate service calls to in mobile environment mode.

Promises NOT callbacks

The Forge module API’s are currently still based on Node.js-style callbacks which often lead to callback hell and are not a natural fit with Angular’s Promises-based approach to deferred and asynchronous computation.

ngForge extends the Forge Module API’s with support for Promises which allows you to use them in the same way as you would in your regular Angular app.

For example, using standard you’d access forge.prefs like this:

With Promises, it instead becomes:

Much cleaner wouldn’t you agree?

Service Configuration

In browser mode, ngForge services can be configured by using Angular config methods. You may want to configure:

  1. Mock data: for example the mock contact book data used by $forgeContact, or
  2. Implementation configuration, for example what key to store data under when using the localStorage version of $forgePrefs.

Each service documents what is configurable. Here is an example config:

Using $forgeHttp instead of the forge.request module’s forge.request module offers cross-origin access and native performance for HTTP request.

However, the request module’s API is based on a subset of the JQuery API and if you are using Angular it would be preferable to replicate the $http service API. (See the Angular $http service documentation for more details.)

This is what the $forgeHttp API looks like:

The following methods are not implemented as yet:

Additionally, the config object supports the following properties:

  • params{string|Object}: Params that are not already query strings are serialized as query strings and appended to the URL.
  • data{Object}: Data to be sent as the request message data. If it’s a get request then it is serialized as a query string and appended to the URL.
  • headers{Object}: Map of strings representing HTTP headers to send to the server.
  • cache{boolean|Object}: A boolean value or object created with $cacheFactory to enable or disable caching of the HTTP response.
  • timeout{number}: timeout in milliseconds
  • responseType{string}: See XMLHttpRequest.responseType.

All these methods return a promise that support the standard methods: then, catch & finally methods that take function with a single argument of the http response object. It also supports the deprecated success & error methods for handling responses. See the Angular Promises Documentation for more detail.

Results of GET are, by default, not cached. Caching is supported in the same way as in $http, that is, by default using simply the value true, or by an instance of $cacheFactory. (See the Angular $http caching documentation for more information)

We also support interceptors that allows you to implement cross cutting concerns for requests or response. Simply add interceptors to the $httpProvider as in the Angular documentation.

The future

AngularJS is a 3rd generation web framework but is already being replaced by 4th generation frameworks such as Angular2 & ReactJS. These feature simpler programming models, ECMAScript 2015 (or even TypeScript) & vastly superior performance.

There are some exciting updates coming that will make it possible for us to update ngForge with support for Angular 2 and Observables and we are planning broad framework support for ngForge in the near future.

I hope you enjoyed reading this quick introduction to ngForge.

Check the project out on GitHub and if you have any questions please feel free to drop me an email:

Big up to

7cups banner users are people we are proud to be associated with! The recent growth of is a testament to the kind of skill and effort we regularly encounter amongst the community.

The aim of the 7cups initiative is to provide online emotional support in a world with “an immense love deficit”. From their website:

7 Cups of Tea is an on-demand emotional health and well-being service. Our bridging technology anonymously & securely connects real people to real listeners in one-on-one chat.

Anyone who wants to talk about whatever is on their mind can quickly reach out to a trained, compassionate listener through our network. We have hundreds of listeners who come from all walks of life and have diverse experiences.

Glen Moriarty, Founder and CEO, is a psychologist who is passionate about the Internet’s power to help people lead better lives. He is joined by a team of professionals with a wide range of capabilities, from counselling and social work to engineering and web design.

As well as a running a succesful website and an app which is available on both IOS and Android, 7cups also maintains an active reddit community, and encourages academic research interest through their Open Research Platform

Working with


We asked Ezra Morse, the Full Stack Engineer at 7 Cups, to tell us a little about working with as a platform for development.

Q – Why did 7cups choose to work with

As the world’s largest emotional support network, 7 Cups is about bringing people together. The last thing we need is to sacrifice dev time on hunting for platform bugs, solving plug-in conflicts and triaging build issues. allowed us to swiftly convert a legacy, first-generation mobile website into a reactive one-page application with the native plug-ins we needed, while keeping our focus where it should be: on user experience and our community.

In the end, we were able to produce a lean, performant app that isn’t mired by stability issues or the long iterative cycles characteristic of a fully native app. We finally have a stable and evolving application that better positions us to reach more people in need.

Q – What is your overall experience of hybrid development in today’s market?

To be honest, wasn’t our first choice on this project. Let’s just say that our first pass at modernizing our app could be described as wanting to have our cake and eat it too.

We bought into too many promises and tried to relegate far too much functionality (UX included) to the native device, thereby leaving us with a slow, bloated hybrid-application that would crash as often as freeze. So we went from an extremely bad scenario where our concerns about speed and the memory footprint of the app simply didn’t allow us to take any chances.

If we wanted to keep our app hybrid, a cordova-flavor just wasn’t going to give us the lean and stable app we wanted to share with the world; we simply could not afford to have performance issues continue to stand in between the people on each end of the device.

In summary, I feel a lot of the hybrid approaches fail to keep it simple on both the application level and the build process, and thereby, the end product suffers. As hybrid developers, should we really need to focus on too much more than what is going on inside that single webview?

7cups screenshot

Thanks Ezra, for making the time to speak to us and fill us in on your development process. We look forward to many more collaborations in the coming months.

From everyone at, keep up the good work!

Discover Forge v2.4: Runtime App Permissions


Following our announcement of Forge Platform v2.4 earlier this month I’m pleased to present, as promised, our first article about the new features that landed with this release.

Today I’ll be covering the support we’ve added for managing iOS and Android runtime permissions and showing you:

  • How you can use our Runtime Permission features to increase your app install rates.
  • How to dynamically adapt your app to the permission preferences of your users.
  • How to save your users from an epic journey into their device preferences if they didn’t grant an app permission the first time round.

What Are Runtime Permissions?

Both iOS and Android apps execute inside a sandboxed environment which places hard restrictions on the device resources accessible by your app.

The goal of this sandboxed environment is to limit the amount of mischief a malicious or misbehaving app can inflict on your device.

In a perfectly secure world, apps would not be able to access any resource outside of their own environment. Unfortunately this would also mean we could not develop apps that make use of device features such as cameras, photo albums, geolocation or notifications.

The compromise then is for apps to explicitly request the user to grant specific “device permissions” to the app.

This informs your users of the device capabilities they are entrusting to your app, but it also places the onus on you, the app developer, to give the user a reason to trust you!

On older versions of Android, and a lesser extent iOS, the user was forced into an all-or-nothing decision about whether to grant access to resources during the initial app installation process.

Given how long the list of requested device permissions can get this unfortunately results in many users responding to such a big “ask” by simply not installing the app.

It’s a little hard to win your user’s trust if they’re not running your app in the first place, right? :-)

Luckily, with the release of Android Marshmallow, Forge v2.4 and our new forge.permissions module, users no longer have to make an upfront leap of faith as it’s now possible to incrementally request device permissions at runtime on both iOS and Android.

This helps your users feel more in control, while simultaneously giving you a chance to make a powerful case for the benefits of trusting you with their device.

Forge and Runtime Permissions

Up till now, the way we’ve dealt with runtime permission requests on iOS and Android Marshmallow has been to automatically trigger the system permission request dialog whenever a module calls a native API requiring that permission.

For example:

Which results in an app flow that looks like this:

Default Runtime Permissions Flow

The good news is that this behaviour has not changed with the release of v2.4 and if you’re satisfied with the way your app works you can stop reading right now. :-)

However, an important gotcha to be aware of is that both Android and iOS devices have the following behaviours hardcoded into their operating systems:

  • On Android: When a user clicks “No” the first time they are asked, they will have the option to prevent the app from making subsequent requests.
  • On iOS: When a user clicks “No” the first time they are asked, the app will be prevented from making subsequent requests.

What this means is that once a permission request has been denied, there is a high likelihood that the only way the user can grant that permission in future is by digging in their device’s System Preferences.

Or to put it another way, once a permission request has been denied (iOS) or disabled (Android) all future requests to will only ever trigger the error callback.

Not an ideal situation, but all is not lost!

We created the forge.permissions module to address precisely this problem and to help you get more control over when and how permission requests are presented.

How To Use The forge.permissions Module

Step 0: Update your platform version and modules to the latest versions

To use the forge.permissions module you need to be on at least platform version v2.4.1 and at least the following module versions:

module version
contact 2.9
calendar 2.7
geolocation 2.4
camera 2.3
file 2.11

Step 1: Add the permissions module to your app

In the modules section of your app’s src/config.json file add the module as follows:

Alternatively, launch the Toolkit and navigate to the Modules section of your app and search for the permissions module.

Step 2: Check Whether You Need To Make A Permission Request

Before we actually request a permission we first need to check whether the user has already granted the permission or not.

Once we know this, we will know whether we will need to initiate a permissions request or whether we can proceed normally with our app.

The API that will give us this information is: forge.permissions.check()

So, let’s say we have a feature that needs to use the API which relies on the permission.

To perform the check you then simply do something like this:

You can find a list of modules and the permissions they require by checking out the Permissions Module Documentation

When granted is true you can simply continue with your app flow and when it is false you can take the steps needed to make a permission request of the user.

Step 3: Request Permission

Now that you know how to check for a permission, you will need to know how to handle the case where the permission has not yet been granted.

To do this we’ll use the forge.permissions.request() API:

Note that, although the user will be presented with the permissions popup when you call forge.permissions.request() this is slightly deceptive.

The dialog the user will see is not generated by the device operating system but rather by the module. If the user clicks “No” in this dialog any future requests for the permission will no longer fail automatically.

It is only after the user has clicked “Yes” that the real system dialog is presented.

With this code, your user will be asked for permission when you call forge.permissions.request() and you then have the option to take an alternate action if the user did not grant the request.

All Together Now

Now that you know how to check for and request permissions, let’s look at an example of how you could put all the pieces together for a smooth user experience in your app:

Custom Runtime Permissions Flow

There are a couple of advantages to doing it this way:

  • The call to forge.permissions.check() provides a logical place to fork your app logic depending on whether the user has already granted the permission or not.
  • By linking the forge.permissions.request() call to a user action which explicitly relates to the permission being requested you greatly reduce uncertainty in the user’s mind about the purpose of the permission request.
  • Being able to check the outcome of the permission request you’re able to easily update your application and explain to the user why you need access to that permission.

That said, this is only one example of how to do it and you may find your application needs a different approach.

For some great ideas on increasing Runtime Permissions conversion I highly recommend you check out this article by Brenden Mulligan: The Right Way To Ask Users For iOS Permissions

Finally, don’t forget to check out the documentation for the Permissions module!


I hope you enjoyed this quick journey through the iOS & Android Runtime Permissions models, how Forge handles permissions by default and the tutorial on how to use the forge.permissions module to implement custom handling of runtime permissions.

As always, please hit us up at if you have any questions or comments! Forge v2.4.1 – Intel Crosswalk, Runtime App Permissions & Android Studio support


Towards the end of last year I wrote about our upcoming 2.4 release and today I’m happy to announce its arrival!

We’ll be covering the individual features landing with v2.4.1 in more detail over the coming weeks but let’s take a quick look at the highlights:

New forge build target: Crosswalk


With the release of Forge v2.4.1 our crosswalk target has finally graduated from the beta branch and has been declared ready for production use.

Anyone developing hybrid apps for Android will be familiar with the myriad of compatibility issues that pop up when you start testing your app against different versions of Android.

Android versions before v4.4 shipped with a proprietary System WebView which lacked many basic HTML5 features, performed poorly and suffered from compatibility issues.

Android versions after v4.4 use whichever version of the Chrome-based System WebView was current when the device shipped.

The very latest versions of Android now periodically update the System WebView when newer versions of Chrome are released but this creates new problems when System WebView changes suddenly render your code inoperable.

The Crosswalk Project resolves these fragmentation issues by integrating the open-source Chromium WebView with your app.

By using our crosswalk target you can now use the latest web standards across all Android devices and control when you want to upgrade your app to support newer Chromium releases.

For more background information please read: Solving Android Fragmentation with Trigger.IO Forge and Intel’s Crosswalk

Runtime App Permissions


With the release of Forge v2.4.1 and our new forge.permissions module we fully support the new Android Runtime Permissions framework and give you complete control over when and how your app makes native permission requests.

By default, all forge module API’s will now only make a request to the user for permissions when the API is called and not during application startup.

While this has the benefit of not requiring a user to make an “all-or-nothing” decision when they install the app it still has the downside that it can quickly get quite complex to handle situations where users deny permission requests.

By using the forge.permissions module you have fine-grained control over permission management, can easily handle cases where permissions are denied and greatly increase the probability that users will grant your app the permissions it requires.

Android Studio Support


With the release of Forge v2.4.1 we have migrated our cloud compilation service to the Gradle build system and updated our Forge Native Module SDK to support the Android Studio IDE.

While we’re huge fans of the IntelliJ IDEA-based Android Studio the primary motivator for this shift came about because Google have now officially deprecated Eclipse for Android development.

This means that all development and official support for the Android Developer Tools (ADT) in Eclipse have now ended. Specifically, this includes the ADT plugin as well as the Android ant build system.

We’ll continue to support native module development with ant and Eclipse for as long as practical but you may be pleasantly surprised at how much easier Native Module development can be with Gradle & Android Studio!

Upgrade your app to Forge v2.4.1

You can find more information in the v2.4.1 release notes but the following steps should get you going:

Step 1 – Upgrade your platform version

Open your app’s src/config.json file in your favorite text editor and set the platform_version key to v2.4.1 as follows:

Step 2 – Check your module versions

Due to changes introduced by the new runtime permissions framework in Android 6.0 Marshmallow (API level 23) you may need to update your modules.

If you are using any of the following modules please ensure you are on the latest versions:

module version
contact 2.9
calendar 2.7
geolocation 2.4
camera 2.3
file 2.11

Step 3 – Develop!

To build your app against the new crosswalk target you can simply run:

Our android and ios targets remain unchanged.

Crosswalk options

We’ve also added two new optional configuration keys to src/config.json that control Crosswalk behaviour:

If you are experiencing rendering issues on some devices the disable_gpu_rasterization setting will work around bugs in their OpenGL implementations.

The disable_pull_to_refresh_effect setting allows you to disable Crosswalk’s default behaviour of refreshing the screen when the user “pulls-down’ on a page.

Check the documentation for more information.

In Conclusion

v2.4.1 is a massive release for us and represents the culmination of almost a year’s worth of engineering effort.

The complexity of integrating a new Forge runtime while simultaneously migrating our Android build system over to Gradle has been non-trivial and I’d like to give a special shout out to:

  • The v2.3beta branch testers who tirelessly hammered on each release, reported bugs and – often – contributed hours of their time to help us track down and reproduce issues. Y’all know who you are, thank you!

  • The Crosswalk team @ Intel. Crosswalk is beautifully engineered so it was rare that we got stuck, but when we did you were there with rapid responses, answers and marketing support!

Finally, if you run into any issues with v2.4.1 or have any questions about this release please don’t hesitate to get in touch with us at

Winding down for the year

Dear Trigger developers,

Well here we are again. The year is drawing to a close, there’s a definite festive spirit in the air and I’m wondering where the time has gone.

2015 has been a landmark year for and I’m pleased as punch to share that we are once again showing stable month-on-month growth. This marks the completion of the transitionary period from externally-funded startup
to a sustainable business and is a reliable indicator that we will continue to be here for all of you, now and in the future.

We wouldn’t have come this far without the willingness of the community to bet on us. So from our oldest customers who have been with us since we were in beta to our newest customers who only joined this week:

“Thank you, you rock!”

I’m not going to get into details on the engineering work we have planned for the new year as I covered it last month. Instead, I’d like to talk about the softer side of the platform.

Over the last couple of weeks I’ve heard from many of you with suggestions and questions about what 2016 holds in store. The dominant theme in all these conversations have been that it’s time for us to put energy and
resources into the Trigger.IO community.

Based on these conversations, some of the things we’d like to look at are:

  • Opening up the development processes around our open source native modules.
  • Making the knowledge accumalated in our support systems publicaly available.
  • Alternatives to for community support and communication.
  • Re-organising tutorials and other how-to information on our blog and website for discoverability.
  • Rebooting a sadly lapsed tradition of showcasing the work our customers are doing.

If you’ve also got ideas you’d like to share, please get in touch.

Finally, our offices will be shutting down on the 15th of December 2015 and will open again on the 7th of January. We will however have someone checking in on support during this time in case any emergencies come up.

Wishing everyone a fantastic holiday to recharge for the coming year, I have a feeling it’s going to be a great one!

All the best,