An ATProtocol powered blogging engine.

refactor: Minor template cleanup for SEO

Changed files
+46 -35
src
templates
+4 -33
src/http.rs
··· 82 slug: String, 83 title: String, 84 created_at: String, 85 } 86 87 impl TryFrom<Post> for PostDisplay { ··· 89 90 fn try_from(post: Post) -> Result<Self> { 91 Ok(PostDisplay { 92 slug: format!("{}-{}", post.record_key, post.slug), 93 title: post.title, 94 created_at: post.created_at.format("%Y-%m-%d %H:%M UTC").to_string(), 95 }) 96 } 97 } ··· 304 .map(PostDisplay::try_from) 305 .collect::<Result<Vec<_>>>() 306 } 307 - 308 - #[cfg(test)] 309 - mod tests { 310 - use super::*; 311 - use crate::storage::Post; 312 - use chrono::Utc; 313 - use serde_json::Value; 314 - 315 - #[tokio::test] 316 - async fn test_post_display_creation() { 317 - let post = Post { 318 - aturi: "at://did:plc:test/com.example.blog/post1".to_string(), 319 - cid: "bafy123".to_string(), 320 - title: "Test Post".to_string(), 321 - slug: "test-post".to_string(), 322 - content: "bafy456".to_string(), 323 - record_key: "post1".to_string(), 324 - created_at: Utc::now(), 325 - updated_at: Utc::now(), 326 - record: Value::Null, 327 - }; 328 - 329 - let display = PostDisplay { 330 - slug: post.slug, 331 - title: post.title, 332 - created_at: post.created_at.format("%Y-%m-%d %H:%M UTC").to_string(), 333 - }; 334 - 335 - assert_eq!(display.slug, "test-post"); 336 - assert_eq!(display.title, "Test Post"); 337 - assert!(display.created_at.contains("UTC")); 338 - } 339 - }
··· 82 slug: String, 83 title: String, 84 created_at: String, 85 + created_at_date: String, 86 + aturi: String, 87 } 88 89 impl TryFrom<Post> for PostDisplay { ··· 91 92 fn try_from(post: Post) -> Result<Self> { 93 Ok(PostDisplay { 94 + aturi: post.aturi, 95 slug: format!("{}-{}", post.record_key, post.slug), 96 title: post.title, 97 created_at: post.created_at.format("%Y-%m-%d %H:%M UTC").to_string(), 98 + created_at_date: post.created_at.format("%Y-%m-%d").to_string(), 99 }) 100 } 101 } ··· 308 .map(PostDisplay::try_from) 309 .collect::<Result<Vec<_>>>() 310 }
+20 -1
templates/index.html
··· 2 {% block title %}Smoke Signal Blog{% endblock %} 3 {% block head %} 4 <meta name="description" content="The Smoke Signal Events blog."> 5 - <link rel="canonical" href="{{ external_base }}/"> 6 <meta property="og:title" content="Smoke Signal Events Blog" /> 7 <meta property="og:type" content="website" /> 8 <meta property="og:url" content="{{ external_base }}/" /> 9 <meta property="og:description" content="The Smoke Signal Events blog." /> 10 <meta property="og:site_name" content="Smoke Signal Events Blog" /> 11 {% endblock %} 12 {% block content %} 13 <main>
··· 2 {% block title %}Smoke Signal Blog{% endblock %} 3 {% block head %} 4 <meta name="description" content="The Smoke Signal Events blog."> 5 <meta property="og:title" content="Smoke Signal Events Blog" /> 6 <meta property="og:type" content="website" /> 7 <meta property="og:url" content="{{ external_base }}/" /> 8 <meta property="og:description" content="The Smoke Signal Events blog." /> 9 <meta property="og:site_name" content="Smoke Signal Events Blog" /> 10 + <link rel="canonical" href="{{ external_base }}/"> 11 + <script type="application/ld+json"> 12 + { 13 + "@context": "https://schema.org", 14 + "@type": "Blog", 15 + "name": "Smoke Signal Events Blog", 16 + "description": "The Smoke Signal Events blog.", 17 + "url": "{{ external_base }}/", 18 + "author": { 19 + "@type": "Person", 20 + "name": "Nick Gerakines", 21 + "url": "https://bsky.app/profile/ngerakines.me" 22 + }, 23 + "publisher": { 24 + "@type": "Organization", 25 + "name": "Smoke Signal", 26 + "url": "https://bsky.app/profile/smokesignal.events" 27 + } 28 + } 29 + </script> 30 {% endblock %} 31 {% block content %} 32 <main>
+22 -1
templates/post.html
··· 2 {% block title %}{{ post.title }} - Blahg{% endblock %} 3 {% block head %} 4 <meta name="description" content="{{ post.title }} posted by @smokesignal.events on {{ post.created_at }}"> 5 - <link rel="canonical" href="{{ external_base }}/"> 6 <meta property="og:title" content="{{ post.title }}" /> 7 <meta property="og:type" content="website" /> 8 <meta property="og:url" content="{{ external_base }}/posts/{{ post.slug }}" /> 9 <meta property="og:description" content="{{ post.title }} posted by @smokesignal.events on {{ post.created_at }}" /> 10 <meta property="og:site_name" content="Smoke Signal Events Blog" /> 11 {% endblock %} 12 {% block content %} 13 <main>
··· 2 {% block title %}{{ post.title }} - Blahg{% endblock %} 3 {% block head %} 4 <meta name="description" content="{{ post.title }} posted by @smokesignal.events on {{ post.created_at }}"> 5 <meta property="og:title" content="{{ post.title }}" /> 6 <meta property="og:type" content="website" /> 7 <meta property="og:url" content="{{ external_base }}/posts/{{ post.slug }}" /> 8 <meta property="og:description" content="{{ post.title }} posted by @smokesignal.events on {{ post.created_at }}" /> 9 <meta property="og:site_name" content="Smoke Signal Events Blog" /> 10 + <link rel="canonical" href="{{ external_base }}/posts/{{ post.slug }}"> 11 + <link rel="alternate" href="{{ post.aturi }}" /> 12 + <script type="application/ld+json"> 13 + { 14 + "@context": "https://schema.org", 15 + "@type": "BlogPosting", 16 + "headline": "{{ post.title }}", 17 + "datePublished": "{{ post.created_at_date }}", 18 + "dateModified": "{{ post.created_at_date }}", 19 + "url": "{{ external_base }}/posts/{{ post.slug }}", 20 + "author": { 21 + "@type": "Person", 22 + "name": "Nick Gerakines", 23 + "url": "https://bsky.app/profile/ngerakines.me" 24 + }, 25 + "publisher": { 26 + "@type": "Organization", 27 + "name": "Smoke Signal", 28 + "url": "https://bsky.app/profile/smokesignal.events" 29 + } 30 + } 31 + </script> 32 {% endblock %} 33 {% block content %} 34 <main>