Vegard Andreas Larsen Vegard Andreas Larsen, slightly peeking above the bottom edge.

A personal website built for 2023

No-one can claim I’ve written a lot on this website. With the last post here being from 2018, just a mere 4 years between posts must be some sort of a record.

I’ve always felt that one big hindrance in writing posts have been the barrier to entry. Even though I work daily in tools like Visual Studio Code, and with Git, having a Git-based workflow makes it more difficult than it needs to be to write a new post. Another consistent pain point have been image handling — mainly resizing, cropping and remembering the Markdown image syntax — it just became this tiny hurdle that made it just that little bit harder to get started on a post.

An idea is born

About 2 months ago we started talking about a CMS for the website for Beat Technology AS. We had these small updates that we would like to include on the website, and since we are using Notion internally, it sparked an idea in me if we could render Notion pages as proper websites. The initial proof of concept didn’t take long to complete, but polishing it into a proper open source project did take a while.

Notion blocks for Svelte ( source on GitHub) allows you to render most Notion pages quite easily using Svelte and SvelteKit; in mostly semantic HTML that you can style to look however you want. It supports most Notion blocks with a few exceptions, and allows you to write articles quickly and easily.

Even though the library allows you to render any Notion page as HTML, it is most useful when you use a database for it. For the posts on this page, I’ve set up a very simple database with just a few properties:

  • Title — you get this one.
  • Description is the meta tag description that get’s added to the HTML.
  • Published is the date of publication.
  • Slug is the slug to use in the URL, this post will be available at https://vega.rd.no/writing/website-for-2023. You can use Notion page IDs for this if you would like, but they are ugly in a URL.
  • Status is a custom status field where I’ve set up a few states that make sense to me: Idea, Draft and Published.
  • Updated is an auto-updated property with the date of the last change.

What it looks like when I am writing a post.

I’ve then set up some filters in Notion for my own use that helps me quickly get an overview of posts that I haven’t completed yet.

My custom views of the blog database in Notion.

I have reproduced the “Published” view using Notion’s API syntax, and I came up with this:

{
    "slug_property": "Slug",
    "query": {
        "database_id": "ba976fef8d814ac18a834f466bd1c4fa",
        "sorts": [
            {
                "property": "Published",
                "direction": "descending"
            }
        ],
        "filter": {
            "and": [
                {
                    "property": "Status",
                    "status": {
                        "equals": "Published"
                    }
                },
                {
                    "property": "Published",
                    "date": {
                        "on_or_before": "2022-12-24"
                    }
                }
            ]
        }
    }
}
Simple filter that filters by Status = Published, and Published after the current date (the on_or_before value is generated on request).

Some notes

  • The library helps with caching the data from Notion’s API on Vercel’s (or Netlify’s) edge network using standard HTTP headers. This is possible because I’ve divided each route in SvelteKit into 3 parts, where a +server.ts gets data from Notion and outputs cache headers. +page.ts then fetches data from +server.ts using a regular HTTP fetch, but doesn’t do any transformation. This allows for using data-sveltekit-preload-data on internal links. +page.svelte then just uses the data to render the page using Notion blocks for Svelte.
  • For styling I’ve been strongly inspired by Svbtle, which is a publishing platform that I have evaluated many times.
  • Auto-switches dark mode depending on your device’s settings.

If you want to have a look at how this was made, I’ve opened up the repository on Github. Feel free to clone it for your own needs. There are also some examples on the Notion Blocks for Svelte website, including the actual Notion database that powers that site.

Published 2022-12-24.