Building atTendance: TenTen’s Internal HR App

Building atTendance: TenTen’s Internal HR App

The homepage/calendar componentYesterday, I deployed TenTen’s new internal human resources app called atTendance. As TenTen continues to expand, it’s becoming harder for us to keep track of absences. We decided to build an internal app to help us with tracking absences and also give us an internal contacts book. As an intern, this project was the perfect opportunity to have a large stake in a low-risk project that would help me gain a lot of real-world software engineering skills.


One of the earlier (now rejected) mockups that we builtThe first week on the job I spent with my team designing the UX of our app. We wrote user stories centring around both managers and employees. As we imagined these potential use cases, we started our wireframing the app with balsamiq. As the user stories grew, the app started coming together. The app would consist of two main components: a ‘users’ section, sort of like an address book for the entire company, and a section to request leaves or absences.

Another one of our rejected mockupsIn my own personal projects, I don’t often wireframe or go through user stories before beginning to code. Going through this entire process was painstaking, but I began to understand the importance of it all. Design is not just lipstick on a pig. Good design begins before the first line of code has been written. It involves architecting your entire app around user-needs. Skipping this crucial process and failing to imagine user needs means potentially spending hours on an app that no one needs or uses. This is a good takeaway.

Sprint 1: Contacts Component

MockupI started work on the contacts app after following a tutorial on React.js. Taking our contacts page from mockup to working prototype was not difficult. Bootstrap made writing the user interface incredibly easy. The primary challenge that I faced was mostly updating the app as the user edited their personal information. I had broken down the app into tiny and modular React stateless functional components which produced cleaner code. The problem was I needed a way to update the user’s information, which was stored in state of the container above it.

Implementation of mockupThe temporary solution I came up with was to throw all of the user’s information in local storage and to update that local storage as a ‘state’ as the user updates their information. This wasn’t best practice, but it worked well enough for me. As I continued working on the application, however, I found the codebase bloating and the localstorage solution I had devised increasingly confusing.

I decided to rewrite most of the state handling operations into Redux. Redux rests on the idea that your entire app has one single state. This state is immutable and the only way to ‘update’ a state is to take in the current state and new data and compute a new state. As my application grew more and more complicated, using Redux seemed to make more and more sense. Thus, I spent two days learning Redux and applying its functional model for modifying state to my existing codebase. While very little visible progress was made on the app, I found the codebase was a lot more readable and a lot more free of side effects. This was the last step to building an MVP for the contacts part of the app.

Adding Corporate Identity

User component from above with theming towards our CI in progress.Along the way, we realised that we needed a way to make our HR app look consistent with TenTen’s website. Ironically for a design studio/startup, we don’t have our own branding and design guidelines. Tin made a CI that we are now using internally for typographical/stylistic direction. She applied the CI to my work. There’s still a lot more we can do with the styling, but it added a lot more polish to the app.

Sprint 2: Requests Component

Calendar component mockupAfter the contacts manager component was complete, we needed to build the requests component. This was mainly smooth sailing as by the time I had worked with the contacts part of the app, I had enough experience with most of the React/Redux stack to make the work reasonably straightforward.

I thought writing the calendar to display everyone’s leave plans would be the hardest part. Surprisingly, the power of React came to my rescue. By making modular components, it’s easy to reuse other people’s work in your app.

Adding a wonderful calendar component was as simple as npm installing react-big-calendar and dispatching several redux actions so that the calendar could render the information that I provided. Thanks to the International Justice Mission for releasing such great open source software!


Announcing atTendance’s release on JIRA! Deploying atTendance was not difficult. Since we are using Webpack to package all of our client-side code into a JS app, deployment was as simple as serving this on an ordinary nginx server. Our Firebase was already setup as this is what we’d been testing on. Roy, our systems administrator, helped me with deploying the app to a nginx server. After a couple of mishaps with HTTPS, we were good to go!

Next Steps

We’re currently QA-ing atTendance and employees in the company are filing bug reports. We intend to run a couple more sprints to incorporate user feedback and some additional features currently present in our backlog. Also, while Firebase was great for building our MVP, we’d love to move to a backend that allows us to move more of the data handling and processing server-side. All in all, this was a fantastic opportunity to get my feet wet with a JavaScript React/Redux stack in a low-pressure environment and I enjoyed it immensely.

I’m currently a full stack engineering intern at TenTen, a small digital design startup in Taipei.