Solving the challenges we face at Buffer has always brought us to some unique places.

From trying many different forms of management to recovering from a serious hacking incident, we are always learning valuable lessons along the way.

Recently, we just wrapped up our 7th Buffer retreat. As our distributed team from corners all around the globe prepared to meet up in Hawaii, we thought one thing that we could improve would be a way of letting everyone on the team know where things are happening—and when.

In the past we’ve used Facebook Messenger to share plans, locations and reminders amongst the team. But now that we’ve grown to 70+ teammates, we’re a bit too large for Messenger to handle. We needed a new solution.

Thus the Buffer Retreat app was born! Here, I’d love to walk you through how we created a fully functioning app to power 92 of us through the retreat in just 45 days time.

Identifying the need for an app

Since Buffer keeps on growing, our retreats keep getting bigger and bigger. As with anything that scales, keeping communication fast, efficient, and easy becomes a challenge.

Patrik, one of our amazing customer researchers, is a retreat veteran. Having been to a few them before, he was quick to recognize a need and propose a solution in the following email:

https---d2mxuefqeaa7sj.cloudfront.net-s_FAAB06B7EAEC513E8F0ADA78F6D1F9A0C6FDDDB4C298BDD4DCF0BEB18D007C65_1454519590335_Screen+Shot+2016-02-03+at+11.12.49+AM

We all agreed that there was a need for what Patrik had proposed. That’s when the retreat app officially started!

Staying lean: Creating our core list of features

You can probably imagine how big our ambitions were in the beginning in terms of features. It’s easy to succumb to feature creep when you start on a project you’re particularly excited about.

But part of the trick to pulling off projects like these is tempering expectations to a certain degree, and identifying just what the user will need most.

Plus timing was a big constraint since the retreat wasn’t far off. We all agreed that staying as lean as possible would be the only option. 

So our dreams of implementing cat GIFs for messaging quickly went into the “Nice to Have” column!

After a little back-and-forth in emails and on Slack, we settled on a few core ideas and needs for the app. The main goals looked something like this:

  • Easily show the entire schedule of the retreat
  • Interact with events of the retreat (i.e. mark yourself as attending, leave comments, etc.)
  • Have two types of events – an activity (for everyone) and a session (for Buffer employees, and optionally significant others)
  • Show everyone’s location on a map if they allowed it
  • Release it on iOS and Android

Having a list of things we needed it to do helped guide the rest of the process and made us identify some things we could cut out to revisit later. 

Designing and streamlining our idea

Lucky for us, Marcus has quite the design chops in addition to being a talented developer. Within a week, he put together a Sketch file that acted as a first pass for the app’s design and became our overall guide to the project.

This was incredibly valuable, since it confirmed a few assumptions we had about the app while also making us challenge other features we initially thought were valuable.

iOS Sketch Design

For example, we felt we could do without the “News” section once we saw it laid out.

Other changes were more along the lines of optimizing the feel for each platform. For instance, in the Sketch file the “Add Activity” view feels more catered towards Android. On iOS, I ended up giving it a little more of a native feel:

Activity

The themes and flows for the user, though, remained as consistent as each platform would allow. For instance, adding an activity looks like this on Android:

androidactivity

The biggest design changes only happened with the icon. Marcus had come up with a few different versions, with the first drafts originally tweaking Buffer’s iOS icon. 

first retreat app icon

Eventually, we decided it was a bit hard to differentiate between the retreat app’s icon and Buffer’s official one. This was amplified by the tendency of most users to place the retreat app right next to Buffer’s app on their iPhone/Android devices.

The answer ended up being simple, as Marcus eventually inverted the colors, which felt perfect:

final retreat app

Development: Borrowing from our codebase for speed

At this point Marcus and I started the development charge! I handled iOS, and Marcus took on Android.

We knew we would have to cut corners wherever possible to deliver the app in time. This meant looking at existing technologies and frameworks that could save us some time. 

For the backend and API, we used Parse—everyone on the mobile team had used it before and it meant we wouldn’t drain any bandwidth from our backend developers. (In the future, we’ll need to make some changes here as Parse will close its doors next year.)

For some of the finer points of the user interface, I turned to some of our own internal solutions. We are huge fans of Cocoapods and use it frequently. Since the design called for each day of the retreat to be listed at the top, I ended up using one of the pods that we use extensively in the Buffer iOS app. 

For example, each day of the retreat displays a different view controller when it’s tapped. It’s the same setup we have in Buffer iOS, where we list “Queue,” “Contributions,” and “Feeds.”

It’s a handy subclass of a collection view controller that Andy had built, and it worked perfectly for the retreat app. I’ve highlighted the control red in the picture below, which you can used between both apps:

SegementsiOS

Over on Android, Marcus was able to do the same thing:

AndroidSegments

All of us on the mobile team at Buffer were welcome to propose changes and contribute. Even though there were two of us primarily developing the app, the rest of the team would push up commits to help us stay on track. 

In particular, Andy worked out a lot of the onboarding on iOS. Tom was extremely proactive in getting some tricky details worked out for the location tracking on Android while Humber suggested Fastlane for automation.

The final stretch: Seeing it through

As the weeks went on, Marcus and I had made progress by allotting a few days out of the week to focus on the app. As December rolled around, I took a two-week vacation and Marcus was in the middle of traveling across the United States. As the retreat inched closer, we devoted a little more time each week to get it shipped.

During development, we would hold a weekly sync over Zoom to discuss how things were going on each platform. This was a key part of the process, as it’s easy to make assumptions of how something should work. Ensuring we were coding features to work the same way across each platform was important. 

One hiccup I caused was accidentally creating a duplicate boolean flag on our Event model. As I mentioned previously, events for the retreat could either be a “session” or an “activity”—which we tracked by using a simple enumeration. If we were creating a session in the app, a user could set the event to only allow Buffer employees (a.k.a. Bufferoos) to attend.

Since I didn’t notice Marcus had already added that field in Parse, I added another one. We were each using different flags to set that value in our code:

anEvent.onlyBufferoos = YES; //iOS

anEvent.isOnlyBufferoos = true; //Java

Of course, holding a quick video chat or a simple exchange over Slack always leads to quick resolutions!
Slack Chat

Putting it to the test: Time for the retreat!

Once January 23 came around, most everyone at Buffer and their significant other had the retreat app installed on their phone!

Thanks to Fabric, we were able to catch and debug a few things that cropped up during the login flow. I also learned firsthand that dealing with different locales and date formats is something to be especially cognizant of!

Immediately, something all of us found really useful was the team directory page. Since we are a remote company with people working all over the globe, most of us were meeting in person for the first time! It was truly magical, as my good friend Ross explained here.

Having a listing of teammates, what they did at Buffer, and their partners or family (if they brought others) ended up being super helpful!

Team

Andy also added a nice touch using Parse’s cloud code functionality.

If a user allowed us to track their location, anytime it was updated an instance of a UserLocation object was created and saved to Parse. This created a breadcrumb-like effect of users’ movements during the retreat.

Tom took this data (over 131k rows!) and made this incredible heat map of our movements:

Buffer Retreat Heatmap

The app really helped us stay on track during the retreat. Seeing when and where sessions were taking place and giving our partners a place to create activities and meet others while we worked during the day worked very well!

In fact, waking up and seeing what sessions or activities the day held became a part of our morning routine. Whether it was checking to see where a particular Buffer session was, or seeing who was brave enough to go on a 5 a.m. hike, there was always something to partake in!

ActivitiesDetail

It was also not uncommon to use the map to find where some of our friends were to meet up. I remember using it one day in particular to find Marcus on the beach to go snorkeling!

Locations iOS

What we learned: Move as fast as possible, but not faster

There were times were I had to make a conscious decision to not “overengineer” some of the code. Since time was short, there were some instances where I coded the app to just work and not think about scaling as much. 

An example is when a user creates an event. As soon as the new event was saved off to Parse, I reloaded all of the events in the app to refresh the user interface. This wasn’t much of an issue since we would be dealing with 20–30 events, tops. 

If the retreat app lives on and Buffer keeps growing (which I hope is the case!) then shifting this approach to use a local cache will be crucial. The way I have it implemented now is equivalent to Facebook fetching and reloading their entire user interface anytime a user hits “like” on a photo!

After development was complete, I found that there were a few times I would open a view controller to see something with “//Clean up later” or “//HACK 🙂“!

For me, this was an important lesson to learn. I tend to preplan architecture and want to know how things will fit perfectly before I code. There is a time and place for this, but on the flip side it’s important to know when to pick your battles. Releasing an app on time that worked was our measure of success, not scaling it to a million users!

Over to you

We learned a lot through developing the retreat app.  It was the closest I’ve been to customer development, and being able to learn from that experience was truly inspiring.

Watching all of my friends inch closer to Waikiki via the app leading up to the retreat was also incredibly fun! 

What about you? Do you have any experience building internal apps for your company? Anything we could’ve done better or optimized more? We’d love to learn from you!

Even better, feel free to visit our Journey page and help us bring mobile at Buffer to the next level!

Free up your day with our Social Media Tools

Buffer can save you up to an hour a day and grow your traffic too.

Learn More
Written by Jordan Morgan

I love iOS, pizza, caffeine, and my family! I’m always up for a nice walk outside or a fun little code jam :-)!

  • Whoa! This is absolutely incredible. Both the app, and the process that went into it. It’s nice to see how much attention you guys give to your internal workings – it’s rare to see a company give their team members so much love =]

    • Thanks so much Hector! It was my first experience with an internal app, it has turned out to be one of the most rewarding experiences so far in my career 🙂

  • Murugaprabu Marimuthu

    The ability to quickly put out a working app to solve your own itch was amazing 🙂 Loved reading the entire writeup.

    • Thanks so much Murugaprabu! So glad you enjoyed the post!

  • Okay that’s pretty cool, Jordan! It would be really neat to work on something like this and see it come together, literally, as people converged on a single map point from around the globe!

    Sounds like you’ve got something powerful for your team, and I enjoyed the peek inside at how the sausage was made. (yay hacks!) Thanks for sharing!

    • Thanks so much @BrendanFDMoore:disqus ! Haha, yep – some hacks were definitely part of the process for sure :-). Thanks for reading!

  • Chaitanya Prabhu

    Love the way you have shown your design layout. How did you do that?

    https://overflow.buffer.com/wp-content/uploads/2016/02/Screen-Shot-2016-02-03-at-12.24.54-PM.png

    • Hey there Chaitanya! – we used Sketch for this. I highly recommend it as it’s super easy to use and really geared towards UI design on the web and mobile. Check it out here: https://www.sketchapp.com/ Thanks so much for reading!

      • abhinav

        Sketchapp is only for MAC , Can you suggest any app that works on windows or linux?

        • Hmmm , that’s a good one Abhinav! Over on Windows, I find myself just using Photoshop for mocking up designs. They also have project Comet coming soon, which looks incredible! I believe that will be available for Windows, too :).

  • James Trever

    Hey, which cocoapods libraries you discussed did you use?

    • I’d love to share that James! Here are the publics pods that were used copied straight from the project’s podfile 🙂 :

      ## UI Pods
      pod ‘DZNEmptyDataSet’, ‘~> 1.5’
      pod ‘FLAnimatedImage’, ‘~> 1.0’
      pod ‘Masonry’, :git => ‘https://github.com/Masonry/Masonry.git’
      pod ‘MBProgressHUD’, ‘~> 0.9.1’
      pod ‘JVFloatLabeledTextField’
      pod ‘IQKeyboardManager’
      pod ‘TTTAttributedLabel’, ‘~> 1.13’
      pod ‘TSMessages’
      pod ‘UzysAnimatedGifPullToRefresh’, :git => ‘https://github.com/uzysjung/UzysAnimatedGifPullToRefresh.git’
      pod ‘UITextView+Placeholder’

      ## Other
      pod ‘ParseFacebookUtilsV4’
      pod ‘ParseUI’
      pod ‘FBSDKCoreKit’
      pod ‘FBSDKLoginKit’
      pod ‘FBSDKShareKit’
      pod ‘GoogleMaps’
      pod ‘Fabric’
      pod ‘Crashlytics’

      • James Trever

        Awesome, really appreciate that!

  • Hi Jordan

    Nice write up, seems like you got the balance between speed and quality just right. Always easier said than done! How did you do the heat map, that is really cool?!

    One other thing which may or may not be relevant to you because your retreats aren’t that frequent but best that you know: although parse isn’t shutting down until January, I found out the other day that if you don’t migrate your app by April they ‘de prioritise your application’ (https://github.com/ParsePlatform/parse-server/wiki/Migrating-an-Existing-Parse-App).

    Lewis

    • Thanks so much for reading Lewis! Our mobile lead Tom made that using cartodb.com! It’s awesome stuff! Definitely hear you about Parse, luckily Andy (our lead iOS dev) has been on top of that and got us all migrated, phew!

  • Nate Scholz

    I’m a innovative-tech-loving, non-developer eavesdropper, who organizes retreats and conferences. What are the chances that you’ll be developing this app for public consumption?

    • That’s a good one @natescholz:disqus – we’ve been looking at ways to see if we can get this open-sourced! Definitely keep an eye out for it!

      • Nate Scholz

        Hey @disqus_3SbMJNexvQ:disqus , checking in to see if there’s any progress on open sourcing your conference app. You suggest keeping an eye out for it, can you suggest where I should be watching? Would you announce that in the comments here? Is there something that I can click to get on an announcement list? Can you tell that I’m hungry for it? ?

        • Hey there – SUPER sorry for the later reply!! The service we built this off of, Parse, was sunset. Right now I’m working on the app to migrate it over to Firebase, and I think we might have some news around this at the end of March (after our next retreat, to make sure the app works and then clean it up!). When we do something here, it’s likely we’ll write a post about it here 🙂

          • Nate Scholz

            Thanks for the reply, Jordan. Not sure I will catch it in the raging flow of social media feeds I’m trying to keep up with. If it’s possible to notify me, I’d be very much obliged to you.