Getting Started with SvelteKit: 10 Tips
Tags: svelte, webdev, javascript
Published: 2021-07-12 09:02:46

---
title: "Getting Started with SvelteKit: 10 Tips"
published: "true"
description: "Getting started with SvelteKit: 10 tips I learned building fast Svelte sites from tooling to integrating SEO components and Netlify config"
tags: "svelte, webdev, javascript"
canonical_url: "https://rodneylab.com/getting-started-with-sveltekit/"
cover_image: "https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8eboqkrjldwruy8113bn.png"
---

## ❤️ Svelte and SvelteKit

It is pretty unlikely that you haven't heard of Svelte, with all the hype that has surrounded it for at least a year now! The Svelte philosophy is one of simplicity. That is clearer nowhere else than in the code for a Svelte site. Unlike for React and some other libraries, it compiles to plain Java Script. User browsers do not have to interpret Svelte code when they load a page; the page will already be in a language they understand: JavaScript. As a result, Svelte sites are fast by default! You will find this post useful if you are getting started with SvelteKit. Included are 10 tips to get you building fast apps quicker.

Compilation to JavaScript aside, there are a lot of similarities between Svelte and React, flattening the learning curve for anyone coming from React. In fact, as it pulls some of the best developer experience forte's from Vue and Angular as well, the barrier to entry is quite low. Want to see what all the buzz is about? Read on to find out how to learn Svelte and also some key tips for getting started with SvelteKit.

## 👨🏽‍🎓 How do you get started with Svelte?

Svelte have written an <a aria-label="Open the official Svelte tutorial" href="https://svelte.dev/tutorial/basics">excellent set of tutorials</a>. These cover quite a bit of ground and take some time to complete. Depending on how you like to learn, I would run with the tutorials and until you have covered the basics and then jump in to building your own toy apps and taking it from there. You will probably need to dip into the tutorials again to understand features such as <a aria-label="Learn about Svelte stores" href="https://svelte.dev/tutorial/writable-stores">Stores</a> and Special Elements, which come later on. However, by no means do you have to complete the tutorials to write your first app.

There is also <a aria-label="Start the MDN Svelte tutorial" href="https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_getting_started">a very good MDN tutorial where you build a Svelte todo app</a>. I did this tutorial in parallel with the official Svelte one so learning didn't become too dry. You probably already have React and HTML5/JavaScript todo apps (from when you were learning those... the todo app is a favourite of tutorial writers 😀), but you can always customise the tutorial to make an issue tracker or <a aria-label="Read more about Bullet Journals" href="https://bulletjournal.com/">Bullet Journal instead</a>. If you want yet more ideas, <a aria-label="Get project ideas from Colby Fayock's book" href="https://50reactprojects.com/">try Colby Fayock's e-book of 50 React Projects</a> (using Svelte instead of React).

## 🧱 How do you create a Skeleton SvelteKit app?

Before looking at how to create a SvelteKit app, let's quickly look at what SvelteKit is. Essentially SvelteKit is a tool for taking your Svelte code and converting it into a node app. Svelte is the underlying language and SvelteKit is a tool for building sites with it. SvelteKit brings server-side rendering (SSR) and code-splitting to your app. The Svelte/SvelteKit relationship is much like that between React and Gatsby or React and Next.js. With that out of the way, let's look at how to get stared with creating a SvelteKit app.

To get going you will need to have node installed on your machine . If you are already running Next.js or Gatsby, you probably have everything you need. Now, run the following commands. For now use the @next version:

```
npm init svelte@next my-sveltekit-app && cd $_
npm install
npm run dev
```

Choose the `Skeleton project` option for a quick start. It literally only takes about 40&nbsp;seconds to download everything you need and start up your local server. Next, open up your browser and go to <a aria-label="Open you running SvelteKit local server" href="http://localhost:3000">http://localhost:3000</a>. If you already have a process running on TCP port `3000`, see the tip below on <a href="#changingSvelteKitDevServerPort">changing the default SvelteKit dev server port</a>.

<h3 id="whatsInside">Getting Started with SvelteKit: What's Inside?</h3>

We'll have a quick run through what files and folders we have and some that it's worth creating. Skip onto the next section if you are already familiar with the structure.

```
.
├── README.md
├── jsconfig.json
├── node_modules
│   ├── ...
│   └── ...
├── package-lock.json
├── package.json
├── src
│   ├── app.html
│   ├── global.d.ts
│   ├── lib
│   └── routes
│       └── index.svelte
├── static
│   └── favicon.ico
└── svelte.config.js
```

1. The `README.md` file contains some tips on getting going, handy to keep while you are still getting used to SvelteKit.

2. `jsconfig.json` defines some paths which the compiler needs. If this is your first SvelteKit project, I would keep files in their default locations.

3. `package.json`: remember you will find the npm script definitions here so you can check back on the build, dev and preview commands if you have as bad a memory as I do. We'll look at <Link to="#changingSvelteKitDevServerPort">some scripts you might want to modify in `package.json` further down</Link>.

4. `src/app.html` is an HTML template, which SvelteKit injects your code into. You can set some accessibility properties here, or alternatively hang on and you will see <a aria-label="See how to set accessibility tags programmatically in SvelteKit" href="#accessibility">a way to set meta tags programmatically</a>, further down.

5. `src/global.d.ts`: if you're a TypeScript person, you already know what this is for!

6. `src/lib`: create this directory and use it to store your own components, utility functions etc. SvelteKit has a nice way of importing files from here, so you don't need to use `../../../../file-i-want.js` notation, which can become burdensome when refactoring code. We go into this later.

7. `src/routes`: SvelteKit creates app pages based on the file and folder structure here. You will find this familiar is you are already have Next.js or Gatsby experience.

8. `static`: by default this directory contains a Svelte favicon, replace that with your own favicon.  Also use this directory for logos and other assets which you do not need SvelteKit to generate at compile time (such as PGP public keys) in here.

9. `svelte.config.js` does what is days on the tin! We will drill into a couple of options below.

<h2 id="10SvleteKitTips">10 Tips for Getting Started with Svelte</h2>

Both SvelteKit dev and preview servers run on port `3000` locally by default. There's a few different services and apps which also use that port so you might find you need to switch. To save having to remember command line switches, I would just update your `package.json` file:

```
        "name": "my-sveltekit-app",
        "version": "0.0.1",
        "scripts": {
                "dev": "svelte-kit dev --port 4000",
                "build": "svelte-kit build && cp netlify/functions/backblaze.js functions/.",
                "preview": "svelte-kit preview --port 4000",
                "lint": "prettier --check --plugin-search-dir=. . && eslint --ignore-path .gitignore .",
                "format": "prettier --write --plugin-search-dir=. ."
        },
  ...
```

Here we change the default port to `4000` for both the dev server and the preview server.

<h3 id="svelteKitTooling">2: Getting Started with SvelteKit: SvelteKit Tooling</h3>

If you are using VSCode, it is worth installing <ExternalLink aria-label="Download Svelte for VSCode" href="https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode">Svelte for VSCode</ExternalLink>. This will give you syntax highlighting and completion options (intellisense). This is something you can just set and forget. The extension is the official one, developed by Svelte.

<h3 id="svelteKitTooling">3: SvelteKit Accessibility</h3>

To make your app accessible, it is important that the HTML document includes a title and the language. The <Link aria-label="Read about accessibility for Gatsby sites" to="/gatsby-site-accessibility-3-quick-gains/">`lang` attribute is helpful for Screen Readers to choose the best pronunciation</Link>. Although you can set the `lang` attribute in `app.html` you might consider setting it programmatically (if you do this delete the lang attribute in `app.html`). There are a few options, varying in complexity. Let's see the simplest below. You might, instead, choose to use a <Link aria-label="Find out what Svelte Layouts are" to="#svelteKitLayouts">Svelte Layout (explained further down)</Link> in a more complex project. If your project will have more than a couple of pages, it is worth <Link aria-label="Learn how to create an SEO component including accessibility meta tags" to="#svelteKitSEO">creating a Svelte SEO component</Link> in which you can include meta tags for search engines and social media sites to ingest, alongside these accessibility tags. However for a small site you can just do something like this on each page (changing the title to match the page):

```svelte
<script>
  // omit script element if it is not needed on your page
</script>
<svelte:head>
  <title>my-sveltekit-app | Home Page</title>
        <html lang="en-GB" />
</svelte:head>
<h1>Welcome to my SvelteKit site</h1>
<p>It is not too difficult to get started with SvelteKit...</p>
```

The <code>`<svelte:head>`</code> element is one of the <a aria-label="Learn more about Svelte special elements" href="https://svelte.dev/tutorial/svelte-self">special elements in Svelte, you can learn more about them in the Svelte tutorial</a>. For more <a aria-label="Open the W 3 C Internationalisation Guide" href="https://www.w3.org/International/articles/language-tags/">language codes see the W3C Internationalisation Guide</a>.

<h3 id="svelteKitLayouts">4: Getting Started with SvelteKit: SvelteKit Layouts</h3>

You will probably already be familiar with layouts if you have previously built a Gatsby site. Basically they save you having manually to add repeated content, like headers and footers to every single page they need to appear on. In SvelteKit, if you create a file with the path `src/routes/__layout.svelte`, this is automatically interpreted as the default layout for your app. In that file you define your layout (e.g. header and footer) and just need to include a `<slot />` element. This is where the content from whichever page is using the layout goes:

```
<header>
        <nav>
                <a href="/.">Home</a>
                <a href="/contact">Contact</a>
        </nav>
</header>
<main>
  <slot />
</main>
<footer>
        <p>
                A project by
                <a aria-label="Open the Rodney Lab site" href="https://rodneylab.com/" target="_blank" rel="nofollow noopener noreferrer"
                        >RODNEY LAB</a
                >.
        </p>
</footer>
```

That's all you need. Save the file and navigate to the home page. You will see you now have a header and footer. For clarity, you don't need to change code in any pages using the layout. They will pick it up automatically. It is easy to <a aria-label="Learn about SvelteKit layout resets" href="https://kit.svelte.dev/docs#layouts-resets">tell SvelteKit not to use a Layout for particular pages</a>, though we won't get into that here.

Remember to use semantic HTML (e.g. <code>`<header>`</code>, <code>`<main>`</code>, <code>`<footer>`</code> etc.) where possible to keep the app accessible.

<h3 id="sveltekit404">5: Getting Started with SvelteKit: SvelteKit 404 Page</h3>

Similar to the default layout, include a default 404 page but creating a file with the path `src/routes/__error.svelte`:

```
<script context="module">
        export function load({ error, status }) {
                return {
                        props: {
                                title: \`\${status}: \${error.message}\`
                        }
                };
        }
</script>
 
<script>
        export let title;
</script>
 
<svelte:head>
        <title>{title}</title>
</svelte:head>
<h1>{title}</h1>
```

We're half way through the tips now. Hope you have learned a couple of handy bits already. There's more on SEO and environment variables coming up.

<h3 id="sveltekitPrivacy">6: Privacy in SvelteKit</h3>

![Getting Started wth SvelteKit: Privacy - Disable FLoC](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8o71j7pn80t10i41xve4.png)

Kudos to SvelteKit for switching off <Link aria-label="Read more about FLoC in a recent Rodney Lab blog post" to="/should-you-worry-about-floc/">Google FLoC by default</Link>. It is admirable that they take this privacy protection step. If you need to switch on FLoC

```
  {`
/** @type {import('@sveltejs/kit').Config} */
const config = {
        kit: {
    floc: true, // override default if you need to
                // hydrate the <div id="svelte"> element in src/app.html
                target: '#svelte'
        }
};
 
export default config
```

<h3 id="sveltekitEnvironmentVariables">7: Environment Variables in SvelteKit</h3>

Environment variables provide a convenient way to store API keys and other private information which we do not want to keep in our repo.  There will be some environment variables which you want the user's browser (client-side) to have access to.  You might have an API site key which is needed on the client side to identify your site to a service.  Beyond client environment variables you will possibly have secret environment variables which only the server has access to.  API secret keys, used to authenticate your site to a service, are included in this category.   SvelteKit can handle both types easily.  For secret, server side API keys <a aria-label="Open Scott Spence post on server side privat keys" href="https://scottspence.com/2021/03/06/22/sveltekit-env-secrets/" rel="nofollow noopener noreferrer">Scott Spence has written a fantastic article</a> explaining the process.  We will focus on client side secrets here.

SvelteKit has the easiest way for handling client side environment variables I have seen. There is no need to install any external packages. You have to be careful importing environment variable into files which have a style element though. If you do this you will probably get an error message in the terminal. There is a workaround which is not too much bother to code up.

1. In general to use environment variables in SvelteKit.  First define them in a <code>.env</code> file:

    ```shell
    VITE_SECRET_SAUCE_RECIPE="onions,tomatoes,oregano,specialIngredient"
    VITE_SUPER_SECRET_API_KEY="$ecret@p1Key
    ```
    note the variables are prefixed `VITE_` (you will omit this prefix for server side secrets).

2. To use the variables in a file, just import them like so:
    ```svelte
      const secretSauceRecipe = import.meta.env.VITE_SECRET_SAUCE_RECIPE
    ```

    If you needed to use an environment variable in the rendered content (for example a public email address stored as an environment variable), you can use and reference it in exactly the same way.  Be careful with what you output to the browser though!

3. If you get cryptic errors in the terminal, read on for some solutions.

<h4 id="crypticErrorMessages">Cryptic Error Messages</h4>

There's a couple of error messages you might see in the terminal when using environment variables. I had this one several times, when ESLint was trying to be helpful and imported something which I did not need. This threw the error:

```shell
Cannot split a chunk that has already been edited (0:7 – "import.meta")
```

There is one more cryptic error I got a few times. If you are using environment variables and get an error in the terminal, something like `[rollup-plugin-dynamic-import-variables] Unexpected token`

```shell
[rollup-plugin-dynamic-import-variables] Unexpected token (6:627)
```

you possibly have a `<style>` tag in a page which also uses environment variables.
There is a workaround which involves a small refactor. Basically we will import all of the
environment variables into a library file and reference them from there wherever we need them.

```javascript
const variables = {
        secretSauceRecipe: import.meta.env.VITE_SECRET_SAUCE_RECIPE,
        superSecretAPIKey: import.meta.env.VITE_SUPER_SECRET_API_KEY,
};
 
export { variables as default };
```

Now you can import the environment variables and use them in pages with style tags:

```
<script>
        import environmentVariables from '$lib/constants/environmentVariables';
        const { superSecretAPIKey } = environmentVariables;
 
        async function handleClick() {
          const options = {
                        method: 'POST',
                        body: JSON.stringify({ secret: superSecretAPIKey })
                };
        await fetch('/.netlify/functions/secret-sauce-server', options);
        }
</script>
<span>
        <button on:click={handleClick}>
                Order Secret Sauce
        </button>
</span>
<style>
        button {
                padding: 1em;
                font-size: 1em;
        }
</style>
```

Note the convenient notation in the second line above. We don't have to use a relative path back to the
constants folder. More on this later.

<h3 id="favicon">8: Where do you put your Favicon in SvelteKit?</h3>

By default, the assets folder for static files is `static/` at the project root. Put any files which SvelteKit does not need to process in here (e.g. small logo files and public PGP keys). You will need to create the folder if you selected a skeleton project when you initialised the app.

<h3 id="usingComponents">9: Getting Started with SvelteKit: Using your Components in Pages</h3>

For convenience, I create the `src/lib/components` folder for SvelteKit for placing components in. As previously mentioned, another of the developer experience tweaks in SvelteKit saves you having to work out and then type out the relative path from the page you are editing to the components folder. The `src/lib` folder is accessible throughout the project, just using `$lib`. Here is an example for importing an `SEO` component with path `src/lib/components/SEO.svelte`, used on the home page:

```svelte
<script>
  import SEO from '$lib/components/SEO/index.svelte';
 
  let title = 'my-svelte-kit-app | Home';
  let metadescription = 'my-svelte-kit-app - my first ever SvelteKit app';
</script>
<SEO {title} {metadescription} />
<h1>Welcome to my SvelteKit site</h1>
<p>It is not too difficult to get started with SvelteKit...</p>
```

Note in line `7` we use a shortcut syntax (another developer experience perk in Svelte). This is equivalent to writing:

```svelte
        <SEO title={title} metadescription={metadescription} />
```

<h3 id="svelteKitSEO">10: Getting Started with SvelteKit: SvelteKit SEO</h3>

Finally, our last tip on getting started with SvelteKit. Like for Gatsby, adding SEO meta tags in SvelteKit is quite easy. In the case of SvelteKit, following the Svelte philosophy of simplicity, we have already seen that you don't even need to install any extra packages to update the HTML head section. We'll look at some example code so exactly you can see how to do it.

For a decent sized app, you would probably want to create separate SEO components for <Link aria-label="Open post on Svelte Kit SEO to see how to add Twitter meta to your Svelte Kit site" href="/sveltekit-seo/">Twitter</Link>, <a aria-label="Open post on Svelte Kit SEO to see how to add Open Graph meta to your Svelte Kit site" to="https://rodneylab.com/open-graph-seo-sveltekit/">OpenGraph</a> (used principally for Facebook but also for What's App and others) and <Link aria-label="Open post on Svelte Kit SEO to see how to add Schema dot org markup to your Svelte Kit site" href="https://rodneylab.com/adding-schema-org-markup-to-sveltekit-site/">Schema.org</a> (used mainly by search engines to serve rich results). Here I have a principal SEO file which imports the other mentioned SEO components:

```svelte
<script>
        import OpenGraph from './OpenGraph.svelte';
        import SchemaOrg from './SchemaOrg.svelte';
        import Twitter from './Twitter.svelte';
        import website from '$lib/config/website.js';
        import { VERTICAL_LINE_ENTITY } from '$lib/constants/entities.js';
        export let title;
        export let metadescription;
        const { author, ogLanguage, siteLanguage, siteTitle, siteTitleAlt } = website;
        const siteUrl = import.meta.env.VITE_SITE_URL;
        const pageTitle = \`\${siteTitle} \${VERTICAL_LINE_ENTITY} \${title}\`;
        const openGraphProps = {
                facebookAppId: import.meta.env.VITE_FACEBOOK_APP_ID,
                image,
                metadescription,
                ogLanguage,
                pageTitle,
                siteTitle,
                siteUrl
        };
        const schemaOrgProps = {
                author,
                siteLanguage,
                siteTitle,
                siteTitleAlt,
                siteUrl
        };
        const twitterProps = {
                author,
                twitterUsername: import.meta.env.VITE_TWITTER_USERNAME,
                metadescription,
                pageTitle,
                siteUrl
        };
</script>
 
<svelte:head>
        <title>{pageTitle}</title>
        <meta name="description" content={metadescription} />
        <meta
                name="robots"
                content="index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1"
        />
        <html lang={siteLanguage} />
        <SchemaOrg {...schemaOrgProps} />
        <OpenGraph {...openGraphProps} />
        <Twitter {...twitterProps} />
</svelte:head>
```

As mentioned earlier, to add elements to the output HTML head, we just wrap them in a <code>`<svelte:head>`</code> tag. Here we have the accessibility `lang` and `title` elements defined within our SEO component. As well as those, we have a `robots` tag which tells search engines we are happy for them to index the page. The Twitter and OpenGraph components work in a similar way so we won't look at those here. Let me know if you would like me to write a separate post on SEO for Social Media in SvelteKit, or more generally &mdash; it's a little too much detail to go into here. I could include a complete example, showing how to add and test social images and generate rich search engine results if you would find that helpful.

For a <a aria-label="Open a blog pot on Svelte Kit S E O" href="https://rodneylab.com/sveltekit-seo/">deeper dive into SvelteKit SEO, take a look at this post dedicated to Search Engine Optimisation in SvelteKit</a>.

<h4 id="schemaOrg">Schema.org</h4>

Because of the way in which we need to define Schema.org in the HTML document, we need to tweak the code a little. This is partly so that Svelte compiles it as intended but also to stop ESLint breaking the code (albeit with good intentions). Schema.org metadata is included as a script of type `application/ld+json`. We create this tag in a few stages. Take a look through the code then see the explanation below:

```svelte
<script>
        import hash from 'object-hash';
        export let author;
        export let siteLanguage;
        export let siteTitle;
        export let siteTitleAlt;
        export let siteUrl;
        const entityHash = hash({ author }, { algorithm: 'md5' });
        const schemaOrgWebsite = {
                '@type': 'WebSite',
                '@id': \`\${siteUrl}/#website\`,
                url: siteUrl,
                name: siteTitle,
                description: siteTitleAlt,
                publisher: {
                        '@id': \`\${siteUrl}/#/schema/person/\${entityHash}\`
                },
                potentialAction: [
                        {
                                '@type': 'SearchAction',
                                target: \`\${siteUrl}/?s={query}\`,
                                query: 'required'
                        }
                ],
                inLanguage: siteLanguage
        };
        const schemaOrgArray = [schemaOrgWebsite];
        const schemaOrgObject = {
                '@context': 'https://schema.org',
                '@graph': schemaOrgArray
        };
        let jsonLdString = JSON.stringify(schemaOrgObject);
        let jsonLdScript = \`
                <script type="application/ld+json">
                        \${jsonLdString}
                \${'<'}/script>
        \`;
</script>
  
<svelte:head>
        {@html jsonLdScript}
</svelte:head>
```

Let's start at the bottom and work our way up. In lines `40–42` we add the script to the HTML head. The `@html` in line `41` is important for the correct compilation of our svelte code. In lines `33–37` we define the script tag which we inject into the DOM at end of the file. The funkiness in line `36`, is the workaround I mentioned to prevent ESLint messing up the code. What we need to output is simply <code>`</script>`</code>, but to stop ESLint in its tracks, we wrap the opening angular bracket using the interpolated template variable syntax.

The rest of the file defines the Schema.org data as a JSON object. I have trimmed this down, for simplicity. Normally you will include further fields in the object, such as a breadcrumb list and details on the publishing entity. Again let me know if you would value a post on this with a full example. SchemaOrg is quite good for SEO, as an example, if you include the right meta, your page will appear like this, above all other results:

![Getting Started wth SvelteKit: SEO](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7s6pnzgt2rqtymlis18u.png)

<h3 id="allGoodThings">All Good Things Must Come to an End!</h3>

That's all for now on getting started with SvelteKit.  If you have found this post useful, you should also look at the <Link aria-label="Open post on using Netlify to host your SvelteKit site" to="/use-netlify-to-host-your-sveltekit-site/">follow-up post on using Netlify to host your SvelteKit site</Link>. Did you learn at least one thing here? Is there anything I should have added. Or, even anything that I did include but was so obvious that I shouldn't have bothered? Please let me know either way. I also want to know how you are finding SvelteKit. Which libraries or frameworks are you more used to? Do you use Netlify? Let me know if you would find a post on using Netlify with SvelteKit and the Netlify adapter. Finally, what have you built so far in SvelteKit?

<h2 id="feedback">Feedback</h2>

How did you find this guide on getting started with SvelteKit? It's a little different to other posts I have written. Normally I like to work on a single project and build out a complete working example. The idea is to see how everything fits together. Once that is clear it is easier to take components out and use them in your own projects. How did you find this format? Would you like to see some complete examples using SvelteKit? Keen to hear your views and also learn where your pain points with learning SvelteKit are. If you have found this post useful and can afford even a small contribution, please <Link aria-label="Support Rodney Lab via Buy me a Coffee" to ="/giving/">consider supporting me through Buy me a Coffee</Link>.

Finally, feel free to share the post on your social media accounts for all your followers who will find it useful. You can get in touch via <a href="https://twitter.com/messages/compose?recipient_id=1323579817258831875">@askRodney</a> on Twitter and also <a aria-label="Contact Rodney Lab via Telegram" href="https://t.me/askRodney">askRodney on Telegram</a>. Also, see <Link aria-label="Get in touch with Rodney Lab" to="/contact">further ways to get in touch with Rodney Lab</Link>. I post regularly on <Link to="/tags/gatsby" aria-label="See posts on gatsby">Gatsby JS</Link> as well as <Link aria-label="See posts on svelte kit" to="https://rodneylab.com/tags/sveltekit/">SvelteKit</Link>. Also <a aria-label="Subscribe to the Rodney Lab newsletter" href="https://rodneylab.com/about/#newsletter">subscribe to the newsletter to keep up-to-date</a> with our latest projects.