Throughout my journey learning new skills in my desire to become a junior developer I have always had two to three side projects, things I would really love to build myself, and projects that inspire me to learn the skills needed to complete them. Having previously managed an extensive project to turn around a large holiday rental company's organic online business, and specifically their website revenue, I have long wondered if I would ever be capable enough to build such a platform myself.

Premise

The website must fill the following criteria (do micro):

  1. Be capable of efficiently and intuitively displaying hundreds of properties
  2. Have a clean URL for each property for SEO purposes
  3. Having backend system and process that allows for easy uploading and editing of properties
  4. Has a backend that provides content and resources such as images quickly and efficiently
  5. Perform extremely well on Lighthouse
  6. It must look like a high-end, bleeding-edge website
  7. Users must be able to upload their own properties

History

The site is currently probably on its fourth or fifth iteration, having been built using every new skill and framework I learned along my journey. As Vue was the first framework I became familiar with the first version of the site was bult in NuxtJS. I then became intersted in what Gridsome could offer as a static site generator, and so the site was rebuilt again. Looking back now, this was just a minor change, though at the time, with very little experience in building such a project, and indeed very little experience in even Javascript or JS frameworks, it seemed like a significant task, as was in practice.

I then discovered Svelte, and became both excited and fascinated by it, having dabbled with React and being scared to death by what at the time seemed like a huge amount of code to display just 'Hello World', especially when compared to Vue and Svelte. Needing a statically generated site which perfomed well with search engines, Sapper became my next focus, and the site was rebuilt again. I was especially intrigued by the fact that Svelte/Sapper is actually a compiler, with its build step creating just the pure Javascript code needed with no extra boilerplate at all. Given the requirement above for an extremely performant website, and knowing that Svelte was such a relatively new framework and the only one I knew of that was a compiler made it all the more attractive.

My burgeoning interest in JS frameworks and what they could offer, both in terms of both developer and user experince was matched by my interest in what was a totally new concept and technology for me - a headless cms. In my previous role a couple of years previously, I'd overseen the company's move away from a legacy Wordpress based site and the implementation of a dedicated PHP based cms called Craft. Headless content management systems and what I considered to be the 'new' frameworks seemed the perfect marriage to me - the latest frontend and backend technolgies working syncronously together, and one I was keen to exploit.

So, my journey through JS frameworks was matched at the time by my exploration of the various headless cms systems, and through my numerous builds of this site I tried, among others, GraphCMS, DatoCMS, NetlifyCMS, TakeShape and Contentful, before finally commiting to Sanity. I may even write a blog article when I have time comparing the pros and cons of each sytem such was my interest in them.

The backend - Sanity.io

From the very beginning of my journey to learn to code, and therefore to build this project, I was adamant that I would never choose the easy option for the sake of it being easier to learn or quicker to implement. I wanted to use to absolute best tools for each job. Sanity is targeted towards developers and provides a backend interface, Sanity Studio, that is built in React and can be hosted locally. As someone much better qualifed than me said:

I feel like I'm cheating when I use @sanity_io. Config is so customizable and feels truly unlimited

Let's look at how schemas are arranged in Sanity. For this project I have one main schema.js file which pulls in my various data objects such as 'siteSettings' and 'reviews', with 'villas' holding the main data.

import createSchema from 'part:@sanity/base/schema-creator'
import schemaTypes from 'all:part:@sanity/base/schema-type'

import siteSettings from './siteSettings'
import villas from './villa'
import mainImage from './mainImage'
import imageArray from './imageArray'
import reviews from './review'
import globalVariables from './globalVariables'

export default createSchema({
    name: 'mySchema',
    types: schemaTypes.concat([
        siteSettings,
        villas,
        mainImage,
        imageArray,
        reviews,
        globalVariables
    ])
})

The power with Sanity lies in a developer's ability to structure their data exactly how they want. Here is an example of the main villa.js schema:

export default {
    title: "Villa",
    name: "villa",
    type: "document",
    fields: [
        {
            title: "Villa Name",
            name: "villaName",
            type: "string",
        },
        {
            title: "Featured on Homepage",
            name: "featuredHome",
            type: "boolean",
        },
        {
            title: "Location",
            name: "villaLocation",
            type: "string",
        },
        {
            title: 'Slug',
            name: 'slug',
            type: 'slug',
        },

        ...
    ]
}

Which then gives us our Sanity Studio.

Sanity Studio
Sanity Studio, hosted locally.

We can see the data inputs defined above in the schema replicated in the Studio, with the data objects on the left.

The frontend - React

'All roads lead to Rome React'. It had to happen. After dabbling with Vue and Svelte I then fell in love with React, first through Next.js and then Gatsby. The current itteration of the project is built using Gatsby, and of course Tailwindcss. Gatsby offers a tremendous ecosystem for a developer, and with this site being particularly image heavy being able to use tools such as Gatsby Image really appeal to me.

Map-GL

React-MapGL is a key component in the site, being used in both the search results page and each respective villa's page. It uses Mapbox to generate location maps showing each villa's location.

In the first picture we see how maps will be utilised for the search results page

Search results page
A non-dynamic version of the search results page

Longitude and latitude are entered in our CMS and then passed into the MapBox component.

Searh results page
The map coordinates field in the cms

The resulting map as shown in a villas information page.

Searh results page
The map, with styling needed

Homepage

The homepage, after the standard layout, consists of location components, each with their own params and query. So to change which villas are featured on the homepage we can firstly use the boolean featuredOnHomepage switch in Sanity Studio. Second, we define locations in the location component.

Homepage
The current homepage

Some text here

The villa page
The villa detail page, with an Airbnb style photo collage

Moving forward

Next I would like to focus on two things, allowing users to upload their own properties and showing the results from dynamic property searches.

React-Admin looks like it could be useful in providing a 'user-backend'. It contects seemlessly with an API endpoint to perform crud operations and also has authentication out of the box, though I suspect in the long run it will be better to build a custom solution. Regarding displaying dynamic search results in Gatsby - if I can really nail this I'll be delighted as it will be a large step forward for me. I'm currently looking at ways of passing in search parametres to the URI and then using these in a dynamic search results page.

With that ll being said, I'm also thinking of starting again and rebuilding the site completely in native React 🤣...