Part 3 - Web Development For Entrepreneurs Who Don't Know Where To Begin - Additional Configurations
Tags: webdev, beginners, serverless, javascript
Published: 2020-08-30 03:18:01

---
series: Web Development For Entrepreneurs Who Don't Know Where To Begin
---

In this part I will show you how to configure a few things that will make your life a little easier.

Some of these configurations are optional (e.g. configuring Sass support), but others are requirements for development (e.g. configuring a proxy server).

These configurations are mostly for Routify, but we will do a few things with our Vercel Serverless Functions to test our Routify configs. Vercel provides options to configure your Vercel serverless functions, if you want to do that, but that is not necessary in most cases. Serverless functions are awesome and Vercel makes them super easy for someone who just wants to build apps rather than messing with configuring and managing servers.

## Git Repository
You can reference the finished code in the following GitHub repo. This is also a good place to look if the code in this tutorial contains typos.

https://github.com/SamuelEarl/where-to-begin-entrepreneurs


## Config #1: Configure Routify to access environment variables
You can pass environment variables, like `NODE_ENV`, to your code by adding something like `NODE_ENV=development` to your `npm` scripts, like this:

```json
"dev": "NODE_ENV=development run-p routify nollup",
```

However, in a Routify project you will get the following error if you try to reference those environment variables in your code with `process.env.NODE_ENV`:

```
`ReferenceError: process is not defined`
```

_NOTE: Vercel functions already have access to environment variables through the `process.env` object, so you don't need to configure them to access environment variables._

The problem is that you have to configure Rollup (and Nollup) to handle and then pass any environment variables to your app code. This is what you have to do:

The `@rollup/plugin-replace` package should already be installed, so you shouldn’t have to install it again.

In your `rollup.config.js` file, find the line marked `// (1)` below:

```js
//  rollup.config.js
...
production,
rollupWrapper: rollup => rollup,  // (1)
svelteWrapper: svelte => {
...
```
...and replace it with the code in between the the two comments:

```js
//  rollup.config.js

import replace from '@rollup/plugin-replace';

...
production,
// Replace with all the code between this comment...
rollupWrapper: rollup => {
  rollup.plugins = [
    ...rollup.plugins,
    replace({
      process: JSON.stringify({
        env: {
          NODE_ENV: process.env.NODE_ENV
        }
      }),
    }),
  ]
},
// ...and this comment.
svelteWrapper: svelte => {
...
```
**NOTE:** Remember to also import `@rollup/plugin-replace` at the top of the file.

Let’s test this. In your Routify `package.json` file, update the `dev` script, like this:

```json

"scripts": {
  "dev": "NODE_ENV=development run-p routify nollup",
  ...
},
```

In your `src/App.svelte` file, enter the code from line `(1)`:

```js
//  src/App.svelte

<script>
  import { Router } from "@roxi/routify";
  import { routes } from "../.routify/routes";

  console.log("CLIENT NODE_ENV:", process.env.NODE_ENV);  // (1)
</script>

<style  global>
  @import "../static/global.css";
</style>

<Router {routes} />
```

Now run your development server (`npm start`) and open your browser console (right click anywhere in the browser, select “Inspect”, and click the “Console” tab). You should see this printed to the console:

```
CLIENT NODE_ENV: development
```

_**Source:** https://linguinecode.com/post/how-to-add-environment-variables-to-your-svelte-js-app_


## Config #2: Setup a proxy server
We will use a proxy server to route our client requests through before they are sent to our serverless functions. 

To understand why you have to use a proxy server to route your requests to a server that is running on a different origin, you need to understand two things:

* What is the origin of a URL? This page explains the different parts of a URL: [How to Get Full URL and Parts In Javascript](https://code-boxx.com/url-parts-javascript/).
* What is CORS? If you don’t know what CORS is, then you can take a look at these pages: 
    * [What is CORS?](https://www.codecademy.com/articles/what-is-cors) (Codecademy)
    * [Cross-Origin Resource Sharing (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) (MDN Docs)

_**NOTE:** I was hoping to find an easy solution to configure the Routify dev server to proxy my requests (similar to [what Vue does with Webpack’s dev server](https://cli.vuejs.org/config/#devserver-proxy) or how you can [proxy requests in plain Svelte/Sapper projects](https://stackoverflow.com/questions/62096839/webpack-devserver-proxy-not-working-with-sapper)), but I haven’t been able to get a simple proxy config to work with Routify yet. I will show you what I have done to get a proxy server working in Routify, but if you have a better way to do this, then please share it. I would be very grateful._

### Create Svelte components
In your Routify code, create the following two files:

* `/src/components/Button.svelte`
* `/src/pages/test/index.svelte`

Now place the following code in those files:

```vue
<!-- src/components/Button.svelte -->

<template>
  <button on:click>
    <slot>Default Button Text</slot>
  </button>
</template>

<style>
  button {
    padding: 10px 25px;
    border-radius: 5px;
    outline: none;
    border: 1px solid lightgray;
    background-color: white;
    box-shadow: 2px 2px 2px lightgray;
    color: #333;
    cursor: pointer;
  }

  button:hover {
    box-shadow: none;
  }
</style>
```

```vue
<!-- src/pages/test/index.svelte -->

<template>
  <h1>Click these buttons to test the API calls</h1>

  <div>
    <Button on:click={handlePayload}>Test Payload</Button>
    &nbsp;
    <Button on:click={handleParams}>Test Params</Button>
  </div>

  <br><br>

  {#if firstNameRes && lastNameRes}
    <div>Test Payload Response: { firstNameRes } { lastNameRes }</div>
  {:else if nameRes}
    <div>Test Params Response: { nameRes } </div>
  {:else}
    <div>Waiting for test response...</div>
  {/if}
</template>

<script>
  import Button from "../../components/Button.svelte";

  let firstNameRes = "";
  let lastNameRes = "";
  let nameRes = "";

  const handlePayload = async () => {
    try {
      firstNameRes = "";
      lastNameRes = "";
      nameRes = "";

      const url = "/api/name";
      let response = await fetch(url, {
        method: "POST",
        body: JSON.stringify({
          firstName: "John",
          lastName: "Doe"
        })
      });

      let result = await response.json();
      console.log("TEST PAYLOAD RESULT:", result);
      firstNameRes = result.body.firstName;
      lastNameRes = result.body.lastName;
    }
    catch(err) {
      console.log("TEST PAYLOAD ERROR:", err);
    }
  };

  const handleParams = async () => {
    try {
      firstNameRes = "";
      lastNameRes = "";
      nameRes = "";

      const firstName = "Jane";
      const lastName = "Doe";
      const name = `${firstName} ${lastName}`;

      const url = `/api/${name}`;
      let response = await fetch(url, {
        method: "GET"
      });

      let result = await response.json();
      console.log("TEST PARAMS RESULT:", result.query);
      nameRes = result.query.name;
    }
    catch(err) {
      console.log("TEST PARAMS ERROR:", err);
    }
  };
</script>
```



With your code running in dev mode, visit http://localhost:5000/test in your browser. You should see a heading “Click these buttons to test the API calls” with two buttons below it.

### Create Vercel serverless functions
In your Vercel code, create the following two files:

* `/api/name.js`
* `/api/[name].js`

...and place the following code snippets in their respective files:

```js
//  api/name.js

module.exports = async (req, res) => {
  console.log("API NODE_ENV:", process.env.NODE_ENV);

  try {
    // You can access values from `req.body` in any
    // of the following ways:
    const payload = JSON.parse(req.body);
    console.log("PAYLOAD:", payload);

    const { firstName } = JSON.parse(req.body);
    console.log("FIRST NAME:", firstName);

    const { lastName } = JSON.parse(req.body);
    console.log("LAST NAME:", lastName);

    // If there are no errors, then return your data as a
    // JSON object and give it a status code of 200.
    res.status(200).json({
      body: { firstName, lastName },
    });
  }
  catch(err) {
    console.log("name.js Error:", err);
    // If there are errors, then return the error object
    // as a JSON object with a 500 status code.
    res.status(500).json(err);
  }
};
```

**CODE NOTES:**
* The values in `req.body` are called "request body parameters" and are often referred to as the "request payload".
* Values from POST, PUT, and DELETE requests will be stored in `req.body`.
* The request body is an object that gets converted to a string before it is sent across the network to the server. That string needs to be converted back into an object before you can work with the payload data. You have to use `JSON.parse()` to convert the payload into an object.

```js
//  api/[name].js

module.exports = async (req, res) => {
  console.log("API NODE_ENV:", process.env.NODE_ENV);

  try {
    // You can access values from the `req.query` object
    // in any of the following ways:
    const params = req.query;
    console.log("PARAMS:", params);

    let { name } = req.query;
    console.log("NAME:", name);

    name = req.query.name;
    console.log("NAME (AGAIN):", name);

    // If there are no errors, then return your data as a
    // JSON object and give it a status code of 200.
    res.status(200).json({
      query: { name },
    });
  }
  catch(err) {
    console.log("[name].js Error:", err);
    // If there are errors, then return the error object
    // as a JSON object with a 500 status code.
    res.status(500).json(err);
  }
};
```

**CODE NOTES:**
* The values in `req.query` are of two types: (1) path parameters and (2) query parameters. Both types of parameters are made available on the `req.query` object. You can read more here: [Path Segments](https://vercel.com/docs/serverless-functions/introduction#path-segments).
* Values from GET requests will be stored on the `req.query` object.
* The parameters that are sent through a GET request are already in object format, so you do not have to convert them into an object first before you can use them.
* When you test this code, you will notice that the key in the `params` object is the same as the name of this file. Files whose names are wrapped with [square brackets] use dynamic names. You should give your dynamic file names meaningful names that reflect the data being passed to them. You can read more here: [Path Segments](https://vercel.com/docs/serverless-functions/introduction#path-segments).

### Test the API without a proxy server
To show you what happens before the proxy server is configured, make sure your code is running in dev mode: `npm start`.

In your browser, go to  http://localhost:5000/test, open the browser console (right click anywhere in the browser, select “Inspect”, and click the “Console” tab), click the buttons and observe what happens. 

You will see errors indicating that the browser request couldn’t find the server. If you look at the terminal window where you ran `npm start`, you will not see any activity. This is also an indicator that the requests never made it to the server.

Now let’s create a proxy server to fix this problem.

### Configure the proxy server
Install the [`cors-anywhere`](https://www.npmjs.com/package/cors-anywhere) package in your project:

```
npm install --save-dev cors-anywhere
```

Inside the Routify `scripts` folder, create a file named `proxy.js` and copy and paste this code:

```js
//  scripts/proxy.js

export default function() {
  // Listen on a specific host via the HOST environment variable
  const host = process.env.HOST || "localhost";
  // Listen on a specific port via the PORT environment variable
  const port = process.env.PORT || 8080;

  const cors_proxy = require("cors-anywhere");
  cors_proxy.createServer({
    originWhitelist: [], // Allow all origins
    requireHeader: ["origin", "x-requested-with"],
    removeHeaders: ["cookie", "cookie2"]
  }).listen(port, host, function() {
    console.log("Running CORS Anywhere on " + host + ":" + port);
  });
};
```

This is your proxy server code. _(NOTE: That code is taken from the example code in the `cors-anywhere` repo and you can look there for more info.)_

Now import the proxy server code into the `/scripts/base.config.js` file and invoke the proxy server to start it up. There are two lines of code that you need to enter and they are marked like this in the snippet below:

```js
// (1) Enter the following line:

// (2) Enter the following line:
``` 

However, there is a lot of configuration code in this file, so it might also be helpful to reference [the code for this file in the Git repo](https://github.com/SamuelEarl/where-to-begin-entrepreneurs/blob/master/scripts/base.config.js).

```js
//  scripts/base.config.js

// Other imports are here...
// (1) Enter the following line:
import proxy from "./proxy.js";

...

const _rollupConfig = {
  inlineDynamicImports: !dynamicImports,
  preserveEntrySignatures: false,
  input: `src/main.js`,
  output: {
    name: 'routify_app',
    sourcemap: true,
    ...outputConfig
  },
  plugins: [
    copy({
      targets: [
        { src: [`${staticDir}/*`, "!*/(__index.html)"], dest: distDir },
        { src: [`${staticDir}/__index.html`], dest: distDir, rename: '__app.html', transform },
      ],
      copyOnce: true,
      flatten: false
    }),
    svelte(svelteConfig),

    // resolve matching modules from current working directory
    resolve({
      browser: true,
      dedupe: importee => !!importee.match(/svelte(\/|$)/)
    }),
    commonjs(),

    // Start the proxy server when this is not a production build.
    // (2) Enter the following line:
    !production && proxy(),

    production && terser(), // minify
    !production && isNollup && Hmr({ inMemory: true, public: staticDir, }), // refresh only updated code
    !production && !isNollup && livereload(distDir), // refresh entire window when code is updated
  ],
  watch: {
    clearScreen: false,
    buildDelay: 100,
  }
}
...
```

Now we need to reference the proxy server when we make API calls to the Vercel functions. Open your `src/pages/test/index.svelte` file and add `"PROXY_URL"` to the beginning of the values of the two `url` variables, like this:

```vue
<!-- src/pages/test/index.svelte -->

<template>
  <h1>Click these buttons to test the API calls</h1>

  <div>
    <Button on:click={handlePayload}>Test Payload</Button>
    &nbsp;
    <Button on:click={handleParams}>Test Params</Button>
  </div>

  <br><br>

  {#if firstNameRes && lastNameRes}
    <div>Test Payload Response: { firstNameRes } { lastNameRes }</div>
  {:else if nameRes}
    <div>Test Params Response: { nameRes } </div>
  {:else}
    <div>Waiting for test response...</div>
  {/if}
</template>

<script>
  import Button from "../../components/Button.svelte";

  let firstNameRes = "";
  let lastNameRes = "";
  let nameRes = "";

  const handlePayload = async () => {
    try {
      firstNameRes = "";
      lastNameRes = "";
      nameRes = "";

      const url = "PROXY_URL" + "/api/name";
      let response = await fetch(url, {
        method: "POST",
        body: JSON.stringify({
          firstName: "John",
          lastName: "Doe"
        })
      });

      let result = await response.json();
      console.log("TEST PAYLOAD RESULT:", result);
      firstNameRes = result.body.firstName;
      lastNameRes = result.body.lastName;
    }
    catch(err) {
      console.log("TEST PAYLOAD ERROR:", err);
    }
  };

  const handleParams = async () => {
    try {
      firstNameRes = "";
      lastNameRes = "";
      nameRes = "";

      const firstName = "Jane";
      const lastName = "Doe";
      const name = `${firstName} ${lastName}`;

      const url = "PROXY_URL" + `/api/${name}`;
      let response = await fetch(url, {
        method: "GET"
      });

      let result = await response.json();
      console.log("TEST PARAMS RESULT:", result.query);
      nameRes = result.query.name;
    }
    catch(err) {
      console.log("TEST PARAMS ERROR:", err);
    }
  };
</script>
```

Now we need to use a Rollup plugin to replace that `"PROXY_URL"` variable with the proxied URL during development and the non-proxied URL during production.

Open the `rollup.config.js` file and add another property to the `replace` plugin:

```js
//  rollup.config.js

...
rollupWrapper: rollup => {
  rollup.plugins = [
    ...rollup.plugins,
    replace({
      process: JSON.stringify({
        env: {
          NODE_ENV: process.env.NODE_ENV
        }
      }),
      // Add the following config:
      "PROXY_URL": production ? "" : `http://localhost:${process.env.PORT}/http://localhost:3000`,
    }),
  ]
},
...
```

**CODE NOTES:**
* During development the `PROXY_URL` will equal the proxy server's URL origin + the Vercel dev server's URL origin with a forward slash in between the two.
* When a production build is created, the `PROXY_URL` will be an empty string (i.e. it won’t exist).

That’s it. Now when you create the URLs for your API calls, you just need to remember to include `"PROXY_URL"` at the beginning of each URL. 

_**Source:** https://www.youtube.com/watch?v=EHikjXtRp_k&t=2004s_


### Test the API with a proxy server
Let’s test our API now with a proxy server. Run your code in dev mode: `npm start`. In your browser, go to  http://localhost:5000/test, open the browser console (right click in the browser, select “Inspect”, and click the “Console” tab), click the buttons and observe what happens.

This time you should see data being returned to the browser console instead of errors. You should also see activity in the terminal window where you ran `npm start`, which is an indication that the requests made it to your server.

## Config #3: Use absolute file paths
You can configure file path aliases that allow you to use absolute file paths. So instead of this:

```vue
<script>
  import Button from "../../components/Button.svelte";
</script>
```

You can use something like this:
 
```vue
<script>
  import Button from "@/components/Button.svelte";
</script>
```

_**NOTE:** This does not apply to importing SCSS files in the `<style>` tag. This only applies to importing files into the `<script>` tag. SCSS files have to be imported using relative paths._

Install the `@rollup/plugin-alias` package as a `devDependency`:

```
npm install --save-dev @rollup/plugin-alias
```

Now import `path` and `@rollup/plugin-alias` into your `rollup.config.js` file and configure the plugin:

```js
//  rollup.config.js

// (1) Import path and @rollup/plugin-alias:
import path from "path";
import alias from "@rollup/plugin-alias";
// Other imports are here...

const production = !process.env.ROLLUP_WATCH;

export const config = {
  ...
  rollupWrapper: rollup => {
    rollup.plugins = [
      ...rollup.plugins,
      replace({
        process: JSON.stringify({
          env: {
            NODE_ENV: process.env.NODE_ENV
          }
        }),
        "PROXY_URL": production ? "" : `http://localhost:${process.env.PORT}/http://localhost:3000`,
      }),
      // (2) Add all the code between this comment...
      alias({
        resolve: [".svelte", ".js"],
        entries: [
          { find: "@", replacement: path.resolve(__dirname, "src") },
        ]
      }),
      // (2) ...and this comment.
    ]
  },
  ...
}
```

Now you can use imports like this:

```vue
<script>
  import Button from "@/components/Button.svelte";
</script>
```

I like to associate the `@` symbol with the `src` directory, which is why I used the `@` symbol in the previous config. But you can associate any symbol or word with any directory in your project. You can also create multiple file path aliases. For example, you could do something like this:

```js
alias({
  resolve: [".svelte", ".js"],
  entries: [
    { find: "pages", replacement: path.resolve(__dirname, "src/pages") },
    { find: "components", replacement: path.resolve(__dirname, "src/components") },
    { find: "utils", replacement: path.resolve(__dirname, "src/utils") },
  ]
}),
```

Then you could use imports like this:

```vue
<script>
  import Section from "pages/Section.svelte";
  import Button from "components/Button.svelte";
  import { date } from "utils/format.js";
</script>
```

Let’s test this. In your `/src/pages/test/index.svelte` file, change the `Button` component import to this:

```vue
<!-- src/pages/test/index.svelte -->

<script>
  import Button from "@/components/Button.svelte";

  ...
</script>
```

Now run your code in dev mode and make sure that you do not get errors. If there are no errors, then the `Button.svelte` file has been imported correctly. 

_**Source:** https://dev.to/sjafferi/absolute-paths-in-svelte-488c_


## Config #4: Configure Routify for Sass support
Install these packages as `devDependencies`:

```
npm install --save-dev postcss autoprefixer node-sass
```

Go to your `rollup.config.js` file and indent the following numbered lines of code...

```js
//  rollup.config.js

...
  svelteWrapper: svelte => {
    svelte.preprocess = [
      autoPreprocess({
        postcss: { plugins: [postcssImport()] },  // (1)
        defaults: { style: 'postcss' }
      })]                                         // (2)
  },
...
```

...to look like this:

```js
//  rollup.config.js

...
svelteWrapper: svelte => {
  svelte.preprocess = [
    autoPreprocess({
      postcss: {                      // (1)
        plugins: [                    // (2)
          postcssImport(),            // (3)
        ],                            // (4)
      },                              // (5)
      defaults: { style: "postcss" }
    }),                               // (6)
  ]                                   // (7)
},
...
```

Now add this numbered line:

```js
//  rollup.config.js

...
svelteWrapper: svelte => {
  svelte.preprocess = [
    autoPreprocess({
      postcss: {
        plugins: [
          postcssImport(),
          require("autoprefixer"),  // (1)
        ],
      },
      defaults: { style: "postcss" }
    }),
  ]
},
...
```

Now if you add `lang="scss"` to your style tags, you can import SCSS files and use SCSS syntax in your components. 

Let’s test that. Create a `src/scss` directory with a `variables.scss` file inside and add this code:

```scss
/*  src/scss/variables.scss */

$text: #333;
```

Then in `src/components/Button.svelte` update the `<style>` tag and the code inside, like this:

```vue
<!-- src/components/Button.svelte -->

<style lang="scss">
  @import "../scss/variables.scss";

  button {
    padding: 10px 25px;
    border-radius: 5px;
    outline: none;
    border: 1px solid lightgray;
    background-color: white;
    box-shadow: 2px 2px 2px lightgray;
    color: $text;
    cursor: pointer;
    &:hover {
      box-shadow: none;
    }
  }
</style>
```

Now when you run your code in dev mode and visit http://localhost:5000/test you should see that your buttons are styled by the color variables.


_**Source:** https://medium.com/@sean_27490/svelte-sapper-with-sass-271fff662da9_


## Config #5: .vercelignore
Create a `.vercelignore` file in your project root directory and add the build output directory to .vercelignore so that your project is rebuilt with each deployment.

```bash
#  .vercelignore

/dist
```

If you configure your output directory to be named something else, then make sure to add the name of that directory here instead.


_**Source:** https://vercel.com/guides/upgrade-to-zero-configuration_


## Test a live deployment
We made a lot of changes to our code. To make sure that everything is still working properly, let's test another live deployment.

Add, commit, and push your code to your `master` branch. Visit your Vercel dashboard, click on your project, and wait for it to finish building. Once it has finished building, visit one of the preview URLs that Vercel provides, add `/test` to the end of the URL, and click the buttons to make sure that the serverless functions are responding.

If that worked, then you are just about ready to start creating your project.


## Other considerations
Here are some additional things to consider when working with Svelte components:


### Configure Visual Studio Code to recognize Svelte syntax
If you use Visual Studio Code, then do this to get VS Code to recognize Svelte syntax:

Install the “Svelte for VS Code” extension.

After that is installed, you will probably have to configure the “Svelte for VS Code” extension with the path where Node.js is installed on your computer. In VS Code open the Settings page (Code  > Preferences > Settings _**or**_ File > Preferences > Settings, depending on your operating system) and search for “svelte”. Toward the top, you should see  “Svelte > Language-server: Runtime”. You will need to enter your Node.js path in that input field. 

If you use NVM to manage your Node versions, then this is how you will find your Node path: 

Open a terminal window and type `which node`. You will see a path like this: 

```
/home/<replace_this_with_your_directory_name>/.nvm/versions/node/v12.16.1/bin/node
```

The problem is that that path is specifically for `v12.16.1`. If you ever update your Node.js version, then the Svelte Language Server probably won’t work anymore. However, you can use only part of that path, which does not specify a particular Node.js version. Enter this into the “Svelte > Language-server: Runtime” input field:

```
/home/<replace_this_with_your_directory_name>/.nvm/versions/node
```

The Svelte Language Server should work and continue working even if you change the Node version on your computer.

If you do not use NVM to manage your Node versions, then you will probably see a path like this when you type `which node`:

```
/usr/local/bin/node
```

If so, then you can simply enter that path into the “Svelte > Language-server: Runtime” input field.

After editing the Svelte syntax configs in VS Code, you will need to close the files that are open or maybe even close the VS Code window that has your Svelte/Routify project open. When you reopen the files (or the project), then the settings should take effect.

If you still have issues with valid SCSS being highlighted with errors, then you might need to install the “SCSS Style Tag” VS Code extension.

_**Source:** https://medium.com/@sean_27490/svelte-sapper-with-sass-271fff662da9_


### Global styles vs Reusable components
Svelte scopes component styles by default, so using global styles that are automatically imported into each component is difficult (or maybe even impossible without some additional configurations). However, the purpose of a component system is to create reusable components rather than global styles. So you should style your components and then reuse those components (e.g. buttons, form inputs, etc) throughout your app instead of using global styles. You can refer to the `Button.svelte` component in this tutorial as an example of a reusable component.

I like to create a `/static/scss/` folder and place three files in there:

* `_media-queries.scss`
* `_colors.scss`
* `variables.scss`

You might want to use additional variable files. I import the media queries and colors into the `variables.scss` file and then I import the `variables.scss` file into the components that need to reference those variables. When creating an app using components you should leave the global styles to a minimum in the `static/global.css` file and try to incorporate reusable components.

If you want, you can use [Storybook](https://storybook.js.org/) to create a Svelte component library. I usually create my components from scratch, but something like Storybook might be helpful.

You can also use an existing component library or fork an existing one and customize it. To see what component libraries exist for Svelte, go to https://svelte-community.netlify.app/code and search for component libraries.


### You can use Vue-like `<template>` tags to wrap your markup
Since Routify comes with `svelte-preprocess` already installed and configured, you can use Vue-like `<template>` tags to wrap and organize your markup without any additional configurations.

I like to wrap my markup in `<template>` tags to keep things a bit more organized. So instead of this:

```vue
<h1>Lorem ipsum dolor sit amet</h1>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod...</p>

<ul>
  <li>dolorem ipsum</li>
  <li>sed quia consequuntur</li>
  <li>exercitation ullamco</li>
  <li>voluptate velit</li>
</ul>

<p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem...</p>

<script>
  // script code...
</script>

<style>
  // style rules...
</style>
```

I do this:

```vue
<template>
  <h1>Lorem ipsum dolor sit amet</h1>

  <p>Lorem ipsum dolor sit amet, consectetur...</p>

  <ul>
    <li>dolorem ipsum</li>
    <li>sed quia consequuntur</li>
    <li>exercitation ullamco</li>
    <li>voluptate velit</li>
  </ul>

  <p>Sed ut perspiciatis unde omnis iste natus error...</p>
</template>

<script>
  // script code...
</script>

<style>
  // style rules...
</style>
```

It looks just a little bit cleaner to me.


### Svelte Icons
You can search the [Svelte Community (Code section)](https://svelte-community.netlify.app/code/) for icons.

My favorite icons are the [MaterialDesignIcons](http://materialdesignicons.com/) and they are even available as Svelte components:

* Website: https://alexxnb.github.io/mdi-svelte/
* NPM: https://www.npmjs.com/package/mdi-svelte

_**NOTE:** You have to install the `@mdi/js` package before you can use the MaterialDesignIcons icons in your components: https://www.npmjs.com/package/@mdi/js._


## Start coding
Now you should be ready to create your project. Run your code in dev mode and start coding.

Enjoy!