diff --git a/axum_server/src/main.rs b/axum_server/src/main.rs
index f3268e7..2699dd0 100644
--- a/axum_server/src/main.rs
+++ b/axum_server/src/main.rs
@@ -10,6 +10,7 @@ mod pages;
mod post_list;
mod post_parser;
mod router;
+mod tag_list;
// mod template;
#[tokio::main]
diff --git a/axum_server/src/pages/index.rs b/axum_server/src/pages/index.rs
index dec6797..a8a1b49 100644
--- a/axum_server/src/pages/index.rs
+++ b/axum_server/src/pages/index.rs
@@ -1,8 +1,12 @@
use askama::Template;
+use axum::http::StatusCode;
-use crate::components::{
- site_footer::{render_site_footer, SiteFooter},
- site_header::HeaderProps,
+use crate::{
+ components::{
+ site_footer::{render_site_footer, SiteFooter},
+ site_header::HeaderProps,
+ },
+ tag_list::get_popular_blog_tags,
};
#[derive(Template)]
@@ -10,12 +14,24 @@ use crate::components::{
pub struct IndexTemplate {
site_footer: SiteFooter,
header_props: HeaderProps,
+ blog_tags: Vec,
}
-pub async fn render_index() -> IndexTemplate {
- let site_footer = render_site_footer().await;
- IndexTemplate {
+pub async fn render_index() -> Result {
+ let site_footer = tokio::spawn(render_site_footer());
+ let blog_tags = tokio::spawn(get_popular_blog_tags());
+
+ let blog_tags = blog_tags
+ .await
+ .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)??;
+
+ let site_footer = site_footer
+ .await
+ .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;
+
+ Ok(IndexTemplate {
site_footer,
header_props: HeaderProps::default(),
- }
+ blog_tags,
+ })
}
diff --git a/axum_server/src/pages/post_list.rs b/axum_server/src/pages/post_list.rs
index d180fa3..f2599cc 100644
--- a/axum_server/src/pages/post_list.rs
+++ b/axum_server/src/pages/post_list.rs
@@ -51,7 +51,6 @@ pub async fn render_post_list(tag: Option>) -> Result HeaderProps::with_back_link(Link {
href: "/blog".to_string(),
@@ -68,6 +67,3 @@ pub async fn render_post_list(tag: Option>) -> Result Result, StatusCode> {
+ const TAGS_LENGTH: usize = 7;
+
+ let post_list = get_post_list::().await?;
+ let tags_sum = post_list
+ .into_iter()
+ .flat_map(|post| post.metadata.tags)
+ .fold(HashMap::new(), |mut acc, tag| {
+ *acc.entry(tag).or_insert(0) += 1;
+ acc
+ });
+
+ let mut sorted_tags_by_count: Vec<_> = tags_sum.into_iter().collect();
+ sorted_tags_by_count.sort_by_key(|&(_, count)| std::cmp::Reverse(count));
+
+ // Log the counts
+ for (tag, count) in &sorted_tags_by_count {
+ debug!("Tag: {}, Count: {}", tag, count);
+ }
+
+ let popular_blog_tags = sorted_tags_by_count
+ .into_iter()
+ .map(|tag_count| tag_count.0)
+ .filter(|tag| tag != "dev")
+ .take(TAGS_LENGTH)
+ .collect::>();
+
+ Ok(popular_blog_tags)
+}
diff --git a/axum_server/styles/input.css b/axum_server/styles/input.css
index cdc6dc5..db3f070 100644
--- a/axum_server/styles/input.css
+++ b/axum_server/styles/input.css
@@ -2,6 +2,14 @@
@tailwind components;
@tailwind utilities;
+a {
+ @apply text-pink-600 underline underline-offset-2;
+
+ &:hover {
+ @apply transition text-blue-400;
+ }
+}
+
.article-body {
h1 {
@apply px-4 text-2xl text-blue-900 my-2;
diff --git a/axum_server/styles/output.css b/axum_server/styles/output.css
index 06aa446..6d05424 100644
--- a/axum_server/styles/output.css
+++ b/axum_server/styles/output.css
@@ -562,16 +562,50 @@ video {
margin: 1rem;
}
+.m-5 {
+ margin: 1.25rem;
+}
+
+.mx-0 {
+ margin-left: 0px;
+ margin-right: 0px;
+}
+
+.mx-0\.5 {
+ margin-left: 0.125rem;
+ margin-right: 0.125rem;
+}
+
+.mx-2 {
+ margin-left: 0.5rem;
+ margin-right: 0.5rem;
+}
+
.mx-4 {
margin-left: 1rem;
margin-right: 1rem;
}
+.mx-5 {
+ margin-left: 1.25rem;
+ margin-right: 1.25rem;
+}
+
.mx-6 {
margin-left: 1.5rem;
margin-right: 1.5rem;
}
+.my-0 {
+ margin-top: 0px;
+ margin-bottom: 0px;
+}
+
+.my-0\.5 {
+ margin-top: 0.125rem;
+ margin-bottom: 0.125rem;
+}
+
.my-12 {
margin-top: 3rem;
margin-bottom: 3rem;
@@ -587,16 +621,6 @@ video {
margin-bottom: 1.5rem;
}
-.mx-2 {
- margin-left: 0.5rem;
- margin-right: 0.5rem;
-}
-
-.my-2 {
- margin-top: 0.5rem;
- margin-bottom: 0.5rem;
-}
-
.mb-1 {
margin-bottom: 0.25rem;
}
@@ -605,6 +629,10 @@ video {
margin-bottom: 0.75rem;
}
+.mb-5 {
+ margin-bottom: 1.25rem;
+}
+
.mt-3 {
margin-top: 0.75rem;
}
@@ -613,6 +641,10 @@ video {
display: block;
}
+.inline-block {
+ display: inline-block;
+}
+
.inline {
display: inline;
}
@@ -707,6 +739,11 @@ video {
border-color: rgb(59 130 246 / var(--tw-border-opacity));
}
+.border-blue-950 {
+ --tw-border-opacity: 1;
+ border-color: rgb(23 37 84 / var(--tw-border-opacity));
+}
+
.bg-blue-50 {
--tw-bg-opacity: 1;
background-color: rgb(239 246 255 / var(--tw-bg-opacity));
@@ -726,6 +763,14 @@ video {
fill: #172554;
}
+.p-0 {
+ padding: 0px;
+}
+
+.p-0\.5 {
+ padding: 0.125rem;
+}
+
.p-3 {
padding: 0.75rem;
}
@@ -740,16 +785,6 @@ video {
padding-right: 1.25rem;
}
-.py-3 {
- padding-top: 0.75rem;
- padding-bottom: 0.75rem;
-}
-
-.py-4 {
- padding-top: 1rem;
- padding-bottom: 1rem;
-}
-
.py-5 {
padding-top: 1.25rem;
padding-bottom: 1.25rem;
@@ -805,6 +840,10 @@ video {
font-weight: 600;
}
+.capitalize {
+ text-transform: capitalize;
+}
+
.italic {
font-style: italic;
}
@@ -843,6 +882,11 @@ video {
color: rgb(31 41 55 / var(--tw-text-opacity));
}
+.text-pink-950 {
+ --tw-text-opacity: 1;
+ color: rgb(80 7 36 / var(--tw-text-opacity));
+}
+
.drop-shadow-md {
--tw-drop-shadow: drop-shadow(0 4px 3px rgb(0 0 0 / 0.07)) drop-shadow(0 2px 2px rgb(0 0 0 / 0.06));
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
@@ -858,6 +902,24 @@ video {
transition-duration: 150ms;
}
+a {
+ --tw-text-opacity: 1;
+ color: rgb(219 39 119 / var(--tw-text-opacity));
+ text-decoration-line: underline;
+ text-underline-offset: 2px;
+ &:hover {
+ --tw-text-opacity: 1;
+ color: rgb(96 165 250 / var(--tw-text-opacity));
+ }
+ &:hover {
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
+ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
+ transition-duration: 150ms;
+ }
+}
+
.article-body {
h1 {
margin-top: 0.5rem;
@@ -959,11 +1021,6 @@ video {
margin: 1rem;
}
-.hover\:bg-blue-200:hover {
- --tw-bg-opacity: 1;
- background-color: rgb(191 219 254 / var(--tw-bg-opacity));
-}
-
.hover\:bg-pink-200:hover {
--tw-bg-opacity: 1;
background-color: rgb(251 207 232 / var(--tw-bg-opacity));
diff --git a/axum_server/templates/components/talent_card.html b/axum_server/templates/components/talent_card.html
index 7e302c2..8a9df82 100644
--- a/axum_server/templates/components/talent_card.html
+++ b/axum_server/templates/components/talent_card.html
@@ -10,7 +10,7 @@
- {{description}}
+ {{description|safe}}
diff --git a/axum_server/templates/index.html b/axum_server/templates/index.html
index 9301701..187771a 100644
--- a/axum_server/templates/index.html
+++ b/axum_server/templates/index.html
@@ -22,20 +22,38 @@
-About me
+About me
-
+
Welcome to my personal website. My name is
Michal Vanko
and I'm a
programmer
- . I am developing software for more than half of my life and I love it! Sometimes I stream working on my side projects and building a community of like minded people. Here you can find blogs of my thoughts and journeys, as well as links to my socials where you can see other content.
+ . I am developing software for more than half of my life and I love it! Sometimes I stream working on my side projects and building a community of like minded people. Here you can find blogs of my thoughts and journeys, as well as links to my socials where you can see other content.
-
+
{% call tc::talent_card("code", "Web development", "Extensive expertise in creating performant, live web applications and websites") %}
{% call tc::talent_card("gamepad", "Game development", "Extensive expertise in creating performant, live web applications and websites") %}
+ {% call tc::talent_card("person-chalkboard", "Mentoring & Consulting", "I offer consulting sessions to assist you in developing higher-quality software and share insights from crafting robust, professional web applications. Schedule a session with me and elevate your projects together.") %}
+Blog
+
+
+
+
+