Compare commits

..

1 Commits

Author SHA1 Message Date
dd2f401e88 Update dependency eslint to v9.33.0
All checks were successful
renovate/stability-days Updates have met minimum release age requirement
test-build / build (pull_request) Successful in 1m17s
2025-08-11 21:28:50 +00:00
36 changed files with 1800 additions and 764 deletions

View File

@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v4
- name: Login to Registry
uses: docker/login-action@v3

View File

@@ -16,7 +16,7 @@ jobs:
container: ghcr.io/renovatebot/renovate:41
steps:
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v4
- name: Renovate
run: renovate

View File

@@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v4
- name: Set up pnpm
uses: pnpm/action-setup@v4

View File

@@ -1,7 +1,7 @@
ARG REGISTRY=docker.io
FROM ${REGISTRY}/node:22.18.0-alpine3.22 AS base
LABEL version="2.0.5"
LABEL version="2.0.0"
LABEL description="Astro based personal website"
ENV PNPM_HOME="/pnpm"

23
LICENSE.md Normal file
View File

@@ -0,0 +1,23 @@
# MIT License
Copyright (c) 2025 Lê Vĩnh Khang
Copyright (c) 2025 Alex Lebens
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,7 +1,7 @@
{
"name": "site-profile",
"type": "module",
"version": "2.0.5",
"version": "2.0.0",
"homepage": "https://www.alexlebens.dev",
"bugs": {
"url": "https://gitea.alexlebens.dev/alexlebens/site-profile/issues",
@@ -38,7 +38,7 @@
"@iconify-json/mdi": "^1.1.63",
"@iconify-json/pajamas": "^1.2.13",
"@iconify-json/simple-icons": "^1.2.47",
"@playform/compress": "^0.2.0",
"@playform/compress": "^0.0.4",
"@rehype-pretty/transformers": "^0.13.2",
"@swup/astro": "1.7.0",
"@tailwindcss/postcss": "^4.1.8",
@@ -47,7 +47,7 @@
"@types/react": "^19.0.0",
"@types/unist": "^3.0.2",
"astro": "^5.12.8",
"astro-compressor": "^1.0.0",
"astro-compressor": "^0.4.1",
"astro-icon": "^1.1.5",
"framer-motion": "^12.16.0",
"mdast-util-to-string": "^4.0.0",
@@ -78,7 +78,7 @@
"prettier-plugin-astro": "^0.14.1",
"prettier-plugin-tailwindcss": "^0.6.14",
"timeago.js": "^4.0.2",
"typescript": "5.9.2",
"typescript-eslint": "8.39.1"
"typescript": "5.8.3",
"typescript-eslint": "8.38.0"
}
}

2327
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -27,13 +27,13 @@ const currentYear = new Date().getFullYear();
</div>
<span class="ml-3 text-xl font-bold text-neutral-800 dark:text-neutral-200">
{global.name}
Blog
</span>
</div>
</a>
<p class="mt-4 text-sm leading-relaxed text-neutral-600 dark:text-neutral-400">
{global.about}
A description of something.
</p>
</div>
<!-- Left links -->

View File

@@ -5,9 +5,21 @@ interface Props {
description: string;
count: number;
publishDate: string;
layoutPattern?: {
smCol: number;
mdCol: number;
row: number;
index: number;
};
}
const { slug, title, description, count, publishDate } = Astro.props;
const { slug, layoutPattern, title, description, count, publishDate } = Astro.props;
const isSingleItem =
layoutPattern &&
layoutPattern.row === 1 &&
(layoutPattern.smCol === 1 || layoutPattern.mdCol === 1);
const formatedDescription = isSingleItem ? `No description available` : description;
const baseClasses =
'group group-hover rounded-xl flex h-full min-h-[220px] cursor-pointer flex-col overflow-hidden';
@@ -20,17 +32,17 @@ const bgColorClasses =
<div
class={`relative min-h-0 flex-grow overflow-hidden transition-all duration-300 ${bgColorClasses}`}
>
<div class="absolute inset-1 flex flex-col p-3 md:p-4 lg:p-5">
<div class="overflow-hidden">
<h2
class="group-hover:text-steel dark:group-hover:text-bermuda transition-text mb-4 text-4xl font-extrabold tracking-tight text-balance whitespace-nowrap text-neutral-800 duration-300 dark:text-neutral-200"
>
{title}
</h2>
<p class="mb-4 font-light text-neutral-600 sm:text-lg dark:text-neutral-400">
{description}
</p>
</div>
<div class="absolute inset-1 flex flex-col justify-end p-3 md:p-4 lg:p-5">
<h2
class="group-hover:text-steel dark:group-hover:text-bermuda transition-text mb-4 text-4xl font-extrabold tracking-tight text-balance text-neutral-800 duration-300 dark:text-neutral-200"
>
{title}
</h2>
<p
class=`mb-4 ${isSingleItem ? 'hidden lg:block' : ''} max-w-prose text-pretty font-light text-neutral-600 dark:text-neutral-400 sm:text-lg`
>
{formatedDescription}
</p>
<div
class="mt-auto flex items-center justify-between pt-1 text-xs text-neutral-600 md:pt-2 dark:text-neutral-300"
>

View File

@@ -7,6 +7,8 @@ interface Props {
}
const { posts } = Astro.props;
const description = 'Here are a few articles that I think are not bad, hope you like too.';
---
<section class="mx-auto mb-10 max-w-[85rem] px-4 py-8 sm:px-6 lg:px-8 2xl:max-w-full">
@@ -15,8 +17,13 @@ const { posts } = Astro.props;
id="selected-articel"
class="smooth-reveal-2 mb-4 text-5xl font-extrabold tracking-tight text-balance text-neutral-800 dark:text-neutral-200"
>
Older Articles
Posts
</h2>
<p
class="smooth-reveal-2 mb-8 max-w-prose font-light text-pretty text-neutral-600 sm:text-xl dark:text-neutral-400"
>
{description}
</p>
</div>
<div class="flex flex-col md:flex-row md:space-x-12 lg:space-x-16">

View File

@@ -10,7 +10,7 @@ interface Props {
const { title, description, url, icon } = Astro.props;
const baseClasses = 'smooth-reveal-2 group group-hover flex flex-col ';
const baseClasses = 'smooth-reveal-2 group group-hover flex flex-col';
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';
@@ -19,7 +19,7 @@ const shadowClasses = 'shadow-xs hover:shadow-md dark:shadow-md dark:hover:shado
<div class={`${baseClasses}`}>
<a
class={`rounded-xl duration-300 transition-all h-30 ${borderClasses} ${bgColorClasses} ${shadowClasses}`}
class={`rounded-xl duration-300 transition-all ${borderClasses} ${bgColorClasses} ${shadowClasses}`}
href={url}
data-astro-prefetch
>

View File

@@ -15,19 +15,19 @@ const global = await directus.request(readSingleton('site_global'));
<div class="grid gap-3 sm:grid-cols-2 sm:gap-6 lg:grid-cols-3">
<FeaturesCard
title="Cloud Engineer"
description="Full stack and cloud engineer."
url="/about"
description="Full stack and multi cloud engineer"
url="#"
icon="mdi:cloud-outline"
/>
<FeaturesCard
title="Homelab"
description="Tinkering, testing, deploying, etc, etc ..."
url="/categories/homelab/"
url="#"
icon="mdi:home-variant-outline"
/>
<FeaturesCard
title="Email"
description={`Send me a message.`}
title="Email Me"
description={`Reach me at ${global.email}`}
url=`mailto:${global.email}`
icon="mdi:email-fast"
/>

View File

@@ -7,7 +7,6 @@ import BlogCard from '@components/blog/BlogCard.astro';
const posts = await directus.request(
readItems('posts', {
filter: { published: { _eq: true } },
fields: ['*'],
sort: ['-published_date'],
})

View File

@@ -1,4 +1,4 @@
---
title: 'Books 📖'
description: 'Books I have read or listened to'
title: '二愣的小书屋 🔖'
description: '生活总是这样,不能让人处处都满意但我们还要热情地活下去'
---

View File

@@ -1,4 +0,0 @@
---
title: 'Cloud ☁️'
description: "Its just someone else's server"
---

View File

@@ -0,0 +1,4 @@
---
title: 'Golang 🚀'
description: 'Go 语言的词法分析与语法分析及折腾下 Go 编译原理吗'
---

View File

@@ -1,4 +0,0 @@
---
title: 'Homelab 🏠'
description: 'What happens when rack servers find a home'
---

View File

@@ -1,4 +1,4 @@
---
title: 'Kubernetes ☸️'
description: 'The container orchestration system'
title: 'kubernetes 💩'
description: 'Kubernetes 是一个开源系统,用于自动化部署、扩展和管理容器化应用程序。'
---

View File

@@ -0,0 +1,4 @@
---
title: 'Laravel 🐛'
description: '最优雅的 PHP 框架'
---

View File

@@ -1,4 +1,4 @@
---
title: 'Life 🏃🏻'
description: 'Just random musings on everyday stuff'
title: '生活 💃'
description: '房贷要还的,水电费要交的,小孩学费也贵的,钱肯定要不够的呀。所以工作不敢扔,我大部分的快乐,都是来自于生活的夹缝。'
---

View File

@@ -1,4 +0,0 @@
---
title: 'Minnesota 🌳'
description: 'Land of 10,000 Lakes'
---

View File

@@ -0,0 +1,4 @@
---
title: 'MySQL'
description: 'MySQL is an open-source relational database management system (RDBMS).'
---

View File

@@ -0,0 +1,4 @@
---
title: 'Nginx 🐕‍🦺'
description: '高性能的 HTTP 和反向代理 Web 服务器,奈何反向代理的 PHP-FMP 服务太慢。'
---

View File

@@ -0,0 +1,4 @@
---
title: 'PHP 🐘'
description: 'PHP is a popular general-purpose scripting language that is especially suited to web development.'
---

View File

@@ -1,4 +0,0 @@
---
title: 'PostgreSQL'
description: 'PostgreSQL is an open-source relational database management system (RDBMS)'
---

View File

@@ -1,4 +0,0 @@
---
title: 'Python 🐍'
description: 'Generally my go to language'
---

View File

@@ -1,4 +1,4 @@
---
title: 'Tool 🪜'
description: 'Usually just the software kind'
description: '停止折腾就老了吧'
---

View File

@@ -1,4 +1,4 @@
---
title: 'What Is?'
description: 'A series on discovery'
description: '什么是快乐星球,什么是快乐星球,什么是快乐星球'
---

5
src/env.d.ts vendored
View File

@@ -1,3 +1,8 @@
<<<<<<< HEAD
/// <reference path="../.astro/types.d.ts" />
/// <reference types="astro/client" />
/// <reference types="astro/content" />
=======
/// <reference types="astro/client" />
/// <reference path="../.astro/types.d.ts" />
>>>>>>> 184f0c7 (fix path)

View File

@@ -25,7 +25,6 @@ export type Post = {
tags: string[];
category: string;
selected: boolean;
published: boolean;
content: string;
image: string;
image_alt: string;

View File

@@ -13,7 +13,6 @@ import blogImg from '@images/autumn_tree.png';
const global = await directus.request(readSingleton('site_global'));
const posts = await directus.request(
readItems('posts', {
filter: { published: { _eq: true } },
fields: ['*'],
sort: ['-published_date'],
})
@@ -21,7 +20,7 @@ const posts = await directus.request(
const selectedPosts: Post[] = posts.filter((p) => p.selected);
const description =
"Sharing what I've learned, one post at a time. I hope you find something useful.";
'Here are some articles that Alex Lebens believes are not bad, hope you enjoy them.';
---
<BaseLayout

View File

@@ -21,7 +21,6 @@ const { category } = Astro.props;
const global = await directus.request(readSingleton('site_global'));
const posts = await directus.request(
readItems('posts', {
filter: { published: { _eq: true } },
fields: ['*'],
sort: ['-published_date'],
})

View File

@@ -14,7 +14,6 @@ import categoryImg from '@images/autumn_bench.png';
const global = await directus.request(readSingleton('site_global'));
const posts = await directus.request(
readItems('posts', {
filter: { published: { _eq: true } },
fields: ['*'],
sort: ['-published_date'],
})
@@ -75,7 +74,7 @@ const categories = (await getCollection('categories'))
});
const description =
'Here are some of the general categories that I am interested in, including homelabs, technology, and Minnesota.';
'Here are some categories that I am interested in, including Laravel, Golang, and my life.';
---
<BaseLayout
@@ -119,6 +118,7 @@ const description =
description={category.data.description}
count={postMap.get(category.slug)?.length ?? 0}
publishDate={timeago(postMap.get(category.slug)?.[0]?.published_date)}
layoutPattern={category.layoutPattern}
/>
</div>
);

View File

@@ -11,8 +11,7 @@ import homeImg from '@images/autumn_mountain.png';
const global = await directus.request(readSingleton('site_global'));
const description =
'Engineering the cloud by day, homelab by night, and exploring Minnesota in between.';
const description = 'Writing on technology, selfhosting, and me.';
---
<BaseLayout

View File

@@ -23,7 +23,6 @@ export async function GET(context: APIContext) {
// Load the content collection entries to add to our RSS feed.
const posts = await directus.request(
readItems('posts', {
filter: { published: { _eq: true } },
fields: ['*'],
sort: ['-published_date'],
})

58
tailwind.config.cjs Normal file
View File

@@ -0,0 +1,58 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}', '*.{js,ts,jsx,tsx,mdx}'],
darkMode: 'class',
theme: {
extend: {
typography: (theme) => ({
DEFAULT: {
css: {
a: {
color: theme('colors.zinc.900'),
'&:hover': {
color: theme('colors.zinc.700'),
},
textDecoration: 'underline',
textDecorationColor: theme('colors.zinc.400'),
textUnderlineOffset: '2px',
},
'h1, h2, h3, h4, h5, h6': {
color: theme('colors.zinc.900'),
},
code: {
color: theme('colors.zinc.900'),
backgroundColor: theme('colors.zinc.100'),
borderRadius: theme('borderRadius.md'),
padding: `${theme('padding.1')} ${theme('padding.1.5')}`,
},
'code::before': {
content: '""',
},
'code::after': {
content: '""',
},
},
},
invert: {
css: {
a: {
color: theme('colors.zinc.100'),
'&:hover': {
color: theme('colors.zinc.300'),
},
textDecorationColor: theme('colors.zinc.700'),
},
'h1, h2, h3, h4, h5, h6': {
color: theme('colors.zinc.100'),
},
code: {
color: theme('colors.zinc.100'),
backgroundColor: theme('colors.zinc.800'),
},
},
},
}),
},
},
plugins: [require('@tailwindcss/typography')],
};