How to create a blog with SvelteKit and dev.to API
Intro
This is my first post and I'm gonna show you how I have created a blog section for my personal website.
The inspiration for that project come up in my mind reading this article by JPBlancoDB
The main difference is that I'm gonna make it with the new SvelteKit framework and I will add a page to read the article directly from your website.
I'm not gonna add any CSS in the examples below
Routing
SvelteKit uses a filesystem-based router. This means that the structure of your application is defined by the structure of the files in the src/routes
folder.
In order to do that, we need to create a folder named blog
and inside that, we need to create two files:
- index.svelte
- [slug].svelte
index.svelte
is just going to be rendered when you visit yourDomain.com/blog
and we are going to show the list of your dev.to post here.
instead
[slug].svelte
is going to be rendered when you visit yourDomain.com/blog/yourDevToPostId
and we are going to show the single article when you click on it
Index.svelte
The main file (index.svelte
) it's structured in the following way.
// this script fetch the posts from the api
// https://svelte.dev/docs#script_context_module
<script context="module">
// this is runned on load (check svelKit doc)
export async function load({ fetch }) {
let articles;
try {
// here you should type your dev.to username
articles = await fetch(`https://dev.to/api/articles?username=ladvace`);
articles = await articles.json();
} catch (e) {
console.log(e);
}
// you can pass the `articles` via props like that
return {
props: {
articles
}
};
}
</script>
// in this second script you are going to declare the articles fetched in the first script and eventually filter them as I did
<script>
export let articles;
// here I blacklist some posts adding the id of the post (from the API) in this array
const blackListedArticles = [432439];
const filteredArticles = articles.filter((article) => !blackListedArticles.includes(article.id));
</script>
<div class="articlesContainer">
<div class="articles">
<h1>Articles</h1>
// if you don't need to filter your posts just pass the `articles` instead if `filteredArticles`
{#each filteredArticles as article}
// here on click you we are passing the article of the id
<a href={`/blog/${article.id}`}>
<div class="article">
<div class="header">
<h2>{article.title} </h2>
<h4>Tags: {article.tags}</h4>
</div>
<p>
{article.description}
</p>
</div>
</a>
{/each}
{#if filteredArticles.length === 0}
<div>No Articles</div>
{/if}
</div
[slug].svelte
The structure of ([slug].svelte
) is very simple.
<script context="module">
export async function load({ fetch, page }) {
let article;
try {
// here we are gonna fetch the single article by id
article = await fetch(`https://dev.to/api/articles/${page.params.slug}`);
article = await article.json();
} catch (e) {
console.log(e);
}
return {
props: {
article
}
};
}
</script>
<script>
export let article;
</script>
<div class="articleContainer">
<div class="article">
<h1>{article.title}</h1>
// you can "parse" HTML with svelte like that
// https://svelte.dev/docs#html
{@html article.body_html}
</div>
</div>
Thanks for reading
Don't hesitate to leave me any comment, improvement tips (for the code and writing posts)