diff --git a/config.toml b/config.toml
index 4de919d..c48ed22 100644
--- a/config.toml
+++ b/config.toml
@@ -39,7 +39,12 @@ background_color = "rosepine"
logo_text = "CherryKitten"
copyright_html = """\
-
© {currentYear} - CherryKitten
Impressum
+ © 2023 - CherryKitten
+ Impressum
+
+ RSS
+
+ 🐱
"""
menu_items = [
@@ -53,3 +58,4 @@ menu_items = [
]
page_titles = "combined"
+post_view_navigation_prompt = "More posts!"
diff --git a/content/blog/rust_1_options_results.md b/content/blog/rust_1_options_results.md
new file mode 100644
index 0000000..29c1377
--- /dev/null
+++ b/content/blog/rust_1_options_results.md
@@ -0,0 +1,245 @@
++++
+title = "Learning Rust Part 1: A kitten's guide to Options and Results"
+date = 2023-02-25
+[taxonomies]
+tags=["Rust", "programming", "code", "learning"]
++++
+### To unwrap() or not to unwrap(), that is the question:
+
+So I've finally given in and started to learn Rust last month. It's a really cool programming language,
+with some interesting differences to what I've used before. (JavaScript and Python, mostly)
+
+There are some really pawesome guides out there, ["The Rust programming language"](https://doc.rust-lang.org/book/) is
+definitely a **must-read** in my opinion, and [Rustlings](https://github.com/rust-lang/rustlings) is nyamazing for
+anyone who likes to learn by actively working through interactive problems.
+
+After reading through a lot of those big thorough guides by experienced Rust developers, I've started working on
+my first actual Project. I approached the development of this project by just trying to get small parts of it
+working in any way I can manage, and then build upon this. In that process, I learned a lot of small subtilties that
+guides like the ones named above just can't really cover. This post is for sharing those things, those cool little
+tips to make your first Rust project just a little cleaner and more Rust-y. Originally I wanted to make this about a lot
+of different topics, but then I've realized that my notes already contain so many things about just one part of Rust:
+The Enums `Option` and `Result`. So this post will be about those, and hopefully will mark the start of a series on this blog.
+
+While reading through this, you might think that the things I'm mentioning are obvious. That's okay, and that's the point.
+Nothing is ever completely obvious to everyone, and this is for those like me, who often don't immediately recognize
+the "obvious". And, to be honest, I am writing this just as much for myself, writing all of that stuff down to aid me in my
+own ongoing learning process.
+
+So, let's start!
+
+
+
+Firstly, a very quick introduction. `Option` and `Result` are part of the Rust standard library. Quoting the official documentation
+is probably the easiest way to summarize their purpose:
+
+> Type `Option` represents an optional value: every Option is either `Some` and contains a value, or `None`, and does not. `Option` types are very common in Rust code, as they have a number of uses:
+>
+> * Initial values
+> * Return values for functions that are not defined over their entire input range (partial functions)
+> * Return value for otherwise reporting simple errors, where `None` is returned on error
+> * Optional struct fields
+> * Struct fields that can be loaned or “taken”
+> * Optional function arguments
+> * Nullable pointers
+> * Swapping things out of difficult situations
+
+and
+
+> `Result` is the type used for returning and propagating errors. It is an enum with the variants, `Ok(T)`, representing success and containing a value, and `Err(E)`, representing error and containing an error value.
+
+At first, it seems so easy to just add a quick `.unwrap()` after every `Option` or `Result`, but this comes with
+the disadvantage of your code [panicking](https://doc.rust-lang.org/std/macro.panic.html) if it fails to unwrap.
+Sometimes, this can be useful during development, to discover potential error cases you might not have thought about, but
+is usually not what you want to happen.
+
+So, what can you do instead?
+
+First of all, don't use `unwrap()` unless you are completely sure that the value will never panic. Sometimes that is the
+case, because an earlier part of your code already made sure that it is `Ok` or `Some`.
+
+In some cases, you actually want the program to panic. But even then, there is a slightly better way. You can use `expect("foo")`
+to add a message to the panic, so the user actually knows what went wrong. That message should be worded in a specific way,
+basically telling the user what you _expected_ to happen.
+
+```rust
+fn main() {
+ let x = Some("Hello, World");
+ // There is no actual "None" type/value in Rust,
+ // this "None" is more specifically Option::None
+ let y: Option = None;
+
+ let z = x.unwrap(); // We explicitly set this to Some, so we can safely unwrap it
+ let rip = y.expect("expected y to not be None");
+
+ println!("{}, {} will never print because it panics above", z, rip);
+}
+```
+
+There are also the non-panicking siblings of `unwrap()`, like `unwrap_or()`, `unwrap_or_else()` and `unwrap_or_default()`.
+
+```rust
+fn main() {
+ let a: Option = None;
+ let b: Option = None;
+ let c: Option = None;
+
+ // unwrap_or() lets you supply a specific value to use if the Option is None
+ let x = a.unwrap_or("Hello there".to_owned());
+
+ // unwrap_or_default() uses the types default value if the Option is None
+ let y = b.unwrap_or_default();
+
+ // unwrap_or_else() lets you specify a closure to run if the Option is None
+ let z = c.unwrap_or_else(|| if 1 + 1 == 2 { true} else { false });
+
+ assert_eq!(x, "Hello there".to_owned());
+ assert_eq!(y, 0);
+ assert_eq!(z, true);
+}
+```
+And then there is this really cool question-mark operator, which comes in very handy once you go multiple functions deep
+and keep having to work with more and more `Result`s and `Option`s. The way it works is that, if you have a `None` or an `Error`,
+it passes up the handling of this one level higher, by returning out of the function early with a `None` or `Error` value itself.
+
+Of course, since return types of functions have to be known at compile time, the question-mark operator only works inside
+functions that already return `Result` or `Option`.
+
+
+```rust
+fn main() {
+ let x = 5;
+ let y = 10;
+ let z = 20;
+
+ match do_something(x, y, z) {
+ Some(result) => println!("Happy noises, {}", result),
+ None => println!("Sad noises"),
+ }
+}
+
+fn do_something(x: i32, y: i32, z: i32) -> Option {
+ let first_result = do_something_more(x, y)?;
+ let second_result = do_something_more(first_result, z)?;
+
+ Some(second_result)
+}
+
+fn do_something_more(x: i32, y: i32) -> Option {
+ Some(x + y)
+}
+```
+
+The advantage of this is that you only have to handle your `None` case exactly once. You don't have to add pattern matching, or
+conditionals, or `unwrap()`s all over the place, just a cute little question mark that delegates the handling to some logic
+higher up.
+
+_"But sammy!"_ you say, _"the compiler keeps shouting at me when I use the question mark on Options when my function
+returns Result \`<-.\_.->´"_
+
+Don't worry my frien! Even this has been considered!
+
+First of all, why does the compiler get upset? It's because the question-mark operator returns the same type that it's used on,
+and `Result` and `Option` are different types. Because of that, I thought I'd have to manually handle `None` cases in all
+of my `Result`-returning functions. Until one day, I was reading through some documentation (I know, I know, I'm a nerd who reads
+through documentation for fun and not just to find specific things) and discovered [Option::Ok_or()](https://doc.rust-lang.org/std/option/enum.Option.html#method.ok_or).
+
+> Transforms the `Option` into a `Result`, mapping `Some(v)` to `Ok(v)` and `None` to `Err(err)`.
+
+This was a life-changer to me, and it was just hiding right there in plain sight. Now I can easily turn a `None` where there shouldn't
+be a `None` into an `Error` to pass up with my pawesome question-mark operator!
+
+```rust
+fn main() -> Result<(), String> {
+ let x = function_that_returns_option().ok_or("error message".to_owned())?;
+ // Instead of:
+ // let x = function_that_returns_option().unwrap();
+ // or any of the other ways to handle None
+
+ assert_eq!(x, ());
+ Ok(x)
+}
+
+fn function_that_returns_option() -> Option<()> {
+ return Some(());
+}
+```
+
+The last thing I want to mention is both an example specific to `Option`s, and a more general tip about how I discovered this one.
+There is this wonderful friend for all Rust developers, called Clippy. No, not the Paperclip from Microsoft Word, but
+[A collection of lints to catch common mistakes and improve your Rust code](https://doc.rust-lang.org/stable/clippy/).
+Clippy is automatically installed when you install Rust via `rustup`, and it runs a whole lot of checks against your code
+to tell you what you can improve.
+
+In my case, I had the following piece of code:
+
+```rust
+let insert = (
+ tracks::title.eq(match tag.title() {
+ Some(title) => Some(title.to_string()),
+ None => None,
+ }),
+ tracks::track_number.eq(match tag.track() {
+ Some(track) => Some(track as i32),
+ None => None,
+ }),
+ tracks::disc_number.eq(match tag.disk() {
+ Some(track) => Some(track as i32),
+ None => None,
+ }),
+ tracks::path.eq(match path.to_str() {
+ None => return Err(Error::msg("Could not get path")),
+ Some(path) => path.to_string(),
+ }),
+ tracks::year.eq(match tag.year() {
+ Some(year) => Some(year as i32),
+ None => None,
+ }),
+ tracks::album_id.eq(match album {
+ Some(album) => Some(album.id),
+ None => None,
+ }),
+ );
+```
+
+This code builds an insert statement for the database holding my music metadata, getting the values from the tags of a file.
+The tag fields are all `Option`s, since the tags might be empty. The databse entries are also all `Option`s, (at least on the Rust side,
+on the database they are just values marked as possibly being Null). So my intuitive idea to build this was to just go through all the entries,
+match the tag, put in `Some(value)` if there is a value, and `None`if there is none.
+
+It works, it's not wrong, but there is a cleaner and more readable way to do this. And clippy told me right away, I ran it
+from my IDE, and it told me:
+
+> Manual implementation of `Option::map`
+
+Huh, okay. Let's check the [documentation](https://doc.rust-lang.org/std/option/enum.Option.html#method.map)
+
+> Maps an `Option` to `Option` by applying a function to a contained value.
+
+So basically exactly what I did with those `match` statements!
+My IDE even had a button to just easily fix this automatically with one click:
+
+```rust
+let insert = (
+ tracks::title.eq(tag.title().map(|title| title.to_string())),
+ tracks::track_number.eq(tag.track().map(|track| track as i32)),
+ tracks::disc_number.eq(tag.disk().map(|track| track as i32)),
+ tracks::path.eq(match path.to_str() {
+ None => return Err(Error::msg("Could not get path")),
+ Some(path) => path.to_string(),
+ }),
+ tracks::year.eq(tag.year().map(|year| year as i32)),
+ tracks::album_id.eq(album.map(|album| album.id)),
+ );
+```
+
+Great, that looks a lot cleaner immediately!
+Note how one of the lines was not changed, that's because that one sets a DB value which is `NOT NULL`, thus if the original `Option` is
+a `None` it means something went wrong, and we should abort this insert and return with an Error.
+
+And with that, we're done with my first blogpost about Rust, with hopefully many more to come!
+As I said, I am still learning, and writing this is part of my learning process. That being said, if you find this interesting,
+learned something from it, etc., feel free to leave me some feedback! I'd love to hear what you think!
+And if I made mistakes, please also tell me. I'm always happy to learn more and to fix those mistakes so others can learn from them too.
+
+Thank you so much for reading 💜
diff --git a/content/index.md b/content/home.md
similarity index 95%
rename from content/index.md
rename to content/home.md
index 1ccd54e..d1a9cc1 100644
--- a/content/index.md
+++ b/content/home.md
@@ -1,5 +1,6 @@
+++
title = "Hello there!"
+template = "page.html"
+++
{{ image(src="/profile.jpeg", alt="Profile picture",
diff --git a/public/404.html b/public/404.html
index 1fd0f26..8b42c84 100644
--- a/public/404.html
+++ b/public/404.html
@@ -65,7 +65,12 @@