With Meteor’s application bundles for iOS and Android, you’re ahead of many other web apps, because your client side JavaScript code will be available offline. Having that bonus, getting accepted for Apple’s App Store is easy - if you properly handle a lost connection to the server. I’ll showcase a simple, extendable solution.

Apple tends to refuse apps that do not offer any benefit compared to Safari’s Add to Home Screen feature. Having your client side JavaScript code available offline, if you add a nice lost-connection overlay with the ability to reconnect manually, from our experience, Apple will likely accept that as enough extra functionality. Yay! So here’s a slim solution for that overlay using the Chronos reactive time utility, Font Awesome and the CoffeeScript JavaScript preprocessor:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Template.connectionOverlay.helpers
  isWaiting: -> Meteor.status().status is 'waiting'
  isConnecting: -> Meteor.status().status is 'connecting'
  isOffline: -> Meteor.status().status is 'offline'
  isConnected: -> Meteor.status().status is 'connected'

  waitingDuration: ->
    s = Math.round((Meteor.status().retryTime - Chronos.now()) / 1000)
    if s?
      if s is 1
        '1 second'
      else
        "#{s} seconds"

Template.connectionOverlay.events
  'click a': (e) ->
    e.preventDefault()
    Meteor.reconnect()

An example Liquid HTML template:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<template name="connectionOverlay">
  {{#unless isConnected}}
  <div class="overlay">
    <div class="modal-warning">
      {{#if isConnecting}}
      <div class="icon fa fa-refresh fa-spin"></div>
      <div class="title">
        Connecting to server ...
      </div>
      {{else}}
      <div class="icon fa fa-warning"></div>
      <div class="title">
        Connection to server lost
      </div>
      {{/if}}
      {{#if isWaiting}}
      <div class="body">
        Trying to reconnect in {{waitingDuration}}.
        <a href="">Click here</a> to reconnect immediately.
      </div>
      {{/if}}
      {{#if isOffline}}
      <div class="body">
        <a href="">Click here</a> to reconnect.
      </div>
      {{/if}}
    </div>
  </div>
  {{/unless}}
</template>

And some example Stylus styles:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
.overlay
  position fixed
  top 0
  left 0
  right 0
  bottom 0
  background-color rgba(0, 0, 0, 0.7)
  z-index 100000

  .modal-warning
    position fixed
    top 50%
    left 50%
    width 80%
    transform translateX(-50%) translateY(-50%)
    background-color #fff
    padding 25px
    text-align center

    .icon
    .title
    .body
      margin-bottom 15px

      &:last-child
        margin-bottom 0

    .icon
      width 100%
      font-size 4em

    .title
      font-weight 600

Finally, add the following to your main layout, I have placed it just before the closing </template>:

1
{{>connectionOverlay}}

That’s it! Users accessing your application through their web browsers will profit as well: Altough they can’t load the page without an internet connection, the widget will be shown if the page is already open and the connection gets lost.

If your application is in waiting state before attempting to reconnect, it may not be responsive at all for a longer time. On the other hand, your users probably got used to Meteor’s real-time features and expect immediate feedback. So it’s generally a very good idea to tell them about the disconnected state urgently.

Happy reconnecting!