Sharing Photos More Conveniently with Privacy in Mind

In my last blog post[1], I wrote about my concerns over giving apps permission to access my photo library. Back then, I had found a workable, yet slightly cumbersome, solution involving a Shortcut[2]. I would run the Shortcut from a selected photo in the photo library and it would strip the metadata and then present a Share Sheet to send the cleaned photo to another app. Of all metadata, I am most concerned with location data.

A few months ago, shortly after installing ios 13.3, I made a pleasant discovery.

Share photo Location options

Interestingly, sometimes it shows Location included and sometimes it has the name of the place, where the photo was taken. I have not figured out the pattern here, yet.

If you tap on the Options button, you’re presented with the following screen:

Metadata to include

Once you turn off the Location switch and tap Done, you get a visual confirmation that no location data will be shared.

No location data

This is significantly faster and a bit easer than my Shortcut. Additionally, it works for multiple images at a time and for videos!


While this is a great step for sharing photos with privacy in mind, hopefully, in the future, we will be able to choose not to share location data by default.

Have any other privacy tips you’d like to share? Find me on Twitter. I’m @yonomitt.

Have a nice day,
Yono


  1. Almost two years ago! 🤭  ↩

  2. In the post, it was still called Workflow — the name before Apple acquired them, renamed the app to Shortcuts, and integrated it into the OS.  ↩

Sharing Photos with Privacy in Mind

Since moving to Germany, one stark difference I have noticed between Germans and Americans is a focus on data privacy. Sure, Facebook and other social media are still popular here, but Germans, and Europeans in general, are more concerned about keeping personal data private.

I’ve also noticed a shift in my thinking. While living in the US, I was a fairly heavy Facebook user. Over the last few years, though, I seldom log in and even more rarely post anything.

Recent news about the Facebook “leaks” and their scope only confirm that my conscious effort to stay away is the right decision – for me.

Earlier this year, my neighbor and I were chatting and the conversation turned to smartphones and data privacy. Our smartphones have so much personal and potentially sensitive information about us, it can be scary to think of it at times.

During our conversation, we explored how giving 3rd party apps access to certain features and sensors could potentially be misused. I then started wondering exactly how secure is the metadata from my photos. For instance, if I give an app access to my photo library, could it extract metadata (including GPS coordinates) from all photos or just the ones I used within the app?

It’s time for a test app!

As a developer, I knew I could find this out by writing a simple app. The app would request permission to the photo library and, upon receiving it, would see which metadata it could extract from which photos.

The results somewhat surprised me. The app could read metadata from every single photo in the library very quickly. And, since GPS was enabled for the camera app, I could see where I was at which time each photo was taken. I could recreate a substantial portion of my life.

Turns out, had I done a little searching beforehand, I could have found Felix Krause’s blog post on the exact same subject, complete with a test app similar to mine. Oh well, it was still fun to figure it out for myself.

Consequences of my test

First and foremost, I immediately removed photos permissions from WhastApp, Slack, Twitter, etc. I don’t have Facebook installed on my phone, but I need WhatsApp. Many people can only (easily) be reached there.[1]

This brought up a problem, though. I still want to share photos through these services.

I don’t want to turn off GPS recording for photos. I find the information interesting to view. It’s also useful as I can search photos by location.

A solution is to use the share sheet via the photos app to only send certain photos to the social apps when necessary. The apps would still be able to extract metadata for any shared photos but not for the entire photo library.

This is good start. But we can do better.

Workflow

I started thinking about a Workflow that would strip metadata from photos. And then… I made one.

Remove metadata and share Workflow

The 3-step workflow is quite simple. It:

  1. Gets the input image
  2. Strips the metadata
  3. Brings up the share sheet

Here’s a a quick example of this workflow in action

Workflow in action

Step by step, I:

  1. Tap the share button for the photo I want to send from the Photos app
  2. Then tap Run Workflow from the bottom row of the share sheet
  3. Choose the Remove EXIF and Share workflow
  4. Select the app to send the metadataless[2] photo

It’s a bit more work and can be confusing, since the share sheet is presented twice during this process. But that’s a small price to pay to restrict the amount of data these apps can collect.

Save photo workflow

I also created a similar workflow that saves a copy of a photo without metadata for rare situations, which may require me to do so.

Remove metadata and save Workflow

It works similarly to the other one.


While it’s too late for any photos I took prior to revoking photo library permissions from these apps, at least I can feel better about all photos going forward. My privacy is certainly better protected now than it was a year ago.

Thoughts or suggestions to improve this workflow? Find me on Twitter. I’m @yonomitt.

Have a nice day,
Yono


  1. Ugh. Sad WhatsApp privacy news recently  ↩

  2. I humbly submit this new word as a candidate for Word of the Year 2018  ↩

A Fun Exercise in Truncatable Primes

The other day, a tweet popped up in my time line.

Huh. Did he have a point? Infinity is quite large. Is this the equivalent of ATP’s on an infinite timescale?

NOTE: I discovered later that these prime numbers are called truncatable primes. The ones where you remove digits on the right side are specifically called right-truncatable primes.

What if we think about it from a software developer’s point of view? How can we design an algorithm to generate – potentially endlessly – all prime numbers that exhibit this characteristic?

Let’s try a simple approach. Instead of searching for large truncatable primes, let’s build them from smaller ones. By building the prime numbers up one digit at a time, we can guarantee that the algorithm will only generate truncatable primes.

In the beginning, there were single digit prime numbers[1]:

primes = [2, 3, 5, 7, 9]

Then, we need to define the possible digits that can be appended to these to make larger primes. For instance, take the first prime in the list 2. Let’s start appending digits to the right to see if we can make larger prime numbers.

initial prime new digit combined prime?
2 1 21 no
2 2 22 no
2 3 23 yes
etc…

Quickly we can toss out all even digits, as any number ending in an even digit is divisible by 2. Additionally, we can leave out 5 as any number ending in a 5 is divisible by 5.

This leaves us with the following possibilities to append to the end of our prime numbers:

appendable_digits = [1, 3, 7, 9]

That’s not too bad. Nice and short.

Now we can create new primes by:

  1. Taking the first number in primes
  2. Trying to create new prime numbers by appending each of the digits in appendable_digits
  3. If the new number is a prime number, add it to primes
  4. Once all combinations with appendable_digits have been tried, go back to step #1

In pseudocode, it would look something like this:

# empty list to hold the final truncatable primes
truncatable_primes = []

while len(primes):

    # get the first prime number in the list
    one_prime = primes[0]
    
    # loop through the appendable digits
    for digit in appendable_digits:
    
        # create a new potential prime by adding the digit to the right
        potential_prime = one_prime * 10 + digit
        
        # check if the created number is prime
        if is_prime(potential_prime):
        
            # add it to the end of the primes list
            primes.append(potential_prime)
        
    # add the original prime to our final output list    
    truncatable_primes.append(one_prime)
    
    # and remove it from the primes list, so we don't keep checking it
    primes = primes[1:]

Besides the is_prime function, which isn’t shown, this pseudocode is actually runnable Python code.

So I ran it.

And here’s the thing. Since it’s building the list of truncatable prime numbers from the ground up, if there were an infinite number of them, the program would never end.

But… it ended.

Here is the final truncatable_primes list:

[2, 3, 5, 7, 9, 23, 29, 31, 37, 53, 59, 71, 73, 79, 97, 233, 239, 293, 311, 313, 317, 373, 379, 593, 599, 719, 733, 739, 797, 971, 977, 2333, 2339, 2393, 2399, 2939, 3119, 3137, 3733, 3739, 3793, 3797, 5939, 7193, 7331, 7333, 7393, 9719, 23333, 23339, 23399, 23993, 29399, 31193, 31379, 37337, 37339, 37397, 59393, 59399, 71933, 73331, 73939, 233993, 239933, 293999, 373379, 373393, 593933, 593993, 719333, 739391, 739393, 739397, 739399, 2339933, 2399333, 2939999, 3733799, 5939333, 7393913, 7393931, 7393933, 23399339, 29399999, 37337999, 59393339, 73939133]

If there were any larger right-truncatable primes out there, they would have to be built from the longest of these numbers. However, since we’ve exhaustively tried appending all digits to the end of them that could make a prime number, we know that we have generated all existing right-truncatable primes. 73939133 is, indeed, the largest.


This isn’t the normal theme to my blog posts, but it was a fun exercise to try.

You can find me on Twitter. I’m @yonomitt.

Have a nice day,
Yono


  1. …and they were good.  ↩

Lessons from SaaS in a Parent Section Redesign

In my last post, I briefly mentioned that Alice and I started discussing a new app. Something that was borne from a recent App Store rejection.

I mentioned, in passing, we were working out how to migrate our existing customers to the new app. As there is a strong relationship between the two, it is important to our business to retain as many of our customers as possible during the transition.

The one teensy, little problem is that we have no contact information for our customers. Ok, it’s actually a major problem. Working around this limitation of the Apple, indie, customer relationship has become our number one priority.

Our problems are further amplified because our apps target children. Children are the users of the apps, but the parents are the customers. We need to attract the attention of the parent, while simultaneously preserving the privacy of the child and complying with COPPA[1].


A Start

Prior to the rejection, some Gus on the Go apps had a parent section to announce the Stories app for that language.

Country map with button to reach the parent section

After tapping the question mark button on the main country map, the user is prompted with a parent gate.

Original parent gate

The parent gate is a requirement for children’s apps, which contain links leading outside the app.

Most children’s apps use a simple addition problem as their parent gate. But honestly, my 4 year old son can do simple addition. He cannot, however, read. So I feel our method is a bit safer for our target age.

After unlocking the parent gate, the user is shown the parent section.

Original parent section


A Redesgin

While technically functional, this parent section had two main problems.

  1. The parent gate is too early in the flow
  2. It’s butt ugly

Parent gate placement

The current parent gate placement directly after tapping the question mark button is suboptimal. The user or parent has no way of knowing what information is available prior to unlocking it. We haven’t given them a reason to find out what’s behind it.

The parent gate is not only important, it’s a requirement. However, it’s only required before any action intended for a parent or which leaves the app.

So why don’t we push it later in the flow? Until just before it’s required? This way we can still present app information they need, which doesn’t require them to leave the app. We can also show our marketing copy for other apps that may be of interest.

Only when they tap on a link designed for a parent, the app should present the parent gate.

Design

The design is quite terrible. To be honest, this was done quickly and last minute. It was one of the last features that needed to go into Stories, and the code was just ported over 1:1 to Gus on the Go.

Unfortunately, the initial implementation leaves much to be desired. As a second pass, we cleaned up the colors for the parent gate and added a non-transparent background with a nice lined paper texture to all parent section screens.

Parent gate, 2nd pass

Parent section, 2nd pass


A Change of Information

The original goal of the parent section was to announce the availability of the Stories app. In addition, we added a couple of share buttons and a rate button. Partially because people say it’s a good idea and partly because it was easy.

Now that we were creating an entirely new product that doesn’t yet exist, our initial thought was to provide info about the new app once it’s available.

Our focus would be migrating customers to the new app and not getting them to download Stories.

Since the release date of the new app is a huge unknown[2], we want to have the apps ping our server. The server tells the apps when it is ok to link to the new product. Until then, the apps present the original parent section pointing to Stories.

However, is this the best plan? It was the first idea that came to us. Could we do better?

A lesson from SaaS

While bringing my one year old daughter to bed one night, something suddenly struck me. We could learn something from the way SaaS companies do business.[3]

Rather than wait for the release of our future product, we could tease it.

New product tease

But why don’t we go all in and ask for their email address?[4]

New product tease with email prompt

Alternate product tease with email prompt

NOTE: these are currently just mock-ups and not yet in the app

We can use this opportunity to build a valuable mailing list for our new, unreleased product. We then have a direct channel to parents interested in what we have to offer.

This was an a-ha moment for me.


Thoughts or comments? I’d love to hear them.

Feel free to reach out on Twitter. I’m @yonomitt.

Have a nice day,
Yono


  1. Children’s Online Privacy Protection Act  ↩

  2. We only have a concept, currently.  ↩

  3. Attempting to think like a SaaS business is something I took away from Curtis Herbert’s fantastic talk at this year’s Release Notes conference  ↩

  4. Email entry will, of course, be behind the parent gate.  ↩

It's Always Worth It

I am exhausted. I’m sitting at gate K16 in terminal 3 of Chicago O’Hare and I am exhausted. Release Notes 2017 is over and it always takes a toll on me. But it’s worth it.

And let me be honest. I knew what I was getting myself into. This was my third Release Notes conference. Two and a half days of almost non stop suppressing my introverted Jekyll and trying to encourage my extroverted Hyde to show up. That’s tiring. The jet lag didn’t help either.

This year was particularly cathartic.

My partner, Alice, and I started the conference feeling completely lost. A fairly recent change to the App Store Review Guidelines suddenly put our entire business model in jeopardy. However, everyone we spoke with at the conference sympathized and many offered advice. By the end, we were starting to feel better and were forming an idea directly inspired by the talks and conversations we had over the course of the conference.

That’s the Release Notes community in a nutshell. Once a year we get together for this truly utterly amazing event and we support one another. We listen. We offer advice. We have fun.

Charles and Joe really know how to put on a good conference. From picking great and skilled speakers to organizing a dine around to making sure everyone feels comfortable and safe. They’ve thought of everything. I particularly enjoy how much time between talks they leave for socializing. They even encourage attendees to switch tables often. It’s a nice, gently push for those of us, for whom meeting new people does not come easy.

The talks this year were among the best I have seen at Release Notes. That is saying something. I have always been impressed with the speakers I have seen at this conference, but somehow they stepped it up a notch.

Since I have attended Release Notes the two previous years, I know many of the other attendees. This makes meeting new people an even greater challenge. It’s very easy to just stick with people you know. It’s comfortable and familiar. Although I am always open to meeting new attendees, I’m certain I could have done better going up to others and introducing myself. It’s something I’ll have to work on next year.

Rejection Rebound

With our recent rejection on my mind, talking to people was especially difficult. I started at a mental disadvantage. I had trouble focusing my energy on the conference. But I tried.

Sometimes, Alice would nudge me to talk to people. Other times, I would do the same for her. That is a benefit of attending the conference with her. We encourage each other to meet others.

Then, something happened Wednesday just before lunch. My brain started putting together bits and pieces of various talks and conversations I had with others. By lunch, I felt I was on to something, but didn’t know exactly what. Around this time, I also saw Alice furiously scribbling in her notebook. I could tell she was working on something, too. This was the first time in the week I started feeling positive. It felt good.

During the afternoon, ideas stewed in my head. I straightened up my posture. I smiled. I talked to more people. During the rest of the talks, Alice and I occasionally glanced at one another and nodded. It seemed as if something in the talks was directed at us. The presenter wrote that slide specifically with us in mind.

After the conference ended, Alice and I went to the John Hancock Center with a group of Release Notes attendees. While waiting for the elevator to the 96th floor, we began discussing our apps’ strong points and weaknesses. We talked about what our customers actually want. We discussed what works and what doesn’t. It felt good. There was an excitement that I think was missing from our business for a while. We wanted to experiment.

Thursday was my last day in Chicago before flying back home. Alice and I went to the Drawing Room with the intention of hammering out a framework and timeline for moving forward. We discussed the core idea for a new app. We tried to work out how to migrate our existing customers. We discussed business models. We thought about features and selling points.

Most importantly, we agreed to move quickly. We cannot spend two years developing an idea, again. We whittled the concept down to the absolute minimum to get started. Our apps never had a huge launch before, anyway. Our modus operandi has always been to grow over time. So we don’t need every feature in there from the start.

I am excited. I’m sitting at my desk in my office in my home and I am excited. Release Notes 2017 is over and it always takes a toll on me.

But it’s worth it.


Update: Dan Counsell, who was also at Release Notes, has a great post on why going to a conference will help your business. I really wish I knew this when I first started my indie career.


Feel free to reach out on Twitter. I’m @yonomitt.

Have a nice day,
Yono

They'll Never Take Our Freedom

I dislike those typical blog posts when the blogger tells the audience about how they’ve fallen off the blogging horse but are back and are here to stay. Usually, the blogger will write 2–3 more posts – sporadically – and thus dies a blog.

So this isn’t that kind of post. Although it will become clear as to why I haven’t written in a while.[1]

Starting late last year, I took an unexpected break from work. My son became extremely ill and needed to be hospitalized. My wife, new born baby daughter, and I moved into the hospital to be with him at all times.[2] We lived in the hospital for three months. Theoretically, there was plenty of time to work, but my head just wasn’t in the right place to do anything productive.[3]

Early this year, after we finally came home, I still had difficulty getting into any kind of working grove. Our son’s life will never be the same and we were adjusting to our new situation.

Apparently, I am not the type of person that uses work as a distraction.

But this is exactly why I value my current professional situation. I am lucky. I completely understand that. Not only does my wife have a good job[4], but prior to going indie, we both saved our money almost religiously. Additionally, my apps continue to sell, providing an almost passive income, when I am not working.

The combination of these three things, gives me the freedom to take an extended break to be with my family.

This doesn’t mean I never want to work again. I do enjoy creating things. But I prefer to do it on my own terms. It’s comforting to know I have this option.

In fact, mid-August, I started a six month contract working for a German startup, in addition to working on Gus. It’s been a ton of fun and I really like the people, with whom I work. But prior to starting, I once again dialed down the work in order to spend more time with my family. Although I continued working, it was not as much and usually at odd times.[5]

For me, this freedom to choose when, on what, and how much I work is extremely important.

I hope they never take my freedom.


Feel free to reach out on Twitter. I’m @yonomitt.

Have a nice day,
Yono


  1. I am trying something very simple to encourage me to write more. I’ve added an item to my daily todo list to write for 15 minutes.  ↩

  2. We literally lived in a room in the ICU for a few months. German healthcare is sooo much better that US healthcare. But that’s a different blog post.  ↩

  3. Although, I did start learning French to help keep my mind somewhat occupied.  ↩

  4. She’s currently on maternity leave – again, the German social system is amazing  ↩

  5. Often when everyone else was asleep.  ↩

Getting the Most Out of a Mailing List

WARNING – I’m not an expert at using mailing lists. But I am trying to get better. While the info in this post isn’t revolutionary or new, I’m capturing it here to remind myself of it.

A couple of weeks ago, I attended Release Notes. I caught up with friends and met a lot of new, interesting people. I learned a lot and came away with good ideas.

After returning home, I continued unfinished conversations with other developers over email. I really enjoy discussing others’ businesses as it often gets met to look at my own from a different angle. It removes my self-imposed blinders.

Coincidentally, two separate email threads ended up turning to newsletters and email lists. And this got me thinking.

I’ve mentioned Alice and I are not doing a great job utilizing our mailing list. It’s something we really want to change, but have been lacking motivation, ideas, and time.

Thinking about how others could concretely benefit from a mailing list brought my attention back to how we could also make use of my own advice.

Getting people to sign up

The first important challenge is getting people to sign up. There are probably two good ways of doing this:

  1. Give something for free for signing up[1]
  2. Promise to provide regular, useful tips or advice via the newsletter

Both of these options require that the content you are giving away greatly interests your target audience. I assume that approach #1 has a higher rate of signups.

Getting people to read the newsletter

The goal, though, is not to just get a ton of subscribers. Subscribers should actually read the newsletter. Otherwise, why have one?

This is the benefit to approach #2, in which people subscribe specifically to get the content of your newsletters as opposed to a one time free product.

Each time someone reads your newsletter, you get to educate and entertain them. When subscribers consistently read your newsletter, you also give them more chances to become customers.

I know from my own personal experience with podcast sponsorships, the more I’m exposed to a particular product, the more likely I’m going to try it out, if it fits my needs. However, if your newsletter content compliments your app, then it likely fits the needs of your subscribers.

Regular readership can be an important marketing tool.[2]

There is another benefit to putting out a regular newsletter. Over time, you start to amass a large collection of content that potential, future subscribers can use. Collect these tips into a document and offer it in exchange for newsletter signups a la approach #1. This could accelerate the rate of signups.

A hypothetical example

Around this time, I listened to an episode of Core Intuition[3], in which Manton said he felt that anyone making a blogging app should have a blog and anyone making a podcast app should have a podcast.

As indies, we tend to create products for our hobbies and our passions. This is a natural fit. We become experts in what we love to do.

So let’s take a newsletter for a well made blogging app as an example. Provided that Manton and I are correct, the creator behind the blogging app is an avid blogger. The extra value the developer can provide to their audience might be writing tips[4]:

  1. Cut filler words out of your sentences (i.e. that, basically, just, etc…)
  2. Writing the way you talk makes your blog more relatable.
  3. Avoid passive voice whenever possible.
  4. etc…

Each newsletter mailing dives into one piece of advice in depth. It includes good examples using the tips AND bad examples ignoring the tips. It helps the readers understand how to incorporate the advice into their own writing.

Some issues of the newsletter may take on alternate forms. An occasional one might focus on blog posts, where the developer loves the writing style and why. Others, perhaps, point out posts where there are problems with the writing.[5] People learn from both good and bad examples.

Ideally, the newsletter’s content appeals to the developer’s subscribers and a decent percentage read most issues. Over time, those who are not already customers realize that if this newsletter gives them so much value, maybe they should try the app that the newsletter accompanies.

Gus on the Go newsletter woes

After going through all of this in my correspondence with other developers and again while writing this blog post, I realized what I think might be the problem with our newsletter.

Our newsletters chiefly discuss:

  1. a new post on our Gus on the Go blog OR
  2. a product announcement[6]

The carrot we use to get people to sign up for our newsletter is super cute printables that parents can download and make with their kids and use as supplemental learning material.

The issue is that our newsletter content and the printables are not necessarily for the same audience. I mean this at a granular level.

People who sign up specifically for the crafts might be more interested in hearing about tools they can use to keep their children active with a new language. They may not be motivated to read our blog post, which generally consist of interviews with parents or educators.[7]

I think we need to better align the newsletters to the reason people sign up. It will make customers happier.

Also, we don’t send out nearly enough newsletters.


Anyway, I hope you get the idea.

Unfortunately, I still haven’t worked out how to best implement this system I’m touting for our language learning apps. I’ll keep thinking about it and working on it.

If you have any comments, I’d love to hear them. Find me on Twitter. I’m @yonomitt.

Have a nice day,
Yono


  1. What we currently do  ↩

  2. I dislike the phrase marketing tool, but can’t think of something better right now.  ↩

  3. At about 6min  ↩

  4. I did not research these, so they may not be the same tips a professional writer would give. Use at your own risk.  ↩

  5. Please don’t point to me!  ↩

  6. Just sent out one today  ↩

  7. Although they should be, as they can potentially learn a lot from others. Maybe we’re not emphasizing that point enough?  ↩

Finding My First Consulting Job

Back in February or March, I decided I wanted to start consulting in addition to creating my own apps. I wrote briefly about it in a post, but haven’t mentioned it since.

In all honesty, getting into consulting ended up being a very slow process for me. I half hoped, foolishly, that simply announcing my interest in writing apps for others would be enough to get the ball rolling. And while several developer friends sent me encouraging messages after I wrote that last post, it was soon clear I would have to do more to land that first job.

While Redefining Indie for Myself was written in late May, I started thinking about this 3 months before that. So, let me back up slightly…

In the beginning

Being very unsure how to proceed, I started off just collecting information. Seems logical, right? In all honesty, this was more of an excuse to procrastinate finding clients. Information collecting was so much easier than acting.

I attended a couple of conferences in the spring. During which, I spoke to many developers about how they got their clients. It was the perfect opportunity to learn the secret formula.

The answer was universal. Networking. Sometimes phrased as through friends of friends.

Sigh. This was less than ideal. Networking is a weak point of mine and I wanted a foolproof formula I could just follow. I am a programmer, after all. Give me steps 10–30!

So, I continued putting off action and stayed in the information collecting phase, searching for an answer I liked better.[1]

Then, while attending UIKonf, I met Jaimee.

Jaimee, stage left

I am a little embarrassed to admit that prior to hearing an interview with Jaimee Newberry on Release Notes (part 1 and part 2), I did not know who she was. I only “discovered” the iOS community fairly late and am somewhat unfamiliar with a lot of the members.

Jaimee has a very contagious energy to her. Listening to the interviews and hearing her talk about her freelancing experiences got me excited about trying to find a consulting job again. I was reinvigorated to go after that first client!

As it just so happens, we both were going to be in Berlin for the same conference. Perfect! I had a ton of questions for her. She was going to be the one to reveal the secrets of finding clients! Right?

Secret formula:

Through connections and meeting people.

Sad trombone.

But, wait! She then said something that made me realize I was asking people the wrong questions. She said that you never know where a job can come from.

This comment flipped a switch in my brain. Until this, I had focused on talking to other iOS developers about consulting[2]. Suddenly, the list of people, to which I should reach out, grew tenfold.

Why hadn’t I realized this before? My best guess is self inflicted blinders. Because I started by talking to other iOS devs, I had led myself to believe that this was the type of friends of friends networking I had continually heard about. The fact that people, who need software development, are not necessarily software developers themselves blew right by me.

Jaimee went on to ask me if I had a website showcasing my consulting offerings and skills. Nope. I should have really thought of that one on my own.[3]

And while I’m very confident in my technical abilities, my ability to sell myself is severely lacking. Jaimee picked up on this immediately and told me I must to work on it. It’s super important but will only come with practice.

To Jaimee – You changed they way I think about consulting and for that, I sincerely thank you!

Act III

After talking with Jaimee, I immediately made a list of 62 new people to contact to get leads. 62!

I once again started slowly. I’m not entirely sure why. Some people I knew better than others. Some I hadn’t talked to in a long, long time. Some I wanted to talk to in person. But, in all honesty, these were just excuses.

At some point I picked up the pace. I began getting a lot of positive responses from people. Not necessarily about work, but rather that they would ask around and keep a look out. I had people putting out feelers for me.[4] I was feeling optimistic.

Then, in late July, I attended a birthday/good bye party for a friend of mine in Frankfurt. I was talking to another friend there. I told him my wife is expecting and about my plans to start taking on consulting work.

He replied, “Have you talked to Marc? Sometimes they [his company] need help with contracts.”

Oh really?

I connected with Marc and about a week and a half later, I was starting my first consulting job.

Epilogue

I am not an expert in getting client work.[5] At the time of this writing, I’ve finished one job, turned down two, and have a good lead on another potential project.

However, I truly think getting the first job is the most difficult. Not because jobs are hard to come by, but because I was standing in my own way. I wasn’t allowing myself to use all resources at hand to find a project. Once, I removed my blinders, things got easier and I made progress.

To sum up:

  1. Networking and friends of friends is very important. But don’t limit yourself to who you contact. Make a list of people to email and start working your way down the list. Go to parties and social events. Attend meetups. Tell everyone you are available for work.
  2. Setup a website touting your consulting services and skills.[6] Point people to this website, so they can forward it on to potential clients.
  3. Learn to sell yourself and your services. This comes with practice. I’m still very much working on this. If a client asks if you can do something, of course you can. If it’s reasonable. Even if you have to learn it, you can do it. Learning on the job is inevitable and super fun.

Have any tips to share or want to tell me how you got your first job? I’m all ears! Find me on Twitter. I’m @yonomitt.

Have a nice day,
Yono


  1. Ignoring data and continuing to search for hypothesis supporting information is bad science. I should have known better!  ↩

  2. If you’re noticing that I’m using the word consulting a lot instead of freelancing, it’s because I’ve been a strongly influenced by a talk Kirby Turner gave at 360iDev this year.  ↩

  3. Duh.  ↩

  4. I need to remember to keep in touch with them.  ↩

  5. yet  ↩

  6. I’m still working on mine. It’ll be up soon. I swear.  ↩

How a Developer Learned to Think Business: Part 2

This is a continuation of last week’s blog post, which started with me talking a friend out of making an app for his business – thanks to Release Notes.

One thing I realized after writing the post was how much I think about business. This, to me, is unbelievable. While I have always tried to think about the non-coding aspect of my business, Release Notes has really helped me up my game. It helped me make it a priority.

One month after the release of Stories by Gus on the Go, Alice and I had a brainstorming meeting. We were disappointed with the launch of the app. Rather than wallow in self pity, we wanted to do something about it. We came up with a list of marketing and business ideas and have since slowly started implementing them.

Many of these ideas grew from seeds planted while attending the Release Notes conference.

The conference

Last year, when Joe and Charles announced they would be putting on a conference, I knew immediately I wanted to attend. And that without ever having attended one before[1].

I convinced Alice we needed to both go as a company with the hopes of learning new things and meeting new people. Maybe we could even help others with our experiences.

I bought tickets very early on. If not on day one, then pretty darn close to it. I was that excited.

Other people started buying tickets and posting such on Twitter. As I am not the best at talking to strangers in person, I used these tweets to introduce myself and follow them long before arriving in Indianapolis.[2] I did so hoping to learn a little bit about the other attendees. My goal was to avoid awkward introductions at the conference. Although my awkwardness still came out, I think it helped me tremendously.

Additionally, I made sure to wear the same hat[3], as the one in my Twitter profile pic. Being unknown in the developer community, it helped some people recognize that they interacted with me online. This is a technique I continue to use while attending other conferences as I have found it quite useful.

There are four aspects of Release Notes that I believe really made my first conference experience so incredible.

  1. Non-technical talks - This is a big one for me. I’m looking to improve my skills, where I am weakest. Business, marketing, self promotion, recognizing opportunities, and networking are all areas, in which I could use help. The talks gave me a lot of ideas. For instance, thanks to John Saddington’s talk, we’re looking into creating a microsite to help draw people’s attention to our main site and products. Jean MacDonald inspired us to consider other ways to market our apps, including podcast and site sponsorships. Chris Liscio helped us realize how much more potential our apps have for niche languages.
  2. Dine around - A fantastic idea in and of itself. All conference attendees were split into groups of about 10 - 12 people, including one of the speakers. Each group was assigned a restaurant and forced to socialize at dinner. This really allowed us to get to know some of the other attendees quite well. It was especially helpful for the introverts among us.
  3. Plenty of time between talks - This, I would find out later, was very key. The conference was single track. With everyone in the same room, the extra time between talks gave us more opportunities to meet one another. There was no feeling of rushing to the next talk. We could take our time and exchange ideas on our businesses or what we learned.
  4. Slack channel for conference attendees - Super helpful in scheduling meet-ups and meals outside the conference events, without having to comb through Twitter. It also gave me the confidence to meet a group of people the day before the conference started.

Everyone I met at Release Notes was friendly and were there for the same reasons as I. To improve our business skills.

I know Charles and Joe put in a lot of work behind the scenes to make the event run as smoothly as it did. They did an amazing job. It shouldn’t come as a surprise that I will be coming back to this year’s Release Notes conference.[4]

Will I see you there too?

Say “hi” on Twitter. I’m @yonomitt.

Have a nice day,
Yono


  1. I did attend iOS 7 Tech Talks in Berlin in 2013, but I don’t think that counts.  ↩

  2. Pro tip.  ↩

  3. An orange Houston Astros hat. It stands out a bit.  ↩

  4. I also bought tickets very early this year.  ↩

How a Developer Learned to Think Business: Part 1

I had an interesting experience last week. I talked a potential client out of getting an app made. It was absolutely the right decision and I have Release Notes to thank for this.

Sounds odd, right? Let me try to explain in a way that doesn’t make me sound like a crazy person.

While I was on vacation a couple of weeks ago, a friend and former colleague sent me an email. He is starting a side business and wanted to have a companion app for it. The email was long and I was trying to avoid any and all work, so I marked it as unread and put it off until I got back.

Sunday night, I read the email and immediately responded with the suggestion we talk over the phone. I wanted to make sure I understood what kind of app he wanted and what features he imagined should be included. I wanted to remove any ambiguity.

I was excited. The project sounded super interesting. Additionally, I’ve mentioned that I want to start picking up freelance work to add some stability to my income. This just fell into my lap. I was feeling lucky.

Monday night, I called my friend and we started chatting. I wanted to find out more about his new business in order to make meaningful suggestions and contributions to what the app would look like. I asked questions. A lot of questions. Seriously. Lots.

About 15 minutes into our conversation, it dawned on me. Despite my really wanting to do this project and take him on as a client, an app is not what his business needs at this time.

My friend’s market is very niche, which, in itself, is not a bad thing. But having an app would not likely drive more customers to discover his business. The companion app he envisioned would be more of a convenience for existing, repeat customers.

I told him, as engineers, our first instinct is just to create something cool. Open up Xcode and run. We need, however, to consider if it makes business sense to create this cool thing.[1]

So instead, I started talking to him about more advantageous things, in which to invest time and money at this point. Driving traffic to his website through targeted and creative marketing, starting an email list and newsletter[2], and getting his first customer.

Many of these things are themes that have really been driven home for me through listening to the Release Notes podcast and attending the Release Notes conference last year.

Release Notes

Any regular reader of this blog knows I am a big fan of Release Notes. I’ve mentioned the podcast or the conference in quite a few posts. Just go up to the search bar and check for yourself.

But why?

There are tons of excellent podcasts, sites, newsletters, and blogs dedicated to the technical aspects of creating an app.[3] Unfortunately, there are not enough good and entertaining ones focused on running an app business.

This is what makes Release Notes stand out.

And while I generally do not have trouble on the programming side (thanks in part to being able to easily find the information I need online), I do need constant help on the business side of things. I need to frequently keep my engineering urges in check. I try to force myself to think more about the business of an app.

The podcast

Each Monday, the Release Notes podcast is prioritized to the top of my playlist. I usually listen to it within a day, if not a few hours.

It didn’t always used to be this way. But over time, I realized this is one of the podcasts I look forward to most. Almost every episode gives me something to think about and consider that I normally would not. Frequently, an episode topic will lead to a discussion with my partner, Alice, about what we could be doing better with our Gus on the Go business.

The podcast helps keep business at the front of my mind, while I’m working on my apps. I learn a lot from it. I really cannot emphasize this enough[4].

It is a big reason as to why I was able to steer my friend away from having an app made and make meaningful suggestions to help grow his business.

The conference

Last year, when Joe and Charles announced they would be putting on a Release Notes conference, I knew immediately I wanted to attend…

However, as this post is already getting long, let’s save that story for next week.


Until then, you can find me on Twitter. I’m @yonomitt.

Have a nice day,
Yono


  1. If you don’t want it to be a hobby.  ↩

  2. And using it!  ↩

  3. It’s one of the reasons I rarely feel the need to write technical blog posts.  ↩

  4. Maybe if I tried a bold font?  ↩

Keeping an Open Mind

Today I want to write about Brexit. Well not quite. Brexit is only tangentially related.

I woke up on Friday the 24th, rolled over, and grabbed my phone. The first thing I did was google the result of the UK referendum. Did they vote to stay in or leave the EU? I was pretty sure I knew the answer.

I am not British, so why am I interested? I do have some British friends, but I am also completely fascinated by the implications for Europe and the world. I happen to live in Europe and the world.

Brexit result

I was shocked.

I had expected the Remain campaign to win by a landslide.

Why?

While I read lots of facts about it online, most of the opinions about the referendum I received via Twitter.

Who do I follow on Twitter?

Mostly developers - iOS, Android, and game.

This made me realize how homogenous the opinions in my Twitter feed are. And this concerns me.

Keeping an open mind is an area I am constantly trying to improve in. I firmly believe that the only way to grow and learn is to be able to recognize that there could be more information out there that needs to be considered. Being willing to change my mind based on new information, while difficult, is extremely important to me.

From my Twitter feed, I was only receiving intelligent arguments and opinions from one side. I was blind to the reality of how big the other side actually was. The complete picture escaped me.

This worries me. A lot.

I did not do a good job seeking out other information in this case.

What does this have to do with development?

The iOS developer community can often behave as an echo chamber. It makes some sense. Generally like minded individuals will share a lot of the same opinions.

I do not mean this in a derogatory way, either. I only discovered this community a little over a year ago and I have met a ton of fantastic people. There is a reason why I am attending four conferences this year after going to my first one last year.

My need to keep an open mind, however, is why I keep a toe in the Android world.[1]

Android is important to iOS developers

I listen to Material to help me keep in touch with what Google and specifically Android are up to. It also doesn’t hurt that the hosts are quite entertaining.

Despite being fully invested in the Apple ecosystem, I love the idea of Android. The competition is good for both platforms. It drives innovation. Each one makes the other stronger.

Apple loves Android

By not dismissing Android outright and by trying to learn about it as much as I can, I am a better developer.

Remember back in the day when iOS developers mocked Android development for having to support a bazillion screen sizes? I did not. I learned from it and was ready long before Apple expanded it’s lineup. The multi-resolution solution[2] I came up with for my Gus apps – influenced by porting them to Android – worked right out of the box.

Having to deal with cheaply made, low-resource-having Android phones lead me to write much more efficient and mobile friendly code. My iOS customers benefit from this, too.

Back to Twitter

Thinking about it more, I probably will not change anything about my Twitter “problem”. Most people I follow on Twitter, I follow for a reason.

Instead, the solution for me will be to try to recognize situations, where I am only receiving information from one side. I can then go out to other sources to try to learn about all the other opinions available. This won’t be easy, however.

And while this usually will not result in a change of opinion, it will allow me to be better informed and strengthen my thoughts one way or another.

That and I should not be as surprised as I was by the Brexit result.

Opinions? Comments? Good or bad, let me know on Twitter. After all, I am trying to gather more information about all of my opinions! I’m @yonomitt.

Have a nice day,
Yono


  1. Well, I do have some Android apps, too.  ↩

  2. Awesome new band name  ↩

Marketing using an iMessage Sticker App

I did not watch the WWDC Keynote live. For some reason, I rarely do. But I did watch it a few hours later, while working at my computer.

Some things I liked. I am optimistic about improvements watchOS 3 will bring to my used-every-single-freakin-day Apple Watch. I like that Siri is being opened up to developers[1]. I’m intrigued by Apple’s use of differential privacy[2].

Some things I did not like. Syncing desktops sounds like a horrific nightmare. Due to Apple’s frequent problems with iCloud syncing, the new Optimized Storage feature of macOS Sierra is also nothing I want to touch.

But of all the things I disliked, the announcement of iMessage stickers was, by far, the worst. My first reactions were, UUUUUUGGGGHHHHH and I’m not 13. This did not, at all, sound interesting.

Then, it got worse. They announced that developers could create iMessage stickers without a single line of code. Everyone and their dog is going to make a sticker app. I can only image how many resources Apple will have to dedicate to keeping copyright infringement out of the iMessages App Store.

As a side note, aren’t the animations used to peel a sticker off the sheet a little skeuomorphic for a post iOS 7 Apple?

Still, I downloaded the video for the iMessage Apps and Stickers, Part 1, anyway. Then, shortly after, I downloaded part 2.

Wait, what?

Despite not caring a flipping bit[3] about virtual stickers, I was intrigued by the new possibility for app discovery. By watching the first sessions, I also hoped to discover what else might be possible with iMessage apps outside of the stickers realm.

However, while watching the videos, I had a little revelation. I realized that our Gus apps had a bunch of super cute, original characters. These characters could work perfectly as iMessage stickers.

iMessage plus Gus characters
Unfortunately, Apple rules seem to prohibit screenshots of the sample Gus sticker app. Use your imagination.

Combining this with iMessage app discovery, maybe this was something worth further investigation, after all.

Marketing using stickers

The main goal of a Gus sticker app would not be direct sales, but rather brand awareness.

Always be branding
Always be branding

I know we have a great product. We receive a fair number of emails from enthusiastic users confirming this. The problem is, as I see it, not enough people know about Gus.

How does a sticker app help with brand awareness?

At a macro level, iMessage is nothing more than a social sharing app. People receiving Gus stickers will automatically be prompted to install the Gus sticker app via a link below the message. This is built into iMessage on iOS 10.

Bob will send a Gus sticker to Jill. Jill will download the app and send Gus stickers to all her friends. You know. Because she likes them so much.

Based on this concept, we can spread the Gus brand to new, potential customers. Not all of them will be interested in a language app for kids. But some may be. The goal will be to ensure that people know about the other Gus apps. Perhaps through links to the website or apps from within the Gus sticker app? I need to see if this is possible and permissible.

Yeah, but is it worth it?

The most basic form of the sticker apps is extremely simple and quick to create. I would venture a guess that dealing with iTunes Connect will require more time than the actual app creation.

One might think that the generation of the image assets could take a bit of time. Luckily, one of the first decisions Alice and I made while making the original Gus on the Go app was to create all of our assets in vector graphic format.

Neither of us knew how to use Inkscape, but I already had a strong inkling we needed to go down this route. We learned the tools and stuck to it. Our initial effort paid off when we ported to Android and again when Apple started releasing more devices with different resolutions.

Since I wrote some scripts to to export images from all of my SVGs at any resolution, asset generation will be super easy.

Our early decision will once again pay off.

Having removed any and all difficult barriers, it seems almost silly not to proceed.

The worst case scenario is spending a few hours to create and upload this sticker app and it ends up doing nothing for brand awareness. Under the best case scenario, the sticker app becomes super popular, tons of people download the app, we get featured by Apple, and the Queen of England knights me. Sir Yono. I like that.

The reality is probably somewhere in between.[4]

But, due to the amount of time I need to try this out, the return on investment does not have to be high to make it worthwhile.


If all goes well with a Gus sticker app, I have some ideas to make an interactive iMessage app that works with the language learning apps we already have. That, however, is a blog post for another time.

I probably spent more time thinking about, writing, and editing this blog post that it will take me to create the sticker app.

Do you have a similar idea for marketing your app through an iMessage app extension? Feel free to ping me on Twitter if you want to discuss it. I’m @yonomitt.

Have a nice day,
Yono


  1. Somewhat… baby steps  ↩

  2. This was the first time I had heard of the concept and it sounds super interesting.  ↩

  3. Binary pun.  ↩

  4. Awww… I was ready to buy a trusty steed and go off to fight dragons.  ↩

Keeping Files Synced

The first Mac I bought was a second generation MacBook Air. I bought it specifically for development and portability. I was in a long distance[1] relationship with my then girlfriend, now wife. So I was traveling a ton.

That laptop was my main development machine for over three years. Can you imagine? It only had 2 gigs of RAM and a 120GB hard drive[2].

During this time, I had a couple of hardware issues. I ended up replacing the hard drive out of warranty. Three times. I was frequently worried about what I would do if it died completely. It seemed inevitable.

My wife suggested I buy an iMac instead of a new laptop. By this point, I was living in Germany. Her thinking was, since I did not travel as much, it would be better to go for power and a large screen to make development easier. She was absolutely correct.

On the german version of Craigslist, I found a slightly used, barely a year old Mid 2011 iMac at a fantastic price. So I bought it.

The problem

Now I had a problem. I had two computers I regularly used. My iMac when I was at home and my MacBook Air when traveling. How could I best keep files synced between the two?

Old solution

Admittedly, my original solution to the problem was super clunky. Are you ready for this?

Flash drives

Flash drives.

Lots and lots of USB flash drives. I had a tiny bag full of them with me at all times[3].

This did have some positives. USB drives are universal. They work with everything. Additionally, they are relatively cheap.

However, they’re not optimal. They are slow and insecure. By insecure, I mean that if I were to lose one, anyone could read the data off of it. They’re not that hard to lose, either.

Frustration

At some point, I had enough. I was tired of constantly swapping USB sticks between computers trying to remember which file was where and, more importantly, which file was the most current version. It was not a very well organized system.

I wanted something like Google Drive or Dropbox, but private. Something I controlled.

New solution

I own a Synology DS413, which doubles as a file server and a part of my backup system.

While searching for open source solutions to the problem, I discovered that Synology has an app for that. It’s called Cloud Station.

Cloud Station

I simply installed a package on my NAS and downloaded the client app to each of my Macs.

It does exactly what I want. It seamlessly syncs files between my computers.

Cloud Station screenshot

I rarely have syncing conflicts. When it happens, Cloud Station syncs both files and clearly names them as having a conflict. It’s usually trivial to figure out which copy I want.

I keep my current projects in the Cloud Station folder and link to them from elsewhere in my directory structure. I do this to prevent having to copy more files than necessary between my computers.

So far I am very happy with this setup. It is fast, easy, and secure. Well, as secure as my home network.

Desktop syncing in macOS

In the WWDC keynote, Craig Federighi introduced desktop syncing for macOS Sierra. While this could possibly work for what I’m doing, it scares the hell out of me!

I strive to keep a clean desktop on both of my Macs. I usually, utterly fail. If the desktop were my primary method to sync files between computers, all hope would be lost.


Do you have another solution for syncing files between computers? Is it better than mine? Let me know!

You can find me on Twitter. I’m @yonomitt.

Have a nice day,
Yono


  1. US - Germany  ↩

  2. Not SSD  ↩

  3. Ok, maybe not all times. But it did more or less permanently live in my backpack, which I took with me most everywhere.  ↩

App Analytics Part 2: More Custom Events

This is a followup to my last post on app analytics with a couple more gotcha examples[1] I ran into. I originally wanted to include them in the last post, but it was getting a little long.

Time measurement issues

An activity in Stories can be categorized as a lesson, review, story, or game. One thing that really interests us is how long our users spend in each type of activity on a per story pack basis.[2]

If very little time is spent, for instance, in a particular game, we want to know. It could be sign the game is either too hard, too easy, or not at all fun. It would also act as a reference for us to see positive and negative impacts of updates we push to the AppStore.

That in mind, my first attempt was a complete and utter failure. Much like with the Tapped event example in the previous article, I initially created an attribute dictionary that looked something like:

let lessonNumber: Int = ...
let timeInSeconds: Int = ...
let attrs = ["Lesson Number": lessonNumber, "Time": timeInSeconds]

Seems logical, right?

But can you spot the problem with how Fabric is going to display this data?

Fabric will aggregate each key-value pair into separate graphs. Numerical values in the attribute dictionary are graphed versus the date collected, while string values are counted up.

Doing this, I got one graph plotting lesson number on the y-axis versus the date on the x-axis and one graph plotting time versus the date.

The second graph sounds ok on the surface, but thinking about it further, it’s an aggregation of time spent in all lessons over time. I wanted time per lesson.

Completely. Utterly. Useless.

To be fair, I was thinking about this all wrong. My fallacy was assuming a dictionary with two key-value pairs would be interpreted as a two axes graph. Had I stopped to think about what would happen if there were more than two entries in the dictionary, maybe I could have avoided this unnecessary issue. Then again, maybe not…

A solution

The way I’ve fixed this, which seems fine for now, is to build my attribute dictionary slightly differently.

let attrs = ["Lesson \(lessonNumber)": timeInSeconds]

This produces graphs more like what I need:

Lesson 0 time analytics

Feature discoverability

Alice and I were also curious about the discoverability of some of the key features of the app. One feature, in particular, is the ability to swipe horizontally and vertically in the interactive lesson.

Interactive lesson

My first attempt to log the horizontal and vertical swipes looked like this:

let num: Int = ...
let vertSwipeCount: Int = ...
let horizSwipeCount: Int = ...

let eventName = "Interactive Lesson Swipes"
let attrs = ["Interactive Lesson Num": num, "Vertical": vertSwipeCount, "Horizontal": horizSwipeCount]

This did not work. Again, all the lesson numbers were aggregated together as were the vertical and horizontal swipe counts. While this gives a little bit of information, as we now knew whether there were any swipes, it wasn’t fine-grain enough for what we needed.

Again, I’m not sure why I thought Fabric could intuit information about my data. How are they supposed to know that those three entries could be grouped nicely into two groups of two? I was too close to it to see there could be other interpretations.

Another solution

I chose to fix this particular issue by breaking out the custom event into two separate events.

let vertEventName = "Interactive Lesson Vertical Swipes"
let horizEventName = "Interactive Lesson Horizontal Swipes"
let vertAttrs = ["Interactive Lesson \(num)": vertSwipeCount]
let horizAttrs = ["Interactive Lesson \(num)": horizSwipeCount]

I could have used a single event such as:

let attrs = ["Interactive Lesson \(num): Vertical": vertSwipeCount, "Interactive Lesson \(num): Horizontal: horizSwipeCount]

However, due to the number of different interactive lessons in the app, it would be more organized to separate the events.

Drawbacks

One thing that still frustrates me is the lack of access to the raw data. Through their dashboard, I can see graphs of recent data, but only the last 30 days. I still can’t download a CSV file with all of my events.[3]

Both of these combined means that if I want to reinterpret my data later, I’m out of luck.

If Stories were to become popular enough, I may look into rolling my own analytics engine and server to gather the data I need. Unless, that is, I learn about a different product that can serve my needs. Or unless Fabric updates their product. Please?[4]


Thanks for reading. If you have a comment, feel free to ping me on Twitter. I’m always happy to learn from others.

I’m @yonomitt.

Have a nice day,
Yono


  1. That’s a technical term  ↩

  2. A story pack is a collection of activities centered around the theme of a single story, such as The Three Little Pigs. It’s the top level of hierarchy in the app.  ↩

  3. If there is a way to do either, please let me know!  ↩

  4. Overall I do like Fabric. It’s almost everything I need.  ↩

Redefining Indie for Myself

For the last four years, I have been exclusively creating and selling my own apps. To me this was the definition of being indie. It wasn’t until I attended Release Notes that this definition started to evolve.

At the conference, I met so many indies, who did not fit my preconception. I met freelancers, book writers, podcasters, bloggers, and people who made their living doing combinations of all of the above. I had been so deep in my own business, I could not see the other possibilities.

In a talk he gave at 360|iDev last year, Charles Perry put it this way:

“If you can take a nap without asking permission, you’re indie in my book.”

I like that.

Freedom

When you boil it down, the most important thing to me is freedom. I have been using the freedom of the indie lifestyle to benefit myself and my family.

My wife was pregnant with our son when I left my job at IBM to go indie full time.

The freedom allows me to be at home as necessary. I drop off and pick up our son from day care. I stay at home with him when he’s sick. I can go grocery shopping and run other errands to keep the household running smoothly. I try to buy fresh flowers for the house once a week. And I often cook dinner for my wife after she’s had a long day at the office.

I’m kind of like a stay-at-home dad, who also works whenever he has a spare minute.

This freedom has been extremely important to us.

Although growing each year, revenue from Gus is not enough to live off, yet. I’m in an extremely lucky position that my wife believes in Gus on the Go and is willing to financially support our family until it gets there. I really married up.

The Times They Are a-Changin’

My wife is now pregnant with kid number 2. She will go on maternity leave in October and likely stay at home until mid 2017[1]. While she gets paid during this time, it will be a fraction[2] of what she currently earns.

I want my wife to have a relaxed pregnancy and enjoy her time at home after the birth. I don’t want her to feel pressured to go back to work before she is ready.

Venture into the unknown

As of immediately, I will begin looking for freelance work. I will continue growing Gus into a sustainable business, but until that time comes, freelancing should add some stability to my income.

I have been thinking about this for several months now and first started talking to other developers about it at UIKonf last week.

Thanks to the people I met at Release Notes, my definition of indie has changed. As long as I still have time for my family when they need me, I will be happy. If I can take a nap without asking permission, I will still be indie.

This new chapter of my indie career also brings about other benefits. I will get to try new things. I hope to play with new technologies that do not make sense to use in a children’s language learning app. I will learn a ton from the experience.

Not that working on Gus has been boring, but a change of scenery can be inspiring.


Know anyone looking for an experienced developer for freelance work?

Help me out! I’m @yonomitt

Have a nice day,
Yono


  1. Germany has fantastic maternity/paternity leave laws! She gets 6 weeks before the birth and up to 12 months after. Wake up America!  ↩

  2. Before you ask, yes, the denominator will be larger than the numerator.  ↩

Out of My Comfort Zone

The last four days, I was in Berlin for UIKonf. This was my first time attending the conference and I really enjoyed it. There were some great talks and I met a bunch of nice people.

While at UIKonf, I had a fantastic opportunity to do something that scared me. Something that required me to venture out of my comfort zone and hopefully grow a little because of it.

I’ve mentioned before that I’m more introverted than not and have a hard time talking to new people. But despite having plenty of opportunities to do that at a conference, that isn’t what I am writing about here.

The Sunday before the conference talks started, UIKonf organized various tours around Berlin – a bike tour of the city, a tour of a WWII bunker, and more. I elected to attend the brewery tour.[1]

The brewery tour was unfortunately plagued with bad luck from the start.

I arrived slightly late and somehow did not recognize the slightly large group of people standing on the street waiting. I had been looking for the blue UIKonf shirt of the volunteer, who was the central contact point for the tour. None of those waiting matched that description.

I proceeded inside and asked the bartender where the brewery tour group was.

“The tour was cancelled.” He replied.

That’s not good.

I quickly sent a message to the UIKonf Slack channel to inquire.

“No way!” was the response I got back from one of the conference organizers. “I’m on my way,” he added.

While waiting, I discovered the group standing out front did in fact belong to the conference. We elected to sit down and enjoy some beers, until the mixup could be resolved.

Shortly after, a guy in a blue UIKonf shirt showed up. It was the conference volunteer in charge of the brewery tour. It turns out his car had broken down on the way. He apologized profusely for being late, but we assured him it was unnecessary. Sometimes, you just have bad luck. Anyway, we were already enjoying the beer by then.

Meanwhile, the organizer, I had informed, showed up and started working things out with the brewery. The brewmaster was now on his way.

But there was a hiccup. Initially, while organizing the tour, the brewery assured the UIKonf organizers that it would be given in English. Attendees come from all over the world and English would be the common language. It turns out the brewmaster spoke very little English.

“Can anyone here translate the tour for us?”

I could. Probably.

Although, I’m not a native German speaker, I am fluent.

But I didn’t speak up.

I had never done on-the-fly translation in front of a crowd. That sounded terrifying. Even if it was only about 20 people, it might as well have been 100.

Our conference volunteer said he would do it, but added that he wouldn’t be able to translate any of the technical brewing terms. The brewer said he could try to work around that.

Crap.

I could translate the brewing lingo.

When I lived in Portland, a friend taught me to brew beer. I continued home brewing after moving to Austin. I knew the words in English and because I had once met a brewer in the Black Forest, I also knew those words in German.

Against every instinct in my body, I slowly raised my hand.

“I… I can translate from German to English. I also know the brewing terminology.”

I was shaking. I felt as if I were visibly shaking. Maybe I was.

I stood next to the brewer waiting for him to begin. With two or three sentences, he introduced himself to the crowd. Then, he paused. He held his hands out toward me to indicate I should translate. In the nervousness of the situation and in trying to keep everything that needed to be translated in my head, I forgot his last name.

He told me it was no big deal, I had gotten the important information across.

Phew.

I had started. Starting was hard. Now I had no choice but to continue.

I began occasionally mixing some jokes in with the translations. This is a bad habit of mine. When I’m nervous or uncomfortable, I joke around more than usual.[2] Kind of like Chandler.

He gave me a smiling nod of approval.

Phew. Again.

I didn’t translate word for word, but rather tried to get the meaning across. For the most part I think I succeeded.

The brewery tour went on for an hour and a half. He commented that it normally only lasts 45 minutes and usually doesn’t get so many questions from the crowd. I had to translate those for him and then his answers back.

By the end, I noticed my jaw was sore. Not from talking, but apparently when nervous, I tighten my jaw muscles. I was extremely glad when it was over.

Many of the attendees thanked me for stepping up and told me they enjoyed the tour. I didn’t know what to say, but I remembered something I had read not too long ago. When someone goes to the effort to complement you, simply accept it and say thank you.

I felt a euphoric rush. I had been confronted with a chance to do something that terrified me and I did it. I stepped out of my comfort zone. I learned something.

Over the next couple of days, I paid close attention to the speakers and organizers on stage. Some were nervous. Some seasoned professionals. Some nervous, seasoned professionals.

They all got up in front of a large crowd and gave a talk. If any were anything like me, that was probably super terrifying. I only had a small taste of what it must be like.

Maybe I’ll try speaking at a conference, next.

Yono


  1. It was technically a brewpub, but that’s not important.  ↩

  2. My wife will call me out on this and tell me to stop. But she wasn’t there.  ↩

App Analytics Part 1: Custom Events

I have never done much with analytics in my apps in the past. This is not, however, because I don’t think it’s important or useful.

My problem with analytics is that it’s overwhelming. There is so much data available, a lot of times I don’t know what I need to track. However, I see my lack of knowledge as a fantastic excuse to learn through experimentation.

In app analytics

The driving force behind wanting to track events from within my apps was to improve the quality of the apps themselves.

While working on Stories, Alice and I were making a lot of design decisions based on instinct and based on a limited number of beta testers.

We spent a lot of time agonizing over details like how to best introduce new vocabulary, how to make the stories more engaging, and whether or not features were discoverable.

Instead of guessing, we wanted real numbers. This led us to add analytics to track the things we were curious about.

Expectations of our users

The first thing we wanted to track was user expectation.

The goal is to make each scene in our stories highly interactive. This keeps the users engaged and curious to discover what else the app can do.

For instance, in our Goldilocks and the Three Bears story, tapping on the clock in the background causes the clock to quickly advance 12 hours. In the same scene, tapping on the logs in the fireplace briefly lights a fire.[1]

Interactive examples in Goldilocks and the Three Bears story

However, playing with our own stories day in and day out, we’ve developed a perspective that’s too close to the issue. We needed to see where real, actual users expected to be able to interact with the scene.

For instance, if enough users tapped on a rock in the scene but nothing happened, we wanted to know. We would then have the option to add an interactive component to the rock via a future update.

Since, a non-interactive part of the scene was, generally, something baked into the background, I couldn’t just report which items were being tapped. I also couldn’t just report every single touch location. That could be an overwhelming amount of data.

My solution was to break up the screen into a 10 x 10 grid and keep track of which squares were tapped.

Example scene with underlying grid

From this I wanted to create a heat map across all users for each scene.

Example scene with heat map

Custom events

For this to work, I figured I could use Fabric’s custom events to track the scene number and the grid number tapped. Additionally, I would need the screen resolution, as that would change the shape of the grid squares. I cannot directly compare iPhone taps to iPad taps without conversion first.

The way custom events work, you give an event a custom name and pass in a dictionary of custom attributes.

Perfect. I could do something like this:

Answers.logCustomEventWithName("Tapped", 
		customAttributes: [
			"scene": 22, 
			"grid": 58, 
			"width": 1024, 
			"height": 768])

Right? Nope.

Well I could, but it turns out that each of the key value pairs in the attributes dictionary are aggregated vertically[2] together.

How attributes are presented

This means that instead of finding out I got 100 taps on grid 58 of scene 22 for a resolution of 1024 x 768, I might get that the median scene tapped was 22 and the median grid tapped was 58, etc…

Not exactly useful.

I emailed Fabric’s support team to find out if they had a way to visualize the data differently. The answer I got:

Everything you’ve asked for is in the eventual roadmap, but not something that can be done at the moment. The best solution we’ll likely release in the near future is a way for you to download your data as a CSV so you can do some manipulation in R or another program you use for data analysis. More sophisticated visualizations based on attribute data are definitely in the planning though- we’ll keep you posted!

This was on August 26, 2015. As far as I can tell, the ability to download a CSV with each event is still not available. I can download CSVs for general metrics, like event counts or number of event users, but not one with the custom attributes for each event sent.

Temporary (?) solution

One thing I am going to try is converting my custom attributes dictionary from above to the following:

Answers.logCustomEventWithName("Tapped", 
		customAttributes: ["scene 22, 1024 x 768": "grid 58"])

This would group all taps for scene 22 on a 1024 x 768 screen together. By making the value in the dictionary a string instead of a number, Fabric would give me counts of those events instead of trying to average them together.

I’m not completely happy with this, but it might be the best solution I available to me so far.

I still need to find a way to get the data out of Fabric and into a script that will create a heat map for me…

What next?

This was a good way to start experimenting with analytics. I made some assumptions, discovered they were wrong, and corrected based on what I learned. I have some more lessons learned I want to share, but as this post was getting long, I’ll save them for another post.[3]

I am still learning, so if you have any suggestions or know something I’m clearly missing, please find me on Twitter and let me know. I’m @yonomitt.

Have a nice day,
Yono


  1. You don’t hear it in the animated gif, but in both instances delightful sound effects also play.  ↩

  2. I don’t know if this is the right term, but hopefully the diagram makes it clear.  ↩

  3. Stay tuned!  ↩

App Store Review Craziness

What’s going on with App Review?[1]

Yesterday morning, I uploaded two apps to iTunes Connect. One that had to go through beta review to be sent to external testers and one that had to go through normal app review to be sold in the AppStore.

Here’s the odd timeline (all times CET):

  • 10:01 - Release app uploaded
  • 11:38 - Beta app uploaded
  • 15:46 - Release app rejected[2]
  • 16:09 - Release app uploaded (again)
  • 19:09 - Release app approved
  • 01:07 - Beta app approved

In the 13 hours and 29 minutes it took to approve my beta app, my release app was rejected once within 5 hours and 45 minutes, then fixed, and then approved in 3 hours!

No expedited reviews were requested.

AMAZING!

Mic drop

Find me on Twitter. I’m @yonomitt.

Have a nice day,
Yono[3]


  1. One of the few times that’s meant in a positive manner.  ↩

  2. For the exact same thing I wrote about here. You’d think I would learn?  ↩

  3. My shortest blog post yet!  ↩

Discipline vs Motivation

The following tweet recently popped up in my Twitter feed:

While reading it, I found myself nodding along agreeing with every word. But something wasn’t right. I couldn’t quite put my finger on what, though, until I discussed it with my wife.

I love discussing intellectual topics with my wife. While we don’t always agree on things, we respect each other’s opinions. We also help each other express our thoughts more clearly than if we were trying to formulate them on our own.

That exactly what my wife helped me with in this case.

While there is some truth in the rant, the more I thought about it, the more I disagreed with the overall message. I think my disagreement can be summarized with one sentence:

Discipline gets the bare minimum done, while motivation allows you to excel.

There’s also no need to choose one over the other. You need both. Discipline is a safety net. Something to fall back on when motivation is not there. While I prefer working when motivated[1], having the discipline to continue when not is invaluable.

I also believe you can train yourself to be motivated. I recently wrote about what I do to motivate myself when I’m just not feeling it.


It feels weird to write such a short blog post. Maybe I just wasn’t motivated?[2]

Find me on Twitter. I’m @yonomitt.

Have a nice day,
Yono


  1. Who doesn’t?  ↩

  2. While that’s supposed to be a joke, quantity is rarely a valid measure for a job done.  ↩

Theoretical Swift Master

I write our Gus apps primarily in C++ sprinkled with a little bit of Objective-C code.

My first app, which I still update, is written entirely in Objective-C.

This means I have not had a need nor desire to learn Swift. I simply did not understand people’s fascination with the language.

Ok, that is not entirely true. I do have one unreleased keyboard extension app written entirely in Swift. But honestly, it’s a bit of a hack job. Not only was it largely written in an Objective-C frame of mind but I also did not understand most of what the compiler was telling me I needed.

However, I thought it made me a Swift expert.

Earlier this year, I discovered it did not.


Have I ever mentioned I listen to a lot of podcasts? In an episode of Core Intuition, Daniel Jalkut said he was reading the The Swift Programming Language little by little. He had added a repeating task in OmniFocus to keep him on track and encourage him to get through it. Daniel said that the book was teaching him the nuances of Swift and it really got him interested in what he could do with the language.

But, frankly, reading a programming manual sounded boring to me. So I did nothing.

A couple of months later I was listening to an episode of SharedInstance. In it, the guys recommended the Protocol-Oriented Programming in Swift video (also known as the Crusty video) from WWDC[1].

To be honest, I had not watched any WWDC videos from 2015[2]. However, if there were one video I had heard about, it was this one. It just kept coming up.

Ok, I was curious. Time to check out what this was all about.

Step 1: Watch the Crusty video

Using my daily hour allocated to learning something new, I watched the Crusty video.

This made me realize I knew nothing about Swift. On top of that, the message was so powerful, it got me really interested in actually learning about the language.

Soooo….

Step 2: Read the manual

I decided to follow Daniel’s example and read The Swift Programming Language, despite assuming it would be really boring.

Boy was I surprised. The manual is very well written. I mean extremely well written. Hats off to the Apple engineers and technical writers that put it together.

#DanielWasRight

Often when I read books on programming or follow online tutorials, I’m left with some questions.

What would happen if I changed this…?

Does this need to go here…?

Why does this need to be in there…?

I then write a test program or app to try to answer my questions.

Inevitably, while reading The Swift Programming Language, questions would pop into my head. The nice thing about programming in Swift is the availability of playgrounds to quickly test an idea. I would then start a Swift playground to try them out.

However, as if the authors anticipated my train of thought, within a few pages the book would actually answer the very question I had! I learned I needed to be a little more patient with firing up a Swift playground.

Step 3: Read blogs and newsletters

Just like when you get to the end of a really good work of fiction, after finishing The Swift Programming Language, I wanted more. I started reading blog posts that would pop up in my Twitter feed. I googled for even more articles on Swift. I subscribed to several iOS related newsletters.

I could not get enough.

Result: Theoretical Swift-ist, Ph.D.

I now had a ton of theoretical knowledge, but very little practical experience. I needed a pet project to test out and refine my Swift knowledge.

Since the graphics for Gus on the Go are 100% vector based[3], I decided to write an SVG reader. A benefit of choosing this project was I could use the subject matter in the Crusty video as a starting point.

My Swift learning adventure is currently at this phase.

I’m writing my SVG reader using my one hour of learning per day. This is nice because it breaks up the monotony of constantly working on Gus. Additionally, when I get stuck on a problem in my Gus code base, taking a break from it to work on the SVG reader tends to give me a new perspective. When I get back to Gus, usually, I figure out the issue quickly[4].

I may, after getting the SVG reader completely working, implement an SVG drawing app. Who knows. It sounds like fun.


I am truly excited about learning more and trying new things in Swift. Something I never imagined I would say a little over a month ago. I haven’t been this excited about learning a new language since I learned Python.

Thanks for reading. Feel free to ping me on Twitter. I’m @yonomitt. I try to post regularly on random topics of interest to me.

Have a nice day,
Yono


  1. They also spoiled the twist. Thanks Sam!  ↩

  2. Again, because Gus is mostly using C++. And time.  ↩

  3. Arguably one of the smartest decisions we made early on.  ↩

  4. This also happens when I sleep.  ↩