My website lesbian.skin
0
fork

Configure Feed

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

Add sketch and create basic projects page

+295 -6
+1 -1
gleam.toml
··· 1 1 name = "website" 2 - target = "javascript" 3 2 version = "1.0.0" 4 3 5 4 [dependencies] 6 5 gleam_stdlib = ">= 0.34.0 and < 2.0.0" 7 6 lustre = ">= 4.2.0 and < 5.0.0" 8 7 birl = ">= 1.6.1 and < 2.0.0" 8 + sketch = ">= 2.1.0 and < 3.0.0" 9 9 10 10 [dev-dependencies] 11 11 gleeunit = ">= 1.0.0 and < 2.0.0"
+5 -1
manifest.toml
··· 12 12 { name = "gleam_crypto", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_crypto", source = "hex", outer_checksum = "ADD058DEDE8F0341F1ADE3AAC492A224F15700829D9A3A3F9ADF370F875C51B7" }, 13 13 { name = "gleam_erlang", version = "0.25.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "054D571A7092D2A9727B3E5D183B7507DAB0DA41556EC9133606F09C15497373" }, 14 14 { name = "gleam_http", version = "3.6.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "8C07DF9DF8CC7F054C650839A51C30A7D3C26482AC241C899C1CEA86B22DBE51" }, 15 + { name = "gleam_javascript", version = "0.8.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_javascript", source = "hex", outer_checksum = "14D5B7E1A70681E0776BF0A0357F575B822167960C844D3D3FA114D3A75F05A8" }, 15 16 { name = "gleam_json", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib", "thoas"], otp_app = "gleam_json", source = "hex", outer_checksum = "9063D14D25406326C0255BDA0021541E797D8A7A12573D849462CAFED459F6EB" }, 16 17 { name = "gleam_otp", version = "0.10.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "0B04FE915ACECE539B317F9652CAADBBC0F000184D586AAAF2D94C100945D72B" }, 17 18 { name = "gleam_package_interface", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_json", "gleam_stdlib"], otp_app = "gleam_package_interface", source = "hex", outer_checksum = "52A721BCA972C8099BB881195D821AAA64B9F2655BECC102165D5A1097731F01" }, ··· 28 29 { name = "lustre_ssg", version = "0.6.1", build_tools = ["gleam"], requirements = ["gleam_stdlib", "jot", "lustre", "simplifile", "tom"], otp_app = "lustre_ssg", source = "hex", outer_checksum = "2C55F49F597DF8FC3FDD651349026FADFD2394763C34BB88BB8A57549E30ECFA" }, 29 30 { name = "marceau", version = "1.1.0", build_tools = ["gleam"], requirements = [], otp_app = "marceau", source = "hex", outer_checksum = "1AAD727A30BE0F95562C3403BB9B27C823797AD90037714255EEBF617B1CDA81" }, 30 31 { name = "mist", version = "1.0.0", build_tools = ["gleam"], requirements = ["birl", "gleam_erlang", "gleam_http", "gleam_otp", "gleam_stdlib", "glisten", "hpack_erl", "logging"], otp_app = "mist", source = "hex", outer_checksum = "7765E53DCC9ACCACF217B8E0CA3DE7E848C783BFAE5118B75011E81C2C80385C" }, 32 + { name = "plinth", version = "0.2.0", build_tools = ["gleam"], requirements = ["gleam_javascript", "gleam_json", "gleam_stdlib"], otp_app = "plinth", source = "hex", outer_checksum = "83211E672D83F3CE14681D0ECD3AD883EE7588E423E7C9DDDB460014AD60AC24" }, 31 33 { name = "ranger", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "ranger", source = "hex", outer_checksum = "1566C272B1D141B3BBA38B25CB761EF56E312E79EC0E2DFD4D3C19FB0CC1F98C" }, 32 34 { name = "repeatedly", version = "2.1.1", build_tools = ["gleam"], requirements = [], otp_app = "repeatedly", source = "hex", outer_checksum = "38808C3EC382B0CD981336D5879C24ECB37FCB9C1D1BD128F7A80B0F74404D79" }, 33 35 { name = "simplifile", version = "1.7.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "1D5DFA3A2F9319EC85825F6ED88B8E449F381B0D55A62F5E61424E748E7DDEB0" }, 36 + { name = "sketch", version = "2.1.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_otp", "gleam_stdlib", "lustre", "plinth"], otp_app = "sketch", source = "hex", outer_checksum = "47175BD019A00CFEAAF2851830825544E24ABA58168083A1D219FA8E06EF6713" }, 34 37 { name = "snag", version = "0.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "snag", source = "hex", outer_checksum = "54D32E16E33655346AA3E66CBA7E191DE0A8793D2C05284E3EFB90AD2CE92BCC" }, 35 38 { name = "spinner", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_community_ansi", "gleam_erlang", "gleam_stdlib", "glearray", "repeatedly"], otp_app = "spinner", source = "hex", outer_checksum = "200BA3D4A04D468898E63C0D316E23F526E02514BC46454091975CB5BAE41E8F" }, 36 39 { name = "thoas", version = "1.2.0", build_tools = ["rebar3"], requirements = [], otp_app = "thoas", source = "hex", outer_checksum = "540C8CB7D9257F2AD0A14145DC23560F91ACDCA995F0CCBA779EB33AF5D859D1" }, ··· 39 42 ] 40 43 41 44 [requirements] 42 - birl = { version = ">= 1.6.1 and < 2.0.0"} 45 + birl = { version = ">= 1.6.1 and < 2.0.0" } 43 46 gleam_stdlib = { version = ">= 0.34.0 and < 2.0.0" } 44 47 gleeunit = { version = ">= 1.0.0 and < 2.0.0" } 45 48 lustre = { version = ">= 4.2.0 and < 5.0.0" } 46 49 lustre_dev_tools = { version = ">= 1.2.2 and < 2.0.0" } 47 50 lustre_ssg = { version = ">= 0.6.1 and < 1.0.0" } 51 + sketch = { version = ">= 2.1.0 and < 3.0.0"}
+19
src/build.gleam
··· 2 2 import gleam/io 3 3 import gleam/list 4 4 import lustre/ssg 5 + import sketch 6 + import sketch/lustre as sklustre 7 + import sketch/options as skoptions 5 8 import website/data/posts 9 + import website/data/projects 6 10 import website/page/blog 7 11 import website/page/index 8 12 import website/page/post 13 + import website/page/project 9 14 10 15 pub fn main() { 16 + let assert Ok(cache) = 17 + skoptions.node() 18 + |> sklustre.setup() 19 + 20 + sketch.prepare(cache) 21 + 11 22 let posts = 12 23 dict.from_list({ 13 24 use post <- list.map(posts.all()) 14 25 #(post.id, post) 15 26 }) 16 27 28 + let projects = 29 + dict.from_list({ 30 + use project <- list.map(projects.all()) 31 + #(project.id, project) 32 + }) 33 + 17 34 let build = 18 35 ssg.new("./out") 19 36 |> ssg.add_static_route("/", index.view()) 20 37 |> ssg.add_static_route("/blog", blog.view(posts.all())) 21 38 |> ssg.add_dynamic_route("/blog", posts, post.view) 39 + |> ssg.add_static_route("/projects", projects.view(projects.all(), cache)) 40 + |> ssg.add_dynamic_route("/projects", projects, project.view) 22 41 |> ssg.build 23 42 24 43 case build {
+1 -4
src/website/data/posts.gleam
··· 2 2 import lustre/attribute 3 3 import lustre/element 4 4 import lustre/element/html 5 + import website/page/index.{link} 5 6 6 7 pub type Post { 7 8 Post( ··· 12 13 summary: element.Element(String), 13 14 content: element.Element(String), 14 15 ) 15 - } 16 - 17 - fn link(text: String, url: String) -> element.Element(a) { 18 - html.a([attribute.href(url)], [element.text(text)]) 19 16 } 20 17 21 18 fn mystcraft_short_descriptor() -> element.Element(String) {
+254
src/website/data/projects.gleam
··· 1 + import gleam/list 2 + import lustre/attribute 3 + import lustre/element 4 + import lustre/element/html 5 + import sketch 6 + import sketch/lustre.{ssr} 7 + import sketch/size.{em, em_} 8 + import website/page/index.{link} 9 + 10 + pub type Link { 11 + Link(title: String, url: String, img: String) 12 + } 13 + 14 + pub type Project { 15 + Project( 16 + id: String, 17 + title: String, 18 + author: String, 19 + img: String, 20 + links: List(Link), 21 + archived: Bool, 22 + summary: element.Element(String), 23 + ) 24 + } 25 + 26 + fn project_class(archived: Bool) -> attribute.Attribute(a) { 27 + let #(bg, bg_hov) = case archived { 28 + True -> #("#cb402b", "#f1553e") 29 + False -> #("#ddd4dd", "#daccda") 30 + } 31 + sketch.class([ 32 + sketch.background(bg), 33 + sketch.padding(em(1)), 34 + sketch.hover([sketch.background(bg_hov)]), 35 + sketch.margin_bottom(em_(0.5)), 36 + sketch.border_radius(em_(0.75)) 37 + ]) 38 + |> sketch.to_lustre 39 + } 40 + 41 + fn icon_class() -> attribute.Attribute(a) { 42 + sketch.class([ 43 + sketch.max_width(em_(3.5)), 44 + sketch.max_height(em_(3.5)), 45 + sketch.border_radius(em_(0.75)), 46 + ]) 47 + |> sketch.to_lustre 48 + } 49 + 50 + fn project_bar_class() -> attribute.Attribute(a) { 51 + sketch.class([ 52 + sketch.display("flex"), 53 + sketch.flex_direction("horizontal"), 54 + sketch.align_items("center"), 55 + sketch.gap(em(1)), 56 + ]) 57 + |> sketch.to_lustre 58 + } 59 + 60 + pub fn view( 61 + projects: List(Project), 62 + cache: sketch.Cache, 63 + ) -> element.Element(String) { 64 + projects 65 + |> list.map(fn(project) { 66 + let links = 67 + project.links 68 + |> list.map(fn(link) { 69 + html.a([attribute.href(link.url)], [ 70 + html.img([ 71 + attribute.alt(link.title), 72 + attribute.src(link.img), 73 + icon_class(), 74 + ]), 75 + ]) 76 + }) 77 + |> html.span([], _) 78 + |> ssr(cache) 79 + sketch.prepare(cache) 80 + html.div([project_class(project.archived)], [ 81 + html.span([project_bar_class()], [ 82 + html.img([attribute.src(project.img), icon_class()]), 83 + html.h2([], [element.text(project.title)]), 84 + links, 85 + ]), 86 + project.summary, 87 + ]) 88 + |> ssr(cache) 89 + }) 90 + |> html.div([], _) 91 + |> ssr(cache) 92 + } 93 + 94 + pub fn all() -> List(Project) { 95 + [ 96 + lilypad(), 97 + caramel(), 98 + mystcraft_ages(), 99 + rpgtitles(), 100 + biomes_only(), 101 + get_pricked(), 102 + asbestos(), 103 + ] 104 + } 105 + 106 + fn curseforge_mod(slug: String) -> Link { 107 + Link( 108 + title: "CurseForge", 109 + url: "https://www.curseforge.com/minecraft/mc-mods/" <> slug, 110 + img: "https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy-minimal/available/curseforge_64h.png", 111 + ) 112 + } 113 + 114 + fn modrinth(slug: String) -> Link { 115 + Link( 116 + title: "Modrinth", 117 + url: "https://mods.gay/" <> slug, 118 + img: "https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy-minimal/available/modrinth_64h.png", 119 + ) 120 + } 121 + 122 + fn codeberg(user: String, repo: String) -> Link { 123 + Link( 124 + title: "Source Code", 125 + url: "https://codeberg.org/" <> user <> "/" <> repo, 126 + img: "https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy-minimal/available/codeberg_64h.png", 127 + ) 128 + } 129 + 130 + fn lilypad() -> Project { 131 + Project( 132 + id: "lilypad", 133 + title: "Lilypad", 134 + author: "naomieow", 135 + img: "https://codeberg.org/repo-avatars/028f375a8ea1cc6fd92e85466b2dfb49247c97f07f66c4dd7d7efb06a8fd3dd6", 136 + links: [codeberg("naomi", "lilypad")], 137 + archived: False, 138 + summary: html.p([], [ 139 + element.text("Lilypad is a general-purpose Discord bot built using "), 140 + link("arikawa", "https://github.com/diamondburned/arikawa/"), 141 + element.text(", mainly for use in my own "), 142 + link("Discord server.", "https://discord.naomieow.xyz/"), 143 + ]), 144 + ) 145 + } 146 + 147 + fn caramel() -> Project { 148 + Project( 149 + id: "caramel", 150 + title: "Caramel", 151 + author: "naomieow", 152 + img: "https://codeberg.org/repo-avatars/1e15f1174f6a90152e3027a13a3727230a32154de6ab12325e6fa25d5a04a5c1", 153 + links: [codeberg("naomi", "caramel")], 154 + archived: False, 155 + summary: html.p([], [ 156 + element.text("A Discord/Revolt bridge using "), 157 + link("arikawa", "https://github.com/diamondburned/arikawa/"), 158 + element.text(" and "), 159 + link("revolt.go", "https://github.com/ben-forster/revolt/"), 160 + ]), 161 + ) 162 + } 163 + 164 + fn mystcraft_ages() -> Project { 165 + Project( 166 + id: "mystcraft_ages", 167 + title: "Mystcraft: Ages", 168 + author: "naomieow", 169 + img: "https://codeberg.org/repo-avatars/de7a4fbec03846014acbbd6751aca89b7e1af056e74cb2750e3d554b5842b1f5", 170 + links: [ 171 + modrinth("ages"), 172 + curseforge_mod("mystcraft-ages"), 173 + codeberg("naomi", "mystcraft-ages"), 174 + ], 175 + archived: False, 176 + summary: html.p([], [ 177 + element.text( 178 + "Mystcraft: Ages is a modern rewrite and reimagining of the original Mystcraft mod.", 179 + ), 180 + ]), 181 + ) 182 + } 183 + 184 + fn rpgtitles() -> Project { 185 + Project( 186 + id: "rpgtitles", 187 + title: "RPGTitles", 188 + author: "naomieow", 189 + img: "https://codeberg.org/repo-avatars/285354680e5bdf1c00b03b453fdb46d8538f371f06ccb7ec85f68681d5f250dd", 190 + links: [ 191 + modrinth("rpgtitles"), 192 + curseforge_mod("rpgtitles"), 193 + codeberg("naomi", "rpgtitles"), 194 + ], 195 + archived: False, 196 + summary: html.p([], [ 197 + element.text( 198 + "Small, cosmetic datapack that adds titles to small things in the game!", 199 + ), 200 + ]), 201 + ) 202 + } 203 + 204 + fn biomes_only() -> Project { 205 + Project( 206 + id: "biomes_only", 207 + title: "Incendium Biomes Only", 208 + author: "naomieow", 209 + img: "./assets/biomes_only.png", 210 + links: [modrinth("ibo"), curseforge_mod("incendium-biomes-only")], 211 + archived: False, 212 + summary: html.p([], [ 213 + element.text( 214 + "Removes structures, items, mobs and bosses from Incendium, leaving only the biomes and terrain.", 215 + ), 216 + ]), 217 + ) 218 + } 219 + 220 + fn get_pricked() -> Project { 221 + Project( 222 + id: "pricked", 223 + title: "Get Pricked!", 224 + author: "naomieow", 225 + img: "https://codeberg.org/repo-avatars/c2ab43e92df20ee1441c1d7a583c5aeaf361c0621d0af2fa5d33d1c5b00bc3b3", 226 + links: [ 227 + modrinth("pricked"), 228 + curseforge_mod("get-pricked"), 229 + codeberg("naomi", "pricked"), 230 + ], 231 + archived: False, 232 + summary: html.p([], [ 233 + element.text( 234 + "Ever been playing the game and thought a block should damage you even though it doesn't? Well, now they do!", 235 + ), 236 + ]), 237 + ) 238 + } 239 + 240 + fn asbestos() -> Project { 241 + Project( 242 + id: "asbestos", 243 + title: "Carcinogenic Fibrous Silicate", 244 + author: "naomieow", 245 + img: "./assets/asbestos.png", 246 + links: [modrinth("cfs")], 247 + archived: True, 248 + summary: html.p([], [ 249 + element.text( 250 + "Small joke mod requested by some friends that adds Asbestos to the game.", 251 + ), 252 + ]), 253 + ) 254 + }
+5
src/website/page/index.gleam
··· 1 1 import lustre/element 2 2 import lustre/element/html 3 + import lustre/attribute 4 + 5 + pub fn link(text: String, url: String) -> element.Element(a) { 6 + html.a([attribute.href(url)], [element.text(text)]) 7 + } 3 8 4 9 pub fn view() -> element.Element(a) { 5 10 html.h1([], [element.text("Index")])
+10
src/website/page/project.gleam
··· 1 + import lustre/element 2 + import lustre/element/html 3 + import website/data/projects.{type Project} 4 + 5 + pub fn view(project: Project) -> element.Element(String) { 6 + html.div([], [ 7 + html.h1([], [element.text(project.title)]), 8 + html.p([], [project.summary]), 9 + ]) 10 + }