add a blog (or changelog) to any SvelteKit site

leblog is made to quickly add a blog (or blogs) to new and existing SvelteKit sites.

Its raison d'être is that I (Nick) wanted to keep changelogs for my SvelteKit projects without the fanfare of signing up for something or adding boilerplate.

It is not:

  • A fully-featured CMS like Strapi, Ghost or Tina.
  • A replacement for Substack.

quick start

npm install leblog

1. install the plugin

In vite.config.js:

import leblog from 'leblog'

export default defineConfig({
  plugins: [leblog(), ...]

2. write

In the posts directory at the root of your project write markdown files with yyyy-mm-dd-{slug}.md-formatted filenames.

title: my epic post

the title says it all

3. load

On any page or in any component:

  import { load } from 'leblog'

  const posts = load('posts')

  {#each posts as post}

      {@html post.html}

Et voila! Full documentation is on github, and you can see it in action on the demo page. Single-file changelogs also work, like this one (source):


  • 0.9.1 mon jul 10 2023


    • Building apps with the leblog plugin would hang indefinitely; no longer!
  • 0.9.0 mon jul 10 2023


    • Feeds are now 'virtual', and the only thing you need to do is specify them in your config. For example:
    export default {
      collections: {
        posts: {
          path: 'posts',
          feed: 'blog.atom'
        changelog: 'CHANGELOG.md'

    And as if by magic, a /blog.atom route will exist on your website with an Atom feed of all your posts (RSS and JSON also work; just change the file extension).

  • 0.8.4 wed jun 28 2023


    • The way this plugin works has been overhauled. It's now a Vite plugin, and you load entries from the exported load function.
  • 0.7.0 sun jun 04 2023


  • 0.6.0 sat jun 03 2023


    • Posts no longer require a slug, so a date is a valid filename (e.g. 2023-06-03.md).
    • Entries now have a path property which you can use for linking pages, which will be the date combined with the slug if there is one. Using the slug property alone still works, in case you don't want the date displayed in the URL.
  • 0.5.0 wed mar 08 2023


    • You can now create Atom and RSS feeds! To do so, export a GET request handler from a page's +server.js:
    import { loadFeed } from 'leblog'
    export const GET = loadFeed('posts')
    • Entries now contain an html field with — you guessed it! — the entry's HTML.
  • 0.4.3 tue mar 07 2023


    • @sveltejs/kit and svelte dependencies are now set correctly.
  • 0.4.2 fri feb 24 2023


    • Entry is now exported from leblog instead of leblog/entry (conditional exports ftw).
  • 0.3.1 thu feb 23 2023


    • loadCollection, loadEntry and load now run on the server in +page.server.js endpoints, removing the need for a handle hook.
    • The Entry component is now exported from leblog/entry.


    • Only markdown files (.md) are now considered entries.


    • The leblog hook, which is replaced by the aforementioned load functions.
  • 0.2.0 thu feb 23 2023


    • A load function to infer a collection/entry, assuming there's only one defined collection.
    • Added an optional second slug parameter to loadEntry, so you can override the default params.slug.
    • An exported handle alias of leblog, so in hooks.server.js you can simply: export { handle } from 'leblog/hooks'.
  • 0.1.0 wed feb 22 2023

    The first release!

Made with ❤️ by nbgoodall