Email can be one of the most powerful ways to engage with your users, and can serve a multitude of purposes. It can be used as a way to highlight selected content (weekly/monthly newsletters, ‘year in review’, etc.), provide a service to users (analytics breakdown of visits to your profile/favorites page), or re-engage with users (new feature announcements, etc.). Here at Artsy we use all of these kinds of emails and have found them to be a very valuable asset. However, best practices for template layout and CSS (keeping in mind the variety of devices and screen sizes that your users have) are quite different from, and very far behind, the current HTML5 standards and practices for making beautiful web pages. In this article, I’d like to present some techniques I’ve successfully used at Artsy to create emails that look good on your browser or mobile device, in some of the most popular email clients out there.
As part of our partnership with The New York Armory Show this year, we installed a number of terminals throughout the fair. These screens used our own real-time data to display an ever shifting set of trending artworks, artists, and booths, to the attendees.
Out of this work, we’ve open-sourced Forgetsy, a lightweight Ruby trending library. Put simply, Forgetsy implements data structures that forget. Loosely based on Bit.ly’s Forget Table concept, Forgetsy uses decaying counters to track temporal trends in categorical distributions.
Testing is a critical part of our workflow at Artsy. It gives us confidence to make regular, aggressive enhancements. But anyone who has worked with a large, complex test suite has struggled with occasional failures that are difficult to reproduce or fix.
These failures might be due to slight timing differences or lack of proper isolation between tests. Integration tests are particularly thorny, since problems can originate not only in application code, but in the browser, testing tools (e.g., Selenium), database, network, or external APIs and dependencies.
The Quarantine
We’ve been automatically retrying failed tests, with some success. However, these problems tend to get worse. (If you have 10 tests that each have a 1% chance of failing, roughly 1 in 10 builds will fail. If you have 50, 4 in 10 builds will fail.)
Martin Fowler offers the most compelling thoughts on this topic in Eradicating Non-Determinism in Tests. (Read it, really.) He suggests quarantining problematic tests in a separate suite, so they don’t block the build pipeline.
At Artsy we’ve been building Node.js applications that share code and rendering between the server and browser. We’ve seen many benefits from this – pages load faster, we can optimize SEO, developers are more productive, and JavaScript coding is just an overall better experience.
Today we’re happy to announce Ezel, our open source boilerplate we use to bootstrap our Node projects and the various node modules that built up to it.
In his article, Isomorphic JavaScript: The Future of Web Apps, Spike Brehm from AirBnB describes this growing trend well and we’re excited to be a part of it. In this article I’ll tell Artsy’s story of moving from a single monolithic application to modular Backbone apps that run in Node and the browser and consume our external API.
I recently went through an exercise of upgrading one of Artsy’s largest web projects to the current HEAD of Mongoid 4.x. This is going to be a major release with numerous changes and I wanted to flush out bugs before the final version of the ODM is released. All Mongoid changes currently live on master.
gem 'mongoid', github: 'mongoid/mongoid'
In the process I’ve worked on making a few gems compatible with Mongoid 4 and learned a couple of things that should help you make this process smooth for your own applications.
OpsWorks is a new service from Amazon that promises to provide high-level tools to manage your EC2-based deployment. From the announcement:
AWS OpsWorks features an integrated management experience for the entire application lifecycle including resource provisioning, configuration management, application deployment, monitoring, and access control. It will work with applications of any level of complexity and is independent of any particular architectural pattern.
After scratching our heads about exactly what that meant, we tried it anyway. If you’ve been straining at the limits of your Platform as a Service (PaaS) provider, or just wishing for more automation for your EC2 deployment, you may want to try it out too.
Artsy has been experimenting with OpsWorks for a few months now and recently adopted it for the production artsy.net site. We’re excited to share what we’ve learned in the process.
A whopping 49% of Artsy users have “gmail.com” email addresses. The next domain name, “hotmail.com”, doesn’t even come close, with only 6%.
GMail addresses ignore periods and are case-insensitive. For example, “Donald.Duck@gmail.com” and “donaldduck@gmail.com” are the same account. You can log-in to GMail with both. Users often register with the former and try to log-in to Artsy with the latter. With so many GMail users, expect a dozen support emails per day.
The solution is to normalize these emails into a canonical form.
The Artsy website, Partner CMS, mobile tools, and all our hackathon experiments are built on top of a core API. We’ve put a lot of effort into documenting it internally. But developers don’t want to have to grok through code. With Grape and Swagger, adding an API explorer and exposing the API documentation has never been easier.
TL;DR
Write fast, headless, tests for Backbone using Node.js. See this project as an example https://github.com/craigspaeth/backbone-headless-testing.
A Brief History
Artsy is mostly a thick client Backbone app that sits on Rails and largely depends on Capybara (Selenium backed bot that clicks around Firefox) for testing it’s javascript. This leads to some seriously brittle and slow integration tests. Despite being able to wrangle Capybara to do most of our client-side testing, we knew there must be a better way.
When building a CMS app for our gallery partners to manage their Artsy inventory, we built a new Backbone app on top of node.js. The result was a headless test suite that runs around 60 times faster.
Let’s take a look at how it’s done.
The artsy.net website is a Backbone.js application that talks to a server-side RESTful Grape API sitting on top of a Rails app which serves minimal HTML markup. The latter includes such things as a page title, along with links to JavaScript and stylesheet packages. A page loads, scripts run, data is fetched from the API. The result is merged into a HAMLJS template and rendered client-side.
Building this kind of one-page apps allows for clean separation between the presentation and API layers. The downside is that it will slow page render times - fetching data after page load means waiting for an AJAX request to complete before displaying anything.
There’re many solutions to this problem, all involving some kind of server-side rendering. You could, for example, share views and JavaScript between client and server. This would be a major paradigm shift for a large application like ours and not something we could possibly maneuver in a short amount of time.
Without changing the entire architecture of the system, how can we bootstrap JSON data server-side and avoid the data roundtrip on every page load?