SvelteKit TypeScript vanilla-extract Starter: Markdown Blog

Rodney Lab - Jun 30 '22 - - Dev Community

🤝 Introducing new SvelteKit TypeScript vanilla-extract Starter

In this post we take a look at getting up and running with the new SvelteKit TypeScript vanilla-extract starter. Vanilla-extract is a CSS in JavaScript or more specifically CSS in TypeScript styling framework. It uses TypeScript to help developers scope styles and enforce coding style. At build-time, vanilla-extract generates CSS stylesheets from your input TypeScript. Because it generates CSS, there is zero runtime overhead, meaning a fantastic experience for end users.

Since vanilla-extract uses TypeScript for styling input, it makes sense also to use TypeScript for the SvelteKit side and leverage autocompletion and type safety together with the other TypeScript benefits. In the rest of this post we look at getting started with the new starter from cloning the repo to build.

SvelteKit TypeScript vanilla-extract Starter: Screen shot of starter homepage in browser, shows Light / dark mode toggle and Home and Contact navigation links.

🚀 Quick Start

Get going in three steps: clone the repo, install packages then spin up a dev server to start building out your new project:

git clone https://github.com/rodneylab/sveltekit-typescript-vanilla-extract-starter.git
cd sveltekit-typescript-vanilla-extract-starter
pnpm install
pnpm run dev
Enter fullscreen mode Exit fullscreen mode

This will spin up a dev server on your machine on TCP port 3000. If you already have something running there, it is easy to switch SvelteKit server port, adding a --port 3001 (or similar) to the project package.json dev script.

When you are ready, to build the site, just do a pnpm run build from the Terminal.

🧐 What's Inside?

.
├── README.md
├── package.json
├── src
│   ├── app.d.ts
│   ├── app.html
│   ├── content
│   │   └── blog
│   │       ├── best-medium-format-camera-for-starting-out
│   │       ├── folding-camera
│   │       └── twin-lens-reflex-camera
│   ├── lib
│   │   ├── assets
│   │   ├── components
│   │   │   ├── BannerImage.css.ts
│   │   │   ├── BannerImage.svelte
│   │   │   ├── ...
│   │   │   ├── PWA.svelte
│   │   │   └── SEO
│   │   ├── config
│   │   │   └── website.ts
│   │   ├── generated
│   │   │   └── posts
│   │   ├── shared
│   │   │   └── stores
│   │   ├── styles
│   │   │   ├── normalise.css
│   │   │   ├── styles.css.ts
│   │   │   ├── themes
│   │   │   └── vars
│   │   └── utilities
│   │       └── blog.ts
│   ├── routes
│   │   ├── [slug]
│   │   │   ├── __layout.svelte
│   │   │   ├── index.json.ts
│   │   │   └── index.svelte
│   │   ├── __layout.svelte
│   │   ├── index.svelte
│   │   └── index.ts
│   └── service-worker.js
├── static
│   ├── apple-touch-icon.png
│   ├── ...
│   └── manifest.webmanifest
├── svelte.config.js
└── tsconfig.json
Enter fullscreen mode Exit fullscreen mode

src

  • app.d.ts here we have custom types used by the app.

  • app.html regular SvelteKit HTML template, we include some favicon links in the html head section.

src/content

This is where we add new blog posts. Create a new folder under src/content/blog for each new post. Just add an index.md file inside the new directory for the post content. Although the file has an .md extension, since the project uses mdsvex you can drop Svelte code in there too. A new post in src/content/blog/new-post/index.md will be generated on https://example.com/new-post/.

src/lib/assets

We have images in here, such as banner images and social sharing images used in the starter’s SEO components.

src/lib/components

  • src/lib/components these are the components we use in pages. We define style files alongside file components. As an example, we have the Svelte component file BannerImage.svelte for next-gen responsive images and next to it; BannerImage.css.ts. In there we define the component’s vanilla-extract styles. If you use VSCode, in the project’s .vscode/settings.json there is an override for explorer.fileNesting.patterns which tucks these .css.ts files into their parent .svelte files.

src/lib/generated

This folder contains a file for each post with responsive data used with vite-imagetools. vite-imagetools generates images in next-gen formats together with responsive sizes. The node script generate-responsive-image-data.ts actually creates these files.

src/lib/shared

Here we have a Svelte store which puts the use light/dark theme preference to local storage. The code checks if there is already a browser preference for light or dark theme. This, however, is overridden when the user toggles the dark/light button. Then, using local storage, we note the choice for future site visits.

src/lib/styles

  • src/lib/styles/styles.css.ts here you will find the main vanilla-extract global styles. The file references variables set in src/lib/styles/vars folder (such as spacing, font sizes and so on).

  • src/lib/styles/themes we have a few files here. theme.css.ts defines the variables which any theme must have. We start to see some of the power of vanilla-extract here. The other two files define those variables for the light and dark themes included in the starter.

src/utilities

  • src/utilities/blog.ts this file contains some code for helping us transform the markdown in blog posts to Svelte. As well as that they help extract fields in the frontmatter (this is the metadata we include at the top of the blog post index.md files).

src/routes

  • src/routes/[slug].json.ts this is essentially a template for blog post data. One of these files is generated at build for each blog post.

If you are new to Svelte, see the post on Getting Started with SvelteKit blog post. That goes into a little detail on some of the other files in a Svelte project. By the same token, the post on using vanilla-extract in SvelteKit talks more about the benefits of using vanilla-extract for styling. As well as that there is more detail on the nuts and bolts of making it work with SvelteKit.

🖋 SvelteKit TypeScript vanilla‑extract Starter: Blog Posts

We just mentioned the blog posts are in index.md files within folders under src/content/blog. Here is an example:

---
postTitle: 'Best Medium Format Camera for Starting Out'
focusKeyphrase: 'best medium format camera'
datePublished: '2022-05-07T16:04:42.000+0100'
lastUpdated: '2022-05-14T10:17:52.000+0100'
seoMetaDescription: "Best medium format camera for starting out is probably a question at the front of your mind right now! Let's take a look."
featuredImage: 'best-medium-format-camera-for-starting-out.jpg'
featuredImageAlt: 'Photograph of a Hasselblad medium format camera with the focusing screen exposed'
ogImage: 'best-medium-format-camera-for-starting-out-open-graph.jpg'
ogSquareImage: 'best-medium-format-camera-for-starting-out-open-graph-square.jpg'
twitterImage: 'best-medium-format-camera-for-starting-out-twitter.jpg'
categories: ''
tags: ''
---

<script>
  import ExternalLink from '$lib/components/ExternalLink.svelte';
  import Link from '$lib/components/Link.svelte';
</script>

## What is a Medium Format Camera?

If you are old enough to remember the analogue film camera era, chances are it is the 35&nbsp;mm canisters with the track cut down the side that first come to 
Enter fullscreen mode Exit fullscreen mode

This looks like regular Markdown at first glance. However, you might notice we have a familiar Svelte script tag in lines 1619. This comes courtesy of mdsvex and lets us use Svelte components within the post content files. The frontmatter fields (like seoMetaDescription and twitterImage) are passed to the starter’s SEO component.

🖼 SvelteKit TypeScript vanilla‑extract Starter: Icons

SvelteKit TypeScript vanilla-extract Starter: Screen shot of footer icons including Twitter , Tik Tok and Git hub icons.

We use Iconify icons in the starter. This gives you access to thousands of icons in dozens of libraries all through a single npm package. The starter uses these icons offline, though you can choose to download them on demand. See the article on using SvelteKit with Iconify for more on customisation together with finding icons.

🙌🏽 SvelteKit TypeScript vanilla-extract Starter: Wrapup

We have a had a quick look at getting up and running with the new SvelteKit TypeScript vanilla-extract starter. In particular we have touched on:

  • cloning and then spinning up the starter,
  • where to find vanilla-extract global styles as well as other important files,
  • some starter features including responsive images and Iconify icons together with light/dark mode.

This was just a quick look though! Probably the best way to get acquainted with the starter is just to clone it, then start playing around. I would love to hear of your suggestions for improvements. Do let me know if there is something missing either in the starter or from this introduction. You can drop a comment below or reach out for a chat on Element as well as Twitter @mention

You can get the starter from the Rodney Lab Git Hub repo.

🙏🏽 SvelteKit TypeScript vanilla‑extract Starter: Feedback

If you have found this video useful, see links below for further related content on this site. I do hope you learned one new thing from the video. Let me know if there are any ways I can improve on it. I hope you will use the code or starter in your own projects. Be sure to share your work on Twitter, giving me a mention so I can see what you did. Finally be sure to let me know ideas for other short videos you would like to see. Read on to find ways to get in touch, further below. If you have found this post useful, even though you can only afford even a tiny contribution, please consider supporting me through Buy me a Coffee.

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 @askRodney on Twitter and also askRodney on Telegram. Also, see further ways to get in touch with Rodney Lab. I post regularly on SvelteKit as well as Search Engine Optimisation among other topics. Also subscribe to the newsletter to keep up-to-date with our latest projects.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .