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

notes by Adam Sullovey

web & mobile application developer
practicing in Toronto, ON

Adam's face

Come find my face at a meetup in Toronto

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 Coalesce Submissions Screenshot

    Students submit work in this app

  • Seneca Coalesce screenshot

    Their work is displayed at the grad show in this app

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.

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

Also in 2017

2016 Projects

Firebase Presentation @ Full Stack Toronto Meetup

  • show me the slides!

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.

writer, presenter
impress.js, rxjs, Firebase
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.

game developer, designer, marketer
App Store & Google Play

Leaflet Learning course mentor

  • Feedback example

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
Oddly Studios
CodePen.io, Leaflet Learning

Leaflet Learning web app

  • Screenshot of Leaflet Learning's UI

Leaflet Learning is a tool designed to make it easier for teachers and assistant to deliver personalized feedback & challenges to students online. It’s also my largest AngularJS project to date. It will continue to grow and gain features through 2017 as new students, mentors, and instructors join for more classes.

What I learned

This project truly lived up to release early, release often. The iteration was so early it didn’t have a name or hosting - it ran right inside of CodePen. We added features as requirements emerged rather than thinking ‘Wouldn’t it be cool if…’ based on nothing concrete as we did with a previous prototype.

I learned that storing as much state as possible in Firebase and letting angularfire sync it simplifies your factories and services… until you need to derive data from that state (e.g. combine 2 collections into one) and keep that data synced as well. Then you end up with a lot of Firebase listeners and have decisions to make about when they start and stop listening for changes in the database.

When I wanted to allow long-term caching of .js bundles by hashing file names, I learned how to use html-webpack-plugin to add paths to the .js bundle files at build time. This takes 100s of kb worth of load time off initial visits to the application.

This project introduced me building UIs with components with Angular 1.6’s component object. The complicated syntax pushed me to try React!

Oddly Studios
contributing front-end and back-end developer
AngularJS, ng-material, Firebase, webpack, Gulp
CircleCI, AWS S3 and CloudFront

York Region International Student Guide iOS & Android app

  • Screenshot of York Region International Student Guide

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.

web/mobile developer
Oddly Studios, Seneca College, York Region
Ionic 1.x, Lunr, Node.js, Google Translate API, xcode, Android Studio
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?

another company
sole web developer
Node.js, Express, Passport, Inform7

Also in 2016

  • tried out Google Analytics Experiments with AngularJS
  • updated Nordica Cottage Cheese contest for its 3rd annual run with Oddly Studios & Agency59, now with webpack instead of grunt and a milking mini-game
  • updated the Gay Lea Advent Calendar contest for its 2nd run with Oddly Studios & Agency59
  • rebuilt of oddlystudios.com with Jekyll, Gulp, and Materialize CSS
  • developed 1 online quiz site with full-screen page transitions
  • created 2 CMS-backed websites for local businesses
  • created 1 proof-of-concept game portal backend using SQLite, Firebase, K’nex, and Express
  • developed 1 proof-of-concept dashboard integrating CodePen and Basecamp to help teachers manage coding classes

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.

  • a person shooting a target with a water cannon

    RaspberryPis mounted above the targets take pictures of players as they shoot water cannons to raise the trucks.

  • people looking at pictures of themselves shooting the water cannon

    When the game is done, players can see their photos embedded in ‘wanted’ posters on the big screens, and use an iPad to save the poster 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.

lead developer, on-site support
Oddly Studios, MacLaren McCann
RaspberryPI, Node.js, Express, MongoDB, Flash, YouTube API, socket.io, AngularJS, FFmpeg
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.

  • slot cars on a race track

    Cars zoomed by our RaspberryPi-based sensors in the track which triggered voltage changes on the copper tape to control speed, video stream source changes, and updates on TV screens, iPads, and phones connected to the track.

  • crowds in line to race

    Big crowds meant the races to flow smoothly to keep the lineup moving.

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?

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

Whistler Lift Status Kibana dashboard

  • graphs and charts showing lift speeds

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

sole developer
Node.js, ElasticSearch, Kibana 3
Heroku, Bonsai

Gay Lea Advent Calendar web app

  • Screenshot of Gay Lea Advent Calendar UI

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.

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

AltLit.ca website

  • AltLit.ca screenshot

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.

Drupal developer
Oddly Studios, CNIB
Drupal 7.x, SASS, Gulp

Also in 2015

  • Second round of Nordica Cottage Cheese campaign with Agency59, now with sounds courtesy of Sound.js

2014 Projects

Nordica Cottage Cheese contest web app

  • Nordica Cottage Cheese Landing Page

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.

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

Also in 2014 with Oddly Studios

  • 1 HTML5 game, data capture form, and coupon generator for a heavy equipment company using Node.js, Restify, SASS, Grunt, and ImageMagick
  • 1 Google Agency Day consulting gig
  • 1 marketing site for soup using Laravel and AngularJS
  • 3 digital signage videos for a bank
  • 1 set of Flash banner ads for a non-profit organization
  • 1 WordPress site rebuild for a local marketing recruiter

And some personal projects

2013 Projects

    Some projects with Oddly Studios

    • ported Kia Poster Maker from desktop to iPad, finding memory leaks with Selenium along the way
    • 3 sprints of new features added to a native Android app
    • 1 Facebook web application for sharing those posters
    • 1 content refresh of a Unity3D game for an eyewear company
    • 2 interactive Flash animations
    • 1 Twitter stream-watching site for a fast-food burger launch
    • 1 web series launch site
    • 1 native Android app adapted for the Amazon Kindle Fire
    • 10 car parts modeled for 3D printing at auto shows
    • 1 Twitter stream-watching app for contests to win 3D printed car parts at auto shows
    • 1 data-collecting Facebook app

    …and some personal projects too

    • I rebuilt my game Gnarshmallow with Unity3D and released the first version for Android on Google Play
    • 1 consulting job on a Unity3D game
    • 1 3D animation for a ski resort
    • 2 personal site rebuilds

    2012 Projects

    Kia Poster Maker

    • screenshot of the poster maker

      The app encourages auto show visitors to make their own digital posters by arranging graphics on a canvas with their fingers.

    • A family playing with the poster maker at one of the auto shows

      Our application traveled with the Kia booth to auto shows all around Canada.

    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!

    front-end developer
    Oddly Studios, SugarMedia
    Easel.js, Backbone.js, Underscore.js, RequireJS
    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

    • 1 Facebook web application for sharing posters made with Kia Poster Maker
    • 1 Facebook web application for talking about cars for a car brand
    • 8 interactive Flash animations for an employee incentives program
    • 1 website header for a Canadian lottery corporation
    • 1 geolocation-checking Twitter bot for an energy bar brand
    • 1 web application for demonstrating the effects of various types of vision loss
    • 1 Facebook profile photo decorator web application

    …and some personal projects

    • 1 last-minute banner ad fix for a footwear brand
    • 1 3D animation for a ski resort

    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.

    lead developer in a team of 4
    Oddly Studios, someone else
    Laravel 1.x & 2.x, Apache, PHP, MySQL
    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.

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

    Also with Oddly Studios

    • 2 interactive Flash animations for an employee incentives program
    • 1 webcam-aware Flash application for a beverage company
    • 1 Twitter stream-watching geolocation-aware Flash marketing site for a tea company
    • 1 Facebook contest web application for a men’s grooming product company
    • 4 websites for a summer marketing campaign for a car company

    …and some personal projects

    • 1 Facebook contest web application for Camp of Champions
    • Consulted on the Android version of the Camp of Champions mobile app

    2010 Projects

    Personal Projects

    Projects with Oddly Studios and other clients

    • 1 widget to advertise cabinets
    • 1 microsite for an unreleased cell phone
    • 1 microsite integrated with an existing website’s comment & news posting system
    • 1 Facebook fan-page tab
    • and many more projects lost to unplugged SVN servers and closed Basecamp accounts

    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.

    • 1 search-engine friendly Flash-based website for a data-centre company
    • 1 search-engine friendly Flash-based website for a marketing agency
    • 1 profile picture bobblehead generating Facebook app to remind people not to drink and drive
    • 1 desktop application for distributing images of various skin conditions to doctors
    • 1 widget for a printer/photocopier company
    • 4 microsites for various companies and products
    • 1 financial trivia game for a Canadian bank
    • 1 desktop application for uploading big video files in chunks to a media website
    • 1 microsite integrated with an existing website’s comment & news posting system
    • 5 videos demonstrating new ski technologies for a sporting goods company

    2008 Projects

    Personal Projects

    • The first version of my game Gnarshmallow went live for desktop browsers.

    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

    • dozens of banner ads
    • multiple car microsites
    • and many more projects lost to unplugged SVN servers and closed Basecamp accounts

    2007 Projects

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

    • lots of Flash banner ads for Sprint, Dodge, Jeep, and Chrysler
    • lots of Sprint Cellular microsites
    • lots of Chrysler/Dodge/Jeep HTML Emails
    • model year refreshes of chrysler.com/dodge.com/jeep.com websites