How to Build a Job Nina with Sapper, Strapi and Netlify
Tags: strapi, netlify, svelte, javascript
Published: 2022-10-03 10:27:38

**Author: Opuama Lucky**

**This article will show you how to build a job search platform using Sapper with Strapi as database and then deploy it to Netlify.**

Job Nina is a platform where jobs are created; the admin/employer can add any field job that matches the company's requirements. Generally speaking, job nina is a job search platform.
In this tutorial, I'll walk you through the steps of creating a job nina with sapper and strapi as the backend then deploy to netlify.

## Prerequisites
To complete this tutorial , you need to have:
- Node.js and NPM installed locally. Visit [article from Teamtreehouse](https://treehouse.github.io/installation-guides/windows/node-windows.html) for instructions on installing Node.js and NPM on your local machine
- Basic understanding of sveltejs/sapper. 
- Basic understanding of strapi. [click to know more](https://docs.strapi.io/developer-docs/latest/getting-started/introduction.html)
- Git and GitHub
- Netlify account

## What is Sapper?
Sapper is a web application framework with a beautiful development experience and flexible filesystem-based routing.

Sapper, unlike single-page apps, does not compromise SEO, progressive enhancement, or the initial load experience. However, unlike traditional server-rendered apps, navigation is instantaneous for that app-like feel. It is a svelte-powered application that creates bigger apps with a smaller footprint.

## What is Strapi?
Strapi is an open-source, Node. js-based, headless CMS that saves developers time while allowing them to use their favorite tools and frameworks. Strapi also enables content editors to streamline content delivery (text, images, video, etc.) across any device. Visit [strapi documentation](http://ocs.strapi.io/developer-docs/latest/getting-started/introduction.html) page for more details. 

## Project Setup
Let's begin setting up our project. 

### Strapi Installation
Before we begin the installation process, make sure that **Node.js** and **NPM** are fully installed on your system.

- Use the following command to start a new project.
```bash
       npx create-strapi-app@latest my-project --quickstart
```
- Change `my-project` to the preferred name of your project. Select `n` when asked for a configuration template.
- Wait for the complete installation. You will be redirected to [http://localhost:1337/admin](http://localhost:1337/admin), where you will be prompted to register your details.
![Strapi Welcome Page](https://paper-attachments.dropbox.com/s_26318BFB0DBB8D55A14941CF89BF292237118B44753A4C89AB918929BA1932E8_1650511264132_new+strapi1.PNG)
- Add your details and click **LET’S START** to access the Strapi dashboard.
![The Strapi Dashboard](https://paper-attachments.dropbox.com/s_26318BFB0DBB8D55A14941CF89BF292237118B44753A4C89AB918929BA1932E8_1650511300559_new+strapi2.PNG)



## Building the Project
In this phase, start by creating a new collection type **Jobs** with the following content and field types as shown below:
- Name             
- Salary            
- Experience  

![Content Architecture Screenshot](https://paper-attachments.dropbox.com/s_480CA2CD7567A4F46D7F68D596F156F4E4B52EDCE9074CAEBFF2E800B8E2D5D1_1659793985637_new-p1.PNG)

Also, create another collection type  **"Job_type"** with content **"Name"**.

![Content Type Screenshot](https://paper-attachments.dropbox.com/s_480CA2CD7567A4F46D7F68D596F156F4E4B52EDCE9074CAEBFF2E800B8E2D5D1_1659794144626_new-p2.PNG)

Then, add a relation for the two collection types. In the collection type `Job_type` field `Name`, click on add **new entry** and select the require field for the relation.

![Content Type Screenshot](https://paper-attachments.dropbox.com/s_480CA2CD7567A4F46D7F68D596F156F4E4B52EDCE9074CAEBFF2E800B8E2D5D1_1659940648012_sapper9.PNG)

Next, head over to **Settings**, navigate to **Roles,** and click on **Public**. Scroll down to **Permissions**,  click on `Jobs` and `Job_type`, then click on "select all" to allow all activities for the application and save.

## Installing Sapper
Sapper installation is very easy; copy and paste the following command on your terminal/cmd.
```bash
     npx degit "sveltejs/sapper-template#rollup" my-app
    # or: npx degit "sveltejs/sapper-template#webpack" my-app
    cd my-app
    npm install
    npm run dev
```
 
The above command install the project's dependencies, scaffold a new project in the my-app directory, and launch a server. Now that you are done with the installation process, start building the project.


## Developing the Frontend
After installing all the necessary packages for developing our front end, we should run the command `npm run dev` to begin working on the front end. After that, a display showing the local address will appear on your cmd screen: `http://localhost:3000`.

This local address can be copied and pasted into your browser to bring up the Sapper page. Next, open the sapper folder in your code editor, navigate to `src/component/nav.svelte`; copy and paste the following code.

```js
    <script>
      export let segment;
      const handleClick = () => {
        console.log(segment);
      };
    </script>
    <nav>
      <div>
        <h1 on:click={handleClick}>JOB FORAGE</h1>
        <ul>
          <li><a class:current={segment === undefined} href=".">Home</a></li>
          <li><a class:current={segment === "about"} href="about">About</a></li>
          <li>
            <a class:current={segment === "contact"} href="contact">Contact</a>
          </li>
          <li><a class:current={segment === "Jobs"} href="Jobs">Jobs</a></li>
        </ul>
      </div>
    </nav>
    <style> 
      nav {
        background: #fff3ef;
      }
      nav div {
        max-width: 960px;
        padding: 0 10px;
        margin: 0 auto;
        display: grid;
        grid-template-columns: 1fr 1fr;
        text-align: center;
      }
      h1 {
        margin-top: 20px;
        font-size: 30px;
        font-weight: bold;
        /* display:flex; */
        text-align: left;
      }
      ul {
        padding: 0;
        margin: 0;
        text-align: right;
      }
      li {
        display: inline-block;
      }
      a {
        text-decoration: none;
        padding: 1em 0.5em;
        display: block;
      }
      a.current {
        border-bottom: 3px solid #ff3e00;
      }
    </style>
```
 
Click on `src/component/footer.svelte`, and include the code below. 
```html
    <footer>copyright 2022 by Opuama Lucky</footer>
    <style>
      footer {
        color: #bbb;
        text-align: center;
        padding: 20px;
        max-width: 400px;
        margin: 40px auto 0;
        border-top: 1px solid #f2f2f2;
      }
    </style>
```    

The code above should display both the nav bar and the footer in your browser.

For the homepage, navigate to `src/routes/index.svelte`;  copy and paste the codes below. 
```html
     <svelte:head>
      <title>Begining sapper</title>
    </svelte:head>
    <div>
      <img src="jet.jpg" alt="" />
      <h1>Job Nina</h1>
      <p>find your next assignment right here</p>
      <a href="Jobs" class="btn">View Job</a>
    </div>
    <style>
      h1,
      p {
        text-align: center;
        margin: 0 auto;
      }
      h1 {
        font-size: 2em;
        text-transform: uppercase;
        font-weight: 700;
        margin: 0 0 0 0.5em 0;
      }
      img {
        width: 200px;
        margin: 0 auto;
        display: block;
      }
      a {
        margin: 40px;
      }
      div {
        margin-top: 60px;
        text-align: center;
      }
      @media (min-width: 480px) {
        h1 {
          font-size: 4em;
        }
      }
    </style> 
```

Unfortunately, you will not see anything on your browser because we have not yet decided how our project should look. To fix this, navigate to `src/routes/ layout.svelte` and enter the following code. The code below assists us in arranging our project.

```js
    <script>
      import Nav from "../components/Nav.svelte";
      import Footer from "../components/Footer.svelte";
      export let segment;
    </script>
    <Nav {segment} />
    <main>
      <slot />
    </main>
    <Footer />
    <style>
      main {
        position: relative;
        max-width: 960px;
        padding: 60px 10px;
        margin: 0 auto;
      }
    </style> 
```

## Connecting Strapi 
Before we begin, we must install axios in order to send asynchronous HTTP requests easily. [Click here to know more about axios](https://axios-http.com/docs/intro).

Run the following command on cmd /terminal
```bash
    npm install axios
    or
    yarn add axios
```

Navigate to the routes folder and create a folder `Jobs`. Create a file `index.svelte` with the following codes (`src/routes/Jobs/index.svelte`).

```js
    <script>
      import { onMount } from "svelte";
      import axios from "axios";
      let jobs = [];
      let error = null;
      
      const getJobs = () => {
        axios.get("http://localhost:1337/api/Jobs").then((res) => {
          jobs = res.data.data;
          console.log(jobs\["id"\]["attributes"]["Name"]);
          return { jobs };
        });
      };
      onMount(getJobs);
    </script>
    <style>
      ul{
        padding:0px;
      }
      li{
        list-style-type:none;
        padding: 10px;
       
      }
      ol li {
        font-weight: bold;
        font-size: 24px;
      }
        .btn{
        display:block;
        padding:15px;
        border:1px solid #6b3fca;
        border-radius:8px;
        background-color: #6b3fca;
        margin:10px auto;
        text-decoration:none;
      }
       a:hover{
        background-color:#9f43e5;
      }
      div{
        text-align:center;
      }
       ol li ul{
        display:none;
    }
     ol li:hover ul{
        display: block;
    }
    </style>
    <main>
    <div>
      <h1>All Current Jobs</h1>
      <hr />
      </div>
      {#await jobs}
        loading...
      {:then jobs}
        <ol>
          {#each jobs as jobs}
            <li > {jobs\["attributes"\]["Name"]}
              <ul>
                <li>Salary:  ${jobs\["attributes"\]["Salary"]}</li>
                <li>Job Requirement:  {jobs\["attributes"\]["Experience"]}</li>
              </ul>
            </li>
          {/each}
        </ol>
      {:catch error}
        {error}
      {/await}
      <div>
        <a href="/Jobs/create" class="btn" >Add a Job </a>
      </div>
    </main>
```    

In the above code, we imported **axios** and ***onMount***  life cycle, which provides a way to run a function when the component is loaded to the DOM. It can be used to initialize values and call API to load. Following that, apply a get request to fetch data from our Strapi backend.

Next, navigate to the `routes` folder again and create a folder `Jobs`. Create a file `create.svelte` with the following code (`src/routes/Jobs/create.svelte`).

```html
    <style>
    h2{
        text-align: center;
    }
    form{
        max-width: 360px;
        margin:40px auto;
        text-align:center;
    }
    input, textarea{
    display:block;
    width:100%;
    padding:10px;
    font-family:arial;
    margin:10px auto;
    border:1px solid #eee;
    border-radius:8px;
    }
    </style>
    
    
    <script>
        import { onMount } from 'svelte';
        import axios from 'axios'
        
        let allJob_type = [];
        let title = "";
        let salary = "";
        let Jobtype = [];
        let details = "";
        let error = null;
        
        
        async function handleSubmit() {
            try {
                const response = await axios.post("http://localhost:1337/api/Jobs", {
                   data: { Name: title,
                    Salary: salary,
                    Experience: details,
                    Job_types: Jobtype,
                   },
                });
                Jobtype=response.data.data
                
            } catch(e) {
                error = e
            }
        }
        onMount(async () => {
        try {
            const response = await axios.get('http://localhost:1337/api/job-types');
            allJob_type = response.data.data
            console.log(allJob_type);
        } catch(e) {
            error = e
        }
    });
        
        </script>
        
        {#if error !== null}
          {error}
        {:else}
           <h2>Add a Job </h2>
           <form>
            <input type ="text" placeholder="Job Title" bind:value={title} required >
            <input type ="number" placeholder="Amount $" bind:value={salary}  required >
            <textarea type ="text" placeholder="Job Requirement" bind:value={details}  required></textarea> 
             <br />
            Select Job_type
            <br />
            {#each allJob_type as jobtype}
                <label>{jobtype\["attributes"\]["name"]}</label>
              <input type="checkbox" bind:group={Jobtype} value={jobtype} />
            {/each} 
            <input type="submit" value="Submit" on:click={handleSubmit} />
        </form>
        
        {/if}
```

In the above code, we declare all of the variables required, and then we define a function handleSubmit to post/insert data to the API and a get request to retrieve the data.
 
Here is our Home page.
![Home page](https://paper-attachments.dropbox.com/s_480CA2CD7567A4F46D7F68D596F156F4E4B52EDCE9074CAEBFF2E800B8E2D5D1_1659934524856_sapper3.PNG)

Here, `Job/index.svelt` is showing all available jobs. Click on **"Add a Job".**

![Available Jobs](https://paper-attachments.dropbox.com/s_480CA2CD7567A4F46D7F68D596F156F4E4B52EDCE9074CAEBFF2E800B8E2D5D1_1659934586864_sapper5.PNG)

You will be directed to the `Jobs/create` page after clicking the **Add a Job** button. Fill out the form and submit it.

![Form](https://paper-attachments.dropbox.com/s_480CA2CD7567A4F46D7F68D596F156F4E4B52EDCE9074CAEBFF2E800B8E2D5D1_1659934721833_sapper8.PNG)

After submitting the form, your information will appear as shown in the image below.

![Form result](https://paper-attachments.dropbox.com/s_480CA2CD7567A4F46D7F68D596F156F4E4B52EDCE9074CAEBFF2E800B8E2D5D1_1659934780562_sapper6.PNG)

Go to Strapi database and refresh.

![Updated data](https://paper-attachments.dropbox.com/s_480CA2CD7567A4F46D7F68D596F156F4E4B52EDCE9074CAEBFF2E800B8E2D5D1_1659934845553_sapper7.PNG)

## Push to GitHub and Deploy to Netlify

In this phase, we will push our Sapper project to GitHub. If you are new to GitHub, [follow this article](https://product.hubspot.com/blog/git-and-github-tutorial-for-beginners) and you will be fine. [Click here to sign up](https://github.com/) as well.

After successfully pushing to GitHub, a similar image should appear on your git repo.

![push confirmation](https://paper-attachments.dropbox.com/s_480CA2CD7567A4F46D7F68D596F156F4E4B52EDCE9074CAEBFF2E800B8E2D5D1_1661983592326_sapper10.PNG)

Let us now deploy to Netlify. If you are new, [sign up and register.](https://app.netlify.com/signup) Once logged in, click on create new site and select import from an existing project. Choose GitHub, search for the GitHub repo, and continue. Update your **build command** to `npm run export`  then deploy.

![netlify deploy](https://paper-attachments.dropbox.com/s_480CA2CD7567A4F46D7F68D596F156F4E4B52EDCE9074CAEBFF2E800B8E2D5D1_1661985866703_sapper11.PNG)

## Testing the Project

Before testing the project, ensure that Strapi app is still running on your system. To run Strapi app,
```bash
    npm run develop   
```
Still on Netlify, click on **open production deploy.** 

![after deploy](https://paper-attachments.dropbox.com/s_480CA2CD7567A4F46D7F68D596F156F4E4B52EDCE9074CAEBFF2E800B8E2D5D1_1661986780063_sapper14.PNG)

![screenshot](https://paper-attachments.dropbox.com/s_480CA2CD7567A4F46D7F68D596F156F4E4B52EDCE9074CAEBFF2E800B8E2D5D1_1661986560908_sapper13.PNG)

## Conclusion
Congratulations, we have reached the end of this tutorial. If you followed the steps in this tutorial, your project should be working fine.

We were able to create collection types and establish a relationship between them. We fetched and submitted data to our Strapi backend, pushed to github and also deployed to Netlify. You can add more features to your project as well.

Here is [the link to the GitHub repository](https://github.com/lucky4242/sapper) for this tutorial.