icon sc-linkedinlogo of codepen-iconlogo of github-iconyoutube play button

Adam Sullovey
web & mobile application developer
practicing in Toronto, ON

Adam's face

Come find my face at a meetup,
or online in these communities

In 2017, my focus is on building web applications that solve problems and entertain people.

I grew up modding computer games and making websites to share my work. Building personal sites led to setting up shops, blogs, and CMSs for small businesses as a freelancer, contributing code & animation to marketing campaigns while working in a marketing agency, and developing a huge variety of campaigns and software products while working in a digital production studio.

Things I enjoy

  • making pixels change colour
  • watching data flow around
  • optimizing things
  • the comforting pull of gravity

Things to do in 2017

  • learn more about data structures & algorithms
  • a big review of design patterns
  • more js!
  • present at a meetup

Highlights from my blog

Projects & Roles

I've highlighted projects where I learned the most below.


2017 Projects

Seneca Coalesce Showcase & Submissions applications

Seneca College wanted new software for School of Communications Arts students to demo their work at grad shows. I contributed to architecture, back-end, and front-end development of a pair of applications for students to submit work, and for the public to view work at the grad show.

What I learned

Redux and Firebase can work together! I figured out a way to keep the redux store synced with Firebase database paths I cared about. Once the team was on board with this architecture we could add new sections to the site, database, and store easily. I should open source this!

Where does state get stored anyway? I used redux for state shared across many routes like authentication info and content from the database, and kept smaller bits of state like form field values inside container components' state within the routes. I think this worked well.

Cloud functions are interesting to me as the guy who monitors our Node.js services on other projects. This application uses them to keep duplicated data in the database synced. I like handing over server administration work to Google's cloud, but I'm still figuring out how to balance the slower script restarts with writing more tests to run locally.

React's ecosystem has useful stuff! I wondered if there would be a library for everything like with angular and jQuery. Dropzone library  is great for file uploads! react-router was a pleasure to use once I figured out the pattern for allowing/denying access to a route. React Developer Tools are helpful! Redux DevTools are very helpful!

Pick and choose your components. This was my first time using the material-ui library. Using some of the larger components like navigation drawers and cards was very helpful, but I feel that simple things like navigation links and form fields are better done the simple way with minimal CSS and HTML elements for better performance & accessibility.

collaborators:
Oddly Studios, Seneca College
role:
lead developer in team of 3
tools:
React, Redux, React Router v4, create-react-app, material-ui, webpack, Firebase
deployment:
CircleCI and Firebase Hosting

Also in 2017


2016 Projects

Firebase Presentation @ Full Stack Toronto Meetup

After using Firebase in several commercial projects, I felt comfortable giving a 30-minute presentation to ~40 people in the Full Stack Toronto Meetup Group on the pros and cons of integrating the database with projects. The talk went well! I was able to answer questions afterward and write a follow-up blog post.

What I learned

Presenting will change how you think. Rewinding my brain back to Firebase beginner meant questioning assumptions I had built up after working with the product. Preparing for this forced me to understand Firebase security rules better, try out tools like Bolt, and be up to date on API changes like the addition of Promises returned by updating/setting data.

Impress.js makes me want to support markdown everywhere. I never considered it would be useful for building slides, but it helped me stop thinking of code and start thinking about content in the context of slideshows.

Roles:
writer, presenter
tools:
impress.js, rxjs, Firebase
deployment:
Full Stack Toronto February Meetup (February 3, 2016 at Street Contxt)

Gnarshmallow for iOS

I finally released my skiing game on iOS! This year I got the paperwork sorted and was confident that the game had enough substance to pass Apple's app review process. It made it through on the first submission!

Get it on Google Play

What I learned

It's all in your head! If you release a game and it sucks, it probably won't get noticed and you'll go try again. However, trying again is key. If you can't release often, don't release early.

roles:
game developer, designer, marketer
tools:
Unity3D
deployment:
App Store & Google Play

Leaflet Learning course mentor

I provide 1-on-1 feedback to over 20 students on their projects every week. I read their code, test it, and provide or hint at bug fixes and opportunities for improvement and learning.

What I learned
collaborators:
Oddly Studios
role:
mentor
tools:
CodePen.io, Leaflet Learning

York Region International Student Guide iOS & Android app

This app distributes info for students coming from abroad to study in York Region.

Get it on Google Play
What I learned

Screen scraping content from a desktop site managed by an enterprise CMS and hoping it will fit right into a mobile app is naive. I worked with Cheerio and lots of regular expressions to remove unnecessary markup and content.

Google Translate API has low maximum length limit. I had to create tools to divide pages of text into small chunks at paragraphs breaks (not mid-sentence), run the chunks through Google Translate, and then stitch them back together into HTML documents.

Lunr.js is really cool. It's a JS search engine you can embed in your application. This app uses it for offline search.

role:
web/mobile developer
collaborators:
Oddly Studios, Seneca College, York Region
tools:
Ionic 1.x, Lunr, Node.js, Google Translate API, xcode, Android Studio
deployment:
App Store & Google Play

Persistent online text-based adventure game

A local creative agency had the idea to market to IT groups with an old-school text-based adventure game that would run in the browser. I worked with an Inform7 developer to integrate the HTML/JS game engine with a modern web application backend so that the game and server could communicate to save progress, trigger events, and let players communicate with each other. And then the project was canceled.

These are some progress bars and activity indicators I animated that never made it into the application. Unlike the Unix applications the game was inspired by, web applications need to tell their users when they are waiting.

What I learned

The conversational nature of Slack makes it easy to get to know your team mates on new projects, but constant notifications of unknown levels of importance can be very distracting. Exercise self control, and be careful about which rooms you chat or work in and when to tag people.

TODO Inform7 integration is neat, I don't think this ever been done before. Can I open source?

collaborators:
another company
role:
sole web developer
tools:
Node.js, Express, Passport, Inform7
deployment:
Heroku

Also in 2016...


2015 Projects

GMC Sierra Proshot installation

I lead the development of a custom photo-booth solution attached to a GMC-branded carnival game at the Calgary Stampede. The project used 5 RaspberryPis (4 with the camera module), 4 iPads, 1 Ubuntu server, and 4 40" LCD screens to take photos of game players, embed them in a western-style Wanted poster, and let players email or SMS the posters to themselves as a souvenir.

I worked on network communication, snapping photos and storing them, generating the wanted posters, and API calls to Mandrill and Twilio. I integrated that with an HTML/CSS/JS UI made by another developer. A fabricator created the waterproof casings for the cameras, and I worked with the project manager to set up all the physical hardware on site at the game.

What I learned

Watching people laugh and enjoy using your work is way more rewarding than judging engagement by looking analytics.

Try headless browser screenshots instead of ImageMagick. If learning ImageMagick's CLI to compose images is driving you crazy, consider composing them with HTML and CSS, and loading the content into PhantomJS to save a screenshot. This will run much slower and eat up more server resources, but could save lots of development time. For this project, time to market was a much higher priority than shaving seconds off the speed we could compose photos inside the Wanted posters.

The RaspberryPi camera needs time to adjust to lighting, it takes better pictures when it has a few seconds to adjust exposure between turning on and taking photos. Tweaking this delay gave us huge improvements in photo quality.

SSH Tunnels will save the day. I learned how to set up tunnels so I could get access each machine in the system from far away in Toronto. I expected our little network of things would be buried in the Stampede Ground's network, so set this up in advance. The tunnels worked great! I could log into an EC2 server from anywhere, and then log into any of the machines in the photo booth's network through that.

The value of a good wiki! The project following this used even more RaspberryPis and cameras. Writing down everything new in this project's GitHub wiki made the next project go faster.

If you don't provide Facebook's crawler with an image size along with a URL in og meta tags, it won't display the share image on the first share because Facebook doesn't know what size the image is yet. I wrote a script to make Facebook visit each poster that could be shared at the time it was generated so that it would share reliably when a human tried later.

role:
lead developer, on-site support
collaborators:
Oddly Studios, MacLaren McCann
tools:
RaspberryPI, Node.js, Express, MongoDB, Flash, YouTube API, socket.io, AngularJS, FFmpeg
deployment:
installation was live at Calgary Stampede for 2 weeks

Chevrolet Power of Play installation

This gigantic slot car racing track was powered and controlled by humans pedaling bikes. Extra energy generated by the players was stored in a stack of Chevrolet Volt batteries as a demonstration of their potential use after finishing their service life in cars. I contributed code to its many components, and worked on-site to keep races going smoothly by patching bugs, fixing loose wires, scrubbing copper, and tweaking brushes.

What I learned

clean socks are underrated

mongodb-queue is good enough for managing multi-step workflows at our scale. It's also easy to get started with if you are already familiar with MongoDB. I used it for running the track's video sharing workflow which was:

  1. download a video
  2. process it with FFmpeg a few times
  3. upload it to YouTube

TODO Dealing with YouTube API Refresh tokens

TODO Programmatic screen recording on Windows with that software with a CLI... http://www.deskshare.com/video-screen-capture.aspx?

role:
1 of 3 developers, on-site support
collaborators:
Oddly Studios, MacLaren McCann
tools:
RaspberryPI, Node.js, Express, MongoDB, YouTube API, WebSockets, PhoneGap
deployment:
installation was live on CNE Grounds for 2 weeks during Toronto PanAm games

Whistler Lift Status Kibana dashboard

After using the ELK stack to monitor servers for a few applications, I decided to try putting data from Whistler Blackcomb's lift status XML into Elastic Search so I could view it in Kibana and get first chair more often. Source code is on GitHub

role:
sole developer
tools:
Node.js, ElasticSearch, Kibana 3
deployment:
Heroku, Bonsai

Gay Lea Advent Calendar web app

This web application is part of a holiday marketing campaign for Gay Lea Foods Co-operative Ltd. Users register and return every day to open doors, view recipes, and win cookies.

What I learned

1 less API server is 1 less thing to worry about. Inspired by large websites that handle as little user interaction synchronously as possible, I decided to try using firebase-queue to handle registering new users, saving contest entries, and other user actions that write to the DB. It worked! Instead of running a public application server with an exposed API, I just needed a static file host and a private server in the background processing jobs from the queues with Node.js. This made my job easier. Firebase was fast enough to do this without making users wait for more than a second to see a change in the UI when info in the database changes as the result of a new job going into the database.

ngAnimate is flexible. I hesitated to build animation-heavy websites with AngularJS for a year, but diving in with this project proved the framework was not going to limit me. Every screen in this application has a transition animation. Some screens have TweenMax-powered animations on them. Opening up a door in the calendar plays a CSS animation that zooms in on the specific door you clicked & loads images during the animation. I was able to find docs that helped me out with all of this, and some motivation from watching Mattias Niemelä's talks at Toronto meetups.

role:
lead developer in a team of 2
collaborators:
Oddly Studios, Agency59
tools:
Firebase, AngularJS, Node.js, webpack, SASS
deployment:
CircleCI, AWS EC2

AltLit.ca website

AltLit.ca is run by the Canadian National Institute for the Blind. It provides alternate reading materials for kids and teens with vision loss. I translated the designer's .psd file into a responsive Drupal theme while adding accessibility features and setting up the structure for the site's content.

What I learned

This website needed top-notch accessibility. After spending time building Unity games, physical installations, and digital signage I had to learn more about what makes a site easy to use for people with vision loss. The site has Drupal modules for adjusting font size and contrast, but two other features caught my eye.

Contrast! Contrast guidelines provided by WCAG and tools like WebAIM's Colour Checker were extremely useful in the early design phases of the site. I could look at the palette and design samples provided and decide which colours could be used beside each other.

Skip to content buttons are helpful. Before this project, I'd never noticed them on many websites. I learned about it from the Drupal Theme that AltLit.ca is build on top of, and now it is something I consider adding to everything I make.

role:
Drupal developer
collaborators:
Oddly Studios, CNIB
tools:
Drupal 7.x, SASS, Gulp

Also in 2015


2014 Projects

Nordica Cottage Cheese contest web app

This Nordica Cottage Cheese contest is part of a marketing campaign for Nordica cottage cheese. Players sign up, choose and name their bobble-headed cow, and then return to the application every day to milk it and earn entries in a contest.

What I learned

Unit testing is like time travel. All the rules about whether a player can play at a given time to earn another entry are based on dates. When did they play last? Is it a weekend? Is it Friday on the last week of the contest? Unit tests let me run hundreds of tests against the rules with different timestamps to find bugs. The alternative was manual testing and changing the system clock which is a huge waste of time.

The Elastic Stack (or any monitoring, really) is wonderful. EventMobi's talk on Continuous Full Stack Deployment talk at a Full Stack Toronto meetup inspired me to set up better monitoring on at the application, web server, and OS level. This helped me track down bugs and made me curious about other tools like New Relic and Sentry.

role:
sole developer, server admin
collaborators:
Oddly Studios, Agency59
tools:
Nginx, PHP, MySQL, Laravel, SASS, Grunt, Backbone.JS, sound.js, Facebook API
deployment:
AWS EC2 via CircleCI

Also in 2014 with Oddly Studios

And some personal projects


2013 Projects

Some projects with Oddly Studios

...and some personal projects too


2012 Projects

Kia Poster Maker

What I learned

I learned how the pinch-zoom gesture works behind the scenes. With help this blog post, I made my own JS implementation that allowed users to translate, zoom, and rotate the poster's graphics on the canvas. I should put this on CodePen!

One constraint was that the car graphics were not allowed going off the edge of the canvas at all. This is easy to manage with circles and axis aligned boxes, but tougher with rotatable rectangles. After messing around with axis-aligned bounding boxes, I finally got comfortable using localToGlobal to check if the corner of a rotated graphic was past the end of the canvas or not. I should put this on CodePen too!

role:
front-end developer
collaborators:
Oddly Studios, SugarMedia
tools:
Easel.js, Backbone.js, Underscore.js, RequireJS
deployment:
8 mini PCs & 32" touch screens, travelling around Canada for 6 months

web application for car fans to comment on pictures of cars

This project was a Facebook canvas application that encouraged fans of a car company's vehciles talk and share and share why they liked their products so much.

What I learned

Leading up to this project, I usually worked on both the frontend and backend of applications with my team. This time, we divided into frontend and backend roles. I worked on the database, administrative tools, and API, while a team-mate took on the public facing front-end of application. I quickly learned not to jump ahead with designing API calls and caching optimizations because what I thought the data the front-end would need to consume was not right at all. My ideas for how JSON should be arranged and when requests are made were different from what my team mate was thinking, so we planned out our API calls and kept the project moving forwards.

Gathering data to show on 1 page of this application could trigger a chain of queries to 7 different tables with joins which was much slower than we expected. I learned about key-based expiration and russian doll caching from the Signal v. Noise blog, and implemented the idea at the model layer. If there was a match in the cache for high level piece of data at a certain date, and a quick check othe database showed that the data in the DB was from the same date as the cache, it was safe to load that data and all data below it from the cache as well. This gave us a huge performance boost.


Also with Oddly Studios


...and some personal projects


2011 Projects

White-labeled Sales Incentive Program application

I lead the development of an application which gamified retails sales peoples' jobs by rewarding them for selling products, learning about products, and talking with other sales people online. The application ran in a Facebook canvas page and used the Facebook API to tie activity in the program to peoples' Facebook accounts.

What I learned

Moving this project from shared hosting to AWS EC2 was my first immersion in Linux. I worked with another developer more experienced with administering servers and learned how set up Apache, SSL, PHP, MySQL, firewalls, fail2ban, and other tools needed to keep a site online. I also set up a virtual machine using VirtualBox for the team to use for testing.

I started this project with the Laravel framework even though it was super young at the time (1.x) because of the friendly documentation and ease of use. This turned out to be great decision. To this day I still value documentation when choosing libraries or frameworks to use with a team.

I learned there is way more to running a web application than serving HTTP requests. This application could generate and export reports, use queues and cron jobs for offline tasks, and communicate with multiple external APIs for analytics and syncing mailing lists.

role:
lead developer in a team of 4
collaborators:
Oddly Studios, someone else
tools:
Laravel 1.x & 2.x, Apache, PHP, MySQL
deployment:
AWS EC2

Transitions Mini-Golf game

In 6 weeks our team went from having minimal Unity3D experience to launching a 9 hole 3D mini-golf game. My job was to take all the 2D and 3D assets from the art team and turn them into a playable game. I also contributed to the HTML and CSS on the page surrounding the game.

What I learned

Collaboration is the only way forward in a project like ths. Building out the levels took hours of back and forth tweaks with the 3D modeler and concept artist as we changed the angles of walls and slopes to ensure a fun game, and the environments surrounding the putting greens to look amazing. Every change we made to the in-game camera's field of view and position relative to the ball influenced the size and position of UI elements which the UI designer tweaked to fit just right.

Tweening engines have a home in 3D too! I was so happy that years of experience using tweening engines in Flash like TweenMax could be applied here too with iTween. This made all the smooth camera fly-bys over the course possible.

role:
lead game developer in a team of 3
collaborators:
Oddly Studios, The Marketing Store
tools:
Unity3D, C#
deployment:
static files hosted someone else's server, embedded in the Transitions website

Also with Oddly Studios

...and some personal projects


2010 Projects

Personal Projects

Projects with Oddly Studios and other clients


2009 Projects

Personal Projects

Projects with Oddly Studios and other clients

Oddly Studios grew, I took on more responsibilities planning projects and leading small teams on the more complicated builds.


2008 Projects

Personal Projects

Projects with Oddly Studios and other clients

My first projects with Oddly Studios went live, and I worked on many more marketing campaigns for big brands with the marketing agencies that hired us


2007 Projects

This year I animated and developed lots of marketing materials while working at marketing agency.