Introducing Climate SvelteKit Blog Starter
This SvelteKit Blog starter is based on the existing Climate Gatsby MDX blog starter. Apart from being built for SvelteKit instead of Gatsby, the other big (related) difference is that it supports blog posts written in markdown files containing Svelte code (MDsvex), while the Gatsby version supported MDX (JSX in markdown). Markdown support for blog authoring is a big deal is much shorthand notation, which saves you having to write out longer, more formal HTML. As an example for a heading in HTML you write
<h1>My heading</h2>, while in Markdown you write
# My heading. There are similar shorter equivalents for writing lists, adding links, pictures and so on . All in all it means you spend less time tracking a missing close tag and concentrate on getting your thoughts down. On top MDsveX makes customising blog posts a lot easier.
If you are completely new to SvelteKit, it might be worth skimming through my recent post on Getting Started with SvelteKit, which will give you a head-start. That said I have built the starter to help you get up to speed quicker if you are still discovering SvelteKit. In this post I outline some key features. If you're more of a hands on person, just crack open the Sveltekit Blog Starter repo and start playing!
In this post rather than go through how I built the starter, to help get you going quicker with SvelteKit, I'll run through the most important parts of configuration. As it's based on the Gatsby equivalent, I can also point out some differences. My hope is that you can hit the ground running with help from the starter. We will start looking at what's inside the repo and where you put your own blog posts. Finally we'll end up with a comparison of Gatsby and SvelteKit, with a look at Server Side generation vs. Static Site Generation thrown in on the journey. If that sounds good to you let's crack on! If you would find a post on building something like this from scratch useful do let me know.
🚀 Quick Start
To get going you will clone the repo, install and spin up a dev server:
You can run
pnpm install instead of
npm install if you have pnpm set up.
🧐 What's Inside?
hooks.jswe define Content Security Policy (CSP) and other HTTP security headers in here. More on this later.
src/lib/componentsthese are the components we use in pages.
src/lib/config/website.jsfor convenience we define properties for the site here such as the site title, contact email addresses and social media accounts. Some properties feed from environment variables. See the earlier post on getting started with SvelteKit for more on environment variables in SvelteKit.
src/lib/stylesdoes what you expect! We use SCSS for styling and source self-hosted fonts in the layouts (we'll see this further down the post).
src/utilities/blog.jsthis 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 fo the blog post
src/routes/[slug].json.jsthis is essentially a template for blog post data. One of these file is generated at build for each blog post. It is used to extract data needed in the Svelte file used to generate the post's HTML.
__layout.sveltethis is a generalised layout template used both for main site pages and individual blog posts. Blog post data it loaded from this layout.
src/routes/best-medium-format-camera-for-starting-outthis is a folder for a blog post. The blog post slug is taken from the folder name, meaning this folder creates a blog post at
www.example.com/best-medium-format-camera-for-starting-out. The actual Svelte in Markdown content for the post is found in the index.md file. Create more blog posts by creating new folders with the same structure.
I mention most of the other files in the Getting Started with SvelteKit blog post, but let me know if I have missed anything which needs more explanation. Next let's look at a blog post file.
🖋️ Blog Posts
Below is a fragment from one of the sample blog posts. The first section is the frontmatter, mentioned earlier. For now the SEO content is barebones, but in an upcoming post, I will run through generating SEO metadata for OpenGraph, Twitter and SchemaOrg. In those posts we will make more use of post frontmatter to ensure we include data tailored for each post in the page's metadata. This has a number of important uses from, having nice pictures show up when your page is shared on Twitter, Telegram or other apps to helping search engines understand what the page is about. The latter is important for improving your SEO ranking. For now the most important use is ensuring we get the right banner image appear, with expected alt text for each post. If you are as keen on SEO as I am, you should read my post on SvelteKit SEO. As you might expect, the dates from frontmatter are used to sort posts in the
🌟 BlogPostSummary Component
Speaking of the blog roll, BlogRoll is used to generate it. We generate one of these components for each blog post. I thought this would be an interesting component to look at to compare Svelte and React code. We want the user to be taken to the blog post when they click anywhere inside the component. So we want it to behave like a link. We also want to include the title and other information as links to the post. Later we might add links to similarly tagged posts within the component.
That's a lot of links! Semantically, you should not have an anchor tag enclosed in another anchor tag. This is what we would have is we used anchors for all the links mentioned just then. Instead I engineered the component so it has the look, feel and behaviour expected by the user as well as being accessible.
This behaviour is implemented using
onClick event handlers in the Gatsby (React) version. In the Svelte version we
on:mousedown inline handlers.
React equivalent — click to expand code.
🔥 Static vs Serve Side Rendered
With SvelteKit you can choose to make pages Server Side Rendered, like Next apps typically are, or static (Static Site Generated, SSG), like Gatsby apps typically are. There is an excellent write up SSG by React guru Dan Abramov , worth the read, even if you already know about SSG. For SSG pages, the SvelteKit Netlify adapter produces a serverless function which acts as the server. With SvelteKit still being in development, there is an issue creating SSR pages with the Netlify adapter. For that reason I have made all pages in the starter static. This was done page by page, by adding a line of code to the module block, telling SvelteKit to prerender the page (in the relevant file):
Remove this line for pages you want to use SSG for. Hopefully the Netlify adapter issue gets fixed soon.
🔧 Self Hosted Fonts
In Gatsby we can install the
@fontsource npm package for the font we want to use on our site and import this in the
gatsby-browser.js file to make it accessible throughout the site. Self hosting makes the page load faster, saving the user's browser having to connect to a different origin to download the fonts it needs. In SvelteKit, it's not too different. Once again, we install the font packages, we just include them differently. In SvelteKt, we can add them to the default layout file if they are used throughout the site:
As with Gatsby, you only need to import the font variants which you will use.
💄 SCSS Styling
I'm a fan of SCSS so, we are using SCSS styling in the starter. There are a few things you need to do to get this to work in SvelteKit (this is all already done in the starter, just listed for information here):
- Install the
sassand Svelte preprocessor packages:
- Set up the Svelte preprocesser to convert SCSS into standard CSS:
The file given in line
8 can be used to include any variables which you want to expose to every style element.
Define any global styles in the files in
Import styles where components or pages need them:
- Include SCSS where you would write regular CSS, specifying
scssas the language:
Note how we can include SCSS variables now.
🔐 Content Security Policy
A Content Security Policy can break your site or make it unusable so it is important to test the policy. Reporting is helpful here and the starter is set up to use Sentry reporting. They offer free reporting, suitable for many use cases. You will need a free Sentry account and API keys for security error catching . Alternatively, remove the reporting lines from the
CSP is set to report only in the starter by default. This means errors will appear in the browser console and the reports will get sent to your Sentry dashboard when there is an error (but no connections will be blocked). You can test your HTTP security headers on securityheaders.com . Once you are happy with the policy you should switch from
Content-Security-Policy. Remember to comment out the report only line when you do this.
To include Security headers, we can use the Svelte hooks handle . The
hooks.js file is in the default location, so you should not have to include it in
svelte.config.js. The Climate SvelteKit Blog Starter SvelteKit config, includes it just for completeness though. You will almost certainly need to customise the CSP HTTP headers in the hooks file for you application.
src/hooks.js — click to expand code.
As it stands the generated sites get an A rating from SecurityHeaders.com. It should be possible to improve this by adding hashes for all inline styles and scripts and removing
unsafe-inline. I will look into how to do this when I get a chance! If you have already written a custom script to handle it, I would love to hear from you!
🖼️ Responsive Images
One area where Gatsby is still ahead of Svelte is on responsive images. I guess we have to wait a little for someone smart to write something like the Gatsby Image API for SvelteKit. In the meantime, I have cobbled together a responsive image component using Imgix for hosting. You will need an Imgix account and to have your images in the cloud somewhere (e.g. AWS S3 or Backblaze) for this to work for you. As normal, place your credentials in the
.env file (see
.env.EXAMPLE for a template).
Imgix generates images in the best format based on the user's browser. Their CDN serves images around the globe with haste. The
BannerImage component is able to query Imgix for the image url and
srcset to create a responsive image. As a temporary hack, I have manually generated these data so that the entire site can be static (this is related to the Netlify adapter issue mentioned earlier). If you also want to keep your site static, you have a choice of either also generating the data manually (or with a script) or using an alternative method for generating images.
⚖️ Gatsby – SvelteKit Comparison
I would say in time SvelteKit will offer the better developer experience, that's not to say that it is not already outstanding! Builds are a lot faster (the Svelte starter builds in around 40 seconds consistently on Netlify, compared to a range of between one minute and three-and-a-half minutes for the Gatsby starter). For bigger sites, I would imagine the difference will have an impact, especially when you have to pay per build minute.
Gatsby is more established so has already has a large ecosystem of plugins and on top there are all the React plugins. I think this gives Gatsby the advantage now if you need to build a new site quickly or generally rely on plugins. I would expect the Svelte ecosystem to grow. As it does there will probably be clear water appearing between the two on developer experience. With that in mind it is probably worth learning Svelte and SvelteKit to future-proof yourself. This is especially the case if you do not heavily rely on plugins for the sites you build, and like to roll your own components.
Please send me feedback! What do you think of the new starter? I mentioned a few improvements I have in mind. I would also love to hear your opinion on how we can be improve it. 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 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 Gatsby JS among other topics. Also subscribe to the newsletter to keep up-to-date with our latest projects.