the home site for me: also iteration 3 or 4 of my site
4
fork

Configure Feed

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

feat: update og styling

+95 -109
+1 -1
content/blog/_index.md
··· 1 1 +++ 2 - title = "All my writings" 2 + title = "index of /blog" 3 3 sort_by = "date" 4 4 template = "blog.html" 5 5 page_template = "blog-page.html"
+16 -30
scripts/genOG.ts
··· 1 1 import puppeteer from "puppeteer"; 2 2 import { readdir, mkdir, access } from "node:fs/promises"; 3 + import { resolve } from "node:path"; 3 4 4 - const template = await Bun.file("scripts/og.html").text(); 5 + const fontsPath = `file://${resolve("static/fonts")}`; 6 + const template = (await Bun.file("scripts/og.html").text()).replace( 7 + /\{\{fontsPath\}\}/g, 8 + fontsPath, 9 + ); 5 10 6 11 const browser = await puppeteer.launch({ 7 12 args: ["--no-sandbox"], ··· 11 16 async function og( 12 17 postname: string, 13 18 type: string, 14 - by: string | undefined, 15 19 outputPath: string, 16 20 width = 1200, 17 21 height = 630, ··· 24 28 template 25 29 .toString() 26 30 .replace("{{postname}}", postname) 27 - .replace("{{type}}", type) 28 - .replace("{{by}}", by || ""), 31 + .replace("{{type}}", type), 32 + { waitUntil: "load" }, 29 33 ); 30 34 31 35 await page.screenshot({ path: outputPath }); ··· 41 45 } 42 46 43 47 try { 44 - // check if the public/blog folder exists 45 - // if not exit 46 - // if it does, get all the folders and then get the title tag from the index.html 47 - 48 48 if (!(await pathExists("public/"))) { 49 49 console.error("public/ does not exist"); 50 50 process.exit(1); 51 51 } 52 52 53 - // read all the files in the current directory filtering for index.htmls 54 53 const files = (await readdir("public/", { recursive: true })).filter((file) => 55 54 file.endsWith("index.html"), 56 55 ); ··· 63 62 directories.has(file), 64 63 ); 65 64 66 - // create not existing 67 65 for (const dir of directories) { 68 66 if (!existing.includes(dir)) { 69 67 await mkdir(`static/${dir.split("/").slice(0, -1).join("/")}`, { ··· 74 72 75 73 console.log("Generating OG images for", files.length, "files"); 76 74 77 - // for each file, get the title tag from the index.html 78 - for (const file of files) { 75 + const tasks = files.map((file) => async () => { 79 76 const index = await Bun.file(`public/${file}`).text(); 80 77 const title = index.match(/<title>(.*?)<\/title>/)[1]; 81 78 let type = "Page"; 82 - let by: string | undefined; 83 79 switch (file.split("/")[0]) { 84 80 case "blog": 85 - type = "Blog"; 86 - if (file.split("/")[1] !== "index.html") { 87 - by = "<p>A post ... yeah thats about it</p>"; 88 - } else { 89 - by = "<p>All authored by me ... or are they???</p>"; 90 - } 81 + type = file.split("/")[1] !== "index.html" ? "Blog" : "Blog Index"; 91 82 break; 92 83 case "verify": 93 84 type = "Slash Page"; 94 - by = "<p>So you can stalk me 💀</p>"; 95 85 break; 96 86 case "pfp": 97 87 type = "Slash Page"; 98 - by = "<p>Want to stare at my pretty face?</p>"; 99 88 break; 100 89 case "tags": 101 - if (file.split("/")[1] === "index.html") { 102 - type = "Tags"; 103 - by = "<p>A total archive!</p>"; 104 - } else { 105 - type = "Tag"; 106 - by = "<p>Find more posts like this!</p>"; 107 - } 90 + type = file.split("/")[1] === "index.html" ? "Tags" : "Tag"; 108 91 break; 109 92 case "index.html": 110 93 type = "Root"; 111 - by = "<p>Where it all begins</p>"; 112 94 break; 113 95 } 114 96 115 97 console.log("Generating OG for", file, "title:", title, "with type:", type); 116 - await og(title, type, by, `static/${file.replace("index.html", "og.png")}`); 98 + await og(title, type, `static/${file.replace("index.html", "og.png")}`); 99 + }); 100 + 101 + for (let i = 0; i < tasks.length; i += 10) { 102 + await Promise.all(tasks.slice(i, i + 10).map((t) => t())); 117 103 } 118 104 } catch (e) { 119 105 console.error(e);
+78 -78
scripts/og.html
··· 2 2 <html> 3 3 <head> 4 4 <style> 5 - :root, 6 - ::backdrop { 5 + @font-face { 6 + font-family: "Maple Mono"; 7 + src: url("{{fontsPath}}/maple-mono-latin-400-normal.woff2") format("woff2"); 8 + font-weight: 400; 9 + font-style: normal; 10 + } 11 + @font-face { 12 + font-family: "Maple Mono"; 13 + src: url("{{fontsPath}}/maple-mono-latin-400-italic.woff2") format("woff2"); 14 + font-weight: 400; 15 + font-style: italic; 16 + } 17 + @font-face { 18 + font-family: "Maple Mono"; 19 + src: url("{{fontsPath}}/maple-mono-latin-700-normal.woff2") format("woff2"); 20 + font-weight: 700; 21 + font-style: normal; 22 + } 23 + @font-face { 24 + font-family: "Maple Mono"; 25 + src: url("{{fontsPath}}/maple-mono-latin-700-italic.woff2") format("woff2"); 26 + font-weight: 700; 27 + font-style: italic; 28 + } 29 + 30 + :root { 7 31 color-scheme: dark; 8 - --bg: #222529; 9 - --bg-light: #464949; 10 - --text: #d6d6d6; 11 - --text-light: #c5c0b7; 12 - --accent: #78b6ad; 13 - --accent-light: #87c9e5; 14 - --accent-text: var(--bg); 15 - --border: #dbd5bc; 16 - --link: #e2c8a2; 17 - --gradient-average-light: oklch(86.49% 0.018 73.05); 18 - --gradient-average-dark: oklch(27.58% 0.0203 289.13); 19 - --nightshade-violet: oklch(22.96% 0.0242 287.67); 20 32 --purple-night: oklch(18.96% 0.0242 287.67); 21 - --dark-crushed-grape: oklch(74.02% 0.0756 311.96); 22 - --light-crushed-grape: oklch(73.48% 0.1008 284.99); 23 - --reseda-green: oklch(62.33% 0.0475 126.94); 24 - --earth-yellow: oklch(87.45% 0.0203 74.93); 25 - --sunset: oklch(87.45% 0.0334 74.93); 26 33 --ultra-violet: oklch(42.21% 0.0676 297.45); 27 34 --rose-quartz: oklch(65.32% 0.0585 311.96); 28 35 --pink-puree: oklch(75.65% 0.0555 290.76); 29 36 --lavendar-breeze: oklch(91.06% 0.0223 290.76); 30 37 --purple-gray: oklch(25.63% 0.0002 290.76); 31 - --alice-blue: oklch(95.38% 0.0118 239.91); 38 + 39 + --bg: var(--purple-night); 40 + --bg-light: var(--ultra-violet); 41 + --text: var(--lavendar-breeze); 42 + --text-light: var(--pink-puree); 43 + --accent: var(--rose-quartz); 44 + --accent-text: var(--purple-gray); 45 + } 46 + 47 + * { 48 + margin: 0; 49 + padding: 0; 50 + box-sizing: border-box; 32 51 } 33 52 34 53 body { 54 + width: 1200px; 55 + height: 630px; 56 + background-color: var(--bg); 57 + font-family: "Maple Mono", ui-monospace, "Cascadia Code", Menlo, Consolas, monospace; 35 58 font-weight: 600; 36 - color: var(--lavendar-breeze); 37 - background-color: var(--purple-night); 38 - font-family: Consolas, Menlo, Monaco, "Andale Mono", "Ubuntu Mono", 39 - monospace; 40 - display: flex; 41 - flex-direction: column; 42 - text-align: center; 59 + color: var(--text); 60 + position: relative; 43 61 } 44 62 45 - div { 46 - margin: 0; 63 + .container { 64 + width: 100%; 65 + height: 100%; 66 + padding: 3rem; 47 67 display: flex; 48 - flex-direction: column; 49 68 align-items: center; 50 69 justify-content: center; 51 - height: 90vh; /* 90% of viewport height */ 52 - width: 90vw; /* 90% of viewport width */ 53 - padding: 5vh 5vw; /* 5% border on all sides */ 54 - box-sizing: border-box; 55 - align-self: center; 70 + position: relative; 56 71 } 57 72 58 - h1 { 59 - font-size: calc(2 * 2vw); 60 - } 61 - h2 { 62 - font-size: calc(1.75 * 2vw); 63 - } 64 - h3 { 65 - font-size: calc(1.5 * 2vw); 66 - } 67 - h4 { 68 - font-size: calc(1.25 * 2vw); 69 - } 70 - h5 { 71 - font-size: calc(1 * 2vw); 72 - } 73 - h6 { 74 - font-size: calc(0.75 * 2vw); 75 - } 76 - 77 - h1, 78 - h2, 79 - h3, 80 - h4, 81 - h5, 82 - h6 { 83 - margin: 0.5em 0 0.5em 0; 84 - padding: 0.22em 0.4em 0.22em 0.4em; 85 - border-radius: 0.1em; 86 - width: fit-content; 87 - color: var(--lavendar-breeze); 73 + .type { 74 + position: absolute; 75 + top: 3rem; 76 + left: 3rem; 77 + font-size: 1.1rem; 78 + color: var(--text-light); 88 79 } 89 80 90 - h1 { 91 - background-color: var(--rose-quartz); 92 - color: var(--purple-gray); 81 + .title { 82 + font-size: 3.5rem; 83 + font-style: italic; 84 + font-weight: 700; 85 + color: var(--accent-text); 86 + background-color: var(--accent); 87 + border-bottom: 5px solid var(--bg-light); 88 + border-radius: 0.2em 0.2em 0.27em 0.27em; 89 + padding: 0.22em 0.4em; 90 + line-height: 1.15; 91 + text-align: center; 92 + max-width: 900px; 93 93 } 94 94 95 - p { 96 - margin: 1rem 0; 97 - color: var(--pink-puree); 98 - font-size: calc( 99 - 1rem + 1vw 100 - ); /* Adjust font size based on viewport width */ 95 + .author { 96 + position: absolute; 97 + bottom: 3rem; 98 + left: 3rem; 99 + font-size: 1.1rem; 100 + color: var(--text-light); 101 101 } 102 102 </style> 103 103 </head> 104 104 <body> 105 - <div> 106 - <h1>{{type}}</h1> 107 - <h2>{{postname}}</h2> 108 - {{by}} 105 + <div class="container"> 106 + <span class="type">{{type}}</span> 107 + <h1 class="title">{{postname}}</h1> 108 + <span class="author">by Kieran Klukas</span> 109 109 </div> 110 110 </body> 111 111 </html>