Using Selenium and ECS to Create Reliable Rendering on Signage Systems

The Problem

My company, TINT, produces dynamic social displays for digital signage (among many social media related products). If you’re walking through a mall and you see Instagram photos show up on a kiosk screen, it could be us, especially if it’s a Westfield mall. Our product is built using web technologies (HTML/CSS/JS) and is rendered through a web browser.

Traditionally, we have relied on the browsers supplied by the signage company vendors, such as Broadsign, Brightsign, and FourWindsInteractive to render our content. However, this often results in performance issues because the hardware isn’t powerful enough to render smooth animations in a browser, or the browser is outdated and difficult to support.

The Solution

My approach in tackling this was to remove the unpredictability of the signage system’s browser, and use a browser running on a server to render a video that can be delivered to the signage system. After all, what kind of signage system doesn’t support video? After doing some research, I found that most signage systems can download a video file from a URL and cache it locally, syncing it occasionally to keep it up-to-date. This is usually done through Media RSS, or MRSS.

Using video instead of HTML has a number of advantages, including:

  1. Reliable playback during network instability
  2. Increased compatibility with older hardware/software
  3. Consistent animation performance
  4. Easier troubleshooting

The tradeoffs are that:

  1. The dimensions of the screen must be known beforehand
  2. There is greater delay from when content is posted on social media to when it is shown on the screen

For most customers, the advantages outweigh the disadvantages, so I decided to move forward with the video approach.

The only thing I had to do was figure out how to create automatically updating videos from webpages in a simple, but scalable way. Unfortunately, there aren’t any off-the-shelf services that provide this kind of thing (startup idea?). However, after some digging, I came up with a creative way to do it myself:

First, I found Headless, a Ruby gem that creates a virtual X screen and records videos of Selenium test runs. I used that to create a simple script to create videos of websites. Through trial and error, I figured out which flags Chrome requires to create a fullscreen video:

Now I had to find a way to take this basic script and scale it up to be production-ready. I decided to use AWS ECS and Docker since it is a simple way to wrap environments around tasks, and have them run on a schedule or in parallel. I thought about Lambda, but AWS Lambda doesn’t support ruby, and I wasn’t sure that Lambda was meant to handle a task as resource intensive as rendering a video from a chrome session. To store metadata about the videos, I used MySQL, and Sinatra to provide an endpoint for signage systems to request videos from.

A flow chart of the system:

TINT Screencast Microservice - Flow Chart

Here’s how it works:

  1. The signage customer provides 4 inputs to an internal tool: URL of the social display, height/width of the screen, and the duration of the video
  2. The tool returns 2 URLs which represent the link to the video file and a link to the corresponding MRSS feed
  3. The customer uses either the video file or MRSS feed link in their signage system (depending on what their system accepts)
  4. When the signage system first requests a video, it receives a response that says “video is being generated”, while the service starts a ECS task which generates the video
  5. Once the ECS task finishes, the video is saved and the video becomes available to download
  6. The signage system periodically requests the video to download, so the second time it makes a request, the video is downloaded, then played on the screen
  7. In the background, an ECS scheduled task iterates through all the videos that have been created to determine whether any videos need to be expired (I expire any videos that have not been requested in a day) or refreshed (I refresh videos every 30 minutes)
  8. Voila:

The system still has some imperfections which I haven’t gotten around to addressing, which include:

  • Autoscaling - I eventually want to use AWS Fargate to handle autoscaling of containers. Right now all of our microservices share resources on our ECS cluster, and I have to manually throttle my video microservice to balance resources. Unfortunately, as I write this Fargate does not support the shm_size parameter, which Chrome crashes without.
  • Unnecessary Proxy - Currently the Sinatra server proxies the video from S3 to keep track of when videos were last accessed. However, I could be parsing S3 logs to do the same thing, which would reduce latency and infrastructure costs in delivering the video.

Overall, I’m happy with how this project came out. It solves a problem for our signage customers and gave me a chance to creatively re-use Selenium in a way that I imagine its original creators didn’t envision, to render visualizations for in-store screens:

TINT display in Westfield SF Centre

Additional Reading

My Experiences with Professional Coaching

It’s after work, before the holidays in 2016 and inside the Lever office in downtown San Francisco, I’m hanging out with my friend Jen, catching up and venting about work. I’m telling her about some hard decision that I didn’t have enough validation on when she suggests, “You know, one thing that’s worked really well with our team is professional coaching.” She explains how she helped her team find the best coaches, the benefits of coaching, and referred me to Christina and Blue Door Partners.

So a week later, I’m dialing their number, not knowing what to expect but open to being challenged.

“Hiiiiiiiii”, says Christina. “Hey, this is Ryo. So, what happens now?”

Fast forward a year, and I’ve been able to work on a bunch of longstanding challenges like,

  • Saying yes too much
  • Taking work too personally
  • Not giving people enough space for their own feelings
  • Not being assertive, authoritative, charismatic, inspiring, vulnerable, or strategic enough
  • How to be a more supportive partner
  • Upcoming challenging social situations
  • Recovering from breaking someone’s trust

Looking back at it, it’s hard to believe I covered all of that. When I started the coaching experiment, I didn’t expect much. But I ended up getting a lot out of it. So, I’m writing this post for anyone who hasn’t explored coaching as an option for personal improvement because I didn’t know what to expect when I started.

Before going into what coaching actually involves, I admit that it seems silly. But when you pay a couple hundred dollars to work with someone to do silly things, you start to pay more attention to both the task and its intended value.

The initial coaching work consisted of exercises like:

  • Inner Voices - Have you ever lost control of your inner monologue? This exercise involves writing a paragraph describing the inner voices in your head. A Saboteur voice that comes up whenever there’s uncertainty. A Practical voice that focuses on what to do next. An Appreciator voice that comes up to reflect on positive situations. etc. These voices are then revisited throughout future coaching sessions to improve recognition and understanding of how you feel.
  • Strengths/Weaknesses - Another part of understanding yourself is appreciating your strengths and admitting your weaknesses. Writing a paragraph about one’s own strengths, and then acting them out in a physical motion representing the strength, and doing an investigation on weaknesses can bring themes to recurring challenges.
  • Improv - How awkward is it to do improv exercises alone and over the phone in a glass conference room that all your coworkers can see and hear into? Very! That’s why I take my calls in the back room. Based on the value I got out of the coaching improv work, I even ended up taking a class at a local theater, BATS.

From there, the sessions followed a common pattern.

  1. Biggest Challenge - The beginning of every session started with a question: “What do you want to work on?”. There’s a significant chunk of value attached to having someone ask you this question. After going through a couple sessions, I realized that in the rush to get things done, it’s easy to ignore the harder challenges that have no easy answers. But they don’t go away. They’re on the back of your mind, collecting in a pool which eventually gets distracting, irritating, then unavoidable. And having someone ask you that question helps empty that pool.
  2. Exploration - Going deeper into the topic through a series of Powerful Questions. Alternating between questions, and having Christina reflect back on me her observations of how I answer. Having a great coach allowed me to have a mirror on both my external projection and internal perception. A coach is supposed to help you find your own answers (although I did from time to time get straight advice, which was nice too).
  3. Homework - identifying actions that can be taken in the next week to either explore or improve the issue. The homework would be reviewed at the beginning of the next session. The pressure to actually follow through with the homework was valuable.

Every 2 weeks, we’d have a 30-minute session following the above structure. The meetings felt like a pocket of intense inner reflection, in a sea of external responsibilities and priorities. And having the support from someone you know you can share everything with feels great.

If you’re interested, Blue Door Partners offers individual coaching in addition to Pop-Up Coaching where they come on-site to run individual coaching sessions for companies. We’ve had a great experience offering the service to our employees as a perk to improve wellness and professional growth. In addition, it’s a smart idea to set up initial introductory sessions with a couple coaches and see who gels with you. Yelp is great for this.

Bicycle Tour - San Francisco to Los Angeles

Ryo at Pismo Beach

Introduction

It was the fall of 2016, shortly after my roommate Stephen got a used road bike. One of us put the idea out there that we should bike from San Francisco to Los Angeles. We both got excited about it. Biking down the coast has been on my bucket list ever since I moved to California and biked from my dorm at USC to the Santa Monica pier. I liked the idea of being able to experience the little details of the state: The small towns and the country roads, stuff you miss when you fly down the freeway.

Overwhelmed with how much planning would need to happen, we put the idea aside. But, Stephen stubbornly still told all of his friends that he was going to do the ride. Not wanting to back down on all of his promises, in the spring of 2017 I bought a used road bike and we started preparing.

Planning and Preparation

We spent about 6 months thinking about planning, and 1 month planning in earnest. Luckily, SF to LA is a popular tour and there are a lot of great blog posts, maps, books, and GPS routes that made it easy to cobble together our own itinerary. Our biggest challenges were assembling the necessary gear (since this was our first long tour) and creating an itinerary that took into account a bridge that had washed out in Big Sur.

We ended up using these 2 RideWithGPS routes to create our own route.

Here are some of the resources we used with the above routes to learn what to expect on our trip:

To navigate, I used RideWithGps.com, and their iOS app. To use their offline maps feature it requires a paid monthly subscription, but I figured a couple dollars is a small price to pay to make sure we don’t get lost! As a secondary resource, we got the ACA Pacific Coast Map #4. Although the map didn’t cover details for our detour, I was really impressed by how useful this map was, especially the at-a-glance elevation information. A lot of people also recommend the book Bicycling The Pacific Coast, but I didn’t find it very useful, especially since it’s written in short paragraphs and doesn’t include any maps.

Gear

Bike Touring Gear

Luckily, I’ve had a chance to collect most of the camping gear over time, so that half of the gear was covered. It took us a month and a couple of amazon orders to collect all of the other odds and ends. Looking back, I had no regrets on what I brought, almost all of it was useful at some point. Going on a couple overnight bike camping trips before the big trip allowed us to winnow the equipment down to the essentials (and a couple luxuries - like the Kindle!).

Clothing

  • boots
  • sandals
  • 3 pairs padded bike shorts
  • 5 underwear
  • 5 regular pairs socks
  • waterproof shell
  • waterproof pants
  • costco night pants
  • gloves
  • heat tech fleece
  • 3 dry fit shirts
  • 1 regular shirts
  • 1 pairs wool socks
  • ear mitts
  • sunglasses

Toiletries

  • shammy
  • tube of body wash
  • sunscreen
  • toothpaste / toothbrush
  • first aid kit
  • non antibacterial wet wipes
  • paper towels
  • toilet paper
  • bug repellant
  • lip balm

Cookware

  • stove / gas
  • tins
  • spork
  • knife
  • dehydrated potatoes
  • oatmeal/dried fruit/nuts/dehydrated milk
  • Backpacking meals
  • instant decaf coffee

Sleeping

  • tent / footprint
  • sleeping bag and liner
  • thermarest
  • pillow bag
  • headlamp
  • extra AAA’s
  • kindle

Bike Tools

  • air pump / patch kit
  • 2 extra tubes
  • tire levers
  • multitool
  • chain oil
  • duct tape
  • zip ties
  • bike lock

Utility

  • Cash
  • Quarters (for showers)
  • Handlebar bag
  • Map
  • Power pack
  • Charging cords
  • Headphones
  • Camelback / water bottles
  • Snacks: trail mix, pringles, chips, oreos
  • Wireless headphones
  • bike vest
  • bike lights

Itinerary

Day End At Mileage Accommodations
1 Half Moon Bay 30 Half Moon Bay State Beach Hiker Biker Campsite
2 Santa Cruz 50 New Brighton State Beach Hiker Biker Campsite
3 Monterey 50 Veterans Memorial Park
4 King City 60 Days Inn
5 Paso Robles 66 Motel 6
6 Pismo Beach 67 Pismo State Beach Oceano Campground (reservation)
7 Solvang 68 Refugio State Beach
8 Ventura 64 Premier Inns
9 Los Angeles 58 Stephen’s house

Day 1: San Francisco to Half Moon Bay

A post shared by Ryo Chiba (@rchiba) on

Our first setback happened before we even started. At the TINT office, Stephen noticed that his rack was crooked, and after looking closer we saw that a screw had fallen off. We were already an hour later than when we needed to leave and we rushed to find a local bike shop that would have a screw. Ended up going to Pedal Revolution. We got the rack back on, but we weren’t able to get it fully secure in the eyelet (foreshadowing for later when the rack tore off of the frame).

Our second setback was when we were heading through the hills between Pacifica and Half Moon Bay. The roads get narrow and there are long downhill stretches where you are riding fast. I hit a series of potholes, my inner tube popped, and I lost control of the bike - flew off and hit the ground. I was incredibly lucky to only have cuts and bruises. One of my favorite memories was Stephen pulling up and laughing hysterically while I’m wondering if I’ve broken any bones. I’m sitting there dizzy, relieved that nothing happened, and expect Stephen to help me replace my flat tire. When I ask him to help me. He says, “You know this… I’m incompetent!” Ahahaha.

We were rewarded with the best campsite of our entire trip, the Half Moon Bay Beach. A clean, freshly cut section of grass next to the beach and clean showers. The raccoons at night steal our snacks but it’s okay, they deserve it.

Day 2: Half Moon Bay to Santa Cruz

A post shared by Ryo Chiba (@rchiba) on

We woke up to thumps on the tent roof. It’s 3am. I poke my head out and there are fruit snacks plunking onto the tent one at a time. I shine my light up into the tree and two glowing raccoon eyes shine down at me. I figure there’s nothing I can do and crawl back into bed to fall asleep.

The highlight of the day is halfway to Santa Cruz when we stop at Swanton Berry Farm. Along the PCH, the farm is a regular stop for anyone looking for fresh made strawberry sweets, and depending on the season, u-pick berries. Today there are catering tables and chairs set up with a band playing in the grassy field next to the parking lot. Not quite sure what the occasion is, we walk through the party to park our bikes. An older man walks up to us and introduces himself as Bern. We learn that Bern used to own the farm and the event is in memory of his younger brother who recently passed away. He invited us to have a slice strawberry pie: The best berry pie I’ve ever had. As we looked onto the sunny California coastline eating fresh berry pie, we share a special moment with strangers.

Day 3: Santa Cruz to Monterrey

A post shared by Ryo Chiba (@rchiba) on

The earplugs I got from the CVS the night before were the best investment, the sleep was unbeatable. We start late as usual and are on the road at 10:30am. Right before we leave, a couple the campsite next door came up and shared that they have always wanted to do bike touring. We realize we’re living the dream! Taco Bell for breakfast and then we rolled out of the city and into the countryside.

The sights and smells were splendid. It’s old chateaus on hills overlooking commercial berry fields, beat up Tauruses and Corollas rumbling down dirt roads. It feels like Indiana, minus the heat and corn. Our spontaneous roadside stop today was Moss Landing, and Phil’s Fish Market & Eatery. We got huge portions of cioppino and fish and chips and eat in a windy gravel parking lot, rejoicing in the heavy paper containers of food in front of us. By the end of the meal we are both so full we can barely finish. Rolling into Monterrey, we struggle up the hill to Veterans Park and as the sun sets, we order delivery pizza to the park.

Day 4: Monterrey to King City

A post shared by Ryo Chiba (@rchiba) on

We met Dominic in the morning who is staying in the campsite next to us. He’s an older black gentleman who told us about how the campground gets really popular in May. He sells rasta bracelets, used to sell them with his wife who can no longer join him due to a chronic illness. He told us more stories, but eventually we headed out away from the coast to begin our inland detour. After about 20 miles we saw a small sign ahead for the Monterrey Zoo. We decided to take a tour and relax for a bit. After an hour of African cats, we rode out, but then I heard Stephen yelling behind me. I turned around. Flat tire? I realized that it’s worse when I see that his rear tire is missing half its spokes. The rack ripped off the mounts and jammed into the wheel, destroying both the frame and the rear wheel. For a long moment we considered our options and decided that our best bet was to have me drop all of my gear and bike back to the nearest town (Salinas) and rent a car to make it to the next city in our itinerary, and once we get there, to figure out next steps. It took me an hour to hustle to Salinas, but am able to successfully rent a car, pick up Stephen, and drive to the Days Inn at King City. That night the motel was a luxury and exactly what we needed.

Day 5: King City to Paso Robles

A post shared by Ryo Chiba (@rchiba) on

I have a dream of Stephen walking out of the motel bathroom holding a friend’s bike. I wake up and tell Stephen, “I have a plan.” Plan: Drive back to San Francisco, pick up friend’s bike, and drive to the next stop in our itinerary to continue our tour tomorrow morning. I called our friend, Chris, he answers and confirms. In 20 minutes we’re ready to roll out of the motel. 3 hours later we’re back in San Francisco, and after almost running out of gas, we drive drive drive. We make it to Paso Robles and assemble the bikes in the car rental parking lot. It’s HOT. We rode and checked into the Motel 6. I laid on the bed and enjoyed the stillness. It felt satisfying to come up with an idea from a dream and turn it into a reality. After the sun sets, we rode to McDonalds to get a soft serve cone.

Day 6: Paso Robles to Pismo Beach

A post shared by Ryo Chiba (@rchiba) on

We woke up earlier than usual, 8am, kicked it into high gear to leave. It was one of our longest days, projected to be almost 70 miles. Breakfast was McDonalds for Stephen and I’m sick of McD’s, so Subway for me. We rode out of Paso Robles and into the countryside. Long rolling hills, and then we hit the hill we saw on the map. Struggles to get the the top, but the views are incredible. Eventually we’re over the clouds, the hills are lush and green, and we saw all the way to the water which was many miles away. We coasted downhill all the way to the Pacific Coast Highway. Short stop at a small path that leads us to a coastal cliff and a beach. Stephen needed to make a couple business calls, so we stopped at a beach town and an old couple started a conversation and ended it by telling us to call our parents. Then, up through foggy farmland and to SLO where we got pork ribs at Firestone Grill. We spent our final calories getting to Pismo Beach to camp out with bohemian lifestylers on a Wednesday evening.

Day 7: Pismo Beach to Refugio Beach

A post shared by Ryo Chiba (@rchiba) on

Another long 70 mile day. I was afraid that any stress injuries would happen today. Focused on my cycling form and tried to pedal smoothly. We found a touristy diner around the corner and got breakfast there. We began our long journey into the countryside again. I waved to a migrant worker with a full face mask working in a field and they waved back at me. This day was dusty, windy, hot, clearly we had passed through the mysterious line that separates North from South. Thirteen miles back, we passed through Guadalupe (population 7k). There’s a mural marking its location in California on the tallest building (4 stories), and main street is empty. The town is memorable and unique, somewhere I would never pass through on a drive, unclaimed by chain stores and franchises, except one Subway where we got lunch. A girl gets dropped off by her mom to start her shift as a Sandwich Artist and I wonder what it’s like to grow up here and what San Francisco must seem like to an outsider. Watching the multicolored triangle flags snap over the used car lot next door, I imagine that for all the days that pass in San Francisco, the same number pass in Guadalupe and these flags are flying regardless.

Rolled out of the tiny town, and we soon hit our first climb, Harris Grade Road. It’s steep, we’re gnashing on our lowest gears, and we stopped a couple of times to catch our breath. We race down the other side and roll into Lompoc where we get some thai food. Even medium sized towns feel much larger after biking through the country for so long. It’s 4pm and it’s onto the final hill. Hours of climbing pass by, and as the sun starts to go down, we race >30 mph down the other side down to the 101 freeway.

We double check but almost unbelievably we’re supposed to go down the freeway. At the junction, as we check directions, I see a half dead rattlesnake at my feet and it makes me jump.

We rode the freeway. Cars and semis going 80mph zoomed past. The worst was the sound of a semi truck as it rumbled from a distance, and as it got closer rose into a terrifying crescendo which peaked as the sudden gust of wind threw gravel onto me. We stayed focused and avoided rattlesnake carcasses on the right and traffic on the left. Finally, we made it to the coast. Continuing down the coast, still on the freeway, there was a sign that read “If flashing, bicyclists on bridge”, but it was clear that it flasheed all the time, clearly a half-hearted stop gap measure for an unsafe bridge with no median.

Sunset at Refugio Beach felt like our little slice of paradise, and in the twilight we reflected on our favorite parts of the trip while eating the last of the backpacking food.

Day 8: Refugio Beach to Ventura

A post shared by Ryo Chiba (@rchiba) on

Leaving Refugio beach, we debate on breakfast plans. The nearest place with breakfast is quite a ways away, so we heat up some oatmeal and hit the road hoping we’ll run into some fast food. The road is mostly flat and along the coast which is a plus, but still along the freeway which is a big minus. Along the way, we take a detour through Santa Barbara. We are thankful to find a Costco where we get our first tasty meal of the day. Pizza and salads. Then, a leisurely cruise through the bike-friendly UCSB campus. It’s fun to pretend to be students for a little bit. Then, back on the beach and down to Carpenteria. We stop at a Pho place and I ask Stephen to pull up the address for the motel that night so that I can start planning our route more accurately. He says, “It’s the Premier Inns, Thousand Oaks.” And I search it on Google Maps and realize that the motel is about 20 miles out of the way of the path to LA. It looks like we weren’t paying attention when we were booking with Travelocity and we ended up booking a place that was slightly cheaper, and probably worth going to if we were driving, but inaccessible by bike. With the sun quickly starting to get dim, we go into planning mode and we start to look for options to re-book in Ventura proper. We are lucky and are able to cancel the reservation with no charge and re-book at a much more convenient location without too much of a last-minute price hike. Whew! We roll down as the sun is setting into Ventura and check into the Vagabond Inn. This is by far the nicest motel we’ve stayed at so far, and it feels glorious to take a private hot shower and lay in a bed in a clean room. We eat takeout fish burritos from Spencer Makenzie’s and they are so good.

Day 9: Ventura to Los Angeles

A post shared by Ryo Chiba (@rchiba) on

The last day of the ride! We can start to feel LA coming up as we roll out of Ventura and through Oxnard, heading to Malibu. We stop to eat some roadside strawberries from a parked truck and below we see houses of the rich and famous. We pass the sign marking the LA county line, and weave through traffic as we enter Malibu. We reach Santa Monica and run into the water. Then, a long Metro ride to Monterrey Park and then crashing at Stephen’s parents’ place.

Surprises

  • The Community - Everyday, other cyclists would wave and start a conversation about where we were headed and what tours they’ve been on. Our bikes were a great way for people to approach us, and it surprised me how popular cycling is even in the remotest areas.
  • Our Own Stamina - We had never done long-distance cycling before planning this trip out, and the training rides we did before the trip were about 40 miles, so we were expecting the 70 mile days we had planned to be absolutely at the edge of our physical limits. However, we found that we had underestimated our abilities and although those days were exhausting, they were do-able. And we were always able to make it to the next campsite before dark.
  • Hike/Bike Campsites - One of my worries was that we’d get to a campsite after a long day of riding to discover that the first-come-first-served hike/bike campsites would be filled up and we’d have to stealth camp on some gun-wielding stranger’s property. Luckily, we never got close to that, because most of the time, we were the only ones at the campsite. Also, I asked rangers at each of the parks if they had ever turned any cyclists away, and all of them said that it never happens.
  • Signage - It was strange but reassuring to see the “Bicycle Route - Pacific Coast” signs pop up even in the most remote and unexpected locations. Near the end of the trip, we needed to get on the 101 freeway, and at first I was like, “no way”, but then after taking the plunge and pedaling down the on-ramp, there were bicycle signs on the freeway too! The signs were a nice touch, I felt like I was on a well-traveled path.

Tips for the first time bike tourist

  • The adventure only starts once something goes wrong. Be ready to adapt to changes in the plan. Keep your expectations low :)
  • Check how much weight your bike frame can hold. We learned the hard way.
  • Related to the above, if you have any issues with your bike, reddit /r/bikewrench is a community of mechanics that’ll give you the advice you need
  • Practice for a longer trip with shorter tours. We bike-camped 2 times on weekends before the long trip and it helped us build our endurance and identify any gear we needed, or didn’t need on the longer trip
  • Never leave any food unsecured at a campsite, raccoons can open clasps, zippers, and claw through plastic bags.
  • Invest in plastic tubes for liquids, our soap container started leaking halfway through the trip.
  • If you’re camping, figuring out the sleeping gear you need to get fully recharged with a great nights sleep is critical. For me, that includes an inflatable sleeping pad and earplugs. A couple camping trips should help you figure this out.

Generate Leads with a Free Product

Instagram Winner Picker leads per day

The above image is a graph of the number of leads generated from a small marketing tool that we created at TINT. Everyday, about 18 marketers use our tool to pick a winner for their Instagram campaign. These emails are valuable to us because anyone who is wrapping up an Instagram campaign is a potential customer.

Are you a team that is lucky enough to have some extra technical talent who can crank out a fun side-project during a hack day? If so, then here’s what you need to do to get leads with a free tool:

1. Find a Customer Problem

Muriel eating a cupcake

Find a problem your customers are having. Here’s how I did it: I was getting lunch with my coworker Muriel, and she mentioned that she was having a hard time picking a winner for our Instagram contest. It was a real pain! There just wasn’t a good tool to pick a winner. She ended up searching Instagram for the contest’s hashtag, closing her eyes, scrolling down, and randomly choosing one of the images.

At that moment, I realized that I had stumbled on a perfect problem. A perfect problem is highly targeted: Something specific enough that you know the people who have this problem are your customers, but universal enough that it’ll be a popular search. Speaking of search, the next step is to…

2. Identify the Search Query

Google Keyword Planner

The next question is how they’ll find your tool. Most likely, they’ll be searching on Google. I asked Muriel what she searched for when she was looking for tools. She said, “Instagram winner picker”. Then I went on a walk outside and thought about what I would search for if I were a marketer looking to pick a winner for my contest. “instagram contest winner chooser”, “pick hashtag contest winner”, and “instagram giveaway generator” were some of the different keywords that came to mind. Finally, I went to Google Keyword Planner to type my ideas in and figure out which keywords were actually being searched for. I picked the top ones, and used that to determine what keywords to optimize the tool for.

3. Build an MVP to solve the problem

Luckily, I’m a developer, so it was easy to find someone to build my idea. But, if you need to recruit someone from the engineering team, you can still make your tool happen.

Some things to keep in mind:

  • Make it look great - A good design can keep people on the site longer, and increase the chances of interaction, which will boost SEO.
  • Make it fast - Page load speed is an important factor in bounce rates, especially when people are looking for a quick tool to solve a specific problem. Improve your ranking by making sure load time is optimized.
  • Make it simple - In our experience, the simplest landing pages perform the best. Make sure it’s brain-dead obvious to someone landing on this page that it solves the problem that they are searching for. Our Instagram Winner Picker tool just has a single button, “Get Started”.

Instagram Winner Picker Screenshot

4. Re-evaluate and iterate every 2 weeks

Although this step is easy to do, it’s also the easiest to forget. First, create a document to track all the details of your marketing experiment. Set calendar events when you release the project in 2 week intervals to:

  • Look at Google Webmaster Tools to see how your rankings are doing
  • Figure out why you might be ranking lower than expected, and build backlinks to your app that can help it rank higher

Results

Product marketing search results

As you can see above, our tool now consistently gets about 80 clicks a day, resulting in about 18 emails a day of marketers who are running Instagram campaigns. Nice.

What is a company culture?

“What is culture and how do you start to define it for your company / startup?”

I ask myself this question often. And I answer it by saying, “A company culture isn’t a list of perks. It’s what people do when their boss isn’t looking. It’s how people make decisions, the norms and habits taken for granted, and invisible relationships that shape our workplace.”

But, how do we define OUR company culture? That’s a harder question.

Greater minds than mine have taken a stab at it. They’ve put together ways of categorizing corporate cultures through surveys and models. Using vocabulary to shine a light on what continues to be an elusive mystery.

Last year Lukas, our PM and go-to person for all miscellaneous knowledge, introduced me to the Schneider Culture Model. In 1999, William Schneider took it upon himself to try to build on previous works to create a model to describe how organizations make decisions.

Schneider’s model divides companies by how they score on two axes, one axis is the “personal vs impersonal”. Are decisions made in a detached and objective way that focuses on the company, or are they personal, taking into account the individuals involved? The other axis is “actuality vs possibility”. Are decisions made with a focus on what we can actually accomplish today, or the possibility of tomorrow?

Based on these two basic ideas, he divides corporate cultures into 4 types:

  • Collaboration - “We succeed by working together”
  • Control - “We succeed by getting and keeping control”
  • Competence - “We succeed by being the best”
  • Cultivation - “We succeed by growing people who fulfill our vision”

Schneider Culture Model

What I like about this model is that there isn’t a “good” or a “bad” culture. These are all different types of cultures that succeed in different environments. There are examples of Great Places to Work™ in each of these categories. For example:

  • Collaboration - Delta, UPS, Valve
  • Control - Proctor and Gamble, Marriot, US Army
  • Competence - Microsoft, Citibank, Pixar, Netflix
  • Cultivation - 3M, Zappos

Most people would be excited to work at any of these companies, yet they occupy totally different spaces in the model. This is important to note! Especially since it’s easy to get distracted by arguing, “oh, this kind of company culture is better”. Nonsense! Instead, I want to figure out what our company culture is, where we want to be, and then find ways to take us there.

So where does TINT fit in the chart? Last year, I had the company sit down and take a 20 question survey to figure it out. I asked the team, “Where do you think our company is today, and where do you want it to be tomorrow?”. And this year, I did the same thing. Here are the results that I got (You can use the checkboxes to explore the data):

Some initial observations:

  • People > Company - We are more people oriented than company oriented. This makes sense, as the company has produced policies that give employees more flexibility and freedom.
  • Possibility > Actuality - We are slightly more possibility oriented than actuality oriented.
  • More Actuality in 2016 - Since 2015, there is double the number of people in the “Collaboration” vs “Cultivation” quadrant, suggesting that we have become more focused on the present than the future. This makes sense, as we’ve gone through some harsh realities in the past year making it essential for us to focus on what we can do right now.
  • Cultivation - According to the results, we succeed by growing people who fulfill our vision. Not surprising, given that our vision statement is to help our team and customers achieve their potential.
  • A Common Future - If you compare the 2 predictions of an ideal future, you will see that the “where do you want to be in the future” has not changed, and that we seek to be in the Cultivation quadrant.

Screen Shot 2016-11-22 at 1.41.40 PM.png

What do I want to do based on these results?

  • The Future - From the survey, we see the team expressing a consistent ideal of being more in the cultivation corner. So, let’s figure out how we can uphold what got us there in the first place!
  • Self Improvement Program - At TINT, we have a program that’s focused on being the best you can be, where we can expense up to $100 in anything related to self improvement, as long as you complete a monthly challenge. The results from the survey highlight the importance of this program at our company, and it lets me know that I personally need to continue putting effort into participating and encouraging others to participate in the program.
    • Advisors - This tells me that I should continue to seek highly skilled advisors to help cultivate our team. Since we’ve brought her on, our sales advisor Bridget has helped us tremendously both with the co-founders management skills and also for our sales process.
    • Recruiting and Onboarding - I want to incorporate this framework into our recruiting and onboarding process to tell candidates and new hires what our company culture is and isn’t, and show them how they can contribute. The best way to maintain a culture with new employees is education, and now I have a vocabulary to teach!
    • Everyday Spirit and Compassion - How do we make a more spirited and compassionate workplace? And how can we introduce more change within our everyday routines to take us closer to a workplace that cultivates others? These are questions that I now need to focus on.

    After doing this exercise, I think it would be even more valuable if other companies joined in to see how they see themselves in terms of culture.

Your Turn

Do you want to do the same experiment for your team?

  • Step 1: Copy this Schneider Culture Survey google form
  • Step 2: Use the results, and this google sheet as a template to figure out X and Y coordinates from the results
  • Step 3: Reflect! Some questions to ask yourself:
    • Do I agree or disagree with the results, why?
    • What policies and processes at the company reflect your culture quadrant?
    • How dispersed is everyone’s assessment of the organization, and what does it mean?
    • How can these results help the team better express the company’s culture?

If you do go about doing the above, book a time to share your results with me. And even if you don’t, I’m happy to chat about anything related to company cultures in startups, I enjoy connecting with like minds on the topic.

Additional Reading

Tough Times Don’t Last But Tough Startups Do

I closed my eyes and counted to three while in an empty and dark conference room. I told myself that I was ready to tell my friend and coworker that I would be laying him off. I needed to shut off my emotions. I needed to close the valve on my feelings, and close it tight. I opened my eyes, and walked downstairs. I tap my friend on the shoulder, “Can we talk?”, and we move into another conference room. Tim, our CEO, is already in the room, ready to co-pilot the meeting with me. I close the door tightly. The three of us sit in a distanced triangle. There is a long pause.

“I need to tell you something important.”

I present the details that need to be presented: The reasons, the timeline, how long benefits will last, severance, next steps. I’ve seen Tim do this before, and I’ve been the co-pilot. It is much easier to be the co-pilot. All you have to do is pay attention and fill in any gaps that you notice. This time, I’m driving. I am making eye contact, fully aware because of the adrenaline. At the same time, distant because of what I told myself in the dark conference room. I dutifully complete the agenda.

“Out of all people, I would have expected you to be more empathetic about this.” says my friend.

All of a sudden, I realize how deeply offensive I must seem to him, to be so cold. Suddenly, the valve in my heart twists open, and all of the feelings start flooding out: The disappointment, the guilt, the anger, and sadness. My eyes begin to water and my throat closes up. I try to speak, but can’t. I hoarsely force a couple words out, but stop mid-sentence. Tim notices, and picks up from where I am stuck, and the meeting continues. How did it get to this?

FUNDRAISING COMMITTEE

On August 24, 2015, the TINT Fundraising Committee was formed to decide on whether or not we should fundraise or to continue to bootstrap our own growth. In the traditional TINT fashion, we democratically elected a 7 person committee, and set up regular weekly meetings. Just one month before in July, we had closed our biggest deal yet.

One of our largest clients wanted to display their social media using TINT, and they committed $120k+ to us. We felt like the world was our oyster as we watched the monthly revenue soar to a spectacular $640k for that month, a huge difference from the previous highest revenue month of $432k.

The committee met weekly for the month of September, and developed a financial model to predict how aggressively we could spend, and when we could start seeing returns from our spending. After much back and forth, the committee coalesced around a single model that highlighted everything from a hiring model to our sales cycle. The model suggested that if we hired aggressively, we would be able to expect to see equally aggressive revenue growth after the negative effects of the slow winter season ended. The model also suggested that we would be able to stay safe even without outside funding.

Based on these suggestions, on October 7th, the committee sent out an email to the team. TINT would “delay fundraising and pursue a course of creating a relatively more aggressive hiring/spending plan. This plan will be focused on driving revenue growth over the next 6 months and measuring the incremental impact of marketing and outbound sales on our revenue as well as increased product and operational expenses.”

However, the committee was not completely blind to the risks. The email from the committee continues: “Admitted Risk: We realize there is a chance that increasing our spend could lead us to no longer being profitable and being forced to fundraise in a situation where we are burning cash in 2016. This is a calculated risk we are taking based on our projections which show we will not end up in a situation with significant burn. Excited to put some gas on the fire and prove out some of our growth assumptions!”

On December 3rd, 2015, we still felt that we were on track, and the committee sent out an update: “I am happy to say that we are overall exceeding our goal, despite being slightly below numbers for November.” The email told the team to anticipate 10 hires before next April.

The graph below shows what we saw when that email was sent. According to the plan, we were still on track. The X-axis is set up such that “4” represents November. On closer examination, you will notice that the revenue line (red) jumps up significantly at 7, 8, and 9, which represent February, March, and April. That’s when we’d start to see the returns from our investment. The model predicted that during those months we would see revenue climb to 580, 620, and 650. We could do it right? We did it in July!

ryochiba.hackpad.com_W9y0E5gwF4h_p.419835_1463877955182_Screen Shot 2016-05-21 at 5.41.31 PM

GAS ON THE FIRE

From September 2015 through February of 2016, we brought on 11 full time employees. 4 of them were international and were previously contracting. Before the growth plan, from April through September, payroll averaged at $234k. From September through February, payroll averaged $293k, growing a whopping $60k.

ryochiba.hackpad.com_W9y0E5gwF4h_p.419835_1463959619750_Screen Shot 2016-05-22 at 4.26.29 PM

In addition, we upgraded our digs. We went from paying $8.5k on a 3000 square foot office to paying $35k on a 10000 square foot office. Total office related expenditures climbed from a $28k in January to $62k in February. The cost of moving offices was even worse than we anticipated because we were not able to find a sublessor for the old office. Given the bullish office real estate market in San Francisco, we expected to make a healthy profit of 8k from our old office. Instead, we were experiencing an 8.5k loss, as we continued to lower the price each month, desperate for a company to move in. Ouch.

ryochiba.hackpad.com_W9y0E5gwF4h_p.419835_1463964569744_2501bryant

COMING TO A HEAD

ryochiba.hackpad.com_W9y0E5gwF4h_p.419835_1463881015319_Screen Shot 2016-05-21 at 5.14.15 PM

In January, we hit our target of $450k. However, the good news did not last long. In February, we missed the 580 target significantly, and only made $436k. By the middle of March, it was clear that we were not going to hit $620k, and it was becoming increasingly obvious that we would not hit $650k as predicted in April. If we were to project more conservative revenue expectations forward, our bank account would look dangerously low.

How low? Well, let’s take a look at the projected health ratio. The health ratio is a number that represents the general health of the business and is simply the business’ bank balance divided by monthly core expenses. Anywhere below 1.0 is dangerous for the business, because once you dip below that, it is possible to not make payroll if revenue for that month does not arrive in time. The projection showed that our health ratio would dip to an alarming 0.6 by the middle of the year, and by the end of the year we would be bankrupt. Simply put, the model put us in an existential crisis. Compounding the necessity to make a decision was a team retreat that was scheduled for the beginning of April. If we were going to make drastic cuts, it would be best to make them before the all hands team retreat.

ryochiba.hackpad.com_W9y0E5gwF4h_p.419835_1463963350649_Screen Shot 2016-05-22 at 5.27.41 PM

The day things came to a head was March 23, 2016. It was decided that afternoon among the co-founders that emergency planning would need to take place, and the co-founders met for extended periods between the 23rd to the 27th, scrambling on Saturday and Sunday to come up with a plan to both reduce expenses and to effectively communicate the reductions to the team. The two plans we needed to decide between were to either Cut Shallow or Cut Deep. The Cut Shallow plan involved cutting around $30k in expenses, and then working on immediately raising a $1-2M buffer round of funding. The Cut Deep plan involved cutting $50k in expenses, and then working on reaching profitability before considering raising money. After debate, we decided to go with the Cut Deep plan because it reduced the chances of a second cut, which would be devastating to morale and our long term growth. From there, we worked to make the impossible decision of which employees would be cut. Ultimately, it was a decision that was based on what would make the least drastic impact to the business.

The decision making process was brutal and ugly. It felt awful. It involved putting everyone’s name on the board and going through them one by one, and going through the impact each person would make on the business if they were laid off. After getting through the list, we went through the list again. And then we went through the list yet again, one last, painful time. Each time, we pushed back against each other when we disagreed and identified areas where we needed to collect more information. We wished we had the experience to be able to make an optimal call. Given the constraints given to us, we did the best we could, but we still walked away disappointed that employees would have to be cut for the mistakes that we had made as the leadership team.

Stakeholders were called in the weekend before the announcement to individually meet with the cofounders. They included some early employees, and continuing employees that would be affected the most. The cofounders shared the components of the plan that applied to them, so that they could gather feedback and to prepare them for Monday. By Sunday night the cofounders had a deck, a timeline, and a sleepless night ahead.

ryochiba.hackpad.com_W9y0E5gwF4h_p.419835_1463963410460_Screen Shot 2016-05-22 at 5.27.28 PM-1

THE LAYOFFS

On Monday, March 28, the co-founders proceeded with the layoffs, scheduling meetings with the applicable employees in hour long calendar events whose sole agenda was to let them know what was happening and to deliver the necessary details. The announcement to the team was scheduled for noon. Unfortunately, the last layoff meeting went longer than expected, and Tim had to deliver the news to the team alone without Ryo and Nik. Tim walked the team through the deck. It explained the necessity to make big expense reductions, restructure the company, and implement new processes.

After the presentation, employees were largely in shock. With a number of missing threads, the social fabric of the team was frayed, and walking through the office it could be felt. Adding to the tumultuous day, one of our top performing salespeople announced her resignation shortly after the presentation. It was by coincidence: She had planned on making her announcement on that day the week before, not knowing about the layoff.

THE AFTERMATH

It was only in the weeks afterward, that we began to realize the mistakes we had made when communicating the layoffs to the team. The biggest mistake we made was that we confused the difference between a firing and a layoff, which are legally very, very different. Inadvertently, we had created an HR liability for our company, and upon learning this mistake, we immediately worked to make clear that this was a layoff, not a firing. Another mistake we made was that we did not announce who was being laid off in the team announcement, until someone asked for it. That was really the only question on everyone’s mind, and it was against our values to not share it immediately. Yet another mistake we made was not looping in our Operations Manager and HR team before the announcement. This would likely have prevented the other mistakes.

On March 30, just 2 days after the announcement, the team set off for Wonder Valley in Fresno for the team retreat. We usually have a retreat every 6 months to strategize and bond. This time, it would be to repair. Our Operations Manager did a wonderful job of planning the retreat for the past couple months, and the retreat proceeded without incident, smoothly and efficiently. We paddled canoes, brainstormed Q2 strategies, and played cards late into the night. However, even the best retreat would not be able to fully heal the wounds left from losing one’s friends from the workplace. The team came back from Fresno closer than they were after the announcement, but still fragmented, and feeling the weird energy the layoffs brought about.

ryochiba.hackpad.com_W9y0E5gwF4h_p.419835_1463962768996_retreat

In April and May we saw a continuation of the aftermath when 2 key engineers announced their resignation in order to pursue their own interests. This hit the team particularly hard because both of these employees represented strong talent on the team.

That brings us to the present. Today, we are still working to handle the situation day by day, leading initiatives to get back to profitability. Until we reach a stable financial state, we will be operating in a mode of scarcity, holding off promotions and our 401k matching program. The scarcity is a painful but important motivator in absorbing the lessons learned.

LESSONS LEARNED / LEARNING

  • Expect the best, but plan for the worst – We expected the best, and planned for the best. At each step of the way, we leaned on the optimistic side. Our aggressive hiring plan assumed that we would be able to source quality candidates in that time, even though past data showed that it takes months to find a quality candidate. Our office plan assumed that we would be making a big profit from subletting the space. The growth plan projected very, very optimistic revenue growth. We should not have baked as much optimism into our plans.
  • Cut Deep, Cut Once – This was the first word of advice from almost every advisor, mentor, and online resource we consulted before making the decision. Leadership only has one chance to convince the team that the company can be turned around.
  • Fundraising – Fundraising should be guided by an individual who has the most experience in fundraising. For us, that person was Allen Morgan, a member of our board, who should have been brought into the discussion much earlier. Instead, he was informed at the beginning of 2016, months after the committee laid the groundwork for the growth plan.
  • HR – We learned that a firing and a layoff are very different, even if both are based on performance. In the future, we will talk to an HR professional before making big moves.
  • Motivation – After making the announcement, morale was at a historic low. The co-founders felt pressure to motivate the team. However, how do you motivate a team that’s just gone through a round of layoffs? What we learned from our sales advisor Bridget Gleason, was “You can’t motivate people – it’s not your job to motivate people – your job is to provide a great environment where motivated people can be successful”. We learned not to beat ourselves up for everyone feeling awful, and to be patient and focus on what is under our control to create a successful environment moving forward.
  • Doing More with Less – In the months after the layoff, we asked ourselves more and more “What does success look like?” Instead of taking a “spray and pray” approach to our activities, we now spend more time tracking impact so that we can learn how we can do more with less. You can only improve what you can measure.

THE FUTURE

Screen Shot 2016-06-08 at 10.19.08 AM

Although we experienced the largest setback in this company’s history, we must remember everyday to appreciate how far we have come. We are making steady revenue from a group of passionate customers and have a product that regularly sells itself. The comments our customers give us for our easy to use product and personal customer service is inspiring.

We have overcome challenges in the past. Depression, burnout, breakups, and surviving on the bare minimum with only 3 months of runway left. Each challenge larger and more daunting than the one before. But each time, we have improved ourselves and developed solutions to move forward.

We are now 2 months past the layoffs, and are experimenting with new ways of approaching work. Here is how we are challenging ourselves to improve:

  • Data – In the past, we never got around to measuring what we wanted to know. Now, when we start a project, we are more disciplined about asking ourselves, “What does success look like?” We are more careful about measuring our results and more disciplined about learning from our mistakes. More analysis means faster failing, more learning, and a higher chance we’ll work on what will make the most difference for our customers.
  • Goals – In the past, we took a scattershot approach to what everyone was working on and didn’t provide adequate direction or coordination. We set goals, but they were often forgotten by the middle of the quarter. Now, we have improved how we create goals, spending more time making sure that they are the right size and have strong business value. Also, we have made our goals more visible by adding them to our 1:1 process. By keeping us focused on our long term objectives, we will be able to achieve more with less.
  • Restructuring – Previously, we had 7 department heads for an organization of about 30. This resulted in significant overhead in coordinating all of the heads. We are now dividing up management responsibilities among the 3 co-founders and our sales director, which results in less communication overhead, and more time to focus on customer needs.

As for what the future holds, much is beyond our control: Competitors continue to leave and enter the space, the market evolves at a rapid pace, and customers’ needs change. However, I believe the future is still in our hands. The best team is going to write the best software, sell the best pitch, generate the greatest following.

We are not the typical VC-funded Silicon Valley company. Because we are self-sustaining, we have the luxury of focusing on sustainable growth. And we have an excellent team at TINT, to move us forward on that path. We feel the pressure, but it makes us stronger. Next time, we’ll be more careful about putting gas on the fire.

My Ebike

Photo of bike

Introduction

My commute to work is about 3 miles through the city of San Francisco. The weather stays around 50-60 throughout the whole year, it’s infrequently rainy, and the road on the way to work has a decent amount of bicycle infrastructure. I prefer to bike to work for a couple of reasons. Mainly, it allows me to get to work at a predictable time. Using Lyft Line or the bus adds variability into my schedule that can often exceed 30 minutes. If I commute using those methods, I have less time to sleep/prepare for my day and I have to spend more time commuting. So, I like to use my bike. Plus, I get to get some fresh air and it’s fun to see the city by bike! However, recently I’ve found that after a long day of work, the last thing I want to do is spend 20 minutes pedaling back home in the dark.

Solution

My colleague recently recommended to me the BBS02 electric bike kit from Luna Cycle. He has been commuting on a mountain bike that he converted to an electric bike and he said it was working well for his commute. After some investigation, I found that the BBS02 is one of the most popular ebike motors in the ebike community. I also found that it is generally reliable, easy to install, powerful, and a good value for the money. I debated myself on whether I should get it for a couple weeks, but eventually I splurged. The motor and battery cost me $970. I also added on a powerful front headlight and rear light to replace my weak blinkers for another $80.

Installation

I nervously waited for the kit to arrive, and when it finally did, I took my bike (a Schwinn Volare Road Bike) to a local bike store to have the kit installed. The hourly rate for the mechanic was $60, and they said it would take about 1-2 hours to install. It ended up taking 2 hours, so I paid them $120 for installation, and I had my first ebike! Before they would give me my bike, the owner of the store took it for a safety run on Market Street. When he came back from the safety run, he seemed pretty shocked at how fast it could go. Most of the bikes they sold at the store were about 350W and the kit is 700W which was probably the reason why he was so emphatic about making sure to take proper safety precautions. Riding back home for the first time on my bike, I could tell that this was a new machine.

Impressions

Riding an ebike for the first time changes the bike fundamentally in that it becomes something that can be driven, not just ridden. In that sense, it almost becomes like a moped or an ultra-lightweight motocross bike that just happens to have pedals. It’s hard to describe the feeling of biking without pedaling, but cycling purists be damned, it is fun! Suddenly any part of the city is accessible to me faster than public transit or if I called a Lyft. For commuting within a city, it cannot be beat (unless you live in a city with crap weather). Every day, my commute feels like a pleasure rather than a chore. Even though externally, the bike looks similar to its original form, it is truly totally different.

Caveats

  • I have to avoid locking my bike outdoors now due to it’s increase in value.
  • More mechanical complexity in the bike, the possibility of more expensive maintenance costs.
  • It’s still too easy to get seriously injured or die on SF streets as a biker due to limited biking affordances. Riding defensively is a must.

Budget

Base Bike

Extras

Total: $1,470

Lessons Learned

  • It’s surprisingly easy to make your own ebike.
  • Having an ebike improved my commute drastically.
  • Commuting by ebike has changed my perspective on what areas of the city are possible to live in now.