This is an online furniture shopping app for furniture company from West Africa. It targets Android devices only and is built on Flutter/Dart. It uses Google Firebase as a backend.
I started working on the project in early November 2019. The customer provided me with mockups in PDF format. After that, I started thinking about the database structure and the app architecture, and setting up the environment. I think that it’s important to plan first and then start developing the app.
Next, I built an authentication system. It was SMS-based authentication using Google Firebase Auth, because people in West Africa are used to using phone numbers rather than email addresses for authentication.
In mid-December 2019, the app was completed: right on time, according to the schedule approved by the customer. I implemented product browsing functionality, product details (including product options, such as size and color), cart screen, checkout flow (including choosing an address and payment method), order tracking and other, a total of 14 screens. A discount system has also been added. I believe that fast image loading is important for online shopping app, so I chose the progressive image loading approach used by Medium and other popular services. First, the app downloads a very small blurry image thumbnail and present a product with the thumbnail to the user. After that it starts downloading the full-sized version of the image in background and replaces the thumbnail immediately after downloading it. I had to create a Google Cloud Function trigger to automatically generate a thumbnail every time a new image is uploaded to Google Cloud Strage. sharp npm package was used for that. This approach has improved the browsing experience, especially for people with poor internet connectivity. Also, the app was localized to 2 languages: English and French.
Later, the customer asked me to implement email notifications about new orders. I added another trigger that generates an email based on a special email-optimized HTML template and sends it to a predefined email address. For sending an email I used nodemailer npm package.
We communicated with the customer via a corporate Slack channel. I documented my work using GitLab wiki so that any future developer can easily join the development process. Guys from the company that hired me were tech savvy enough to build the app directly from the repository, so we didn’t spend time for setting up CI/CD for the client app. However, I set up GitLab CI/CD for the server side.
Freelancer Jobs is my own project I worked on my spare time. It was interesting to me to try out the backend development, and I’ve decided to implement a custom backend on Vapor: a server-side Swift web framework. MySQL was chosen as a database due to its simplicity and out of the box integration with Vapor. Both compiled web app and the database were packed into Docker containers to properly isolate the components from each other. I had to work out the dependency between two Docker containers and that was hard, as Docker was a new technology to me. But finally I got that managed and deployed the containers onto Ubuntu 18.04 server. Overall, it was amazing new experience for me to learn new server-side technologies.
The client app was written on Swift and it’s a simple job feed with few setting screens. However, the implementation had its own complexities. For example, job feed is live and pagination needed to consider the new jobs can be added while the user is scrolling down. I solved that problem by using
maxId approach suggested by Twitter.
A neat feature I’ve included into the app was Ask To Rate dialog. What it does is to politely asks the user to leave a review on the AppStore. If the user thinks the app doesn’t deserve a good review, it asks to send a feedback to the developer instead. In short, after I’ve implemented the component, the app reached amazing 4.6 average rating!
The app has a simple basic UI I created myself. Also the app doesn’t use storyboard at all: all the UI is created in code. The code-based UI has many advantages though it slows down the development a bit. Since Freelancer Jobs was my own project, I could afford it 🙂
This is a large project I worked on in 2017. RaffleHunter is an iOS app, letting people win cool prizes from companies. I was provided with designs in Sketch format by my employer, PurpleVolt Inc., and, after refining the requirements, started developing the app using Swift. To reach AppStore faster I was also asked to implement a backend using Parse Server hosted on back4app.com for the MVP version of the app. In a few months PurpleVolt had their own backend ready, and we’d successfully migrated the app onto it. I used that chance to refactor the code and switch from callbacks to promises (Hydra library), which made the codebase less verbose and more structured.
For simpler user engagement we’ve implemented social logins (Facebook and Google) along with standard email/password login. Also the client asked me to implement a referral system, so people could increase their chances of winning a raffle by inviting friends. I used Branch SDK for that. It gave us the ability to know the user’s referrer even before the user has installed the app.
I integrated CircleCI for automated tests: it ran unit tests every time we pushed commits to GitHub and sends reports directly to Slack. CircleCI integration along with a strategy of covering just implemented feature by unit tests reduced number of issues and crashes: we had 0 crashes since then.
After 6 months of development the project has grown and PurpleVolt has hired another iOS developer. I took the lead of iOS development, explained the architecture of the project and prepared a detailed README for him. I also commented the code base as much as possible, so it’s easier for someone to jump into the project.
By the beginning of 2018 our team has grown to 10 people, including designers, QA, Android, iOS and backend developers. We’ve communicated via Slack channels and assigned tasks to each other on Trello. These tools greatly improved our cooperation. Since I was the only person who worked on the project from its beginning, I was often asked to clarify the requirements or suggest a way to improve or change UX on a certain feature. This helped to reduce a workload of the product manager and allowed him to focus on the strategy of the project and design tasks.
A git branching model I set up included 3 main branches: master, beta and develop. If there was a large feature to work on, I created a new branch for that feature, so it’s possible to quickly hold off the progress on the feature and switch to develop branch. Later I made a full continuous integration using Fastlane and CircleCI: pushing to beta branch triggered a new beta release to TestFlight automatically. Pushing to master branch triggered a submission of a release candidate build (which is pointing to the production server) to TestFlight automatically. After RC build is reviewed by QA team, it got submitted to the AppStore. This model saved us a lot of time.
Socium is an iOS Social Network app template, my own project. The project uses Parse Server as a backend hosted on AWS S3 instance. I set the minimal iOS target to iOS 8 to get a wider audience (>99.08% according to Mixpanel reports).
The app has a typical social networking app functionality: user profiles, user-posted content (text/images), private chats, followings/followers, push notifications. I wanted to make private chats realtime for great user experience. To achieve that I used Parse LiveQuery technology allowing to interact with the backend using websockets (almost instantly receive and send messages). Websockets also helped to reduce energy consumption and increase battery life while using the app. The appearance of the app can be easily modified even by a person, who is not proficient with all that programming stuff. Adjustments can be simply made by editing a configuration file.
I was able to create a clean and robust architecture for Socium and wrote a blog post regarding that.
I’ve used SwiftLint as a static code analyzer tool for this project. SwiftLint is a common tool among experienced iOS developers. It helped me to maintain highest coding standards and to get a better code readability. Aside from using the linting tool, I was using “treat warnings as errors” rule when writing the code. I also paid attention on commenting my code as I knew the project will be used by other iOS developers.
The project is integrated with Facebook, allowing the users to log in/sign up with their Facebook accounts. CLImageEditor open-source library was used to integrate a photo adjustment functionality. Instead of writing a custom solution I picked JSQMessagesViewController to operate the message feed. This decision greatly saved the development time and increased the overall stability of the app. I believe it’s better to use a popular open-source solution rather than reinventing a wheel. Nonetheless, I don’t use dead and outdated libraries.
The backend includes Parse Server, MongoDB, Parse CloudCode and Parse Dashboard. All of them are packed into a Docker container for easier deployment process. Socium is the template, after all.
Studio Music Player is a music app playing tracks from iTunes library. The client wanted to have an app for people, who wants to have a precise control over the sound quality. The app was initially written on Swift 1.3, then migrated to Swift 2 and Swift 3. According to the requirements I’ve implemented a wide number of features and tweaks: equalizer, factory and user presets, sound effects, skins and user playlists. Storing presets and user playlists required to integrate Core Data framework.
I worked closely with the client in order to bring his vision of the app design to life. AutoLayout was used to make the app Universal (suitable for both iPhone and iPad) and to look good in both Landscape and Portrait mode. The client also wanted to let the user to select a skin for entire app. I implemented a system, which redraws the current screen and also notifies all other opened screens that the user has changed the skin.
According to requirements factory presets must be easy to update without resubmitting the app, so I suggested to store them on the web, and let the app to download them and then save locally on device. Since the app works with audio files, it must be fast and well optimized. I made a bunch of small and large optimizations using Xcode Instruments. We’ve also covered edge-cases of playing audio, e.g. when Siri is called, when incoming or outgoing call is occurred, when headphones are plugged or unplugged. When a device (headphones, bluetooth speakers, car) is connected with iPhone, the app automatically selects an associated preset.
The client asked to prepare two app versions: Paid and Free version with In-App Purchases. I implemented it by having two targets (Paid and Free) in the project to avoid having two distinct project and integrated In-App Purchases with using CargoBay library.
Localization was another major feature requested by the client. He wanted to translate the UI to 21 languages. I extracted all localizable strings from source code and storyboards to *.strings files, then the client had them translated to necessary languages. We’ve integrated the files back to the project and got internationalized interface.
There is a spin-off project: Studio Music Player DX with the ability to play tracks stored in Dropbox folder and from iTunes Shared folder. Other than that it has the same functionality as Studio Music Player.
I worked with CenterPunch at the end of 2014 to build a quiz app. As Swift programming language was too young at that time the project was written on Objective C. There wasn’t a complex business logic in the requirements, so I’ve advised to select Parse.com as a backend for the app to save on overall cost and reduce development time. As we figured out later, their servces fully met our needs.
The app has nice and very flexible design, as the client asked to implement a mechanism allowing setting colors for each quiz and section individually without resubmitting the app to AppStore. Quizzes also have different types, so the app is able to present quizzes in different formats according to their types. For example, there is a Tinder-like quiz, where the user can swipe cards left or right. Another quiz type involves a countdown timer. All of quizzes are controlled by CenterPunch remotely and don’t require the app to be updated or rebuilt.
I’ve integrated 2 SDKs for analytics: Mixpanel and Facebook, and set appropriate events for these SDKs. Analytic reports helped CenterPunch to better understand the user’s behavior within the app and to find ways to improve UX.
In January 2016 Parse.com announced they’re winding down Parse service and making it open-source. I was hired again in late 2016 to migrate from Parse.com. I’ve successfully migrated the database and backend to self-hosted Parse Server + MongoDB instance on AWS S3, without downtime and any data loss.
Andrey has been a vital and extraordinary contributor to my project and team.
He was professional, provided accurate estimates and delivered high quality work on schedule. In addition to his excellent technical skills, Andrey also provided key architecture and design recommendations, which ultimately led to a better product.
I would gladly work with Andrey on future projects.