---
title: "Testing Out The Blog"
subtitle: "Just testing out all the features to see if this works."
author: "Riley Leff"
url: "https://rileyleff.com/blog/testing-out-the-blog"
published: "2026-02-28"
series: "hello-world"
tags: ["rust", "svelte", "infrastructure", "meta"]
---

# Testing Out The Blog

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

<!-- Capitalized tags like <Plot /> are interactive figures on the web version: https://rileyleff.com/blog/testing-out-the-blog -->

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

<Note type="info">
Yes, this is overkill for a personal blog.
</Note>

## 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:

```rust
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:

```typescript
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:

<LeaderboardEmbed slug="llm-arena" title="LLM Arena Rankings" />

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:

<ParticleField count={100} color="#5ce8ff" connectDistance={120} />

This runs entirely client-side!

## Math

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

$$
\nabla \times \mathbf{E} = -\frac{\partial \mathbf{B}}{\partial t}
$$

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

$$
\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](https://rileyleff.com)
- 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 words[^1]. Here's some more stuff [^2].

[^1]: Here's some footnote. 
[^2]: Crazy second footnote.

<Updated date="2026-03-01">
Added the interactive particle field component and leaderboard embed with live data from production.
</Updated>

## Trying Out Series

Check out [part 2](/blog/posts-in-a-series) for the next post in the series.
