This is a simple project where I showcase some of my full-stack software development skills, knowledge of best practices and also serve as a playground to try new things.
It's a simple app to manage trips using hierarchical role-based access control. The app is functional but is still a work in progress.
URL: https://wtrips-demo.firebaseapp.com/
User: admin@example.com
Password: 123456
The front-end started with React 15.x and bootstrapped using create-react-app. The plan is to update the project to use React 16.x and use its new features such as Suspense and Hooks.
The project is using the Ant Design UI framework which, in my opinion, is one of the best ones. It looks awesome and has a bunch of high-quality components.
I'm also following some Responsive Design guidelines, especially making using of media queries, so the app can be used on laptops, tablets, and phones without problems.
The CSS preprocessor SASS (with SCSS syntax) was used to style the application. The SCSS files were organized following the 7-1 architecture pattern and some tips of the Sass Guidelines were adopted as well.
To better structure the CSS classes, some naming conventions were tested like BEM and OOCSS. However, after some experiments, the SUIT name convention was chosen because it plays well with React components. But maybe it's just a personal preference.
For state management, MobX was chosen just because I'd like to play with it a bit. It is cool, but I didn't like it much because many things happen behind the scenes and you kinda lose control over them. I intend to move to Redux and use its functional approach.
The back-end is a regular stateless REST API built with Node.js and Express.
To persist data I'm using Postgres, just because of my large experiece with it. I'm also creating a thin repository layer using knex (a query builder library) together with the Objection ORM.
For validation of the request payloads, yup is being used. One of the most popular projects for validation is joi, but I chose yup because joi has some limitations with async validation. I'm also using the xss library to prevent XSS attacks.
The authentication was done using JSON Web Tokens (JWT) that are sent through the Authorization header, which is the most recommended way to build authentication for a stateless API. For authorization, the project is using a simple access control list, built with the virgen-acl package.
Unit tests were written using Jest. End-to-end tests were created using Cypress, which is an awesome tool and turns the usually painful task of creating that end-to-end test a breeze.
The project is using ESLint, one of the most popular JavaScript linters, together with the rules provided by the Airbnb JavaScript Style Guide, with just some few customizations.
The Stylelint linter, in conjunction with the SASS guidelines, is also used to format and verify the project's SCSS code.
Docker and Docker Compose were introduced later. The first intention was to use the images for deployment but it also was used to experiment with the idea of using Docker for development, which is interesting, especially in big projects where, at least in theory, we could run one command (docker-compose up) and have everything we need to start the app (database, Redis cache, queues, etc) without having to set up anything in your local machine.
I'm using CircleCI to enable Continuous Integration and a pretty simple Continuous Delivery process. I had some troubles with CircleCI though. Especially problems related to the cache when I was trying to decrease the build time by leveraging Docker cache and also when I was trying to run the end-to-end tests - they got pretty inconsistent, sometimes falling because of timeouts. I gave up solving those problems for a while and I'll try another tool when I have more time.
The first idea was to deploy the app to AWS Elastic Beanstalk, as I have some experience with it. But The AWS Free Tier only gives us 12 months of free EC2 usage and I wasn't willing to pay to keep an EC2 instance up all the time after that period.
Then, after a little struggle, I've found a free forever approach. The back-end is hosted on Heroku and the front-end hosted on Firebase. I'd like to use one single service, but it turns out that Heroku is not so good for hosting static files (it's possible, but it's kinda hacky) and Firebase cannot host Node.js apps. Another solution is to serve the static files through the back-end Express server but I'd have to change the current code and the Docker image to enable that.