Pagespeed hates this one trick!
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m33s

This commit is contained in:
2025-06-12 23:58:06 -06:00
parent 28f41ac94d
commit 2a79d0da67
8 changed files with 100 additions and 77 deletions

View File

@ -9,10 +9,8 @@ import node from '@astrojs/node';
import icon from 'astro-icon'; import icon from 'astro-icon';
import mdx from '@astrojs/mdx'; import mdx from '@astrojs/mdx';
// https://astro.build/config // https://astro.build/config
export default defineConfig({ export default defineConfig({
site: 'https://atri.dad', site: 'https://atri.dad',
@ -23,6 +21,18 @@ export default defineConfig({
vite: { vite: {
plugins: [tailwindcss()] plugins: [tailwindcss()]
}, },
// Enable experimental responsive images
experimental: {
responsiveImages: true,
},
// Configure default image behavior
image: {
experimentalLayout: 'constrained',
experimentalObjectFit: 'cover',
experimentalObjectPosition: 'center',
},
integrations: [preact(), mdx(), icon({ integrations: [preact(), mdx(), icon({
include: { include: {

36
pnpm-lock.yaml generated
View File

@ -1035,8 +1035,8 @@ packages:
resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==}
engines: {node: '>=16'} engines: {node: '>=16'}
caniuse-lite@1.0.30001722: caniuse-lite@1.0.30001723:
resolution: {integrity: sha512-DCQHBBZtiK6JVkAGw7drvAMK0Q0POD/xZvEmDp6baiMMP6QXXk9HpD6mNYBZWhOPG6LvIDb82ITqtWjhDckHCA==} resolution: {integrity: sha512-1R/elMjtehrFejxwmexeXAtae5UO9iSyFn6G/I806CYC/BLyyBk1EPhrKBkWhy6wM6Xnm47dSJQec+tLJ39WHw==}
ccount@2.0.1: ccount@2.0.1:
resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
@ -1254,8 +1254,8 @@ packages:
ee-first@1.1.1: ee-first@1.1.1:
resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
electron-to-chromium@1.5.166: electron-to-chromium@1.5.167:
resolution: {integrity: sha512-QPWqHL0BglzPYyJJ1zSSmwFFL6MFXhbACOCcsCdUMCkzPdS9/OIBVxg516X/Ado2qwAq8k0nJJ7phQPCqiaFAw==} resolution: {integrity: sha512-LxcRvnYO5ez2bMOFpbuuVuAI5QNeY1ncVytE/KXaL6ZNfzX1yPlAO0nSOyIHx2fVAuUprMqPs/TdVhUFZy7SIQ==}
emoji-regex@10.4.0: emoji-regex@10.4.0:
resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==}
@ -2627,8 +2627,8 @@ packages:
typescript: ^4.9.4 || ^5.0.2 typescript: ^4.9.4 || ^5.0.2
zod: ^3 zod: ^3
zod@3.25.62: zod@3.25.63:
resolution: {integrity: sha512-YCxsr4DmhPcrKPC9R1oBHQNlQzlJEyPAId//qTau/vBee9uO8K6prmRq4eMkOyxvBfH4wDPIPdLx9HVMWIY3xA==} resolution: {integrity: sha512-3ttCkqhtpncYXfP0f6dsyabbYV/nEUW+Xlu89jiXbTBifUfjaSqXOG6JnQPLtqt87n7KAmnMqcjay6c0Wq0Vbw==}
zwitch@2.0.4: zwitch@2.0.4:
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
@ -3596,9 +3596,9 @@ snapshots:
xxhash-wasm: 1.1.0 xxhash-wasm: 1.1.0
yargs-parser: 21.1.1 yargs-parser: 21.1.1
yocto-spinner: 0.2.3 yocto-spinner: 0.2.3
zod: 3.25.62 zod: 3.25.63
zod-to-json-schema: 3.24.5(zod@3.25.62) zod-to-json-schema: 3.24.5(zod@3.25.63)
zod-to-ts: 1.2.0(typescript@5.8.3)(zod@3.25.62) zod-to-ts: 1.2.0(typescript@5.8.3)(zod@3.25.63)
optionalDependencies: optionalDependencies:
sharp: 0.33.5 sharp: 0.33.5
transitivePeerDependencies: transitivePeerDependencies:
@ -3679,8 +3679,8 @@ snapshots:
browserslist@4.25.0: browserslist@4.25.0:
dependencies: dependencies:
caniuse-lite: 1.0.30001722 caniuse-lite: 1.0.30001723
electron-to-chromium: 1.5.166 electron-to-chromium: 1.5.167
node-releases: 2.0.19 node-releases: 2.0.19
update-browserslist-db: 1.1.3(browserslist@4.25.0) update-browserslist-db: 1.1.3(browserslist@4.25.0)
@ -3693,7 +3693,7 @@ snapshots:
camelcase@8.0.0: {} camelcase@8.0.0: {}
caniuse-lite@1.0.30001722: {} caniuse-lite@1.0.30001723: {}
ccount@2.0.1: {} ccount@2.0.1: {}
@ -3891,7 +3891,7 @@ snapshots:
ee-first@1.1.1: {} ee-first@1.1.1: {}
electron-to-chromium@1.5.166: {} electron-to-chromium@1.5.167: {}
emoji-regex@10.4.0: {} emoji-regex@10.4.0: {}
@ -5678,15 +5678,15 @@ snapshots:
yoctocolors@2.1.1: {} yoctocolors@2.1.1: {}
zod-to-json-schema@3.24.5(zod@3.25.62): zod-to-json-schema@3.24.5(zod@3.25.63):
dependencies: dependencies:
zod: 3.25.62 zod: 3.25.63
zod-to-ts@1.2.0(typescript@5.8.3)(zod@3.25.62): zod-to-ts@1.2.0(typescript@5.8.3)(zod@3.25.63):
dependencies: dependencies:
typescript: 5.8.3 typescript: 5.8.3
zod: 3.25.62 zod: 3.25.63
zod@3.25.62: {} zod@3.25.63: {}
zwitch@2.0.4: {} zwitch@2.0.4: {}

View File

@ -107,8 +107,8 @@ export default function NavigationBar({ currentPath }: NavigationBarProps) {
aria-label={item.tooltip} aria-label={item.tooltip}
data-tip={item.tooltip} data-tip={item.tooltip}
> >
<Icon size={18} class="sm:w-5 sm:h-5" /> <Icon size={18} class="sm:w-5 sm:h-5" />
<span class="sr-only">{item.name}</span> <span class="sr-only">{item.name}</span>
</a> </a>
</li> </li>
); );

View File

@ -1,38 +1,44 @@
--- ---
import { Icon } from 'astro-icon/components'; import { Icon } from "astro-icon/components";
import SpotifyIcon from './SpotifyIcon'; import SpotifyIcon from "./SpotifyIcon";
import { socialLinks } from '../config/data'; import { socialLinks } from "../config/data";
// Helper function to check if icon is a string (Astro icon) // Helper function to check if icon is a string (Astro icon)
function isAstroIcon(icon: any): icon is string { function isAstroIcon(icon: any): icon is string {
return typeof icon === 'string'; return typeof icon === "string";
} }
// Helper function to check if icon is SpotifyIcon component // Helper function to check if icon is SpotifyIcon component
function isSpotifyIcon(icon: any): boolean { function isSpotifyIcon(icon: any): boolean {
return icon === SpotifyIcon; return icon === SpotifyIcon;
} }
--- ---
<div class="flex flex-row gap-1 sm:gap-4 text-3xl"> <div class="flex flex-row gap-4 text-3xl">
{socialLinks.map((link) => { {
if (isSpotifyIcon(link.icon)) { socialLinks.map((link) => {
return ( if (isSpotifyIcon(link.icon)) {
<SpotifyIcon profileUrl={link.url} client:load /> return <SpotifyIcon profileUrl={link.url} client:load />;
); } else if (isAstroIcon(link.icon)) {
} else if (isAstroIcon(link.icon)) { return (
return ( <a
<a href={link.url}
href={link.url} target={
target={link.url.startsWith('http') ? '_blank' : undefined} link.url.startsWith("http") ? "_blank" : undefined
rel={link.url.startsWith('http') ? 'noopener noreferrer' : undefined} }
aria-label={link.ariaLabel} rel={
class="hover:text-primary transition-colors" link.url.startsWith("http")
> ? "noopener noreferrer"
<Icon name={link.icon} /> : undefined
</a> }
); aria-label={link.ariaLabel}
class="hover:text-primary transition-colors"
>
<Icon name={link.icon} />
</a>
);
}
return null;
})
} }
return null;
})}
</div> </div>

View File

@ -1,28 +1,30 @@
--- ---
import { Icon } from 'astro-icon/components'; import { Icon } from "astro-icon/components";
import { techLinks } from '../config/data'; import { techLinks } from "../config/data";
// Helper function to check if icon is a string (Astro icon) // Helper function to check if icon is a string (Astro icon)
function isAstroIcon(icon: any): icon is string { function isAstroIcon(icon: any): icon is string {
return typeof icon === 'string'; return typeof icon === "string";
} }
--- ---
<div class="flex flex-row gap-1 sm:gap-4 text-3xl"> <div class="flex flex-row gap-4 text-3xl">
{techLinks.map((link) => { {
if (isAstroIcon(link.icon)) { techLinks.map((link) => {
return ( if (isAstroIcon(link.icon)) {
<a return (
href={link.url} <a
target="_blank" href={link.url}
rel="noopener noreferrer" target="_blank"
aria-label={link.ariaLabel} rel="noopener noreferrer"
class="hover:text-primary transition-colors" aria-label={link.ariaLabel}
> class="hover:text-primary transition-colors"
<Icon name={link.icon} /> >
</a> <Icon name={link.icon} />
); </a>
);
}
return null;
})
} }
return null; </div>
})}
</div>

View File

@ -43,8 +43,6 @@ export const personalInfo: PersonalInfo = {
profileImage: { profileImage: {
src: logo, src: logo,
alt: "A drawing of Atridad Lahiji by Shelze!", alt: "A drawing of Atridad Lahiji by Shelze!",
width: 150,
height: 150,
}, },
tagline: "Researcher, Full-Stack Developer, and IT Professional.", tagline: "Researcher, Full-Stack Developer, and IT Professional.",
description: "Researcher, Full-Stack Developer, and IT Professional.", description: "Researcher, Full-Stack Developer, and IT Professional.",

View File

@ -10,9 +10,12 @@ import { personalInfo, homepageSections } from "../config/data";
<Image <Image
src={personalInfo.profileImage.src} src={personalInfo.profileImage.src}
alt={personalInfo.profileImage.alt} alt={personalInfo.profileImage.alt}
height={personalInfo.profileImage.height} width={300}
width={personalInfo.profileImage.width} height={300}
loading="eager" layout="constrained"
priority={true}
class="rounded-full mx-auto"
style="max-width: 12rem; width: 100%;"
/> />
<h1 <h1
@ -21,15 +24,19 @@ import { personalInfo, homepageSections } from "../config/data";
{personalInfo.name} {personalInfo.name}
</h1> </h1>
<h2 class="text-xl sm:text-3xl font-bold text-center"> <h2 class="text-xl sm:text-3xl font-bold text-center mx-6">
{personalInfo.tagline} {personalInfo.tagline}
</h2> </h2>
<h3 class="text-lg sm:text-2xl font-bold">{homepageSections.socialLinks.title}</h3> <h3 class="text-lg sm:text-2xl font-bold">
{homepageSections.socialLinks.title}
</h3>
<SocialLinks /> <SocialLinks />
<h3 class="text-lg sm:text-2xl font-bold">{homepageSections.techStack.title}</h3> <h3 class="text-lg sm:text-2xl font-bold">
{homepageSections.techStack.title}
</h3>
<TechLinks /> <TechLinks />
</Layout> </Layout>

View File

@ -91,8 +91,8 @@ export interface PersonalInfo {
profileImage: { profileImage: {
src: ImageMetadata; src: ImageMetadata;
alt: string; alt: string;
width: number; width?: number;
height: number; height?: number;
}; };
tagline: string; tagline: string;
description?: string; description?: string;