Simple svelte demo deployed in Netlify
Tags: svelte, javascript, netlify
Published: 2019-08-29 19:42:35

I was learning Svelte, and i created a simple project to explain some functionalities.

Before to begin, always you can found the source code in gitlab https://gitlab.com/edades/cart-svelte and the deployed project in Netlify 
https://silly-liskov-fc7aa8.netlify.com/


###Create a Svelte project.

You have two options:
1- Build you own environment with rollup and create your configuration files and scrips.

2- Get a clean/simple project from svelte repo.

```
npx degit sveltejs/template my-svelte-project
cd my-svelte-project
npm install
npm run dev
```

###Folder Structure
For this example i created the follow structure:

-src
--Components
---ContentBox.svelte
---Header.svelte
---Product.svelte
--Store
---store.js
--Views
---Home.svelte
--App.svelte
--main.js
--products.js

i came from react world and, i tried to maintain a similar folder structure with containers(views) and components.
Also i created a products.js for get static products data.


the main file put the application into document.body
```javascript
import App from './App.svelte';

const app = new App({
	target: document.body
});

export default app;
```

And in our App.svelte we can import our (in this case) containers components (views).

```javascript
<script>
	import HomeLayout from './Views/Home.svelte';
</script>

<HomeLayout />
```

First, we've the javascript code and below the component.

Now, let's to see the Views/Home.svelte component.

```javascript
<script>
  import Header from '../Components/Header.svelte';
  import ContentBox from '../Components/ContentBox.svelte';
  import productsJson from '../products.js'
  import { onMount } from 'svelte';

  let products


  onMount(() => {
    products = productsJson
  })
</script>

<div class="container-home">
  <Header />
  <ContentBox products={products} />
</div>
```

First, we can import the components that we going to use, also we import the productsJson. and also we going to use a function from svelte life cycle *onMount*

`let products` is our state for store the data from productsJson (or returned data from any service).
so, in onMount function we can to do this assignament.

Note that in `<ContentBox products={products} />` we are passing the product list to the component. we going to see this later.

now, let's see the Header component.
here we can found some more fun.

This component is more large, so if you want to see the full source code, please go to https://gitlab.com/edades/cart-svelte/blob/master/src/Components/Header.svelte

In top on the code, we have the styles rules.
```css
<style>
  .header {
    height: auto;
    width: 100%;
    background: skyblue;
    box-sizing: border-box;
    padding: 7px;
  }
  .header .menu {
    display: flex;
    align-items: center;
    list-style-type: none;
    justify-content: flex-end;
  }
  .
  .
  .
</style>
```

in the middle we have the javscript content.

```javascript
<script>
  const logoUrl = 'http://placehold.it/180x60';
  let menuOptions = [
    {
      title: 'Option 1',
      url: '#',
      active: false
    },
    {
      title: 'Option 2',
      url: '#',
      active: false
    },
    {
      title: 'Option 3',
      url: '#',
      active: false
    }
  ];

  const setActivate = ({ title }) => {
    menuOptions = menuOptions.map(item => ({
      ...item,
      active: item.title === title
    }))
  }
</script>
```

`const logoUrl` is a simple constant for store the logo url, we can use this directly in the code.

`let menuOptions` is a state (in vue or react), and here we manage the menu options.

`const setActivate` is a function that modify the state 'menuOption'. we pass a title, and set the item from array when the title be equal to select item in the menu.


after this, we have the html code.

```html
<li class="logo"><img src={logoUrl} alt="logo" /></li>
{#each menuOptions as option}
  <li
    class="menuItem{option.active ? ' active' : ''}"
    on:click={() => setActivate(option)}>
     {option.title}
  </li>
{/each}
```

1- we user the logoUrl const for get the logo.
2- we use `#each` for iterate the menuOptions array. this is a function from svelte.
3- we use a condition class for active items in the menu using ternary operator.
4- we use `on:click` for override event click and call to the function setActivate for pass the current option


##ContentBox component

- Remember that you can find the full source code for this component here: https://gitlab.com/edades/cart-svelte/blob/master/src/Components/ContentBox.svelte

So, in this component we've some styles in the begin.

after the styles, we've the script content. let's see this:

```javascript
<script>
  import Product from './Product.svelte'
  import { cart } from '../Store/store.js'
  
  export let products = []

  let total = 0

  cart.subscribe(c => {
    total = c
  })

  const removeItem = () =>
    cart.update(c => c - 1)
</script>
```

1- Import the component Product
2- Import the cart store.

---- Let's see how the store works ----
- In the folders of our project, we have Store/store.js.

```javascript
import { writable } from 'svelte/store'

export const cart = writable(0)
```
- Here we are importing the writable function from svelte/store, 
and we create our 'global' state calling `cart`. 
in this case we only have a writable with a int value.
you could have and object, array, string, etc.

--- back to ContenBox component ---

3- this `export let products = []` is the data received by props. and also we are assign it an empty array as default value.

4- `let total = 0` is our local state for store the data from the Store (cart state)

5- `cart.subscribe` is a native function from cart object (store) and it allow to cart state listen the changes and use this new data.
in this case, when the cart state is changed we set out local variable total with the new cart value.

6- `removeItem` is a function that is called when the user press the link for remove items from the cart. and this call a `cart.update` for update the state value with a new value. in this case we are taking the current value and decrease it in 1

Now, from the html side we've the follow code:

```html
<div class="content-box">
  <h1>Product list</h1>
  <div class="cart">
    <h3>You have {total} products in the cart</h3>
    {#if total > 0}
      <a href="javascript:void(0)" on:click={removeItem}>Click to remove an item from cart</a>
    {/if}
  </div>
  <div class="product-cotainer">
    {#each products as product}
      <Product product={product} />
    {/each}
  </div>
</div>
```

1- `<h3>..{total}..</h3>` we are showing our local state `total`, this value changes when the 'global' state cart was changing.

2- We've an if condition for show/hide a link for remove items from the cart.

3- We've an `each` for create a `Product` component dynamically and pass to it a product object as a prop. 


##Product Component

Here we have no new functionality.
So, let's to review the code quickly.

```javascript
<script>
  import { cart } from '../Store/store.js'
  export let product = {}

  const setCart = () => cart.update(total => total + 1)
</script>
```
1- Import the cart store object
2- Receive the product object from the parent (as a prop)
3- `setCart` update the 'global' state cart increase it in 1.

the html side:

```html
<div class="product">
  <picture>
    <img src={product.image} alt="" />
  </picture>
  <div class="product-info">
    <h1>{product.name}</h1>
    <h3>{product.description}</h3>
  </div>
  <div class="product-price">
    <p>{product.price}</p>
    {#if product.stock < 5}
      <strong>¡Hurry up!</strong>
    {/if}
  </div>
  <div class="addtocart">
    <button on:click={setCart}>Add to cart</button>
  </div>
</div>
```

Here we can use the product object for get the product data.
We have an `if` conditional for show/hide a message for the product stock quantity.
And finally we've a button with the click event for update the cart state.

In general this are all the files.
Remember that you can check here the live website: https://silly-liskov-fc7aa8.netlify.com/


____ Deploying on netlify ____

!! First upload you code to Gitlab (in this case, but can use bitbucket or github).
- Create a project https://gitlab.com/projects/new
- Upload repo: 
```
git clone git@gitlab.com:MYUSER/my-fancy-repo.git
cd my-fancy-repo
touch README.md
git add README.md
git commit -m "add README"
git push -u origin master
```
---

Ok, now go to https://www.netlify.com/.
and create a free account.

After, go to https://app.netlify.com/start.
And select the source of you code (gitlab, github, bitbucket)
And finally Select you repo (project)

Now, we need to set our deploy settings.

You need to set the branch (in this case is master)
the build command in this case is: `npm run build` (this command is in the package.json file)
and the publish directory is: `public` (this is the default folder used by svelte for store the build files).

Finally click on 'Deploy Site' :D


Now that you have the site with gitlab and netlify, when you merge code to master branch (in this case), netlify going to re deploy your app with you new changes, fantastic!!

For more svelte documentation please visit https://svelte.dev/ and check the tutorial and the examples sections.

And for routes and server-side features, svelte use Sapper (https://sapper.svelte.dev/).

This is all! See u ;)