Recreating Notion's Homepage with Tailwind CSS and Vue JS
Tags: showdev, css, vue, tailwindcss
Published: 2021-01-25 20:23:48

## View the Project:
[My Recreation of Notion's Homepage](https://gallant-bose-76c7bd.netlify.app/recreations/notion/)

## Compare it to the Original
[Notion's Homepage](https://www.notion.so/product)

# Deciding what to build to showoff my front-end skills
When I first decided to build something ~~for the Digital Ocean Hackathon~~ to show off my front-end webdev skills, I asked myself "What would be useful for a real business?"

The answer I came to is recreating the website of a real business, a business whose website is so important to them that it serves as a foundation of how they do business and serve their customers.

The first criteria I had was obvious to me: the business whose website I chose to recreate had to be huge, or at least hugely valuable.

The second criteria was less obvious: the business' website had to not depend on the use of outside assets and graphics to make it look nice. Pretty assets don't show off my front-end skills and don't show off how I can best help businesses.

So I wanted to recreate an existing successful business' website that uses a variety of CSS skills: flexbox, grid, and a variety of styles for images, text, and a lot of data that needed to be managed in a robust way.

After all, part of the reason I decided to recreate a serious internet business' homepage, is that I wanted to improve my front-end webdev process and this offered me the perfect challenge: totally doable, yet more complicated than any page I've created before.

I looked at a few sites before I chose one:

First I looked at Nike because I like their branding, but after looking at their website, I realized most of my work recreating it would just be copying their media assets. 

![Nike's Homepage](https://dev-to-uploads.s3.amazonaws.com/i/3n5qzpb45gjlklfieqxa.png)

Sure, I could recreate their navigation menus using flexbox and product displays using grid, but most of my work wouldn't show through.

Second, I looked at Stripe. Stripe's website is beautiful, but boy is it complicated and, secondly, it has the same problem as Nike: recreating Stripe's website depends on using a lot of outside assets, except it's worse! Stripe's website uses assets that are harder to access and implement.

![Stripe's Homepage](https://dev-to-uploads.s3.amazonaws.com/i/9fkd88qy4i4d5kz1tt1o.png)

Still, Stripe's website uses some pretty cool layout designs I could recreate using grid. Maybe this is something I'll revisit later.

Lastly, I looked at Notion. Notion's website, like their application, is beautiful, friendly, and accessible. It uses a bunch of assets, but, unlike Stripe and Nike's websites, doesn't rely on them. It uses modern CSS skills like flexbox and grid and a lot of text data that's managed best dynamically using components.

Notion's homepage was the clear and obvious winner.

## My Process

One thing I decided early on was that I wasn't going to look at the original webpage's code. If someone wants to hire me to create a website for them, I don't have any starting code to work with so I'm not going to use that here either. They'll simply hand me off some wireframes from Figma or Sketch with the assets I need and/or a validated product spec.

I recreated all the page's designs and layout by sight.

No inspecting code, no copying code. All translating what I see into what write.

For me, there's only one good solution for this "what you see is what you code" sort of webdev framework and that's [Tailwind CSS](https://tailwindcss.com/)

Tailwind is great because it removes the layer of abstraction and lock-in that makes global CSS so unmanageable.

Next, there's data. All the data serious internet business websites use is managed dynamically using components.

```html
<!-- testimonials section -->
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-12 md:gap-16 p-8 md:p-16 mx-auto">
    <a href="#" v-for="testimonial in testimonials" class="bg-gray-100 rounded-lg border border-gray-100 hover:border-gray-300 p-4 flex flex-col items-start">
        <img :src="testimonial.companyLogo" :alt="testimonial.sourceTitle" class="h-12 object-contain object-left overflow-hidden">
        <div class="text-lg my-6 h-full">
            "{{testimonial.content.trim()}}"
        </div>
        <div class="text-sm flex">
            {{testimonial.source}}
        </div>
        <div class="text-sm text-gray-700 capitalize">
            {testimonial.sourceTitle}}
        </div>
    </a>
</div>
```

You alter design and data using two separate processes which keep both safe from accidental changes to each other.

```json
testimonials:[
    {
        companyLogo:"images/blinkist.png",
        content:"On notion, everything is in one place and everyone can find what they need on their own. We have cut down on interruptions, and stayed more focused on priorities.",
        source:"Milica Radojevic",
        sourceTitle:"People experience partner, Blinkist",
    },
    {
        companyLogo:"images/figma.png",
        content:"Notions ease-of-use is one of its hallmarks. It helps you visually navigate contact and remember where something is.",
        source:"Marie Szuts",
        sourceTitle:"Head of people ops, Figma",
    },
    {
        companyLogo:"images/duolingo.png",
        content:" we wouldn't be able to customize our workflow like this in any other product",
        source:"Justin Goff",
        sourceTitle:"product manager, duolingo",
    },
],
```

Components let you update how data's displayed across your website without updating individual pages one by one.

![Testimonials on Notion's Homepage](https://dev-to-uploads.s3.amazonaws.com/i/7m6nhvd1xwc22l1hss73.png)

Avoiding code duplication helps you avoid making errors that make your website harder to manage, less friendly to use, and less focused on satisfying your users.

I manage the webpage's data using [Vue JS](https://vuejs.org/). Its fast modern framework makes managing data easy and reliable.

But there's one problem with Vue JS and that's SEO.

Vue JS, like React and Angular, render a webpage's content dynamically, so they're not good for SEO.

To solve this problem, my next steps are rebuilding this site 
using [NUXT JS](https://nuxtjs.org/) which builds static HTML pages to get all the benefits of dynamic rendering and component organization from Vue JS with all the SEO benefits of static HTML.

### CSS Properties I Learned
```html
pointer-events-none
```
Makes images non-draggable

### CSS Properties I knew, but hadn't used before
```html
flex-row-reverse
```
Useful for conditionally reversing the orientation of your footer elements on mobile, such as when you want to show a copyright notice on the left in your footer on desktop, but below everything else on mobile.