At its core, Linc provides a pretty easy-to-grasp capability: A unique URL for every commit, against every backend. And while that capability might be easy to grasp, the implications are wide-reaching and unexpected.
Now Linc has been in public beta for a couple of months, we've been collecting some stories from our customers (and from within the team) about surprising & unexpected ways that Preview Links are being used. We're always looking for more stories & case-studies, so if you have any to share, get in touch.
So here are the first 10 surprising ideas that might you might like to try out with Linc:
- 1. Involve non-developers in UI decisions
- 2. Debug a production edge-case
- 3. Performance problems in production
- 4. Usability & performance testing on real devices
- 5. Automatic browser screenshots
- 6. Set up a Demo environment that works without authentication
- 7. Pre-release for your best customers
- 8. Tracking down a regression
- 9. Reverse-proxy a Ruby on Rails site with a new frontend
- 10. Smoke tests using Cypress
1. Involve non-developers in UI decisions
The first one is one of my own new favourite habits: as a frontend developer myself, I'll often see two or three alternative implementations when working on a new feature. That might be reordering some UI element, choosing how something wraps on a smaller screen, or something as simple as aligning something left or right or choosing how to visually emphasise a call-to-action. As a developer, I'm usually not the best person to make the final call as to which choice to make. That's where Linc comes in.
I can build it one way, commit & push, then try an alternate design and commit & push that too. Linc will give me two URLs that I can now send across to a designer or product owner to make the call. They can open those links on whatever device, in whatever backend environment, and really use the product in each of those states, and make the best-informed decision possible.
Best of all, this process is now asynchronous. My decision-maker doesn't need to be interrupted, and just as crucially, I don't need to wait. I can move on with building the feature and
git revert the version that they didn't choose, or, if I set up a multiple branches, merge or delete the branch with the alternate design. I really like working this way.
2. Debug a production edge-case
One of our customers had a really frustrating bug—one of their users, trying to access a particular page, would hit a JS exception and the UI would crash out. The error was reproducible but only under the one specific circumstance—it had to be production data, and it had to be that one user. Worse still, the application wasn't flaky, there was plenty of error-catching code that should have been handling any unexpected data coming from the server, but this was somehow bypassing it.
There was a discussion about the best way to recreate the conditions for the failure somewhere they could better observe the JS itself. Due to the nature of the system, the best case looked like cloning the entire production DB down onto a development machine and running that locally, until the team realised that Linc might be exactly what they needed.
Each Preview Link that Linc generates can be linked against any of your backends—usually that means during development you'll use a Staging or Testing environment as the default then switch to the production API when doing a pre-release QA check. But in this case, creating a branch with a bunch of debug logging, committing & pushing that gave the team exactly what they needed—a forensic trace of exactly what was going wrong. No infrastructure changes necessary, the fix was identified and deployed straight away.
3. Performance problems in production
Continuing on with the theme of production edge-cases, one of our customers has a vastly different amount of data in their Production environment than the Staging one they use for development. That means that deploying to production often acts as a stress-test of the performance of the React code they're writing. Sometimes it's a JS-specific optimisation that needs to be made, sometimes the JS is fine but the DOM becomes the bottleneck, there's no easy way to look at the code and anticipate how it'll perform under load.
One option would be to fill the staging server with so much data to really test the performance of features as they're being developed, but that has a major drawback—your code is now preoccupied with performance and new ideas or workflows that really suit your users might never be attempted. Experimentation is at the core of a good UI design methodology, only once your team decides that an idea is worth pursuing should performance become a guiding principle.
This team now uses URLs against Staging during development for faster iteration and experimentation, then Production URLs before merging & releasing. This makes sure that performance problems are caught before their users are impacted, without stifling creativity.
4. Usability & performance testing on real devices
Developers, like anyone really, only reliably do whatever is easiest. Some will do more, but in general, what's easy is what gets done. Take code review for example: to properly review a feature you need to stash your own changes, pull the new code, rekick your development environment and step through the new feature to see if it works. It might only take a few minutes, but the disruption to flow, and the fact that it messes up your (potentially fragile) local dev environment, means that all too often code reviews review only the code, not the feature itself.
The same idea applies to on-device testing. One of our customers has a product with a relatively high proportion of users on older or lower-specced mobile devices, and wanted to build discipline around testing on these devices before shipping anything to production. With Linc, since there's always URLs for each commit being generated in the background, any time an on-device review needs to happen, the URL is already there. That's been enough to lower the friction to make these tests a habit, rather than a burden.
5. Automatic browser screenshots
Following on from the above, testing a feature in more than one browser should absolutely be more common than it is. As a loyal Firefox user, it's not uncommon to hit browser-specific bugs on fairly major web apps because their developers only use Chrome. And as disciplined as I might be, I still find myself accidentally shipping UI that looks broken in Safari, simply because I don't test it regularly enough.
For example, this was Linc's UI a few months back in Safari:
Safari treats "transparent" in CSS as "black with 0% opacity", which means gradients from white to "transparent" go through a series of semi-transparent greys. I knew this, I've been bitten by this behaviour before, but I still made the mistake without realising, and it was a customer who brought it to my attention. 😬
Services like BrowserStack and Sauce Labs make it trivial to get a screenshot of a webpage in whatever browser you want. If you know that a particular browser is a blind-spot for your team (IE11, perhaps?), you can paste in a Linc URL and get a screenshot as part of a code review process. This works surprisingly well: browser breakages will usually be immediately apparent from a screenshot: either the UI looks drastically wrong or there might be no UI at all, which means your JS has probably exploded.
For the moment, this is a manual process, but integrating these services automatically is definitely on the roadmap. Let us know if you'd like to be a beta tester of this feature and get early access.
6. Set up a Demo environment that works without authentication
One of the tricky things with a modern JS web application is that all of the complex UI is usually only visible once you're logged in. Certainly, browser or device testing is made more difficult if you can't reach the section of the app you want to test without stepping through the log in process.
We've solved this by creating a "Demo" environment, which we document in detail in our recent blog post. But as a summary, this environment sets our API to a "Demo" backend, which proxies our normal Production backend GraphQL API, with the following alterations:
- All mutations are disabled, making this "backend" read-only.
- No authentication is required, all requests have a demo user account's credentials added before being forwarded to the real backend.
This has two really massive benefits for us. Firstly, it gives us URLs to be using for BrowserStack or a test device without us having to log in to our real Linc accounts. But more importantly, it gives us a way for potential customers to see how Linc works without having to create an account themselves. And it's kept up to date—the URL https://linc-front-end-demo.release.linc-preview.sh is a permanent link to our exact Production release, just in the Demo backend (readonly, no auth needed).
That's a Release Preview URL by the way, there's one for each Environment you set up, in case you want to do the same sort of thing:
7. Pre-release for your best customers
Sometimes, it's not a separate environment you want to share a URL to, but a separate branch—maybe one that tracks the features that are coming up. We have one customer that uses a
next branch that sort-of sits between
master, and they make use of Linc's Branch Preview URLs:
This URL will track whatever is merged into the
next branch, the same way
master is automatically deployed to their production infrastructure. It means they can give a subset of their userbase a preview of what's to come, ask for their candid feedback, and start to genuinely involve them in their product development.
In future, Linc will allow you to run a cohort of users on a prerelease branch like this in production, under your production URL. If that sounds like something you'd be interested in, get in touch.
8. Tracking down a regression
This one is ours, somewhat embarrassingly. Early on in the Linc project, our homepage had a CSS bug which we didn't notice for a few days. Several of us were pushing to different parts of the site at the same time, and suddenly the homepage was all wrong.
Our strategy: open each Preview Link for that project going back 4 or 5 days in its own tab. Switch between them all, find the first one that was broken & follow the link to the commit responsible. Once we knew that the visual bug was introduced in this particular commit, what seemed like an innocuous CSS change was revealed to be the culprit. It ended up taking us no more than a few minutes to find, understand, and fix the bug.
This is one of the benefits to Linc and the FAB ecosystem. FABs are so efficient that we never have to remove old ones—they're always there, just in case you need them.
9. Reverse-proxy a Ruby on Rails site with a new frontend
This is a fairly advanced use-case and needs a fair bit of detail to explain, so expect to see a blog post, case study & a tutorial in future on this topic, but it's probably the most unexpected application of Linc so far.
One of our customers has a product running on Ruby on Rails with the most complex UI sections built as a Single Page App in React. There's still multiple pages (like the homepage, and the sign in form) that are still fully Rails-rendered, but once you're authenticated you get a SPA-like experience. They plan to transition to a fully-decoupled Rails API and React frontend, but they don't have to to get the benefits of Linc for their frontend.
Since FABs can have a full server-side component, we were able to create a small JS server that proxies their staging Rails environment and injects the latest React JS & CSS bundles. It lets them iterate just as fast as any other team on their UI, without having to massively upgrade their Rails deployment infrastructure or drastically change their app's architecture.
We think that's pretty neat, and we're in the process of open-sourcing some of this logic and will be talking about it more widely in the coming months. But as always, if you want to chat about this use-case right now, shoot us an email.
10. Smoke tests using Cypress
To round out our list, I thought I'd add a use-case we're exploring with Linc right at the moment with a few customers—the ability to run an automated smoke tests on bundles before releasing to customers, using Cypress.
If you haven't heard of smoke tests, they're fairly unsophisticated but incredibly valuable end-to-end tests. For a modern frontend app, it could be as simple as navigating around every page in your app and looking for JS console errors. This looks for fairly catastrophic bugs where, say, an entire page doesn't load. In other words, to find out if your app is on fire, look for the smoke.
Since every commit is deployed against each of your backends, you can coordinate as much or as little testing for each as appropriate. For production, you obviously don't want to be making modifications, but something akin to a smoke test might be just right.
This is an area of active development and if you'd like to be involved, just get in touch and let us know your use case.