Opengraph
All checks were successful
Docker Deploy / build-and-push (push) Successful in 4m39s

This commit is contained in:
2026-02-07 00:28:33 -07:00
parent 6b77ce091d
commit dce37681af
13 changed files with 336 additions and 230 deletions

View File

@@ -10,8 +10,8 @@
"nix": "nix develop" "nix": "nix develop"
}, },
"dependencies": { "dependencies": {
"@astrojs/mdx": "5.0.0-beta.3", "@astrojs/mdx": "5.0.0-beta.5",
"@astrojs/node": "10.0.0-beta.0", "@astrojs/node": "10.0.0-beta.2",
"@astrojs/rss": "4.0.15", "@astrojs/rss": "4.0.15",
"@astrojs/vue": "6.0.0-beta.0", "@astrojs/vue": "6.0.0-beta.0",
"@iarna/toml": "^2.2.5", "@iarna/toml": "^2.2.5",
@@ -19,7 +19,7 @@
"@react-pdf/renderer": "^4.3.2", "@react-pdf/renderer": "^4.3.2",
"@tailwindcss/typography": "^0.5.19", "@tailwindcss/typography": "^0.5.19",
"@tailwindcss/vite": "^4.1.18", "@tailwindcss/vite": "^4.1.18",
"astro": "6.0.0-beta.6", "astro": "6.0.0-beta.9",
"astro-icon": "^1.1.5", "astro-icon": "^1.1.5",
"lucide-vue-next": "^0.563.0", "lucide-vue-next": "^0.563.0",
"react": "^19.2.4", "react": "^19.2.4",
@@ -32,7 +32,7 @@
"@catppuccin/daisyui": "^2.1.1", "@catppuccin/daisyui": "^2.1.1",
"@iconify-json/mdi": "^1.2.3", "@iconify-json/mdi": "^1.2.3",
"@iconify-json/simple-icons": "^1.2.69", "@iconify-json/simple-icons": "^1.2.69",
"@types/react": "^19.2.10", "@types/react": "^19.2.13",
"daisyui": "^5.5.17" "daisyui": "^5.5.18"
} }
} }

434
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

BIN
public/logo.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

View File

@@ -142,6 +142,35 @@ export const config: Config = {
url: "https://atri.dad", url: "https://atri.dad",
author: "Atridad Lahiji", author: "Atridad Lahiji",
}, },
openGraph: {
image: "/logo.png",
type: "website",
locale: "en_US",
siteName: "Atridad Lahiji",
},
pageOpenGraph: {
home: {
title: "Atridad Lahiji",
description:
"Personal website of Atridad Lahiji - Researcher, Full-Stack Developer, and IT Professional",
},
posts: {
title: "Blog Posts",
description: "Thoughts and ramblings.",
},
projects: {
title: "Projects",
description: "Projects I'm working on.",
},
talks: {
title: "Talks",
description: "Conference talks and presentations by Atridad Lahiji",
},
resume: {
title: "Resume",
description: "My Resume and Resume Generator",
},
},
giteaDomains: ["https://git.atri.dad"], giteaDomains: ["https://git.atri.dad"],
}, },

View File

@@ -9,14 +9,25 @@ import "../styles/global.css";
export interface Props { export interface Props {
title?: string; title?: string;
description?: string; description?: string;
ogImage?: string;
ogType?: "website" | "article";
} }
const { title, description } = Astro.props; const { title, description, ogImage, ogType } = Astro.props;
const pageTitle = title const pageTitle = title
? `${title} | ${config.siteConfig.meta.title}` ? `${title} | ${config.siteConfig.meta.title}`
: config.siteConfig.meta.title; : config.siteConfig.meta.title;
const pageDescription = description || config.siteConfig.meta.description; const pageDescription = description || config.siteConfig.meta.description;
const og = config.siteConfig.openGraph;
const canonicalUrl = new URL(Astro.url.pathname, config.siteConfig.meta.url)
.href;
const resolvedOgImage = ogImage || og.image;
const resolvedOgImageUrl = resolvedOgImage
? new URL(resolvedOgImage, config.siteConfig.meta.url).href
: undefined;
const resolvedOgType = ogType || og.type || "website";
--- ---
<!doctype html> <!doctype html>
@@ -25,10 +36,24 @@ const pageDescription = description || config.siteConfig.meta.description;
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" /> <meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/x-icon" href="/favicon.ico" /> <link rel="icon" type="image/x-icon" href="/favicon.ico" />
<link rel="canonical" href={canonicalUrl} />
<meta name="generator" content={Astro.generator} /> <meta name="generator" content={Astro.generator} />
<meta name="description" content={pageDescription} /> <meta name="description" content={pageDescription} />
<meta name="author" content={config.siteConfig.meta.author} /> <meta name="author" content={config.siteConfig.meta.author} />
<title>{pageTitle}</title> <title>{pageTitle}</title>
<meta property="og:title" content={pageTitle} />
<meta property="og:description" content={pageDescription} />
<meta property="og:type" content={resolvedOgType} />
<meta property="og:url" content={canonicalUrl} />
{og.siteName && <meta property="og:site_name" content={og.siteName} />}
{og.locale && <meta property="og:locale" content={og.locale} />}
{
resolvedOgImageUrl && (
<meta property="og:image" content={resolvedOgImageUrl} />
)
}
<ClientRouter /> <ClientRouter />
</head> </head>
<body class="flex flex-col min-h-screen overflow-x-hidden"> <body class="flex flex-col min-h-screen overflow-x-hidden">

View File

@@ -3,7 +3,7 @@ import Layout from "../layouts/Layout.astro";
import FuzzyText from "../components/FuzzyText.vue"; import FuzzyText from "../components/FuzzyText.vue";
--- ---
<Layout title="404 - Not Found"> <Layout title="404 - Not Found" description="Page not found">
<div class="flex flex-col items-center justify-center w-full"> <div class="flex flex-col items-center justify-center w-full">
<FuzzyText <FuzzyText
text="404" text="404"

View File

@@ -6,7 +6,12 @@ import Layout from "../layouts/Layout.astro";
import { config } from "../config"; import { config } from "../config";
--- ---
<Layout> <Layout
title={config.siteConfig.pageOpenGraph.home.title}
description={config.siteConfig.pageOpenGraph.home.description}
ogImage={config.siteConfig.pageOpenGraph.home.image}
ogType={config.siteConfig.pageOpenGraph.home.type}
>
<Image <Image
src={config.personalInfo.profileImage.src} src={config.personalInfo.profileImage.src}
alt={config.personalInfo.profileImage.alt} alt={config.personalInfo.profileImage.alt}

View File

@@ -17,7 +17,11 @@ const { post }: { post: CollectionEntry<"posts"> } = Astro.props;
const { Content } = await render(post); const { Content } = await render(post);
--- ---
<Layout> <Layout
title={post.data.title}
description={post.data.description}
ogType="article"
>
<div class="w-full p-4 md:p-8"> <div class="w-full p-4 md:p-8">
<div class="max-w-3xl mx-auto"> <div class="max-w-3xl mx-auto">
<div class="p-4 md:p-8"> <div class="p-4 md:p-8">

View File

@@ -2,6 +2,7 @@
import Layout from "../layouts/Layout.astro"; import Layout from "../layouts/Layout.astro";
import { getCollection, type CollectionEntry } from "astro:content"; import { getCollection, type CollectionEntry } from "astro:content";
import { Icon } from "astro-icon/components"; import { Icon } from "astro-icon/components";
import { config } from "../config";
// Get all posts from the content collection // Get all posts from the content collection
const posts = await getCollection("posts"); const posts = await getCollection("posts");
@@ -21,7 +22,12 @@ function formatDate(date: Date): string {
} }
--- ---
<Layout> <Layout
title={config.siteConfig.pageOpenGraph.posts.title}
description={config.siteConfig.pageOpenGraph.posts.description}
ogImage={config.siteConfig.pageOpenGraph.posts.image}
ogType={config.siteConfig.pageOpenGraph.posts.type}
>
<div class="w-full max-w-3xl mx-auto p-4 sm:p-8"> <div class="w-full max-w-3xl mx-auto p-4 sm:p-8">
<h1 <h1
class="text-3xl sm:text-4xl font-bold text-primary mb-6 sm:mb-8 text-center" class="text-3xl sm:text-4xl font-bold text-primary mb-6 sm:mb-8 text-center"

View File

@@ -51,7 +51,12 @@ const sortedProjects = projectsWithGiteaInfo.sort((a, b) => {
}); });
--- ---
<Layout> <Layout
title={config.siteConfig.pageOpenGraph.projects.title}
description={config.siteConfig.pageOpenGraph.projects.description}
ogImage={config.siteConfig.pageOpenGraph.projects.image}
ogType={config.siteConfig.pageOpenGraph.projects.type}
>
<div class="w-full max-w-3xl mx-auto p-4 sm:p-8"> <div class="w-full max-w-3xl mx-auto p-4 sm:p-8">
<h1 <h1
class="text-3xl sm:text-4xl font-bold text-primary mb-6 sm:mb-8 text-center" class="text-3xl sm:text-4xl font-bold text-primary mb-6 sm:mb-8 text-center"

View File

@@ -95,7 +95,12 @@ if (!data) {
} }
--- ---
<Layout title="Resume"> <Layout
title={config.siteConfig.pageOpenGraph.resume.title}
description={config.siteConfig.pageOpenGraph.resume.description}
ogImage={config.siteConfig.pageOpenGraph.resume.image}
ogType={config.siteConfig.pageOpenGraph.resume.type}
>
<ResumeSettingsModal client:load /> <ResumeSettingsModal client:load />
<div class="container mx-auto p-4 sm:p-6 lg:p-8 max-w-4xl w-full"> <div class="container mx-auto p-4 sm:p-6 lg:p-8 max-w-4xl w-full">
<h1 <h1

View File

@@ -18,7 +18,12 @@ function formatDate(dateStr: string): string {
} }
--- ---
<Layout> <Layout
title={config.siteConfig.pageOpenGraph.talks.title}
description={config.siteConfig.pageOpenGraph.talks.description}
ogImage={config.siteConfig.pageOpenGraph.talks.image}
ogType={config.siteConfig.pageOpenGraph.talks.type}
>
<div class="w-full max-w-3xl mx-auto p-4 sm:p-8"> <div class="w-full max-w-3xl mx-auto p-4 sm:p-8">
<h1 <h1
class="text-3xl sm:text-4xl font-bold text-primary mb-6 sm:mb-8 text-center" class="text-3xl sm:text-4xl font-bold text-primary mb-6 sm:mb-8 text-center"

View File

@@ -169,6 +169,20 @@ export interface HomepageSections {
}; };
} }
export interface OpenGraphConfig {
image?: string;
type?: "website" | "article";
locale?: string;
siteName?: string;
}
export interface PageOpenGraph {
title?: string;
description?: string;
image?: string;
type?: "website" | "article";
}
export interface SiteConfig { export interface SiteConfig {
personal: PersonalInfo; personal: PersonalInfo;
homepage: HomepageSections; homepage: HomepageSections;
@@ -179,6 +193,14 @@ export interface SiteConfig {
url: string; url: string;
author: string; author: string;
}; };
openGraph: OpenGraphConfig;
pageOpenGraph: {
home: PageOpenGraph;
posts: PageOpenGraph;
projects: PageOpenGraph;
talks: PageOpenGraph;
resume: PageOpenGraph;
};
giteaDomains?: string[]; giteaDomains?: string[];
} }