- Who is Sailogy?
- A complete separation of backend and frontend
- The goal in nine points
Who is Sailogy?
Sailing is a great experience that many people would like to enjoy more often than they do. The demand for simpler booking tools indicates that there is a large market to serve. Sailogy currently offers 22,375 certified boats and over 800 destinations, from the Mediterranean to the Caribbean, enough options for everyone to make a great choice!
Sailogy Group aims to make sailing holidays accessible to everyone: through a rich portfolio of vertical websites, every customer can rent a boat in comfort and safety.
Customers from all over the world can choose from a wide selection of sailing yachts, motor yachts, catamarans and gulets, all available to rent with or without experienced skippers and hosts.
This exceptional offering is born out of a very long experience in the field – Master Yachting GmbH has been the undisputed leader in the German charter business since 1990.
In 2018, Master Yachting became part of the Sailogy Group. Sailogy was founded in 2013 with the aim of revolutionizing the boat rental market, making a product that is considered niche even in a low-tech market accessible to everyone. Continuously aiming for excellence, the company has since modernized their software and websites, an experience that could be helpful to many developers.
We have partnered with Sailogy to launch a coding challenge for front-end developers. Join the challenge to test your knowledge against your peers, and be in to win an Amazon voucher worth €500.
A complete separation of backend and frontend
The end goal was to completely separate the backend and frontend, using the most appropriate modern technologies. The process started with migration operation, with refactoring worked on in a subsequent phase.
Lighthouse audit is a good way to evaluate improvement in performance, as well as to monitor page serving time and rendering time.
More specifically, Lighthouse evaluates every webpage according to search engine methods. A score is given, based on five categories: Performance, Accessibility, Best Practices, SEO and PWA (Progressive Web Apps). PWA is still a fairly new technology that promises to make websites run faster when viewed repeatedly.
Lighthouse produces a score between 0 and 100. The better your Lighthouse score, the higher your webpage will appear on a search engine.
A high score means that your site meets the best practice and SEO standards outlined by Google in terms of performance and accessibility.
Lighthouse can help to identify common problems that affect the quality of a website, and will also suggest solutions for these issues.
The easier it is for users to interact with the page, the happier users will be and the more time they will spend on the website overall. This also increases the page rank of each page, meaning that organic traffic will soon increase leading to more users navigating the website.
Using Next.js facilitated a switch from server-side rendered pages (SSR) to build-time server generated pages (SSG) and on-request-time regenerated pages (ISR), reducing server costs and making pages faster.
Thanks to the Next.js SSG and ISR pattern, the server now carries API response only, ignoring anything frontend-related, and requests are made only when pages need to be updated, producing a significant reduction in requests and server computation.
Page generation also means that pages are static files ready to be serviced, with very low latency for landing pages (using HTML files) and during navigation (using JSON files for page hydration).
These choices had a huge impact on the SEO metrics, as shown by the statistics. The refactoring phase will also benefit.
The goal in nine points
The overall result was structured according to nine important points. Performances, front/back separation, mobile, and a long life for the resulting code were the key principles behind the nine pillars, listed below.
- Separate Frontend from Backend to improve code maintenance and work management between the two departments;
- Develop reusable components to reduce bundle weight and development time, with a codebase shared among the various brands of the group;
- Conceive mobile-first pages to increase the usability of the site on mobile devices;
- Preserve the logics present in the old site during the transition to the new version through a Continuous Delivery process, even though the old site was mostly undocumented;
- Reduce page loading times to within the acceptable parameters of the Core Web Vitals, resulting in improved page rank, and therefore, page positioning on search engines;
- Improve usability to increase the Conversion Rate on the various pages, thus impacting bookings;
- Use modern technologies to ensure a longer life for the software;
- Strengthen the codebase with test sets to prevent bugs and preserve business logic over time;
- Write all code with types found in TypeScript to better control data processing and create a well-documented code.
All nine key points will be addressed in brief below.
#01: The past
The site was originally serviced by a monolithic, Django-based infrastructure, with an interface that was hard to use on mobile devices. This made loading times very long, leading to confused users.
Frontend and Backend were therefore split into two different entities. Communication was established through REST APIs: this choice allowed not only the distribution of the workload necessary to page servicing, but also facilitated the correct sorting of issues arising between the various F/E and B/E departments, allowing departments to work in parallel.
#02: Stateless pure functions w/React
Sailogy encompasses various brands of the group and several individual websites. It was therefore important to develop easy and rapid codebase maintenance, whilst simultaneously ensuring customization of the various components for all brands.
A core library was chosen to be shared between the various projects. This offered two advantages: a toolset consistent with the centralized business logic, and the scalability and customization of the various components. Business logic was coded in small, stateless, pure functions (easy to test), using React Hooks to share the logic between the components of different ecosystems, such as web and native mobile.
#03: Mobile first
The old layout wasn’t optimized for mobile devices, so the mobile bounce rate was penalized. It was essential to rethink the pages with a mobile-first philosophy, given the high number of mobile visitors – already greater than 50% of traffic when the new website was in planning.
The logic of the old site was not documented, something that often occurs in modernizing software systems. Sailogy decided to proceed with a three-step strategy: porting, redesigning, and enriching.
Redesigning the main pages of the site was the second step. This phase was executed one page at a time, respecting usability and checking compatibility with the old booking flow.
Designing the remaining pages of the site, enriching them with features, and adapting them to a long-term roadmap was the third and final step. This phase completed the restyling process.
The first phase of the process was quite long, but allowed the team to avoid losing a single functionality from the old site, and to proceed at a faster speed in subsequent phases as the business logic was already written.
#05: Static page serving
A static file approach to serving looked like the best choice for Sailogy. The final result was a reduction in loading times without impacting infrastructure costs, such as occurs when external caching services are implemented.
In the case of Server Side Generated (on build/deploy time) and Incremental Static Regeneration (on request time) pages, the loading times for Sailogy’s websites have been reduced by a factor of six, accessing pages in under one second, with an average of 0.8 sec.
Next.js allows for two forms of pre-rendering: Static Generation and Server-side Rendering. The difference lies in when the HTML for a page is generated: static generation occurs when the HTML is generated at build time and reused on each request, while in server-side rendering the HTML is generated on each request.
Although static generation is the recommended mode, server-side rendering can be very helpful in many situations. This is the case when maximum information reliability is required. When pages that demand this are to be serviced, such as the page that shows the boat and its availability, the Server Side Rendering technique is preferable. Service time is between 1.5 and 2 seconds.
To further reduce the time required to view individual boats in the search phase, it was decided that clicking on the card would not open the detail page of the boat, but would first open a preview page using the boat data provided by the boat-listing API, subsequently loading missing data asynchronously. This choice made it possible to view boats brought up by a search in a practically instantaneous way.
A session-side caching technique for API requests called SWR was also implemented, in order to minimise network requests to the servers and reduce the response time.
SWR is an HTTP Cache-Control Extensions for Stale Content. ‘Stale’ refers to out-of-date data. SWR is a strategy that returns cached (stale) data first, then sends the fetch request (revalidate), and finally presents the updated data.
What is important about SWR is that components will constantly and automatically receive a stream of data updates and the UI will be always fast and reactive.
Using listing responses to preload product detail pages is another technique that makes navigation even more immediate and fluid, opening product pages in preview mode and lazy loading additional content.
This series of interventions eased navigation in terms of both enjoyment and time. The overall user experience was greatly improved, and the average time users spent on the site rose by a full minute (a 30% improvement), with a 15% reduction in bounce rate compared to the previous period. Furthermore these UX improvements doubled the number of user searches on the search page, further demonstrating usability improvement.
#06: Time to booking
A mobile-first approach was used to improve the user experience during the page redesign. One focal point was shortening the time-to-booking: fewer steps during booking, shorter waits while browsing boats, and information reorganization by means of user behavior heatmaps. Tools such as Hotjar have been very useful in this respect.
The improvement in page performance also led to a better page ranking, and consequently to an exponentially greater number of visits from organic traffic: these almost doubled, when compared to the previous period..
The renewed Sailogy website experienced a doubling of bookings compared to the pre-pandemic period, both on desktop and mobile, despite a challenging period for the tourism sector.
#07: Stack: Next + React
There are some tips and tricks for rendering pages that permit faster servicing. These include refreshing pages, image engine, and time for loading stylesheets.
Some additional work has been done here too. Traditional React apps render all their content in the client-side browser, introducing delays and other problems in the page display. Rendering files on the server side shortens waiting times and avoids such problems. Next.js is an open-source development framework, built on top of Node.js, that helps generate static websites.
Refresh-page regeneration can be done on request, generated during the build (e.g., search). The ISR (Incremental Static Regeneration) is then generated within the build but with a defined lifetime: when it expires, it is rebuilt in Html/Json, with an ultra-fast response and data that have been updated without needing to first be caught.
In the final version, Next.js provides a built-in image optimization component, to serve the best image format based on a device viewport, using HTML standards and supporting tools for image processing such as IMGIX.
Next.js is also great for servicing optimized pages with zero configuration, similar to CSS prefetching for a fast page painting.
All these solutions contribute to a high Lighthouse score, taking advantage of Google’s open-source tool for performance comparison, with its continuous updates.
#08: CI/CD – Code coverage
Code, or Test coverage, is a measure used to describe the degree to which the source code of a program is executed when a particular test suite runs. Many different metrics can be used to calculate test coverage.
The writing of test suites was fundamental to achieving a code coverage higher than 90%. This was the rate necessary to preserve the business logic and avoid writing useless code for the expected behavior of the component. Integrating test execution in the CI/CD (Continuous Integration/Continuous Delivery) process made it possible to guarantee safety and solidity regardless of the frequency of releases. Good code coverage is also an indispensable factor in scaling the development team, protecting the business logic and enabling a test-driven development method.
To keep the code tidy and clean, linting tools as well as extensive use of TypeScript were employed to automatically check the code. In addition to increasing the robustness of the code, typing exploits types and interfaces to understand the internal flow of the component without having to write additional documentation, ensuring component documentation is always up-to-date. The perfect integration of TypeScript within modern IDEs means that users are able to benefit from real-time check and auto-completion, taking Developer eXperience to the highest levels.
Furthermore, Typescript is well integrated with Next.js on an out-of-the-box level. Sailogy developed internal documentation in the first stages, while visual tools such as Storybook will be used late for the development of complete documentation.
Writing websites is not the easy task many believe it to be. Even professionals often think that choosing the right stack is enough, but this also the foundation for choosing the right toolset.
Sailogy rewrote their software to effect a transformation, separating front-end and back-end completely.
This article only tells the first half of the story: more will be revealed in a companion article to follow, dedicated to back-end choices. Stay tuned!