To Top

Our Blog

Guru Technologies

Custom Social Media App

Recently, we finished developing a social media custom software project for a Utah-based couple called Dela. It was a delight to work with them and build their dream application for iOS and Android.

We got to build this app in one of our favorite mobile frameworks, Flutter. As a company, we’ve become very proficient with this technology.

KSL recently showcased their app in an article that talks about why they built it, they wanted to stay in touch with family without having to use traditional social media apps, which not everyone in their family is a part of.

Read the original article at here:

Here’s another app screenshot:

Good UX is All About Confidence

Fast food self-ordering kiosks are here to stay. Who knew there could be so many ways to get a McDouble?

Those kiosks have been tried before, you know. Decades ago, one fast food spot in my town built cabinets to house old boxy touch-screen computer monitors for the customer’s use. Yeah, it didn’t really catch on. But just like virtual reality, it kept coming back, making an appearance now and then to see whether the world was ready. Efficiency demands it. Getting more people to use the kiosk means cheaper food for us, and a bigger market share for the company. And the batch that McDonald’s rolled out in 2015 seems to have stuck for good.

But even now, not everybody will use it. As we come through the door, our first choice is whether to interface with a computer or the teen behind the counter. A whole lot of us still choose to line up to meet the human, even if it means waiting a little longer to eat. 

So why is it so hard to get a tech-savvy populace to use a simple touch-screen to order lunch?

It’s a matter of confidence.

It’s not that we don’t trust that the kiosk software works properly (though that may be part of it.) It’s that we lack confidence in ourselves—we don’t trust that we will know how to use the software well enough to get our own order right.

Crisis of Confidence

Whether dining or shopping, we like getting help from a human. They are the experts at their store. They know their inventory and are experienced in answering the kinds of questions that you might ask. They might have helpful suggestions you hadn’t thought of. There are verbal cues, facial expressions, and body language that help you know when you’re on the same page, and validation that your order makes sense.

These are things that software can’t easily provide (yet). Even the best clean and modern user interfaces can still be confusing. A vaguely-worded button makes a user hesitate. An unexpected choice of colors from their phone screen makes them wonder whether they had done the right thing. Without the utmost care to UX detail, your users’ confidence level can quickly drop. And it doesn’t have to drop far to turn into a frustrating experience.

It’s not enough anymore to make it reasonably clear what the software is doing. Plan on your users second-guessing themselves, your software, and you—because they will. “I’m pretty sure I’ve entered this the way that I’m supposed to, but you could also read it this other way. Maybe that’s what the software wants me to do.”

It must be so incredibly obvious what the software is doing, that it’s also clear that it is not doing everything else.

The trend these days is to aim to create software that “delights”. I like to think of it another way. Picture your users as opening your software only because they have to in order to get something done. They want to get that thing done quickly and with minimal frustration, and then move on to the next thing on their to-do list.

Pretty isn’t as important as solid. And no matter how stable and bug-free your software actually is, it won’t feel solid to them without a confidence-building UX.

Your Confidence-building Toolbox

If this crisis of confidence is ringing true for your app, don’t let this get you down. Most software needs improvement in this area. And even if you don’t have easy access to a professional designer, there is a lot you can do.

Let’s examine your UX toolbox, filled with double-edged swords that you have already been using, for good or ill. Used properly, each of these tools can assure your users that they are using your software properly, even upon first use! They can also be used for ill, unintentionally plaguing your users (and customer support representatives) with anxiety and frustration.


Color can be a powerful way to communicate status, importance, and validation. By default, consider giving your app only one or two colors outside of the greyscale spectrum. Then, when you smartly use color to communicate status, importance, or validation, it will stand out and be meaningful to the user. For example, if you’re going to make a button stand out with color, make sure it’s the main, primary action on that screen.

Be sure to follow your intuition and conventions here. For instance, red messages usually mean that there is an abnormal problem (e.g. the server is down) or is used to scold the user for trying something invalid. (By the way, try to craft your software so that it’s difficult to get into a situation where a user would need to be scolded.)


Take time with your verbiage. Whittle it down to something very clear and brief. Your users don’t want to read long messages explaining software functionality.

Think of different ways that something can be read. Oftentimes, something that is obvious to you might confuse a colleague. Run it by them and ask what they think. Discover how to craft it in a way that it can’t be interpreted any differently than you mean it.


Sometimes thought of as unnecessary fluff, subtle animation can add vital clarity to what is going on. For instance, when the user takes an action to filter a list and a few items disappear, it can be visually disorienting for the screen to change in an instant, as the user needs to get her bearings again. Instead, consider having an animation have them fade or slide out from view.

Another fine example is when you navigate from one week to the next in Google Calendar. A subtle motion of the calendar content tells your brain which direction you’re moving.

After the Fact

It’s important to give users confidence that the button they are about to click will do the thing they want to do. Additionally, after the action has been taken they will look for similar reassurance. “No news is good news” does not apply here.

It can be quite helpful to display a message showing a few words confirming what happened, and that it was successful. Be sure to remove all doubt that they may have done the wrong thing.

For instance, if a user just submitted a popup form (i.e. modal) providing feedback, it is nice to indicate that it was successfully received. This is sometimes done with another modal where the user needs to click OK.

However, a small, out-of-the-way message is usually even better, commonly called a “toast”. (Think of a toaster at the bottom of your screen, popping up little informational messages that don’t need to be acknowledged and that don’t get in the way of the user.) Have it say “Feedback received” with a little ‘x’ to allow the user to close it, but have it also disappear on its own after a few seconds. The user smiles at the encouragement that all went as expected, but isn’t interrupted. Gmail is great at this, by the way.


Once your user sees that actions can be undone, she will take actions quicker and be more at ease knowing that it will be harder for her to permanently mess things up. Consider having this “undo” action be a part of your non intrusive toast that appears after an action has been taken. Again, Gmail does this flawlessly.

Follow Conventions

Sometimes we like to buck the trend and be a little different. I admire your creativity, but with UX conventions, this is often the wrong move. Users grow accustomed to things that they find common among other apps and have already done the work to learn their meaning. Following conventions is a way that you can tap into what they already know. Don’t be afraid to ride the river of convention as far as you can, and have them walk on shore only as far as they need to in order to learn the truly unique parts of your app.

For instance, you may want to be cute and use “Forget about it” instead of the boring “Cancel”. Even if the meaning seems obvious to you, your user will pause and think, “Wait a minute. If this button was going to cancel, then they would have just said ‘cancel’. This must do something slightly different. Instead of canceling my changes, is it going to delete the order from the system?” Little things like this unnecessarily detract from their confidence in your app.

Study the big, well-established apps. Don’t plagiarize, but make sure you’re not far out of line with them.

Cater to the Brand New User

The software manuals are in the landfills where they belong, and your software experience has to be incredibly intuitive. Forget what you know and look at your app with fresh eyes. Test your UX with coworkers and family and watch their reactions.

You’ve got great software that works. Now, just put some extra time into your UX and raise the average user confidence level from 85% to 95%. Believe me, it will pay off.

P.S. If you need any help with your app—whether it’s just advice, help with coding, or building the whole thing from scratch—Guru Technologies is always ready, and at a reasonable hourly rate.

Cross Platform iOS/Android Development

When developing a mobile app, it’s pretty much a given that you will eventually need to support the two major platforms: iOS and Android. Developing for both platforms can be a challenge because:

  • Development costs are almost double due to having to develop with two completely different frameworks and codebases
  • Testing and QA – You need to test every feature in both platforms
  • Different UI is required since iOS and Android have different design philosophies
  • Problems keeping things in sync – When you add features to one, sometimes it takes time to add the same features to the other so unless you can finish both at the same time you are waiting on the other platform to release, or you have to live with the two not having feature parity
  • The required development skills for each platform are different – Android is written in either Kotlin (our favorite), or Java while iOS is written in either Swift (our favorite) or Objective C. This means you need to engage developers with different backgrounds to code both platforms, or one with experience in both

What can be done about this?

Enter Flutter

In the past, we’ve used cross-platform tools like Adobe PhoneGap / Cordova, Xamarin, etc. While these are useful, we’ve recently started using Google’s new Flutter framework that uses the Dart programming language.

This is a great article that explains why Flutter is such a great framework for cross-platform development even though it doesn’t use native platform widgets: .

Basically, it compiles to low level code, and it doesn’t use a webview or native UI elements like others; instead it uses Skia which means it’s using OpenGL.

Why do we like Flutter?

  1. Code once run anywhere
  2. Familiar Language and Layout
  3. Rapid Development
  4. Stateful Hot Reloading
  5. UI Flexibility
  6. Native Like Performance
  7. Small Deploy Size
  8. Eventual Support for Desktop and Web

Flutter had it’s 1.0 release in December 2018, and as of today, we’ve already successfully used it in 4 apps for our clients, including projects that required a lot of underlying hardware control such as Bluetooth interfacing with hardware devices.

Not Always the Right Choice

Having said that, Flutter may not always be the right choice depending on the app project. We carefully consult with each client to determine their requirements, and what kind of user experience they want with a project and we make sure we always use the right tool for the job.

We think Flutter is a great addition to the space but it may not always be the best choice, and we still do a lot of native iOS and native Android development and have a lot of expertise with those platforms. The great part about Flutter is you can still use all the native API’s or write native code in combination with Flutter for a unified user experience and faster development.

Technologies We Are Using Right Now

Today we did a quick check on the technologies we are actively using right now across all the projects we are actively developing and made this poster with a bunch of them. This isn’t fully comprehensive but it’s a good sample of the technologies we use and rely on every day as we code

Here is a brief list of some of the tech we are using right now:

  • Docker
  • NPM
  • Cordova
  • Android
  • iOS
  • AWS
  • Apache
  • Gitlab
  • MySQL
  • Flutter
  • Firebase
  • NGiNX
  • Java
  • WPF
  • Realm
  • .NET Core
  • Grape
  • Angular
  • MongoDB
  • PostgresQL
  • Node.JS
  • Rails
  • SQL Server
  • django
  • CakePHP
  • C# .NET
  • Laravel

Vimeo Video Script

The Vimeo Video Script (AKA Maggie Script) is a basic Web Scrapper that retrieves video information from a Vimeo endpoint. This data includes fields such as quality, type, width/height, link, fps, etc. The script will then take the retrieved data and convert it into a CSV file.

While building the application I found that, due to the size of data Vimeo was returning, their Api would occasionally throw a 504 gateway timeout. This error is reasonable as the script was making a request for an array of 100 video objects that contained quite a bit of data. The request would take about 5-10 seconds, and depending on how many videos you want, could be up to 100 requests (The theoretical max). To work around this, I added a 2 second cool down between each request.


  • Multi-threading
  • Settings page (Adjust access token & video count)
  • Progress messages
  • CSV Converter
  • Light Weight (< 1MB)


You can download the executable below

Vimeo Video Download

New Student Classroom Management App – Kodiak Picker

We recently were contacted by a school in Kodiak Alaska to help them do a classroom management app. They had tried unsuccessfully several times to get someone to make this app for them, so we thought we’d take a crack at it. Overall it’s a pretty simple app, but we’re proud of it because we put it together very quickly for them, and they are enthralled with the results. It demonstrates the use of AngularJS and Google’s Material Design that was made originally for the latest Android OS. We made use of the Angular Material plugin on this project.

We released the source code for this project, Kodiak-Picker, under the open source GPL License and the code is freely available on Github: kodiak-picker – Github

The Kodiak Picker app itself is an application written to help track and manages students, quarters/semesters (referred to as “cycles”), and classes (referred to as “tutorials”). The application allows students to choose classes to sign up for out of those available. This can be overriden by teachers or administrators who may know better the needs of specific students. The software can also generate reports about which students are in any class, or search by student to find out what class they are in at any given time. Rooms and instructors are also included for each class. Registration for new cycles can occur while an existing cycle is ongoing.

Kodiak Picker Screenshot

Newest App to Hit the Store…

We just finished our latest iOS app for a longtime client, Inwest Title.

The app is designed to enhance their current product offerings and give them a competitive advantage in the market. Inwest Title is Utah’s largest independent title company, with 13 office locations. They will now be able to offer features directly on clients phones or tablets such as tracking files, placing orders (even via a picture), quote fees and more.


Startup Weekend Ogden

We decided to take our team to Startup Weekend Ogden in November. According to, the event is described as follows:

“All Startup Weekend events follow the same basic model: anyone is welcome to pitch their startup idea and receive feedback from their peers. Teams organically form around the top ideas (as determined by popular vote) and then it’s a 54 hour frenzy of business model creation, coding, designing, and market validation. The weekends culminate with presentations in front of local entrepreneurial leaders with another opportunity for critical feedback.”

After giving a winning pitch, Mike led our team (which included some other awesome entrepreneurs) on a project/application that would be able to facilitate Bitcoin transfers for the banking industry.

Below is a pic of a brainstorming session with our group.IMG_0146

Pictured here are the Guru guys hard at work coding. These guys are incredible;  they did hardcore coding from morning to night the whole weekend! Good thing there was a constant flow of food and drinks provided by the event… IMG_0145-1

At the end of the weekend, we presented our working application! Its amazing what our team accomplished in just 54 hours. We took a concept, designed and built a system, received market validation and have a prototype to show. Go Team!IMG_0151

New Product Release

We have been working with School Improvement Network on enhancing their line of educational products for the last few months. They offer a wide range of tools for professional development and teacher training throughout the United States, Canada, and overseas.

School Improvement Network has just released an app we helped create for them which streamlines the process administrators go through to conduct teacher assessments in the classroom. Check it out here:

Evidence 360

Coming soon from this partnership: a dynamic e-reader teachers can use to continue their professional development.

We created this app using Objective-C.

Troubleshooting Disk Failures on a Linux Software RAID with LVM

The following describes a failure of a drive I had on Ubuntu Linux with a Linux software RAID 5 volume with LVM, how I diagnosed it, and how I went about fixing it. The server had 4 2TB drives in software RAID 5.

When checking kernel messages, here is an example of the bad sectors:

# dmesg -T
[Sun Jul 21 13:36:30 2013] ata4.00: status: { DRDY ERR }
[Sun Jul 21 13:36:30 2013] ata4.00: error: { UNC }
[Sun Jul 21 13:36:30 2013] ata4.00: configured for UDMA/133
[Sun Jul 21 13:36:30 2013] ata4: EH complete
[Sun Jul 21 13:36:32 2013] ata4.00: exception Emask 0x0 SAct 0x1 SErr 0x0 action 0x0
[Sun Jul 21 13:36:32 2013] ata4.00: irq_stat 0x40000008
[Sun Jul 21 13:36:32 2013] ata4.00: failed command: READ FPDMA QUEUED
[Sun Jul 21 13:36:32 2013] ata4.00: cmd 60/20:00:2c:eb:7e/00:00:08:00:00/40 tag 0 ncq 16384 in
[Sun Jul 21 13:36:32 2013] res 41/40:00:2f:eb:7e/00:00:08:00:00/40 Emask 0x409 (media error) <F>
[Sun Jul 21 13:36:32 2013] ata4.00: status: { DRDY ERR }
[Sun Jul 21 13:36:32 2013] ata4.00: error: { UNC }
[Sun Jul 21 13:36:32 2013] ata4.00: configured for UDMA/133
[Sun Jul 21 13:36:32 2013] sd 3:0:0:0: [sdd] Unhandled sense code
[Sun Jul 21 13:36:32 2013] sd 3:0:0:0: [sdd] Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE
[Sun Jul 21 13:36:32 2013] sd 3:0:0:0: [sdd] Sense Key : Medium Error [current] [descriptor]
[Sun Jul 21 13:36:32 2013] Descriptor sense data with sense descriptors (in hex):
[Sun Jul 21 13:36:32 2013] 72 03 11 04 00 00 00 0c 00 0a 80 00 00 00 00 00
[Sun Jul 21 13:36:32 2013] 08 7e eb 2f
[Sun Jul 21 13:36:32 2013] sd 3:0:0:0: [sdd] Add. Sense: Unrecovered read error - auto reallocate failed
[Sun Jul 21 13:36:32 2013] sd 3:0:0:0: [sdd] CDB: Read(10): 28 00 08 7e eb 2c 00 00 20 00
[Sun Jul 21 13:36:32 2013] end_request: I/O error, dev sdd, sector 142535471
[Sun Jul 21 13:36:32 2013] ata4: EH complete

It’s clear in this case with those messages that the problem was with sdd, but in some cases, it’s not always clear which ata# in dmesg matches up with which drive, so for that I followed this askubuntu guide to see if ata4.00 was the same as /dev/sdd:

In my case, it’s clear that the problem is indeed with /dev/sdd or (ata4)

I have my RAID configured to email me if there’s a problem with the RAID, but it wasn’t doing it, even though I confirmed it was configured to do so.

I checked to make sure the RAID looked normal:

cat /proc/mdstat

looked normal (all U’s on the drives)

The output of mdadm looked fine as well

# mdadm --detail /dev/sdd

The problem from dmesg seems to be that it was having trouble reading specific sectors on drive [sdd]. So I knew I needed to start checking that drive specifically.

There are some good guides available about dealing with badblocks, such as the “bad block HOWTO”

Also, the FAQ for smartmontools (which contains the smartctl program):

The problem with the bad block HOWTO was that didn’t cover my case which is RAID/LVM. You definitely don’t want to get the dd command wrong, and I was nervous about trying to get it right on my system. A better approach my be to use hdparm as described here (forcing a hard disk to reallocate bad sectors). However, I didn’t do this for reasons explained below

The crux of that last page is looking for the bad sector in dmesg, and then confirming is with this command (entering your sector):

# hdparm –read-sector 1261069669234239432572396425

You should get:

/dev/sdb: Input/Output error

Then, the drive can’t be part of the array when you do this, doing a:

# hdparm –write-sector 1261069669234239432572396425 /dev/sdb

Followed by an force assemble to get the drive back in.

However, I didn’t want to do all that for two reasons, I didn’t know the extent of the bad sectors (if the bad sectors were isolated, or the whole drive was going bad), and because the command writes 0’s into the sector which means you will loose data if not done carefully (taking precautions to ensure that since our array is still functioning otherwise, I don’t write 0’s into the good drives), so I decided to try something else instead.

I started with smartctl reported that the individual drive was healthy. It turns out that a drive can actually be on the verge of failure or not healthy, and smart still reports it as being healthy. Smart health is more like an indicator that things can go bad not a definitive way to tell:

# smartctl -Hc /dev/sdd
SMART overall-health self-assessment test result: PASSED

Then I checked for vendor-specific SMART attributes using -a. The thing that stands out here is the “197 Current_Pending_Sector” being higher than 0 (in my case 40), meaning that there are sectors pending re-allocation. This means there is a high likelihood there are bad sectors.

# smartctl -a

SMART Attributes Data Structure revision number: 16
Vendor Specific SMART Attributes with Thresholds:
1 Raw_Read_Error_Rate 0x002f 200 200 051 Pre-fail Always - 0
3 Spin_Up_Time 0x0027 253 253 021 Pre-fail Always - 6200
4 Start_Stop_Count 0x0032 100 100 000 Old_age Always - 23
5 Reallocated_Sector_Ct 0x0033 188 188 140 Pre-fail Always - 89
7 Seek_Error_Rate 0x002e 200 200 000 Old_age Always - 0
9 Power_On_Hours 0x0032 093 093 000 Old_age Always - 5693
10 Spin_Retry_Count 0x0032 100 253 000 Old_age Always - 0
11 Calibration_Retry_Count 0x0032 100 253 000 Old_age Always - 0
12 Power_Cycle_Count 0x0032 100 100 000 Old_age Always - 21
192 Power-Off_Retract_Count 0x0032 200 200 000 Old_age Always - 18
193 Load_Cycle_Count 0x0032 200 200 000 Old_age Always - 4
194 Temperature_Celsius 0x0022 080 074 000 Old_age Always - 72
196 Reallocated_Event_Count 0x0032 113 113 000 Old_age Always - 87
197 Current_Pending_Sector 0x0032 200 200 000 Old_age Always - 40
198 Offline_Uncorrectable 0x0030 200 200 000 Old_age Offline - 0
199 UDMA_CRC_Error_Count 0x0032 200 200 000 Old_age Always - 0
200 Multi_Zone_Error_Rate 0x0008 200 200 000 Old_age Offline - 0

I decided to run a short test:

# smartctl -t short /dev/sdd

And then 60 seconds later I checked the status:

# smartctl -l selftest /dev/sdd

SMART Self-test log structure revision number 1
Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error
# 2 Short offline Completed: read failure 90% 5691 71314612

That confirmed there was a bad sector. At this point, I decided I needed to make a judgment on whether the drive was going bad, or there were just some bad sectors I needed to mark as such and move on. You can mark sectors as bad by writing 0’s to the bad area, and the disk firmware should automatically mark them as bad. The reason for this is explained in the earlier mentioned smartmontools FAQ:

If the disk can read the sector of data a single time, and the damage is permanent, not transient, then the disk firmware will mark the sector as ‘bad’ and allocate a spare sector to replace it. But if the disk can’t read the sector even once, then it won’t reallocate the sector, in hopes of being able, at some time in the future, to read the data from it. A write to an unreadable (corrupted) sector will fix the problem. If the damage is transient, then new consistent data will be written to the sector. If the damange is permanent, then the write will force sector reallocation. Please see Bad block HOWTO for instructions about how to force this sector to reallocate (Linux only).

The disk still has passing health status because the firmware has not found other signs of trouble, such as a failing servo.

Such disks can often be repaired by using the disk manufacturer’s ‘disk evaluation and repair’ utility. Beware: this may force reallocation of the lost sector and thus corrupt or destroy any file system on the disk. See Bad block HOWTO for generic Linux instructions.

The problem I had is the “bad block HOWTO” guide I mentioned earlier doesn’t cover my scenario, RAID/LVM. I’m sure you could dig in and find exactly the sector and mark it, but I didn’t want to risk it. So I was about to track down a western digital disk evaluation and repair utility, when I ran across a post that suggested I can just do a RAID sync (was a “repair” on older kernels”). To initiate, you run:

# echo 'check' > /sys/block/md0/md/sync_action

Then check the RAID check status with:

# cat /proc/mdstat

In my case, it was going really slow, so I first did what I could to shut down unecessary activity on the drive, and then ran through suggestions from here

The main thing that sped things up was setting the stripe cache size to a higher level than the default 256.

# echo 32768 > /sys/block/md3/md/stripe_cache_size

As it was doing the check, lots of errors were being thrown about the drive in dmesg, so I knew it wasn’t an isolated incident I was going to be able to fix by using a drive utility to mark bad sectors, the whole drive would need to be replaced.

As I was monitoring the RAID status, it got through about 5% and then the RAID removed the drive from the array and stopped it’s work. Here’s what dmesg said:

[Sun Jul 21 17:14:29 2013] md/raid:md0: Disk failure on sdd2, disabling device.
[Sun Jul 21 17:14:29 2013] md/raid:md0: Operation continuing on 3 devices.
[Sun Jul 21 17:14:29 2013] md: md0: data-check done.

so now I have a degraded array, and need to get a new drive ASAP to replace it and rebuild the array.

To do this, I had to ensure that the serial numbers matched properly.  Also, since the drive was no longer showing up in my system, I had to issue one of the following commands:

mdadm /dev/md0 -r detached


mdadm /dev/md0 -r failed

The man page says:

“The first causes all failed device to be removed. The second causes any device which is no longer connected to the system (i.e an ‘open’ returns ENXIO) to be removed. This will only succeed for devices that are spares or have already been marked as failed.”