From 0 to App in 1.5 weeks

Arjun Anand
6 min readDec 3, 2014

Building a hybrid mobile app using the Ionic Framework

We, at Crowdtap, are constantly evolving our product offering. In our near 5 years of existence, we have had much success with the technologies we’ve used and implemented. We had built an iOS App about 2 years ago in Titanium but had to pull the plug on it because we were changing out the underlying architecture of how Crowdtap works.

Since then, we have changed out the underlying architecture of Crowdtap and added to the suite of product offerings. We currently have a mobile-friendly web-app but we decided to try out the Ionic framework to see if we can build a nice little app on a spike. We narrowed the scope to one action in the suite of products that Crowdtap offers and created the Missions app.

DISCLAIMER: This article assumes that you have played with the Ionic framework and know how to generate and setup a basic ionic app.

Objectives for the sprint:

  • Build an app where a beta tester can login via FB, and can participate in a simple photo and text response mission
  • Allow beta testers to vote on each other’s responses
  • Build an experience that simplifies one task for a user
  • Test performance of a hybrid (native + webapp) app development framework
  • Implement a clean codebase, even though this was just a spike

Reasons for choosing Ionic:

  • Relatively new framework with good number of dev adoptions
  • Fast development because of familiarity with Angular.js
  • Easier to write using js than having to learn new languages
  • Easy to test using cucumber.js
  • Great documentation!(Seriously, cannot state this enough)

Code Organization:

Javascript:

Ionic is a great framework, but if you look at the app that is generated when you create a new app using the generator, it comes with 1 controller.js file and 1 services.js file which contains all the controllers and services respectively. While this is great for a starter app, it doesn’t really work when you add more complexity into the app. So, we came up with a code organization that we liked.
It looks like this:

▾ js/
▾ controllers/
LoginCtrl.js
MissionCtrl.js
MissionZeroStateCtrl.js
MultipleChoiceActionResultsCtrl.js
MultipleChoiceActionStepCtrl.js
OnboardingCtrl.js
OpenEndedActionResultsCtrl.js
OpenEndedActionStepCtrl.js
PhaseAskCtrl.js
PhaseCtrl.js
PhaseResultsCtrl.js
PhasesCtrl.js
PhaseThanksCtrl.js
PhotoActionResultsCtrl.js
PhotoActionStepCtrl.js
RequestNextMissionCtrl.js
RequestNotificationsCtrl.js
▾ services/
base64.js
Camera.js
FirebaseMember.js
Me.js
Mission.js
openfb.js
Participation.js
PushWoosh.js
ResponsesDistributions.js
StepProgress.js
app.js

Templates:

Our Template files are also organized in a similar manner. We also adopted some conventions from Rails. For instance, template files that are not primary files and are only rendered from other template files, we deemed as partials and use the “_<file_name>” notation for those files.

mission.html
_mission_context.html
_mission_phases.html
_mission_prizes.html

Styling:

Ionic comes bundled with CSS components similar to Bootstrap, but focused on the mobile landscape. It gives you nearly all of the mobile components you expect to find in an app: from headers and tab bars to range sliders and cards. Out of the box, Ionic provides a nice default color scheme for all of these elements, but they are all configurable through a SASS variables file.

During our sprint, we opted for Less as our pre-processor of choice, even though Ionic’s styles are built using SASS. There aren’t a lot of solid reasons for this decision aside from:

  • Familiarity. We’ve been using Less across all of our front end applications.
  • Compatibility. We share Less global variables (i.e. brand colors) across applications, and we might want to do the same for this new application.
  • JavaScriptability. Less makes more sense to us in the world of JavaScript and Node.js.

We’d like to recompile Ionic’s CSS components with our own color scheme, so we may switch over to SASS to avoid running two preprocessors in our build task. Choice of preprocessor isn’t a big deal for us anyway, as we only leverage their variables feature and otherwise stick as close to vanilla CSS as possible. In any case, we organize our own CSS components and styles like so:

www/less
├── animations.less
├── bars.less
├── base.less
├── buttons.less
├── iconList.less
├── imageBlock.less
├── index.less
├── missionDescription.less
├── multipleChoiceAction.less
├── multipleChoiceResult.less
├── navTabs.less
├── openEndedAction.less
├── photoAction.less
├── photoResult.less
├── progressBar.less
├── screenLogin.less
├── screenMissionDescription.less
├── screenMissionZeroState.less
├── screenPhasesIndex.less
├── screenPhasesShow.less
├── screenRequestNextMission.less
├── screenRequestNotification.less
├── slideBoxOnboarding.less
├── slideBoxPhasesIndex.less
├── slideBoxPhotoAction.less
├── stepCounter.less
├── submission.less
└── variables.less

Tying it all in together:

When you have that many js files, including them in the index.html file becomes tedious. So, we wrote a gulp task to concat all the js files together and we include that file in our index.html file.

You’ll notice that the js files are all concatenated into www/build/js/app.js, and the css files are all concatenated into www/build/css/app.css. These are the files we can then include in our index.html.

GOTCHA: Note that “cordova.js” file is still included as a separate file and is not concatenated into the app.js file. This is because we dont have access to the cordova.js file until runtime.

Local Testing:

The Missions app makes several api calls to Crowdtap’s servers to fetch data for members. When trying to test this locally using “ionic serve”, we ran into CORS issues. Our local server would also take a little longer to respond with a response. So we decided to use an express.js server to return canned responses. This helped us move faster with our development. Setting up an express.js server is pretty easy. This is how we did it:

  • Define a server.js file that allows CORS requests and stubs out the requests you expect to make to respond with your canned responses:
  • Start the express server with gulp:
  • Make use of the express server when making api calls while developing the app

Lessons Learnt:

  • Ionic is really fast to pick up and easy to deal with for web devs like me.
  • The ionic framework documents are really nicely written for a framework that is so new.
  • The performance of an ionic app v/s that of a native app is negligible as far as what our app is doing. It might differ for you depending on your app, but our app makes use of a lot of images, voting mechanisms, and api calls and we experienced minimal, almost negligible, performance deterioration.
Swiping experience using Ionic
  • Forming good conventions around coding is important when you’re working in a team. Even when you’re spiking, it is a good idea to keep certain best practices in mind.
  • Using xcode to get a build of an app onto an iOS device is really confusing to set up but is seamless once set up.
  • Deploying to a connected android device is relatively much easier.
  • When installing plugins, we found that we had to always remove the platforms and add them in again for the plugins to work properly.
  • Ionic doesn’t have an easy way to specify splash screen images. We had to write a custom gulp task to set the splash screen for each device.
  • You can minify the app.js file to reduce footprint of the app.
  • HockeyApp made it very easy to send the app to beta testers.

(For reference, the full gulpfile is available here.)

Footnote:

All in all, we had fun building this app in Ionic. I’d like to give them kudos for making this framework and all the awesome work they’ve been doing. Also, if building apps and web-apps like this is something that you enjoy, I’d like to point out that Crowdtap is hiring

--

--

Arjun Anand

Technology lover, tennis buff, gamer. VP of Engineering at BeenVerified. Affectionately known as a crazy tester and yodarjun. Opinions are my own.