Files for my website bwc9876.dev

Finishing touches

+96 -27
+10 -11
src/components/projects/ProjectCard.astro
··· 1 1 --- 2 2 import { Image } from "@astrojs/image/components"; 3 - import defaultSrc from "@images/default-project-image.webp"; 3 + import getProjectImageSrc from "@images/utils"; 4 4 import type { CollectionEntry } from "astro:content"; 5 5 6 - export const getGithubOpenGraph = (repoDouble: string) => { 7 - const hash = Math.random() * 1000; 8 - return `https://opengraph.githubassets.com/${hash}/${repoDouble}`; 9 - }; 10 - 11 6 export interface Props { 12 7 project: CollectionEntry<"projects">; 13 8 } 14 9 15 10 const { project } = Astro.props; 11 + 12 + const src = await getProjectImageSrc( 13 + project.data.links?.github ?? "Not Found", 14 + project.data.image?.src 15 + ); 16 16 --- 17 17 18 18 <article> ··· 22 22 <Image 23 23 width={500} 24 24 height={500} 25 - format="webp" 26 25 position="center" 26 + format="webp" 27 + src={src} 27 28 alt={project.data.name} 28 - src={project.data.image?.src ?? 29 - getGithubOpenGraph(project.data.links?.github ?? "Not Found")} 30 29 /> 31 30 </div> 32 31 <strong class="project-name">{project.data.name}</strong> ··· 40 39 41 40 <style> 42 41 article { 43 - margin-bottom: 0; 44 - margin-top: 0; 42 + margin-bottom: 0 !important; 43 + margin-top: 0 !important; 45 44 display: flex; 46 45 flex-direction: column; 47 46 }
+5 -1
src/content/projects/portfolio-site.mdx
··· 9 9 links: 10 10 github: Bwc9876/portfolio-site 11 11 other: 12 - "Website (...In case you didn't know it???)": https://bwc9876.dev/ 12 + Website: https://bwc9876.dev/ 13 + image: 14 + src: portfolio 15 + width: 600 16 + height: 600 13 17 --- 14 18 15 19 import ExtLink from "@components/ExtLink.astro";
src/images/default-og.png

This is a binary file and will not be displayed.

src/images/default-project-image.webp

This is a binary file and will not be displayed.

src/images/portfolio.png

This is a binary file and will not be displayed.

+14
src/images/utils.ts
··· 1 + const getGithubOpenGraph = (repoDouble: string) => { 2 + const hash = Math.random() * 1000; 3 + return `https://opengraph.githubassets.com/${hash}/${repoDouble}`; 4 + }; 5 + 6 + const getProjectImageSrc = async (ghRepo: string, inSrc?: string) => { 7 + let src = inSrc; 8 + if (src && !src.startsWith("https://")) { 9 + src = (await import(`../images/${src}.png`)).default.src; 10 + } 11 + return src ?? getGithubOpenGraph(ghRepo); 12 + }; 13 + 14 + export default getProjectImageSrc;
+44 -3
src/layouts/Layout.astro
··· 1 1 --- 2 2 import { Image } from "@astrojs/image/components"; 3 + import { getImage } from "@astrojs/image"; 3 4 import IconLink from "@components/IconLink.astro"; 4 5 import "@picocss/pico/css/pico.min.css"; 6 + 7 + import defaultOg from "@images/default-og.png"; 5 8 6 9 export interface Props { 7 10 title: string; 11 + description?: string; 12 + keywords?: string[]; 13 + og?: { 14 + src: string; 15 + alt: string; 16 + }; 8 17 } 9 18 10 - const { title } = Astro.props; 19 + const { title, description: oldDescription, keywords, og: oldOg } = Astro.props; 20 + 21 + const og = oldOg ?? { src: defaultOg.src, alt: "Ben C's Avatar" }; 22 + 23 + const ogImg = await getImage({ 24 + format: "webp", 25 + width: 1920, 26 + height: 1080, 27 + position: "center", 28 + fit: "inside", 29 + background: "white", 30 + ...og 31 + }); 32 + 33 + og.src = `${Astro.url.origin}${ogImg.src}`; 34 + 35 + const description = oldDescription ?? "Ben C's software development portfolio"; 36 + const fullTitle = `${title} | Ben C`; 37 + const canonical = Astro.url.toString(); 11 38 --- 12 39 13 40 <!DOCTYPE html> 14 41 <html data-theme="dark" lang="en"> 15 42 <head> 16 43 <meta charset="UTF-8" /> 44 + <meta http-equiv="X-UA-Compatible" content="IE=edge" /> 17 45 <meta name="viewport" content="width=device-width" /> 18 - <link rel="icon" type="image/svg+xml" href="/favicon.png" /> 46 + <meta name="description" content={description} /> 47 + <meta name="keywords" content={["portfolio"].concat(keywords ?? []).join(", ")} /> 19 48 <meta name="generator" content={Astro.generator} /> 20 - <title>{title} | Bwc9876</title> 49 + <meta property="og:type" content="website" /> 50 + <meta property="og:title" content={fullTitle} /> 51 + <meta property="og:description" content={description} /> 52 + <meta property="og:url" content={canonical} /> 53 + <meta property="og:image" content={og.src} /> 54 + <meta property="og:image:alt" content={og.alt} /> 55 + <meta name="twitter:title" content={fullTitle} /> 56 + <meta name="twitter:description" content={description} /> 57 + <meta name="twitter:card" content="summary_large_image" /> 58 + <meta name="twitter:image" content={og.src} /> 59 + <link rel="canonical" href={canonical} /> 60 + <link rel="icon" href="/favicon.png" /> 61 + <title>{fullTitle}</title> 21 62 </head> 22 63 <body> 23 64 <nav class="container">
+3 -2
src/pages/index.astro
··· 23 23 24 24 <hgroup> 25 25 <h2>Recent Projects</h2> 26 - <h3>Sorted By Date</h3> 26 + <h3>Sorted By Year</h3> 27 27 </hgroup> 28 28 <ProjectGrid limitTo={6} /> 29 29 <div class="view-more"> 30 - <a href="/projects">View All</a> 30 + <a href="/projects">View All Projects</a> 31 31 </div> 32 32 </Layout> 33 33 34 34 <style> 35 35 .view-more { 36 + margin-top: var(--spacing); 36 37 display: flex; 37 38 justify-content: center; 38 39 width: 100%;
+14 -4
src/pages/projects/[...slug].astro
··· 3 3 import { Image } from "@astrojs/image/components"; 4 4 import Layout from "@layouts/Layout.astro"; 5 5 import IconLink from "@components/IconLink.astro"; 6 - import defaultSrc from "@images/default-project-image.webp"; 7 - import { getGithubOpenGraph } from "@components/projects/ProjectCard.astro"; 6 + import getProjectImageSrc from "@images/utils"; 7 + import { getImage } from "astro/dist/assets/internal"; 8 8 export async function getStaticPaths() { 9 9 const renameEntries = await getCollection("projects"); 10 10 return renameEntries.map((entry) => ({ ··· 14 14 } 15 15 const { entry } = Astro.props; 16 16 const { Content } = await entry.render(); 17 + 18 + const src = await getProjectImageSrc( 19 + entry.data.links?.github ?? "Not Found", 20 + entry.data.image?.src 21 + ); 22 + 23 + const og = { 24 + src, 25 + alt: entry.data.name 26 + }; 17 27 --- 18 28 19 - <Layout title={entry.data.name}> 29 + <Layout title={entry.data.name} description={entry.data.summary} keywords={entry.data.tags} og={og}> 20 30 <header> 21 31 <div class="img-container"> 22 32 <Image ··· 27 37 width={entry.data.image?.width ?? 474} 28 38 height={entry.data.image?.height ?? 474} 29 39 alt={entry.data.name} 30 - src={entry.data.image?.src ?? getGithubOpenGraph(entry.data.links.github)} 40 + src={src} 31 41 /> 32 42 </div> 33 43 <hgroup>
+1 -1
src/pages/projects/index.astro
··· 6 6 const projectEntries = (await getCollection("projects")).length; 7 7 --- 8 8 9 - <Layout title="Projects"> 9 + <Layout title="Projects" description="Ben C's Projects"> 10 10 <hgroup> 11 11 <h1>My Projects</h1> 12 12 <h2>Sorted By Year • {projectEntries} Total</h2>
+5 -5
tsconfig.json
··· 1 1 { 2 2 "extends": "astro/tsconfigs/strict", 3 3 "compilerOptions": { 4 - "baseUrl": ".", 4 + "baseUrl": "./src", 5 5 "paths": { 6 - "@layouts/*": ["src/layouts/*"], 7 - "@components/*": ["src/components/*"], 8 - "@assets/*": ["src/assets/*"], 9 - "@images/*": ["src/images/*"] 6 + "@layouts/*": ["layouts/*"], 7 + "@components/*": ["components/*"], 8 + "@assets/*": ["assets/*"], 9 + "@images/*": ["images/*"] 10 10 } 11 11 } 12 12 }