Svelte + Markdown blog images setup
There are plenty of guides online on how to setup a svelte + markdown based blog app, but they seem to be missing one key ingredient: how to attach images to your articles and manage all the post-processing and optimisations on them. So, I figured I’ll throw together a short guide, maybe it’ll help someone.
Step 1, the imagetools
The first thing you need to add — and that’s regardless whether it’s a blog app or any other type of svelte apps — is the vite-imagetools plugin to your vite setup:
import { sveltekit } from "@sveltejs/kit/vite";
import { imagetools } from "vite-imagetools";
const config: UserConfig = {
plugins: [sveltekit(), imagetools()],
// ....
What it does, it enables image optimisation and preprocessing for all the image assets in your Svelte/Vite based application. Once that is installed, you can configure the optimisation preferences for the images you’re importing in your app:
<script>
import face from "assets/face.jpg?w=400&webp";
</script>
<img src={face}>
Here by adding the ?w=400&webp
query string to the end of the original image file, I asked the image to be resided to the width of 400px
and converted to the webp
format. This way you can do all sorts of magic, like having multiple sizes of the same original image for different devices, change formats, etc.
Step 2, add markdown plugins
The great thing about mdsvex — the default svelte markdown processor — is that it supports the remark and rehype plugins ecosystems. Long story short, remark adds features to convert markdown to HTML, and rehype adds features to convert HTML to HTML; as in post-process HTML itself.
To make this thing work, you will need two plugins. The first one is a remark plugin called
mdsvex-relative-images. And the second one
is a rehype plugin called rehype-figure.
Import them both and add them to your svelte.config.js
file in your mdsvex config like so:
import remarkRelativeImages from "mdsvex-relative-images";
import rehypeFigure from "rehype-figure";
const config = {
preprocess: [
mdsvex({
extensions: [".md", ".mdx"],
remarkPlugins: [
remarkRelativeImages,
// ...
],
rehypePlugins: [
[rehypeFigure, { className: "my-class" }],
// ...
],
// ...
}),
],
// ...
Profit
A now a bit of explanation how it all works. The relative images plugin allows you to refer to local images that usually live next to your markdown file, like so:
lorem ipsum blah blah blah
![alt text](./face.jpg?w=600&webp)
lorem ipsum blah blah blah
The plugin will not only automatically sort out the paths and file locations, but also shovel your o/g images through the imagetools optimisation pipeline. This way you can keep your o/g images in high res and whatever format, and control how they will be actually deployed in the production build.
The first plugin will produce a regular <img />
tag, which is less than ideal for styling purposes, and that is why you need the rehype-figure
plugin, which will turn your vanilla <img />
tag into a proper <figure>
envelope:
<img src="/assets/face-hash459.webp" alt="Alt text" />
<!-- converted into -->
<figure class="my-class">
<img src="/assets/face-hash459.webp" alt="Alt text">
<figcaption>Alt text</figcaption>
</figure>
It also will neatly place the figure
tag in between the p
text blocks, which is a way easier to style nicely.
And, that’s pretty much the whole story. Enjoy!