Moving our UI to the next level
This is the first post of our blog series, — the story of building a modern web app.
Building a product is hard, — a balance between writing great code and moving fast. Over the last three years we built Tallie from the ground up. It has the right features, looks good, and used by hundreds of companies on a daily basis. We feel good about where we are at right now.
We are not done yet — perfecting a product is even harder. To deliver the best possible experience we need to solve some exciting engineering problems. For us, this year will be about leveling up our UI and pushing the boundaries of the browsers.
Our current stack
We started with a clean plate. Only had an idea about the product, but no designs or specifications. No front-end codebase or UI engineering team. We shaped the product along the way, and learned a lot.
As a first step, we had to pick our front-end stack.
Building a lean startup means not knowing how the product will look in 6 months, especially in the early days. To get started, we built separate pages for the different parts of the product. Later these pages evolved into complex views, handling lots of data and user interactions. To support this multi-page structure, we chose Knockout.js, which is strong at the UI data bindings. Looking back, it made sense to support the lightwave pages and ensure the application UI is always in sync with the data.
Libraries / Tools
We experimented with a lot of open-source libraries to solve smaller problems. Here is a few that proved to be mature enough for production.
- We built our dropdowns and typeaheads on Select2 and Typeahead.js
- We use SignalR to send down real-time messages to the client side
- Our drag and drop and file upload features are built on HTML5 DND and File APIs.
- Bundler compiles, bundles and minifies our CoffeeScript and LESS files
- Grunt.js runs our unit tests with mocha.js
Over time we learned a lot about these technologies, and how to build a complex web app, — which we are planning to share in the future.
But the front-end industry is moving fast, and there is always room for improvement. Here are a few problems we see coming our way this year.
Single Page Application
To create a more-native-app-like product experience, we are converting to a single page application. This will enable us to create more robust features and make the experience faster.
We are using Knockout.js — powerful with UI bindings, but the rest of the code is on us. A single page app will need a more robust architecture. Either powering up our current view layer, or introducing a new framework for this. Finding one that plays well with the current codebase will be tricky, but not impossible. Durandal.js feels like an obvious choice, since its built on Knockout. Angular 2.0 looks promising, having the best of Durandal and Angular. Flux has an interesting concept, and the Facebook libraries look really strong. We need to pick the one that fits our current architecture the most.
Took us 25k+ lines of LESS to get to the current product — a lot of styling. And a customized Bootstrap 2.3. While there are best practices for complex JS apps, not that many for structuring styling. It will be quite a journey to get our LESS codebase under control again, and upgrade to the latest Bootstrap.
Our back-end is built on the .NET MVC framework, which serves us well. But on page load you have two options — use Razor templates, or dump the data in a JSON and let Knockout display it. While this second way speeds up development, causes some delay on every page load. With Node.js we could use the Knockout templates to render the HTML on the server side.
We all strive for a smooth product experience. Quantifying quality is challenging but there are things we can improve on.
Eliminating all the bugs is hard when moving fast — but better tests can help with it. We already have unit tests for data models; the tricky part will be to expand these to the views. To improve the code coverage we are implementing TDD in the team. We are also adding automated UI tests for more confidence when shipping the code.
The best way to get receipts into Tallie is to use our native iPhone and Android apps. Our users do everything else on a computer, that’s why we tailored that experience. But we understand this is changing and more people will use it on the road. We need to make sure our tablet experience is as smooth as using it from desktop.
As the front-end team grows we need to enhance our processes to foster learning and improve productivity.
Currently Bundler and Grunt split the tasks during the deployment flow. Our plan is to push Grunt.js into the spotlight — compile, minify, bundle and lint code, run unit and automated tests and generate docs. We are also moving all our libraries over to Bower and npm for an easier maintainability.
We have regular code reviews but we need to involve them more in our daily routine. We believe code review can turn into the most important step for writing quality code, and learning from each other.
As we grow more and more engineers asks the same questions — starting a code style guide will help with this. We are a big fan of productivity: no one has time to write docs — well commented code should speak for itself. That said, there are couple of good tools to auto generate docs from code comments that we need to explore and incorporate.
But we are not there yet. We don’t have time to rewrite code just for the sake of rewriting code. Our story is about to find the right way to make our UI a magnitude better. Please join us for this exciting journey.
Follow me @korsosm for more updates.