summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/404.html9
-rw-r--r--src/assets/css/default.scss276
-rw-r--r--src/assets/css/syntax.scss243
-rw-r--r--src/assets/fonts/AtkinsonHyperlegibleMono-Regular.ttfbin0 -> 34320 bytes
-rw-r--r--src/assets/fonts/AtkinsonHyperlegibleNext-Regular.ttfbin0 -> 48064 bytes
-rw-r--r--src/assets/images/converter.webpbin0 -> 18080 bytes
-rw-r--r--src/assets/images/erebus.webpbin0 -> 17652 bytes
-rw-r--r--src/assets/images/favicon.icobin0 -> 14098 bytes
-rw-r--r--src/assets/images/noise.pngbin0 -> 26039 bytes
-rw-r--r--src/assets/images/nonbinary-flag.svg21
-rw-r--r--src/index.html97
-rw-r--r--src/pages/playlists.html57
-rw-r--r--src/posts/2025-06-20-vr-plus-nixos-plus-nvidia.md130
-rw-r--r--src/templates/archive.html3
-rw-r--r--src/templates/default.html97
-rw-r--r--src/templates/post-list.html5
-rw-r--r--src/templates/post.html7
17 files changed, 945 insertions, 0 deletions
diff --git a/src/404.html b/src/404.html
new file mode 100644
index 0000000..4bbf02f
--- /dev/null
+++ b/src/404.html
@@ -0,0 +1,9 @@
+---
+title: 404 Not Found
+---
+
+<p>The page you requested cannot be found.</p>
+
+<p>
+ <a href="/">Click here to return back to the home page.</a>
+</p>
diff --git a/src/assets/css/default.scss b/src/assets/css/default.scss
new file mode 100644
index 0000000..8509dfb
--- /dev/null
+++ b/src/assets/css/default.scss
@@ -0,0 +1,276 @@
+// VARIABLES AND IMPORTS
+// ---------------------------------------------------------------------------
+
+$clr-bg: oklch(22.49% 0.008 297.21);
+$clr-fg: oklch(98.51% 0 0);
+$clr-primary: oklch(82.67% 0.096 307.5);
+$clr-secondary: oklch(from $clr-primary l c 240); // hue-shifted copy
+
+$gap: 1rem;
+$max-width: 50rem;
+$mobile: 980px;
+
+@import "syntax";
+
+// MIXINS
+// ---------------------------------------------------------------------------
+
+@mixin phone-only {
+ @media (max-width: $mobile) {
+ @content;
+ }
+}
+
+@mixin std-block {
+ display: block;
+ margin: 0;
+}
+
+// GLOBAL RESET & TYPOGRAPHY
+// ---------------------------------------------------------------------------
+
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+
+* {
+ padding: 0;
+ margin: 0;
+ transition: 0.1s ease-in-out;
+ font-family: "Atkinson Hyperlegible Next", sans-serif;
+ font-optical-sizing: auto;
+ text-transform: lowercase;
+}
+
+html {
+ font-size: 16px;
+}
+
+// 1rem base
+
+body {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: $gap;
+ padding: 5rem $gap $gap;
+ overflow-x: hidden;
+ color: $clr-fg;
+ background-color: black;
+ background:
+ url("/assets/images/noise.png"),
+ radial-gradient(circle at center, $clr-bg, transparent),
+ radial-gradient(circle at bottom left, #27577d, transparent),
+ radial-gradient(circle at top right, #952ea4 0%, transparent),
+ radial-gradient(circle at center right, #6949a5 0%, transparent),
+ radial-gradient(circle at top center, #336ba0 0%, transparent);
+ background-attachment: fixed;
+}
+
+// LAYOUT WRAPPER
+// ---------------------------------------------------------------------------
+
+body > * {
+ // every top-level section
+ display: flex;
+ flex-direction: column;
+ gap: $gap;
+ width: 100%;
+ max-width: $max-width;
+ padding: 1.5rem 2.5rem;
+ background: $clr-bg;
+ outline: 0.2rem solid $clr-bg;
+ outline-offset: 0.2rem;
+}
+
+@include phone-only {
+ body {
+ padding: 0;
+ gap: 0.2rem;
+ }
+
+ body > * {
+ outline: 0;
+ }
+}
+
+// NAVIGATION
+// ---------------------------------------------------------------------------
+
+nav {
+ position: fixed;
+ transform: translateX(28rem);
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: $gap;
+ padding: 1rem 2rem;
+ width: 0rem;
+
+ svg {
+ width: 2rem;
+ height: 2rem;
+ fill: $clr-fg;
+ }
+
+ a {
+ writing-mode: vertical-rl;
+ text-orientation: sideways;
+ text-decoration: none;
+ color: $clr-fg;
+ }
+
+ hr {
+ width: 100%;
+ }
+}
+
+@include phone-only {
+ nav {
+ position: static;
+ transform: none;
+ flex-direction: row;
+ justify-content: space-between;
+ width: 100%;
+
+ a {
+ writing-mode: horizontal-tb;
+ }
+
+ hr {
+ display: none;
+ }
+ }
+}
+
+// TYPOGRAPHIC ELEMENTS
+// ---------------------------------------------------------------------------
+
+p,
+ul,
+span {
+ font-size: 1.2rem;
+ text-align: justify;
+}
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ @include std-block;
+ padding-top: 0.5rem;
+ font-size: 1.75rem;
+}
+
+// auto-generate heading prefixes
+@for $i from 1 through 6 {
+ h#{$i}::before {
+ $hashes: "";
+
+ @for $_ from 1 through $i {
+ $hashes: $hashes + "#";
+ }
+
+ content: "#{$hashes} ";
+ color: oklch(82.67% 0.087 #{280 + ($i - 1) * 40});
+ }
+}
+
+// LISTS
+// ---------------------------------------------------------------------------
+
+ul {
+ display: flex;
+ flex-direction: column;
+ gap: 0.5rem;
+ list-style: none;
+
+ li::before {
+ content: "~";
+ padding: 0 0.25rem 0 0.5rem;
+ color: oklch(82.67% 0.087 180);
+ }
+}
+
+// rainbow list items
+@for $i from 1 through 15 {
+ ul li:nth-child(n + #{$i})::before {
+ color: oklch(82.67% 0.087 #{100 + ($i - 1) * 80});
+ }
+}
+
+// LINKS & MISC
+// ---------------------------------------------------------------------------
+
+a {
+ color: $clr-primary;
+
+ &:hover {
+ filter: brightness(0.75);
+ }
+}
+
+hr {
+ $c: oklch(from $clr-fg 0.45 c h);
+ background: $c;
+ border-color: $c;
+}
+
+img {
+ user-select: none;
+}
+
+address {
+ opacity: 0.5;
+ text-align: right;
+ margin-top: -2.1lh;
+ margin-bottom: 0.5rem;
+}
+
+footer {
+ gap: 0;
+
+ > * {
+ text-align: center;
+ font-size: 1rem;
+ opacity: 0.5;
+ }
+}
+
+// CODE BLOCKS
+// ---------------------------------------------------------------------------
+
+div.sourceCode {
+ padding: 0.2rem;
+ overflow: hidden;
+ font-family: "Atkinson Hyperlegible Mono", monospace;
+ background-color: black;
+ background:
+ url("/images/noise.png"),
+ radial-gradient(circle at center, $clr-bg, transparent),
+ radial-gradient(circle at bottom left, #27577d, transparent),
+ radial-gradient(circle at top right, #952ea4 0%, transparent),
+ radial-gradient(circle at center right, #6949a5 0%, transparent),
+ radial-gradient(circle at top center, #336ba0 0%, transparent);
+ background-attachment: scroll;
+
+ outline: 0.2rem solid $clr-bg;
+ outline-offset: 0.2rem;
+
+ > * {
+ background: $clr-bg;
+ background-attachment: fixed;
+ padding: 1.2rem;
+ overflow: auto;
+ }
+
+ * {
+ font-family: "Atkinson Hyperlegible Mono", monospace;
+ text-transform: none;
+ font-size: 1.05rem;
+ }
+}
diff --git a/src/assets/css/syntax.scss b/src/assets/css/syntax.scss
new file mode 100644
index 0000000..42be310
--- /dev/null
+++ b/src/assets/css/syntax.scss
@@ -0,0 +1,243 @@
+a.sourceLine {
+ display: inline-block;
+ line-height: 1.25;
+}
+
+a.sourceLine {
+ pointer-events: none;
+ color: inherit;
+ text-decoration: inherit;
+}
+
+a.sourceLine:empty {
+ height: 1.2em;
+}
+
+.sourceCode {
+ overflow: visible;
+}
+
+code.sourceCode {
+ white-space: pre;
+ position: relative;
+}
+
+div.sourceCode {
+ margin: 1em 0;
+}
+
+pre.sourceCode {
+ margin: 0;
+}
+
+@media screen {
+ div.sourceCode {
+ overflow: auto;
+ }
+}
+
+@media print {
+ code.sourceCode {
+ white-space: pre-wrap;
+ }
+
+ a.sourceLine {
+ text-indent: -1em;
+ padding-left: 1em;
+ }
+}
+
+pre.numberSource a.sourceLine {
+ position: relative;
+ left: -4em;
+}
+
+pre.numberSource a.sourceLine::before {
+ content: attr(title);
+ position: relative;
+ left: -1em;
+ text-align: right;
+ vertical-align: baseline;
+ border: none;
+ pointer-events: all;
+ display: inline-block;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ padding: 0 4px;
+ width: 4em;
+ color: #aaaaaa;
+}
+
+pre.numberSource {
+ margin-left: 3em;
+ border-left: 1px solid #aaaaaa;
+ padding-left: 4px;
+}
+
+div.sourceCode {
+}
+
+@media screen {
+ a.sourceLine::before {
+ text-decoration: underline;
+ }
+}
+
+code span.al {
+ color: #f85858;
+ font-weight: bold;
+}
+
+/* Alert */
+code span.an {
+ color: #3dddd8;
+ font-weight: bold;
+ font-style: italic;
+}
+
+/* Annotation */
+code span.at {
+ color: #2ac68e;
+}
+
+/* Attribute */
+code span.bn {
+ color: #2ac68e;
+}
+
+/* BaseN */
+code span.bu {
+}
+
+/* BuiltIn */
+code span.cf {
+ color: #2ac68e;
+ font-weight: bold;
+}
+
+/* ControlFlow */
+code span.ch {
+ color: #008ce3;
+}
+
+/* Char */
+code span.cn {
+ color: #f85858;
+}
+
+/* Constant */
+code span.co {
+ color: #3dddd8;
+ font-style: italic;
+}
+
+/* Comment */
+code span.cv {
+ color: #3dddd8;
+ font-weight: bold;
+ font-style: italic;
+}
+
+/* CommentVar */
+code span.do {
+ color: #f85858;
+ font-style: italic;
+}
+
+/* Documentation */
+code span.dt {
+ color: #f85858;
+}
+
+/* DataType */
+code span.dv {
+ color: #2ac68e;
+}
+
+/* DecVal */
+code span.er {
+ color: #f85858;
+ font-weight: bold;
+}
+
+/* Error */
+code span.ex {
+}
+
+/* Extension */
+code span.fl {
+ color: #40a070;
+}
+
+/* Float */
+code span.fu {
+ color: #008ce3;
+}
+
+/* Function */
+code span.im {
+}
+
+/* Import */
+code span.in {
+ color: #3dddd8;
+ font-weight: bold;
+ font-style: italic;
+}
+
+/* Information */
+code span.kw {
+ color: #2ac68e;
+ font-weight: bold;
+}
+
+/* Keyword */
+code span.op {
+ color: #aaaaaa;
+}
+
+/* Operator */
+code span.ot {
+ color: #2ac68e;
+}
+
+/* Other */
+code span.pp {
+ color: #ff8a00;
+}
+
+/* Preprocessor */
+code span.sc {
+ color: #4070a0;
+}
+
+/* SpecialChar */
+code span.ss {
+ color: #008ce3;
+}
+
+/* SpecialString */
+code span.st {
+ color: #008ce3;
+}
+
+/* String */
+code span.va {
+ color: #008ce3;
+}
+
+/* Variable */
+code span.vs {
+ color: #008ce3;
+}
+
+/* VerbatimString */
+code span.wa {
+ color: #3dddd8;
+ font-weight: bold;
+ font-style: italic;
+}
diff --git a/src/assets/fonts/AtkinsonHyperlegibleMono-Regular.ttf b/src/assets/fonts/AtkinsonHyperlegibleMono-Regular.ttf
new file mode 100644
index 0000000..157d62e
--- /dev/null
+++ b/src/assets/fonts/AtkinsonHyperlegibleMono-Regular.ttf
Binary files differ
diff --git a/src/assets/fonts/AtkinsonHyperlegibleNext-Regular.ttf b/src/assets/fonts/AtkinsonHyperlegibleNext-Regular.ttf
new file mode 100644
index 0000000..3fa771f
--- /dev/null
+++ b/src/assets/fonts/AtkinsonHyperlegibleNext-Regular.ttf
Binary files differ
diff --git a/src/assets/images/converter.webp b/src/assets/images/converter.webp
new file mode 100644
index 0000000..36764fa
--- /dev/null
+++ b/src/assets/images/converter.webp
Binary files differ
diff --git a/src/assets/images/erebus.webp b/src/assets/images/erebus.webp
new file mode 100644
index 0000000..510545e
--- /dev/null
+++ b/src/assets/images/erebus.webp
Binary files differ
diff --git a/src/assets/images/favicon.ico b/src/assets/images/favicon.ico
new file mode 100644
index 0000000..5000bb7
--- /dev/null
+++ b/src/assets/images/favicon.ico
Binary files differ
diff --git a/src/assets/images/noise.png b/src/assets/images/noise.png
new file mode 100644
index 0000000..93c1ad7
--- /dev/null
+++ b/src/assets/images/noise.png
Binary files differ
diff --git a/src/assets/images/nonbinary-flag.svg b/src/assets/images/nonbinary-flag.svg
new file mode 100644
index 0000000..5252870
--- /dev/null
+++ b/src/assets/images/nonbinary-flag.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="64px" height="64px" viewBox="0 0 64 64" style="enable-background:new 0 0 64 64;" xml:space="preserve">
+<style type="text/css">
+ .st0{fill:#FFF430;}
+ .st1{fill:#FFFFFF;}
+ .st2{fill:#9C59D1;}
+ .st3{fill:#99A8AE;}
+ .st4{fill:#6E8189;}
+</style>
+<path class="st0" d="M4,4.25c0,4.13,0,6.96,0,11.09c19.33,7.81,38.67-7.81,58,0c0-6.8,0-4.28,0-11.09C42.67-3.55,23.33,12.06,4,4.25
+ z"/>
+<path class="st1" d="M4,13.13c0,4.13,0,6.96,0,11.09c19.33,7.81,38.67-7.81,58,0c0-4.13,0-6.96,0-11.09
+ C42.67,5.32,23.33,20.94,4,13.13z"/>
+<path class="st2" d="M4,22c0,4.13,0,6.96,0,11.09c19.33,7.81,38.67-7.81,58,0c0-6.8,0-4.28,0-11.09C42.67,14.19,23.33,29.81,4,22z"
+ />
+<path d="M4,30.87c0,3.17,0,5.8,0,8.87c19.33,7.81,38.67-7.81,58,0c0-8.6,0-0.66,0-8.87C42.67,23.06,23.33,38.68,4,30.87z"/>
+<path class="st3" d="M2,4.12V62l4,0V4.12C6,1.29,2,1.29,2,4.12z"/>
+<path class="st4" d="M2.99,2.27c0.57,0.32,1,0.91,1,1.82L4,61.97l2,0V4.09C6,2.18,4.18,1.6,2.99,2.27z"/>
+</svg>
diff --git a/src/index.html b/src/index.html
new file mode 100644
index 0000000..574743e
--- /dev/null
+++ b/src/index.html
@@ -0,0 +1,97 @@
+---
+title: Hi!
+---
+
+<h1>Hi! I'm Jamie!</h1>
+
+<p>
+ I also go by skiletro, or just simply skil, and use they/them pronouns. I'm
+ interested in a whole range of things; most of which have some sort of
+ connection to technology. Mechanical keyboards, and linux ricing are some of
+ my current interests, alongside esports, hardware, and a little language
+ learning on the side!
+</p>
+
+<h2>Projects</h2>
+<ul>
+ <li>
+ <img
+ src="/assets/images/erebus.webp"
+ height="120px"
+ align="right"
+ style="padding-left: 1rem"
+ />
+ <a href="https://codeberg.org/skil/erebus">erebus</a>
+ - A Nix flake containing all of my system configuration. It features
+ numerous custom packages, configurations for multiple systems, and secrets
+ handling, just to name a few features. I've put a <em>lot</em> of effort
+ into considering both form and function. Before this, I worked on another
+ flake called <a href="https://github.com/skiletro/nixfiles">nixfiles</a>,
+ which has gained more attention over the years.
+ </li>
+ <li>
+ <img
+ src="/assets/images/converter.webp"
+ height="120px"
+ align="left"
+ style="padding-right: 1rem"
+ />
+ <a href="http://github.com/skiletro/cave-360-video-converter/"
+ >cave 360 video converter</a
+ >
+ - Written in Go as part of my software dev internship at MMU, this internal
+ tool converts panoramic 360 videos into a format that can be used as a
+ background for the university's cave facility.
+ </li>
+ <li>
+ <!-- <img -->
+ <!-- src="https://placehold.co/120x90" -->
+ <!-- align="right" -->
+ <!-- style="padding-left: 1rem" -->
+ <!-- /> -->
+ <a href="https://github.com/skiletro/Simple2FA">Simple2FA</a> - Written as
+ part of my undergraduate studies, Simple2FA, as the name suggests, is a very
+ basic two-factor authentication app. It has support for manual entry, as
+ well as scanning QR codes, to import TOTP keys.
+ </li>
+ <li>
+ <!-- <img -->
+ <!-- src="https://placehold.co/120x90" -->
+ <!-- align="left" -->
+ <!-- style="padding-right: 1rem" -->
+ <!-- /> -->
+ <a href="https://www.behance.net/skiletro#">Graphics design work</a> - While
+ I haven't updated my portfolio in a while, I've done quite a lot of work in
+ the graphics design space, creating logos and whatnot. I intend to move this
+ portfolio to this website sometime in the future, but for now all my work
+ happily lives on Behance.
+ </li>
+ <li>
+ ...and more! I honestly can't think of everything off the top of my head,
+ and I'm always doing more stuff, so check here often!
+ </li>
+</ul>
+
+<h2>Programming Languages and Other Skills</h2>
+<ul>
+ <li>C#</li>
+ <li>Java</li>
+ <li>Nix</li>
+ <li>HTML</li>
+ <li>CSS/SCSS</li>
+ <li>Figma</li>
+</ul>
+
+<h2>Contact Me</h2>
+<p>
+ Feel free to contact me on
+ <a href="https://matrix.to/#/@jvmi:matrix.org">matrix</a>, or through social
+ media. I don't bite!
+</p>
+
+<hr />
+
+<h2>Posts</h2>
+$partial("templates/post-list.html")$
+
+<p>…or you can find more in the <a href="/archive">archives</a>.</p>
diff --git a/src/pages/playlists.html b/src/pages/playlists.html
new file mode 100644
index 0000000..8437667
--- /dev/null
+++ b/src/pages/playlists.html
@@ -0,0 +1,57 @@
+<h1>Playlists</h1>
+
+<h2>Consider Yourself Drunk</h2>
+<a
+ class="playlist"
+ href="https://open.spotify.com/playlist/7iIEBEu2fy3EO3N6NqO1aY"
+>
+ <img
+ src="https://i.scdn.co/image/ab67706c0000bebbcd4fc31e9428d0fd768b5192"
+ height="8.5em"
+ />
+ A chill DnB-ish Playlist
+</a>
+
+<h2>Lofi Refined</h2>
+<a
+ class="playlist"
+ href="https://open.spotify.com/playlist/4mMjbHWBUIkM7xvXNkumM6"
+>
+ <img
+ src="https://i.scdn.co/image/ab67706c0000bebbac86dba0d9d11f29d279e91c"
+ height="8.5em"
+ />
+ A smaller set of lofi songs, more carefully picked
+</a>
+
+<h2>Chilled Out</h2>
+<a
+ class="playlist"
+ href="https://open.spotify.com/playlist/53G9wAEwl7c4ulPH2VsKNx"
+>
+ <img
+ src="https://i.scdn.co/image/ab67706c0000bebb37d20f6170a2c883bd4e839f"
+ height="8.5em"
+ />
+ Mix of chiller DnB and stuff like that
+</a>
+
+<h2>Pills</h2>
+<a
+ class="playlist"
+ href="https://open.spotify.com/playlist/7qKp0piqkOPEpRwGTN6ckO"
+>
+ <img
+ src="https://image-cdn-fa.spotifycdn.com/image/ab67706c0000d72c8bfa12b132704e6fb5acad07"
+ height="8.5em"
+ />
+ DnB, Jump-up, all that good stuff
+</a>
+
+<h2>More Playlists</h2>
+<p>
+ More playlists can be found on my
+ <a href="https://open.spotify.com/user/skiletro">Spotify profile</a>! I try
+ and add new songs to my playlists as much as I can, and I'm always creating
+ new playlists too!
+</p>
diff --git a/src/posts/2025-06-20-vr-plus-nixos-plus-nvidia.md b/src/posts/2025-06-20-vr-plus-nixos-plus-nvidia.md
new file mode 100644
index 0000000..7270865
--- /dev/null
+++ b/src/posts/2025-06-20-vr-plus-nixos-plus-nvidia.md
@@ -0,0 +1,130 @@
+---
+title: VR + NixOS + Nvidia
+---
+
+## ⚠️ Note
+
+This post is quite outdated now.
+The 'prerequisites' section is still quite accurate, as you still need the proprietary drivers, however setting WiVRn
+up is significantly easier. I recommend looking at the [Linux VR Adventures Wiki](https://lvra.gitlab.io/docs/distros/nixos/)
+for a much better guide.
+
+## Introduction
+
+For the longest time, getting VR working nicely with Linux (and especially NixOS) was a monumental task.
+Nowadays however, it is easier than ever: only requiring a handful of lines of Nix!
+
+## Prerequisites
+
+In this blog post, I will be focusing on getting VR working with Steam games, using an Oculus Quest 2 headset.
+Ensure you have the proprietary Nvidia drivers installed, as this will most likely not work without them.
+You will also need Home Manager setup, as we will be utilising that to get Steam games working.
+
+```nix
+# Generic drivers, good to have
+hardware.graphics = {
+ enable = true;
+ enable32Bit = true;
+};
+
+# Nvidia specific
+hardware.nvidia = {
+ modesetting.enable = true;
+ open = true;
+};
+
+services.xserver.videoDrivers = ["nvidia"];
+```
+
+## Installing WiVRn
+
+As I am using a Quest 2, I am going to use an application called WiVRn, which will allow me to stream both wired _or_ wirelessly.
+If you are using a tethered headset such as a HTC Vive or Valve Index, I can recommend you look into [Monado](https://gitlab.freedesktop.org/monado/monado).
+WiVRn is actually based on Monado, so gertting it up and running should be fairly similar.
+All we need to get WiVRn installed is put the following in our configuration!
+
+```nix
+/* configuration.nix */
+services.wivrn = {
+ enable = true;
+ openFirewall = true; # Required for wireless streaming
+ defaultRuntime = true;
+};
+```
+
+Although we don't _necessarily_ need anything else now, installing some quality-of-life tools will definitely benefit us.
+
+```nix
+/* configuration.nix */
+environment.systemPackages = with pkgs; [
+ wlx-overlay-s # In-VR overlay
+ android-tools # Allows for wired WiVRn
+];
+```
+
+## Getting Steam games working
+
+If all we want to do is play OpenXR games, we're set!
+Most, if not all, steam games use OpenVR though, so we will need a compatibility layer: OpenComposite.
+We can tell Steam to use OpenComposite and WiVRn for games by writing a few configuration files.
+Because these files live in our home directory, we need to use Home Manager.
+In home.nix, or wherever you have your home configuration:
+
+```nix
+/* home.nix */
+xdg.configFile."openxr/1/active_runtime.json".source =
+ "${osConfig.services.wivrn.package}/share/openxr/1/openxr_wivrn.json";
+
+xdg.configFile."openvr/openvrpaths.vrpath".text = ''
+ {
+ "config" :
+ [
+ "${config.xdg.dataHome}/Steam/config"
+ ],
+ "external_drivers" : null,
+ "jsonid" : "vrpathreg",
+ "log" :
+ [
+ "${config.xdg.dataHome}/Steam/logs"
+ ],
+ "runtime" :
+ [
+ "${pkgs.opencomposite}/lib/opencomposite"
+ ],
+ "version" : 1
+ }
+'';
+```
+
+We are using `osConfig` in this case, as to use the same package we use when enabling WiVRn, meaning that if we changed `services.wivrn.package` in the future, it will use that package instead of the generic one from nixpkgs.
+
+Going back to our main configuration, we now need to tell the game to actually use these settings.
+
+We can do this by setting our game launch options to...
+
+```sh
+PRESSURE_VESSEL_FILESYSTEMS_RW=$XDG_RUNTIME_DIR/wivrn/comp_ipc %command%
+```
+
+...however, that isn't very "Nix", is it?
+To do this for _every_ game, we can override our steam package to include this environment variable.
+
+```nix
+/* configuration.nix */
+programs.steam.package = lib.mkDefault (
+ pkgs.steam.override (prev: {
+ extraEnv =
+ {
+ PRESSURE_VESSEL_FILESYSTEMS_RW = "$XDG_RUNTIME_DIR/wivrn/comp_ipc";
+ }
+ // (prev.extraEnv or {});
+ })
+);
+```
+
+Don't worry about your flatscreen games: they should just ignore this setting!
+
+## Done!
+
+We should now just be able to open the "WiVRn server" GUI application, and start gaming!
+You can read the [official WiVRn documentation](https://github.com/WiVRn/WiVRn?tab=readme-ov-file#running-1) for platform independent help on getting it up and running now, as the Nix specific stuff has now been sorted.
diff --git a/src/templates/archive.html b/src/templates/archive.html
new file mode 100644
index 0000000..346e978
--- /dev/null
+++ b/src/templates/archive.html
@@ -0,0 +1,3 @@
+Here you can find all my previous posts:
+<!-- prettier-ignore -->
+$partial("templates/post-list.html")$
diff --git a/src/templates/default.html b/src/templates/default.html
new file mode 100644
index 0000000..58df794
--- /dev/null
+++ b/src/templates/default.html
@@ -0,0 +1,97 @@
+<!doctype html>
+<html lang="en">
+ <head>
+ <meta charset="UTF-8" />
+ <title>$title$ ~ Skiletro</title>
+ <meta name="viewport" content="width=device-width,initial-scale=1" />
+ <meta name="description" content="" />
+ <link rel="stylesheet" type="text/css" href="/assets/css/default.css" />
+ <link rel="icon" href="/assets/images/favicon.ico" />
+ <meta name="theme-color" content="#9141ac" />
+ <meta property="og:title" content="" />
+ <meta property="og:description" content="" />
+ <meta property="og:image" content="" />
+ <meta name="twitter:card" content="" />
+ <meta name="twitter:site" content="" />
+ <meta name="twitter:title" content="" />
+ <meta name="twitter:description" content="" />
+ <meta name="twitter:image" content="" />
+ </head>
+ <body>
+ <nav>
+ <a href="/"
+ ><svg class="logo" width="25" height="25" viewBox="0 0 980.4 1e3">
+ <path
+ d="M235.84 924.57a498 498 0 0061.81 32.76l-8.3-72.08z"
+ transform="translate(-9.8)"
+ ></path>
+ <path
+ d="M297.65 957.34a498 498 0 0065.1 23.58l-15.94-80z"
+ transform="translate(-9.8)"
+ ></path>
+ <path
+ d="M106.47 808.4l33.65-81C87.2 708.58 52.2 688 30.46 672.18A498.84 498.84.0 00106.47 808.4z"
+ transform="translate(-9.8)"
+ ></path>
+ <path
+ d="M362.76 980.92a498.66 498.66.0 0070.37 14.63L407.74 919.2z"
+ transform="translate(-9.8)"
+ ></path>
+ <path
+ d="M433.14 995.55A505 505 0 005e2 1e3l-33.06-76.45z"
+ transform="translate(-9.8)"
+ ></path>
+ <path
+ d="M164.33 735.49h0l23.17 71.42 28.1-57.41 32 57.41 32.54-44.58 37.1 56.76 30-47.88 19.61 51.36L405 775.87l25.42 49.32 38.3-46.87L5e2 830.41l31.32-52.09 38.3 46.87L595 775.87l38.13 46.7 19.61-51.36 30 47.88 37.1-56.76 32.54 44.58 32-57.41 28.09 57.41 23.17-71.42h0C759.29 759.35 650.92 778.6 5e2 778.6s-259.29-19.25-335.67-43.11z"
+ transform="translate(-9.8)"
+ ></path>
+ <path
+ d="M702.35 957.33a498 498 0 0061.81-32.76l-53.51-39.32z"
+ transform="translate(-9.8)"
+ ></path>
+ <path
+ d="M637.25 980.92a498 498 0 0065.1-23.58l-49.16-56.42z"
+ transform="translate(-9.8)"
+ ></path>
+ <path
+ d="M893.53 808.4a498.84 498.84.0 0076-136.22C947.8 688 912.8 708.58 859.88 727.41z"
+ transform="translate(-9.8)"
+ ></path>
+ <path
+ d="M566.87 995.55a498.66 498.66.0 0070.37-14.63l-45-61.72z"
+ transform="translate(-9.8)"
+ ></path>
+ <path
+ d="M5e2 1e3a505 505 0 0066.86-4.45l-33.8-72z"
+ transform="translate(-9.8)"
+ ></path>
+ <path
+ d="M526.1 376.88c25.15-186.25 147.42-287.57 199.81-323a500.87 500.87.0 00-451.82.0c52.39 35.47 174.66 136.79 199.81 323C506.11 615.39 290 737.32 9.8 598.89q4.09 20.4 9.83 40.16C64.44 675.61 195.83 753.8 5e2 753.8s435.56-78.19 480.37-114.75q5.71-19.75 9.83-40.16C710 737.32 493.89 615.39 526.1 376.88z"
+ transform="translate(-9.8)"
+ ></path></svg
+ ></a>
+ <hr />
+ <a href="/">Home</a>
+ <a href="/archive">Archive</a>
+ <a href="/pages/playlists">Playlists</a>
+ <hr />
+ <img
+ src="/assets/images/nonbinary-flag.svg"
+ width="20rem"
+ height="20rem"
+ />
+ </nav>
+ <main>$body$</main>
+ <footer>
+ <p>Branding © 2016-2025 Skiletro, All Rights Reserved</p>
+ <p>
+ Made with ❤ in Haskell and
+ <a href="https://jaspervdj.be/hakyll/">Hakyll</a>
+ - Site built with commit
+ <a href="https://github.com/skiletro/website/commit/$revision$"
+ >$revision$</a
+ >
+ </p>
+ </footer>
+ </body>
+</html>
diff --git a/src/templates/post-list.html b/src/templates/post-list.html
new file mode 100644
index 0000000..a614f13
--- /dev/null
+++ b/src/templates/post-list.html
@@ -0,0 +1,5 @@
+<ul>
+ $for(posts)$
+ <li><a href="$url$">$title$</a> - $hdate$</li>
+ $endfor$
+</ul>
diff --git a/src/templates/post.html b/src/templates/post.html
new file mode 100644
index 0000000..27f17da
--- /dev/null
+++ b/src/templates/post.html
@@ -0,0 +1,7 @@
+<h1>$title$</h1>
+<address class="author">
+ Posted on
+ <time pubdate datetime="$cdate$" title="$hdate$">$hdate$</time>
+</address>
+<!-- prettier-ignore -->
+$body$