diff --git a/astro/astro-paper-main/.dockerignore b/.dockerignore
similarity index 100%
rename from astro/astro-paper-main/.dockerignore
rename to .dockerignore
diff --git a/.gitignore b/.gitignore
index 4b430ede..9a5d91f2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,32 @@
-_site
-.sass-cache
-.jekyll-cache
-.jekyll-metadata
-vendor
+# build output
+dist/
+.output/
-.DS_Store
\ No newline at end of file
+# dependencies
+node_modules/
+
+# logs
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+
+
+# environment variables
+.env
+.env.production
+
+# macOS-specific files
+.DS_Store
+
+# ignore .astro directory
+.astro
+
+# yarn
+.yarn/*
+!.yarn/patches
+!.yarn/plugins
+!.yarn/releases
+!.yarn/sdks
+!.yarn/versions
+.pnp.*
diff --git a/astro/astro-paper-main/.markdownlint.json b/.markdownlint.json
similarity index 100%
rename from astro/astro-paper-main/.markdownlint.json
rename to .markdownlint.json
diff --git a/astro/astro-paper-main/.prettierignore b/.prettierignore
similarity index 100%
rename from astro/astro-paper-main/.prettierignore
rename to .prettierignore
diff --git a/astro/astro-paper-main/.prettierrc b/.prettierrc
similarity index 100%
rename from astro/astro-paper-main/.prettierrc
rename to .prettierrc
diff --git a/404.html b/404.html
deleted file mode 100644
index 3a16ab53..00000000
--- a/404.html
+++ /dev/null
@@ -1,25 +0,0 @@
----
-permalink: /404.html
-layout: page
----
-
-
-
-
-
404
-
-
Page not found :(
-
The requested page could not be found.
-
diff --git a/astro/astro-paper-main/CHANGELOG.md b/CHANGELOG.md
similarity index 100%
rename from astro/astro-paper-main/CHANGELOG.md
rename to CHANGELOG.md
diff --git a/Gemfile b/Gemfile
deleted file mode 100644
index 51afb8cf..00000000
--- a/Gemfile
+++ /dev/null
@@ -1,36 +0,0 @@
-source "https://rubygems.org"
-# Hello! This is where you manage which Jekyll version is used to run.
-# When you want to use a different version, change it below, save the
-# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
-#
-# bundle exec jekyll serve
-#
-# This will help ensure the proper Jekyll version is running.
-# Happy Jekylling!
-gem "jekyll", "~> 4.3.3"
-# This is the default theme for new Jekyll sites. You may change this to anything you like.
-gem "minima", "~> 2.5"
-# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
-# uncomment the line below. To upgrade, run `bundle update github-pages`.
-# gem "github-pages", group: :jekyll_plugins
-# If you have any plugins, put them here!
-group :jekyll_plugins do
- gem "jekyll-feed", "~> 0.12"
- gem "jekyll-remote-theme"
- gem "jekyll-sitemap"
- gem 'jekyll-toc'
-end
-
-# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem
-# and associated library.
-platforms :mingw, :x64_mingw, :mswin, :jruby do
- gem "tzinfo", ">= 1", "< 3"
- gem "tzinfo-data"
-end
-
-# Performance-booster for watching directories on Windows
-gem "wdm", "~> 0.1.1", :platforms => [:mingw, :x64_mingw, :mswin]
-
-# Lock `http_parser.rb` gem to `v0.6.x` on JRuby builds since newer versions of the gem
-# do not have a Java counterpart.
-gem "http_parser.rb", "~> 0.6.0", :platforms => [:jruby]
diff --git a/Gemfile.lock b/Gemfile.lock
deleted file mode 100644
index 44990c5d..00000000
--- a/Gemfile.lock
+++ /dev/null
@@ -1,101 +0,0 @@
-GEM
- remote: https://rubygems.org/
- specs:
- addressable (2.8.6)
- public_suffix (>= 2.0.2, < 6.0)
- colorator (1.1.0)
- concurrent-ruby (1.2.3)
- em-websocket (0.5.3)
- eventmachine (>= 0.12.9)
- http_parser.rb (~> 0)
- eventmachine (1.2.7)
- ffi (1.16.3)
- forwardable-extended (2.6.0)
- google-protobuf (3.25.2-arm64-darwin)
- http_parser.rb (0.8.0)
- i18n (1.14.1)
- concurrent-ruby (~> 1.0)
- jekyll (4.3.3)
- addressable (~> 2.4)
- colorator (~> 1.0)
- em-websocket (~> 0.5)
- i18n (~> 1.0)
- jekyll-sass-converter (>= 2.0, < 4.0)
- jekyll-watch (~> 2.0)
- kramdown (~> 2.3, >= 2.3.1)
- kramdown-parser-gfm (~> 1.0)
- liquid (~> 4.0)
- mercenary (>= 0.3.6, < 0.5)
- pathutil (~> 0.9)
- rouge (>= 3.0, < 5.0)
- safe_yaml (~> 1.0)
- terminal-table (>= 1.8, < 4.0)
- webrick (~> 1.7)
- jekyll-feed (0.17.0)
- jekyll (>= 3.7, < 5.0)
- jekyll-remote-theme (0.4.3)
- addressable (~> 2.0)
- jekyll (>= 3.5, < 5.0)
- jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0)
- rubyzip (>= 1.3.0, < 3.0)
- jekyll-sass-converter (3.0.0)
- sass-embedded (~> 1.54)
- jekyll-seo-tag (2.8.0)
- jekyll (>= 3.8, < 5.0)
- jekyll-sitemap (1.4.0)
- jekyll (>= 3.7, < 5.0)
- jekyll-toc (0.19.0)
- jekyll (>= 3.9)
- nokogiri (~> 1.12)
- jekyll-watch (2.2.1)
- listen (~> 3.0)
- kramdown (2.4.0)
- rexml
- kramdown-parser-gfm (1.1.0)
- kramdown (~> 2.0)
- liquid (4.0.4)
- listen (3.8.0)
- rb-fsevent (~> 0.10, >= 0.10.3)
- rb-inotify (~> 0.9, >= 0.9.10)
- mercenary (0.4.0)
- minima (2.5.1)
- jekyll (>= 3.5, < 5.0)
- jekyll-feed (~> 0.9)
- jekyll-seo-tag (~> 2.1)
- nokogiri (1.16.7-arm64-darwin)
- racc (~> 1.4)
- pathutil (0.16.2)
- forwardable-extended (~> 2.6)
- public_suffix (5.0.4)
- racc (1.8.1)
- rb-fsevent (0.11.2)
- rb-inotify (0.10.1)
- ffi (~> 1.0)
- rexml (3.2.6)
- rouge (4.2.0)
- rubyzip (2.3.2)
- safe_yaml (1.0.5)
- sass-embedded (1.70.0-arm64-darwin)
- google-protobuf (~> 3.25)
- terminal-table (3.0.2)
- unicode-display_width (>= 1.1.1, < 3)
- unicode-display_width (2.5.0)
- webrick (1.8.1)
-
-PLATFORMS
- arm64-darwin-23
-
-DEPENDENCIES
- http_parser.rb (~> 0.6.0)
- jekyll (~> 4.3.3)
- jekyll-feed (~> 0.12)
- jekyll-remote-theme
- jekyll-sitemap
- jekyll-toc
- minima (~> 2.5)
- tzinfo (>= 1, < 3)
- tzinfo-data
- wdm (~> 0.1.1)
-
-BUNDLED WITH
- 2.3.26
diff --git a/astro/astro-paper-main/LICENSE b/LICENSE
similarity index 100%
rename from astro/astro-paper-main/LICENSE
rename to LICENSE
diff --git a/astro/astro-paper-main/README.md b/README.md
similarity index 100%
rename from astro/astro-paper-main/README.md
rename to README.md
diff --git a/_config.yml b/_config.yml
deleted file mode 100644
index 5960360e..00000000
--- a/_config.yml
+++ /dev/null
@@ -1,58 +0,0 @@
-# Welcome to Jekyll!
-#
-# For technical reasons, this file is *NOT* reloaded automatically when you use
-# 'bundle exec jekyll serve'. If you change this file, please restart the server process.
-#
-# Site settings
-# These are used to personalize your new site. If you look in the HTML files,
-# you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.
-# You can create any custom variable you would like, and they will be accessible
-# in the templates via {{ site.myvariable }}.
-
-title: Coding-Steve's Blog
-email: tyrinteractivestudios@gmail.com
-description: >- # this means to ignore newlines until "baseurl:"
- My first blog, the place where I plan on writing some things down.
- At the very least, it's an outlet for writing about tech and things
- I find interesting!
-
-include: ["_includes"]
-
-github_username: StevenPG
-linkedin_username: test
-
-# For now until I get a dedicated site up and running
-url: "https://stevenpg.com" # the base hostname & protocol for your site, e.g. http://example.com
-
-# Google Analytics
-google_analytics: G-2ZPXM6LPR3
-
-home_post_limit: 5
-
-# Build settings
-remote_theme: jekyll/minima
-#gravatar_hash: ## YOUR GRAVATAR HASH ##
-plugins:
- - jekyll-feed
- - jekyll-remote-theme
- - jekyll-sitemap
- - jekyll-toc
-
-# Used by simple links page
-social-links:
- LinkedIn: https://linkedin.com/in/abc123
- StackOverflow: https://stackoverflow.com/users/abc123
- GitHub: https://github.com/abc123
- Website: https://howoldaremycats.com
-
-social:
- name: Steve
- links:
- - https://linkedin.com/in/abc123
- - https://github.com/abc123
-
-collections:
- personal: # collection for personal blog posts
- output: true
-
-future: true
diff --git a/_includes/custom_footer.html b/_includes/custom_footer.html
deleted file mode 100644
index 009b4831..00000000
--- a/_includes/custom_footer.html
+++ /dev/null
@@ -1,35 +0,0 @@
-
\ No newline at end of file
diff --git a/_layouts/base.html b/_layouts/base.html
deleted file mode 100644
index 8ee5156c..00000000
--- a/_layouts/base.html
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-{%- include head.html -%}
-
-
-
-{%- include header.html -%}
-
-
-
- {{ content }}
-
-
-
-{%- include custom_footer.html -%}
-
-
-
-
\ No newline at end of file
diff --git a/_layouts/default.html b/_layouts/default.html
deleted file mode 100644
index 651398ce..00000000
--- a/_layouts/default.html
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-{%- include head.html -%}
-
-
-
-
- {%- include header.html -%}
-
-
-
-
- {{ content | toc }}
-
-
-
-
- {%- include custom_footer.html -%}
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/_layouts/home.html b/_layouts/home.html
deleted file mode 100644
index 605eb999..00000000
--- a/_layouts/home.html
+++ /dev/null
@@ -1,60 +0,0 @@
----
-layout: default
----
-
- {%- if page.title -%}
-
{{ page.title }}
- {%- endif -%}
-
- {{ content }}
-
- {%- if site.posts.size > 0 -%}
-
{{ page.list_title | default: "Latest Tech Posts" }}
-
- {%- assign post_limit = site.home_post_limit | default: 5 -%}
- {%- for post in site.posts limit:post_limit -%}
- -
- {%- assign date_format = site.minima.date_format | default: "%b %-d, %Y" -%}
- {{ post.date | date: date_format }}
-
- {%- if site.show_excerpts -%}
- {{ post.excerpt }}
- {%- endif -%}
-
- {%- endfor -%}
-
-
-
- {%- endif -%}
-
- {%- if site.personal.size > 0 -%}
- {%- assign personalPosts = site.personal | sort: date | reverse -%}
-
Latest Life Posts
-
- {%- assign post_limit = site.home_post_limit | default: 5 -%}
- {%- for post in personalPosts limit:post_limit -%}
- -
- {%- assign date_format = site.minima.date_format | default: "%b %-d, %Y" -%}
- {{ post.date | date: date_format }}
-
- {%- if site.show_excerpts -%}
- {{ post.excerpt }}
- {%- endif -%}
-
- {%- endfor -%}
-
- {%- endif -%}
-
-
-
-
-
\ No newline at end of file
diff --git a/_layouts/post.html b/_layouts/post.html
deleted file mode 100644
index 428b7e99..00000000
--- a/_layouts/post.html
+++ /dev/null
@@ -1,38 +0,0 @@
----
-layout: base
----
-
-
-
-
-
- {{ content }}
-
-
- {%- if site.disqus.shortname -%}
- {%- include disqus_comments.html -%}
- {%- endif -%}
-
-
-
\ No newline at end of file
diff --git a/_layouts/projects.html b/_layouts/projects.html
deleted file mode 100644
index 0c90ce5a..00000000
--- a/_layouts/projects.html
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-{%- include head.html -%}
-
-
-
-
-
-
-
- {%- include header.html -%}
-
-
-
-
- {{ content }}
-
-
-
-
-
-
-
- {%- include custom_footer.html -%}
-
-
-
-
\ No newline at end of file
diff --git a/_personal/2024-02-04-the-cat-door.markdown b/_personal/2024-02-04-the-cat-door.markdown
deleted file mode 100644
index 156eec4c..00000000
--- a/_personal/2024-02-04-the-cat-door.markdown
+++ /dev/null
@@ -1,64 +0,0 @@
----
-layout: post
-title: "Freedom of Travel for the Three Legged Cat"
-date: 2024-02-06 12:00:00 -0500
-categories:
- - story
- - personal
----
-
-## Eli, the three legged cat
-
-![Image of Eli]({{site.url}}{{site.baseurl}}/assets/jVNLPaR.jpg)
-
-My wife and I have a BUNCH of cats, but our oldest boy cat is 14
-and just survived a battle with a cancerous tumor in his leg.
-
-A month of late night vet visits and over a year of secondary chemotherapy
-and he is finally cancer free!
-
-Unfortunately, the result was a very agitated three legged cat.
-
-A few months later though, he's happy and energetic again. Sometimes
-I wonder if he ever remembers having four legs. He's adapted to it surprisingly well.
-
-![Picture of Three Legged Cat]({{site.url}}{{site.baseurl}}/assets/ILGJD3b.jpg)
-
-(Wilson is making an appearance in the image above)
-
-So ever since the rounds of chemo (where we had to leave Eli at a vet for hours at a time)
-he's become a lot more... needy.
-
-Unfortunately, as a software developer I spend most of my time every day locked in my office
-working or gaming. For the past few years, I get up every 10-30 minutes to let
-Eli into the room or out of the room. Sometimes it's so he can use the bathroom, sometimes it's so
-he can eat some food or drink water, and other times I think it's just to remind me
-that he controls me.
-
-So I started looking into getting a microchip reading cat door. The reviews for all of the reasonably priced
-doors were terrible... so we ended up getting this: [SureFlap Microchip Pet Door](https://www.amazon.com/dp/B009NH6NR0)
-
-No affiliate links here, odds are this blog will never earn a dime, but I don't mind advertising things that work!
-
-Speaking of dimes, this door costs MANY. But it's been working perfectly.
-
-It's taken Eli a few days to figure it out, but he now cries for a few moments to see if he can command me to
-open the door for him. If I don't respond, he pushes his little nose through the door (in or out) and jumps inside.
-
-I can tell he's proud of himself afterward, because he acts a lot more energetic than when I used to just let him in myself.
-
-The most important part about this door though, is that only the two or three cats that can be trusted (not to destroy everything)
-are registered via microchip to get into the office.
-
-I occasionally spot the other cats peeking in, jealous of the special portal that only allows in select creatures. It has to
-appear as magic to them, and I know some of them have attempted to open the door, only to find it locked and unable to be opened.
-
-![Image of Cat peeking through cat door]({{site.url}}{{site.baseurl}}/assets/EZb9cQ7.jpg)
-
-Thankfully, our objective has been complete. Eli has total freedom to enter and exit the office all day long. It always
-impresses me how technology can be creatively used for functional purposes outside of the originally intended purpose.
-
-What's meant to be a life-saving measure to get an animal back home when they escape (or are let out to roam) can be used
-in an automated way to enable functionality.
-
-It's like my cat has an office badge, and it's crazy convenient!
diff --git a/_posts/2024-02-04-my-first-post.markdown b/_posts/2024-02-04-my-first-post.markdown
deleted file mode 100644
index 21d0d079..00000000
--- a/_posts/2024-02-04-my-first-post.markdown
+++ /dev/null
@@ -1,61 +0,0 @@
----
-layout: post
-title: "My First Post, on My First Blog"
-date: 2024-02-04 12:00:00 -0500
-categories:
- - story
- - tech
----
-
-## The Hook
-
-What do I write on my first post under the "Tech Posts" section of this blog? It's gotta be something
-tech related... And the only thing on my mind is this blog made with Jekyll. So I'll write a little
-bit about my setup and Jekyll!
-
-## How these pages were built
-
-Shout-out to [Chad Baldwin][chadbaldwin.net], who's blog I came across when I started searching on how to
-get this Jekyll thing up off the ground. He created a really cool bootstrapping github template that I
-planned on using, but I like to understand tools by messing with them myself.
-
-His site was the inspiration for this one!
-
-So I jumped over to [Jekyll's Install][jekyll-install] and got it installed on my Mac.
-
-Speaking of my local machine, I do nearly all of my work on a steeply discounted Apple M1 Pro I picked up
-right when the M2 Pro released.
-
-![Image of Directory]({{site.url}}{{site.baseurl}}/assets/LvdGYAG.jpg)
-
-In the spirit of open source, I've been cross referencing Chad's blog
-and the official Jekyll documentation.
-
-Once I got everything installed, I kicked off the process with `gem install jekyll` and
-got to creating!
-
-## Building the Blog
-
-As soon as I had jekyll installed, I ran `bundle exec jekyll serve`. This created
-a _site and .jekyll-cache and started serving my site locally.
-
-I quickly found myself in over my head at this point, and went through the step by step
-tutorial available [on jekyll's docs page](https://jekyllrb.com/docs/step-by-step/01-setup/)
-
-From there, I created a _layouts folder and set up the format
-I wanted by default (default.html), and for my home page (home.html).
-
-[The layout docs are right here](https://jekyllrb.com/docs/step-by-step/04-layouts/)
-
-![Image of Directory]({{site.url}}{{site.baseurl}}/assets/44wMq0Z.png)
-
-I followed the instructions in the Blogging section of the step-by-step and took some
-inspiration from Chad's repository, and separated my posts into personal and tech.
-
-As of this post, that's where I am now!
-
-I'll be updating the site, and everything (including all my commits and history) will be
-available [in the github repository that serves this site!](https://github.com/StevenPG/coding-steve)
-
-[chadbaldwin.net]: https://chadbaldwin.net
-[jekyll-install]: https://jekyllrb.com/docs/installation/macos/
diff --git a/_posts/2024-03-04-microservice-spring-boot-2-to-3-graalvm-native-image-conversion.markdown b/_posts/2024-03-04-microservice-spring-boot-2-to-3-graalvm-native-image-conversion.markdown
deleted file mode 100644
index 5d4859c4..00000000
--- a/_posts/2024-03-04-microservice-spring-boot-2-to-3-graalvm-native-image-conversion.markdown
+++ /dev/null
@@ -1,397 +0,0 @@
----
-layout: post
-title: "Converting Spring Boot 2 to Spring Boot 3 Native Image w/ GraalVM"
-toc: true
-date: 2024-03-04 12:00:00 -0500
-categories:
- - software
- - spring boot
- - graalvm
- - native-image
----
-
-# Migrating to Spring Boot 3 and Native Image
-
-2024 comes with it a sense of finality when it comes to the end-of-life status of Spring Boot 2
-and the embrace of Spring Boot 3 by the Spring community.
-
-Tutorials are being updated, Spring Initialzr no longer supports any Spring Boot 2 versions and
-dependencies are supporting Spring Boot 3 explicitly.
-
-At my current job, I've spent a good deal of time converting Spring Boot 2 applications to Spring Boot
-3, and with it a migration into utilizing Native Images using GraalVM. In my experience, the documentation
-around this transition is spotty and disjoint. I can't find a singular place where the basic changes
-needed to perform the upgrade are clearly listed out.
-
-So I intend to create that place, with a simple blog post that walks through converting an application with
-common pieces, all in one place.
-
-## The Latest Tools
-
-In support of upgrading, we should upgrade to the latest Java and Gradle versions. The same may apply to Maven but I'm
-only including Gradle in this post.
-
-For this post, we're going to be talking about the latest version of GraalVM so that we can take advantage of spring boot's
-native image support.
-
-If you're not familiar with GraalVM, it can be thought of as a different distribution of the Java Runtime Engine, and it can
-execute Java applications the same as any JRE. However, it also supports native image creation, which will be addressed
-in this page and the results we can expect from going native-image. This post won't go into the benefits or tradeoffs with
-native images, but focuses on creating them reliably.
-
-#### Windows
-
-GraalVM installation on windows can be done easily using the .msi file available on [Oracle's website](https://www.oracle.com/java/technologies/downloads/#jdk21-windows)
-
-#### MacOS + Linux
-
-Similar to installing normal Java installations, we can use [sdkman](https://sdkman.io/) to perform the install
-
-#### Gradle Upgrade
-
-Since we're focused on Gradle instead of Maven, we want to upgrade to the latest version of Gradle to try to guarantee
-compatibility.
-
-## Upgrading a Spring Boot 2 Application
-
-The assumptions in this post are that we're converting a Spring Boot application that uses
-Spring Data JPA, Spring Web MVC, Spring Actuator and a few more smaller dependencies.
-
-### Going Spring Boot 3
-
-We can look at our `build.gradle` file and update the following components:
-
- plugins {
- id 'java'
- id 'org.springframework.boot' version '3.2.2'
- id 'io.spring.dependency-management' version '1.1.4'
- }
-
- java {
- sourceCompatibility = '21'
- }
-
-That should be it! You may need to make updates to your IDE or environment to account
-for JDK21, but otherwise reloading the gradle project will get the ball rolling!
-
-### Gradle Plugin Updates
-
-To support native compilation, we're going to need to add a gradle plugin. Use your existing configuration (single or
-multi module) to add the following plugin:
-
-`id 'org.graalvm.buildtools.native' version '0.9.28'`
-
-Grab the latest version! This is the latest as of early 2024.
-
-Next we have 2 sections to configure, one will be explained later.
-
-The first is `bootBuildImage`. This may be different, but the instructions here will be
-in Gradle - Groovy.
-
-Add the following sections to your `build.gradle`
-
- bootJar {
- enabled = true
- }
-
- bootBuildImage {
- builder = "paketobuildpacks/builder-jammy-full:0.3.331"
- environment = [
- "BP_NATIVE_IMAGE": "true",
- "BP_JVM_VERSION": "21"
- ]
- }
-
- graalvmNative {
- testSupport = false
- metadataRepository {
- enabled = true
- }
-
- binaries {
- configureEach {
- resources.autodetect()
- }
- }
- }
-
-The `bootJar` section is for enabling our runnable jar that'll be used for building the native image.
-
-Second is the `bootBuildImage`. This is what we'll use to build runnable images that can be deployed.
-We include the configuration for native images and Java 21, but you can change these to the values needed
-for your project.
-
-Lastly, the `graalvmNative` section is where we'll add in our support for AoT tests and the metadata repository.
-
-The details around the metadata repository are included in the above Spring documentation, but suffice to say we'll want
-to enable the metadata repository in our project to avoid as many native issues as possible.
-
-These types of issues are explained in the documentation, with a deeper explanation available here:
-
-[GraalVM Native Image Documentation](https://www.graalvm.org/22.0/reference-manual/native-image/)
-
-### Javax to Jakarta
-
-We're starting with an interesting change that occurred in 2020 around Jakarta EE. If you haven't
-already run into this issue, many libraries post-2020 are using
-[Jakarta EE 9](https://jakarta.ee/blogs/javax-jakartaee-namespace-ecosystem-progress/), which changes the namespace
-from `javax` to `jakarta`. So when you update to the next version of spring boot from the last step,
-this may be the first build error you run into.
-
-For example, `import javax.persistence cannot be resolved`
-
-To resolve this issue, simply find-and-replace all `javax` imports and change them to `jakarta`, and that's it!
-
-If you are using old libraries that depend on javax, you should be able to locate the javax api dependencies and
-add them into the project. For example, some older dependencies may require `javax.servlet-api`.
-
-That dependency can be found here:
-
-[Maven Central: javax.servlet/javax.servlet-api](https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api)
-
-### Spring Security
-
-The sample Spring Security setup below is a common security configuration for
-a Spring Web MVC application.
-
- @Component
- public class SecurityConfig extends WebSecurityConfigurerAdapter
- {
- @Override
- protected void configure(HttpSecurity http) throws Exception {
- http.authorizeRequests(authorizeRequests -> authorizeRequests
- .mvcMatchers("/actuator/**").permitAll()
- .mvcMatchers("/api/**").authenticated()
- .anyRequest().denyAll()
- )
- .oauth2ResourceServer().jwt()
- .jwtAuthenticationConverter(converter());
- }
-
-This configuration changes greatly for Spring Boot 3.
-
-We transition from a `WebSecurityConfigurerAdapter` to a `SecurityFilterChain`. The reference
-[doc for the new security component is available here](https://docs.spring.io/spring-security/reference/servlet/architecture.html#servlet-securityfilterchain)
-
- @EnableWebSecurity
- @Configuration
- public class SecurityConfig
- {
- @Bean
- public SecurityFilterChain webFilterChain(HttpSecurity http) throws Exception {
- http.authorizeHttpRequests( authorize -> authorize
- .requestMatchers("/actuator/**").permitAll()
- .requestMatchers("/v1/**").authenticated()
- .anyRequest().denyAll()
- )
- .oauth2ResourceServer(oauth2 ->
- oauth2.jwt(
- jwt -> jwt.jwtAuthenticationConverter(converter())
- )
- );
- return http.build();
- }
-
-The tl;dr for this section, are the following three changes.
-
-The first is the copy-paste structural change. The second, is updating mvcMatchers to
-`requestMatchers`. The third is using the new format of passing a lambda into the method, see
-the converter() above across the two different examples.
-
-With that (and some nuanced changes that can be found in the official documentation); we've migrated
-the spring security configuration.
-
-At this point, we can take some time to review the documentation spring has made available
-to try to understand what's happening when we're creating these native images.
-
-Check out the documentation below. It doesn't attempt to go into detail like this guide does about individual changes,
-but it's invaluable to understand the information they've provided to be able to update our application
-to be a functional native image.
-
-https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#native-image
-
-### GraalVM and Building for the Tracing Agent
-
-Now for the most confusing but interesting part of this
-whole GraalVM process.
-
-It's mentioned in the documentation, but I hope here to summarize this complicated part of the native-image process.
-
-When you do a nativeCompile (for example), the GraalVM
-compilation process attempts to locate and mark down all
-of the places in the code things that aren't supported
-by native images are done. Things like reflection, dynamic property configuration, classloading, reading
-files off of the filesystem dynamically, etc.
-
-However, it's not perfect (far from it!), so we have to help out the process.
-
-The documentation on the tracing agent is available here:
-https://www.graalvm.org/latest/reference-manual/native-image/metadata/AutomaticMetadataCollection/
-
-There's a set of files that contain each a very specific chunk of data
-that together, informs the native-image what needs to be included in the compilation.
-
-These files are generated and then placed in the src/main/resources/META-INF/native-image folder.
-
-Trying to write these files by hand would be CRAZY difficult, so the tracing agent allows us to execute our application via the JVM, and the agent will write out the files for us.
-
-The methodology will be explained in the how-to-run section coming up!
-
-Until then, here are the files you can expect to generate (and sometimes manually update!)
-
-These files are (with examples!):
-
-1. jni-config.json
-
- Any JNI references the application needs to know about
-
- [{
- "name":"java.util.Arrays",
- "methods":[{"name":"asList","parameterTypes":["java.lang.Object[]"] }]
- }]
-
-2. predefined-classes-config.json
-
- Bytecode references to existing, predefined classes. (I've never seen this populated across the dozen applications I've migrated to native-image!)
-
- [{
- "type": "agent-extracted",
- "classes": [
- {
- "hash": "",
- "nameInfo": ""
- },
- "name": "",
- "customTargetConstructorClass": ""
- }
- ],
- "lambdaCapturingTypes": [
- {
- "condition": {
- "typeReachable": ""
- },
- "name": "",
- "customTargetConstructorClass": ""
- }
- ]
- }
-
-
-### Running the Tracing Agent
-
-The tracing agent is an agent-lib we're going to attach to our jar execution. It's going to generate the files from the previous section.
-
-The goal of the tracing agent, is to exercise the application. Each time a new reflection activity occurs, or a new file is loaded, the agent will populate the file.
-
-We have two options, specifying the directory to write these files to, or merging to an existing directory.
-
-The latter makes it easier to test your application holistically and with multiple passthroughs.
-
-We'll first build the application using `./gradlew clean build`
-
-The first option, is simply providing a folder to the agent:
-
- $JAVA_HOME/bin/java -agentlib:native-image-agent=config-merge-dir=/config -jar /build/libs/app.jar
-
-The merge option is
-
- $JAVA_HOME/bin/java -agentlib:native-image-agent=config-merge-dir=/config -jar /build/libs/app.jar
-
-### How to run our Native Image
-
-Now that we have our native-image metadata files that should help guarantee our application runs correctly, we can focus on the two initial ways to run out native-image.
-
-The first, manually compiling our executable and running it by hand.
-
-This is a simple process. First we run `./gradlew clean build nativeCompile`
-
-From there, you'll find a file called `app` in the ./build/native folder structure.
-
-You can run this simply using `./app`.
-
-Our second option, is a one-step process. We simply execute `./gradlew clean build nativeRun`
-
-This will nativeCompile and execute the application.
-
-### Building Docker Containers
-
-Our final (and most useful) native-image option is `bootBuildImage`.
-
-This command will perform a native compilation and embed the executable in a Docker image.
-
-This image can be run anywhere that supports Docker, making this command immensely powerful.
-
-There are plenty of configurations available with building this image as well; different base images, pre-named images, hard coded values like JVM_VERSION, etc.
-
-### Final Thoughts
-
-This is far from an all inclusive guide on GraalVM native-images using Spring Boot 3, but I hope anyone who stumbles across this page gains some value from it.
-
-I've filled this page will all of the things that slowed me down during my own journey to convert a handful of my company's applications into native-images.
\ No newline at end of file
diff --git a/_posts/2024-03-05-logging-request-body-with-spring-webclient.markdown b/_posts/2024-03-05-logging-request-body-with-spring-webclient.markdown
deleted file mode 100644
index 91445d24..00000000
--- a/_posts/2024-03-05-logging-request-body-with-spring-webclient.markdown
+++ /dev/null
@@ -1,68 +0,0 @@
----
-layout: post
-title: "Logging Request Body with Spring WebClient"
-date: 2024-03-05 12:00:00 -0500
-categories:
- - software
- - spring webflux
----
-
-## Previously!
-
-Logging should be one of the easiest thing a programming language or framework provides its developers. It's the first line of defense when trying to debug or keep track of what's going on in an application.
-
-In a [previous blog post on my dev.to account](https://dev.to/stevenpg/logging-with-spring-webclient-2j6o), I wrote up a simple document with a straightforward way of logging using Spring's WebClient.
-
-I was frustrated that I couldn't find any full examples, so (being the change I wanted to see in the world) I wrote it up myself!
-
-That's resulted in a very very small, but non-zero amount of traffic to that article.
-
-![Image of page view statistics, showing 22k visitors since 2020]({{site.url}}{{site.baseurl}}/assets/3GzdjxY.png)
-
-While that would normally be something I'm happy about, the methodology in my old article is outdated and poorly recommended.
-
-There is a better option than messing around with the WebClient's internal HttpClient, and it is called...
-
-## Logbook
-
-For years now, and especially since Spring Boot 3 arrived on the scene, there is a logging library that can handle just about everything and I use it in every Spring application. Big or small.
-
-I'm talking of course, about [Zalando - Logbook](https://github.com/zalando/logbook)
-
-Here's an example of what you get out of the box with Logbook, using ONLY the addition of the Logbook dependency. No special bean configurations needed!
-
-There's a [section in the README that explains how to add the starter](https://github.com/zalando/logbook?tab=readme-ov-file#spring-boot-starter), but I'll summarize and add a bit about the bom here:
-
-Using gradle, we can use the logbook-bom to align the versions of the logbook dependencies.
-
- // Logging
- implementation platform("org.zalando:logbook-bom:${logbookVersion}")
- implementation "org.zalando:logbook-spring-boot-starter"
- implementation "org.zalando:logbook-core"
- implementation "org.zalando:logbook-netty"
-
- With this simple setup, we get full Spring WebClient integration, with clean request and response logging on every invocation of WebClient.
-
- That's not all, there's a ton of modules the logbook supports dynamically. It's all laid out in the README!
-
- As long as you have the `logbook-spring-boot-starter`, you'll get a Logbook object for free by the spring autoconfiguration and there's no configuration necessary.
-
- In keeping with this short and sweet post, I'll include the configuration that ends up being added into every single application I've built or worked on.
-
- logbook:
- obfuscate:
- headers:
- - Authorization
- parameters:
- - none
- exclude:
- - /actuator/**
- format.style: json
-
- This formats the logs into JSON (easily consumable by any logging or monitoring tool that supports json logs) and changes the Authorization header into `XXX` in the logs.
-
- With this, it's trivial to get your spring boot application logging at a production-capable level.
-
-## Outro
-
-If you're coming from that previous page, I highly recommend simply using Logbook. If you're in an environment where dependencies are limited, the methods laid out in that post are still valid and functional. But in a production environment, Logbook is going to provide the best bang for your buck for setting up simple no-nonsense logging.
diff --git a/_posts/2024-04-14-graalvm-native-image-reflect-config-demystified.markdown b/_posts/2024-04-14-graalvm-native-image-reflect-config-demystified.markdown
deleted file mode 100644
index 85a923df..00000000
--- a/_posts/2024-04-14-graalvm-native-image-reflect-config-demystified.markdown
+++ /dev/null
@@ -1,234 +0,0 @@
----
-layout: post
-title: "GraalVM Native Image Reflect Config Demystified"
-toc: true
-date: 2024-04-13 12:00:00 -0500
-categories:
- - software
- - spring boot
- - graalvm
- - native-image
----
-
-One of the hardest things about compiling a Spring Boot application into a GraalVM native image is
-generating the necessary reflection, resource and proxy configurations needed for the native image runtime.
-
-These files, placed in the `src/main/resources/META-INF/native-image` will inform the runtime about all
-of the java magic that would be happening in a JVM environment, that isn't available in the native-image.
-
-When we do a nativeCompile, some native-image metadata is generated by the build process. But it can only see
-what information is available at build-time. The recommended way of generating the additional data that isn't
-available at build-time is by using the `tracing-agent`. It's [fairly documented here on the official GraalVM site](https://www.graalvm.org/latest/reference-manual/native-image/metadata/AutomaticMetadataCollection/)
-
-There is a major downside to this tracing-agent process; lets say we have a native-image application with a dozen
-api endpoints using spring-web-mvc. When a developer updates the application and adds a new endpoint, the metadata
-hasn't necessarily been updated to make the native-image runtime aware of the new reflection metadata. So while
-the application may compile and run correctly, the endpoint will fail at runtime. An example of this will be shown
-in this post.
-
-To complete the example, we would simply execute the application using the JVM and the tracing agent, and exercise
-the endpoint. This will inform the tracing agent of what needs to be added to the reflect-config.json and other files.
-
-The goal of this post is to explain exactly what the `reflect-config.json` file is doing and what information the
-tracing agent looks to write.
-
-## Test Project
-
-To accomplish this, we're going to create a new project and go through a typical workflow to build and update
-a native-image application.
-
-![Image of Spring Initializr]({{site.url}}{{site.baseurl}}/assets/f8eae9e1-d1b0-4ee0-a19a-56a6ea290af3.png)
-
-We can use Spring Initializr to generate our test project.
-
-Executing a native run will show the application successfully executing.
-
- $ ./gradlew nativeRun
- ...
- > Task :nativeRun
-
- . ____ _ __ _ _
- /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
- ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
- \\/ ___)| |_)| | | | | || (_| | ) ) ) )
- ' |____| .__|_| |_|_| |_\__, | / / / /
- =========|_|==============|___/=/_/_/_/
- :: Spring Boot :: (v3.2.4)
-
- ... INFO 12345 --- [demo] [ main] com.example.demo.DemoApplication : Starting AOT-processed DemoApplication using Java 21.0.2 with PID 12345
- ... INFO 12345 --- [demo] [ main] com.example.demo.DemoApplication : No active profile set, falling back to 1 default profile: "default"
- ... INFO 12345 --- [demo] [ main] com.example.demo.DemoApplication : Started DemoApplication in 0.023 seconds (process running for 0.053)
-
-We need to add some reflection to upset the native-image application. Rather than linking to a github
-repository, this example is short enough that we can just include it here:
-
-In the following example, we're gonna call the class automatically in a PostConstruct
-completely through reflection. At build time, the application has no idea what we're doing.
-
- @SpringBootApplication
- public class DemoApplication {
- public static void main(String[] args) {
- SpringApplication.run(DemoApplication.class, args);
- }
- @PostConstruct
- void test() throws ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchMethodException {
- Class> printerClass = Class.forName("com.example.demo.TestPrinter");
- // Class>.newInstance() is deprecated, so this example eventually won't work
- TestPrinter printer = (TestPrinter) printerClass.newInstance();
- Method printMethod = printerClass.getDeclaredMethod("print");
- printMethod.setAccessible(true);
- printMethod.invoke(printer);
- }
- }
- class TestPrinter {
- void print() {
- System.out.println("Hello World");
- }
- }
-
-Now that we have some reflection, we'll execute the same command and see what happens!
-
- $ ./gradlew nativeRun
- > Task :nativeRun FAILED
-
- . ____ _ __ _ _
- /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
- ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
- \\/ ___)| |_)| | | | | || (_| | ) ) ) )
- ' |____| .__|_| |_|_| |_\__, | / / / /
- =========|_|==============|___/=/_/_/_/
- :: Spring Boot :: (v3.2.4)
-
- ... INFO 12346 --- [demo] [ main] com.example.demo.DemoApplication : Starting AOT-processed DemoApplication using Java 21.0.2 with PID 12346
- ... INFO 12346 --- [demo] [ main] com.example.demo.DemoApplication : No active profile set, falling back to 1 default profile: "default"
- ... WARN 12346 --- [demo] [ main] o.s.c.support.GenericApplicationContext : Exception encountered during context initialization - cancelling refresh attempt:
- org.springframework.beans.factory.BeanCreationException:
- Error creating bean with name 'demoApplication': com.example.demo.TestPrinter
- ... ERROR 12346 --- [demo] [ main] o.s.boot.SpringApplication : Application run failed
-
-Reviewing what we know about native-image compilation, this makes perfect sense.
-
-Our specific error that was output in the stacktrace was
-
- Caused by: java.lang.NoSuchMethodException: com.example.demo.TestPrinter.()
-
-Lets first execute this application with the tracing agent and see if we can resolve our runtime issue by making
-the build aware of this reflection at build-time.
-
-## Tracing Agent Execution
-
-First, we're going to run a build with `./gradlew build` to create our jvm executable.
-
-Next, we'll execute our tracing agent execution from the jvm application. We don't need to explicitly run through
-any workflows so the tracing agent can see the JVM instantiations, since we do this in a post-construct.
-
-`java -agentlib:native-image-agent=config-merge-dir=./config -jar build/libs/demo-0.0.1-SNAPSHOT.jar`
-
-The output is what you'd expect from the jvm application version, namely "Hello World" was printed
-to the console via reflection.
-
-However, in our `./config` folder, we now have a handful of native-image metadata files.
-
-Now the tracing agent records everything it can, so even though we're looking for a single reflection
-configuration, we ended up with a 49Kb text file with a ton of internal spring reflection registrations. Many
-of these would be handled at build-time or through reachability metadata. Here's an example of the type
-of things the tracing agent picks up additionally:
-
- ...
- {
- "name":"org.springframework.context.annotation.ComponentScan",
- "queryAllDeclaredMethods":true
- },
- {
- "name":"org.springframework.context.annotation.ComponentScan$Filter",
- "queryAllDeclaredMethods":true
- },
- {
- "name":"org.springframework.context.annotation.Conditional",
- "queryAllDeclaredMethods":true
- },
- {
- "name":"org.springframework.context.annotation.Configuration",
- "queryAllDeclaredMethods":true
- },
- ...
-
-In most cases, just generating the metadata using the tracing agent is
-the simplest solution. However, for the sake of understanding what's happening,
-we're going to add the file by hand.
-
-First, we're going to create the location to inject these files into the build process;
-creating the `src/main/resources/META-INF/native-image` directory.
-
-Inside, we'll create the reflect-config.json file.
-
-![Directory Sample]({{site.url}}{{site.baseurl}}/assets/b40a4c04-5106-4a2e-9947-95eadcc59bb3.png)
-
-## Breaking Down Reflect-Config
-
-The official GraalVM documentation has examples of all of the available input types for each of the
-metadata files generated by the tracing agent and used by the native-image build process.
-
-When you need to figure out what to add, using that as a reference will describe the JSON.
-
-Now, lets get into creating this file. Because it is fairly abstract, we'll build the json as we go
-and update each piece, rather than display the final file with notes.
-
-It starts with an empty array of json objects:
-
- [{}]
-
-Inside, we need to let the build know our class and it's path
-
- [{
- "name":"com.example.demo.TestPrinter", // Our classname and path
- }]
-
-We reflectively create an instance of the object, so we need to let the build know
-that this class has a constructor.
-
- [{
- "name":"com.example.demo.TestPrinter", // Our classname and path
- "methods":[{
- "name":"", // representation of the constructor
- "parameterTypes":[] // no constructor parameters
- }]
- ]}
-
-Now finally, we need to make it aware of the `print` method.
-
- [{
- "name":"com.example.demo.TestPrinter", // Our classname and path
- "methods":[{
- "name":"", // representation of the constructor
- "parameterTypes":[] // no constructor parameters
- },{
- "name":"print", // the name of our defined method
- "parameterTypes":[] // no method parameters
- }]
- ]}
-
-With just the contents above, we can now rerun our native-image and see if that was
-enough to inform the build process about the required reflection to execute as we expect!
-
- ... INFO 96340 ... com.example.demo.DemoApplication : Starting AOT-processed DemoApplication using Java 21.0.2 with PID 12347
- ... INFO 96340 ... com.example.demo.DemoApplication : No active profile set, falling back to 1 default profile: "default"
- Hello World
- ... INFO 96340 ... com.example.demo.DemoApplication : Started DemoApplication in 0.025 seconds (process running for 0.052)
-
-Success!!
-
-With the native-image builder made aware of the only required reflection, our app runs perfectly.
-
-Comparing our java execution to our native-image execution shows the order of magnitude increase in startup time,
-one of the massive benefits of running as a native-image.
-
- Native: Started DemoApplication in 0.025 seconds (process running for 0.052)
- JVM: Started DemoApplication in 0.415 seconds (process running for 0.658)
-
-## Takeaways
-
-Sometimes when writing spring boot native-image applications, we'll have a complicated workflow
-that is hard or impossible to catch with the tracing-agent. In these instances, adding the reflection
-configuration by hand is a perfectly acceptable way to ensure the application will function correctly
-at runtime.
\ No newline at end of file
diff --git a/_posts/2024-06-05-partitioning-tables-with-postgres.markdown b/_posts/2024-06-05-partitioning-tables-with-postgres.markdown
deleted file mode 100644
index 8906c1cc..00000000
--- a/_posts/2024-06-05-partitioning-tables-with-postgres.markdown
+++ /dev/null
@@ -1,130 +0,0 @@
----
-layout: post
-title: "Partitioning Tables with Progress"
-toc: true
-date: 2024-06-05 12:00:00 -0500
-categories:
- - software
- - spring boot
- - postgres
----
-
-# Partitioning Databases in PostgreSQL
-
-I'm writing this post after doing some research into this topic and finding
-a ton of articles written about partitioning, but nobody ever has ALL of the information
-needed to recreate the example they're providing. This article DOES assume an understanding
-of Docker and basic usage of dockerized applications, specifically pgAdmin. (If you've never used
-it, it's pretty straightforward).
-
-So in this article, I want to provide everything needed to understand
-exactly how powerful this functionality is and how anyone can roll this into
-their project.
-
-First and foremost, what exactly is partitioning and why do we want to partition.
-
-Imagine we have a database that keeps track of cars that have driven
-over a certain highway. As time goes on, our database is going to get larger and larger.
-
-When we query our database for certain data, we may have to scan the entire table
-which will take longer and longer. The way to get around this is to cut down our
-table into smaller tables, thus; partitioning!
-
-For example, we can partition our database by time so that we can limit the
-size of our table. (It's not the best example, but it'll do!)
-
-## Setting up our database
-
-To get easy access to a database that we can use to test, we're going to run
-`docker-compose -d up` on the following file:
-
- version: '3.7'
- services:
- pgAdmin:
- platform: linux/amd64
- image: dpage/pgadmin4:latest
- ports: [ '9001:80' ]
- environment: [ PGADMIN_DEFAULT_EMAIL=postgres, PGADMIN_DEFAULT_PASSWORD=password ]
- restart: on-failure
- depends_on:
- - postgresql
- postgresql:
- platform: linux/amd64
- image: postgis/postgis:16-master
- ports: [ '5432:5432' ]
- environment: [ POSTGRES_PASSWORD=password, POSTGRES_DB=postgres ]
- restart: on-failure
- command:
- - "postgres"
- - "-c"
- - "log_statement=all"
-
-This config works on an M1 Pro Macbook, but it should work
-on most machines that can run Docker.
-
-## Configure Our Database
-
-We're going to use pgAdmin (or any other tool, but we included this one with Docker).
-
-Execute the following script to seed our database with data:
-
- create table traffic_data (
- id varchar(255),
- total_cars numeric,
- measure_date date
- ) partition by range (measure_date);
-
- create table traffic_data_jan_2024 partition of traffic_data for values from ('2024-01-01') to ('2024-02-01');
- create table traffic_data_feb_2024 partition of traffic_data for values from ('2024-02-01') to ('2024-03-01');
- create table traffic_data_mar_2024 partition of traffic_data for values from ('2024-03-01') to ('2024-04-01');
-
- insert into traffic_data (id, total_cars, measure_date) values
- ('1', 63, '2024-01-14'),
- ('2', 65, '2024-01-21'),
- ('3', 51, '2024-02-09'),
- ('4', 59, '2024-02-19'),
- ('5', 42, '2024-03-03'),
- ('6', 46, '2024-03-26');
-
-You should get a success message
-
- INSERT 0 6
- Query returned successfully in X msec.
-
-We can't see it easily yet, but our inserts seamlessly loaded into the created partitions.
-
-## What are our queries actually doing?
-
-Now that we have our database configured, we'll start reviewing some queries:
-
- explain select * from public.traffic_data
-
-![Full Table Scan]({{site.url}}{{site.baseurl}}/assets/a368fd78-2be5-412b-b744-265e20ef4aef.png)
-
-
-We can see that when we query the entire table, we do a sequential scan across the
-entire database. Now lets throw a `where` clause in and see what happens!
-
-Lets run the query `select * from public.traffic_data where measure_date < '2024-02-15'`
-
-![Query result]({{site.url}}{{site.baseurl}}/assets/7225cac2-0224-4f0a-ae86-8057a1629022.png)
-
-We see that we got the data we expected, but what happened in postgres?
-
-![2 Table Scan]({{site.url}}{{site.baseurl}}/assets/8aaaf23a-d737-4e9d-bcb4-61ddcc9e5a2a.png)
-
-We see that we did a sequential scan of the two tables that were relevant for us,
-but we never scanned our third table. If we were to query a more specific date, we know
-that we would only scan the relevant table!
-
-![Single Table Scan]({{site.url}}{{site.baseurl}}/assets/c972da73-155a-426a-b487-5ad73295c918.png)
-
-Pairing this with indexing allows us to really optimize our tables!
-
-## Takeaways
-
-The major takeaway, besides the ability to optimize our database queries, is that
-within our applications that use postgres, we can simply use the framework or library
-being used to add a `where` clause to a query and we automatically use the correct partition.
-In the same vein, we can easily insert into the root table and know that our data
-is going to be pushed into the correct partition.
\ No newline at end of file
diff --git a/_posts/2024-07-21-homelab-drives-and-buying-used.markdown b/_posts/2024-07-21-homelab-drives-and-buying-used.markdown
deleted file mode 100644
index 6bb4b164..00000000
--- a/_posts/2024-07-21-homelab-drives-and-buying-used.markdown
+++ /dev/null
@@ -1,63 +0,0 @@
----
-layout: post
-title: "Homelab Drives & Buying Used"
-date: 2024-07-21 12:00:00 -0500
-categories:
- - hardware
----
-
-# Homelab Drives & Buying Used
-
-Understanding the lifespan of your homelab's hard drives is crucial for maintaining data integrity and preventing unexpected downtime.
-
-This post will guide you through the process of checking your disk life and provide insights based on real-world examples from my homelab.
-
-### Understanding Your Disk's Health
-To assess your hard drive's health, you'll need two primary tools:
-
-lsblk: Displays block devices with their mount points, label, UUID, and size.
-smartctl: Retrieves S.M.A.R.T. data, which provides information about the drive's health, performance, and reliability.
-Basic Commands:
-
-{% highlight bash %}
-sudo lsblk -f
-sudo smartctl --all /dev/sda > output.txt
-{% endhighlight %}
-
-
-The first command lists your block devices, while the second saves the S.M.A.R.T. data of /dev/sda to a text file for analysis.
-
-### Case Study: My Used Homelab Drives
-
-I purchased a pair of used 2TB Seagate HDDs from ebay in a "lot" purchase.
-
-The first thing I did was check the S.M.A.R.T data and see how good the "deal" was.
-
-- Drive A: 125 power-on hours.
-- Drive B: 23081 power-on hours (approximately 63 days running).
-
-Based on the power-on hours, it's clear that the Seagate 2TB HDD with 23081 hours is approaching its expected lifespan.
-
-In this case, I got a decent deal on the drives and I have them set up in a RAID configuration. This should allow me to
-take advantage of the dual drive layout, but be well aware that Drive B is likely to fail and fallback to Drive A.
-
-### Interpreting S.M.A.R.T. Data
-
-While power-on hours provide a good basic estimate, a deeper analysis of S.M.A.R.T. data is crucial.
-
-We should look at the following attribute entries:
-
-- Power On Hours: High values mean the drive is closer to end of life (EOL)
-- Read/write errors: High values indicate potential issues.
-- Reallocated sectors: An increasing number suggests the drive is failing.
-
-Tools like smartctl make it easy to retrieve and help interpret this data.
-
-### Proactive Measures for used drives
-
-When buying used drives, it's good to act as though they could fail sooner than
-brand new store-bought drives.
-
-
-- Implement a reliable backup strategy to safeguard your data.
-- Use tools like smartctl or dedicated monitoring software.
diff --git a/_posts/2024-08-04-scs-record-recoverable-processor-error-handling.markdown b/_posts/2024-08-04-scs-record-recoverable-processor-error-handling.markdown
deleted file mode 100644
index 8be637a2..00000000
--- a/_posts/2024-08-04-scs-record-recoverable-processor-error-handling.markdown
+++ /dev/null
@@ -1,236 +0,0 @@
----
-layout: post
-title: "Spring Cloud Stream's RecordRecoverableProcessor for Workflow Error Handling"
-toc: true
-date: 2024-08-04 12:00:00 -0500
-categories:
-- software
-- spring boot
-- java
-- kafka
----
-
-# Brief
-
-The purpose of the post is to explain the RecordRecoverableProcessor which is a new addition
-to the Spring Cloud Streams library of functions available to the Kafka Streams collection of stream functions.
-
-If you'd like to view the notes here on the RecordRecoverableProcessor, you can simple scroll
-down to the "Solution" section, or check out the [Spring Cloud Stream Samples][scs-samples] under the `kafka-recoverable`
-sub-project.
-
-## Spring Cloud Streams
-
-[Spring Cloud Stream][spring-cloud-stream-documentation] is a framework for building rich event processing applications
-with minimal code and relatively straightforward configurations.
-
-In my professional career, I've used spring cloud streams extensively to create
-tons of messaging applications using the supported message processing softwares such as
-Kafka, RabbitMq, Solace, etc.
-
-There are a great deal of sample projects available in the [Spring Cloud Stream Samples][scs-samples] repository.
-
-Here's a quick snippet of how simple this framework makes the process of wiring up
-event driven applications to set the stage for why we would use this framework over others.
-
-##### Minimal Configuration
-
-{% highlight yaml %}
-spring:
- cloud:
- function:
- # Enable the bean by name
- definition: readAndPublish
- stream:
- bindings:
- # The configuration for the function IN binding
- readAndPublish-in-0:
- destination: my.in.topic
- # The configuration for the function OUT binding
- readAndPublish-out-0:
- destination: my.out.topic
-{% endhighlight %}
-
-##### Minimal Java Code
-
-{% highlight java %}
-
-@SpringBootApplication
-public class SpringCloudStreamExample {
-
- public static void main(String[] args) {
- SpringApplication.run(SpringCloudStreamExample.class, args);
- }
-
- /**
- * This stream we've defined simple checks if the incoming value is not equal to null.
- * If it isn't null, then it gets passed to the BeanName-out-0 configuration from our properties.
- *
- * The name of this bean is what gets mapped to the configuration, where "in-0" is the input configuration
- * and "out-0" is the output configuration for the function that we return here.
- **/
- @Bean
- public Function, KStream> readAndPublish() {
- return input -> input.filter(value -> value != null);
- }
-}
-{% endhighlight %}
-
-This minimal code example does a simple null check and passes the message from the in-0 configuration
-to the out-0 configuration. The framework comes with a TON of sensible default values, so a basic configuration is all
-that's needed to set up our simple example.
-
-However, my team noticed a relatively large gap when building incredibly
-complex pipelines using Spring Cloud Streams, specifically when working with
-Kafka Streams using the [Spring Cloud Stream Kafka Streams Binder][kafka-streams-binder-documentation]
-
-## Problem
-
-Before the introduction of RecordRecoverableProcessor, handling errors in Kafka Streams was a real headache. The framework primarily focused on [deserialization errors][deserialization-error-scs-ks], leaving developers to fend for themselves when it came to processing logic.
-
-To manage exceptions, we were forced to wrap every processing step in a try-catch block and manually handle errors. This was not only tedious but also error-prone. To make matters worse, Spring Cloud Streams' default behavior was to kill the consumer thread upon any exception, preventing message acknowledgments and leading to endless restart loops.
-
-A common workaround was to return Optional values from processing components and filter out errors. However, this approach introduced its own set of challenges, including type inference issues and a less-than-ideal developer experience.
-
-{% highlight java %}
-// Pseudocode
-@Bean
-public Function, KStream> readAndPublish() {
- return input -> input
- // This method has a complicated try-catch with logging and DLQ
- // and then ends in Optional.empty() if an error occurred
- .process(someMethod::returnsOptional)
- .filter(optional -> optional.isPresent())
- .process(someOtherMethod::returnsOptional2)
- .filter(optional -> optional.isPresent())
- .process(sometOtherOtherMethod::returnsOptional3)
- .filter(optional -> optional.isPresent())
-}
-{% endhighlight %}
-
-Implementing a Dead Letter Queue (DLQ) was also a manual nightmare. While the framework offered DLQ capabilities for deserialization errors, there was no out-of-the-box solution for processing errors.
-
-It wasn't until after raising [Issue #2779][spring-cloud-stream-issues-2779] with the Spring Cloud Streams team that the RecordRecoverableProcessor was introduced. This marked a significant improvement in the framework's error handling capabilities.
-(Special thanks to [Soby Chako][soby-chako])
-
-Attempting to implement a dead-letter-queue process (which is fully available via configuration during deserialization)
-was an extremely manual process too.
-
-## Solution
-
-The solution, the RecordRecoverableProcessor and the DltAwareProcessor.
-
-These two Processor components support supplying a function that is applied to the
-incoming data and the result pushed to the outgoing data sink. They also can receive an error handling
-function that gets applied to any exception thrown from inside the supplied function.
-
-The new section of the documentation for these capabilities is [available here][non-deserialization-error-scs-ks].
-
-There are two new components that can be used as KStream processor objects.
-
-Both operate on a similar concept.
-
-This is the main body of the [RecordRecoverableProcessor][rrp]:
-
-{% highlight java %}
-try {
- // The delegate function is the function passed into the processor
- Record downstreamRecord = this.delegateFunction.apply(record);
- this.context.forward(downstreamRecord);
-}
-catch (Exception exception) {
- // The processorRecordRecoverer is the error function supplied.
- if (this.processorRecordRecoverer == null) {
- this.processorRecordRecoverer = defaultProcessorRecordRecoverer();
- }
- this.processorRecordRecoverer.accept(record, exception);
-}
-{% endhighlight %}
-
-Both rely on the `this.context.forward` call to propagate the record downstream.
-
-If `forward` is not called on the message, it is simply consumed on the spot and does not continue
-through the stream, and no exception is propagated.
-
-Below are examples of each of the two new components:
-
-#### DltAwareProcessor
-
-{% highlight java %}
-
-@Bean
-public Function, KStream> dltAwareExample(
- DltPublishingContext dltPublishingContext) {
- return input -> input
- .process(() -> new DltAwareProcessor<>(myRecord -> {
- throw new RuntimeException("Something went wrong, Error");
- }, "my.dead-letter-queue.topic", dltPublishingContext));
-}
-
-{% endhighlight %}
-
-#### RecordRecoverableProcessor
-
-Here is a sample RecordRecoverableProcessor, fully laid out. An IDE will suggest turning many parts
-of this example into lambda functions, making it significantly cleaner. I will link both here to show what exactly
-is happening with the expanded version, but also how short it can be with the cleaned up version.
-
-{% highlight java %}
-
-// Expanded version
-@Bean
-public Function, KStream> rrpDemo(){
- return input -> input
- .process(new ProcessorSupplier() {
- @Override
- public Processor get() {
- return new RecordRecoverableProcessor<>(
- new Function, Record>() {
- @Override
- public Record apply(Record stringStringRecord) {
- return stringStringRecord;
- }
- },
- new BiConsumer, Exception>() {
- @Override
- public void accept(Record stringStringRecord, Exception e) {
- log.error(e.getMessage());
- }
- }
- );
- }
- }
- );
-}
-
-// Collapsed Version
-@Bean
-public Function, KStream> rrpDemo(){
- return input -> input
- .process(() -> new RecordRecoverableProcessor<>(
- stringStringRecord -> stringStringRecord,
- (stringStringRecord, e) -> log.error(e.getMessage()
- )
- ));
-}
-
-{% endhighlight %}
-
-
-
-### Finally
-
-With Spring Cloud Streams, we can easily create rich and powerful pipelines connecting any number
-of message processing systems.
-
-I'm proud to have had a hand in closing what I see as one of the largest gaps in this framework
-and look forward to the continued development of something so useful to the spring community!
-
-[scs-samples]: https://github.com/spring-cloud/spring-cloud-stream-samples
-[spring-cloud-stream-documentation]: https://spring.io/projects/spring-cloud-stream
-[kafka-streams-binder-documentation]: https://cloud.spring.io/spring-cloud-stream-binder-kafka/spring-cloud-stream-binder-kafka.html#_kafka_streams_binder
-[deserialization-error-scs-ks]: https://cloud.spring.io/spring-cloud-stream-binder-kafka/spring-cloud-stream-binder-kafka.html#_handling_deserialization_exceptions
-[non-deserialization-error-scs-ks]: https://cloud.spring.io/spring-cloud-stream-binder-kafka/spring-cloud-stream-binder-kafka.html#_handling_non_deserialization_exceptions
-[soby-chako]: https://github.com/sobychacko
-[spring-cloud-stream-issues-2779]: https://github.com/spring-cloud/spring-cloud-stream/issues/2779
-[rrp]: https://github.com/spring-cloud/spring-cloud-stream/blob/main/binders/kafka-binder/spring-cloud-stream-binder-kafka-streams/src/main/java/org/springframework/cloud/stream/binder/kafka/streams/RecordRecoverableProcessor.java#L84
diff --git a/_posts/2024-09-17-Java-Streams-Gather-Jdk-23.markdown b/_posts/2024-09-17-Java-Streams-Gather-Jdk-23.markdown
deleted file mode 100644
index 0be0cee2..00000000
--- a/_posts/2024-09-17-Java-Streams-Gather-Jdk-23.markdown
+++ /dev/null
@@ -1,236 +0,0 @@
----
-layout: post
-title: "Jdk 23 Streams - How To Use Gather Operations"
-toc: true
-date: 2024-09-29 12:00:00 -0500
-categories:
-- software
-- java
----
-
-# It's finally here! JDK 23
-
-Just kidding, this isn't an LTS release
-
-The next LTS release that will include all of the changes in JDK 23 (assuming Gatherers make the cut) is JDK 25 and
-that won't be available until September 2025. When that happens, all of the links on this page will be updated for JDK 25.
-
-This post is a simple overview of the new [java.util.stream.Gatherer][gatherer-javadoc] and related classes that have been added
-as part of JDK 23. These operations are incredibly powerful and right away, I wasn't able to find
-a good resource on the web that helped me understand.
-
-SO, in keeping with this site, I intend to write up a simple article that I (and others!) can reference
-in the future when we need to understand something about this new non-terminating stream capability!
-
-### Let's get to demo-ing!
-
-We can install Java 23 quickly using Sdkman! using `sdk install java 23-tem`
-
-The link to the release notes for Jdk23 are right here: [https://openjdk.org/projects/jdk/23][openjdk23]
-
-This feature is a pretty powerful addition for anyone that's been
-leveraging Java Streams heavily for stream processing!
-
-Specifically for Gatherers, the JEP is right over here: [https://openjdk.org/jeps/473][jeps473]
-
-## JEP-473
-
-Stream Gatherers is a preview API delivered in JDK 22 that's in preview again
-in JDK 23. Gatherers allow for stream pipelines to transform
-data through intermediate operations instead of needing to perform
-a terminating operation and generate a new stream.
-
-Today, if we want to process a list of elements, then perform an operation on the entire list,
-and then continue processing the list, we'd have to do it like this:
-
-```java
-void main(String[] args) {
- var mylist = Stream.of(1,2,3)
- .map(integer -> integer + 10)
- .collect(Collectors.toList());
- // We can't perform any operations on the full list
- // So we have to terminate the stream and spin up
- // a new one, just to perform this simple operation
- mylist.remove(1);
- var myListMinusFirstElement = mylist.stream()
- .map(integer -> integer + 20)
- .toList();
- System.out.println(myListMinusFirstElement);
-}
-```
-
-```bash
-$ java --enable-preview demo
-[31, 33]
-```
-
-With Gatherers, we're able to do this in a cleaner way by
-doing our extra processing in an intermediate method!
-
-Ok before you look at this, it's not really `cleaner` per-say, but
-it's a good example of how powerful these operations can really be!
-
-```java
-void main(String[] args) {
-
- Supplier initializer = () -> new AtomicInteger(0);
-
- // Integrator
- // 1 – the type of state used by this integrator
- // 2 – the type of elements this integrator consumes
- // 3 – the type of results this integrator can produce
- Gatherer.Integrator integrator =
- (state, element, downstream) -> {
- int index = state.getAndIncrement();
- // We want to simply remove the second element from the list
- if (index != 1) {
- downstream.push(element);
- }
- return true;
- };
-
- var mylist = Stream.of(1, 2, 3)
- .map(integer -> integer + 10)
- .gather(Gatherer.ofSequential(initializer, integrator))
- .map(integer -> integer + 20)
- .toList();
- System.out.println(mylist);
-}
-```
-
-```bash
- $ javac demo.java --enable-preview -source 23
- $ java --enable-preview demo
- [31, 33]
-```
-
-From this simple example, we can see how extemely powerful this operation can be, allowing us
-to bring in ANY state and mutate it, while also making filtering decisions. Since we can define
-the output type, we can also perform mapping operations... Which is an excellent pivot into the next topic!
-
-## Gatherer Operations
-
-First, a quick terminology overview:
-
-Streams begin with a source (Stream.of() or myList.stream(), for example). Sources are followed by intermediate operations
-such as map, filter, flatMap, etc. Finally, there is a terminating operation that closes the stream and emits a final object.
-
-There are simple terminating stream operators such as .toList or .toSet. However, Gatherers are similar to .collect. .collect
-is a terminating stream operation, but it allows you to override a Collector and control the output of the stream.
-
-### Three Gatherer Functions
-
-Gatherers are designed to transform elements in a one-to-one, one-to-many, many-to-one or many-to-many fashion.
-
-#### Initializer
-
-The initializer function sets up a mechanism for storing data while
-processing stream elements. A gatherer can use this to store the
-current element and compare it to incoming elements, emitting only
-the larger one. This effectively combines two input elements into one
-output element.
-
-#### Integrator
-
-The integrator is responsible for processing incoming elements and
-producing new output based on the current data and internal state.
-It can terminate the process prematurely, such as a gatherer that
-stops searching for the largest integer once it finds Integer.MAX_VALUE.
-
-#### Finisher
-
-The finisher function is executed once all input elements have been
-processed. It can analyze the collected data and generate a final output.
-For example, a gatherer searching for a specific element might throw an
-exception if it's not found when the finisher is called.
-
-##### Examples
-
-This is an example of a basic mapping integrator.
-
-```java
-// C is the type being consumed, P is the type being produced
-Integrator integrator =
- (state, element, downstream) -> {
- // we can ignore the state for a simple mapper
- var result = someMapperFunction.apply(element);
- // We emit the result to the next iteration after applying the mapping
- downstream.push(result);
- // Continue to process items in the stream
- return true;
- };
-Gatherer.of(integrator);
-```
-
-Next, here is an example recreating the `.limit` stream operation, that uses an integrator and initializer
-
-```java
-import java.util.concurrent.atomic.AtomicInteger;
-
-Supplier initializer = () -> new AtomicInteger(0);
-Integrator integrator =
- (state, element, downstream) -> {
- // Edit our state for the current index
- int currIndex = state.getAndIncrement();
- // Only push through results if within the stream size
- if(currIndex < someStreamSize) {
- downstream.push(element);
- }
- // Return whether the next index will be within stream size
- return currIndex + 1 < someStreamSize;
- };
-Gatherer.ofSequential(initializer, integrator);
-```
-
-## Built-In Gatherers
-
-TODO - add link to JavaDoc for each with examples!
-The following are built-in gatherers in the [java.util.stream.Gatherers][gatherers-javadoc] class:
-
-[fold][fold] is a stateful many-to-one gatherer which constructs an aggregate
-incrementally and emits that aggregate when no more input elements exist.
-
-TODO - example
-
-[mapConcurrent][mapConcurrent] is a stateful one-to-one gatherer which invokes a supplied
-function for each input element concurrently, up to a supplied limit.
-
-TODO - example
-
-[scan][scan] is a stateful one-to-one gatherer which applies a supplied function
-to the current state and the current element to produce the next element,
-which it passes downstream.
-
-TODO - example
-
-[windowFixed][windowFixed] is a stateful many-to-many gatherer which groups input
-elements into lists of a supplied size, emitting the windows
-downstream when they are full.
-
-TODO - example
-
-[windowSliding][windowSliding] is a stateful many-to-many gatherer which groups input
-elements into lists of a supplied size. After the first window, each
-subsequent window is created from a copy of its predecessor by dropping
-the first element and appending the next element from the input stream..
-
-TODO - example
-
-## Gatherers are so useful, we can re-create every intermediate stream operation
-
-TODO - recreate everything as gatherers
-
-TODO - find real life example
-- distinctBy
-- grouping and applying a change to the whole collection
-
-[soby-chako]: https://github.com/sobychacko
-[openjdk23]: https://openjdk.org/projects/jdk/23/
-[jeps473]: https://openjdk.org/jeps/473
-[gatherer-javadoc]: https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/util/stream/Gatherer.html
-[gatherers-javadoc]: https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/util/stream/Gatherers.html
-[windowFixed]: https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/util/stream/Gatherers.html#windowFixed(int)
-[windowSliding]: https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/util/stream/Gatherers.html#windowSliding(int)
-[fold]: https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/util/stream/Gatherers.html#fold(java.util.function.Supplier,java.util.function.BiFunction)
-[scan]: https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/util/stream/Gatherers.html#scan(java.util.function.Supplier,java.util.function.BiFunction)
-[mapConcurrent]: https://docs.oracle.com/en/java/javase/23/docs/api/java.base/java/util/stream/Gatherers.html#mapConcurrent(int,java.util.function.Function)
diff --git a/_posts/2024-09-19-Easy-Spring-Rest-Client-with-OAuth2.markdown b/_posts/2024-09-19-Easy-Spring-Rest-Client-with-OAuth2.markdown
deleted file mode 100644
index 9cc05115..00000000
--- a/_posts/2024-09-19-Easy-Spring-Rest-Client-with-OAuth2.markdown
+++ /dev/null
@@ -1,186 +0,0 @@
----
-layout: post
-title: "Easy Spring Rest Client w/ OAuth2"
-toc: true
-date: 2024-09-19 12:00:00 -0500
-categories:
-- software
-- spring boot
-- java
----
-
-# Brief
-
-My goal is to make posts like this the SIMPLEST place on the internet to learn how to do things
-that caused me trouble. That way, if this is found, someone doesn't have to do the same digging I had to do.
-
-# What is OAuth2?
-
-OAuth2 is a popular authorization framework that allows users to grant
-third-party applications access to their data without revealing their
-credentials. It's often used for services like social media logins, API integrations, and more.
-
-### Key Components of OAuth2
-
-- Authorization Server: Issues access tokens to clients after user authorization.
-- Resource Server: Protects resources that can only be accessed with valid access tokens.
-- Client: The application requesting access to resources.
-- User: The person granting or denying access.
-
-### How OAuth2 Works
-
-- User Authorization: The user grants permission to the client to access specific resources.
-- Token Exchange: The client exchanges an authorization code for an access token.
-- Resource Access: The client uses the access token to access protected resources.
-
-### Why RestClient?
-
-While **RestTemplate** has been a staple for many years, its limitations and the
-introduction of more modern alternatives have led to its deprecation in recent
-versions of Spring. Let's dive into the key differences between WebClient
-and RestClient and why RestTemplate is being phased out.
-
-**WebClient** is built on top of Project Reactor, a reactive
-programming framework. This means it can handle asynchronous operations efficiently,
-making it well-suited for scenarios where concurrent requests and non-blocking I/O
-are essential.
-
-However, with RestTemplate's deprecation, the only real Spring alternative is WebClient.
-This requires including the spring-webflux dependencies and calling `.block()` when making
-blocking API calls. It feels shoe-horned into place.
-
-In comes [RestClient][restClientBlogAnnouncement], a client written in the same functional style as WebClient, but supports
-synchronous and asynchronous operations out of the box. This lets us remove the spring-webflux
-dependency and use spring-web-mvc as the primary HTTP dependency for server and client applications.
-
-## The Setup (Currently a Milestone Release but this will be updated!)
-
-Here's everything you need to get RestClient working with OAuth2!
-
-build.gradle
-```groovy
-plugins {
- id 'org.springframework.boot' version '3.3.3'
-}
-
- // ... The rest of the stuff, this is just what's required
-
- dependencies {
- implementation 'org.springframework.boot:spring-boot-starter-security'
- implementation 'org.springframework.boot:spring-boot-starter-web'
- implementation 'org.springframework.security:spring-security-oauth2-client:6.4.0-M3'
- }
-}
-```
-
-application.yaml
-```yaml
-spring:
- security:
- oauth2:
- client:
- registration:
- my-oauth-client:
- client-id: ${oauthClientId}
- client-secret: ${oauthClientSecret}
- provider: my-oauth-provider
- authorization-grant-type: client_credentials
- scope: openid
- provider:
- my-oauth-provider:
- token-uri: ${oauth2ServerUri}/protocol/openid-connect/token
- issuer-uri: ${oauth2ServerUri}
-```
-
-application-local.yaml
-```yaml
-oauth2ServerUri: http://myServerUri:9090
-oauthClientId: clientId
-oauth2ClientSecret: mySecretSecret
-```
-
-RestClientConfiguration.java using the new [OAuth2ClientHttpRequestInterceptor][oAuth2ClientHttpRequestInterceptor]
-```java
-@Configuration
-public class RestClientConfiguration
-{
- // This needs to match the YAML configuration
- private static final String CLIENT_REGISTRATION_ID = "my-oauth-client";
-
- @Bean
- public OAuth2AuthorizedClientManager authorizedClientManager (
- ClientRegistrationRepository clientRegistrationRepository,
- OAuth2AuthorizedClientService authorizedClientService
- ){
- // We create a manager using the autowired clientRegistrations from YAML and connect it to the service
- AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager =
- new AuthorizedClientServiceOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientService);
-
- // Setting the clientManager to look for a clientCredentials configuration
- authorizedClientManager.setAuthorizedClientProvider(OAuth2AuthorizedClientProviderBuilder.builder()
- .clientCredentials()
- .build());
- return authorizedClientManager;
- }
-
- @Bean
- public RestClient oauth2RestClient(
- OAuth2AuthorizedClientManager authorizedClientManager) {
-
- // This is the new class!!! We instantiate a new one and provide it the client registration to match
- OAuth2ClientHttpRequestInterceptor oAuth2ClientHttpRequestInterceptor =
- new OAuth2ClientHttpRequestInterceptor(authorizedClientManager, request -> CLIENT_REGISTRATION_ID);
-
- // From here we simply return the client with any custom configuration, and we're good to go!
- return RestClient.builder()
- .baseUrl("http://myBaseUrl:8080")
- .requestInterceptor(oAuth2ClientHttpRequestInterceptor)
- .build();
- }
-}
-```
-
-### Bonus: Setting up HttpServiceProxyFactory (not required but useful!)
-
-[HttpServiceProxyFactory][httpServiceProxyFactory] is new in [Spring 6][httpServiceProxyFactoryJavadoc]!
-
-```java
-public interface MyHttpService {
-
- @PostExchange("api/my/path")
- SomeResponse post(@RequestBody MyPostBody request);
-}
-```
-
-```java
-@Configuration
-public class HttpServiceFactory
-{
- @Bean
- public MyHttpService getMyHttpService(RestClient oauth2RestClient) {
- // We're simply injecting our restClient into the factory and creating a concrete instance of the interface
- HttpServiceProxyFactory factory = HttpServiceProxyFactory
- .builderFor(RestClientAdapter.create(oauth2RestClient))
- .build();
- return factory.createClient(MyHttpService.class);
- }
-}
-```
-
-## Summary
-
-The new RestClient is already a popular alternative for developers in the Spring ecosystem.
-The lack of an OAuth2 component has been a sore spot for new users converting over from WebClient. So with
-this new feature releasing in Spring Boot 3.4.0, it can now take it's rightful place as the default, non-webflux
-HTTP Client for Spring MVC!
-
-## Update Note
-
-Once this is available in the official spring release, I'll update this from milestone versions and
-hook up the JavaDoc instead of the originating Github Issue!
-
-[restClientBlogAnnouncement]: https://spring.io/blog/2023/07/13/new-in-spring-6-1-restclient
-[oAuth2ClientHttpRequestInterceptor]: https://github.com/spring-projects/spring-security/issues/13588
-[httpServiceProxyFactoryJavadoc]: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/service/invoker/HttpServiceProxyFactory.html
-[httpServiceProxyFactory]: https://www.baeldung.com/spring-6-http-interface
-[soby-chako]: https://github.com/sobychacko
diff --git a/about.markdown b/about.markdown
deleted file mode 100644
index aa1b99e5..00000000
--- a/about.markdown
+++ /dev/null
@@ -1,26 +0,0 @@
----
-layout: page
-title: About Me
-permalink: /about/
----
-
-Welcome! I'm Steve
-
-I'm a 30 year old software developer starting his first blog. Partly as a
-way to record my thoughts, partly to document things that don't get documented elsewhere.
-
-I have a ton of DevOps experience across CI/CD, Docker/Kubernetes and Cloud. On top of
-that I've been coding in Java using Spring Boot for about 8 years, along with a bunch
-of other tools, languages and integrations.
-
-I've worked across e-commerce, aerospace, corporate tax and accounting industries. So
-I finally feel like I've experienced enough unique situations that I want to start writing
-down the hardest stuff for someone in my shoes to get value out of.
-
-(And honestly, I'll probably come back to reference things I've forgotten too)
-
-My hobbies mostly including; poking at software and hardware, taking care of 11 cats
-and trying to feed a diminishing interest in cars.
-
-I'm trying to get into blogging *as you can see*.
-
diff --git a/archive.html b/archive.html
deleted file mode 100644
index b27a9c53..00000000
--- a/archive.html
+++ /dev/null
@@ -1,17 +0,0 @@
----
-layout: page
-title: Old Posts
----
-
-{%- assign allposts = site.posts | concat: site.personal | sort_natural: "date" | reverse %}
-
-{%- assign postsByYearMonth = allposts | group_by_exp:"allposts", "allposts.date | date: '%Y %B'" %}
-
-{%- for yearMonth in postsByYearMonth %}
-{{ yearMonth.name }}
-
-{%- endfor %}
\ No newline at end of file
diff --git a/astro/astro-paper-main/astro.config.ts b/astro.config.ts
similarity index 100%
rename from astro/astro-paper-main/astro.config.ts
rename to astro.config.ts
diff --git a/astro/astro-paper-main/.gitignore b/astro/astro-paper-main/.gitignore
deleted file mode 100644
index 9a5d91f2..00000000
--- a/astro/astro-paper-main/.gitignore
+++ /dev/null
@@ -1,32 +0,0 @@
-# build output
-dist/
-.output/
-
-# dependencies
-node_modules/
-
-# logs
-npm-debug.log*
-yarn-debug.log*
-yarn-error.log*
-pnpm-debug.log*
-
-
-# environment variables
-.env
-.env.production
-
-# macOS-specific files
-.DS_Store
-
-# ignore .astro directory
-.astro
-
-# yarn
-.yarn/*
-!.yarn/patches
-!.yarn/plugins
-!.yarn/releases
-!.yarn/sdks
-!.yarn/versions
-.pnp.*
diff --git a/astro/astro-paper-main/src/assets/images/3GzdjxY.png b/astro/astro-paper-main/src/assets/images/3GzdjxY.png
deleted file mode 100644
index 7940bbe5..00000000
Binary files a/astro/astro-paper-main/src/assets/images/3GzdjxY.png and /dev/null differ
diff --git a/astro/astro-paper-main/src/assets/images/44wMq0Z.png b/astro/astro-paper-main/src/assets/images/44wMq0Z.png
deleted file mode 100644
index f4b68407..00000000
Binary files a/astro/astro-paper-main/src/assets/images/44wMq0Z.png and /dev/null differ
diff --git a/astro/astro-paper-main/src/assets/images/7225cac2-0224-4f0a-ae86-8057a1629022.png b/astro/astro-paper-main/src/assets/images/7225cac2-0224-4f0a-ae86-8057a1629022.png
deleted file mode 100644
index de243634..00000000
Binary files a/astro/astro-paper-main/src/assets/images/7225cac2-0224-4f0a-ae86-8057a1629022.png and /dev/null differ
diff --git a/astro/astro-paper-main/src/assets/images/8aaaf23a-d737-4e9d-bcb4-61ddcc9e5a2a.png b/astro/astro-paper-main/src/assets/images/8aaaf23a-d737-4e9d-bcb4-61ddcc9e5a2a.png
deleted file mode 100644
index 1d340c53..00000000
Binary files a/astro/astro-paper-main/src/assets/images/8aaaf23a-d737-4e9d-bcb4-61ddcc9e5a2a.png and /dev/null differ
diff --git a/astro/astro-paper-main/src/assets/images/EZb9cQ7.jpg b/astro/astro-paper-main/src/assets/images/EZb9cQ7.jpg
deleted file mode 100644
index 19426c20..00000000
Binary files a/astro/astro-paper-main/src/assets/images/EZb9cQ7.jpg and /dev/null differ
diff --git a/astro/astro-paper-main/src/assets/images/ILGJD3b.jpg b/astro/astro-paper-main/src/assets/images/ILGJD3b.jpg
deleted file mode 100644
index af57c2f3..00000000
Binary files a/astro/astro-paper-main/src/assets/images/ILGJD3b.jpg and /dev/null differ
diff --git a/astro/astro-paper-main/src/assets/images/LvdGYAG.jpg b/astro/astro-paper-main/src/assets/images/LvdGYAG.jpg
deleted file mode 100644
index 2aa0dd98..00000000
Binary files a/astro/astro-paper-main/src/assets/images/LvdGYAG.jpg and /dev/null differ
diff --git a/astro/astro-paper-main/src/assets/images/a368fd78-2be5-412b-b744-265e20ef4aef.png b/astro/astro-paper-main/src/assets/images/a368fd78-2be5-412b-b744-265e20ef4aef.png
deleted file mode 100644
index a58eadd3..00000000
Binary files a/astro/astro-paper-main/src/assets/images/a368fd78-2be5-412b-b744-265e20ef4aef.png and /dev/null differ
diff --git a/astro/astro-paper-main/src/assets/images/b40a4c04-5106-4a2e-9947-95eadcc59bb3.png b/astro/astro-paper-main/src/assets/images/b40a4c04-5106-4a2e-9947-95eadcc59bb3.png
deleted file mode 100644
index 05d92362..00000000
Binary files a/astro/astro-paper-main/src/assets/images/b40a4c04-5106-4a2e-9947-95eadcc59bb3.png and /dev/null differ
diff --git a/astro/astro-paper-main/src/assets/images/c972da73-155a-426a-b487-5ad73295c918.png b/astro/astro-paper-main/src/assets/images/c972da73-155a-426a-b487-5ad73295c918.png
deleted file mode 100644
index 0cbee3ee..00000000
Binary files a/astro/astro-paper-main/src/assets/images/c972da73-155a-426a-b487-5ad73295c918.png and /dev/null differ
diff --git a/astro/astro-paper-main/src/assets/images/f8eae9e1-d1b0-4ee0-a19a-56a6ea290af3.png b/astro/astro-paper-main/src/assets/images/f8eae9e1-d1b0-4ee0-a19a-56a6ea290af3.png
deleted file mode 100644
index e3dd4e4c..00000000
Binary files a/astro/astro-paper-main/src/assets/images/f8eae9e1-d1b0-4ee0-a19a-56a6ea290af3.png and /dev/null differ
diff --git a/astro/astro-paper-main/src/assets/images/jVNLPaR.jpg b/astro/astro-paper-main/src/assets/images/jVNLPaR.jpg
deleted file mode 100644
index 637a586d..00000000
Binary files a/astro/astro-paper-main/src/assets/images/jVNLPaR.jpg and /dev/null differ
diff --git a/astro/astro-paper-main/doc-posts/adding-new-post.md b/doc-posts/adding-new-post.md
similarity index 100%
rename from astro/astro-paper-main/doc-posts/adding-new-post.md
rename to doc-posts/adding-new-post.md
diff --git a/astro/astro-paper-main/doc-posts/astro-paper-2.md b/doc-posts/astro-paper-2.md
similarity index 100%
rename from astro/astro-paper-main/doc-posts/astro-paper-2.md
rename to doc-posts/astro-paper-2.md
diff --git a/astro/astro-paper-main/doc-posts/astro-paper-3.md b/doc-posts/astro-paper-3.md
similarity index 100%
rename from astro/astro-paper-main/doc-posts/astro-paper-3.md
rename to doc-posts/astro-paper-3.md
diff --git a/astro/astro-paper-main/doc-posts/astro-paper-4.md b/doc-posts/astro-paper-4.md
similarity index 100%
rename from astro/astro-paper-main/doc-posts/astro-paper-4.md
rename to doc-posts/astro-paper-4.md
diff --git a/astro/astro-paper-main/doc-posts/customizing-astropaper-theme-color-schemes.md b/doc-posts/customizing-astropaper-theme-color-schemes.md
similarity index 100%
rename from astro/astro-paper-main/doc-posts/customizing-astropaper-theme-color-schemes.md
rename to doc-posts/customizing-astropaper-theme-color-schemes.md
diff --git a/astro/astro-paper-main/doc-posts/dynamic-og-images.md b/doc-posts/dynamic-og-images.md
similarity index 100%
rename from astro/astro-paper-main/doc-posts/dynamic-og-images.md
rename to doc-posts/dynamic-og-images.md
diff --git a/astro/astro-paper-main/doc-posts/example-draft-post.md b/doc-posts/example-draft-post.md
similarity index 100%
rename from astro/astro-paper-main/doc-posts/example-draft-post.md
rename to doc-posts/example-draft-post.md
diff --git a/astro/astro-paper-main/doc-posts/how-to-add-a-new-social-icon.md b/doc-posts/how-to-add-a-new-social-icon.md
similarity index 100%
rename from astro/astro-paper-main/doc-posts/how-to-add-a-new-social-icon.md
rename to doc-posts/how-to-add-a-new-social-icon.md
diff --git a/astro/astro-paper-main/doc-posts/how-to-add-an-estimated-reading-time.md b/doc-posts/how-to-add-an-estimated-reading-time.md
similarity index 100%
rename from astro/astro-paper-main/doc-posts/how-to-add-an-estimated-reading-time.md
rename to doc-posts/how-to-add-an-estimated-reading-time.md
diff --git a/astro/astro-paper-main/doc-posts/how-to-add-latex-equations-in-blog-posts.md b/doc-posts/how-to-add-latex-equations-in-blog-posts.md
similarity index 100%
rename from astro/astro-paper-main/doc-posts/how-to-add-latex-equations-in-blog-posts.md
rename to doc-posts/how-to-add-latex-equations-in-blog-posts.md
diff --git a/astro/astro-paper-main/doc-posts/how-to-configure-astropaper-theme.md b/doc-posts/how-to-configure-astropaper-theme.md
similarity index 100%
rename from astro/astro-paper-main/doc-posts/how-to-configure-astropaper-theme.md
rename to doc-posts/how-to-configure-astropaper-theme.md
diff --git a/astro/astro-paper-main/doc-posts/how-to-connect-astro-paper-blog-with-forestry-cms.md b/doc-posts/how-to-connect-astro-paper-blog-with-forestry-cms.md
similarity index 100%
rename from astro/astro-paper-main/doc-posts/how-to-connect-astro-paper-blog-with-forestry-cms.md
rename to doc-posts/how-to-connect-astro-paper-blog-with-forestry-cms.md
diff --git a/astro/astro-paper-main/doc-posts/how-to-integrate-giscus-comments.md b/doc-posts/how-to-integrate-giscus-comments.md
similarity index 100%
rename from astro/astro-paper-main/doc-posts/how-to-integrate-giscus-comments.md
rename to doc-posts/how-to-integrate-giscus-comments.md
diff --git a/astro/astro-paper-main/doc-posts/how-to-update-dependencies.md b/doc-posts/how-to-update-dependencies.md
similarity index 100%
rename from astro/astro-paper-main/doc-posts/how-to-update-dependencies.md
rename to doc-posts/how-to-update-dependencies.md
diff --git a/astro/astro-paper-main/doc-posts/portfolio-website-development.md b/doc-posts/portfolio-website-development.md
similarity index 100%
rename from astro/astro-paper-main/doc-posts/portfolio-website-development.md
rename to doc-posts/portfolio-website-development.md
diff --git a/astro/astro-paper-main/doc-posts/predefined-color-schemes.md b/doc-posts/predefined-color-schemes.md
similarity index 100%
rename from astro/astro-paper-main/doc-posts/predefined-color-schemes.md
rename to doc-posts/predefined-color-schemes.md
diff --git a/astro/astro-paper-main/doc-posts/setting-dates-via-git-hooks.md b/doc-posts/setting-dates-via-git-hooks.md
similarity index 100%
rename from astro/astro-paper-main/doc-posts/setting-dates-via-git-hooks.md
rename to doc-posts/setting-dates-via-git-hooks.md
diff --git a/astro/astro-paper-main/doc-posts/tailwind-typography.md b/doc-posts/tailwind-typography.md
similarity index 100%
rename from astro/astro-paper-main/doc-posts/tailwind-typography.md
rename to doc-posts/tailwind-typography.md
diff --git a/astro/astro-paper-main/doc-posts/terminal-development.md b/doc-posts/terminal-development.md
similarity index 100%
rename from astro/astro-paper-main/doc-posts/terminal-development.md
rename to doc-posts/terminal-development.md
diff --git a/astro/astro-paper-main/eslint.config.mjs b/eslint.config.mjs
similarity index 100%
rename from astro/astro-paper-main/eslint.config.mjs
rename to eslint.config.mjs
diff --git a/index.markdown b/index.markdown
deleted file mode 100644
index 06715078..00000000
--- a/index.markdown
+++ /dev/null
@@ -1,6 +0,0 @@
----
-# Feel free to add content and custom Front Matter to this file.
-# To modify the layout, see https://jekyllrb.com/docs/themes/#overriding-theme-defaults
-
-layout: home
----
diff --git a/astro/astro-paper-main/package-lock.json b/package-lock.json
similarity index 100%
rename from astro/astro-paper-main/package-lock.json
rename to package-lock.json
diff --git a/astro/astro-paper-main/package.json b/package.json
similarity index 100%
rename from astro/astro-paper-main/package.json
rename to package.json
diff --git a/astro/astro-paper-main/public/assets/dev.svg b/public/assets/dev.svg
similarity index 100%
rename from astro/astro-paper-main/public/assets/dev.svg
rename to public/assets/dev.svg
diff --git a/astro/astro-paper-main/public/assets/forrest-gump-quote.webp b/public/assets/forrest-gump-quote.webp
similarity index 100%
rename from astro/astro-paper-main/public/assets/forrest-gump-quote.webp
rename to public/assets/forrest-gump-quote.webp
diff --git a/astro/astro-paper-main/public/assets/logo.png b/public/assets/logo.png
similarity index 100%
rename from astro/astro-paper-main/public/assets/logo.png
rename to public/assets/logo.png
diff --git a/astro/astro-paper-main/public/assets/logo.svg b/public/assets/logo.svg
similarity index 100%
rename from astro/astro-paper-main/public/assets/logo.svg
rename to public/assets/logo.svg
diff --git a/astro/astro-paper-main/public/astropaper-og.jpg b/public/astropaper-og.jpg
similarity index 100%
rename from astro/astro-paper-main/public/astropaper-og.jpg
rename to public/astropaper-og.jpg
diff --git a/astro/astro-paper-main/public/favicon.svg b/public/favicon.svg
similarity index 100%
rename from astro/astro-paper-main/public/favicon.svg
rename to public/favicon.svg
diff --git a/astro/astro-paper-main/public/toggle-theme.js b/public/toggle-theme.js
similarity index 100%
rename from astro/astro-paper-main/public/toggle-theme.js
rename to public/toggle-theme.js
diff --git a/astro/astro-paper-main/remark-collapse.d.ts b/remark-collapse.d.ts
similarity index 100%
rename from astro/astro-paper-main/remark-collapse.d.ts
rename to remark-collapse.d.ts
diff --git a/assets/3GzdjxY.png b/src/assets/images/3GzdjxY.png
similarity index 100%
rename from assets/3GzdjxY.png
rename to src/assets/images/3GzdjxY.png
diff --git a/assets/44wMq0Z.png b/src/assets/images/44wMq0Z.png
similarity index 100%
rename from assets/44wMq0Z.png
rename to src/assets/images/44wMq0Z.png
diff --git a/assets/7225cac2-0224-4f0a-ae86-8057a1629022.png b/src/assets/images/7225cac2-0224-4f0a-ae86-8057a1629022.png
similarity index 100%
rename from assets/7225cac2-0224-4f0a-ae86-8057a1629022.png
rename to src/assets/images/7225cac2-0224-4f0a-ae86-8057a1629022.png
diff --git a/assets/8aaaf23a-d737-4e9d-bcb4-61ddcc9e5a2a.png b/src/assets/images/8aaaf23a-d737-4e9d-bcb4-61ddcc9e5a2a.png
similarity index 100%
rename from assets/8aaaf23a-d737-4e9d-bcb4-61ddcc9e5a2a.png
rename to src/assets/images/8aaaf23a-d737-4e9d-bcb4-61ddcc9e5a2a.png
diff --git a/astro/astro-paper-main/src/assets/images/AstroPaper-v3.png b/src/assets/images/AstroPaper-v3.png
similarity index 100%
rename from astro/astro-paper-main/src/assets/images/AstroPaper-v3.png
rename to src/assets/images/AstroPaper-v3.png
diff --git a/astro/astro-paper-main/src/assets/images/AstroPaper-v4.png b/src/assets/images/AstroPaper-v4.png
similarity index 100%
rename from astro/astro-paper-main/src/assets/images/AstroPaper-v4.png
rename to src/assets/images/AstroPaper-v4.png
diff --git a/assets/EZb9cQ7.jpg b/src/assets/images/EZb9cQ7.jpg
similarity index 100%
rename from assets/EZb9cQ7.jpg
rename to src/assets/images/EZb9cQ7.jpg
diff --git a/assets/ILGJD3b.jpg b/src/assets/images/ILGJD3b.jpg
similarity index 100%
rename from assets/ILGJD3b.jpg
rename to src/assets/images/ILGJD3b.jpg
diff --git a/assets/LvdGYAG.jpg b/src/assets/images/LvdGYAG.jpg
similarity index 100%
rename from assets/LvdGYAG.jpg
rename to src/assets/images/LvdGYAG.jpg
diff --git a/assets/a368fd78-2be5-412b-b744-265e20ef4aef.png b/src/assets/images/a368fd78-2be5-412b-b744-265e20ef4aef.png
similarity index 100%
rename from assets/a368fd78-2be5-412b-b744-265e20ef4aef.png
rename to src/assets/images/a368fd78-2be5-412b-b744-265e20ef4aef.png
diff --git a/assets/b40a4c04-5106-4a2e-9947-95eadcc59bb3.png b/src/assets/images/b40a4c04-5106-4a2e-9947-95eadcc59bb3.png
similarity index 100%
rename from assets/b40a4c04-5106-4a2e-9947-95eadcc59bb3.png
rename to src/assets/images/b40a4c04-5106-4a2e-9947-95eadcc59bb3.png
diff --git a/assets/c972da73-155a-426a-b487-5ad73295c918.png b/src/assets/images/c972da73-155a-426a-b487-5ad73295c918.png
similarity index 100%
rename from assets/c972da73-155a-426a-b487-5ad73295c918.png
rename to src/assets/images/c972da73-155a-426a-b487-5ad73295c918.png
diff --git a/assets/f8eae9e1-d1b0-4ee0-a19a-56a6ea290af3.png b/src/assets/images/f8eae9e1-d1b0-4ee0-a19a-56a6ea290af3.png
similarity index 100%
rename from assets/f8eae9e1-d1b0-4ee0-a19a-56a6ea290af3.png
rename to src/assets/images/f8eae9e1-d1b0-4ee0-a19a-56a6ea290af3.png
diff --git a/assets/jVNLPaR.jpg b/src/assets/images/jVNLPaR.jpg
similarity index 100%
rename from assets/jVNLPaR.jpg
rename to src/assets/images/jVNLPaR.jpg
diff --git a/astro/astro-paper-main/src/assets/images/v9EGGek.jpeg b/src/assets/images/v9EGGek.jpeg
similarity index 100%
rename from astro/astro-paper-main/src/assets/images/v9EGGek.jpeg
rename to src/assets/images/v9EGGek.jpeg
diff --git a/astro/astro-paper-main/src/assets/socialIcons.ts b/src/assets/socialIcons.ts
similarity index 100%
rename from astro/astro-paper-main/src/assets/socialIcons.ts
rename to src/assets/socialIcons.ts
diff --git a/astro/astro-paper-main/src/components/Breadcrumbs.astro b/src/components/Breadcrumbs.astro
similarity index 100%
rename from astro/astro-paper-main/src/components/Breadcrumbs.astro
rename to src/components/Breadcrumbs.astro
diff --git a/astro/astro-paper-main/src/components/BuyMeACoffee.astro b/src/components/BuyMeACoffee.astro
similarity index 100%
rename from astro/astro-paper-main/src/components/BuyMeACoffee.astro
rename to src/components/BuyMeACoffee.astro
diff --git a/astro/astro-paper-main/src/components/Card.tsx b/src/components/Card.tsx
similarity index 100%
rename from astro/astro-paper-main/src/components/Card.tsx
rename to src/components/Card.tsx
diff --git a/astro/astro-paper-main/src/components/Datetime.tsx b/src/components/Datetime.tsx
similarity index 100%
rename from astro/astro-paper-main/src/components/Datetime.tsx
rename to src/components/Datetime.tsx
diff --git a/astro/astro-paper-main/src/components/Footer.astro b/src/components/Footer.astro
similarity index 100%
rename from astro/astro-paper-main/src/components/Footer.astro
rename to src/components/Footer.astro
diff --git a/astro/astro-paper-main/src/components/Header.astro b/src/components/Header.astro
similarity index 100%
rename from astro/astro-paper-main/src/components/Header.astro
rename to src/components/Header.astro
diff --git a/astro/astro-paper-main/src/components/Hr.astro b/src/components/Hr.astro
similarity index 100%
rename from astro/astro-paper-main/src/components/Hr.astro
rename to src/components/Hr.astro
diff --git a/astro/astro-paper-main/src/components/LinkButton.astro b/src/components/LinkButton.astro
similarity index 100%
rename from astro/astro-paper-main/src/components/LinkButton.astro
rename to src/components/LinkButton.astro
diff --git a/astro/astro-paper-main/src/components/Pagination.astro b/src/components/Pagination.astro
similarity index 100%
rename from astro/astro-paper-main/src/components/Pagination.astro
rename to src/components/Pagination.astro
diff --git a/astro/astro-paper-main/src/components/Search.tsx b/src/components/Search.tsx
similarity index 100%
rename from astro/astro-paper-main/src/components/Search.tsx
rename to src/components/Search.tsx
diff --git a/astro/astro-paper-main/src/components/ShareLinks.astro b/src/components/ShareLinks.astro
similarity index 100%
rename from astro/astro-paper-main/src/components/ShareLinks.astro
rename to src/components/ShareLinks.astro
diff --git a/astro/astro-paper-main/src/components/Socials.astro b/src/components/Socials.astro
similarity index 100%
rename from astro/astro-paper-main/src/components/Socials.astro
rename to src/components/Socials.astro
diff --git a/astro/astro-paper-main/src/components/Tag.astro b/src/components/Tag.astro
similarity index 100%
rename from astro/astro-paper-main/src/components/Tag.astro
rename to src/components/Tag.astro
diff --git a/astro/astro-paper-main/src/config.ts b/src/config.ts
similarity index 100%
rename from astro/astro-paper-main/src/config.ts
rename to src/config.ts
diff --git a/astro/astro-paper-main/src/content/blog/easy-spring-rest-client-with-oauth2.md b/src/content/blog/easy-spring-rest-client-with-oauth2.md
similarity index 100%
rename from astro/astro-paper-main/src/content/blog/easy-spring-rest-client-with-oauth2.md
rename to src/content/blog/easy-spring-rest-client-with-oauth2.md
diff --git a/astro/astro-paper-main/src/content/blog/graalvm-native-image-reflect-config-demystified.md b/src/content/blog/graalvm-native-image-reflect-config-demystified.md
similarity index 100%
rename from astro/astro-paper-main/src/content/blog/graalvm-native-image-reflect-config-demystified.md
rename to src/content/blog/graalvm-native-image-reflect-config-demystified.md
diff --git a/astro/astro-paper-main/src/content/blog/homelab-drives-and-buying-used.md b/src/content/blog/homelab-drives-and-buying-used.md
similarity index 100%
rename from astro/astro-paper-main/src/content/blog/homelab-drives-and-buying-used.md
rename to src/content/blog/homelab-drives-and-buying-used.md
diff --git a/astro/astro-paper-main/src/content/blog/java-streams-gather-Jdk-23.md b/src/content/blog/java-streams-gather-Jdk-23.md
similarity index 100%
rename from astro/astro-paper-main/src/content/blog/java-streams-gather-Jdk-23.md
rename to src/content/blog/java-streams-gather-Jdk-23.md
diff --git a/astro/astro-paper-main/src/content/blog/logging-request-body-with-spring-webclient.md b/src/content/blog/logging-request-body-with-spring-webclient.md
similarity index 100%
rename from astro/astro-paper-main/src/content/blog/logging-request-body-with-spring-webclient.md
rename to src/content/blog/logging-request-body-with-spring-webclient.md
diff --git a/astro/astro-paper-main/src/content/blog/microservice-spring-boot-2-to-3-graalvm-native-image-conversion.md b/src/content/blog/microservice-spring-boot-2-to-3-graalvm-native-image-conversion.md
similarity index 100%
rename from astro/astro-paper-main/src/content/blog/microservice-spring-boot-2-to-3-graalvm-native-image-conversion.md
rename to src/content/blog/microservice-spring-boot-2-to-3-graalvm-native-image-conversion.md
diff --git a/astro/astro-paper-main/src/content/blog/my-first-post.md b/src/content/blog/my-first-post.md
similarity index 100%
rename from astro/astro-paper-main/src/content/blog/my-first-post.md
rename to src/content/blog/my-first-post.md
diff --git a/astro/astro-paper-main/src/content/blog/partitioning-tables-with-postgres.md b/src/content/blog/partitioning-tables-with-postgres.md
similarity index 100%
rename from astro/astro-paper-main/src/content/blog/partitioning-tables-with-postgres.md
rename to src/content/blog/partitioning-tables-with-postgres.md
diff --git a/astro/astro-paper-main/src/content/blog/scs-record-recoverable-processor-error-handling.md b/src/content/blog/scs-record-recoverable-processor-error-handling.md
similarity index 100%
rename from astro/astro-paper-main/src/content/blog/scs-record-recoverable-processor-error-handling.md
rename to src/content/blog/scs-record-recoverable-processor-error-handling.md
diff --git a/astro/astro-paper-main/src/content/blog/the-cat-door.md b/src/content/blog/the-cat-door.md
similarity index 100%
rename from astro/astro-paper-main/src/content/blog/the-cat-door.md
rename to src/content/blog/the-cat-door.md
diff --git a/astro/astro-paper-main/src/content/config.ts b/src/content/config.ts
similarity index 100%
rename from astro/astro-paper-main/src/content/config.ts
rename to src/content/config.ts
diff --git a/astro/astro-paper-main/src/env.d.ts b/src/env.d.ts
similarity index 100%
rename from astro/astro-paper-main/src/env.d.ts
rename to src/env.d.ts
diff --git a/astro/astro-paper-main/src/layouts/AboutLayout.astro b/src/layouts/AboutLayout.astro
similarity index 100%
rename from astro/astro-paper-main/src/layouts/AboutLayout.astro
rename to src/layouts/AboutLayout.astro
diff --git a/astro/astro-paper-main/src/layouts/GoogleAnalytics.astro b/src/layouts/GoogleAnalytics.astro
similarity index 100%
rename from astro/astro-paper-main/src/layouts/GoogleAnalytics.astro
rename to src/layouts/GoogleAnalytics.astro
diff --git a/astro/astro-paper-main/src/layouts/Layout.astro b/src/layouts/Layout.astro
similarity index 100%
rename from astro/astro-paper-main/src/layouts/Layout.astro
rename to src/layouts/Layout.astro
diff --git a/astro/astro-paper-main/src/layouts/Main.astro b/src/layouts/Main.astro
similarity index 100%
rename from astro/astro-paper-main/src/layouts/Main.astro
rename to src/layouts/Main.astro
diff --git a/astro/astro-paper-main/src/layouts/PostDetails.astro b/src/layouts/PostDetails.astro
similarity index 100%
rename from astro/astro-paper-main/src/layouts/PostDetails.astro
rename to src/layouts/PostDetails.astro
diff --git a/astro/astro-paper-main/src/layouts/Posts.astro b/src/layouts/Posts.astro
similarity index 100%
rename from astro/astro-paper-main/src/layouts/Posts.astro
rename to src/layouts/Posts.astro
diff --git a/astro/astro-paper-main/src/layouts/TagPosts.astro b/src/layouts/TagPosts.astro
similarity index 100%
rename from astro/astro-paper-main/src/layouts/TagPosts.astro
rename to src/layouts/TagPosts.astro
diff --git a/astro/astro-paper-main/src/pages/404.astro b/src/pages/404.astro
similarity index 100%
rename from astro/astro-paper-main/src/pages/404.astro
rename to src/pages/404.astro
diff --git a/astro/astro-paper-main/src/pages/about.md b/src/pages/about.md
similarity index 100%
rename from astro/astro-paper-main/src/pages/about.md
rename to src/pages/about.md
diff --git a/astro/astro-paper-main/src/pages/index.astro b/src/pages/index.astro
similarity index 100%
rename from astro/astro-paper-main/src/pages/index.astro
rename to src/pages/index.astro
diff --git a/astro/astro-paper-main/src/pages/og.png.ts b/src/pages/og.png.ts
similarity index 100%
rename from astro/astro-paper-main/src/pages/og.png.ts
rename to src/pages/og.png.ts
diff --git a/astro/astro-paper-main/src/pages/posts/[...page].astro b/src/pages/posts/[...page].astro
similarity index 100%
rename from astro/astro-paper-main/src/pages/posts/[...page].astro
rename to src/pages/posts/[...page].astro
diff --git a/astro/astro-paper-main/src/pages/posts/[page].astro b/src/pages/posts/[page].astro
similarity index 100%
rename from astro/astro-paper-main/src/pages/posts/[page].astro
rename to src/pages/posts/[page].astro
diff --git a/astro/astro-paper-main/src/pages/posts/[slug]/index.astro b/src/pages/posts/[slug]/index.astro
similarity index 100%
rename from astro/astro-paper-main/src/pages/posts/[slug]/index.astro
rename to src/pages/posts/[slug]/index.astro
diff --git a/astro/astro-paper-main/src/pages/posts/[slug]/index.png.ts b/src/pages/posts/[slug]/index.png.ts
similarity index 100%
rename from astro/astro-paper-main/src/pages/posts/[slug]/index.png.ts
rename to src/pages/posts/[slug]/index.png.ts
diff --git a/astro/astro-paper-main/src/pages/robots.txt.ts b/src/pages/robots.txt.ts
similarity index 100%
rename from astro/astro-paper-main/src/pages/robots.txt.ts
rename to src/pages/robots.txt.ts
diff --git a/astro/astro-paper-main/src/pages/rss.xml.ts b/src/pages/rss.xml.ts
similarity index 100%
rename from astro/astro-paper-main/src/pages/rss.xml.ts
rename to src/pages/rss.xml.ts
diff --git a/astro/astro-paper-main/src/pages/search.astro b/src/pages/search.astro
similarity index 100%
rename from astro/astro-paper-main/src/pages/search.astro
rename to src/pages/search.astro
diff --git a/astro/astro-paper-main/src/pages/tags/[tag]/[...page].astro b/src/pages/tags/[tag]/[...page].astro
similarity index 100%
rename from astro/astro-paper-main/src/pages/tags/[tag]/[...page].astro
rename to src/pages/tags/[tag]/[...page].astro
diff --git a/astro/astro-paper-main/src/pages/tags/[tag]/[page].astro b/src/pages/tags/[tag]/[page].astro
similarity index 100%
rename from astro/astro-paper-main/src/pages/tags/[tag]/[page].astro
rename to src/pages/tags/[tag]/[page].astro
diff --git a/astro/astro-paper-main/src/pages/tags/index.astro b/src/pages/tags/index.astro
similarity index 100%
rename from astro/astro-paper-main/src/pages/tags/index.astro
rename to src/pages/tags/index.astro
diff --git a/astro/astro-paper-main/src/styles/base.css b/src/styles/base.css
similarity index 100%
rename from astro/astro-paper-main/src/styles/base.css
rename to src/styles/base.css
diff --git a/astro/astro-paper-main/src/types.ts b/src/types.ts
similarity index 100%
rename from astro/astro-paper-main/src/types.ts
rename to src/types.ts
diff --git a/astro/astro-paper-main/src/utils/generateOgImages.tsx b/src/utils/generateOgImages.tsx
similarity index 100%
rename from astro/astro-paper-main/src/utils/generateOgImages.tsx
rename to src/utils/generateOgImages.tsx
diff --git a/astro/astro-paper-main/src/utils/getPostsByTag.ts b/src/utils/getPostsByTag.ts
similarity index 100%
rename from astro/astro-paper-main/src/utils/getPostsByTag.ts
rename to src/utils/getPostsByTag.ts
diff --git a/astro/astro-paper-main/src/utils/getSortedPosts.ts b/src/utils/getSortedPosts.ts
similarity index 100%
rename from astro/astro-paper-main/src/utils/getSortedPosts.ts
rename to src/utils/getSortedPosts.ts
diff --git a/astro/astro-paper-main/src/utils/getUniqueTags.ts b/src/utils/getUniqueTags.ts
similarity index 100%
rename from astro/astro-paper-main/src/utils/getUniqueTags.ts
rename to src/utils/getUniqueTags.ts
diff --git a/astro/astro-paper-main/src/utils/loadGoogleFont.ts b/src/utils/loadGoogleFont.ts
similarity index 100%
rename from astro/astro-paper-main/src/utils/loadGoogleFont.ts
rename to src/utils/loadGoogleFont.ts
diff --git a/astro/astro-paper-main/src/utils/og-templates/post.tsx b/src/utils/og-templates/post.tsx
similarity index 100%
rename from astro/astro-paper-main/src/utils/og-templates/post.tsx
rename to src/utils/og-templates/post.tsx
diff --git a/astro/astro-paper-main/src/utils/og-templates/site.tsx b/src/utils/og-templates/site.tsx
similarity index 100%
rename from astro/astro-paper-main/src/utils/og-templates/site.tsx
rename to src/utils/og-templates/site.tsx
diff --git a/astro/astro-paper-main/src/utils/postFilter.ts b/src/utils/postFilter.ts
similarity index 100%
rename from astro/astro-paper-main/src/utils/postFilter.ts
rename to src/utils/postFilter.ts
diff --git a/astro/astro-paper-main/src/utils/slugify.ts b/src/utils/slugify.ts
similarity index 100%
rename from astro/astro-paper-main/src/utils/slugify.ts
rename to src/utils/slugify.ts
diff --git a/astro/astro-paper-main/tailwind.config.cjs b/tailwind.config.cjs
similarity index 100%
rename from astro/astro-paper-main/tailwind.config.cjs
rename to tailwind.config.cjs
diff --git a/astro/astro-paper-main/tsconfig.json b/tsconfig.json
similarity index 100%
rename from astro/astro-paper-main/tsconfig.json
rename to tsconfig.json