← Manuel Hitz, CV

Doodle

Senior Fullstack Developer · May 2014 – Aug 2017

I see my time at Doodle as four chapters: maintenance and APIs, a new mobile web app, a complete responsive redesign, and the team practices that held it together. I was originally hired as a full-stack engineer for BookMe, but that product was discontinued shortly after I joined.

Maintenance and small features

I started by helping introduce Sass and cleaning up the existing CSS, taking stock of fonts, colors and sprites. It made the team aware that limiting the number of colors and defining a style guide would pay off in the future.

Two months in, I became the mentor of Angela, our intern. With no prior frontend experience, she chose to migrate FullCalendar from version 2 to 3 for the calendar view of Doodle polls.

In parallel, Spyros and I specified, implemented and documented a new JSON API for the upcoming iOS app, built by an agency. I could draw on previous experience building APIs with the same stack and well-structured data transfer objects, rather than ad-hoc JSON. The iOS app also needed push notifications, which was new territory for me.

In fall 2014, I finally worked on my first user-facing feature: a new step in the poll creation wizard for inviting participants, with address book integration.

Participant invitation step with contact suggestions
Inviting participants, with suggestions from Google and Outlook contacts

The following months were mostly refactoring: introducing constants, structuring client-side data better, using icon sprites everywhere, and so on. Then came multi-day events, the first major feature I built with Mirjam as product manager; until then, Malte had led the product.

Calendar with selected date ranges
Selecting date ranges for multi-day events
Start and end time inputs for each date range
Time proposals for multi-day events

In early 2015, iOS development moved in-house, a new office opened in Berlin, and Matthias took over from Malte as web product manager. An Android app was in the works as well.

A new mobile web app

In April 2015, we started building a new mobile web app, designed by an external agency since we had no in-house designer yet. With Tom, who had recently joined along with Jay, I built a React prototype, benchmarked against a Backbone prototype built by Spyros and Jay. Backbone won on server-side rendering, which settled the stack for the next couple of years: Backbone with a home-grown framework on top, many Jasmine/Karma unit tests, and Cucumber/WebdriverIO integration tests.

Besides building the poll participation page, with its very tricky ad behaviors, and the poll creation wizard, I made a set of existing content pages responsive and made sure new pages were responsive too. Work on the API continued, and I implemented Apple in-app purchases (which were never used). In summer 2015, our small team also redesigned MeetMe as doodle.me, a project that was stopped shortly afterwards.

The mobile web app went live in early 2016 with a completely new look. A mobile-specific version of a service might seem surprising at a time when responsive design was the norm, but that was the decision at the time. Here is what we built.

Old and new

First, the previous version, showing:

And the new Doodle mobile web app, showing:

Some screens are unchanged, and some features are missing. Let’s take a closer look.

Creating and reading polls

Apart from fairly standard forms, poll creation now has a combined date and time selection screen, where there used to be two separate steps. The confirmation screen shown after creating a poll is also a bit more polished.

Combined date and time selection
Poll created confirmation

Fitting in every requirement is not always easy. The EU requires a cookie notice, product management wants an app download banner, and ads keep the service free. Add a long poll description and the screen gets so crowded that the part users actually need to interact with is no longer visible.

Poll page crowded by banners and ads

A poll’s options, the things participants vote on, are shown as a list rather than a table. The most popular option is marked with a blue star, and once the poll creator closes the poll, the chosen option gets an orange star. The row below the blue header gets crowded when a poll has both a location and participants. The screenshots also show how dates are formatted differently for single-day and multi-day options.

Poll with the most popular option starred
Closed poll with the final option starred

Doodle supports several types of polls. In hidden polls, participants cannot see each other’s votes (only the poll creator can). In single choice polls, participants can vote for only one option. Limited polls cap the number of votes per option: with a limit of 2, an option with two votes can no longer be chosen.

Hidden, single choice poll
Limited poll with a full option

Some polls ask participants for additional information, such as a phone number or their full name. And besides dates and times, polls can also be about anything, as simple text options.

Poll asking for additional information
Text poll

In if-need-be polls, participants can answer yes, no, or “if need be”. Tapping an option cycles through the answers:

Languages, errors and spacing

Doodle is translated into many languages, which makes some screens tricky to build. German, for example, tends to need more space for everything, and date formats vary a lot between languages.

Poll in English
Poll in German

Time formats differ too. We only had to handle two grammatical numbers, singular and plural, and only left-to-right scripts. I was curious how hard it would be to support both reading directions, as the WHO website does in English and Arabic, since the whole layout has to be mirrored.

Localized poll, first language
Localized poll, second language

The app shows two kinds of errors: field validation errors, usually detected on the device, and errors returned by the server. The second screenshot is not a great example, since “OK” and “Cancel” do exactly the same thing. There was still room for improvement.

Field validation error
Server error dialog

I care about clean, maintainable code, which rules out pixel values that just happen to work. There has to be a system. Many websites use a grid, but the Doodle app does not lend itself to one. Instead, as the screenshots show, it uses a very small set of spacing units, and lets flexbox handle centering and filling the available space. The app also got a fixed color palette and assets for high-density displays, both long overdue at Doodle.

Spacing units overlaid on the poll page Spacing units overlaid on the poll creation page

Ads

Ads were a large part of Doodle’s revenue, and with traffic shifting to mobile, the new app had to include them. There were four placements, depending on the visitor’s country. We spent a lot of time making sure only one ad was visible at a time and that it stayed visible (“sticky”), and refreshing placements often enough to count more impressions, but not so often that ad networks would penalize us. In the video, ads at the top alternate with ads at the bottom depending on what the user does; there are also full-screen ads and static ads within the content.

Under the hood

The redesign also made several static pages responsive, such as the privacy policy and the about page.

The app used a new, cleaner API, the same one built for the native apps. The codebase was much better structured, and test coverage was excellent, with over 700 tests.

Test coverage report
Test coverage of the new mobile web app, code-named “Stingray”

For compatibility with the rest of the codebase, we used Backbone and RequireJS, solid if not fashionable choices, and Sass with Compass for CSS.

Limits

When the new mobile experience went live in early 2016, poll creation was only available in the UK, the home page, closing a poll and the poll list were still on the old version, and many features were only available in the desktop view. The result was an inconsistent mobile experience. A change in company priorities then froze development of the mobile app, before it got a new dashboard and home page, and it only worked in browsers that supported flexbox.

The redesign

In early 2016, the mobile web app (code-named Stingray) gave way to a complete redesign of doodle.com. It was initially planned for desktop only, but the engineers argued for reusing the previous year’s work, effectively adopting a mobile-first approach.

We also worked style-guide-first: we built reusable components, showcased them in a style guide, and then replaced the existing elements in Stingray with them. It went smoothly, helped by the decision to finally drop server-side rendering. We also adopted SVG sprites and experimented with moving the frontend build to webpack, which brought dependency management, faster builds and ES2015.

Redesigned Doodle on desktop
Doodle on desktop, as designed in 2016
Redesigned Doodle on mobile
Doodle on mobile, as designed in 2016

With the backend almost entirely frozen, I could focus fully on frontend development. Step by step, we worked towards feature parity with the existing doodle.com. I worked on:

Table comparing header variations before and after the redesign
Header variations before and after the redesign
The home page at widths from 320px to over 1300px
The responsive home page at each breakpoint
The unified poll view, switching from list to table as the window gets wider

Team practices

I believe code knowledge should be shared across the whole team, which is why I read every commit to Doodle’s main repository. That is not something I expect from everyone, so I started doing consistent, structured code reviews on GitHub and convinced the team to do the same. With Tom, we then formalized the use of pull requests, which I am sure did a lot for code quality. I also started referencing Basecamp to-dos, and later Jira issues, in commit messages to give code changes more context. I brought that habit from my previous job; it took some getting used to at Doodle, but it stuck.

As Spyros once pointed out, I was something of a behind-the-scenes scrum master, picking the parts I was interested in. I never wanted to write retrospective minutes or prepare demos, but I did start documenting the web engineering process.

In 2017, I led recruiting for two frontend positions, which became three, then four. I learned a lot, and we did reasonably well, though there was room for improvement, especially in speed. I am particularly proud of having brought a woman developer onto the team.

Chart of average days to reach each hiring stage
Average number of days from application to each stage of the hiring pipeline
Time to fill and time to hire for the frontend positions
Time to fill and time to hire for the four frontend positions