my page ollie.earth
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 347 lines 9.4 kB view raw
1import blogatto 2import blogatto/config 3import blogatto/config/markdown 4import blogatto/config/robots 5import blogatto/post 6import glaze/oat/badge 7import glaze/oat/theme 8import gleam/list 9import gleam/option.{None, Some} 10import gleam/time/timestamp 11import lustre/attribute.{attribute} 12import lustre/element.{type Element} 13import lustre/element/html 14import page/svgs 15 16pub fn main() -> Nil { 17 let assert Ok(Nil) = blogatto.build(config()) 18 Nil 19} 20 21pub fn config() -> config.Config(Nil) { 22 let robots = 23 robots.new("https://ollie.earth") 24 |> robots.robot( 25 robots.Robot(user_agent: "*", allowed_routes: [], disallowed_routes: [ 26 "/", 27 "*", 28 "/*", 29 ]), 30 ) 31 32 let md = 33 markdown.default() 34 |> markdown.markdown_path("./blog") 35 |> markdown.route_prefix("blog") 36 |> markdown.template(fn(post, _posts) { page(post.contents) }) 37 38 config.new("https://page.ollie.earth") 39 |> config.output_dir("./dist") 40 |> config.static_dir("./static") 41 |> config.markdown(md) 42 |> config.robots(robots) 43 |> config.route("/", home_view) 44} 45 46fn page(content) { 47 html.html([attribute.lang("en")], [ 48 html.head([], [ 49 html.meta([ 50 attribute.name("viewport"), 51 attribute.content("width=device-width, initial-scale=1.0"), 52 ]), 53 54 html.meta([ 55 attribute.content("ollie@sharkey.mar.ollie.earth"), 56 attribute.name("fediverse:creator"), 57 ]), 58 59 html.link([ 60 attribute.rel("me"), 61 attribute.href("https://sharkey.mar.ollie.earth/@ollie"), 62 ]), 63 64 html.title([], "ollie.earth"), 65 html.link([ 66 attribute.rel("icon"), 67 attribute.href("/media/small_snoot_round.png"), 68 ]), 69 70 html.link([ 71 attribute.rel("stylesheet"), 72 attribute.href("/oat.min.css"), 73 ]), 74 html.script( 75 [ 76 attribute.attribute("defer", "defer"), 77 attribute.src("/oat.min.js"), 78 ], 79 "", 80 ), 81 font(), 82 theme.style_tag( 83 theme.default_theme() 84 |> theme.set(theme.Background, "light-dark(#f9f6f1, #09090b)") 85 |> theme.set(theme.Foreground, "light-dark(#f67cbc, #fafafa)") 86 |> theme.set(theme.Primary, "light-dark(#9ceca6, #fafafa)") 87 |> theme.set(theme.PrimaryForeground, "light-dark(#624226, #18181b)") 88 |> theme.set(theme.Muted, "light-dark(#f9f6f1, #27272a)") 89 |> theme.set(theme.MutedForeground, "light-dark(#ffc8e8, #a1a1aa)") 90 |> theme.set(theme.FontSans, "Papernotes") 91 |> theme.set(theme.FontMono, "Papernotes"), 92 ), 93 html.link([ 94 attribute.rel("stylesheet"), 95 attribute.href("/style.css"), 96 ]), 97 ]), 98 html.body([], [ 99 html.div( 100 [attribute.class("container"), attribute.style("max-width", "850px")], 101 content, 102 ), 103 ]), 104 ]) 105} 106 107fn home_view(posts: List(post.Post(Nil))) -> Element(Nil) { 108 let sorted = list.sort(posts, fn(a, b) { timestamp.compare(b.date, a.date) }) 109 110 page([ 111 html.nav([attribute.attribute("data-topnav", "")], [ 112 html.div([attribute.class("hstack")], [ 113 html.div([attribute.class("hstack")], [ 114 link_icon( 115 to: "ollie.earth", 116 at: "https://ollie.earth", 117 with_image: "/media/small_snoot_round.png", 118 size: Small, 119 scaling: None, 120 ), 121 html.div([attribute.style("font-size", "var(--text-2)")], [ 122 element.text("ollie.earth"), 123 ]), 124 ]), 125 html.div( 126 [ 127 attribute.class("hstack hide-s"), 128 ], 129 [ 130 html.a([attribute.href("https://en.pronouns.page/@liiv")], [ 131 badge.badge([], [element.text("pronouns")]), 132 ]), 133 html.a([attribute.href("https://www.last.fm/user/nnuuvv")], [ 134 badge.badge([], [element.text("lastfm")]), 135 ]), 136 ], 137 ), 138 // socials(Some("hide-md"), Size(26, 26)), 139 ]), 140 ]), 141 html.main([], [ 142 html.div([attribute.class("container")], [ 143 html.h3([], [element.text("hi there!")]), 144 html.p([], [ 145 element.text("im ollie, a developer from germany"), 146 html.br([]), 147 element.text("welcome to my little corner of the internet"), 148 ]), 149 html.p([], [ 150 element.text( 151 "i enjoy backend development, devops, self hosting and, these days, occasionally gaming", 152 ), 153 html.br([]), 154 element.text( 155 "you can find my public facing services below (the ones i remembered to put here at least...)", 156 ), 157 ]), 158 159 html.hr([]), 160 161 html.section([], [ 162 html.h3([], [element.text("stuff hosted by me")]), 163 html.div([attribute.class("hstack")], [ 164 svgs.services(None, svgs.Size(3.25, 3.25)), 165 ]), 166 ]), 167 168 html.hr([]), 169 170 html.section([], [ 171 html.h3([], [element.text("people and projects i like")]), 172 html.div([attribute.class("hstack")], [ 173 link_icon( 174 to: "mar", 175 at: "https://strawmelonjuice.com", 176 with_image: "https://strawmelonjuice.com/strawmelonjuice.svg", 177 size: Large, 178 scaling: None, 179 ), 180 link_icon( 181 to: "gleam", 182 at: "https://gleam.run", 183 with_image: "/media/lucy.svg", 184 size: Large, 185 scaling: Some(Scaling(Some("auto"), Some("85%"))), 186 ), 187 link_icon( 188 to: "lustre", 189 at: "https://github.com/lustre-labs", 190 with_image: "/media/lustre.png", 191 size: Large, 192 scaling: None, 193 ), 194 // louis 195 // giacomo 196 // hayleigh 197 // mar 198 // gleam 199 // lustre 200 ]), 201 ]), 202 203 html.hr([]), 204 205 html.section([], [ 206 html.h3([], [element.text("me in other places")]), 207 svgs.socials(None, svgs.Size(3.25, 3.25)), 208 ]), 209 210 html.hr([]), 211 212 html.h3([], [ 213 element.text("this is where id put my blog posts..."), 214 ]), 215 element.text("IF I HAD ANY!"), 216 217 // html.img([attribute.src("/media/ref.png")]), 218 // html.img([attribute.src("/media/puppy.png")]), 219 html.ul( 220 [], 221 list.map(sorted, fn(p) { 222 html.li([], [ 223 html.a([attribute.href("/blog/" <> p.slug)], [ 224 element.text(p.title), 225 ]), 226 ]) 227 }), 228 ), 229 230 html.footer([attribute.class("footer text-light")], [ 231 html.p([], [ 232 element.text("made with "), 233 html.a([attribute.href("https://gleam.run")], [ 234 element.text("gleam"), 235 ]), 236 element.text(" using "), 237 html.a([attribute.href("https://blogat.to")], [ 238 element.text("blogatto"), 239 ]), 240 element.text(", "), 241 html.a([attribute.href("https://oat.ink")], [ 242 element.text("oat ui"), 243 ]), 244 245 element.text(" and "), 246 html.a( 247 [ 248 attribute.href( 249 "https://github.com/daniellionel01/glaze/tree/main/glaze_oat", 250 ), 251 ], 252 [ 253 element.text("glaze_oat"), 254 ], 255 ), 256 ]), 257 258 html.div([attribute.class("carbonbadge"), attribute.id("wcb")], []), 259 html.script( 260 [ 261 attribute("defer", ""), 262 attribute.src( 263 "https://unpkg.com/website-carbon-badges@1.1.3/b.min.js", 264 ), 265 ], 266 "", 267 ), 268 ]), 269 ]), 270 ]), 271 ]) 272} 273 274fn font() -> Element(Nil) { 275 html.style( 276 [attribute.type_("text/css")], 277 " 278@font-face { 279 font-family: \"Papernotes\"; 280 font-display: swap; 281 src: url('/fonts/Papernotes.woff2') format(\"woff2\"); 282} 283 284* { 285 font-family: \"Papernotes\" !important; 286} 287", 288 ) 289} 290 291type Size { 292 Small 293 Normal 294 Large 295} 296 297type Scaling { 298 Scaling(width: option.Option(String), height: option.Option(String)) 299} 300 301fn scaling_to_style(scaling: Scaling) -> attribute.Attribute(a) { 302 let Scaling(width:, height:) = scaling 303 304 let width = width |> option.unwrap("100%") 305 let height = height |> option.unwrap("100%") 306 307 attribute.styles([#("width", width), #("height", height)]) 308} 309 310fn link_icon( 311 to target_name: String, 312 at target_link: String, 313 with_image image_source: String, 314 size size: Size, 315 scaling scaling: option.Option(Scaling), 316) -> Element(_) { 317 html.a( 318 [ 319 attribute.href(target_link), 320 attribute.target("_blank"), 321 attribute.style("width", "fit-content"), 322 attribute.style("height", "fit-content"), 323 ], 324 [ 325 html.figure( 326 [ 327 attribute.attribute("data-variant", "avatar"), 328 attribute.style("display", "flex"), 329 attribute.class(case size { 330 Small -> "small" 331 Normal -> "normal" 332 Large -> "large" 333 }), 334 attribute.aria_label(target_name), 335 ], 336 [ 337 html.img([ 338 option.map(scaling, scaling_to_style) 339 |> option.unwrap(attribute.none()), 340 attribute.src(image_source), 341 attribute.alt(target_name), 342 ]), 343 ], 344 ), 345 ], 346 ) 347}