Lessons Learned from Enterprise Grade UX Customization
When I joined the IBM Connections project, it took me little to realize that few or none of our end users were seeing our product as we developed it, i.e. with the default styles and UX. Connections is IBM’s flagship enterprise social collaboration offering, comprising of a suite of web applications, native mobile clients, and a range of plugins and extensions for other IBM offerings like WebSphere Portal.
Connections was born as a Lotus product that could be installed on-premises in the customers’ own IT infrastructure and used in the intranet, but later became the backbone of IBM’s social offering, offered as a solution in a number of flavors and variants, standalone or integrated with other capabilities, e.g. WebSphere Portal, Kenexa Talent Suite, also made available as a SaaS cloud offering.
Our development team was tasked with the unique mission of having to develop and maintain a performant, accessible and globalized product that delivered a compelling experience out of the box, but were also extensible and customizable to meet the customers’ unique requirements for integration, wording, visual design, and extension.
We wouldn’t have been able to deliver on the mission hadn’t we had the support of a few elements:
- An amazingly powerful and flexible style toolkit that provided us with a full range of visual patterns
- Support for resource customization, that let admins override any of the resources used by the applications
- A style guide that provided developers with a live catalog of patterns and widgets
The OneUI Toolkit
I had the pleasure to collaborate since the start with a small team of clever front-end developers who produced the Lotus OneUI Toolkit, a CSS framework that implemented BEM before it was a thing — albeit without the block__element — modifier syntax, but a camel cased one, e.g. .lotusPost, .lotusPostAvatar, .lotusPostAuthorInfo. Chris, Matt, Mike, you’re awesome. The Toolkit produced styles for a number of supported layouts (two, or three columns, plus special pages) and an extensive set of components, from buttons to menus, from banners to flyouts.
The OneUI style guide had some dynamic behavior, in that it loaded patterns in <iframe>’s thus allowing the container page to load different content based on URL parameters, enabling prototypers to use it as a test bench while coding the very styles. The dropdown menus for language, directionality, and base text size are absent from the public style guide, but you can still request them manually.
Runtime aggregator
Another precious ally in our quest for total customization was the use of a runtime resource aggregator built on an OSGi architecture that could crawl, inline and serve all resources that could be parsed and described as a graph of dependencies. The Connections dev team in fact forked the Rational Team Concert SDK “Jazz” framework and added support for resource-by-resource customization.
At the peak of its heyday our resource aggregator was able to crawl and aggregate JS files via AMD require() or the Dojo Toolkit’s dojo.require(), and CSS files via @import. It could also customize file by file JS and CSS resources, as well as HTML templates, Java .properties files for localized strings, and plain text files.
A living style guide
To the maximum extent possible, we arranged and organized our library of UI patterns and widgets into a live style guide. A living style guide is like a catalog of patterns implemented with HTML and CSS, but also made live by JavaScript to match the end user’s interaction. Since our applications were mostly single page JS apps, using Dojo widgets heavily, this meant the pages were often simple launchers for widgets with a number of variations of configuration settings.
We got as far as reaching a point where we were doing true Style Guide Driven Development as popularized by Nicole Sullivan, in fact we mostly used this approach to publish a catalog of existing patterns to aid our refactor from legacy Dojo module system to AMD, and used the pages of the live style guide as test rig to execute end to end tests with WebDriver.
The reality
While we set everything up in theory, in practice we had underestimated the creativity of our users. Some cracked open, modified and repackaged our themes, others figured out a way to inject their app inside one of our pages after stripping it out of content.
I had a sudden flashback while I was reading the brilliant article Building an Enterprise CSS Framework by Salesforce.com’s Stephanie Rewis who states:
Salesforce partners wanted their apps to have a Salesforce look, but many didn’t have the resources or developers needed to make it happen, and those that did were inspecting in the browser to reverse engineer our code. A version of Bootstrap with a Salesforce look was created, though not by us, and it quickly fell out of step with our changing designs.
We had an even worse problem. Since we committed to let our customers create visual themes that matched their corporate identity by overriding our styles, it meant that we couldn’t alter the structure of pages without breaking all of our customers’ custom themes. This had a negative impact on our own internal development as well, as visual theme updates like the gen4 theme had to be markup-compatible with the existing UX.
Lessons Learned
All in all, it was a continuous learning process that taught us the hard way. During that experience, we learned many important lessons that I’d like to write down for my own records for future reference, as well as share them with front-end developers tasked with similar goals.
Namespace your class names
Since our application was integrated in contexts beyond our control, or customers could arbitrarily inject third party styles into pages, namespacing our classes was essential.
This reduced the likelihood of interferences between the product’s own CSS selectors and third party styles’ selectors to a minimum.
In detail, the OneUI Toolkit used the lotus* prefix for all classes, e.g. lotusMain, lotusBanner, while Connections’ own styles had a prefix of lconn*, later superseded by ic-* or ics-* (acronyms of IBM Connections, or IBM Collaboration Solutions respectively[1]).
Style guide driven development is awesome
With a fast paced development schedule, regularly upcoming deadlines, and a physiological turnover of developers and designers in the project, it is essential to facilitate communication between design and dev, as well within the development team at large.
In our experience, developing a catalog of UX patterns proved invaluable to quickly iterate over designs, prototype new widgets or entire pages, and try them out with all supported themes.
While our style guide was never published or shared with customers, it served well as a development tool, also exercised by automated end to end tests in CI, as well as a communication tool to browse and review patterns.
Document and test extension points
A nice side effect of offering extension points was the ability to use them to provide a different UX in on-prem and cloud deployment configurations, e.g. different typeaheads or person cards when used against a multitenant directory service in the cloud.
When your code is shipped to customers, it’s out. You can’t control it anymore. It took us a couple of releases to figure out we’d better document extension points and cover them with automated unit tests, than let customers be creative and choose where to attach their extensions.
As a result, the number of problems reported on the field went down dramatically, as most of the regressions and problems were caught during development sprints.
Let them build it
One of the key advantages of using a runtime aggregator was to enable a single deployment to serve different code to user agents, without knowing a priori what code would be requested. The ability to aggregate and serve minified code on the fly was essential given our product was often integrated in custom-built solutions.
If you don’t have such a use case, you’d better build your resources into layers via Webpack, Gulp, or Grunt, and publish static files to an HTTP server like Apache or Nginx. If you have a requirement to let customers override your resources, share them as open source (your front-end code is most often not your secret sauce, after all) or via shared source agreements, and give them instructions to build them themselves.
Open source your style toolkit
Before CSS preprocessors and build systems like Less or Sass became mainstream, our documentation instructed customers to extract a copy of the CSS from the deployed applications, clone it and modify it, then place it in a location where the the product would’ve read it to replace or extend the default stylesheets.
Open sourcing your style toolkit allows customers to clone, modify and rebuild the stylesheets of the product, as well as lets them make use of the style guide and tests, thus taking advantage not just of the code, but also the development methodology to ensure continuous quality.
[1] These are actually acronyms of acronyms.