Testing Out The Blog

Just testing out all the features to see if this works.

Finally got my blog up and running. Just putting out a quick pilot post to see if everything is working as intended.

How It Works

The site runs on a single Hetzner box. Here's what's on it:

  • Caddy — reverse proxy and automatic TLS
  • SvelteKit — the frontend you're looking at
  • riley_cms — a git-backed CMS I wrote in Rust
  • riley_leaderboards — a versioned ranking service
  • riley_auth — my simple OAuth wrapper (I never store your password on my end).
  • PostgreSQL 18 with PostGIS

How Content Works

Blog posts are MDX files in a git repository. When I push changes, the CMS picks them up serves them via API. The SvelteKit frontend fetches posts at request time and renders the markdown server-side with syntax highlighting and whatnot.

The interesting part is custom components. MDX lets me drop in things like <Note>, <Updated>, and <LeaderboardEmbed>, which are real Svelte 5 components that get mounted at render time.

Code Highlighting

Here's a Rust snippet from the CMS itself:

pub async fn get_post(
    &self,
    slug: &str,
) -> Result<Post> {
    let content_dir = self
        .repo_path
        .join("content");
    let post_dir = content_dir.join(slug);
 
    let config: PostConfig = self
        .load_toml(&post_dir.join("config.toml"))?;
    let content = tokio::fs::read_to_string(
        post_dir.join("content.mdx"),
    )
    .await?;
 
    Ok(Post {
        slug: slug.to_string(),
        title: config.title,
        content,
        ..Default::default()
    })
}

And some TypeScript from the frontend's MDX parser:

export async function parseMDX(
    raw: string,
): Promise<Segment[]> {
    const segments: Segment[] = [];
    let lastIndex = 0;
 
    COMPONENT_RE.lastIndex = 0;
 
    let match;
    while (
        (match = COMPONENT_RE.exec(raw))
        !== null
    ) {
        const before = raw.slice(
            lastIndex,
            match.index,
        );
        if (before.trim()) {
            const html =
                await renderMarkdown(before);
            if (html) segments.push({
                type: 'html',
                content: html,
            });
        }
        // ... extract component name,
        // props, children
    }
    return segments;
}

Live Leaderboard

One of the services I built is a versioned leaderboard API. Here's a little demo, embedded in a blog post:

LLM Arena Rankings

Loading...

That component fetches from the leaderboard API at render time. If there are multiple versions, you can switch between them with the dropdown. The data is stored in PostgreSQL and managed through TOML files in a separate content repo.

Interactive Components

Since the frontend is SvelteKit, I can embed fully interactive Svelte 5 components directly in posts. Here's a particle field that responds to your cursor:

Move your cursor over the field

This runs entirely client-side!

Math

Posts support LaTeX math via KaTeX. Inline math like E=mc2E = mc^2 works mid-sentence, and display math gets its own block:

∇×E=−∂B∂t\nabla \times \mathbf{E} = -\frac{\partial \mathbf{B}}{\partial t}

Here's something crazy. Why note put the Navier-Stokes momentum equation:

ρ(∂u∂t+u⋅∇u)=−∇p+μ∇2u+f\rho \left( \frac{\partial \mathbf{u}}{\partial t} + \mathbf{u} \cdot \nabla \mathbf{u} \right) = -\nabla p + \mu \nabla^2 \mathbf{u} + \mathbf{f}

The rendering happens server-side through remark-math and rehype-katex in the unified pipeline — no client-side JavaScript needed.

Markdown Features

The usual suspects all work. Bold, italic, strikethrough, and inline code.

Blockquotes look like this. They're good for calling out important ideas or quoting other people.

Lists

Unordered:

  • First item
  • Second item with bold and a link
  • Third item

Ordered:

  1. Step one
  2. Step two
  3. Step three

Tables

Service Language Purpose
riley_cms Rust Content management
riley_leaderboards Rust Versioned rankings
riley_auth Rust Identity / OAuth
Frontend TypeScript SvelteKit app

Footnotes

Here's some words1. Here's some more stuff 2.

Footnotes

  1. Here's some footnote. ↩

  2. Crazy second footnote. ↩

Updated Mar 1, 2026
Added the interactive particle field component and leaderboard embed with live data from production.

Trying Out Series

Check out part 2 for the next post in the series.

Comments

Loading comments...