SvelteKit Tutorial: Build a Svelte MDsveX Blog Site
Tags: svelte, webdev, javascript
Published: 2021-07-28 13:06:08

---
title: "SvelteKit Tutorial: Build a Svelte MDsveX Blog Site"
published: "true"
description: "SvelteKit Tutorial: Learn how to build an accessible, fast and secure static Svelte blog site using SvelteKit and Svelte in Markdown (MDsveX)."
tags: "svelte, webdev, javascript"
canonical_url: "https://rodneylab.com/sveltekit-tutorial-mdsvex-blog-site/"
cover_image: "https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pr4nu2s2x12cxgjbzjl7.png"
---

## 🧑🏽‍🎓 SvelteKit Tutorial

SvelteKit Tutorial: with all the buzz around SvelteKit, we'll run through how to sep up an accessible, fast and secure Svelte Blog using SvelteKit.  Our posts will be powered by Svelte in markdown (MDsveX).  Essentially this new project is an extension on the recent blog post where we <a aria-label="Find out more on the M D svex Blog Starter" href="https://rodneylab.com/sveltekit-blog-starter/">looked at the SvelteKit MDsveX Blog starter</a>.  This time we are taking a more hands on approach, customising the site and adding some MDsveX to the blog posts.  If that sounds like the kind of thing you can get exited about, let's get going!

## 🚀 Let's Get the Ball Rolling!
</Heading>

To hit the ground running, we will be using the <a aria-label="Find out more on the M D svex Blog Starter" href="https://rodneylab.com/sveltekit-blog-starter/">MDsvex Blog Starter</a>.  So, the first thing we need to do is clone it.  I will be using pnpm as the package manager, but if you prefer npm, just drop the first p from all the pnpm commands.  Let's clone the repo and set it up at the command line:

```shell
git clone https://github.com/rodneylab/sveltekit-blog-mdx.git sveltekit-tutorial
cd sveltekit-tutorial
pnpm install
cp .env.EXAMPLE .env
pnpm run dev
```

If this is your first time using SvelteKit, you might find it useful to skim through the <Link aria-label="Learn about how to get started with Svelte Kit" to="/getting-started-with-sveltekit/">post on Getting Started with SvelteKit</Link>. However, if anything is unclear, please get in touch (see details below), as it could be something I forgot to mention! Now in your browser go to <ExternalLink aria-label="Open your dev site in your browser" href="http://localhost:3000">localhost:3000</ExternalLink>.

As you have the site open, have a look though the pages.  You will see there is some demo content in there already.  In this post we will:

- update styling,
- change fonts,
- add a new Svelte component and use it in an MDsveX blog post.

If you're as keen as I am, then let's jump on to the next part and see how you update the styling in the starter.

## 💄 Styling

We use SCSS for styling in the starter.  Much of the styling is set by variables in two files: `src/lib/styles/styles.scss` and `src/lib/styles/variables.scss`.  Styles propagate globally from there.  This makes it easy to update the site's styling.  Let's start by changing the colours up.  Edit `src/lib/styles/variables.scss`:

```scss
// Colours
$color-theme-1: #e63946; // imperial red
$color-theme-2: #a8dadc; // powder blue
$color-theme-3: #457b9d; // celadon blue
$color-theme-4: #1d3557; // prussian blue
 
$color-primary: #005b99;
$color-text: #0d1821; // rich black FOGRA 29
$color-heading: $color-theme-4;
$color-heading-black: $color-theme-4;
$color-accent: #f1faee; // honeydew
$color-success: #2ec4b6; // tiffany blue
$color-danger: #e71d36; // rose madder
```

Excuse the inconsistent spelling of the word &ldquo;colour&rdquo;!  Do other non-Americans do this, or is it just me? <GrinningFaceEmoji />

Next, let's remove the italic styling for level 1 headings, deleting that line so that `src/lib/styles/styles.scss` ends up looking like this:

```scss
h1 {
  margin-top: 0;
  font-weight: $font-weight-black;
  font-size: $font-size-6;
  color: $color-heading-black;
}
```

No peeking until we have finished!  Next we will change the `BlogPostSummary` and `Card` components:

```html
	  ...
    <span id={idString} aria-hidden="true" class="read-more-text">Read more {H_ELLIPSIS_ENTITY}</span>
  </div>
</div>
```

```html
 .content {
    width: 100%;
    border-radius: $spacing-2;
    margin: $spacing-0 auto;
    padding: $spacing-4 $spacing-0;
 
    h3 {
      margin: $spacing-0 $spacing-2;
    }
    p {
      color: $color-theme-3;
      font-size: $mobile-font-size-2;
      margin: $spacing-2;
    }
    .read-more-text {
      margin: $spacing-2;
    }
  }
 
  .content:hover {
    h3 {
      color: $color-accent;
    }
    p {
      color: $color-theme-2;
    }
```

```html
  .content {
    width: 100%;
    background-color: $color-theme-2;
    border-radius: $spacing-1;
    margin: $spacing-0 auto;
    padding: $spacing-4;
  }
```

Then finally, let's spruce up the home page, whose code is at `src/routes/index.svelte`.  We're changing up the title and restyling the &ldquo;About Me&rdquo; card:

```html
<header>
  <h1>My Film Photography Blog</h1>
</header>
<Card>
  <div class="card">
    <h2><span>About me</span></h2>
    <p>
      I live and breathe analogue photography. I show you my favourite analogue film cameras on this
      site. Hopefully if you are not into analogue photography yet, some of my enthusiasm will rub off
      onto you.
    </p>
  </div>
</Card>
<BlogRoll {posts} />
 
<style lang="scss">
  .card h2 { margin-top: $spacing-0; }
</style>
```

OK, you can take a look in the browser now. What do you think?  Change it up a little more if it's not yet your cup of tea!  When you're ready to move on, we'll change the fonts.

## 🖋 Fonts

The starter uses self-hosted fonts.  This allows the page to load faster, improving user experience.  One thing you need to remember is to install the new fonts when you change them.  Let's start by uninstalling the starter fonts which we no longer want at the command line:

```shell
pnpm uninstall @fontsource/lora @fontsource/source-sans-pro	
```

Next, as you probably guessed, we will install a replacement font:

```shell
pnpm install @fontsource/slabo-27px
```

We will also use Lato, but that is already installed.  Slabo 27px will be used for headings and Lato for other elements.  Most free fonts are available as Fontsource packages, you <ExternalLink aria-label="See Font source documentation" href="https://fontsource.org/">see the Fontsource website for more details</ExternalLink>.  Be sure to check which weights and styles are supported for your chosen font.

Now we have the fonts installed, we need to import them and then set them as our chosen fonts in the SCSS variables file.  Let's start with the variables file:

```scss
// Fonts
$font-family-serif: 'Lato', 'Lustria', 'Noto Serif', 'Merriweather', 'Georgia', 'Cambria',
  'Times New Roman', 'Times', serif;
$font-body: $font-family-serif;
$font-heading: 'Slabo 27px', $font-family-serif;
```

Let's carry on to the final step; importing the fonts.  Since all pages use our global layout file (`src/routes/__layout.svelte`), we will import fonts there removing the original import:

```html
<script>
	// Lato - supported variants:
	// weights: [100, 300, 400, 700, 900]
	// styles: [italic, normal]
	import '@fontsource/lato/400.css';
  
	// Slabo 27px - supported variants:
	// weights: [400]
	// styles: [normal]
	import '@fontsource/slabo-27px/400.css'
	...
```

## ⚓️ Headings with Scroll to Anchor

Sadly we're almost finished.  Let's carry on with the next step.  I promised we would create a new svelte component and add it to out blog post markup.  We will do exactly that now.  We will implement scroll to anchor.  You have probably been on websites on which if you hover over a title a little link icon appears.  You can copy that link to reference it from somewhere else, or just click it so the section you are reading scrolls to the top of the screen.  That's just what we will set up now.  Let's start by creating the new `Heading` component.  Make a new file at `src/lib/components/Heading.svelte`:

```html
<script>
	import LinkIcon from '$lib/components/Icons/Link.svelte';
 
	export let id;
 
	$: showLink = false;
 
	const handleMouseEnter = (event) => {
		showLink = true;
	}
 
	const handleMouseLeave = (event) => {
		showLink = false;
	}
</script>
 
<h2
	{id}
	on:mouseenter={handleMouseEnter}
	on:mouseleave={handleMouseLeave}
>
	<slot />
	{#if showLink}
	<a href={\`#\${id}\`}>
		<LinkIcon />
	</a>
	{/if}
</h2>
```

That code fragment is packed full of sveltisms.  There's a bit too much to go into here.  <a aria-label="Open the Svelte tutorial" href="https://svelte.dev/tutorial/basics">It's worth checking the Svelte tutorial for explanations</a>, though also feel free to get in touch if I can help.  We rely on default browser behaviour for the scrolling.  An `id` will be supplied by the component consumer.  We label out heading with that `id`.  Because of that, the browser knows where to scroll when we specify that `id` in the anchor element.

This is quite a basic version to demonstrate MDsveX.  You can go to town here when you implement it on your own site.  For example you might want to generate the ids automatically or have custom heading levels.  There is so much you can do with this one tiny element.

You will notice we imported a Link icon which we need to add the icon to our project.  Let's get cracking on that.

### Link Icon

Create a new file at `src/lib/components/Icons/Link.svelte` and give it the following content to import the corresponding Feather icons icon:

```html
<script>
  import { DEFAULT_ICON_SIZE } from './index.js';
  import LinkIcon from 'svelte-feather-icons/src/icons/LinkIcon.svelte';
  export let size = DEFAULT_ICON_SIZE;
</script>
 
<LinkIcon {size} />
```

Our final step is to import the component in a blog post and use it.  Open up `src/routes/best-medium-format-camera-for-starting-out/index.md`.  The file is a little messy, with a lot of front matter because of a temporary workaround for the Netlify adapter. That aside, let's import and use the Heading element:

```html
<script>
  import ExternalLink from '$lib/components/ExternalLink.svelte';
  import Heading from '$lib/components/Heading.svelte';
  import Link from '$lib/components/Link.svelte';
</script>
 
<Heading id="whatIsAMediumFormatCamera">What is a Medium Format Camera? </Heading>
...
```

Now go to your browser and hover over the link and the link icon should appear, you can click it to scroll to anchor.  When you move the mouse away from the link, it should disappear.  Hope it's all working.  What do you think?

## 🙌🏽 SvelteKit Tutorial: Wrapup

That's it for now.  Normally I would also run automated accessibility tests in Cypress using Axe.  Unfortunately, <a aria-label="Read about cypress Svelte kit workarounds" href="https://github.com/cypress-io/cypress/issues/8090#issuecomment-722431756">Cypress is not currently compatible with SvelteKit out of the box, though there are a few workarounds you can try</a>.  As an alternative, you can install the Axe browser addin then open up Axe from your browser Dev Tools.

I am keen to hear how you will extend what we have run though here.  What will you blog about?

## Sveltekit Tutorial: Feedback

Please send me feedback! Have you found the post useful? Would you like to see posts on another topic instead? Get in touch with ideas for new posts. Also if you like my writing style, get in touch if I can write some posts for your company site on a consultancy basis. Read on to find ways to get in touch, further below. If you want to support posts similar to this one and can spare a couple of dollars, rupees, euros or pounds, please <a aria-label="Support Rodney Lab via Buy me a Coffee" href ="https://rodneylab.com/giving/">consider supporting me through Buy me a Coffee</a>.

Finally, feel free to share the post on your social media accounts for all your followers who will find it useful. As well as leaving a comment below, you can get in touch via <a aria-label="Message Rodney Lab on Twitter" 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 <a aria-label="Get in touch with Rodney Lab" href="/contact">further ways to get in touch with Rodney Lab</a>. I post regularly on <a aria-label="See posts on svelte kit" href="https://rodneylab.com/tags/sveltekit/">SvelteKit</a> as well as <a href="https://rodneylab.com/tags/gatsby" aria-label="See posts on Gatsby">Gatsby JS</a> among other topics. 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.