Compare commits

..

1 Commits

Author SHA1 Message Date
e463b8d956 chore(deps): update dependency eslint to v10
All checks were successful
renovate/stability-days Updates have met minimum release age requirement
test-build / build (pull_request) Successful in 1m16s
2026-02-08 20:41:14 +00:00
18 changed files with 378 additions and 608 deletions

View File

@@ -26,10 +26,10 @@ COPY --from=build /app/dist /app/dist
ENV HOST=0.0.0.0 ENV HOST=0.0.0.0
ENV SITE_URL=https://www.alexlebens.dev ENV SITE_URL=https://www.alexlebens.dev
ENV DIRECTUS_URL=https://directus.alexlebens.net ENV DIRECTUS_URL=https://directus.alexlebens.dev
ENV PORT=4321 ENV PORT=4321
LABEL version="2.5.0" LABEL version="2.3.3"
LABEL description="Astro based personal website" LABEL description="Astro based personal website"
EXPOSE $PORT EXPOSE $PORT

View File

@@ -14,7 +14,7 @@ For detailed help with Astro CLI commands, visit [Astro's documentation](https:/
## Thanks ## Thanks
Thanks https://github.com/godruoyi/gblog/tree/gblog-template, https://github.com/mearashadowfax/ScrewFast, Thanks https://github.com/mearashadowfax/ScrewFast, https://github.com/godruoyi/gblog/tree/gblog-template
## License ## License

View File

@@ -1,7 +1,7 @@
{ {
"name": "site-profile", "name": "site-profile",
"type": "module", "type": "module",
"version": "2.5.0", "version": "2.3.3",
"homepage": "https://www.alexlebens.dev", "homepage": "https://www.alexlebens.dev",
"bugs": { "bugs": {
"url": "https://gitea.alexlebens.dev/alexlebens/site-profile/issues", "url": "https://gitea.alexlebens.dev/alexlebens/site-profile/issues",
@@ -33,16 +33,16 @@
"@astrojs/react": "^4.4.2", "@astrojs/react": "^4.4.2",
"@astrojs/rss": "^4.0.15", "@astrojs/rss": "^4.0.15",
"@astrojs/sitemap": "^3.7.0", "@astrojs/sitemap": "^3.7.0",
"@directus/sdk": "^21.1.0", "@directus/sdk": "^21.0.0",
"@giscus/react": "^3.1.0", "@giscus/react": "^3.1.0",
"@iconify-json/mdi": "^1.2.3", "@iconify-json/mdi": "^1.2.3",
"@iconify-json/pajamas": "^1.2.15", "@iconify-json/pajamas": "^1.2.15",
"@iconify-json/simple-icons": "^1.2.70", "@iconify-json/simple-icons": "^1.2.69",
"@playform/compress": "^0.2.1", "@playform/compress": "^0.2.1",
"@swup/astro": "^1.7.0", "@swup/astro": "^1.7.0",
"@tailwindcss/postcss": "^4.1.18", "@tailwindcss/postcss": "^4.1.18",
"@tailwindcss/vite": "^4.1.18", "@tailwindcss/vite": "^4.1.18",
"@types/react": "^19.2.13", "@types/react": "^19.2.10",
"@types/unist": "^3.0.3", "@types/unist": "^3.0.3",
"astro": "^5.17.1", "astro": "^5.17.1",
"astro-compressor": "^1.2.0", "astro-compressor": "^1.2.0",
@@ -50,7 +50,7 @@
"marked": "^17.0.1", "marked": "^17.0.1",
"marked-shiki": "^1.2.1", "marked-shiki": "^1.2.1",
"mdast-util-to-string": "^4.0.0", "mdast-util-to-string": "^4.0.0",
"motion": "^12.34.0", "motion": "^12.31.0",
"preline": "^4.0.1", "preline": "^4.0.1",
"react": "^19.2.4", "react": "^19.2.4",
"react-dom": "^19.2.4", "react-dom": "^19.2.4",
@@ -62,14 +62,14 @@
"ultrahtml": "^1.6.0" "ultrahtml": "^1.6.0"
}, },
"devDependencies": { "devDependencies": {
"@eslint-react/eslint-plugin": "^2.12.2", "@eslint-react/eslint-plugin": "^2.9.4",
"@tailwindcss/forms": "^0.5.11", "@tailwindcss/forms": "^0.5.11",
"@tailwindcss/typography": "^0.5.19", "@tailwindcss/typography": "^0.5.19",
"astro-icon": "^1.1.5", "astro-icon": "^1.1.5",
"eslint": "^10.0.0", "eslint": "^10.0.0",
"eslint-config-prettier": "^10.1.8", "eslint-config-prettier": "^10.1.8",
"eslint-plugin-astro": "^1.5.0", "eslint-plugin-astro": "^1.5.0",
"eslint-plugin-format": "^1.4.0", "eslint-plugin-format": "^1.3.1",
"eslint-plugin-react": "^7.37.5", "eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^7.0.1", "eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-react-refresh": "^0.5.0", "eslint-plugin-react-refresh": "^0.5.0",
@@ -78,6 +78,6 @@
"prettier-plugin-tailwindcss": "^0.7.2", "prettier-plugin-tailwindcss": "^0.7.2",
"timeago.js": "^4.0.2", "timeago.js": "^4.0.2",
"typescript": "^5.9.3", "typescript": "^5.9.3",
"typescript-eslint": "^8.55.0" "typescript-eslint": "^8.54.0"
} }
} }

614
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -15,12 +15,11 @@ const borderClasses = 'border border-neutral-100 dark:border-stone-500/20';
const bgColorClasses = const bgColorClasses =
'bg-neutral-100/80 hover:bg-neutral-100 dark:bg-neutral-800/60 dark:hover:bg-neutral-800/90'; 'bg-neutral-100/80 hover:bg-neutral-100 dark:bg-neutral-800/60 dark:hover:bg-neutral-800/90';
const shadowClasses = 'shadow-xs hover:shadow-md dark:shadow-md dark:hover:shadow-lg'; const shadowClasses = 'shadow-xs hover:shadow-md dark:shadow-md dark:hover:shadow-lg';
const sizeClasses = 'h-30 w-100 md:w-[300px]';
--- ---
<div class={`${baseClasses}`}> <div class={`${baseClasses}`}>
<a <a
class={`rounded-xl duration-300 transition-all ${sizeClasses} ${borderClasses} ${bgColorClasses} ${shadowClasses}`} class={`rounded-xl duration-300 transition-all h-30 ${borderClasses} ${bgColorClasses} ${shadowClasses}`}
href={url} href={url}
data-astro-prefetch data-astro-prefetch
> >

View File

@@ -1,52 +0,0 @@
---
import { Image } from 'astro:assets';
import { blurStyle } from '@support/image';
const { srcLight, srcDark, alt, style, disableBlur, width, height } = Astro.props;
const showBlur = !disableBlur;
const blurLight = (srcLight?.fsPath && showBlur) ? await blurStyle(srcLight.fsPath) : {};
const blurDark = (srcDark?.fsPath && showBlur) ? await blurStyle(srcDark.fsPath) : {};
---
<div class="themed-image-container">
<Image
src={srcLight}
alt={alt}
class={`light-logo ${style}`}
style={blurLight}
inferSize={true}
width={width}
height={height}
/>
<Image
src={srcDark}
alt={alt}
class={`dark-logo ${style}`}
style={blurDark}
inferSize={true}
width={width}
height={height}
/>
</div>
<style>
.themed-image-container {
display: grid;
grid-template-areas: "stack";
}
.themed-image-container :global(img) {
grid-area: stack;
}
:global(.dark) .light-logo {
display: none !important;
}
:global(.dark) .dark-logo {
display: block !important;
}
</style>

View File

@@ -1,17 +0,0 @@
---
import ImageTheme from '@components/ui/images/ImageTheme.astro';
const { srcLight, srcDark, alt } = Astro.props;
---
<ImageTheme
srcLight={srcLight}
srcDark={srcDark}
alt={alt}
style='color: transparent; width: 48px; height: 48px; object-fit: contain; max-height: 100%; max-width: 100%;'
draggable="false"
loading="lazy"
width="48"
height="48"
/>

View File

@@ -1,71 +0,0 @@
---
import { Icon } from 'astro-icon/components';
import { readItems } from '@directus/sdk';
import Logo from '@components/ui/logos/Logo.astro';
import type { Application } from '@lib/directusTypes';
import directus from '@lib/directus';
const applications = await directus.request(
readItems('site_applications', {
fields: ['*'],
sort: ['-isActive'],
})
);
const baseClasses = 'smooth-reveal-cards rounded-xl flex flex-col group group-hover';
const borderClasses = 'border border-neutral-100 dark:border-stone-500/20';
const bgColorClasses =
'bg-neutral-100/80 hover:bg-neutral-100 dark:bg-neutral-800/60 dark:hover:bg-neutral-800/90';
const shadowClasses = 'shadow-xs hover:shadow-md dark:shadow-md dark:hover:shadow-lg';
---
<section class:list={['flex flex-col gap-4', Astro.props.className]}>
<div class="grid grid-cols-1 gap-3 md:grid-cols-2 print:flex print:flex-col">
{
applications.map((application: Application) => {
return (
<div class={`${baseClasses}`}>
<a
class={`rounded-xl transition-all duration-300 ${borderClasses} ${bgColorClasses} ${shadowClasses}`}
href={application.url}
>
<div class="p-4 md:p-10">
<div class="flex items-center">
<Logo
srcLight={application.logoUrl}
srcDark={application.logoUrl}
alt={`Logo of ${application.name}`}
/>
<h3 class="text-lg font-bold text-gray-800 dark:text-white ml-4">
{application.name}
</h3>
</div>
<p class="mt-2 text-gray-500 dark:text-neutral-400">{application.description}</p>
<ul class="mt-1 flex list-disc flex-col gap-2 text-sm text-gray-500 dark:text-neutral-400 [&>li]:ml-4">
{application.highlights.map((highlight) => {
return <li class="marker:text-yellow-500">{highlight}</li>;
})}
</ul>
<div class="ml-6 flex">
<div
class="group-hover relative inline-block gap-x-1 rounded-lg border border-transparent disabled:pointer-events-none disabled:opacity-50"
>
<div class="group-hover:text-steel dark:group-hover:text-bermuda transition-text relative z-10 mx-auto flex min-h-11 items-center text-sm font-semibold text-neutral-600 decoration-2 duration-300 sm:mx-0 sm:mt-4 dark:text-neutral-300">
<span class="relative inline-block overflow-hidden"> Visit Page </span>
<Icon
name="mdi:keyboard-arrow-right"
class="translate-y-0.5 transition duration-300 group-hover:translate-x-1"
/>
</div>
</div>
</div>
</div>
</a>
</div>
);
})
}
</div>
</section>

View File

@@ -1,12 +1,10 @@
--- ---
import { Icon } from 'astro-icon/components'; import { Icon } from 'astro-icon/components';
import { readItems } from '@directus/sdk'; import { readItems } from '@directus/sdk';
import Logo from '@components/ui/logos/Logo.astro';
import type { Education } from '@lib/directusTypes'; import type { Education } from '@lib/directusTypes';
import directus from '@lib/directus'; import directus from '@lib/directus';
import { getDirectusImageURL } from '@lib/directusFunctions';
const education = await directus.request( const education = await directus.request(
readItems('site_education', { readItems('site_education', {
@@ -22,7 +20,7 @@ const certificate = await directus.request(
}) })
); );
const baseClasses = 'rounded-xl flex flex-col group group-hover'; const baseClasses = 'rounded-xl flex flex-col';
const borderClasses = 'border border-neutral-100 dark:border-stone-500/20'; const borderClasses = 'border border-neutral-100 dark:border-stone-500/20';
const bgColorClasses = const bgColorClasses =
'bg-neutral-100/80 hover:bg-neutral-100 dark:bg-neutral-800/60 dark:hover:bg-neutral-800/90'; 'bg-neutral-100/80 hover:bg-neutral-100 dark:bg-neutral-800/60 dark:hover:bg-neutral-800/90';
@@ -42,41 +40,38 @@ const shadowClasses = 'shadow-xs hover:shadow-md dark:shadow-md dark:hover:shado
<ul class="space-y-4 py-3"> <ul class="space-y-4 py-3">
<div class="grid md:grid-cols-2 sm:grid-cols-1 gap-4"> <div class="grid md:grid-cols-2 sm:grid-cols-1 gap-4">
{ {
education.map(({ institution, area, url, graduationDate, logo, logoDark }) => { education.map(({ institution, area, url, graduationDate}) => {
return ( return (
<div class="smooth-reveal-cards mt-4 rounded-xl"> <div class="smooth-reveal-cards mt-4 rounded-xl">
<a <div
class={`p-4 md:p-6 transition-all duration-300 ${shadowClasses} ${bgColorClasses} ${baseClasses} ${borderClasses}`} class={`p-4 md:p-6 transition-all duration-300 ${shadowClasses} ${bgColorClasses} ${baseClasses} ${borderClasses}`}
href={url}
> >
<div class="flex items-center"> <h3 class="flex flex-row text-lg font-bold text-neutral-800 dark:text-neutral-200">
<Logo <Icon
srcLight={getDirectusImageURL(logo)} name="mdi:university-outline"
srcDark={getDirectusImageURL(logoDark)} class="mr-2 h-3 w-3 translate-y-1 md:h-5 md:w-5"
alt={`Logo of ${institution}`}
/> />
<h3 class="text-lg font-bold text-neutral-800 dark:text-neutral-200 ml-4">
{institution} {institution}
</h3> </h3>
</div> <p class="mt-2 ml-7 text-xs font-medium text-neutral-600 uppercase dark:text-neutral-400">
<p class="ml-16 text-xs font-medium text-neutral-600 uppercase dark:text-neutral-400">
{area} - {new Date(graduationDate).getFullYear()} {area} - {new Date(graduationDate).getFullYear()}
</p> </p>
<div class="ml-6 flex"> <div class="ml-6 flex">
<div <a
class="group-hover relative inline-block gap-x-1 rounded-lg border border-transparent disabled:pointer-events-none disabled:opacity-50" class="group group-hover relative inline-block gap-x-1 rounded-lg border border-transparent disabled:pointer-events-none disabled:opacity-50"
href={url}
> >
<div class="group-hover:text-steel dark:group-hover:text-bermuda transition-text relative z-10 mx-auto flex min-h-11 items-center text-sm font-semibold text-neutral-600 decoration-2 duration-300 sm:mx-0 sm:mt-4 dark:text-neutral-300"> <div class="group-hover:text-steel dark:group-hover:text-bermuda transition-text relative z-10 mx-auto flex min-h-[44px] items-center text-sm font-semibold text-neutral-600 decoration-2 duration-300 sm:mx-0 sm:mt-4 dark:text-neutral-300">
<span class="relative inline-block overflow-hidden"> Visit Page </span> <span class="relative inline-block overflow-hidden"> Visit Page </span>
<Icon <Icon
name="mdi:keyboard-arrow-right" name="mdi:keyboard-arrow-right"
class="translate-y-0.5 transition duration-300 group-hover:translate-x-1" class="translate-y-0.5 transition duration-300 group-hover:translate-x-1"
/> />
</div> </div>
</div>
</div>
</a> </a>
</div> </div>
</div>
</div>
); );
}) })
} }
@@ -92,39 +87,38 @@ const shadowClasses = 'shadow-xs hover:shadow-md dark:shadow-md dark:hover:shado
</h4> </h4>
<ul class="space-y-4 py-3"> <ul class="space-y-4 py-3">
<div class="grid md:grid-cols-2 sm:grid-cols-1 gap-4"> <div class="grid md:grid-cols-2 sm:grid-cols-1 gap-4">
{certificate.map(({ name, issuer, issuerDate, url, logoName }) => { {certificate.map(({ name, issuer, url }) => {
return ( return (
<div class="smooth-reveal-cards mt-4 rounded-xl"> <div class="smooth-reveal-cards mt-4 rounded-xl">
<a <div
class={`p-4 md:p-6 transition-all duration-300 ${shadowClasses} ${bgColorClasses} ${baseClasses} ${borderClasses}`} class={`p-4 md:p-6 transition-all duration-300 ${shadowClasses} ${bgColorClasses} ${baseClasses} ${borderClasses}`}
href={url}
> >
<div class="flex items-center"> <h3 class="flex flex-row text-lg font-bold text-neutral-800 dark:text-neutral-200">
<div class="text-neutral-800 dark:text-neutral-200"> <Icon
<Icon name={logoName} class="h-12 w-12" /> name="mdi:script-text-outline"
</div> class="mr-2 h-3 w-3 translate-y-1 md:h-5 md:w-5"
<h3 class="text-lg font-bold text-neutral-800 dark:text-neutral-200 ml-4"> />
{name} {name}
</h3> </h3>
</div> <p class="mt-2 ml-7 text-xs font-medium text-neutral-600 uppercase dark:text-neutral-400">
<p class="ml-16 text-xs font-medium text-neutral-600 uppercase dark:text-neutral-400"> {issuer}
{issuer} - {new Date(issuerDate).getFullYear()}
</p> </p>
<div class="ml-6 flex"> <div class="ml-6 flex">
<div <a
class="group-hover relative inline-block gap-x-1 rounded-lg border border-transparent disabled:pointer-events-none disabled:opacity-50" class="group group-hover relative inline-block gap-x-1 rounded-lg border border-transparent disabled:pointer-events-none disabled:opacity-50"
href={url}
> >
<div class="group-hover:text-steel dark:group-hover:text-bermuda transition-text relative z-10 mx-auto flex min-h-11 items-center text-sm font-semibold text-neutral-600 decoration-2 duration-300 sm:mx-0 sm:mt-4 dark:text-neutral-300"> <div class="group-hover:text-steel dark:group-hover:text-bermuda transition-text relative z-10 mx-auto flex min-h-[44px] items-center text-sm font-semibold text-neutral-600 decoration-2 duration-300 sm:mx-0 sm:mt-4 dark:text-neutral-300">
<span class="relative inline-block overflow-hidden"> Visit Page </span> <span class="relative inline-block overflow-hidden"> Visit Page </span>
<Icon <Icon
name="mdi:keyboard-arrow-right" name="mdi:keyboard-arrow-right"
class="translate-y-0.5 transition duration-300 group-hover:translate-x-1" class="translate-y-0.5 transition duration-300 group-hover:translate-x-1"
/> />
</div> </div>
</div>
</div>
</a> </a>
</div> </div>
</div>
</div>
); );
})} })}
</div> </div>

View File

@@ -7,12 +7,12 @@ import FeaturesCard from '@components/ui/cards/FeaturesCard.astro';
const global = await directus.request(readSingleton('site_global')); const global = await directus.request(readSingleton('site_global'));
--- ---
<section class="mx-auto mb-20 max-w-340 px-4 py-10 sm:px-6 lg:px-8 lg:py-14 2xl:max-w-full"> <section class="mx-auto mb-20 max-w-[85rem] px-4 py-10 sm:px-6 lg:px-8 lg:py-14 2xl:max-w-full">
<div <div
class="flex flex-col items-center justify-center gap-y-2 sm:flex-row sm:gap-x-12 sm:gap-y-0 lg:gap-x-24" class="flex flex-col items-center justify-center gap-y-2 sm:flex-row sm:gap-x-12 sm:gap-y-0 lg:gap-x-24"
> >
<div class="max-w-5xl sm:px-6 lg:px-8"> <div class="mx-auto max-w-5xl px-4 sm:px-6 lg:px-8">
<div class="flex flex-wrap gap-6 sm:grid-cols-2 sm:gap-6 lg:grid-cols-3 justify-center"> <div class="grid gap-3 sm:grid-cols-2 sm:gap-6 lg:grid-cols-3">
<FeaturesCard <FeaturesCard
title="Cloud Engineer" title="Cloud Engineer"
description="Full stack and cloud engineer." description="Full stack and cloud engineer."
@@ -25,12 +25,6 @@ const global = await directus.request(readSingleton('site_global'));
url="/categories/homelab/" url="/categories/homelab/"
icon="mdi:home-variant-outline" icon="mdi:home-variant-outline"
/> />
<FeaturesCard
title="Documentation"
description="Reference and guides for my homelab."
url="https://docs.alexlebens.dev"
icon="mdi:file-document-multiple"
/>
<FeaturesCard <FeaturesCard
title="Email" title="Email"
description={`Send me a message.`} description={`Send me a message.`}

View File

@@ -13,7 +13,7 @@ const projects = await directus.request(
}) })
); );
const baseClasses = 'smooth-reveal-cards rounded-xl flex flex-col group group-hover'; const baseClasses = 'smooth-reveal-cards rounded-xl flex flex-col';
const borderClasses = 'border border-neutral-100 dark:border-stone-500/20'; const borderClasses = 'border border-neutral-100 dark:border-stone-500/20';
const bgColorClasses = const bgColorClasses =
'bg-neutral-100/80 hover:bg-neutral-100 dark:bg-neutral-800/60 dark:hover:bg-neutral-800/90'; 'bg-neutral-100/80 hover:bg-neutral-100 dark:bg-neutral-800/60 dark:hover:bg-neutral-800/90';
@@ -31,9 +31,8 @@ const shadowClasses = 'shadow-xs hover:shadow-md dark:shadow-md dark:hover:shado
projects.map((project: Project) => { projects.map((project: Project) => {
return ( return (
<div class={`${baseClasses}`}> <div class={`${baseClasses}`}>
<a <div
class={`rounded-xl transition-all duration-300 ${borderClasses} ${bgColorClasses} ${shadowClasses}`} class={`rounded-xl transition-all duration-300 ${borderClasses} ${bgColorClasses} ${shadowClasses}`}
href={project.source}
> >
<div class="p-4 md:p-10"> <div class="p-4 md:p-10">
<h3 class="text-lg font-bold text-gray-800 dark:text-white">{project.name}</h3> <h3 class="text-lg font-bold text-gray-800 dark:text-white">{project.name}</h3>
@@ -44,22 +43,31 @@ const shadowClasses = 'shadow-xs hover:shadow-md dark:shadow-md dark:hover:shado
})} })}
</ul> </ul>
<div class="flex"> <div class="flex">
<div <a
class="group group-hover relative inline-block gap-x-1 rounded-lg border border-transparent disabled:pointer-events-none disabled:opacity-50" class="group group-hover relative inline-block gap-x-1 rounded-lg border border-transparent disabled:pointer-events-none disabled:opacity-50"
href={project.url}
> >
<div class="group-hover:text-gitea-primary dark:group-hover:text-gitea-primary transition-text text-md relative z-10 mx-auto flex min-h-11 items-center font-semibold text-neutral-600 decoration-2 duration-300 sm:mx-0 sm:mt-4 dark:text-neutral-300"> <div class="group-hover:text-steel dark:group-hover:text-bermuda transition-text text-md relative z-10 mx-auto flex min-h-[44px] items-center font-semibold text-neutral-600 decoration-2 duration-300 sm:mx-0 sm:mt-4 dark:text-neutral-300">
<Icon name="pajamas:gitea" /> <span class="relative inline-block overflow-hidden"> Visit Page </span>
<span class="relative inline-block overflow-hidden ml-2"> Visit Source </span>
<Icon <Icon
name="mdi:keyboard-arrow-right" name="mdi:keyboard-arrow-right"
class="translate-y-0.5 transition duration-300 group-hover:translate-x-1" class="translate-y-0.5 transition duration-300 group-hover:translate-x-1"
/> />
</div> </div>
</div> </a>
</div> <a
class="group group-hover relative ml-auto inline-block gap-x-1 rounded-lg border border-transparent disabled:pointer-events-none disabled:opacity-50"
href={project.source}
>
<div class="group-hover:text-gitea-primary dark:group-hover:text-gitea-primary transition-text text-md relative z-10 mx-auto flex min-h-[44px] items-center font-semibold text-neutral-600 decoration-2 duration-300 sm:mx-0 sm:mt-4 dark:text-neutral-300">
<span class="relative inline-block overflow-hidden"> Source </span>
<Icon name="pajamas:gitea" class="ml-2 translate-y-0.5" />
</div> </div>
</a> </a>
</div> </div>
</div>
</div>
</div>
); );
}) })
} }

View File

@@ -13,14 +13,13 @@ export const NavigationLinks: NavigationLink[] = [
{ name: 'Home', url: '/' }, { name: 'Home', url: '/' },
{ name: 'Blog', url: '/blog/' }, { name: 'Blog', url: '/blog/' },
{ name: 'Categories', url: '/categories/' }, { name: 'Categories', url: '/categories/' },
{ name: 'Apps', url: '/apps/' },
{ name: 'About Me', url: '/about/' }, { name: 'About Me', url: '/about/' },
]; ];
export const FooterLinks: NavigationLink[] = [ export const FooterLinks: NavigationLink[] = [
{ name: 'RSS', url: '/rss.xml' }, { name: 'RSS', url: '/rss.xml' },
{ name: 'Gitea', url: 'https://gitea.alexlebens.dev' }, { name: 'Gitea', url: '/https://gitea.alexlebens.dev' },
{ name: 'Docs', url: 'https://docs.alexlebens.dev' }, { name: 'Docs', url: '/https://docs.alexlebens.dev' },
]; ];
export const SEO = { export const SEO = {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 MiB

View File

@@ -3,7 +3,6 @@ import { createDirectus, rest } from '@directus/sdk';
import type { import type {
Global, Global,
Post, Post,
Application,
Experience, Experience,
Education, Education,
Certificate, Certificate,
@@ -16,7 +15,6 @@ import { getDirectusURL } from '@lib/directusFunctions';
type Schema = { type Schema = {
site_global: Global; site_global: Global;
posts: Post[]; posts: Post[];
site_applications: Application;
site_experience: Experience; site_experience: Experience;
site_education: Education; site_education: Education;
site_certificate: Certificate; site_certificate: Certificate;

View File

@@ -2,7 +2,7 @@ const getDirectusURL = () => {
if (process.env.DIRECTUS_URL) { if (process.env.DIRECTUS_URL) {
return `https://${process.env.DIRECTUS_URL}`; return `https://${process.env.DIRECTUS_URL}`;
} }
return 'https://directus.alexlebens.net'; return 'https://directus.alexlebens.dev';
}; };
async function getDirectusImageURL(image: string) { async function getDirectusImageURL(image: string) {

View File

@@ -3,7 +3,6 @@ export type Global = {
about: string; about: string;
about_description: string; about_description: string;
about_blog: string; about_blog: string;
about_applications: string;
about_categories: string; about_categories: string;
initials: string; initials: string;
email: string; email: string;
@@ -13,12 +12,10 @@ export type Global = {
portrait_alt: string; portrait_alt: string;
home_image: string; home_image: string;
home_image_alt: string; home_image_alt: string;
blog_image: string;
blog_image_alt: string;
categories_image: string; categories_image: string;
categories_image_alt: string; categories_image_alt: string;
applications_image: string; blog_image: string;
applications_image_alt: string; blog_image_alt: string;
footer_image: string; footer_image: string;
footer_image_alt: string; footer_image_alt: string;
}; };
@@ -40,16 +37,6 @@ export type Post = {
updated_date: Date; updated_date: Date;
}; };
export type Application = {
id: string;
name: string;
isActive: boolean;
description: string;
highlights: string[];
url: string;
logoUrl: string;
};
export type Experience = { export type Experience = {
id: string; id: string;
name: string; name: string;
@@ -73,8 +60,6 @@ export type Education = {
area: string; area: string;
studyType: string; studyType: string;
graduationDate: string; graduationDate: string;
logo: string;
logoDark: string;
}; };
export type Certificate = { export type Certificate = {
@@ -83,7 +68,6 @@ export type Certificate = {
issuer: string; issuer: string;
issuerDate: string; issuerDate: string;
url: string; url: string;
logoName: string;
}; };
export type Project = { export type Project = {

View File

@@ -1,66 +0,0 @@
---
import { readSingleton } from '@directus/sdk';
import directus from '@lib/directus';
import BaseLayout from '@layouts/BaseLayout.astro';
import HeroSection from '@components/ui/sections/HeroSection.astro';
import Applications from '@components/ui/sections/Applications.astro';
import applicationImg from '@images/cedar_tree.png';
const global = await directus.request(readSingleton('site_global'));
---
<BaseLayout
title="Applications"
description={global.about_applications}
structuredData={{
'@context': 'https://schema.org',
'@type': 'WebPage',
inLanguage: 'en-US',
'@id': Astro.url.href,
url: Astro.url.href,
name: `Applications | ${global.name}`,
description: global.about_applications,
isPartOf: {
'@type': 'WebSite',
url: global.site_url,
name: global.name,
description: global.about,
},
}}
>
<HeroSection
title="Applications"
subTitle={global.about_applications}
src={applicationImg}
alt={global.applications_image_alt}
/>
<section class="mx-auto max-w-340 px-4 sm:px-6 lg:px-8 lg:py-14 pb-10">
<main class="relative grid grid-cols-1 md:grid-cols-6 gap-12 p-2 md:p-16 xl:gap-24 max-w-7xl mx-auto">
<div class="space-y-12 col-span-1 md:col-span-6">
<Applications className="smooth-reveal-2" />
</div>
</main>
</section>
</BaseLayout>
<script>
// Add smooth reveal animations for content after loading
document.addEventListener('astro:page-load', () => {
const animateContent = () => {
// Animate group 1
const smoothReveal = document.querySelectorAll('.smooth-reveal');
smoothReveal.forEach((el, index) => {
setTimeout(
() => {
el.classList.add('animate-reveal');
},
50 + index * 100
);
});
};
animateContent();
});
</script>

View File

@@ -145,7 +145,7 @@ const content = marked.parse(post.content);
</div> </div>
<article <article
class="prose prose-blog sm:prose-lg dark:prose-invert max-w-none text-neutral-800 dark:text-neutral-200" class="prose prose-blog sm:prose-lg dark:prose-invert max-w-none text-justify text-neutral-800 dark:text-neutral-200"
> >
<div set:html={content} /> <div set:html={content} />
</article> </article>