Skip to content

Repository files navigation

Moss Theme Home Page Frost Theme Blog

mtil.uk - personal website

This is my personal website where I write and share my projects and thoughts. This is primarily a static site built with Next.js and is self-hosted on a VPS behind Docker.

The design was inspired by dithered and retro themed media out there - which is some of my favourite.

Framework Next.js (App Router, React 19)
Styling Tailwind CSS v4
Content MDX files on disk, rendered with next-mdx-remote
Animation Motion
Deploy Docker Compose, output: "standalone"

Running locally

npm install
cp .env.example .env    # fill in the values below
npm run dev

Environment

Variable Required Notes
NEXT_PUBLIC_SITE_URL yes Absolute site URL. Read at build time — baked into the image.
DISCORD_WEBHOOK_URL yes Where contact form submissions are delivered.
GITHUB_TOKEN no Classic PAT, no scopes needed. Used for the contribution graph on the GitHub social card and star counts on project cards. Without it, public (rate-limited) APIs are used instead.

Content

All content for the site is done using markdown or JSON - there is no database or CMS to keep the site as simple as possible.

content/
├── blogs/*.mdx        posts — frontmatter + body
└── socials.yaml       profile data for the social hover cards

Slugs are derived from filenames, not frontmatter. If you name a blog post content/blogs/my-post.mdx then the path for the post will be /blog/my-post

Footnote-style references at the bottom of a post are parsed out of the body.

Layout

app/            routes, API handlers, feed/sitemap/robots
components/
├── article/    long-form rendering: MDX components, references, share
├── home/       home page sections
├── layout/     site chrome: preferences bar
├── providers/  theme context
├── socials/    per-platform hover cards
├── icons/      hand-rolled brand marks
└── ui/         primitives
lib/            content loading, palettes, validation

Notable bits

Themes (⌘B) swap a set of CSS custom properties registered with @property, so every colour on the page cross-fades rather than snapping. The choice is applied by an inline script before first paint to avoid a flash.

Social cards are per-platform widgets that mimicks each platforms UI. The GitHub widget has a contribution graph, Letterboxd has a poster row and LinkedIn has the LinkedIn colours and banner.

Sounds play on interactions and are always on.

Deploying

docker compose up -d --build

Serves on port 3001, expecting a reverse proxy in front for TLS.

Releases

Packages

Contributors

Languages