I want to document how I got custom push notification sounds working on iOS and Android with the React Native Firebase library and Firebase Cloud Messaging (FCM).

The process is not difficult once you understand it. It’s just hard to find a complete set of instructions on how to do it. I hope this will save you time when setting it up in your project.

Set up the Firebase libraries

First step is an obvious one. Make sure you install React Native Firebase core library and the Cloud Messaging modules. Be sure to follow all instructions for each platform carefully.

Select a sound format

Apple supports .wav .aiff or .caf files. Android supports .mp3, .ogg or .wav.

Since our back-end server used the same push body for both platforms, it was easier to use a format that both platforms could share, so I chose .wav.

Set up custom sound on iOS

  1. Go to your_project_root/ios and place the sound in there. This doesn’t yet add it to the project, it just places the sound in a logical spot.
  2. Open up Xcode and go to the project navigator tab.
  3. Drag your sound into your project. Select “copy files if needed” on the dialog.
  4. That’s it!

Set up custom sound on Android

Setup on Android is a little more complex than iOS. As of Android API level 26, notifications need to be set to a notification channel in order for them to work at all.

Android Notification Channels

The channel defines the sound to use, vibration pattern, and other things about your push notifications. React Native Firebase creates its own channel internally to help provide a basic push functionality with their Cloud Messaging library, but if you want a custom sound or other customization, this channel is not accessible to you to edit. You must create your own custom notification channel. On native Android, this is Java code that executes at runtime, it’s not done on a configuration file.

React Native Firebase does not provide an API to this native API for creating a channel. It used to provide it on v5, but since v6 it has stopped supporting it because it was out of scope of Firebase.

Luckily it’s pretty simple to add you own without the need of a custom library to do it. You simply need to update your MainActivity.java file in your project so a notification channel is created and configured.

Before you can create your notification channel. You must do the following:

1. Define a name for your notification channel

It can be anything, and you will use it to target your custom channel from your push message, so that the custom sound you will tie to your channel plays.

I should note that after installing the app the channel name will remain registered until the app is uninstalled. So keep that in mind if you change channel names later.

2. Add your sound as a resource

Drag your .wav sound into the your_project_root/android/app/src/main/res/raw folder (if it doesn’t exist, create it).

Add the notification channel code

The code below must be placed inside the onCreate method of your MainActivity class. Fill in the text surrounded in brackets with your own, and customize anything else you need on your notification:

          NotificationChannel notificationChannel = new NotificationChannel("{ENTER THE NOTIFICATION NAME HERE}", "{ENTER APP NAME HERE}", NotificationManager.IMPORTANCE_HIGH);
          AudioAttributes att = new AudioAttributes.Builder()
          notificationChannel.setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + getPackageName() + "/raw/{ENTER SOUND NAME HERE WITHOUT EXTENSION}"), att);
          notificationChannel.setVibrationPattern(new long[]{400, 400});
          NotificationManager manager = getSystemService(NotificationManager.class);

Here’s a code example with some values filled in:

          NotificationChannel notificationChannel = new NotificationChannel("new_email_arrived_channel", "My Emailer", NotificationManager.IMPORTANCE_HIGH);
          AudioAttributes att = new AudioAttributes.Builder()
          notificationChannel.setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + getPackageName() + "/raw/my_custom_sound"), att);
          notificationChannel.setVibrationPattern(new long[]{400, 400});
          NotificationManager manager = getSystemService(NotificationManager.class);

Notice my_custom_sound is not written with the extension (.wav). You just need to add the file name.

Test the custom sound

With the sound in place you can now test your implementation. Before you can test it you will need to fish out Firebase’s FCM token from your app. This token is used by FCM to route the push notification to the correct device.

Log the FCM token to your console

Firebase lets you retreive the FCM token using the messaging().getToken() function. Use this function to log the FCM token to your console:

const _getToken = async () => {
  try {
    const token = await messaging().getToken();
    console.log('FCM token registered:', token);
  } catch (error) {
    console.error('Error getting FCM token:', error);

Do this for both Android and iOS devices. It will create a different token for both.

We will use this token to test sending push notifications directly to our test devices.

Test with the FCM REST API

I will show how to test with the FCM REST API because it will give you all the flexibility you need to edit the push body as you would need to set it on your server.

Follow the steps below to get testing.

Install Postman

Postman is a great API testing application for your desktop computer and will make setting up the FCM REST API very easy. Download and install the app here

If you could purchase a script that set up a custom push notification sound on your project, would you buy one?

Get your Firebase server key

Before we configure Postman we need that our API push requests are authenticated against our project. For this we need to authenticate with our server key. To find it:

  1. Go to your Firebase project
  2. Click the project settings button (the gear icon) and select Project Settings
  3. Go to the Cloud Messaging tab
  4. If you followed installation instructions for React Native Firebase earlier, you should have a server key listed at the top of this page. If you don’t it means you have not yet set up your project for Cloud Messaging and you need to go back to the installation instructions.
  5. Copy the server key

Configure Postman to send an FCM push request

  1. Open Postman
  2. Click on the + button on the page to create a new API request
  3. For the HTTP method, set it to POST
  4. Set the URL to https://fcm.googleapis.com/fcm/send
  5. Go to the Authorization tab
  6. For authorization type select “Bearer Token”
  7. Add your server key from your Firebaess project, into the token field
  8. Go back to the body tab
  9. Set the body type to “raw”
  10. Make sure the data type at the end of the body type options is set to JSON and not Text or any other type

Set up the push body

Now that your request is configured, let’s add the push body. This is done in the body tab in the empty area under the data type options. Here is an example body:

    "to": "<FCM TOKEN>",
    "notification": {
      "title": "Some title",
        "body": "Some body",
        "sound": "my_custom_sound.wav",
        "android_channel_id": "new_email_arrived_channel"
    "data": {
        "field1": "value1",
        "field2": "value2"
    "content_available": true,
    "priority": "high"

The key items here to get your sound to work is the “to”, “sound”, and “android_channel_id” fields.

to field

Here you will need to add your device’s FCM token in quotes

sound field

Your sound field must set the sound name including the extension.

android_channel_id field

The “android_channel_id” field must have the name of your custom Android push channel you created earlier. These names must match or else your channel won’t be found and your device will simply play a default sound.

NOTE: You may find some forums out on the internet saying the field name should be “channel_id” and not “android_channel_id”. This is half true. They are correct that the REAL name for the push field is “channel_id” on Android. But remember, we are using FCM and FCM handles both iOS and Android. We are not making a request to Google’s push server directly.

So for FCM, the field name is “android_channel_id”, but once the push is delivered to the Android device this field comes in as “channel_id”. FCM translates the field name correctly for us once its delivered.

Send the notification

Hit the send button on Postman, you should receive the push with custom sound.

If you get any errors on the API call, make sure you resolve those

Troubleshoot common problems

If you are having trouble getting the sound to play or the push doesn’t come through here are some suggestions you can try to help you troubleshoot.


Hope this helps you in your push journey. It’s strangely a confusing and complex feature to set up.

Copy of MainActivity.java for reference

package io.myapp;

import com.facebook.react.ReactActivity;

import org.devio.rn.splashscreen.SplashScreen;

import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.ContentResolver;
import android.media.AudioAttributes;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;

import androidx.core.app.NotificationCompat;

public class MainActivity extends ReactActivity {

  protected void onCreate(Bundle savedInstanceState) {
      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
          NotificationChannel notificationChannel = new NotificationChannel("myapp_notification", "MyApp", NotificationManager.IMPORTANCE_HIGH);
          AudioAttributes att = new AudioAttributes.Builder()
          notificationChannel.setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + getPackageName() + "/raw/myapp"), att);
          notificationChannel.setVibrationPattern(new long[]{400, 1000, 400});
          NotificationManager manager = getSystemService(NotificationManager.class);


   * Returns the name of the main component registered from JavaScript. This is used to schedule
   * rendering of the component.
  protected String getMainComponentName() {
    return "MyApp";

When I first looked into how to plan, market, and launch my timesheet and invoicing software product Dev Dashboard, I got discouraged because there was more info about how to go about it than I could take in.

After a lot of reading and YouTube-ing, I found myself going through what they call “analysis paralysis”. I had too many options, too much info, and I couldn’t make a decision.

However, after some time of having this product idea in my head I realized that I needed to stop thinking and do something, anything, and start getting one foot in front of the other.

In this post I’d like to share my simple set of questions, to help you take your first step in creating your software product.

The questions

What is your idea?

Describe what your idea is about. Keep it short — pretend you want to describe it to someone in 30 seconds or less. Mention the benefits of your app to your users. It doesn’t have to be perfect. Remember, you can always come back and adjust it.

In my case, for Dev Dashboard, my idea sounds something like this:

Dev Dashboard helps freelance software developers increase productivity with a simple, easy to use time tracking and invoice app that runs on the desktop.

Who do you want to help?

Write down some things that describes your user. What are their habits? Where do they hang out online/offline? What sort of pain points do they have that relate to your product? Where do they live? What do the like to eat?

As I said before, it doesn’t need to be perfect. The important thing is to get moving forward. Just begin to write some useful things down that helps you better understand your users.

Here’s what I wrote for Dev Dashboard:

Target Users:
– Remote freelancers
– Digital nomads
– Multiple clients with different timesheets
– Use a lot of different ways to keep track of time (multiple timesheets)
– May use spreadsheets to track time
– May use templates for invocing
– Use a lot of manual process to create invoices, track time
– Wears multiple hats in their business
– They are located globally
– They work for agencies
– They work for mom and pop shops
– They work in small teams

How does your app benefit your users?

If you can’t describe how you can benefit your users you might not have a good app idea. So this one is important. Think about how you can save them time, increase their productivity, increase their revenue, improve their life in some way, make them happier/healthier, etc…

Think about why your app will help them — what is the reason behind the reason.

Here are some benefits I wrote for Dev Dashboard:

– Make better business decisions by planning and tracking your annual income goals against your current revenue
– Improve your work efficiency by using a single source of truth for all your timesheets
– Keep clients happy by staying easily informed of project budget progress
– Stay organized with all time data and invoices tracked in one spot
– Decrease stress by using a clean, easy to use and efficient application

Are there similar products out there?

Do a little research on your competition. Maybe you will find that there is already a great solution for what you want to build, and you can move on to your next idea.

Get inspired from competition

You might also find there are some similar products, and as you learn more about them you will think of ideas of improving your own idea that you hadn’t even thought about.

Write down the top ones, and describe how your app is similar and different to each.

What I did

For my product, 3 similar apps where Freshbooks, Timely, and Toggl

There were a lot of similarities, and they have some features that I just can’t compete with at this time, but I did find some differences where I could take advantage:

How will you make money?

We all want to make money with our idea. Now you need to think about how you will provide a lot of value to your users at a price they are willing to pay.

Get a point of reference

To get an idea of what the price range could be, I looked at my competitor price points to see what they were doing.

Freshbooks has these prices points: https://www.freshbooks.com/pricing
Toggle has these: https://toggl.com/pricing
Timely has these: https://memory.ai/timely/pricing

They all have 3-4 options, ranging between $5-$50, and they also have custom pricing.

What I did

In my case, I think their price ranges are pretty broad. As an individual developer, I should be able to give a lot of value and compete at a reasonable price point.

I’m not yet sure about what my own prices should be, so it’s still a work in progress. But I will definitely provide a free option, a middle option with added value, and a custom option where users can pick and choose their features.

Provide a free option

It’s important to always give a free option. Users want to test your app out before they buy. As we saw, the timesheet apps provide a trial version. Which is acceptable.

I personally prefer just a “no strings attached” free option, which is what I’ll do, but you need to decide on what will be best for you.

How will you find users?

Ok, the product is a little more fleshed out, and you have some possible price options and target audience. Now, you need to figure out how you will find your audience.

I’m not sure where to find them

If you still have no clue where they could be online, maybe you need to spend more time defining your users. Go back to that step and see if you can flesh it out more.

*Make a list of sites**

When you’re ready, make a simple list of possible sites, social media, forums, groups, chat channels, or any other place your users visit, online or offline, where you can engage with them and ask them to check your app out and give you feedback once you have a version of your app ready to test drive.

What I’m doing

What I’ve decided for my product so far has been to join Indie Hackers, which is a great community for product developers, and start engaging with others who are also building products. I also plan to post on LinkedIn, and connect with other freelance developers who may be interested and build a network that can help me better understand their needs.

In the future I plan on doing more, but the idea here is to get started and moving forward. Don’t overthink where you will find users, just select one or two sites, and focus on those. If you see those places aren’t working, just choose another.

Who else do you need on your team to help you?

This is an important question. Do you need a software developer? A designer? Someone in sales?

Get the right team in place. Don’t try to do too much on your own, that is if unless you have the time of course. If that’s the case, I recommend you do as much as you can, if you’re good at it.

How much will it cost you to build this?

Once you know who you need, define an MVP for your product. Get cost estimates from the team you bring in. Calculate what your infrastructure and third-party service costs are per month.

This may also make you adjust your software price.


In conclusion, I hope this helps you get started. If you’re interested in my journey in building Dev Dashboard, check our posts here. I will be blogging more about it and sharing my experiences ?

Many of us software developers love to build things, and many are creating their own products to add additional revenue to their business, or just to make their own lives easier.

I created Devstimate as a product that will make my life a lot easier (and hopefully the lives of other freelancers out there), and hopefully in the future it can be a way to add a little extra revenue. We have to start somewhere, right? ?

I’ll tell you how I came up with it.

Estimating… so tedious?

I’ve been freelancing and running my own software development company for quite some time already – a little over 8 years. As any software developer will tell you, every project is different, each with its own unique items to consider.

We cannot really use a specific estimation “template” of some kind, that could cover all our cases. They just vary too much. There are some common things, but they apply sometimes differently, or with more or less complexity.

In a month I estimate projects for leads at least once or twice. The process for me goes like this:

  1. Lead provides information about their project, and provides wireframes, description, flowcharts, designs
  2. I use this information, go through all the documents and begin to form questions for the lead, to clarify details
  3. If things are clear, I begin the process of breaking down the project into logical chunks
  4. I break down each chunk into tasks, and estimate them
  5. Once I estimate all tasks within each chunk, I run these estimations through some form of formula that can give me a cost estimate
  6. I then calculate a lower/upper range for this estimate
  7. I add any necessary markup
  8. I then provide this quote to my client, with a breakdown of the work, and the total cost

I then relax because I won’t have to do this tedious process again for another week or two.

Once I estimate, this estimation has been so customized, that I tend to discard it afterwards. It was of value to me for that client, but it won’t apply for other clients easily.

I wanted to be smarter about how I used my time. There were some estimation apps and calculators out there, but I didn’t feel I had the control I wanted. I wanted to be able to break projects down into tasks, and use some kind of base task as an estimation start, and modify if needed.

The idea to have the flexibility of re-using a task, applying default values when I wanted to, and overriding them when they didn’t quite fit, was also something I really wanted.

I also wanted this to be a quick experience. I wanted to search through a list of tasks and find the one I want in just a couple of seconds. And just tap once or twice to add it. No copying or pasting from an excel sheet, and definitely not having to remember what I estimated the same task in the past.

I also didn’t want to do math ?

The app should do the math for me.

I also really wanted to estimate as I already did with Agile teams, which was by using relative estimation with story points. This yielded a more accurate estimation for me than just estimating by hours.

This is why I decided to try and build something that could help me and others estimate their projects. Enter Devstimate ?

With Devstimate, I designed it to estimate in 3 ways. I can estimate by providing flat fees for each task, I can estimate by hours, and I can estimate using story points.

The first time I used it for an actual client, I could see the change right away. I was estimating a lot faster, and I felt less stressed. It was kinda fun almost, because it had everything I needed and I didn’t have to think too much.

I hope I can give this feeling to other developers. There’s a lot of work to do though. I just added the bare essentials into it for now.

How I architected the app

This brings me to more technical details, the architecture I wanted to talk about.

My architecture was based on some goals:

  1. Bring it to iOS and Android as soon as I can
  2. Don’t invest too much time into it. Who knows if I will find it useful let alone anyone else ?‍♂️
  3. Keep cost low, because, well, you have no budget

With this in mind, I went off on my adventure.

React Native

I decided to use React Native for this task. There was no need to do heavy native work for either platform, and I could share most if not all my logic through React Native.

I kept my idea simple to stick to my goals:

  1. No login at all
  2. Just a few screens that can be wired up quickly
  3. Minimal design, just focus on functionality
  4. Generate the totals in the simplest way possible


I kept the UI simple, and with the help of React Native Elements and React Native Vector Icons I was able to get components in place that looked nice, without having to think much about design at this point.

For list swiping, I used React Native Swipeable. It was simple to implement, and worked just how I wanted it to.

I had the front-end tech decided on, and I really did not want to spend time building a back-end system. This idea is not tested, I felt it would waste time. I did need to save the estimation data somewhere though ?


This looked like a perfect moment for Firebase, which is a serverless technology. I can save info directly to the firebase database, without a back-end.

Firebase also offers anonymous login. This means the user can log into my system anonymously, and their data can be organized by their unique anonymous ID. This was perfect. Saved me lots of time.

On the React Native side, I decided to use the React Native Firebase library. It’s a very cool library which lets me use the native iOS and Android Firebase libraries in React Native. Couldn’t have built it without it.

I wanted to shave some more time off by using other helper libraries in React Native. To help me with the Firebase integration into Redux, I used React Redux Firebase.

It was really helpful to have a lot of the Redux integration already handled for me, and the querying to Firebase is made a lot easier through this library.

For navigation, I used React Navigation, and my routes were simple, so there was no trouble at all here.

In total I spent maybe 2 months of part time work to get 90% of it done. The last 10% took very long due to my work schedule, and with the help of other developers we were able to finish the last lingering bugs.

What I learned so far

Since I built it, I’ve had a lot more experience in developing applications and using Firebase.

I think Firebase for this use case, was a perfect choice. The data is not that structured, and doesn’t require heavy querying. The anonymous login sets me up perfectly for the future when I do add a proper auth system. Anonymous accounts can be merged into real accounts, so my users data won’t disappear.

The built-in analytics also help me get basic analytics data into my dashboard, which is nice. I’m not too concerned with user counts right now, anyway.

I did learn that some of my initial ideas need tweaking. I think I can organize the tasks in an even easier set up, but adding the fuzzy search feature for tasks helped a lot in finding the task template you want.

One of the biggest things I overlooked, was the target platform for the app. It’s nice to have an estimator handy in your phone, but I really would like to have it on my laptop too. I might build a desktop version in the future.


Marketing is something I’m still thinking about. For now I’m going to try and blog about it more, invite other freelance developers to use the app, join forums, and try to get the word out.

I’m more concentrated on listening to users as they try it out, than I am anything else.


I’ll be writing more about Devstimate for sure, and other things I work on. If you’re interested in knowing a little more about Devstimate, check out my case study.

Also, don’t forget to check it out for yourself, on iOS or Android.

If you find this sort of topic interesting please come by again. Also, feel free to reach out if there’s any questions about the tech I used, or about anything about building products.

I want to talk about what startup founders/entrepreneurs do to build bad software for their business.

If you are interested in this post, you might be startup founder or business owner with a great app idea. You may already have a well thought-out business plan, and a solid marketing strategy to execute behind it.

You may not be tech savvy though. But you do have a general idea of the development process and what tech you need to implement. You just need someone with experience that can get it done.

It’s important to find the right person of course. But first, you need to know what a good developer experience looks like. Not knowing the service you are supposed to be receiving can blind-side you.

Many clients come to me with horror stories about their previous developer.

Some devs are terrible at communication — timezone differences aside.

Some devs start a project, then disappear.

Others don’t have the experience, and they tell you they do (sometimes they think they actually do). They make a mess of things, and create buggy, unscalable work.

Entrepreneurs later realize after many years of slow progress, do-overs, and endless bug fixes, their “dirt cheap” developers become insanely expensive.

It’s not the dev’s fault completely, either. There’s also things entrepreneurs do wrong.

I hope to point out some things that you as well as your developers are doing that is making your project fail.

I also hope to offer some tips on how you can improve, so you are in a better position to hire the right “Programming Ninja Expert Guru Person”, or whatever.

See the signs!

Here is my list of top problems which are clear signs that your software project is on the road to failure.

Sign #1: You hire a dev you don’t know

Your friend knows this guy, he’s about 15 hours away in the other side of the globe.

He seems smart, and even though he hasn’t worked in a team environment before, didn’t show work samples, and gave no real proof that he knows what he’s doing, you have a “gut feeling” about him, because he’s a really nice guy.

Plus, your friend recommended him. Your friend is not a tech savvy person either, but you trust he makes good decisions about fields he doesn’t know about.

Sign #2: You avoid experienced devs because they are pricey

You feel a Senior level developer is too expensive. You have to watch your budget after all! Two cheap Junior developers are still less than a Senior level developer, and they will do twice the work!

Sure, they haven’t led a project. But look how cheap they are! Besides, you can guide them yourself, and with a little effort they will get it through the finish line.

It won’t be “Senior dev” perfect, but it will save you tons of cash.

Sign #3: You don’t have a process describing how to reach your goals

Your dev doesn’t have a structured way of defining scope of work, scheduling releases, determining priorities, measuring their speed, enforcing project contribution guidelines, reviewing other devs’ work, automating processes, and many other things.

They just plan a list of to-do items and determine their own priorities. New work is completed at irregular rates and feels incomplete. There doesn’t seem to be a clear goal in mind with the work released.

You review the work and ask them to make updates. They push back saying the update will take too long, or will push the deadline further back.

You feel disappointed with the lack of order, confusion, and poor quality.

Sign #4: Your developer behaves like your employee

You created a document that describes what your app is about in detail. You added a list of features you would like such as social login, push notifications, database integration, messaging, etc…

There are flowcharts and wireframes for them to follow, and even references to other apps that have similar functionality to yours.

Your dev takes this initial information, and provides you with a quote. They also let you know they have enough information and are ready to get started with your project.

You are impressed that they did not ask you to clarify certain uses cases, what problem does your app hope to solve, who is your target market, how many users do you plan to have in the first year, and other important business-related questions that should direct the technical strategy.

They also did not push back much in the features or descriptions for your timeline, or how you hope to accomplish certain goals.

Since they haven’t asked much, you figure your documentation was enough, and they must have understood right away. Your gut tells you something is wrong, but you assume it’s fine because they are professionals.

Sign #5: Your communication with your dev is poor

You haven’t heard from your dev in weeks. You figure they are working because they continue to charge you.

They reply 3 days after you DM them. They tell you all is fine and they will have something for you soon.

You’re sure if they have any question they will reach out to you. Once something is ready for you to review, you can then see how things are going. You’ll just wait patiently.

Sign #6: You manage the project yourself

Agile method-what? User stories? Scoring sessions? Standups? Sprint planning? Roadmaps? Scoping? This is so unnecessary. Only large enterprise projects need this level of planning.

Your app is simple, and easy to understand by anyone.

You choose to just manage the project on your own.

You don’t understand the drop on communication from your developers, when you assign a task.

They seem to work extra slow, the tasks are not complete as you described them, and get bogged down by details they should have gotten right already.

You get the sense that they are not understanding the scope or reason for the ticket, and you feel forced to “micro-manage” them too much.

Sign #7: You are a perfectionist

Your app features are all equally important and refuse to remove any of them to lower the development timeline for “version 1”.

You already know what your target users want because you did extensive market research.

You refuse to lower your app’s quality at the cost of bringing it to market quickly, because you feel it will affect your brand.

It’s not you it’s us

Like I said it’s an issue on both sides.

There are underqualified developers running your projects, and entrepreneurs without the experience to know how it should run from the start.

If you relate to this, let’s talk about how to avoid the signs.

Tip #1: Vet your developers carefully

Don’t take anyone’s word (friend or developer) for the experience they claim. Ask questions that will let you better understand their experience. Below are some question you might want to ask (there are many more you can ask, these are just a few).

How long have you worked in the field?

This is a pretty basic question. If you are looking for someone to lead your project, you should find someone with at the very least, 3 years total experience, in my opinion.

I don’t mean 3 years experience in the tech you want to use, just 3 years in total development experience. Tech changes way too much, you should look for core experience and skill. This is a much better way to measure their experience.

Even so, they should have work experience similar to what you are looking to get done.

If they have been in the field less time, that’s fine, so as long as you have someone to lead them. They probably don’t have the experience to lead a project yet, unless they can demonstrate they can without any doubt.

Tell me about the apps you have developed in the past?

You want to know that they have done work similar to what you need, and are able to describe in some detail about their experience.

Viewing links to their work is not good enough. It leaves it up to you to guess at what they actually did.

Ask them for details. They don’t need to get too technical, but they should be able to explain some key details about their work that gives you some confidence in them.

Side Note: This will also help you gauge their communication skills. They should be able to explain to you in plain english, without going over your head, what they have done and the impact it had on the project. You want to hire someone who you can communicate well with, since you will be working closely together. You don’t want to work with someone who cannot describe development concerns to you in a way you can understand.

What has been your biggest challenge you have had to face on a project, and how did you resolve it?

I like to ask this question because it helps me understand what they consider to be a challenge, and how they think through problems.

For example, if their biggest challenge has been laying out a list of data, then you can tell they probably don’t have much experience, because laying out data on a list is pretty common. They still may be hireable, but they should not lead the project.

If you are looking for a tech lead, their challenges should come from an architectural perspective — the overall technical planning around the development.

Since these are broader ideas, they should be able to explain to you without getting too technical as well.

You want to look for challenges that are similar to the challenges you think your project has. If you have some use case concerns on your project, you might want to ask them how they would handle those cases, as a way to test them.

Can I see code samples of your work?

You need to know if they can write clean, scalable code that can be modified easily as your app grows, or if they create messy “spaghetti code” that is hard to modify and will burn through your budget.

You also need to know if their work feels over-engineered, or if it has an elegant feel to it.

This is pretty crucial, and one of the biggest problems I’ve found with problematic projects. The work is just not great, and needs huge re-writes.

Get help

It can be really tough to know if a dev is up to the task if you don’t have that dev experience yourself to dig deep into their experience.

If you’re having a hard time knowing if someone is a good fit, just hire an experienced consultant that can vet them for you. It will be worth the cost in the long run to hire someone who knows exactly what to look for, and how to ask the tough questions.

Tip #2: Hire a Senior Level developer

I have a particular set of skills

Why hire an experienced developer?

There is a drastic difference between experienced and inexperienced developers. The main difference is that inexperienced developers simply do not have the ability or know-how to build sustainable software.

A piece of software that is naively built can easily double or triple the cost of the entire project during its lifetime.

In contrast, while an experienced developer comes at a higher up-front cost, their experience will pay off in a big way in the end. Their years of experience in building applications lets them see issues way ahead of time. They can easily spot and fix bad architectural patterns that would otherwise become a nightmare down the road.

Experienced developers have failed enough to know what should and shouldn’t be done in a project. They have made all the mistakes you don’t want to make, many times over.

They are very efficient coders, and they have custom tooling and libraries to back them up as they work so their efforts are spent in the areas you need the most.

Devs with experience also typically have led teams already, and learned how to collaborate with developers of different personalities and temperaments. They also learned how to lead by example, share their knowledge, and not boss developers around.

Their experience is very valuable. The cost of an experienced developer in your corner, having that knowledge and skill available to your business is a great investment that can’t be understated.

Should I even hire a Junior dev at all?

Yes! Again, Junior level developers in your team are great so as long as they are being led properly. Don’t shy from hiring Juniors, they will definitely give you a lot of bang for your buck.

I recommend that each team of Junior devs are lead by a Senior team lead, who also assists in implementation, and can help in app architecture, recommending best coding practices, helping with code reviews, and determining high-level technical decisions.

If you feel a Senior dev is too expensive, then hire them only for tech leadership and/or project management portion, and not for the hands-on implementation work. That should lower their cost, and you still will benefit from their experience.

If you do have the budget, I do recommend one or a few Senior developers also assisting in implementation (doing the actual coding). They will bring high value this way by their efficiency, creating scalable work and by solving problems a lot faster and better than they do if they are only communicating their knowledge to Junior developers — this is a huge win.

Tip #3: Stay organized

Any developer with experience will tell you, a major part of software development is organization.

At a high-level there is also tons to keep track of (features, bugs, tasks, components, designs, userflows, transaction flows, etc…).

Since there is so much to keep in mind, it takes a bit of practice and experience to organize things in a way that makes sense to everyone.

If you don’t have a project management background, this may be difficult for you. And this can cause a lot of miscommunication between you and your developers.

As the product owner hiring a project lead, you should find a lead who can organize the project correctly. It is a big burden to put on yourself.

A good project lead will typically follow similar practices I describe below. There are more qualities of a good project lead, but this is just a small example of maybe the more important ones.

A good lead will organize and group tasks logically

The project lead should group tasks logically, with a hierarchy.

There are tasks that cover broad ideas (authentication, search, push notifications).

Some tasks track concepts within broad ideas (user registration flow, user roles, etc…)

Other tasks track details (implement UI registration modal, implement forgot password feature, add user admin role)

And you can break these down even more. The point is, there is a hierarchy. Tasks are organized in a logical order that is easy to identify and track.

A good lead will also try to centralize all project information into one location.

Discussions about a certain feature should remain in that ticket. Commits of work should be referenced in the ticket that commits belongs to. Links to supporting information should also be linked on the ticket.

Project-wide info should be linked at the project level. Things should be organized in ways that are logical, and require very little explaining to other team members.

The lead should use the right tools to bring all this together. Typically this is done with a decent project management tool, such as JIRA, or Pivotal Tracker, or maybe even Trello boards.

I personally use JIRA right now, it has everything I need to manage and track a project, and then some.

I’m not a fan of Trello, but I believe it may work for smaller projects.

It’s not important what they use. The main point is, they need something that can track work, and group/organize them in ways that make sense to everyone.

Be aware if their project to-do items have no form, no logical order, and related notes are in multiple places without a true “single source of truth”. These are the signs of disorder and confusion in a project.

A good project lead will favor faster releases over long drawn out releases

A good project lead will implement some form of the Agile method for software development, which is out of the scope of this post.

One of the concepts of Agile is releasing often. You don’t want to wait too long to get features out to users.

Their feedback is valuable and you should view them as collaborators on your product, to help you understand what they really want, and how you can deliver that to them.

Long timelines work against you because you don’t have a constant feedback that can direct your future features. It slows down your product’s rate of improvement.

A good project lead will have a workflow that keeps your eyes on the goal

One big reason for this is to avoid distractions. In my opinion, one of the main distractions is bug fixing.

As product owners review the work that is done, they will inevitably find bugs. There is no escaping this, and depending on how complex a feature is, you might have a lot of bugs to get fixed.


A common way to maintain a workflow structure is by using Sprints (another Agile concept). The project lead could make use of sprints as part of your worflow, to help with managing priorities and stay focused.

In a sprint, you create a range of time to commit to a goal. You prioritize tasks (and bugs) for the sprint, determine a common goal, and get working. You will not change course until your sprint is done.

If new bugs are found during the sprint, these are added to a backlog and are not worked on immediately. This keeps the developers focused on their goal for the sprint, and not on the bugs that are trickling in throughout the day.

Once the sprint is over, and it’s time for a new one, the tasks and bugs will be prioritized again, and the process starts all over.

Of course, if there are bugs that need to be fixed right away, they are added to the sprint.

Using sprints is a very common way which is good to be aware of. It may not be the only way, but the point here is to have a structure that reduces distractions and keeps everyone on the same page, and focused.

QA Workflow

Hire a QA person if it’s in your budget. As a product owner, you have better ways to use your precious time, than to check someone’s work every day, and submit bug tickets.

A QA person will check all work that may be released, and inform each dev of any bugs that are found. The devs will fix and update way before you ever get a review link.

It’s also good to mention that this reduces your stress level because you are not being bothered with the details of development.

Keeping your stress low will make a huge impact — it’s worth the investment.

Tip #4: Partner with developers

If you want to hire someone to lead your project, look for a developer who behaves like a partner, and not like an employee.

Partners will be proactive and will contribute to the project with ideas on increasing revenue or lowering costs.

They will also recommend the best tech for your business goals, and not just what they are comfortable in using, or what you suggest.

Aside from using their time, your dev should offer their knowledge and experience to better your business.

Tip #5: Communicate often

In my opinion, you should expect consistent communication from your devs, at least every couple of days to once a week, even if it is just a quick update.

You need to know how things are going, and what problems they are experiencing, so you are able to catch problems early, or re-align priorities.

Communication lets everyone know how that the project is moving, and keeps up morale.

You should also communicate and check in with your devs if you haven’t spoken in a few days, just to make sure all is well. When devs feel you care and know you are there for them, they also care ?

Tip #6: Minimum Viable Product for the win

Keep your initial version lean and nimble. You won’t know what your users really want until you get the product to them. The sooner you can do this the faster you can get feedback and create features real users are asking for.

No product will ever be perfect. It will continue to evolve and shape itself into something you may not even have expected.


I hope this post has helped you make better decisions with your software projects. If you have any questions about how you can avoid production problems feel free to write me, or catch me on LinkedIn

Let me tell you why you’re here.

You’re here because you know something, but you can’t explain it.

You’ve felt it your entire career.

There’s something wrong in your front end developer skillset — you don’t know what it is, but it’s there.

Like a splinter in your mind. Driving you mad.

It is this feeling that has brought you to me. Do you know what I’m talking about?

Of course you do. It’s Unix shell scripting ?

You never learned this world of scripting — bash commands and .sh files just looked like something other devs did. You, much like me, just copied and pasted commands and hoped for the best.

It’s good to take a little time to learn shell scripting, because it’s helpful and it’s actually not that hard to learn. The basic commands will take you far.

Knowing how to use shell commands will also make you a more valuable software developer. Plus, you will be just that much closer to seeing the matrix like Neo ?

In this first post of my Unix shell scripting series, I will try to explain shell scripting in a simple way, and I’ll show you the foundational commands that will make you productive right away.

With that said, pick the red pill, stay in wonderland, and let’s see how far the rabbit hole goes…


Unix on MacOs

You’ve been living in a dream world, Neo

The MacOS user interface is hiding from you a lot of what happens behind the scenes. The reality is, everything you do on a Mac is being controlled by Unix commands — moving files around, copying/saving, searching for files, downloading — the list goes on and on. The visual layer that we interact with, is just a pretty looking design that lets us control the lower things.

OK, So What is Unix exactly?

Unix is the core of the Mac operating system. It is what runs “under the hood” of the pretty UI we are used to and interact with. You don’t need to know much about Unix to get started using it, but here are some key points that are helpful:

Let’s get you ready for our ride. Sit still. This won’t hurt…


That helps, but what is bash scripting, and what is the Unix shell?

OK, you may have heard these before, but never really took time to know what they were.

Let’s get these terms out of the way. You will see they are very easy to understand.

You control Unix through a command line interface, as I said earlier. Unix commands need to be interpreted into something the innermost/lower-level components of Unix can understand. Unix requires a “shell” to do this.

The shell is the program that sits between us and the low level Unix things, that manages a lot of technical details, and interprets our commands to Unix in a way Unix can understand and execute our commands. Any time we write a command on the command line, we are doing it through a shell, therefore we never write commands outside of a shell program.

Unix is not married to one specific shell. This means you can actually pick a shell you like to work with, and use that. One popular shell is called Bash.

By default, MacOS uses the Bash shell. After some years of using Bash I thought I’d try a different shell that seemed to have some additional features. So, right now I personally use a shell called “Zsh”. If you’re interested in the differences between these two shells you might find this article intertesting.

That’s pretty much all the background info you probably need about the Unix shell. Let’s dive deeper.

What Are You Waiting for Neo? You are faster than this

You’ll be suprised what you can do on the command-line to speed up your workflow. You can automate moving and processing files, downloading data, replacing text in files, creating files and directories, searching files, and much much more.

The main idea with scripting is to make your work life easier. You can create commands that will automate repetitive tasks, and in the end make you work faster.

In front end development, this usually means we will automate some part of our project’s build process, but there are many other reasons to use shell commands.

Can I use programs I have installed on my machine to help automate things?

Yes you can. This is a big reason for automation. Most programs are built to allow you to use them in the command line, through a CLI (command line interface).

An example of a CLI can be seen when running Node.js. Node.js doesn’t ship with a visual interface. You can only interact with it through commands.

Other examples are Java, or the Android SDK, or Xcode. They all have a CLI that lets you interact with these programs. These are just a small list of programs. Like I said, most programs out there that you will use in front end development will probably have a CLI.

Note: It’s important for programs to be this flexible, because automations are rarely done on a user interface. Without the command line access, automating program tasks would be really difficult to do.

So, lets start with basic Unix commands you should know, but first, I want to make sure you know exactly where to write the commands.

How to open the terminal

Before we start, I’ll show you how to actually open the terminal on MacOS, so you can write commands into it.

To open it, simply open your finder, and open Applications/utilities/Terminal

You might want to add the terminal program to your dock, so it’s easy for you to open later.

By default, MacOS will use the Bash shell. So when you open the terminal, you will be logged into a Bash shell instance.

Basic Shell Commands

As I said earlier, you interact with Unix by executing commands. To execute a command, simply type a command in the terminal, and hit enter.

There are commands that allow you to do probably more than you will ever need. Since we are talking about front end developers here, we will stick to what is most useful to front end developers, and I will touch on some other commands that are good to know as well.

Let’s get into it. First, I’ll show you a useful command, that helps you get info on any command you want to learn about. There is a handy command in Unix, called man, that does this.


man = The command manual that will tell you anything you want to know about any Unix command.

Bash Script Example

This example would output the manual for the ls command (the ls command just lists files on a directory) and would tell you the options associated with it. This is really helpful when you are not sure what options a command has.

man ls

The manual on how to use the ls command, separated in pages.

While viewing a manual:

The next command you typically learn is echo


echo = Lets you print values on to the console. Similar to console.log in Javascript. You can print messages or print variable names to see their value.

Bash Script Example: Printing a message

echo Hello World

Hello World

Bash Script Example: Printing a variable

This will output a series of paths, tied to the $PATH variable:

echo $PATH


Note: More on the $PATH variable later, but it is basically a very commonly used global variable in Unix that stores paths


Exiting is odd to me, it is not consistent. It is annoying enough that I had to make sure I got in all the possible ways to exit here.

Typically, you can hit q when you are in a paginated output (such as the output the man command gives you)

You can also try x, ctrl + q, ctrl + x, or ESC

The more common ways to exit would be force quit with ctrl + c, or type exit.

We haven’t really done much with commands that would require and exit yet, but I have written this and will be here for you when you need it.

Going to a Previous Command

When you have a lot of commands you’ve written, you don’t want to write them over again later. You can press the ⬆️ or ⬇️ arrows in your keyboard, to go back/forward to the commands you have already used.

Going to the beginning or end of a command, or to a specific character in a command

Sometimes you want to edit a command you wrote already, this will help you go to the exact spot you need to edit.

ctrl + a = Move cursor to beginning of the line
ctrl + e = Move cursor to the end of the line
option + click = Moves cursor to where you clicked

Autocomplete commands or file names

You can save some time and have the shell help you autocomplete commands of file names for you

tab = Auto complete command or file name
tab + tab = Whenever auto complete doesn’t work, it will show a list of possible matches

Clearing your screen of output

Sometimes you have too much output in your Terminal. Run cmd + k to clear your output.

** Note: This will not exit/force quit your running script. It will just clear the output. **

Multiple Commands

You don’t need to run a command one by one. You can separate commands with semicolons.

Bash Script Example

ls; echo $PATH; echo complete!

That concludes the absolute basics. Are you ready for more?

Neo Kung Fu

Cool! Let’s continue by navigating the file system!

Navigating the File System

Unix lets you manipulate files in any way possible. You can view files in the command line, you can create new files, you can list files/directories, or launch an app that shows the file you want to view.

To do this, it’s first important to know that you need to target the directory the file is located in first, before you can actually do anything with a file. To do this, you typically will need to change directory from where you are to the directory the file is located in.

When you open the Terminal, the default directory you are targeting at that time is typically your user directory (the directory with your name). To switch to another directory, you will use the cd command.


cd = Change directories

Bash Script Example

cd to/some/other/directory

Note: If you know the name of the directory, you can type some of the name, then hit tab to autocomplete the rest of the name. If you are not sure what the name of the directory is, you can hit tab twice to get a list of options.

Other cd tricks

You can type cd and press the up/down arrow key to get the last directories you changed to.

To go back to the parent folder, just use cd ..

To go back multiple parent folders, just use cd ../../../, adding as many ../ as you need to go to the right parent folder

To go to the top most folder in your Mac, type cd /

To go to your user folder (the folder with your name on it), type cd ~

To toggle between current and previous directory, type cd -


Now that you can change directories, you might want to know what files are in a directory. To do this just use the ls command.

This command will list all files and directories in the current directory you are in.

There are a few options you can add to the command, which are explained below:

ls = List files/folders located in the current directory
ls -l = List files vertically, and display details about each file/directory
ls -la = List all files, including hidden files/directories
ls -lah = List all files as -la, but also showing file sizes


If you are ever confused on what directory you are targeting commands into, simply execute the pwd command. This returns the present working directory.

Manipulating the File System

Now that you know how to change to directories and list files, let me show you how you can read, modify, create and delete files.

How to Read Files

There’s a few useful commands for reading files:

cat = Outputs the contents of the file.

Bash Script Example:

cat filename.txt

less = Outputs contents of files, with pagination.

Bash Script Example:

less filename.txt

cat -n = Will output the contents of multiple files.

Bash SCript Example:

cat -n file.text file2.txt

Note: Doesn’t have to be .txt, can be any file type that can be read.

How to Modify Files

mv = Move file — also commonly used for renaming files

Bash Script Example: Move a File

mv myFile.txt my-directory-name

Bash Script Example: Rename a File

mv myFile.txt my-renamed-file.txt

cp = Copies a file. You can’t copy a directory with this command.
cp -R = Use this to copy directories. The -R option tells the cp command to copy recursively. This means it will copy a directory and its children.

Bash Script Example

In this example, “some-file.txt” is copied as “some-file-copy.txt”:

cp some-file.txt some-file-copy.txt

In this example, “some-directory” is copied as “some-directory-copy”. All files and directories inside of “some-directory” will also be copied into “some-directory-copy”:

cp -R some-directory some-directory-copy

How to Create New Files/Directories

mkdir = Creates a directory

Bash Script Example

mkdir myNewDirectory

touch = Updates access time of a file, or if the file doesn’t exist, will create it with default permissions.

Bash Script Example

touch someFileName.txt

How to Delete Files

rm = Removes a file (does not send to trash!)
rm -rf = Deletes a file or directory recursively (does not send to trash!)

Bash Script Example

I tend to always use rm -rf even on single files. This command will remove “some-directory” and any files/folders inside of it.

rm -rf some-directory

Note: Worth noting again that using these commands will not send the files to the trash. You will delete them immediately. So make sure you really want to delete the file before you run this command!

I have shown you a good amount of commands so far. Play with those commands and make sure you are comfortable with them.

Once you are ready lets continue our trip through the file system and see what else we can do.

User Types And Their Privileges

In software development, you will run into issues where you cannot run a command because the folder you want to execute a command on doesn’t allow you to do it.

This happens a lot when running build scripts on your machine and things like that.

Here are some tools that will let you make a Matrix move around all those pesky directory and file ownership issues.

The Matrix Bullet Dodge

User Types

When you use a shell, you are typically defaulted to the MacOS logged in user. There are folders that have different owners, and some commands may not be executable if the user you are logged in as doesn’t have permission. This is the reason for the sometimes frustrating situation where you try to modify a file, or run an installation script, but it won’t let you because you don’t have permission.

It means the user type you are logged into in your Mac, does not allow you to perform the operation.

There are three types of users you should be aware of.

The first is the root user, second is an admin user, and the other is a non-admin type of user.

The Root User

The root user refers to the top user who can modify and execute anything in the OS, outside of admin users. You will not ever need to log in as the root user, and in fact it is a security issue to do so.

The root user is disabled by default on MacOS.

Admin User

This is a user that has elevated privileges — more so than regular users, but less privileges than the root user.

It will be common to have an admin user in your Mac to have freedom of making changes to the system and files.

Non-admin User

This is a more restricted user type, which is necessary to disallow unathorized users from modifying your computer in ways they should not be allowed to do so.

Take on Privileges, With the sudo Command

As I said, login as root user is disabled, but it does have some execution privileges you may need. If that’s the case, this is where the sudo command comes into play.

sudo Stands for “substitute user and do”. It executes the provided command as root, which is able to do anything in the computer.

Note: Notice I said it executes AS root, but it does not log you in as root. It is the recommended way to execute root commands, in a secure manner.

Bash Script Example

sudo mv my-file.txt my-renamed-file.txt

When you run the sudo command, you may be prompted for a password. This should be the password you established as your admin user.

With sudo you can also take on the privileges of other users, not just root:

sudo -u someotheruser commandtoexecute

Not everyone can do sudo, only admins. This is setup when creating a user account.

Determine Who You Are Logged in as

If you are unsure of what user you are logged in as. Try these commands below:

whoami = Tells you the user you are logged in as.
groups = The groups that your user belongs to.

File/directory permissions

Unix lets you control permissions on a file pretty easily. Before I show you how to update permissions on a file, let me show you how to determine what permissions are applied to a file before you actually modify a permission.

Determine existing permissions first

Let’s go back to the ls command, using the -l option:

ls -l

This is going to give you a list of files for your current directory. To the left of that list, in the first column, you will see some odd-looking characters next to each item, that look something like this:


These characters are telling you whether the item is a file or directory, and what permissions are applied to that item.

Directories will always start with a ‘d’ as the first character:


Items that are not directories will start with a ‘-‘:


After this initial character, you will have a series of characters, ‘r’, ‘w’, ‘x’, and ‘-‘. These characters define the permissions the item has:

‘r’ = This file/directory is allowed to be read
‘w’ = This file/directory is allowed to be written to
‘x’ = This file/directory is allowed to be executed
‘-‘ = This file/directory does not have this permission. The permission affected depends on where the ‘-‘ is set.

You’ll notice these characters can be repeated many times. This is because each file or directory has 3 “user” categories permissions can be set to.

The categories, from left to right, are “user”, “group”, and “other”.

Unix gives you full control for setting permissions for each category. Since there are 3 permissions you can set, each category will have 3 slots you can activate a permission onto it.

Bash Script Example: User permissions

For example, if a file had read, write, and executing permissions for a user, but not for groups or other, you would see a permission that looks like this:


If the file had only read permissions for a user it would look like this:


Notice how the ‘-‘ character works. For permissions that are denied, a ‘-‘ is used.

Note: Remember the first ‘-‘ in the line of my example just tells you this item is a file. It is not telling you about a denied permission.

Bash Script Example: Group and other permissions

If a file only had group permissions you would see this:


If the permissions were set for the “other” category of users. You would see this:


Bash Script Example: Permissions on all categories

If we allowed all permissions for all 3 categories, you would see this:


Now you should be able to read the permissions like a kung fu masta 🙂

Setting permissions with chmod

Now that you know how to read permissions. Setting them will be just as easy.

The command you will use is chmod.

chmod = Stands for “change mode”

You can write the command in two different ways.

1. The less-common way

You will write chmod, then as options you will target each category I talked about earlier (“user”, “group”, “other”) and set the permissions to it.

Bash Script Example

The below example sets permissions to each category, replacing whatever permissions where previously set:

chmod u=rwx,g=rwx,o=rwx someFile.ext

Bash Script Example: Modify permission

Slightly quicker way to write. This will update user and group (“ug”) to add (+) the write permission. Existing permissions are not affected:

chmod ug+w someFile.ext

You can also remove a permission by changing the + into a -:

chmod ug-w someFile.ext

Bash Script Example: Modify permissions recursively

So far we have only modified permissions for one file or folder.

If you modify a folder, its subfolders are actually not modified with the permission.

To make sure all sub folders and files are modified as well, use the -R option:

chmod -R a+x somedirectory

Octal notation permissions

There is an even quicker way to set permissions. And this one is the most common way to do it. You write numbers that equal to the permissions you want to set.

With octal notation, read = 4, write = 2, execute = 1, when we add up the 3 numbers when setting for each category, it represents the state of the permissions for a file.

Bash Script Example

The highest number (777), adds permissions for users, groups, other, and gives read, write, execute permissions:

chmod 777 filename.ext

This would set read, write, execute. Everyone else just read:

chmod 755 filename.ext

This would give no permissions to anyone:

chmod 000 filename.ext

Changing File/Directory Ownership

In Unix, you can take ownership of a file away from the one who owns it. In my experience as a software developer, I have used this typically to gain read, write, and execute permissions on a file. This is what you will most likely use it for as well.

chown = Stands for change ownership

Bash Script Example

chown kevin:somegroup somefile.txt

chown kevin somfile.txt = Changes owner to the kevin user
chown :somegroup somefile.text = Changes owner to the group provided
chown -R kevin:group somedirectory = Changes owner and everything in it. -R stands for recursive. You will need sudo to make this work.

I know what you’re trying to do…

Congrats Neo, you are well on your way to confronting agent Smith.

You now know a whole lot about shell scripting and can begin to read the Matrix, sorta.

This trip goes deeper. I can only show you the door, you’re the one that has to walk through it.

The journey continues on the next part, coming soon…

Neo Stop Bullets

A render prop is a function you provide to a custom component, for the purpose of controlling how that component renders content.

The react props object provides any kind of data you might want a component to receive from an outer component, or from a state management library such as Redux. A component can be very flexible because it can make use of anything outside of itself to modify itself internally.

You can also pass functions as a prop aside from data. You typically use these functions as callback functions to the parent component, that you can trigger once something in your child component has changed.

The ability to pass functions provided an interesting pattern developers began to use, called render props. Render props are cool because you can affect what is rendered by your child component, from your parent component.

How Render Props Work

  1. In your parent component, pass a function as a prop, as you typically do with a callback function. I will call it “myRenderProp” in my example :
render () {
    return <MyComponent myRenderProp={this._myRenderPropFunction}/>
  1. Call the render prop inside the render function of your custom/child component:
//Inside of "MyComponent"
render () {
    return this.props.myRenderProp();

With this setup, the function _myRenderPropFunction in the parent, will be triggered on each render. This gives you a lot of flexibility, because your child component just renders the output of the function you passed into it, and the parent component now has control over the rendered output.

This is useful when you can’t anticipate what will be rendered by your component and you need it to be as flexible as possible. This especially useful when building a custom component library, where you may want to give the developer the flexibility on deciding what to render within your library component, without modifying your library’s code to fit their needs.

Passing Arguments

We can pass arguments to the render prop, just like we do when we call callbacks in our components. The arguments can be internal state data, that your parent component has no access to otherwise. It could be used to pass ids, or items, or any type of data, that lets you know what is going on inside your component when your render prop is called. The parent component can use this info to help it determine what needs to be rendered at that point.

Child component:

//Inside of "MyComponent"
render () {
    return this.props.myRenderProp(some, internal, params)

Parent component:

_myRenderPropFunction = (some, internal, params) => {
    console.log(some, internal, params);

It is a very simple set up, but the benefits should be easy to see. The children items in your custom component are now “variable”, and can be anything you want to pass into it, at runtime.


Render props are all about flexiblity for your projects and libraries?

This sort of setup helps you solve a lot of complex rendering issues. If you feel like your child component needs to render different elements based on its use, then render props are a great way to go!

React Native UI library choices come in many different flavors and sizes. A lot of thought has been put into these libraries to save developers many hours of tedious setup time. The creators are also very interested in fixing bugs and making their libraries even better so that we all can benefit. They are great tools for development and get you up and running fast.

A Simple Question

When starting out, I felt it was important to learn about the UI library options out there, and I wanted the “correct” one implemented into my projects right away.

I realized that many libraries had a learning curve, and used different approaches to accomplishing the same thing. I also found myself often digging into the default styles, and other “under the hood” type of things, to fit my clients’ designs.

Some components also had bugs in them that left me at the mercy of the developers, unless I spent some time getting into the library’s code and fixing things.

I found the libraries began to work a bit against me, instead of making my workflow easier. I still felt this was the way to go. The libraries have so many re-usable components all set up and ready to use. I felt once I got over the learning curve, and default adjustments, it would be smooth sailing.

Some time later I got a new project which I had the opportunity to co-architect. I spoke to my teammate on the project with my options for UI libraries, suggesting my favorite ones. His response was simply, “Do we really need one?”.

At this point in time I had not really thought about that question. I guess I assumed we did need one because, how could we possibly work fast without one? We had to build from scratch otherwise, and it did not make much sense to me.

I’m glad my colleague asked this really simple question though, because he was right, did we really need one? The answer for our project, I found, was definitely no.

Think More About “why” and Less About “how”

It felt great to just start getting things laid out right away as we began working on our project. I did not have to think about how a particular library requires that I nest items or configure them. Finding and tweaking default styles was out of the picture.

Each component was controlled by a simple style file, and some global colors and fonts — the rest was just a combination of built-in components. View, TextInput, TouchableOpacity, TouchableHighlight, and list components got me very far. I was aware how I was affecting every part of my components because I had full control of the styles I was adding. If something was off I knew exactly where to fix things. I could finely tune whatever I needed.

I was getting work done extremely fast. In fact, it was probably the fastests I’ve ever done layout in React Native before. And I felt less stressed, and happier as I worked.

I learned a good lesson here. I thought I should use a React Native UI library because it seemed like a requirement for React Native developers, but I never asked myself why I needed to use it to begin with. It would have been completely unnecessary in this case. And I feel we would have lost a lot of time.

Don’t get me wrong, these libraries are really great and powerful. They just don’t help you all that much in all projects — especially those with very custom design work.

I have been learning to question current standards and choices more as I continue to get more experience in software development. Instead of just assuming that there is good reason for a specific decision, I have learned to ask why was that decision made — and why it is better over another option. My work has improved because I have now come to understand that it is OK to question what seems to be the standard.


This is a brief overview of what React Native is, at a high level. I wanted to put myself in the shoes of clients who want to be educated about some of the technology out there, without going cross-eyed. And I also wanted to speak for developers who are very new to the field and want to know about this technology without going deep into the rabbit hole yet. I hope to explain why React Native is so popular, and why you should probably use it.

Native Applications

Mobile apps are part of our every day lives, with new ones coming to app stores daily. Apple and Google have given us tools to develop apps and publish them to the app stores. Each platform has different requirements in how to develop for that platform. iOS for example, requires that you program in a programming language called Swift, or Objective C. Android requires that you program in Kotlin or Java. This is what we call “native” programming, and building “native” apps. These apps perform very well, because they compile down to bytecode and are ran by the device processor very efficiently.

Native programming creates a big problem when you want to develop an app that is published to both the app store and the Google Play store. The app programmed in native languages, only works for its respective store and device. We cannot, for example, publish an app we built with iOS tools to the Google Play store. We also cannot install an iOS app into an Android phone, and vice-versa.

This means a developer that would like to target both stores in turn has to build the app twice, once for iOS and once for Android. This is highly inefficient, not to mention costly.

Hybrid Applications

Enter the hybrid applications. This issue with incompatibility made some smart developers to come up with interesting ways to get around this. One such work-around (to put it at its simplest terms) was to create native apps that just display a web view, a sort of simplified web browser component, where the developer could load a web application with the look and feel of an app.

This web app would be bundled with the native application and since the application was really a web app, most of the code could be reused for both iOS and Android platforms. Not only that, but now web developers could use their existing skills to program mobile applications. This was great! The apps had access to native components as needed as well, if there were platform specific features they needed to target.

This worked suprisingly well, and was a great solution for most apps. It is still widely used today. The need for native development was still needed though, because the performance of these “hybrid” apps, was nowhere near that afforded by native apps. The struggle continued.

React Native

Now we come to React Native. The intention with React Native is to bring the best of both web and native worlds together, with improved performance. With React Native, the embedded web view was ditched, and developers had full native access. The user interface would live mainly in a layer separate from the full native layer, where it could “bridge” over to the native layer if it needed to.

This user interface layer is an environment similar to a web browser environment, where a web developer could feel right at home here, programming in Javascript (the web’s programming language) and a markup language similar to HTML called JSX.

This Javascript layer’s code can be shared between iOS and Android, and if developers need to use platform specific features, or if they need that fast native performance, they can easily bridge over to the native layer and make use of anything they need.

This is the power of React Native. The developer chooses what they want to make native, and what can be shared between platforms. You no longer need to hire two developers to program two separate apps. Now you can hire one developer to program most apps and only tap into native code if absolutely necessary.


I hope this has given you some very basic understanding on what React Native is. I hope to write some more articles that will slowly introduce you to more React Native concepts and topics that you might find interesting ?

Working without a structure hinders your wokflow. You know you are working with a bad structure if you have to think too hard to find something. Another sign of a bad structure is if your IDE search is not finding files as effectively as it could. A good React Native project structure set up right from the start can help you massively in your projects.

I’d like to share my structure below, as well as some of the thinking I had behind it.

Trying to Organize With a Purpose

I’ve learned to think better about how I am organizing items. It’s good to think about not only how to organize things, but who it will benefit. Also, I have realized that how I categorize is not necessarily the same way a teammate categorizes. What I name files doesn’t always help me find them in search. I’ve learned that to make my daily coding tasks easier to work with I need to think more sensibly.

It’s OK to flatten out some hierarchies

It was hard for me to stop making files and folders everywhere ?. Here are some of the things I needed to realize for myself:

With these main ideas in mind, I decided to go for a React Native project structure that looks something like the below. I have also added some comments next to most to explain the purpose:

One Note on the components/containers folders

These folders hold my dumb components and those connected to Redux. I have chosen not to add any sub-folders in my React Native project structure, and just let them all live on the first level. This just makes it easier to navigate into through the file system. If I choose good names for the filenames, things should be pretty easy to understand.

I also chose to keep the style files in here, because typically if I open a component I want to open the style file as well. The style and component files will stay together because the style has the same name as the component except with “Style” appended, so this makes things very easy to find. Also, if I search from the IDE, I can easily tell what file is the component and what is the style file.

File naming for better search

Some filenames are easy to find because they are so unique and you just remember them. But tricky ones can be file names that don’t have a pattern you can search for.

An example of this can be a button component called CallToAction.jsx and one called ClickForPopover.jsx. These names will not be helpful at all if you weren’t sure of the button’s name and wanted to get a search result list of all the buttons you have in your project.

I like to use a naming convention that includes the type of component followed by the component’s name. With this in mind, a better name for the two buttons above could be ButtonCallToAction.jsx and ButtonClickForPopover.jsx. If this naming convention for buttons is enforced, you can find a button in list of all the buttons by just searching for “Button”.

We could also benefit other component types: ModalSummerPromo.jsx, ModalAddress.jsx, PopUpError.jsx, PopUpSuccess.jsx — you get the point.

This naming convention is not necessary for all cases, but for some of those components with many variations it works pretty well.

If you want to be extra organized, you can also categorize by the variations you want to distinguish by. For example, buttons that only occurs in the footer could be distinguished from buttons that have a similar function elsewhere:

FooterButtonContact.jsx, FooterButtonSocial.jsx, HeaderButtonContact.jsx, HeaderButtonSocial.jsx

It depends on your needs though, the size of your app, or your app’s purpose too. Some of this naming convention can become overkill. Just stick with the mindset that whatever you set up is supposed to help you and not hinder you.


I hope my React Native project structure helps you out in your projects, or at least gets you thinking about how you can improve your own structure. Nothing is set in stone, and what works for one team may not work for another.

A work breakdown structure is overlooked often…

If everything could go exactly as planned, that would be great

You, 5 hours earlier…

I’ve been given a new feature to add — can’t wait to jump into the code!

Planning you say? Oh, no, it’s fine, I’ve done this a thousand times, and I already have it mapped out in my head. Plus, I did look at the client’s task description a couple days ago after all. It’s so simple. It’s time to get things done and impress my client about how fast I finished. I got this!

Unexpected suprises? No problem — I’ll just deal with them as they come along — I’m a coding ninja after all. I can code with one eye shut, and half my left brain pointed at Youtube 🙂 🙂

You, 5 hours later…

All done, and with unit tests ??

I must be like, in the top 3% of coders. Nobody has my work ethic. I’m just plain awesome, and I smell good ?

My client is going to freak out when he sees how fast I finished!

Wait, before I do, I should just check the task description to make sure all is ready. Oh, wait, I missed a small edge case…

Here we go…

Wait, I totally missed this one sentence at the end. This task has 3 separate use cases, and I only programmed for one. And actually, some of what I wrote won’t work for the other cases.

Wait, did I just do 3 hours of work for no reason? These 2 other use cases are really complex, what happens when the user does this? Wait, this is going to take 3 times longer than I thought. Actually, I’m not even sure how long, I don’t have enough information to really know what I’m getting into. I need to ask someone about this, and this. How do I even begin to work through this? There’s a lot of API calls going on here. I’m feeling…overwhelmed…


Cry me a river

Welp, you tried, and you failed miserably. Now you are left with a pathetic feeling of regret and disgust in yourself. Yes, cry, because you should have known better than to forget your training and rush off into the dark expanse of programming without a conquer strategy, grass-hoppa.

One Does Not Simply Program

Patience is worth its weight in gold

Let me start by saying I have lost count of the amount of times I’ve been in your situation. I read the task, and jump into the code all eagerly, foaming at the mouth, that is until my fantasy is suddenly interrupted by the inevitable effects of impatience. Impatience is costly. It will quickly eat away at your time as you undo and redo work, rethink and replan.

A little thought into exactly what you need to do and how, upfront, will go a very long way. With patience and planning, you will not only better understand what you need to do, but how the feature works as a whole, as well as how your work needs to be architected. Most importantly, you will complete nearly as fast, but with a much much higher quality of work right off the bat, and with less bugs and back-and-forth with the client.

Work Breakdown Structure FTW

I want to write about how to make use of a structure for breaking down your tasks, which will help you better understand them, organize your tasks in a logical order, bring up questions about the work, and keep yourself from becoming overwhelmed with way too much complexity.

So, is this way of planning a “thing”?

Yeah, it is. Out there, in the world outside, they call it a work breakdown structure. There’s software out for this, but for the context I’m writing about (day to day software development tasks) it’s probably overkill. I will be sharing how I do it, with a simple hierarchical list which you can write on paper or on your favorite note taking app.

Let’s work with an example

Before I explain how I plan, let’s first introduce a real-world example for a project I had. Let’s take a look at what this example task requires from a product perspective, and how we can begin to understand and break this task down into easy chunks to work with. After that, we can think about how to plan for it.

The task

Program search filtering controls based on provided UI components, and have controls modify the search results on the page. Only items matching the filter controls should display to the end-user.

Controls include:
– Filter by date range
– Filter by document age
– Filter by industry
– Filter by author

Yeah I know, planning stinks

I know how you feel, planning is a chore. It feels like you are wasting time over-planning instead of actually getting any work done. The problem is, you think you know the task and your mind map tells you everything you need to know. But when you force yourself to look at each step closely and think about exactly how you should accomplish a task, you will begin to unravel problems in ways you had not yet thought about. These are little suprises that don’t come till later and are waiting to make your day horrible.

The product description usually touches on how it should work as how a user interacts with it, and doesn’t touch on all the moving parts behind the scenes. So now that you see this planning can be useful, the first thing you must do is stop, take a deep breath and clear your mind. You are going to dial back on your need to code up a storm, and take it slow.

Now, get up — yes you. Go to the kitchen and make yourself a nice cup of tea or coffee. If you have one already, then good you can stop reading right now and move ahead on this post, you highly caffeinated dev you.

Notes and to-dos

So, let’s talk about writing notes!

Channel your younger college self

Remember in college when we all cared a lot and took notes? Yeah, let’s bring that back. This is the first component for tackling a task. Before we can fix or build we need to know how it works and why it works that way.

Now, it’s important for me (for my own sanity) to make notes that are clear and concise. I also am aware that any notes I take are personal — meaning, nobody else needs to understand them but me. It is my own personal plan for tackling a task.

I also know, that I can’t trust myself in remembering what I wrote an hour ago let alone 3 days ago, so I can’t assume I will remember what I was talking about in my notes. I have to write descriptively not only explaining the what, but also the where, how, and why. Clear and concise does not == short and vague. If short explanations don’t always work, write long and make sure you have written in a way that reminds you of the context, and describes things in detail so you will remember what you wrote at a later time. This is key, and without it your notes could be too vague to do their purpose.

Get your to-do lists on

Once I dump my thoughts on paper or whatever note app I’m using, what I do is make a butt-ugly bullet point list, for to-do items I need to list out. You got a fancy to-do list you like to use? That’s wonderful. I just want to write things down and not get bogged down by to-do list features and other nonesense.

I use bullet points to help in readability (I can read things easier like this), and if I want to do certain steps in order I use numbered lists to keep organized. As I complete an item I put an X at the beginning of the line. I told you, it’s ugly. It’s just fine for me. Use what you want to use 🙂

Step 1: Take notes of how things work now, before you make the changes

OK, let’s go back to our example. Our little search filter task seems simple enough, but how does it all work right now? The very first step looks obvious, take the app for a test run.

From running our fictitious app, we can see that right now we have search results and there is no filtering functionality at all.

OK, now we know how it works — wait, no we don’t. We still have no clue how this works under the hood. How is the code architected to control filtering and display these search results?

These are notes that can be very useful, as many features out in the wild can be very complex. Sometimes you just understand them for like, an hour, and then you need to remind yourself again. Therefore, without any notes you will need to run the app again to get a handle of how it comes together. If you haven’t experienced this in your work, trust me, you will eventually — because some work is THAT complicated.

After digging into the code, and running through it, we have found some things. Here are the notes:

How it works now

{"results": [{"name": "Latest Fashions", "body": "article body goes here", "date": 1532001248, "age": 2016, "industry": "fashion", "author": "Luke Duncan"}]}

This is great. We learned a lot about the app by taking some time to see the flow of things. We learned how the app is architected to get and process the info, and we learned the data is persisted. That’s an important point to know about the app because that tells us we may need to persist the filters selection. This exercise also allowed us to make a quick note on how the search results data looks like. This could be a good reference point in case we need to check against it while coding. We are starting to get a better picture of how things work, and we can now possibly form better questions to our client/team that we would have otherwise done before.

Step 2: Write down questions that need to be answered before proceeding

From the bit of code review we did, some questions come to mind. Here are my notes:

What to ask

After talking to the back-end guys and project lead, I got some answers. Let’s write the answers right under each question:

What to ask

    date : [array, of, timestamps]
    document: [array, of, titles]
    industry: [array, of industries]
    author: [array, of, names]

Sweet, the answers helped and now I can look at the designs. I see that each filter control is different, and each is populated differently. I’ll just make a note of that to document to myself, under my styling question, since that sorta make sense to me:

This is perfect, I’m starting to form a plan in my mind about how to go about doing some of the work, but we have a lot of moving parts right now — I need to organize my plan.

Step 3: Break large problems down into steps

So, there’s a few things going on in our task. Let’s continue creating this mental map on paper, err on screen in our case. I think we KNOW enough about what is going on, and what we need to do at a high level.

Let’s get this high-level plan written down so we see where we stand by creating our actual work breakdown list, writing down what we know we must do so far. Here’s the initial list:


Not bad for an overview of what needs to be done, overall tasks are separated which is nice. We can still dig deeper though. I want a more detailed plan.

Step 4: Break high-level tasks down further, into sub-tasks

We should think deeper, and break down each task by sub-tasks. Let’s start from the 1st and 2nd task, since they are related, and work our way down.


This is very detailed. It seems so unnecessary

Well, it is detailed, but you are essentially writing down what you already are keeping track of in your mind anyway. This just gives you a more tangible map that you can refer to, add to, revisit later, and cross out tasks as you move forward. Because of this, it becomes really hard to forget your plan, your concerns about your plan, or to get confused as to what you should do next, because it is written in order from what you should do first to what you should do last. You are doing all that planning up-front, and don’t need to think about it with as much effort again. It puts your thoughts on auto-pilot, kinda.

The goal is to note tasks at one or two levels deeper than the top-level tasks. The goal here is not to write every single tiny step you must do — just what makes sense to you to write down, that is convenient to note, and that is something you might forget that you want to track.

Let’s work with the rest of the tasks. We will use the info from our answered questions to get some of these broken down, and we’ll write other important details too:

We have a decent list of tasks laid out.

Before moving forward, take a minute to compare the list we have created, and what we had to go by in the original task description. It’s a huge difference!

We can now finally start working?

Mark step as complete and move forward

As we start to complete items. Simple add an X at the beginning like I do, or just cross them out:

If new bugs are found after you have completed something, simply make not of it as an extra step:

If questions pop up at this stage, I like to make a note of the question, as a sub item of the task:

Once your question is answered, you can convert it to a sub-task, or write the answer under it. I do both of these, depending on what makes most sense:

Once the bug is squashed, just X it or strike it through:


That about does it for this post. I hope it is useful to you in your daily work as it is to me. I would not work any other way now ?