Files for my website bwc9876.dev
0
fork

Configure Feed

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

at main 266 lines 6.0 kB view raw
1--- 2import { Image, getImage } from "astro:assets"; 3 4import defaultOg from "@assets/default-og.webp"; 5import cow from "@assets/cow.webp"; 6import Socials from "@components/Socials.astro"; 7import IconLink from "@components/IconLink.astro"; 8import "@styles/style.css"; 9import type { ImageMetadata } from "astro"; 10 11export interface Props { 12 title: string; 13 appendTitle?: boolean; 14 description?: string; 15 keywords?: string[]; 16 og?: { 17 src: ImageMetadata; 18 alt: string; 19 }; 20} 21 22const { title, appendTitle, description: oldDescription, keywords, og: oldOg } = Astro.props; 23 24const og = { 25 src: ( 26 await getImage({ 27 src: oldOg?.src ?? defaultOg, 28 format: "webp" 29 }) 30 ).src, 31 alt: oldOg?.alt ?? "Ben C's Profile Picture" 32}; 33 34og.src = `${Astro.url.origin}${og.src}`; 35 36const description = oldDescription ?? "Ben C's software development portfolio"; 37const fullTitle = (appendTitle ?? true) ? `${title} | Ben C` : title; 38const canonical = Astro.url.toString(); 39--- 40 41<!doctype html> 42<html lang="en"> 43 <head> 44 <title>{fullTitle}</title> 45 <meta charset="UTF-8" /> 46 <meta http-equiv="X-UA-Compatible" content="IE=edge" /> 47 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 48 <meta name="description" content={description} /> 49 <meta name="keywords" content={["portfolio"].concat(keywords ?? []).join(", ")} /> 50 <meta name="generator" content={Astro.generator} /> 51 <meta property="og:type" content="website" /> 52 <meta property="og:title" content={fullTitle} /> 53 <meta property="og:description" content={description} /> 54 <meta property="og:url" content={canonical} /> 55 <meta property="og:image" content={og.src} /> 56 <meta property="og:image:alt" content={og.alt} /> 57 <meta name="twitter:title" content={fullTitle} /> 58 <meta name="twitter:description" content={description} /> 59 <meta name="twitter:image" content={og.src} /> 60 <link rel="canonical" href={canonical} /> 61 <link rel="icon" href="/favicon.ico" /> 62 <link 63 rel="alternate" 64 type="application/rss+xml" 65 title="Ben C's Blog" 66 href={new URL("feed.xml", Astro.site)} 67 /> 68 <style is:global> 69 @view-transition { 70 navigation: auto; 71 } 72 </style> 73 </head> 74 <body id="top"> 75 <header class="container"> 76 <nav aria-label="Main navigation"> 77 <a href="/" 78 ><Image 79 class="nav-icon" 80 width={150} 81 height={150} 82 transition:name="pfp" 83 transition:persist 84 format="webp" 85 alt="Ben C's Avatar" 86 src={cow} 87 /> 88 <span style="color: var(--text);"><span class="gradient-text">Bwc9876</span>.dev</span> 89 </a> 90 <span> 91 <a href="/projects">Projects</a> 92 <a href="/blog">Blog</a> 93 <a href="/uses">Uses</a> 94 </span> 95 <Socials labelPlacement="bottom" /> 96 </nav> 97 </header> 98 <main transition:name="main" class="container"> 99 <slot /> 100 </main> 101 <footer transition:name="footer" class="container"> 102 <p> 103 <IconLink 104 label="Back To Top" 105 placement="top" 106 icon="arrow-bar-up" 107 data-tooltip="Back To Top" 108 href="#top" 109 /> 110 </p> 111 <p class="copyright">© Ben C 2026</p> 112 <Socials labelPlacement="top" /> 113 </footer> 114 </body> 115</html> 116 117<style> 118 body { 119 background-color: var(--background); 120 background-image: url("@assets/bg-tile.webp"); 121 background-repeat: round; 122 background-blend-mode: multiply; 123 animation: 124 rainbow 5s linear infinite, 125 bg-scroll 120s linear infinite; 126 127 margin: 0; 128 padding: 0; 129 display: flex; 130 flex-direction: column; 131 min-height: 100vh; 132 width: 100vw; 133 overflow-x: hidden; 134 } 135 136 body > * { 137 background-color: color(from var(--background) srgb r g b / 70%); 138 backdrop-filter: blur(200px); 139 padding: 0 var(--4); 140 } 141 142 header { 143 border-bottom: var(--section-border); 144 } 145 146 @keyframes bg-scroll { 147 0% { 148 background-position: 0 0; 149 } 150 50% { 151 background-position: 50% 50%; 152 } 153 100% { 154 background-position: 100% 100%; 155 } 156 } 157 158 @keyframes rainbow { 159 0% { 160 backdrop-filter: hue-rotate(0deg); 161 } 162 50% { 163 backdrop-filter: hue-rotate(180deg); 164 } 165 100% { 166 backdrop-filter: hue-rotate(360deg); 167 } 168 } 169 170 nav { 171 display: flex; 172 gap: var(--1); 173 flex-direction: column; 174 align-items: center; 175 padding: var(--2) 0; 176 } 177 178 nav > :nth-child(3) { 179 display: none; 180 } 181 182 @media (width >= 1050px) { 183 nav { 184 flex-direction: row; 185 } 186 187 nav > :nth-child(3) { 188 display: flex; 189 } 190 } 191 192 nav a { 193 text-decoration: none; 194 195 &:hover { 196 text-decoration: underline; 197 } 198 } 199 200 nav > a:first-child { 201 font-size: var(--2); 202 display: flex; 203 gap: 5px; 204 flex-direction: row; 205 align-items: center; 206 justify-content: center; 207 background-color: color(from var(--secondary) srgb r g b / 67%); 208 padding: 5px 7px; 209 border-radius: 5px; 210 211 & > span > span { 212 transform: translateY(-2px); 213 } 214 } 215 216 nav > span { 217 display: flex; 218 flex-direction: row; 219 gap: var(--2); 220 } 221 222 nav > span:nth-child(2) { 223 flex-grow: 1; 224 } 225 226 .nav-icon { 227 width: var(--4); 228 height: var(--4); 229 border-radius: 100%; 230 transition: transform 800ms 231 linear( 232 0, 233 0.36 6.7%, 234 0.635 13.9%, 235 0.832 21.8%, 236 0.904 26.1%, 237 0.958 30.6%, 238 1.015 38.6%, 239 1.036 48.1%, 240 1.034 56.4%, 241 1.005 81.2%, 242 1 243 ); 244 245 @starting-style { 246 transform: translateX(calc(-1 * 50vw - var(--5))) rotate(-300deg); 247 } 248 } 249 250 main { 251 flex-grow: 1; 252 } 253 254 footer > p { 255 margin: var(--1); 256 } 257 258 footer { 259 border-top: var(--section-border); 260 display: flex; 261 flex-direction: column; 262 align-items: center; 263 justify-content: center; 264 padding: var(--2) 0; 265 } 266</style>