diff --git a/.gitignore b/.gitignore index 10166c2..e007998 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .DS_Store /target/ -/config.kdl \ No newline at end of file +/config.kdl +/static/fonts/ diff --git a/blog_server/src/main.rs b/blog_server/src/main.rs index 4d12e67..9e2c7de 100644 --- a/blog_server/src/main.rs +++ b/blog_server/src/main.rs @@ -3,7 +3,8 @@ mod fs_watcher; mod post; mod posts_store; mod render; -mod services; +mod service; +mod template; use std::{env, fs, path::PathBuf, thread}; @@ -79,7 +80,7 @@ fn main() -> miette::Result<()> { } async fn run(config: Config, posts_store: ConcurrentPostsStore) -> miette::Result<()> { - let service = services::site_service( + let service = service::site_service( posts_store, &config.static_dir, config.concurrency_limit diff --git a/blog_server/src/service/index.rs b/blog_server/src/service/index.rs new file mode 100644 index 0000000..90047b3 --- /dev/null +++ b/blog_server/src/service/index.rs @@ -0,0 +1,52 @@ +use axum::extract::Extension; +use maud::html; + +use crate::{ + posts_store::ConcurrentPostsStore, + template, +}; +use super::response::HtmlResponse; + +pub async fn handle(Extension(posts): Extension) -> HtmlResponse { + HtmlResponse::new() + .with_title_static("Placeholder title") + .with_crawler_permissive() + .with_head(html! { + link href="/static/styles/main.css" rel="stylesheet"; + }) + .with_body(template::main_page(html! { + section .content_section { + h2 { "Who I am" } + p { + "Hi! I'm Tom, a computer science student and hobbyist programmer." + } + figure { + img src="/static/images/tombot_450.png" + alt="A drawing by @smolrobots (on Twitter) of me as a robot. It has an \ + egg-shaped body and a smiling face, and is doing a little dance next \ + to a Raspberry Pi." + width="256"; + figcaption { + "Drawn by " + a href="https://twitter.com/smolrobots" { "@smolrobots" } + } + } + } + + section .content_section { + h2 { "Things I've made" } + p { "Todo" } + } + + section .content_section { + h2 { "Articles" } + ul { + @for post in posts.read().await.iter_by_created().rev() { + li { + a href={"/posts/" (post.id_str())} { (post.title()) } + } + } + } + } + })) +} diff --git a/blog_server/src/services/mod.rs b/blog_server/src/service/mod.rs similarity index 100% rename from blog_server/src/services/mod.rs rename to blog_server/src/service/mod.rs diff --git a/blog_server/src/services/posts.rs b/blog_server/src/service/posts.rs similarity index 100% rename from blog_server/src/services/posts.rs rename to blog_server/src/service/posts.rs diff --git a/blog_server/src/services/response.rs b/blog_server/src/service/response.rs similarity index 98% rename from blog_server/src/services/response.rs rename to blog_server/src/service/response.rs index 6fe4ca1..585242e 100644 --- a/blog_server/src/services/response.rs +++ b/blog_server/src/service/response.rs @@ -131,6 +131,7 @@ impl IntoResponse for HtmlResponse { head { meta charset="utf-8"; meta name="robots" content=(self.crawler_hints); + meta name="viewport" content="width=device-width, initial-scale=1"; title { (self.title) } @if let Some(head) = self.head { (head) diff --git a/blog_server/src/services/site.rs b/blog_server/src/service/site.rs similarity index 100% rename from blog_server/src/services/site.rs rename to blog_server/src/service/site.rs diff --git a/blog_server/src/services/static_content.rs b/blog_server/src/service/static_content.rs similarity index 100% rename from blog_server/src/services/static_content.rs rename to blog_server/src/service/static_content.rs diff --git a/blog_server/src/services/index.rs b/blog_server/src/services/index.rs deleted file mode 100644 index 293a739..0000000 --- a/blog_server/src/services/index.rs +++ /dev/null @@ -1,24 +0,0 @@ -use axum::extract::Extension; -use maud::html; - -use crate::posts_store::ConcurrentPostsStore; -use super::response::HtmlResponse; - -pub async fn handle(Extension(posts): Extension) -> HtmlResponse { - HtmlResponse::new() - .with_title_static("Placeholder title") - .with_crawler_permissive() - .with_body(html! { - h1 { "Here is my great heading" } - p { "Hello world" } - ul { - @for post in posts.read().await.iter_by_created().rev() { - li { - a href={ "/posts/" (post.id_str()) } { - (post.title()) - }; - } - } - } - }) -} diff --git a/blog_server/src/template.rs b/blog_server/src/template.rs new file mode 100644 index 0000000..e0cd44f --- /dev/null +++ b/blog_server/src/template.rs @@ -0,0 +1,34 @@ +use maud::{html, Markup}; + +pub fn main_page(content: Markup) -> Markup { + html! { + header #page_header .sticky_header { + nav #page_nav { + #title_box { + a href="/" { "Pantonshire" } + } + #right_nav_box { + ul { + li { a href="/" { "Articles" } } + li { a href="/" { "Atom" } } + li { a href="/" { "RSS" } } + li { a href="/" { "GitHub" } } + li { a href="/" { "Contact" } } + } + } + } + } + + main #page_main { + #content { + (content) + } + } + + footer #page_footer { + #page_footer_content { + span { "Here is some footer text" } + } + } + } +} diff --git a/static/images/tombot_450.png b/static/images/tombot_450.png new file mode 100644 index 0000000..1a5b561 Binary files /dev/null and b/static/images/tombot_450.png differ diff --git a/static/style/main.css b/static/style/main.css deleted file mode 100644 index e69de29..0000000 diff --git a/static/style/code.css b/static/styles/code.css similarity index 100% rename from static/style/code.css rename to static/styles/code.css diff --git a/static/styles/main.css b/static/styles/main.css new file mode 100644 index 0000000..5e115b9 --- /dev/null +++ b/static/styles/main.css @@ -0,0 +1,176 @@ +@font-face { + font-family: 'Rubik'; + font-style: normal; + font-weight: 300; + src: local(''), + url('/static/fonts/rubik-v20-latin-300.woff2') format('woff2'), + url('/static/fonts/rubik-v20-latin-300.woff') format('woff'); +} + +@font-face { + font-family: 'Rubik'; + font-style: normal; + font-weight: 700; + src: local(''), + url('/static/fonts/rubik-v20-latin-700.woff2') format('woff2'), + url('/static/fonts/rubik-v20-latin-700.woff') format('woff'); +} + +@font-face { + font-family: 'Rubik'; + font-style: normal; + font-weight: 800; + src: local(''), + url('/static/fonts/rubik-v20-latin-800.woff2') format('woff2'), + url('/static/fonts/rubik-v20-latin-800.woff') format('woff'); +} + +@font-face { + font-family: 'Rubik'; + font-style: italic; + font-weight: 300; + src: local(''), + url('/static/fonts/rubik-v20-latin-300italic.woff2') format('woff2'), + url('/static/fonts/rubik-v20-latin-300italic.woff') format('woff'); +} + +body { + min-height: 100vh; + display: grid; + grid-template-areas: + "header" + "main" + "footer"; + grid-template-columns: 100%; + grid-template-rows: auto 1fr auto; + margin: 0; + padding: 0; + /* font-family: Gill Sans, Gill Sans MT, Calibri, sans-serif; */ + font-family: Rubik, sans-serif; + font-size: 1.1rem; + font-weight: 300; + background-color: #94BFBE; + color: white; +} + +#page_header { + background-color: #94BFBE; + color: white; +} + +#page_nav { + /* background-color: #F7B801; */ + /* background-color: #7678ED; */ + display: flex; + flex-direction: row; + justify-content: space-between; + padding: 1rem 1rem; + margin: 0 auto; + max-width: 60rem; + /* box-shadow: 0px 2px 10px #B8B8B8; */ +} + +#page_nav #title_box { + font-size: 2rem; + font-weight: 800; +} + +#page_nav #right_nav_box { + display: flex; + align-items: center; + flex-direction: row; +} + +#page_nav ul { + list-style-type: none; + display: grid; + grid-template-columns: repeat(5, auto); + grid-template-rows: 100%; + column-gap: 1.5rem; + margin-top: 0; + margin-bottom: 0; + padding: 0; + font-size: 1.5rem; +} + +#page_nav li { + margin: 0; + vertical-align: middle; +} + +#page_nav a { + text-decoration: none; + color: inherit; +} + +#page_main { + background-color: white; + color: black; +} + +#page_footer { + background-color: #94BFBE; + color: white; +} + +#page_footer_content { + padding: 1rem 1rem; + margin: 0 auto; + max-width: 60rem; + color: white; +} + +.sticky_header { + position: sticky; + top: 0; +} + +.offwhite { + background-color: white; + padding: 2rem 8rem; +} + +.textsection { + background-color: #F5F5F0; + padding: 1rem 2rem; + margin-top: 2rem; +} + +#content { + margin: 0 auto; + padding: 2rem 1rem 4rem 1rem; + max-width: 60rem; +} + +.content_section { + margin-bottom: 2rem; +} + +h2 { + margin-top: 0.5rem; + margin-bottom: 0.5rem; +} + +figure { + /* display: flex; + flex-direction: column; */ + width: fit-content; + margin: 0; +} + +figcaption { + text-align: center; + font-size: 0.9rem; + color: #898989; +} + +figcaption a { + color: inherit; +} + +/* +Palette +#94BFBE +#F5F5F0 +#FFFFFF +*/ \ No newline at end of file diff --git a/static/test.html b/static/test.html new file mode 100644 index 0000000..bc1c7cc --- /dev/null +++ b/static/test.html @@ -0,0 +1,87 @@ + + + + + + + + Placeholder title + + + + + + + + + + +
+
+
+

Who I am

+

Hi! I'm Tom, a computer science student and hobbyist programmer.

+ +
+ +
Drawn by @smolrobots
+
+
+ +
+

Things I've made

+

+ Todo + + +

+
+ +
+

Articles

+ +
+
+
+ + + + + \ No newline at end of file