This repository demonstrates how a blog with SvelteKit can be built, without using any markdown or extra packages.
Demo: https://blog-sveltekit-approach.netlify.app
The idea is to put every blog post inside of a route resp. SvelteKit page. For example, one blog post could be the SvelteKit page src/routes/post/first-post/+page.svelte
. In these SvelteKit pages, we can do whatever we want. We can also add Svelte components without any extra configuration.
Metadata are exported from the context script tag:
<!-- src/routes/post/first-post/+page.svelte --->
<script lang="ts" context="module">
import Post from "../Post.svelte";
export let title = "My first blog post";
export let date = new Date("2023-01-22");
</script>
<Post {title} {date}>
<p>
Write something here
</p>
</Post>
In the wrapper Post.svelte
component, we render the metadata in a consistent way. We can also add anything which every post needs to include, for example a link to the page with all posts. (This is somewhat similar to a layout file, but more flexible, and the usage of props seems to be more easy than using page data.)
<!-- src/routes/post/Post.svelte -->
<script lang="ts">
export let title: string;
export let date: Date;
</script>
<svelte:head>
<title>{title}</title>
</svelte:head>
<h2>{title}</h2>
<p>{date.toLocaleDateString()}</p>
<slot />
<p >
<a href="/">All Posts</a>
</p>
Now, in order to list all posts on a page, we make the following computation in its load function:
// src/routes/+page.server.ts
export const load = async () => {
const posts_paths = Object.keys(
import.meta.glob("/src/routes/post/*/+page.svelte")
);
const unsorted_posts: post[] = await Promise.all(
posts_paths.map(async (path) => {
const link = path.split("/").at(-2) ?? "";
const component = await import(
`../routes/post/${link}/+page.svelte`
);
const { title, date } = component;
return { link, title, date };
})
);
const posts = unsorted_posts.sort(
(p, q) => q.date.getTime() - p.date.getTime()
);
return { posts };
};
The main steps are the following:
import.meta.glob
function gives us the list of all pages in our post folder.await import(...)
and extract their props.post
is declared in app.d.ts
.On the page itself, we can now list links to all posts as follows:
<!-- src/routes/+page.svelte -->
<script lang="ts">
export let data;
const { posts } = data;
</script>
<ul>
{#each posts as post}
<li>
<a href="/post/{post.link}">{post.title}</a>
–
<span>{post.date.toLocaleDateString()}</span>
</li>
{/each}
</ul>
It should be clear how to add any other post data, for example a summary, updated-at date, etc.