diff --git a/.gitignore b/.gitignore
index c335c2c..370651e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
 /target
 target
 guests.json
+Cargo.lock
diff --git a/.woodpecker.yaml b/.woodpecker.yaml
index 483aa44..c1c95a5 100644
--- a/.woodpecker.yaml
+++ b/.woodpecker.yaml
@@ -1,17 +1,18 @@
 when:
-  branch: ['main']
+  branch: ["main"]
   event: ["push", "manual"]
 steps:
   - name: build
     image: woodpeckerci/plugin-docker-buildx
-    secrets: [ gitpat ]
     settings:
-      repo: git.iwakura.rip/hex/iwakura-web
+      repo: git.iwakura.rip/hex/iwakuweb
       platforms: linux/amd64
       dockerfile: Dockerfile
-      tags: ["${CI_COMMIT_BRANCH}-latest","${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA}"]
+      tags:
+        ["${CI_COMMIT_BRANCH}-latest", "${CI_COMMIT_BRANCH}-${CI_COMMIT_SHA}"]
       username: hex
-      registry: git.iwakura.rip
+      registry:
+        git.iwakura.rip
         #insecure: true
       password:
         from_secret: gitpat
diff --git a/Cargo.lock b/Cargo.lock
index bca63c1..001bd2d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -139,9 +139,9 @@ dependencies = [
 
 [[package]]
 name = "bstr"
-version = "1.9.1"
+version = "1.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706"
+checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c"
 dependencies = [
  "memchr",
  "serde",
@@ -155,21 +155,27 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
 
 [[package]]
 name = "bytemuck"
-version = "1.16.1"
+version = "1.16.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e"
+checksum = "102087e286b4677862ea56cf8fc58bb2cdfa8725c40ffb80fe3a008eb7f2fc83"
+
+[[package]]
+name = "byteorder"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
 
 [[package]]
 name = "bytes"
-version = "1.6.0"
+version = "1.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
+checksum = "fca2be1d5c43812bae364ee3f30b3afcb7877cf59f4aeb94c66f313a41d2fac9"
 
 [[package]]
 name = "cc"
-version = "1.1.0"
+version = "1.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eaff6f8ce506b9773fa786672d63fc7a191ffea1be33f72bbd4aeacefca9ffc8"
+checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc"
 
 [[package]]
 name = "cfg-if"
@@ -704,9 +710,9 @@ dependencies = [
 
 [[package]]
 name = "indexmap"
-version = "2.2.6"
+version = "2.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
+checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0"
 dependencies = [
  "equivalent",
  "hashbrown",
@@ -900,6 +906,18 @@ dependencies = [
  "windows-sys 0.48.0",
 ]
 
+[[package]]
+name = "mio"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "wasi",
+ "windows-sys 0.52.0",
+]
+
 [[package]]
 name = "multer"
 version = "3.1.0"
@@ -942,7 +960,7 @@ dependencies = [
  "kqueue",
  "libc",
  "log",
- "mio",
+ "mio 0.8.11",
  "walkdir",
  "windows-sys 0.48.0",
 ]
@@ -984,9 +1002,9 @@ dependencies = [
 
 [[package]]
 name = "object"
-version = "0.36.1"
+version = "0.36.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce"
+checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e"
 dependencies = [
  "memchr",
 ]
@@ -1021,7 +1039,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
 dependencies = [
  "cfg-if",
  "libc",
- "redox_syscall 0.5.2",
+ "redox_syscall 0.5.3",
  "smallvec",
  "windows-targets 0.52.6",
 ]
@@ -1167,9 +1185,12 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
 
 [[package]]
 name = "ppv-lite86"
-version = "0.2.17"
+version = "0.2.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
+checksum = "dee4364d9f3b902ef14fab8a1ddffb783a1cb6b4bba3bfc1fa3922732c7de97f"
+dependencies = [
+ "zerocopy",
+]
 
 [[package]]
 name = "proc-macro2"
@@ -1243,9 +1264,9 @@ dependencies = [
 
 [[package]]
 name = "redox_syscall"
-version = "0.5.2"
+version = "0.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd"
+checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4"
 dependencies = [
  "bitflags 2.6.0",
 ]
@@ -1483,20 +1504,21 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.120"
+version = "1.0.121"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5"
+checksum = "4ab380d7d9f22ef3f21ad3e6c1ebe8e4fc7a2000ccba2e4d71fc96f15b2cb609"
 dependencies = [
  "itoa",
+ "memchr",
  "ryu",
  "serde",
 ]
 
 [[package]]
 name = "serde_spanned"
-version = "0.6.6"
+version = "0.6.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0"
+checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d"
 dependencies = [
  "serde",
 ]
@@ -1606,9 +1628,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.70"
+version = "2.0.72"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f0209b68b3613b093e0ec905354eccaedcfe83b8cb37cbdeae64026c3064c16"
+checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1651,18 +1673,18 @@ dependencies = [
 
 [[package]]
 name = "thiserror"
-version = "1.0.61"
+version = "1.0.63"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
+checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.61"
+version = "1.0.63"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
+checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1712,27 +1734,26 @@ dependencies = [
 
 [[package]]
 name = "tokio"
-version = "1.38.0"
+version = "1.39.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a"
+checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1"
 dependencies = [
  "backtrace",
  "bytes",
  "libc",
- "mio",
- "num_cpus",
+ "mio 1.0.1",
  "pin-project-lite",
  "signal-hook-registry",
  "socket2",
  "tokio-macros",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
 name = "tokio-macros"
-version = "2.3.0"
+version = "2.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a"
+checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1765,9 +1786,9 @@ dependencies = [
 
 [[package]]
 name = "toml"
-version = "0.8.14"
+version = "0.8.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335"
+checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
 dependencies = [
  "serde",
  "serde_spanned",
@@ -1777,18 +1798,18 @@ dependencies = [
 
 [[package]]
 name = "toml_datetime"
-version = "0.6.6"
+version = "0.6.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf"
+checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "toml_edit"
-version = "0.22.15"
+version = "0.22.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d59a3a72298453f564e2b111fa896f8d07fabb36f51f06d7e875fc5e0b5a3ef1"
+checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d"
 dependencies = [
  "indexmap",
  "serde",
@@ -1971,9 +1992,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
 
 [[package]]
 name = "version_check"
-version = "0.9.4"
+version = "0.9.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
+checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
 
 [[package]]
 name = "walkdir"
@@ -2244,9 +2265,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
 
 [[package]]
 name = "winnow"
-version = "0.6.13"
+version = "0.6.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1"
+checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f"
 dependencies = [
  "memchr",
 ]
@@ -2259,3 +2280,24 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
 dependencies = [
  "is-terminal",
 ]
+
+[[package]]
+name = "zerocopy"
+version = "0.6.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "854e949ac82d619ee9a14c66a1b674ac730422372ccb759ce0c39cabcf2bf8e6"
+dependencies = [
+ "byteorder",
+ "zerocopy-derive",
+]
+
+[[package]]
+name = "zerocopy-derive"
+version = "0.6.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "125139de3f6b9d625c39e2efdd73d41bdac468ccd556556440e322be0e1bbd91"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
diff --git a/assets/css/global.css b/assets/css/global.css
new file mode 100644
index 0000000..2a792f8
--- /dev/null
+++ b/assets/css/global.css
@@ -0,0 +1,138 @@
+/* I know everything looks absolutely trash :3 */
+#top {
+    margin-top: 2vw;
+    margin-left: 15vw;
+    margin-right: 15vw;
+}
+@font-face {
+    font-family: "Hack Nerd Font";
+    src: url(/assets/ttf/HNF-Reg.ttf);
+}
+@font-face {
+    font-family: "Jetbrains Mono";
+    src: url(/assets/ttf/JBM.ttf);
+}
+.user-display {
+}
+.prefix {
+    display: inline;
+    margin-right: 5px;
+    font-size: 12px;
+}
+:root {
+    --text-color: #8941ad;
+    --term-color: #4af626;
+}
+body {
+    color: var(--term-color);
+    background-color: black;
+    font-family: "Jetbrains Mono";
+}
+#link-container a {
+    text-decoration: none;
+    color: black;
+}
+#link-container {
+    display: flex;
+    gap: 4vw;
+    background-color: var(--term-color);
+    justify-content: center;
+}
+hr {
+    margin-top: 1px;
+    color: var(--term-color);
+}
+
+#entries {
+    align-items: center;
+    gap: 10px;
+    margin-top: 10px;
+    display: flex;
+    flex-direction: column;
+}
+.guest-entry {
+    width: 100%;
+}
+bu {
+    font-weight: bold;
+    text-decoration: underline;
+}
+.entry-header {
+    display: flex;
+    justify-content: space-between;
+}
+.entry-body {
+    font-size: 14px;
+    overflow: auto;
+    word-wrap: break-word;
+}
+a {
+    text-decoration: none;
+    color: var(--term-color);
+}
+#post-container {
+    text-align: center;
+    padding: 5px;
+    margin: auto;
+    margin-top: 10px;
+    flex-direction: row;
+    flex-wrap: wrap;
+    justify-content: space-between;
+    flex: 0 0 auto;
+}
+input,
+textarea {
+    margin-left: 5vw;
+}
+.break {
+    flex-basis: 100%;
+    height: 0;
+}
+.link:hover {
+    background-color: var(--term-color);
+    color: black;
+}
+label {
+    text-align: left;
+    clear: both;
+    float: left;
+}
+
+:root {
+    --sin-padding: 5px;
+}
+#service-containers {
+    display: flex;
+    gap: 10px;
+    flex-wrap: wrap;
+    width: 100%;
+    justify-content: center;
+}
+.service-link {
+    color: var(--term-color);
+    vertical-align: middle;
+}
+.service-icon {
+    vertical-align: middle;
+}
+#content {
+    margin-top: 5px;
+}
+.service-title {
+    align-items: center;
+    gap: 5px;
+    display: flex;
+    margin: 0;
+    justify-content: center;
+}
+.service-container {
+    padding: var(--sin-padding);
+    padding-top: 0px;
+    flex-shrink: 0;
+    border: 1px solid var(--term-color);
+    flex-basis: 22%;
+}
+.service-container hr {
+    margin-left: calc(-1 * var(--sin-padding));
+    margin-right: calc(-1 * var(--sin-padding));
+}
diff --git a/assets/img/authelia.png b/assets/img/authelia.png
new file mode 100644
index 0000000..52c5aea
Binary files /dev/null and b/assets/img/authelia.png differ
diff --git a/assets/img/dn42.png b/assets/img/dn42.png
new file mode 100644
index 0000000..8f4d63b
Binary files /dev/null and b/assets/img/dn42.png differ
diff --git a/assets/img/jellyfin.png b/assets/img/jellyfin.png
new file mode 100644
index 0000000..ae08791
Binary files /dev/null and b/assets/img/jellyfin.png differ
diff --git a/assets/img/jellyseerr.ico b/assets/img/jellyseerr.ico
new file mode 100644
index 0000000..dbca29f
Binary files /dev/null and b/assets/img/jellyseerr.ico differ
diff --git a/assets/img/lain.png b/assets/img/lain.png
deleted file mode 100644
index 5c70f81..0000000
Binary files a/assets/img/lain.png and /dev/null differ
diff --git a/assets/img/mail.png b/assets/img/mail.png
new file mode 100644
index 0000000..7910223
Binary files /dev/null and b/assets/img/mail.png differ
diff --git a/assets/img/woodpecker.svg b/assets/img/woodpecker.svg
new file mode 100644
index 0000000..1cd49a8
--- /dev/null
+++ b/assets/img/woodpecker.svg
@@ -0,0 +1,10 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="284.538" height="253.96">
+  <style>
+    @media (prefers-color-scheme: dark) {
+      path {
+        fill: white;
+      }
+    }
+  </style>
+  <path d="M162.51 33.188c-26.77.411-54.004 6.885-71.494 3.745-1.313-.232-2.124 1.338-1.171 2.265 14.749 14.003 20.335 28.16 36.718 30.065l.476.103c-7.567 7.799-14.028 18.018-18.571 31.171-4.89 14.106-6.268 29.421-7.89 47.105-2.445 26.332-5.173 56.152-20.038 93.54a246.489 246.489 0 0 0-13.27 45.946h22.652a221.202 221.202 0 0 1 11.249-37.786c16.049-40.374 19.073-73.257 21.505-99.693 1.493-16.255 2.806-30.309 6.796-41.853 11.647-33.527 39.408-40.889 61.056-36.693 21.004 4.067 41.673 20.502 40.592 44.016-.772 15.985-7.76 23.166-12.87 28.43-2.793 2.883-5.47 5.611-6.731 9.498-3.037 9.19.101 19.434 8.494 27.568 22.24 20.734 34.338 59.717 33.681 106.513h22.176c.592-52.935-13.951-97.839-40.503-122.626-2.097-2.021-2.69-3.604-3.191-3.347 1.222-1.544 3.217-3.346 4.633-4.813 29.382-21.79 77.813-1.892 107.054 9.653 7.58 2.985 11.274-4.338 4.067-8.623-25.097-14.84-76.54-54.016-105.368-79.718-4.029-3.54-6.796-7.8-11.455-11.738-15.547-27.439-41.84-33.127-68.597-32.728Zm35.238 60.27a15.161 15.161 0 0 0-2.008.232 15.161 15.161 0 0 0-1.506 29.434 15.154 15.154 0 0 0 9.473-28.79 15.161 15.161 0 0 0-5.959-.876zm-44.286 147.17a2.033 2.033 0 0 0-1.133.374c-1.08.772-1.93 3.05-.772 5.701 5.38 12.394 9.1 25.445 12.536 40.413h22.484c-5.676-16.629-16.307-34.055-27.851-43.978-2.008-1.737-3.913-2.574-5.251-2.51z" style="stroke-width:12.8704" transform="translate(-67.27 -33.169)"/>
+</svg>
diff --git a/assets/pgp/andre.txt b/assets/pgp/andre.txt
new file mode 100644
index 0000000..801c67e
--- /dev/null
+++ b/assets/pgp/andre.txt
@@ -0,0 +1,13 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mDMEZs80XRYJKwYBBAHaRw8BAQdAFEbr22JHklXkyOgqDp/o/IgngPN6Sck3Mjih
+LLDjwTy0GEFuZHJlIDxvcGVucmNAcG9zdGVvLmRlPoiTBBMWCgA7FiEEIe1Ep7aw
+ZGGQHzkyFuz+3MRZea4FAmbR+S0CGwMFCwkIBwICIgIGFQoJCAsCBBYCAwECHgcC
+F4AACgkQFuz+3MRZea7GewD/cEexNFi6y0eZqiWduihvyrJjnD8mDKQ8W5+Nt23v
+60IA/2AdbuULXtJ2wsww/3VpIjN22AJdTTZQq9SEgLbhqfwLuDgEZs80XRIKKwYB
+BAGXVQEFAQEHQL53gX/5GbufLJYAcb+nAT59LCaPFXk5FgmoOZTxic49AwEIB4h4
+BBgWCgAgFiEEIe1Ep7awZGGQHzkyFuz+3MRZea4FAmbPNF0CGwwACgkQFuz+3MRZ
+ea754AEAkjXsfyVYCBBUHiBKF8m1aEtWx1xFwUlXXQ6AX0gBYHsBAM+okBmzAqQr
+1GhAgSqafxHs9a/aNdINQVp9APQiD5QK
+=+1X6
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/assets/pgp/hex.txt b/assets/pgp/hex.txt
new file mode 100644
index 0000000..6e0e0d3
--- /dev/null
+++ b/assets/pgp/hex.txt
@@ -0,0 +1,53 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+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
+5jeQGlf9A7iXF80g
+=1mQ+
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/assets/ttf/JBM.ttf b/assets/ttf/JBM.ttf
new file mode 100644
index 0000000..3fce55d
Binary files /dev/null and b/assets/ttf/JBM.ttf differ
diff --git a/resources/img/lain.png b/resources/img/lain.png
deleted file mode 100644
index 5c70f81..0000000
Binary files a/resources/img/lain.png and /dev/null differ
diff --git a/resources/ttf/HNF-Reg.ttf b/resources/ttf/HNF-Reg.ttf
deleted file mode 100644
index 124e362..0000000
Binary files a/resources/ttf/HNF-Reg.ttf and /dev/null differ
diff --git a/src/main.rs b/src/main.rs
index bc88407..3384941 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -3,27 +3,26 @@ mod logger;
 extern crate rocket;
 extern crate rocket_dyn_templates;
 
-use rocket::response::content::RawJson;
-use rocket::{get, post, launch, build, routes};
 use rocket::fs::FileServer;
-use rocket_dyn_templates::{Template, context};
-use rocket::serde::{Deserialize, Serialize, json::Json};
+use rocket::serde::{json::Json, Deserialize, Serialize};
+use rocket::{build, get, launch, post, routes};
+use rocket_dyn_templates::{context, Template};
 
 use chrono::Local;
 
 use std::borrow::Cow;
+use std::fs::read_to_string;
+use std::fs::File;
 use std::io::Write;
 use std::path::Path;
-use std::fs::File;
-use std::fs::read_to_string;
 
-use serde_json::{Value, json};
+use serde_json::{json, Value};
 
-use crate::logger::iwakulog::{LogLevel, log};
+use crate::logger::iwakulog::{log, LogLevel};
 
-const ASSETS_DIR:       &str = "./assets";
-const GUEST_MESSAGES:   &str = "./guests.json";
-const DATE_TIME_FORMAT: &str = "%Y-%m%d | %H:%M";
+const ASSETS_DIR: &str = "./assets";
+const GUEST_MESSAGES: &str = "./guests.json";
+const DATE_TIME_FORMAT: &str = "%Y-%m-%d | %H:%M";
 
 #[derive(Serialize, Deserialize)]
 #[serde(crate = "rocket::serde")]
@@ -32,7 +31,6 @@ struct GuestMessage<'r> {
     body: Cow<'r, str>,
 }
 
-
 fn check_file(path: &str) -> bool {
     Path::new(path).exists()
 }
@@ -46,22 +44,34 @@ fn read_guest_messages() -> Result<Value, Box<dyn std::error::Error>> {
 fn post_guest_message(name: &str, body: &str) {
     let mut guest_json = match read_guest_messages() {
         Ok(x) => x,
-        Err(x) => panic!("Error while reading guest messages: {x:?}")
+        Err(x) => panic!("Error while reading guest messages: {x:?}"),
     };
     let messages = guest_json["messages"]
         .as_array_mut()
         .expect("Object is not an array?");
-    let date = Local::now().format(DATE_TIME_FORMAT);
+    let date = Local::now();
     messages.push(json!({
         "name": name,
         "body": body,
-        "date": date.to_string(),
+        "date": date.timestamp(),
     }));
     let mut file = File::create(GUEST_MESSAGES).expect("Couldn't read msgs");
-    file.write_all(guest_json.to_string().as_bytes()).expect("wah");
+    file.write_all(guest_json.to_string().as_bytes())
+        .expect("wah");
 }
 
-
+#[get("/abuse")]
+fn abuse() -> Template {
+    Template::render("abuse", context! {})
+}
+#[get("/post")]
+fn post() -> Template {
+    Template::render("post", context! {})
+}
+#[get("/members")]
+fn members() -> Template {
+    Template::render("members", context! {})
+}
 
 #[get("/")]
 fn index() -> Template {
@@ -74,11 +84,16 @@ fn post_msg(input: Json<GuestMessage<'_>>) {
     return;
 }
 
+#[get("/services")]
+fn services() -> Template {
+    Template::render("services", context! {})
+}
+
 #[get("/guestbook")]
 fn guests() -> Template {
     let guest_json = match read_guest_messages() {
         Ok(x) => x,
-        Err(x) => panic!("Error while reading guest messages: {x:?}")
+        Err(x) => panic!("Error while reading guest messages: {x:?}"),
     };
     Template::render("guest", &guest_json)
 }
@@ -86,13 +101,23 @@ fn guests() -> Template {
 #[launch]
 fn rocket() -> _ {
     if !check_file(GUEST_MESSAGES) {
-        log(LogLevel::Warn, format!("Guest messages file ({}) has not been found. Creating a new one.", GUEST_MESSAGES).as_str());
+        log(
+            LogLevel::Warn,
+            format!(
+                "Guest messages file ({}) has not been found. Creating a new one.",
+                GUEST_MESSAGES
+            )
+            .as_str(),
+        );
         let mut file = File::create(GUEST_MESSAGES).expect("Failed to create file.");
-        file.write_all(b"{\"messages\":[]}").expect("Failed to write to file.");
+        file.write_all(b"{\"messages\":[]}")
+            .expect("Failed to write to file.");
     }
     build()
-        .mount("/", routes![index, guests, post_msg])
+        .mount(
+            "/",
+            routes![index, guests, post_msg, members, post, services, abuse],
+        )
         .mount("/assets", FileServer::from(ASSETS_DIR))
         .attach(Template::fairing())
 }
-
diff --git a/templates.old/guest.html.tera b/templates.old/guest.html.tera
new file mode 100644
index 0000000..5b1c20b
--- /dev/null
+++ b/templates.old/guest.html.tera
@@ -0,0 +1,159 @@
+<title>Guest Book</title>
+<div id="page-container">
+  <div id="header-container">
+    <h1 id="title"><a href="/">iwakura.rip</a></h1>
+    <p>Leave a nice message for others to read :)</p>
+    <p>Dates are in UTC+2/CEST.</p>
+    <a class="link" id="msg-post" onclick="show_message_poster()" style="margin-bottom: 10px;">&nbsp;[ post message ]&nbsp;</a>
+  </div>
+  <div id="entries-container">
+  {% for message in messages %}
+    <div class="guest-entry">
+      <div class="entry-header">
+        <bu class="entry-title">{{ message.name }}</bu>
+        <bu class="entry-date">{{ message.date | date(format="%Y-%m-%d | %H:%M", timezone="Europe/Amsterdam")}}</bu>
+      </div>
+      <div class="entry-body">
+        <p>{{ message.body }}</p>
+      </div>
+    </div>
+  {% endfor %}
+  </div>
+  <div id="post-container">
+      <bu id="name-label">name</bu>
+      <input type="text" id="name-box" name="name-box"><br>
+    <div class="break"></div>
+      <bu id="msg-label">message</bu>
+      <textarea id="msg-box"></textarea>
+    <div class="break"></div>
+    <a class="link" onclick="send_msg()">&nbsp;[ send ]&nbsp;</a>
+  </div>
+</div>
+<script>
+  let show_post_message = false;
+  let show_message_poster = () => {
+    if (!show_post_message) {
+      show_post_message = !show_post_message
+      document.getElementById("entries-container").style.display = "none";
+      document.getElementById("post-container").style.display = "flex";
+      document.getElementById("msg-post").innerText = " [ back ] ";
+      return
+    }
+    document.getElementById("msg-post").innerText = " [ post message ] "
+    show_post_message = !show_post_message
+    document.getElementById("entries-container").style.display = "flex";
+    document.getElementById("post-container").style.display = "none";
+  }
+  let send_msg = async () => {
+    fetch("/post_message", {
+      "method": "POST",
+      "body": JSON.stringify({
+        body: document.getElementById("msg-box").value,
+        name: document.getElementById("name-box").value
+      }),
+    }).then(x => {
+      window.location.reload()
+    })
+  }
+</script>
+<style>
+a {
+  text-decoration: none;
+}
+a:active {
+  text-decoration: none;
+}
+:root {
+  --term-color: #4AF626;
+  --title-gap: 0px;
+  --title-font: "Hack Nerd Font";
+}
+@font-face {
+  font-family: "Hack Nerd Font";
+  src: url(/assets/ttf/HNF-Reg.ttf);
+}
+#title {
+    background: url("/assets/img/lain.png");
+    background-position: -100px 1125px;
+    -webkit-background-clip: text;
+    -webkit-text-fill-color: transparent;
+    font-size: 35px;
+    font-weight: bold;
+    text-align: center;
+    margin-bottom: calc(var(--title-gap) + 10px);
+    margin-top: var(--title-gap);
+    font-family: var(--title-font);
+}
+#post-container {
+  width: 50%;
+  padding: 5px;
+  border: 1px solid var(--term-color);
+  display: none;
+  margin: auto;
+  margin-top: 10px;
+  flex-direction: row;
+  flex-wrap: wrap;
+  justify-content: space-between;
+  flex: 0 0 auto;
+}
+input {
+  margin-left: auto;
+  float: right;
+}
+.break {
+  flex-basis: 100%;
+  height: 0;
+}
+.link:hover {
+  background-color: var(--term-color);
+  color: black;
+}
+label {
+  text-align: left;
+  clear: both;
+  float: left;
+}
+.link {
+  cursor: default;
+  align-items: center;
+  margin-left: auto;
+  margin-right: auto;
+  text-align: center;
+  transition: 0.3s;
+}
+#header-container {
+  text-align: center;
+}
+#entries-container {
+  align-items: center;
+  gap: 10px;
+  margin-top: 10px;
+  display: flex;
+  flex-direction: column;
+}
+#page-container {
+  font-family: "Hack Nerd Font";
+  color: var(--term-color);
+}
+.guest-entry {
+  width: 50%;
+  padding: 5px;
+  border: 1px var(--term-color) solid;
+}
+.entry-header {
+  display: flex;
+  justify-content: space-between;
+}
+.entry-body {
+  font-size: 14px;
+  overflow: auto;
+  word-wrap: break-word;
+}
+bu {
+  font-weight: bold;
+  text-decoration: underline;
+}
+body {
+  background-color: black;
+}
+</style>
diff --git a/templates.old/index.html.tera b/templates.old/index.html.tera
new file mode 100644
index 0000000..2557739
--- /dev/null
+++ b/templates.old/index.html.tera
@@ -0,0 +1,159 @@
+<div id="main-content">
+  <div id="middle-box">
+    <p style="text-align: center;margin-bottom: 5px;font-size: 20px;">[ iwakura.rip ]</p>
+    <img id="main-img" style="display:block;margin-left:auto;margin-right:auto;" src="https://media1.tenor.com/m/OlHMWq46CtAAAAAC/serial-experiments-lain-lain.gif" width="332" height="235">
+    <div class="link-container" id="service-container">
+      <a id="anim-1" href="https://mail.iwakura.rip">&nbsp;[ mail ]&nbsp;</a>
+      <a id="anim-2" href="https://git.iwakura.rip">&nbsp;[ git ]&nbsp;</a>
+      <a id="anim-3" href="https://media.iwakura.rip">&nbsp;[ media ]&nbsp;</a>
+      <a id="anim-4" href="https://blog.iwakura.rip">&nbsp;[ blog ]&nbsp;</a>
+    </div>
+    <div class="link-container" id="main-container">
+      <a onclick="showContainer(aboutContainer)">&nbsp;[ about ]&nbsp;</a>
+      <a onclick="showContainer(serviceContainer)">&nbsp;[ services ]&nbsp;</a>
+      <a href="/guestbook">&nbsp;[ guestbook ]&nbsp;</a>
+      <a href="/pgp">&nbsp;[ pgp ]&nbsp;</a>
+    </div>
+    <div class="link-container" id="about-container">
+      <a onclick="showSect(aboutSect)">&nbsp;[ i ]&nbsp;</a>
+      <a onclick="showSect(explaSect)">&nbsp;[ ? ]&nbsp;</a>
+      <a onclick="showSect(disclSect)">&nbsp;[ ! ]&nbsp;</a>
+    </div>
+  </div>
+  <br>
+  <div id="about-box" class="fadeIn">
+    <div id="about-sect">
+      <bu>About</bu>
+      <p>iwakura.rip is a collection of servers hosting mostly-private services for hexlocation & friends.</p>
+      <p>The iwakura.rip website is also connected to dn42 (<a href="https://iwakura.dn42">iwakura.dn42</a>). We are planning to connect our services to dn42 too.</p>
+    </div>
+    <div id="expla-sect">
+      <bu>Explanation</bu>
+      <p>Most of the gifs/art/names/ui design is inspired by/based on <a href="https://en.wikipedia.org/wiki/Serial_Experiments_Lain"><b>Serial Experiments Lain</b></a>, an anime series about Lain <u>Iwakura</u></p>
+    </div>
+    <div id="discl-sect">
+      <bu>Disclaimer</bu>
+      <p>Serial Experiments Lain is the property of Triangle Studios. iwakura.rip is not affiliated with Triangle Studios.</p>
+    </div>
+  </div>
+</div>
+<style>
+@keyframes fadeIn {
+  to {
+    opacity: 1;
+  }
+}
+@keyframes fadeOut {
+  0% {
+    opacity: 1;
+  }
+  100% {
+    opacity: 0;
+  }
+}
+bu {
+  font-weight: bold;
+  text-decoration: underline;
+}
+#expla-sect, #discl-sect, #about-sect {
+  opacity:0;
+  display:none;
+}
+.fadeIn {
+  animation: fadeIn 0.5s forwards;
+}
+.fadeOut {
+  animation: fadeOut 0.5s forwards;
+}
+:root {
+  --term-color: #4AF626;
+}
+@font-face {
+  font-family: "Hack Nerd Font";
+  src: url(/assets/ttf/HNF-Reg.ttf);
+}
+a:hover {
+  color: black !important;
+  background-color: var(--term-color);
+}
+body {
+  background-color: black;
+}
+#main-container {
+  animation-delay: 0.2s;
+}
+a {
+  text-decoration: none;
+  transition: 0.3s;
+  cursor: default;
+}
+.link-container {
+  display: flex;
+  margin-top: 5px;
+  align-items: center;
+  justify-content: center;
+  transition: 0.5s;
+  opacity:0;
+}
+#service-container {
+  display: none;
+}
+#main-content, a {
+  font-family: "Hack Nerd Font";
+  color: var(--term-color);
+}
+#main-content {
+  /*font-family: "Hack Nerd Font";
+  color: var(--term-color);*/
+  position:absolute;
+  top: 40%;
+  left: 50%;
+  transform: translate(-50%, -50%);
+}
+</style>
+<script>
+  let getId = (i) => document.getElementById(i);
+
+  let serviceContainer = getId('service-container');
+  let mainContainer = getId('main-container');
+  let aboutContainer = getId('about-container');
+
+  let aboutSect = getId('about-sect');
+  let disclSect = getId('discl-sect');
+  let explaSect = getId('expla-sect');
+
+  let sections = [aboutSect, disclSect, explaSect];
+
+  mainContainer.classList.add("fadeIn");
+
+  let containers = [serviceContainer, mainContainer, aboutContainer];
+  function showContainer(container){
+    for (let _container of containers) {
+      //_container.style.display = "none";
+      if (_container == container) continue
+      _container.classList.remove("fadeIn");
+      _container.style.display = "none"
+    }
+    container.classList.add("fadeIn");
+    container.style.display = "flex";
+  }
+
+  let showSect = (s) => {
+    for (let _s of sections) {
+      console.log(_s)
+      if (_s == s) continue;
+      _s.style.display = "none";
+    }
+    s.style.display = "block";
+    s.classList.add("fadeIn");
+  }
+
+  let showAbout = () => document.getElementById('about-box').style.display = "block";
+  document.getElementById("main-img").onclick = () => {
+    showContainer(mainContainer)
+    for (let _s of sections) {
+      _s.style.display="none";
+      _s.classList.remove("fadeIn");
+    }
+  }
+</script>
diff --git a/templates.old/verify.html.tera b/templates.old/verify.html.tera
new file mode 100644
index 0000000..449f689
--- /dev/null
+++ b/templates.old/verify.html.tera
@@ -0,0 +1,35 @@
+<head>
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+</head>
+<body>
+  <div id="main-content">
+    <p id="title">Make sure to verify our PGP keys when communicating with us.</p>
+    <a href="/assets/pgp/hex.txt" style="text-decoration: none">hex</a>
+    <a href="/assets/pgp/andre.txt" style="text-decoration: none">andre</a>
+    <p>Please encrypt any messages containing important details towards using our PGP keys. Thank you.</p>
+  </div>
+</body>
+<style>
+:root {
+  --term-color: #4AF626;
+}
+#title {
+  font-weight: bold;
+}
+#main-content {
+  border: 1px var(--term-color) solid;
+  max-width: 50vw;
+  margin: auto;
+}
+@font-face {
+    font-family: "Hack Nerd Font";
+    src: url(/assets/ttf/HNF-Reg.ttf);
+}
+body {
+    text-align: center;
+    color: var(--term-color);
+    font-family: "Hack Nerd Font";
+    background-color: black;
+}
+</style>
+<!-- I'm on your side... -->
diff --git a/templates/abuse.html.tera b/templates/abuse.html.tera
new file mode 100644
index 0000000..bef5c49
--- /dev/null
+++ b/templates/abuse.html.tera
@@ -0,0 +1,21 @@
+{% extends "base" %}
+{% block title %}report abuse{% endblock title %}
+{% block content %}
+We ask that you report any abuse you find to: abuse@iwakura.rip.<br>
+Please make sure your e-mail contains the following:
+<ol>
+  <li>Type of abuse</li>
+  <li>Evidence (no screenshots, <b>hard evidence only</b>)</li>
+  <li>Origin of abuse (e-mail address, IP, domain etc)</li>
+  <li>Additional information that might help us.</li>
+</ol>
+
+Please consider the following when sending an abuse e-mail.
+<ol>
+  <li>We are *not* able to provide any personal identifiable information, as we do not store them.</li>
+  <li>We take abuse notifications very serious. Sending us multiple false abuse reports will result in a permanent block from our mailserver.</li>
+  <li>We try to respond within 48 hours. Do not flood our inboxes.</li>
+  <li>Please be respectful at all times.</li>
+</ol>
+
+{% endblock content %}
diff --git a/templates/base.html.tera b/templates/base.html.tera
new file mode 100644
index 0000000..35aa331
--- /dev/null
+++ b/templates/base.html.tera
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <title>{% block title %}{% endblock title %} - iwakura.rip</title>
+    <link rel="stylesheet" href="/assets/css/global.css">
+</head>
+<body>
+    <div id="top">
+      <h1 style="font-size: 50px;text-align:center;margin:0;">iwakura.rip</h1><br>
+
+      <div id="link-container">
+        <a href="/">home</a>
+        <a href="/services">services</a>
+        <a href="/guestbook">guestbook</a>
+        <a href="/members">members</a>
+        <a href="/abuse">report abuse</a>
+      </div>
+      <div id="content">{% block content %}{% endblock content %}</div>
+    </div>
+</body>
+</html>
diff --git a/templates/guest.html.tera b/templates/guest.html.tera
index c650655..2014939 100644
--- a/templates/guest.html.tera
+++ b/templates/guest.html.tera
@@ -1,155 +1,20 @@
-<div id="page-container">
-  <div id="header-container">
-    <h1 id="title"><a href="/">iwakura.rip</a></h1>
-    <a class="link" id="msg-post" onclick="show_message_poster()" style="margin-bottom: 10px;">&nbsp;[ post message ]&nbsp;</a>
-  </div>
-  <div id="entries-container">
+{% extends "base" %}
+{% block title %}guestbook{% endblock title %}
+{% block content %}
+<p style="text-align:center;"><a href="/post">post a message?</a></p>
+<hr>
+<div id="entries">
   {% for message in messages %}
     <div class="guest-entry">
       <div class="entry-header">
         <bu class="entry-title">{{ message.name }}</bu>
-        <bu class="entry-date">{{ message.date }}</bu>
+        <bu class="entry-date">{{ message.date | date(format="%Y-%m-%d | %H:%M", timezone="Europe/Amsterdam")}}</bu>
       </div>
       <div class="entry-body">
         <p>{{ message.body }}</p>
       </div>
+      <hr>
     </div>
   {% endfor %}
-  </div>
-  <div id="post-container">
-      <bu id="name-label">name</bu>
-      <input type="text" id="name-box" name="name-box"><br>
-    <div class="break"></div>
-      <bu id="msg-label">message</bu>
-      <textarea id="msg-box"></textarea>
-    <div class="break"></div>
-    <a class="link" onclick="send_msg()">&nbsp;[ send ]&nbsp;</a>
-  </div>
 </div>
-<script>
-  let show_post_message = false;
-  let show_message_poster = () => {
-    if (!show_post_message) {
-      show_post_message = !show_post_message
-      document.getElementById("entries-container").style.display = "none";
-      document.getElementById("post-container").style.display = "flex";
-      document.getElementById("msg-post").innerText = " [ back ] ";
-      return
-    }
-    document.getElementById("msg-post").innerText = " [ post message ] "
-    show_post_message = !show_post_message
-    document.getElementById("entries-container").style.display = "flex";
-    document.getElementById("post-container").style.display = "none";
-  }
-  let send_msg = async () => {
-    fetch("/post_message", {
-      "method": "POST",
-      "body": JSON.stringify({
-        body: document.getElementById("msg-box").value,
-        name: document.getElementById("name-box").value
-      }),
-    }).then(x => {
-      window.location.reload()
-    })
-  }
-</script>
-<style>
-a {
-  text-decoration: none;
-}
-a:active {
-  text-decoration: none;
-}
-:root {
-  --term-color: #4AF626;
-  --title-gap: 0px;
-}
-@font-face {
-  font-family: "Hack Nerd Font";
-  src: url(/assets/ttf/HNF-Reg.ttf);
-}
-#title {
-    background: url("/assets/img/lain.png");
-    background-position: -100px 1125px;
-    -webkit-background-clip: text;
-    -webkit-text-fill-color: transparent;
-    font-size: 35px;
-    font-weight: bold;
-    text-align: center;
-    margin-bottom: calc(var(--title-gap) + 10px);
-    margin-top: var(--title-gap);
-    font-family: var(--title-font);
-}
-#post-container {
-  width: 50%;
-  padding: 5px;
-  border: 1px solid var(--term-color);
-  display: none;
-  margin: auto;
-  margin-top: 10px;
-  flex-direction: row;
-  flex-wrap: wrap;
-  justify-content: space-between;
-  flex: 0 0 auto;
-}
-input {
-  margin-left: auto;
-  float: right;
-}
-.break { 
-  flex-basis: 100%;
-  height: 0;
-}
-.link:hover {
-  background-color: var(--term-color);
-  color: black;
-}
-label {
-  text-align: left;
-  clear: both;
-  float: left;
-}
-.link {
-  cursor: default;
-  align-items: center;
-  margin-left: auto;
-  margin-right: auto;
-  text-align: center;
-  transition: 0.3s;
-}
-#header-container {
-  text-align: center;
-}
-#entries-container {
-  align-items: center;
-  gap: 10px;
-  margin-top: 10px;
-  display: flex;
-  flex-direction: column;
-}
-#page-container {
-  font-family: "Hack Nerd Font";
-  color: var(--term-color);
-}
-.guest-entry {
-  width: 50%;
-  padding: 5px;
-  border: 1px var(--term-color) solid;
-}
-.entry-header {
-  display: flex;
-  justify-content: space-between;
-}
-.entry-body {
-  font-size: 14px;
-  overflow: auto;
-  word-wrap: break-word;
-}
-bu {
-  font-weight: bold;
-  text-decoration: underline;
-}
-body {
-  background-color: black;
-}
-</style>
+{% endblock content %}
diff --git a/templates/index.html.tera b/templates/index.html.tera
index d3b773d..e07635b 100644
--- a/templates/index.html.tera
+++ b/templates/index.html.tera
@@ -1,157 +1,6 @@
-<div id="main-content">
-  <div id="middle-box">
-    <p style="text-align: center;margin-bottom: 5px;font-size: 20px;">[ iwakura.rip ]</p>
-    <img id="main-img" style="display:block;margin-left:auto;margin-right:auto;" src="https://media1.tenor.com/m/OlHMWq46CtAAAAAC/serial-experiments-lain-lain.gif" width="332" height="235">
-    <div class="link-container" id="service-container">
-      <a id="anim-1" href="https://mail.iwakura.rip">&nbsp;[ mail ]&nbsp;</a>
-      <a id="anim-2" href="https://git.iwakura.rip">&nbsp;[ git ]&nbsp;</a>
-      <a id="anim-3" href="https://media.iwakura.rip">&nbsp;[ media ]&nbsp;</a>
-      <a id="anim-4" href="https://blog.iwakura.rip">&nbsp;[ blog ]&nbsp;</a>
-    </div>
-    <div class="link-container" id="main-container">
-      <a onclick="showContainer(aboutContainer)">&nbsp;[ about ]&nbsp;</a>
-      <a onclick="showContainer(serviceContainer)">&nbsp;[ services ]&nbsp;</a>
-      <a href="/guestbook">&nbsp;[ guestbook ]&nbsp;</a>
-    </div>
-    <div class="link-container" id="about-container">
-      <a onclick="showSect(aboutSect)">&nbsp;[ i ]&nbsp;</a>
-      <a onclick="showSect(explaSect)">&nbsp;[ ? ]&nbsp;</a>
-      <a onclick="showSect(disclSect)">&nbsp;[ ! ]&nbsp;</a>
-    </div>
-  </div>
-  <br>
-  <div id="about-box" class="fadeIn">
-    <div id="about-sect">
-      <bu>About</bu>
-      <p>iwakura.rip is a collection of servers hosting mostly-private services for hexlocation & friends.</p>
-    </div>
-    <div id="expla-sect">
-      <bu>Explanation</bu>
-      <p>Most of the gifs/art/names/ui design is inspired by/based on <a href="https://en.wikipedia.org/wiki/Serial_Experiments_Lain"><b>Serial Experiments Lain</b></a>, an anime series about Lain <u>Iwakura</u></p>
-    </div>
-    <div id="discl-sect">
-      <bu>Disclaimer</bu>
-      <p>Serial Experiments Lain is the property of Triangle Studios. iwakura.rip is not affiliated with Triangle Studios.</p>
-    </div>
-  </div>
-</div>
-<style>
-@keyframes fadeIn {
-  to {
-    opacity: 1;
-  }
-}
-@keyframes fadeOut {
-  0% {
-    opacity: 1;
-  }
-  100% {
-    opacity: 0;
-  }
-}
-bu {
-  font-weight: bold;
-  text-decoration: underline;
-}
-#expla-sect, #discl-sect, #about-sect {
-  opacity:0;
-  display:none;
-}
-.fadeIn {
-  animation: fadeIn 0.5s forwards;
-}
-.fadeOut {
-  animation: fadeOut 0.5s forwards;
-}
-:root {
-  --term-color: #4AF626;
-}
-@font-face {
-  font-family: "Hack Nerd Font";
-  src: url(/assets/ttf/HNF-Reg.ttf);
-}
-a:hover {
-  color: black !important;
-  background-color: var(--term-color);
-}
-body {
-  background-color: black;
-}
-#main-container {
-  animation-delay: 0.2s;
-}
-a {
-  text-decoration: none;
-  transition: 0.3s;
-  cursor: default;
-}
-.link-container {
-  display: flex;
-  margin-top: 5px;
-  align-items: center;
-  justify-content: center;
-  transition: 0.5s;
-  opacity:0;
-}
-#service-container {
-  display: none;
-}
-#main-content, a {
-  font-family: "Hack Nerd Font";
-  color: var(--term-color);
-}
-#main-content {
-  /*font-family: "Hack Nerd Font";
-  color: var(--term-color);*/
-  position:absolute;
-  top: 40%;
-  left: 50%;
-  transform: translate(-50%, -50%);
-}
-</style>
-<script>
-  let getId = (i) => document.getElementById(i);
-
-  let serviceContainer = getId('service-container');
-  let mainContainer = getId('main-container');
-  let aboutContainer = getId('about-container');
-
-  let aboutSect = getId('about-sect');
-  let disclSect = getId('discl-sect');
-  let explaSect = getId('expla-sect');
-
-  let sections = [aboutSect, disclSect, explaSect];
-
-  mainContainer.classList.add("fadeIn");
-
-  let containers = [serviceContainer, mainContainer, aboutContainer];
-  function showContainer(container){
-    for (let _container of containers) {
-      //_container.style.display = "none";
-      if (_container == container) continue
-      _container.classList.remove("fadeIn");
-      _container.style.display = "none"
-    }
-    container.classList.add("fadeIn");
-    container.style.display = "flex";
-  }
-
-  let showSect = (s) => {
-    for (let _s of sections) {
-      console.log(_s)
-      if (_s == s) continue;
-      _s.style.display = "none";
-    }
-    s.style.display = "block";
-    s.classList.add("fadeIn");
-  }
-
-  let showAbout = () => document.getElementById('about-box').style.display = "block";
-  document.getElementById("main-img").onclick = () => {
-    showContainer(mainContainer)
-    for (let _s of sections) {
-      _s.style.display="none";
-      _s.classList.remove("fadeIn");
-    }
-  }
-</script>
+{% extends "base" %}
+{% block title %}homepage{% endblock title %}
+{% block content %}
+Welcome to iwakura.rip. We are a small group of technology nerds and geeks fascinated by computers and technology.<br>
+We host a bunch of services on this domain for usage by friends & co. 
+{% endblock content %}
diff --git a/templates/macros.html.tera b/templates/macros.html.tera
new file mode 100644
index 0000000..6655393
--- /dev/null
+++ b/templates/macros.html.tera
@@ -0,0 +1,20 @@
+{% macro service(title, description, href, img, h="16") %}
+<div class="service-container">
+    <p class="service-title">
+      <img class="service-icon" src="{{img}}" height="{{h}}" >
+      <a href="{{href}}" class="service-link">{{title}}</a>
+    </p>
+    <hr />
+    <p class="service-description">{{description}}</p>
+</div>
+{% endmacro service %}
+{% macro user_display(username, role=0) %}
+    {% if role == 0 %}
+        {% set_global prefix = "<p class='prefix' style='color:gray;'>member</p>" %}
+    {% elif role == 1 %}
+        {% set_global prefix = "<p class='prefix' style='color:pink;'>friend</p>" %}
+    {% elif role == 2 %}
+        {% set_global prefix = "<p class='prefix' style='color:red;'>admin</p>" %}
+    {% endif %}
+    <li class="user-display">{{prefix | safe}}<a href="/assets/pgp/{{username}}.txt">{{username}}</a></li>
+{% endmacro user_display %}
diff --git a/templates/members.html.tera b/templates/members.html.tera
new file mode 100644
index 0000000..9d0e056
--- /dev/null
+++ b/templates/members.html.tera
@@ -0,0 +1,12 @@
+{% import "macros" as macros %}
+{% extends "base" %}
+{% block title %}members{% endblock title %}
+{% block content %}
+These are currently members of iwakura.rip, participating in some form.
+<ul>
+    {{macros::user_display(username="hex", role=2)}}
+    {{macros::user_display(username="andre", role=1)}}
+    {{macros::user_display(username="grng", role=1)}}
+</ul>
+If communicating with any of our members, please encrypt your message against their pgp key, if they have one.
+{% endblock content %}
diff --git a/templates/post.html.tera b/templates/post.html.tera
new file mode 100644
index 0000000..4d3a743
--- /dev/null
+++ b/templates/post.html.tera
@@ -0,0 +1,26 @@
+{% extends "base" %}
+{% block title %}post a message{% endblock title %}
+{% block content %}
+  <div id="post-container">
+      <bu id="name-label">name</bu>
+      <input type="text" id="name-box" name="name-box"><br>
+    <div class="break"></div>
+      <bu id="msg-label">message</bu>
+      <textarea id="msg-box"></textarea>
+    <div class="break"></div>
+    <a class="link" onclick="send_msg()">send!</a>
+  </div>
+<script>
+  let send_msg = async () => {
+    fetch("/post_message", {
+      "method": "POST",
+      "body": JSON.stringify({
+        body: document.getElementById("msg-box").value,
+        name: document.getElementById("name-box").value
+      }),
+    }).then(x => {
+      window.location.reload()
+    })
+  }
+</script>
+{% endblock content %}
diff --git a/templates/services.html.tera b/templates/services.html.tera
new file mode 100644
index 0000000..0a5f476
--- /dev/null
+++ b/templates/services.html.tera
@@ -0,0 +1,18 @@
+{% import "macros" as macros %}
+{% extends "base" %}
+{% block title %}services{% endblock title %}
+{% block content %}
+<div id="service-containers">
+  {{macros::service(title="Forgejo", description="A place for everyone to host their source code!", href="https://git.iwakura.rip", img="https://www.marefa.org/w/images/thumb/0/05/Forgejo_logo.svg/640px-Forgejo_logo.svg.png")}}
+  {{macros::service(title="Jellyfin", description="For all your media consumption needs.", href="https://media.iwakura.rip", img="/assets/img/jellyfin.png")}}
+  {{macros::service(title="Woodpecker CI", description="Powerful CI/CD to use together with Forgejo.", href="https://ci.iwakura.rip", img="/assets/img/woodpecker.svg")}}
+  {{macros::service(title="Jellyseerr", description="Get information about your favorite movies and TV shows, all together in one place.", href="https://request.iwakura.rip", img="/assets/img/jellyseerr.ico")}}
+  {{macros::service(title="DN42", description="We are currently in the process of connecting all of our services to DN42 - an overlay network using internet technologies.", href="https://iwakura.dn42", img="/assets/img/dn42.png")}}
+  {{macros::service(title="Authelia", description="Open-source authentication & authorization platform.", href="https://a.iwakura.rip", img="/assets/img/authelia.png")}}
+  {{macros::service(title="E-mail", description="We are hosting our own e-mail servers on an off-shore hosting provider. Note: all emails are currently being stored in plain text. We recommend using PGP encryption.", href="https://mail.iwakura.rip", img="/assets/img/mail.png")}}
+  {{macros::service(title="Blog", description="Our blog where we post some stuff, sometimes :)", href="https://blog.iwakura.rip", img="")}}
+  {{macros::service(title="Enclosed", description="Enclosed is a minimalistic web application designed for sending private and secure notes.", href="https://bin.iwakura.rip", img="https://github.com/CorentinTh/enclosed/raw/main/.github/icon-light.png")}}
+</div><br>
+Other services can be added on request. We also try to provide space for members wanting to host their own services, though iwakura.rip is a hobby project made by a single guy in his basement, so stability is something to think about when asking for this.
+<p style="font-size: 10px">We do not own the copyright for any of the projects mentioned above. All copyright goes to their respective owners. We only host instances of them.</p>
+{% endblock content %}
diff --git a/views/guest.html b/views/guest.html
deleted file mode 100644
index 443ea34..0000000
--- a/views/guest.html
+++ /dev/null
@@ -1,69 +0,0 @@
-<div id="page-container">
-  <div id="header-container">
-    <h1 id="title">iwakura.rip</h1>
-  </div>
-  <div id="entries-container">
-    <div class="guest-entry">
-      <div class="entry-header">
-        <bu class="entry-title">hexlocation</bu>
-        <bu class="entry-date">12 Jun.</bu>
-      </div>
-      <div class="entry-body">
-        <p>Hello nerds!</p>
-      </div>
-    </div>
-  </div>
-</div>
-<style>
-:root {
-  --term-color: #4AF626;
-  --title-gap: 0px;
-}
-@font-face {
-  font-family: "Hack Nerd Font";
-  src: url(../resources/ttf/HNF-Reg.ttf);
-}
-#title {
-    background: url("../resources/img/lain.png");
-    background-position: -200px 1125px;
-    -webkit-background-clip: text;
-    -webkit-text-fill-color: transparent;
-    font-size: 35px;
-    font-weight: bold;
-    text-align: center;
-    margin-bottom: calc(var(--title-gap) + 10px);
-    margin-top: var(--title-gap);
-    font-family: var(--title-font);
-}
-#entries-container {
-  align-items: center;
-  gap: 10px;
-  display: flex;
-  flex-direction: column;
-}
-#page-container {
-  font-family: "Hack Nerd Font";
-  color: var(--term-color);
-}
-.guest-entry {
-  width: 50%;
-  padding: 5px;
-  border: 1px var(--term-color) solid;
-}
-.entry-header {
-  display: flex;
-  justify-content: space-between;
-}
-.entry-body {
-  font-size: 14px;
-  overflow: auto;
-  word-wrap: break-word;
-}
-bu {
-  font-weight: bold;
-  text-decoration: underline;
-}
-body {
-  background-color: black;
-}
-</style>