update prettier and add eslint
All checks were successful
renovate / renovate (push) Successful in 18s
test-build / build (push) Successful in 2m11s

This commit is contained in:
2025-06-09 15:54:56 -05:00
parent dbbf886de9
commit 8a05fa4d96
30 changed files with 1226 additions and 207 deletions

View File

@@ -3,4 +3,4 @@
.gitea .gitea
.vscode .vscode
node_modules node_modules
dist dist

View File

@@ -75,7 +75,7 @@ jobs:
with: with:
url: '${{ secrets.NTFY_URL }}' url: '${{ secrets.NTFY_URL }}'
topic: '${{ secrets.NTFY_TOPIC }}' topic: '${{ secrets.NTFY_TOPIC }}'
title: "Gitea Action" title: 'Gitea Action'
priority: 3 priority: 3
headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}' headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}'
tags: action,successfully,completed tags: action,successfully,completed
@@ -88,7 +88,7 @@ jobs:
with: with:
url: '${{ secrets.NTFY_URL }}' url: '${{ secrets.NTFY_URL }}'
topic: '${{ secrets.NTFY_TOPIC }}' topic: '${{ secrets.NTFY_TOPIC }}'
title: "Gitea Action" title: 'Gitea Action'
priority: 4 priority: 4
headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}' headers: '{"Authorization": "Bearer ${{ secrets.NTFY_CRED }}"}'
tags: action,failed tags: action,failed

View File

@@ -2,7 +2,7 @@ name: tag-old-issues
on: on:
schedule: schedule:
- cron: "@daily" - cron: '@daily'
jobs: jobs:
tag-old-issues: tag-old-issues:

View File

@@ -30,5 +30,8 @@ jobs:
- name: Install Dependencies - name: Install Dependencies
run: pnpm install run: pnpm install
- name: Lint Code
run: pnpm lint
- name: Build Project - name: Build Project
run: pnpm build run: pnpm build

1
.gitignore vendored
View File

@@ -24,4 +24,3 @@ pnpm-debug.log*
# ide # ide
.vscode/ .vscode/
site-profile.code-workspace site-profile.code-workspace
.pre-commit-config.yaml

1
.npmrc
View File

@@ -1,3 +1,2 @@
engine-strict=true engine-strict=true
save-exact=true save-exact=true

View File

@@ -1,17 +0,0 @@
{
"printWidth": 100,
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"useTabs": false,
"plugins": ["prettier-plugin-astro", "prettier-plugin-tailwindcss"],
"overrides": [
{
"files": "*.astro",
"options": {
"parser": "astro"
}
}
]
}

View File

@@ -33,4 +33,4 @@ ENV DIRECTUS_URL=https://directus.alexlebens.dev
ENV PORT=4321 ENV PORT=4321
EXPOSE $PORT EXPOSE $PORT
CMD ["node", "./dist/server/entry.mjs"] CMD ["node", "./dist/server/entry.mjs"]

View File

@@ -21,7 +21,7 @@ Personal site used for information about myself and blog.
### Requirements ### Requirements
- Node.js 16+ and pnpm/yarn - Node.js 22+ and pnpm
### Installation ### Installation
@@ -30,22 +30,18 @@ Personal site used for information about myself and blog.
git clone https://gitea.alexlebens.dev/alexlebens/site-profile git clone https://gitea.alexlebens.dev/alexlebens/site-profile
# Navigate to project directory # Navigate to project directory
cd astro-blog cd site-profile
# Install dependencies # Install dependencies
pnpm install pnpm install
# Create .env file from template
cp .env.example .env
# Edit .env with your information
``` ```
### Development ### Development
```bash ```bash
# Start development server # Start development server
pnpm run dev pnpm dev
# Open browser at http://localhost:4321 # Open browser at http://localhost:4321
``` ```
@@ -54,10 +50,10 @@ pnpm run dev
```bash ```bash
# Create production build # Create production build
pnpm run build pnpm build
# Preview production build # Preview production build
pnpm run preview pnpm preview
``` ```
## Project Structure ## Project Structure

View File

@@ -16,14 +16,14 @@ export default defineConfig({
integrations: [tailwindcss(), react()], integrations: [tailwindcss(), react()],
plugins: { plugins: {
"@tailwindcss/postcss": {}, '@tailwindcss/postcss': {},
}, },
vite: { vite: {
plugins: [tailwindcss()] plugins: [tailwindcss()],
}, },
adapter: node({ adapter: node({
mode: 'standalone' mode: 'standalone',
}) }),
}); });

11
eslint.config.mjs Normal file
View File

@@ -0,0 +1,11 @@
import eslintPluginAstro from 'eslint-plugin-astro';
import eslintConfigPrettier from "eslint-config-prettier/flat";
export default [
...eslintPluginAstro.configs.recommended,
eslintConfigPrettier,
{
rules: {
}
}
];

View File

@@ -7,7 +7,9 @@
"dev": "astro dev", "dev": "astro dev",
"build": "astro build", "build": "astro build",
"preview": "astro preview", "preview": "astro preview",
"format": "prettier . --write", "format": "prettier --write \"**/*.{js,jsx,ts,tsx,md,mdx,astro}\"",
"lint": "eslint \"src/**/*.{js,ts,jsx,tsx,astro}\"",
"lint:fix": "eslint --fix \"src/**/*.{js,ts,jsx,tsx,astro}\"",
"astro": "astro" "astro": "astro"
}, },
"dependencies": { "dependencies": {
@@ -32,8 +34,13 @@
}, },
"devDependencies": { "devDependencies": {
"@tailwindcss/typography": "^0.5.16", "@tailwindcss/typography": "^0.5.16",
"@typescript-eslint/parser": "8.34.0",
"eslint": "9.28.0",
"eslint-config-prettier": "10.1.5",
"eslint-plugin-astro": "1.3.1",
"prettier": "^3.5.3", "prettier": "^3.5.3",
"prettier-plugin-astro": "^0.14.0", "prettier-plugin-astro": "^0.14.1",
"prettier-plugin-tailwindcss": "^0.6.0" "prettier-plugin-tailwindcss": "^0.6.12",
"typescript-eslint": "8.34.0"
} }
} }

1075
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
/** @type {import('postcss-load-config').Config} */ /** @type {import('postcss-load-config').Config} */
const config = { const config = {
plugins: { plugins: {
"@tailwindcss/postcss": {}, '@tailwindcss/postcss': {},
autoprefixer: {}, autoprefixer: {},
'postcss-preset-env': { 'postcss-preset-env': {
features: { features: {

23
prettier.config.mjs Normal file
View File

@@ -0,0 +1,23 @@
/** @type {import("prettier").Config} */
const config = {
printWidth: 100,
semi: true,
singleQuote: true,
tabWidth: 2,
trailingComma: 'es5',
useTabs: false,
plugins: [
'prettier-plugin-astro',
'prettier-plugin-tailwindcss',
],
overrides: [
{
files: '*.astro',
options: {
parser: 'astro',
},
},
],
};
export default config;

View File

@@ -6,4 +6,3 @@
} }
</style> </style>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 713 B

After

Width:  |  Height:  |  Size: 712 B

View File

@@ -5,17 +5,17 @@
<div class="theme-transition-all fixed inset-0 -z-10 overflow-hidden"> <div class="theme-transition-all fixed inset-0 -z-10 overflow-hidden">
<!-- Dot pattern background --> <!-- Dot pattern background -->
<div <div
class="bg-grid-pattern theme-transition-bg absolute inset-0 bg-[center_top_-1px] [mask-image:radial-gradient(white,transparent_85%)]" class="bg-grid-pattern theme-transition-bg absolute inset-0 [mask-image:radial-gradient(white,transparent_85%)] bg-[center_top_-1px]"
> >
</div> </div>
<!-- Ambient glow effects --> <!-- Ambient glow effects -->
<div <div
class="animate-glow theme-transition-bg absolute left-1/4 top-1/4 h-96 w-96 -translate-x-1/2 -translate-y-1/2 rounded-full bg-zinc-400/20 opacity-50 blur-3xl dark:bg-zinc-500/20" class="animate-glow theme-transition-bg absolute top-1/4 left-1/4 h-96 w-96 -translate-x-1/2 -translate-y-1/2 rounded-full bg-zinc-400/20 opacity-50 blur-3xl dark:bg-zinc-500/20"
> >
</div> </div>
<div <div
class="animate-glow animation-delay-1000 theme-transition-bg absolute bottom-1/3 right-1/4 h-64 w-64 translate-x-1/2 translate-y-1/2 rounded-full bg-zinc-300/20 opacity-40 blur-3xl dark:bg-zinc-600/20" class="animate-glow animation-delay-1000 theme-transition-bg absolute right-1/4 bottom-1/3 h-64 w-64 translate-x-1/2 translate-y-1/2 rounded-full bg-zinc-300/20 opacity-40 blur-3xl dark:bg-zinc-600/20"
> >
</div> </div>

View File

@@ -33,7 +33,7 @@ const socialLinks = [
> >
<div class="pointer-events-none absolute inset-0 overflow-hidden"> <div class="pointer-events-none absolute inset-0 overflow-hidden">
<div <div
class="theme-transition-all animate-float-slow absolute -right-40 -top-40 h-80 w-80 rounded-full bg-zinc-100 opacity-50 blur-3xl dark:bg-zinc-800/30" class="theme-transition-all animate-float-slow absolute -top-40 -right-40 h-80 w-80 rounded-full bg-zinc-100 opacity-50 blur-3xl dark:bg-zinc-800/30"
> >
</div> </div>
<div <div
@@ -41,12 +41,12 @@ const socialLinks = [
> >
</div> </div>
<div <div
class="theme-transition-all animate-float-slow animation-delay-1000 absolute left-1/4 top-20 h-40 w-40 rounded-full bg-zinc-200/50 opacity-30 blur-2xl dark:bg-zinc-700/20" class="theme-transition-all animate-float-slow animation-delay-1000 absolute top-20 left-1/4 h-40 w-40 rounded-full bg-zinc-200/50 opacity-30 blur-2xl dark:bg-zinc-700/20"
> >
</div> </div>
</div> </div>
<div class="relative px-4 pb-12 pt-16 sm:px-6"> <div class="relative px-4 pt-16 pb-12 sm:px-6">
<div class="mx-auto max-w-4xl"> <div class="mx-auto max-w-4xl">
<!-- Main footer content --> <!-- Main footer content -->
<div class="grid grid-cols-1 gap-10 md:grid-cols-12"> <div class="grid grid-cols-1 gap-10 md:grid-cols-12">
@@ -108,7 +108,7 @@ const socialLinks = [
<!-- Quick links --> <!-- Quick links -->
<div class="col-span-1 md:col-span-3"> <div class="col-span-1 md:col-span-3">
<h3 <h3
class="theme-transition-color relative inline-block pb-2 text-sm font-semibold uppercase tracking-wider text-zinc-900 after:absolute after:bottom-0 after:left-0 after:h-0.5 after:w-8 after:bg-zinc-300 after:content-[''] dark:text-zinc-100 dark:after:bg-zinc-700" class="theme-transition-color relative inline-block pb-2 text-sm font-semibold tracking-wider text-zinc-900 uppercase after:absolute after:bottom-0 after:left-0 after:h-0.5 after:w-8 after:bg-zinc-300 after:content-[''] dark:text-zinc-100 dark:after:bg-zinc-700"
> >
Navigation Navigation
</h3> </h3>

View File

@@ -19,7 +19,7 @@ const currentPath = pathname.slice(1);
--- ---
<header <header
class="fixed left-0 right-0 top-0 z-40 border-b border-zinc-100 bg-white py-4 dark:border-zinc-800 dark:bg-zinc-900" class="fixed top-0 right-0 left-0 z-40 border-b border-zinc-100 bg-white py-4 dark:border-zinc-800 dark:bg-zinc-900"
> >
<div class="mx-auto flex max-w-3xl items-center justify-between px-4"> <div class="mx-auto flex max-w-3xl items-center justify-between px-4">
<!-- Logo --> <!-- Logo -->

View File

@@ -94,7 +94,7 @@ const encodedUrl = encodeURIComponent(url);
> >
<span <span
id="copy-tooltip" id="copy-tooltip"
class="absolute -top-8 left-1/2 -translate-x-1/2 transform whitespace-nowrap rounded bg-zinc-800 px-2 py-1 text-xs text-white opacity-0 transition-opacity duration-300 dark:bg-zinc-700" class="absolute -top-8 left-1/2 -translate-x-1/2 transform rounded bg-zinc-800 px-2 py-1 text-xs whitespace-nowrap text-white opacity-0 transition-opacity duration-300 dark:bg-zinc-700"
> >
Copied! Copied!
</span> </span>

View File

@@ -5,14 +5,14 @@
<button <button
id="theme-toggle" id="theme-toggle"
data-theme-toggle data-theme-toggle
class="group relative touch-manipulation overflow-hidden rounded-full p-1.5 transition-all duration-300 hover:bg-zinc-100 focus:outline-none focus:ring-2 focus:ring-zinc-300 dark:hover:bg-zinc-800 dark:focus:ring-zinc-700 sm:p-2" class="group relative touch-manipulation overflow-hidden rounded-full p-1.5 transition-all duration-300 hover:bg-zinc-100 focus:ring-2 focus:ring-zinc-300 focus:outline-none sm:p-2 dark:hover:bg-zinc-800 dark:focus:ring-zinc-700"
aria-label="Toggle dark mode" aria-label="Toggle dark mode"
> >
<div class="relative z-10 flex h-5 w-5 items-center justify-center"> <div class="relative z-10 flex h-5 w-5 items-center justify-center">
<!-- Sun icon --> <!-- Sun icon -->
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
class="icon-light absolute h-5 w-5 rotate-0 scale-100 text-zinc-800 transition-all duration-500 dark:-rotate-90 dark:scale-0 dark:text-zinc-200" class="icon-light absolute h-5 w-5 scale-100 rotate-0 text-zinc-800 transition-all duration-500 dark:scale-0 dark:-rotate-90 dark:text-zinc-200"
viewBox="0 0 24 24" viewBox="0 0 24 24"
fill="none" fill="none"
stroke="currentColor" stroke="currentColor"
@@ -29,7 +29,7 @@
<!-- Moon icon --> <!-- Moon icon -->
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
class="icon-dark absolute h-5 w-5 rotate-90 scale-0 text-zinc-800 transition-all duration-500 dark:rotate-0 dark:scale-100 dark:text-zinc-200" class="icon-dark absolute h-5 w-5 scale-0 rotate-90 text-zinc-800 transition-all duration-500 dark:scale-100 dark:rotate-0 dark:text-zinc-200"
viewBox="0 0 24 24" viewBox="0 0 24 24"
fill="none" fill="none"
stroke="currentColor" stroke="currentColor"

View File

@@ -30,10 +30,10 @@ try {
--- ---
<Layout title={post.title} description={post.description}> <Layout title={post.title} description={post.description}>
<article class="prose prose-zinc mx-auto max-w-4xl dark:prose-invert lg:prose-lg"> <article class="prose prose-zinc dark:prose-invert lg:prose-lg mx-auto max-w-4xl">
<div class="mb-12"> <div class="mb-12">
<h1 <h1
class="mb-4 text-4xl font-bold tracking-tight text-zinc-900 dark:text-zinc-100 sm:text-5xl" class="mb-4 text-4xl font-bold tracking-tight text-zinc-900 sm:text-5xl dark:text-zinc-100"
> >
{post.title} {post.title}
</h1> </h1>
@@ -76,7 +76,7 @@ try {
{ {
post.updated_date && ( post.updated_date && (
<div class="mt-8 text-sm italic text-zinc-500 dark:text-zinc-400"> <div class="mt-8 text-sm text-zinc-500 italic dark:text-zinc-400">
Last updated on <FormattedDate date={post.updated_date} /> Last updated on <FormattedDate date={post.updated_date} />
</div> </div>
) )

View File

@@ -9,11 +9,11 @@ import Layout from '../layouts/Layout.astro';
<!-- Animated background elements --> <!-- Animated background elements -->
<div class="absolute inset-0 overflow-hidden"> <div class="absolute inset-0 overflow-hidden">
<div <div
class="animate-blob absolute -left-20 -top-20 h-64 w-64 rounded-full bg-zinc-100 opacity-50 blur-3xl dark:bg-zinc-800/50" class="animate-blob absolute -top-20 -left-20 h-64 w-64 rounded-full bg-zinc-100 opacity-50 blur-3xl dark:bg-zinc-800/50"
> >
</div> </div>
<div <div
class="animate-blob animation-delay-2000 absolute right-1/4 top-1/2 h-96 w-96 rounded-full bg-zinc-200 opacity-30 blur-3xl dark:bg-zinc-800/30" class="animate-blob animation-delay-2000 absolute top-1/2 right-1/4 h-96 w-96 rounded-full bg-zinc-200 opacity-30 blur-3xl dark:bg-zinc-800/30"
> >
</div> </div>
<div <div
@@ -26,14 +26,14 @@ import Layout from '../layouts/Layout.astro';
<div class="relative z-10 mx-auto max-w-xl"> <div class="relative z-10 mx-auto max-w-xl">
<div class="glitch-wrapper"> <div class="glitch-wrapper">
<h1 <h1
class="glitch text-9xl font-bold leading-none text-zinc-900 dark:text-zinc-100 sm:text-[12rem]" class="glitch text-9xl leading-none font-bold text-zinc-900 sm:text-[12rem] dark:text-zinc-100"
data-text="404" data-text="404"
> >
404 404
</h1> </h1>
</div> </div>
<h2 class="mt-6 text-2xl font-bold text-zinc-800 dark:text-zinc-200 sm:text-3xl"> <h2 class="mt-6 text-2xl font-bold text-zinc-800 sm:text-3xl dark:text-zinc-200">
Page Not Found Page Not Found
</h2> </h2>
@@ -91,7 +91,7 @@ import Layout from '../layouts/Layout.astro';
<div <div
class="mx-auto mt-16 max-w-md rounded-xl border border-zinc-100 bg-zinc-50 p-6 shadow-sm backdrop-blur-sm dark:border-zinc-700/50 dark:bg-zinc-800/50" class="mx-auto mt-16 max-w-md rounded-xl border border-zinc-100 bg-zinc-50 p-6 shadow-sm backdrop-blur-sm dark:border-zinc-700/50 dark:bg-zinc-800/50"
> >
<h3 class="text-sm font-medium uppercase tracking-wider text-zinc-500 dark:text-zinc-400"> <h3 class="text-sm font-medium tracking-wider text-zinc-500 uppercase dark:text-zinc-400">
Did you know? Did you know?
</h3> </h3>
<p class="mt-2 text-sm text-zinc-700 dark:text-zinc-300" id="fun-fact"> <p class="mt-2 text-sm text-zinc-700 dark:text-zinc-300" id="fun-fact">

View File

@@ -22,18 +22,18 @@ const skills = await directus.request(
<div class="relative mb-12 sm:mb-16 md:mb-20"> <div class="relative mb-12 sm:mb-16 md:mb-20">
<!-- Decorative elements --> <!-- Decorative elements -->
<div <div
class="animate-blob theme-transition-bg absolute -left-10 -top-10 h-36 w-36 rounded-full bg-zinc-100 opacity-30 blur-3xl dark:bg-zinc-800/30 sm:-left-20 sm:-top-20 sm:h-48 sm:w-48 md:h-72 md:w-72" class="animate-blob theme-transition-bg absolute -top-10 -left-10 h-36 w-36 rounded-full bg-zinc-100 opacity-30 blur-3xl sm:-top-20 sm:-left-20 sm:h-48 sm:w-48 md:h-72 md:w-72 dark:bg-zinc-800/30"
> >
</div> </div>
<div <div
class="animate-blob animation-delay-2000 theme-transition-bg absolute -bottom-10 -right-10 h-36 w-36 rounded-full bg-zinc-200 opacity-30 blur-3xl dark:bg-zinc-800/30 sm:-bottom-20 sm:-right-20 sm:h-48 sm:w-48 md:h-72 md:w-72" class="animate-blob animation-delay-2000 theme-transition-bg absolute -right-10 -bottom-10 h-36 w-36 rounded-full bg-zinc-200 opacity-30 blur-3xl sm:-right-20 sm:-bottom-20 sm:h-48 sm:w-48 md:h-72 md:w-72 dark:bg-zinc-800/30"
> >
</div> </div>
<div class="relative grid grid-cols-1 items-center gap-8 md:grid-cols-2 md:gap-12"> <div class="relative grid grid-cols-1 items-center gap-8 md:grid-cols-2 md:gap-12">
<div class="order-2 text-center md:order-1 md:text-left"> <div class="order-2 text-center md:order-1 md:text-left">
<h1 <h1
class="theme-transition-color mb-4 text-3xl font-bold tracking-tight text-zinc-900 dark:text-zinc-100 sm:mb-6 sm:text-4xl md:text-5xl" class="theme-transition-color mb-4 text-3xl font-bold tracking-tight text-zinc-900 sm:mb-6 sm:text-4xl md:text-5xl dark:text-zinc-100"
> >
Hello, I'm <span Hello, I'm <span
class="theme-transition-all bg-gradient-to-r from-zinc-500 to-zinc-900 bg-clip-text text-transparent dark:from-zinc-300 dark:to-zinc-100" class="theme-transition-all bg-gradient-to-r from-zinc-500 to-zinc-900 bg-clip-text text-transparent dark:from-zinc-300 dark:to-zinc-100"
@@ -42,7 +42,7 @@ const skills = await directus.request(
</h1> </h1>
<p <p
class="theme-transition-color mb-6 text-lg leading-relaxed text-zinc-600 dark:text-zinc-400 sm:mb-8 sm:text-xl" class="theme-transition-color mb-6 text-lg leading-relaxed text-zinc-600 sm:mb-8 sm:text-xl dark:text-zinc-400"
> >
{about.background} {about.background}
</p> </p>
@@ -56,7 +56,7 @@ const skills = await directus.request(
<div class="relative order-1 md:order-2"> <div class="relative order-1 md:order-2">
<div <div
class="theme-transition-all mx-auto aspect-square w-full max-w-[280px] overflow-hidden rounded-3xl border-4 border-white shadow-xl dark:border-zinc-800 sm:max-w-[320px] sm:border-8 sm:shadow-2xl md:max-w-md" class="theme-transition-all mx-auto aspect-square w-full max-w-[280px] overflow-hidden rounded-3xl border-4 border-white shadow-xl sm:max-w-[320px] sm:border-8 sm:shadow-2xl md:max-w-md dark:border-zinc-800"
> >
<img <img
src=`${process.env.DIRECTUS_URL ?? "https://directus.alexlebens.dev"}/assets/${global.portrait}` src=`${process.env.DIRECTUS_URL ?? "https://directus.alexlebens.dev"}/assets/${global.portrait}`
@@ -68,7 +68,7 @@ const skills = await directus.request(
<!-- Decorative elements --> <!-- Decorative elements -->
<div <div
class="theme-transition-all absolute -bottom-4 -right-4 flex h-16 w-16 items-center justify-center rounded-full border-2 border-white bg-zinc-100 shadow-lg dark:border-zinc-900 dark:bg-zinc-800 sm:-bottom-6 sm:-right-6 sm:h-20 sm:w-20 sm:border-4 md:h-24 md:w-24" class="theme-transition-all absolute -right-4 -bottom-4 flex h-16 w-16 items-center justify-center rounded-full border-2 border-white bg-zinc-100 shadow-lg sm:-right-6 sm:-bottom-6 sm:h-20 sm:w-20 sm:border-4 md:h-24 md:w-24 dark:border-zinc-900 dark:bg-zinc-800"
> >
<span class="text-2xl sm:text-3xl">👋</span> <span class="text-2xl sm:text-3xl">👋</span>
</div> </div>
@@ -80,18 +80,18 @@ const skills = await directus.request(
<div class="theme-transition-all mb-16 sm:mb-20 md:mb-24"> <div class="theme-transition-all mb-16 sm:mb-20 md:mb-24">
<div class="mx-auto max-w-3xl"> <div class="mx-auto max-w-3xl">
<h2 <h2
class="theme-transition-color mb-6 flex items-center justify-center text-2xl font-bold text-zinc-900 dark:text-zinc-100 sm:mb-8 sm:text-3xl md:justify-start" class="theme-transition-color mb-6 flex items-center justify-center text-2xl font-bold text-zinc-900 sm:mb-8 sm:text-3xl md:justify-start dark:text-zinc-100"
> >
<span <span
class="theme-transition-bg mr-4 hidden h-1 w-8 bg-zinc-300 dark:bg-zinc-700 sm:inline-block sm:w-12" class="theme-transition-bg mr-4 hidden h-1 w-8 bg-zinc-300 sm:inline-block sm:w-12 dark:bg-zinc-700"
></span> ></span>
About Me About Me
<span <span
class="theme-transition-bg ml-4 hidden h-1 w-8 bg-zinc-300 dark:bg-zinc-700 sm:inline-block sm:w-12" class="theme-transition-bg ml-4 hidden h-1 w-8 bg-zinc-300 sm:inline-block sm:w-12 dark:bg-zinc-700"
></span> ></span>
</h2> </h2>
<div class="theme-transition-all prose prose-zinc max-w-none dark:prose-invert"> <div class="theme-transition-all prose prose-zinc dark:prose-invert max-w-none">
<p class="theme-transition-color mb-4 text-base leading-relaxed sm:mb-6 sm:text-lg"> <p class="theme-transition-color mb-4 text-base leading-relaxed sm:mb-6 sm:text-lg">
{about.experience} {about.experience}
</p> </p>
@@ -110,7 +110,7 @@ const skills = await directus.request(
<!-- Skills Section --> <!-- Skills Section -->
<div class="theme-transition-all mb-16 sm:mb-20 md:mb-24"> <div class="theme-transition-all mb-16 sm:mb-20 md:mb-24">
<h2 <h2
class="theme-transition-color mb-8 text-center text-2xl font-bold text-zinc-900 dark:text-zinc-100 sm:mb-12 sm:text-3xl" class="theme-transition-color mb-8 text-center text-2xl font-bold text-zinc-900 sm:mb-12 sm:text-3xl dark:text-zinc-100"
> >
Tech Stack Tech Stack
</h2> </h2>
@@ -122,34 +122,34 @@ const skills = await directus.request(
skills.map((skill, index) => ( skills.map((skill, index) => (
<div <div
key={`${skill.title}-${index}`} key={`${skill.title}-${index}`}
class="skill-card theme-transition-element mx-2 min-w-[220px] transform rounded-xl border border-zinc-200 bg-white transition-all duration-300 hover:-translate-y-2 hover:scale-105 hover:border-zinc-300 hover:shadow-xl dark:border-zinc-700 dark:bg-zinc-800/50 dark:hover:border-zinc-600 sm:mx-4 sm:min-w-[280px]" class="skill-card theme-transition-element mx-2 min-w-[220px] transform rounded-xl border border-zinc-200 bg-white transition-all duration-300 hover:-translate-y-2 hover:scale-105 hover:border-zinc-300 hover:shadow-xl sm:mx-4 sm:min-w-[280px] dark:border-zinc-700 dark:bg-zinc-800/50 dark:hover:border-zinc-600"
> >
<div class="p-4 sm:p-6"> <div class="p-4 sm:p-6">
<div class="mb-4 flex items-center justify-between sm:mb-6"> <div class="mb-4 flex items-center justify-between sm:mb-6">
<div class="flex items-center gap-2 sm:gap-4"> <div class="flex items-center gap-2 sm:gap-4">
<div class="theme-transition-bg theme-transition-color flex h-8 w-8 transform items-center justify-center rounded-lg bg-zinc-100 text-zinc-800 transition-transform group-hover:rotate-12 dark:bg-zinc-800 dark:text-zinc-200 sm:h-12 sm:w-12"> <div class="theme-transition-bg theme-transition-color flex h-8 w-8 transform items-center justify-center rounded-lg bg-zinc-100 text-zinc-800 transition-transform group-hover:rotate-12 sm:h-12 sm:w-12 dark:bg-zinc-800 dark:text-zinc-200">
<skill.icon <skill.icon
size={20} size={20}
className="sm:text-2xl transform transition-all hover:scale-125" className="sm:text-2xl transform transition-all hover:scale-125"
/> />
</div> </div>
<h3 class="theme-transition-color text-base font-semibold text-zinc-900 dark:text-zinc-100 sm:text-xl"> <h3 class="theme-transition-color text-base font-semibold text-zinc-900 sm:text-xl dark:text-zinc-100">
{skill.title} {skill.title}
</h3> </h3>
</div> </div>
<span class="theme-transition-all rounded-full bg-zinc-100 px-2 py-0.5 font-mono text-xs text-zinc-600 dark:bg-zinc-800 dark:text-zinc-400 sm:px-2.5 sm:py-1 sm:text-sm"> <span class="theme-transition-all rounded-full bg-zinc-100 px-2 py-0.5 font-mono text-xs text-zinc-600 sm:px-2.5 sm:py-1 sm:text-sm dark:bg-zinc-800 dark:text-zinc-400">
{skill.level}% {skill.level}%
</span> </span>
</div> </div>
<div class="theme-transition-bg relative h-1.5 w-full overflow-hidden rounded-full bg-zinc-100 dark:bg-zinc-700 sm:h-2"> <div class="theme-transition-bg relative h-1.5 w-full overflow-hidden rounded-full bg-zinc-100 sm:h-2 dark:bg-zinc-700">
<div <div
class="progress-bar-animate theme-transition-bg absolute left-0 top-0 h-full rounded-full bg-gradient-to-r from-zinc-700 via-zinc-600 to-zinc-800 transition-all duration-1000 dark:from-zinc-300 dark:via-zinc-400 dark:to-zinc-200" class="progress-bar-animate theme-transition-bg absolute top-0 left-0 h-full rounded-full bg-gradient-to-r from-zinc-700 via-zinc-600 to-zinc-800 transition-all duration-1000 dark:from-zinc-300 dark:via-zinc-400 dark:to-zinc-200"
style={`width: ${skill.level}%`} style={`width: ${skill.level}%`}
/> />
</div> </div>
<div class="theme-transition-color mt-1 flex justify-between font-mono text-[10px] text-zinc-400 dark:text-zinc-500 sm:mt-2 sm:text-xs"> <div class="theme-transition-color mt-1 flex justify-between font-mono text-[10px] text-zinc-400 sm:mt-2 sm:text-xs dark:text-zinc-500">
<span>Beginner</span> <span>Beginner</span>
<span>Advanced</span> <span>Advanced</span>
</div> </div>
@@ -161,11 +161,11 @@ const skills = await directus.request(
<!-- Gradient overlays for smooth fade effect --> <!-- Gradient overlays for smooth fade effect -->
<div <div
class="theme-transition-bg absolute bottom-0 left-0 top-0 z-10 w-12 bg-gradient-to-r from-white to-transparent dark:from-zinc-900 sm:w-24" class="theme-transition-bg absolute top-0 bottom-0 left-0 z-10 w-12 bg-gradient-to-r from-white to-transparent sm:w-24 dark:from-zinc-900"
> >
</div> </div>
<div <div
class="theme-transition-bg absolute bottom-0 right-0 top-0 z-10 w-12 bg-gradient-to-l from-white to-transparent dark:from-zinc-900 sm:w-24" class="theme-transition-bg absolute top-0 right-0 bottom-0 z-10 w-12 bg-gradient-to-l from-white to-transparent sm:w-24 dark:from-zinc-900"
> >
</div> </div>
</div> </div>
@@ -174,12 +174,12 @@ const skills = await directus.request(
<!-- Contact Section --> <!-- Contact Section -->
<div class="theme-transition-all mx-auto max-w-3xl text-center"> <div class="theme-transition-all mx-auto max-w-3xl text-center">
<h2 <h2
class="theme-transition-color mb-4 text-2xl font-bold text-zinc-900 dark:text-zinc-100 sm:mb-6 sm:text-3xl" class="theme-transition-color mb-4 text-2xl font-bold text-zinc-900 sm:mb-6 sm:text-3xl dark:text-zinc-100"
> >
Get in Touch Get in Touch
</h2> </h2>
<p <p
class="theme-transition-color mb-6 text-base text-zinc-600 dark:text-zinc-400 sm:mb-8 sm:text-lg" class="theme-transition-color mb-6 text-base text-zinc-600 sm:mb-8 sm:text-lg dark:text-zinc-400"
> >
I'm always open to new opportunities and collaborations. If you'd like to work together or I'm always open to new opportunities and collaborations. If you'd like to work together or
just say hello, feel free to reach out. just say hello, feel free to reach out.
@@ -187,7 +187,7 @@ const skills = await directus.request(
<a <a
href=`mailto:${global.email}` href=`mailto:${global.email}`
class="theme-transition-all inline-flex items-center justify-center rounded-lg bg-zinc-900 px-6 py-3 text-base font-medium text-zinc-100 transition-colors hover:bg-zinc-700 dark:bg-zinc-100 dark:text-zinc-900 dark:hover:bg-zinc-300 sm:px-8 sm:py-4 sm:text-lg" class="theme-transition-all inline-flex items-center justify-center rounded-lg bg-zinc-900 px-6 py-3 text-base font-medium text-zinc-100 transition-colors hover:bg-zinc-700 sm:px-8 sm:py-4 sm:text-lg dark:bg-zinc-100 dark:text-zinc-900 dark:hover:bg-zinc-300"
> >
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"

View File

@@ -43,23 +43,23 @@ const { post, nextPost, prevPost } = Astro.props;
> >
<!-- Main Content - Enhanced with better typography and spacing --> <!-- Main Content - Enhanced with better typography and spacing -->
<div <div
class="prose prose-sm prose-zinc max-w-none dark:prose-invert sm:prose-base prose-headings:scroll-mt-24 prose-headings:font-semibold prose-a:font-medium prose-a:text-zinc-800 prose-a:underline-offset-4 hover:prose-a:text-zinc-600 prose-img:rounded-xl dark:prose-a:text-zinc-300 dark:hover:prose-a:text-zinc-100" class="prose prose-sm prose-zinc dark:prose-invert sm:prose-base prose-headings:scroll-mt-24 prose-headings:font-semibold prose-a:font-medium prose-a:text-zinc-800 prose-a:underline-offset-4 hover:prose-a:text-zinc-600 prose-img:rounded-xl dark:prose-a:text-zinc-300 dark:hover:prose-a:text-zinc-100 max-w-none"
> >
<div set:html={post.content} /> <div set:html={post.content} />
</div> </div>
<!-- Next/Previous Navigation - Improved responsive design --> <!-- Next/Previous Navigation - Improved responsive design -->
<div <div
class="mt-12 grid grid-cols-1 gap-4 border-t border-zinc-200 pt-8 dark:border-zinc-800 sm:mt-16 sm:gap-6 sm:pt-12 md:grid-cols-2" class="mt-12 grid grid-cols-1 gap-4 border-t border-zinc-200 pt-8 sm:mt-16 sm:gap-6 sm:pt-12 md:grid-cols-2 dark:border-zinc-800"
> >
{ {
prevPost && ( prevPost && (
<a <a
href={`/blog/${prevPost.slug}`} href={`/blog/${prevPost.slug}`}
class="group relative flex h-full flex-col overflow-hidden rounded-xl border border-zinc-200 p-4 transition-all duration-300 hover:-translate-y-1 hover:bg-zinc-50 dark:border-zinc-800 dark:hover:bg-zinc-800/50 sm:p-6" class="group relative flex h-full flex-col overflow-hidden rounded-xl border border-zinc-200 p-4 transition-all duration-300 hover:-translate-y-1 hover:bg-zinc-50 sm:p-6 dark:border-zinc-800 dark:hover:bg-zinc-800/50"
> >
<div class="absolute inset-0 bg-gradient-to-r from-zinc-100 to-transparent opacity-0 transition-opacity duration-300 group-hover:opacity-100 dark:from-zinc-800 dark:to-transparent" /> <div class="absolute inset-0 bg-gradient-to-r from-zinc-100 to-transparent opacity-0 transition-opacity duration-300 group-hover:opacity-100 dark:from-zinc-800 dark:to-transparent" />
<span class="relative z-10 mb-1 flex items-center gap-1 text-xs font-medium text-zinc-500 dark:text-zinc-400 sm:mb-2 sm:gap-2 sm:text-sm"> <span class="relative z-10 mb-1 flex items-center gap-1 text-xs font-medium text-zinc-500 sm:mb-2 sm:gap-2 sm:text-sm dark:text-zinc-400">
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
width="20" width="20"
@@ -76,7 +76,7 @@ const { post, nextPost, prevPost } = Astro.props;
</svg> </svg>
Previous Article Previous Article
</span> </span>
<h3 class="line-clamp-2 text-base font-medium text-zinc-900 transition-colors group-hover:text-zinc-700 dark:text-white dark:group-hover:text-zinc-300 sm:text-lg"> <h3 class="line-clamp-2 text-base font-medium text-zinc-900 transition-colors group-hover:text-zinc-700 sm:text-lg dark:text-white dark:group-hover:text-zinc-300">
{prevPost.title} {prevPost.title}
</h3> </h3>
</a> </a>
@@ -86,10 +86,10 @@ const { post, nextPost, prevPost } = Astro.props;
nextPost && ( nextPost && (
<a <a
href={`/blog/${nextPost.slug}`} href={`/blog/${nextPost.slug}`}
class="group relative flex h-full flex-col overflow-hidden rounded-xl border border-zinc-200 p-4 transition-all duration-300 hover:-translate-y-1 hover:bg-zinc-50 dark:border-zinc-800 dark:hover:bg-zinc-800/50 sm:p-6 md:text-right" class="group relative flex h-full flex-col overflow-hidden rounded-xl border border-zinc-200 p-4 transition-all duration-300 hover:-translate-y-1 hover:bg-zinc-50 sm:p-6 md:text-right dark:border-zinc-800 dark:hover:bg-zinc-800/50"
> >
<div class="absolute inset-0 bg-gradient-to-l from-zinc-100 to-transparent opacity-0 transition-opacity duration-300 group-hover:opacity-100 dark:from-zinc-800 dark:to-transparent" /> <div class="absolute inset-0 bg-gradient-to-l from-zinc-100 to-transparent opacity-0 transition-opacity duration-300 group-hover:opacity-100 dark:from-zinc-800 dark:to-transparent" />
<span class="relative z-10 mb-1 flex items-center gap-1 text-xs font-medium text-zinc-500 dark:text-zinc-400 sm:mb-2 sm:gap-2 sm:text-sm md:justify-end"> <span class="relative z-10 mb-1 flex items-center gap-1 text-xs font-medium text-zinc-500 sm:mb-2 sm:gap-2 sm:text-sm md:justify-end dark:text-zinc-400">
Next Article Next Article
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@@ -106,7 +106,7 @@ const { post, nextPost, prevPost } = Astro.props;
<path d="m9 18 6-6-6-6" /> <path d="m9 18 6-6-6-6" />
</svg> </svg>
</span> </span>
<h3 class="line-clamp-2 text-base font-medium text-zinc-900 transition-colors group-hover:text-zinc-700 dark:text-white dark:group-hover:text-zinc-300 sm:text-lg"> <h3 class="line-clamp-2 text-base font-medium text-zinc-900 transition-colors group-hover:text-zinc-700 sm:text-lg dark:text-white dark:group-hover:text-zinc-300">
{nextPost.title} {nextPost.title}
</h3> </h3>
</a> </a>

View File

@@ -36,23 +36,23 @@ const allTags = [...new Set(sortedPosts.flatMap((post) => post.tags || []))];
<div class="relative mb-12 sm:mb-20"> <div class="relative mb-12 sm:mb-20">
<!-- Decorative elements --> <!-- Decorative elements -->
<div <div
class="animate-blob absolute -left-10 -top-10 h-48 w-48 rounded-full bg-zinc-100 opacity-30 blur-3xl dark:bg-zinc-800/30 sm:-left-20 sm:-top-20 sm:h-72 sm:w-72" class="animate-blob absolute -top-10 -left-10 h-48 w-48 rounded-full bg-zinc-100 opacity-30 blur-3xl sm:-top-20 sm:-left-20 sm:h-72 sm:w-72 dark:bg-zinc-800/30"
> >
</div> </div>
<div <div
class="animate-blob animation-delay-2000 absolute -bottom-10 -right-10 h-48 w-48 rounded-full bg-zinc-200 opacity-30 blur-3xl dark:bg-zinc-800/30 sm:-bottom-20 sm:-right-20 sm:h-72 sm:w-72" class="animate-blob animation-delay-2000 absolute -right-10 -bottom-10 h-48 w-48 rounded-full bg-zinc-200 opacity-30 blur-3xl sm:-right-20 sm:-bottom-20 sm:h-72 sm:w-72 dark:bg-zinc-800/30"
> >
</div> </div>
<div class="relative text-center"> <div class="relative text-center">
<h1 <h1
class="mb-4 text-3xl font-bold tracking-tight text-zinc-900 dark:text-zinc-100 sm:text-4xl md:text-5xl" class="mb-4 text-3xl font-bold tracking-tight text-zinc-900 sm:text-4xl md:text-5xl dark:text-zinc-100"
> >
Blog Blog
</h1> </h1>
<p <p
class="mx-auto mb-6 max-w-2xl text-sm text-zinc-600 dark:text-zinc-400 sm:mb-10 sm:text-base" class="mx-auto mb-6 max-w-2xl text-sm text-zinc-600 sm:mb-10 sm:text-base dark:text-zinc-400"
> >
Thoughts, ideas, and explorations on technology and selfhosting. Thoughts, ideas, and explorations on technology and selfhosting.
</p> </p>
@@ -65,23 +65,23 @@ const allTags = [...new Set(sortedPosts.flatMap((post) => post.tags || []))];
{ {
sortedPosts.length > 0 && ( sortedPosts.length > 0 && (
<div class="mb-8 sm:mb-12 md:col-span-12"> <div class="mb-8 sm:mb-12 md:col-span-12">
<article class="group relative overflow-hidden rounded-none border-b border-zinc-200 pb-6 dark:border-zinc-800 sm:pb-8"> <article class="group relative overflow-hidden rounded-none border-b border-zinc-200 pb-6 sm:pb-8 dark:border-zinc-800">
<div class="flex h-full flex-col gap-6 sm:gap-8 md:flex-row"> <div class="flex h-full flex-col gap-6 sm:gap-8 md:flex-row">
{sortedPosts[0].image && ( {sortedPosts[0].image && (
<div class="mx-auto h-60 w-full max-w-full overflow-hidden sm:h-80 sm:max-w-md md:mx-0 md:h-96 md:w-1/2"> <div class="mx-auto h-60 w-full max-w-full overflow-hidden sm:h-80 sm:max-w-md md:mx-0 md:h-96 md:w-1/2">
<img <img
src={`${process.env.DIRECTUS_URL ?? 'https://directus.alexlebens.dev'}/assets/${sortedPosts[0].image}`} src={`${process.env.DIRECTUS_URL ?? 'https://directus.alexlebens.dev'}/assets/${sortedPosts[0].image}`}
alt={sortedPosts[0].title} alt={sortedPosts[0].title}
class="h-full w-full object-cover grayscale transition-all duration-700 hover:grayscale-0 group-hover:scale-105" class="h-full w-full object-cover grayscale transition-all duration-700 group-hover:scale-105 hover:grayscale-0"
loading="eager" loading="eager"
/> />
</div> </div>
)} )}
<div class="flex flex-1 flex-col justify-center"> <div class="flex flex-1 flex-col justify-center">
<div class="mb-3 flex items-center justify-center gap-2 text-xs text-zinc-500 dark:text-zinc-400 sm:text-sm md:justify-start"> <div class="mb-3 flex items-center justify-center gap-2 text-xs text-zinc-500 sm:text-sm md:justify-start dark:text-zinc-400">
<span class="font-medium uppercase tracking-wider">Featured</span> <span class="font-medium tracking-wider uppercase">Featured</span>
<span class="h-px w-6 bg-zinc-300 dark:bg-zinc-700 sm:w-8" /> <span class="h-px w-6 bg-zinc-300 sm:w-8 dark:bg-zinc-700" />
{sortedPosts[0].published_date && ( {sortedPosts[0].published_date && (
<time datetime={sortedPosts[0].published_date.toLocaleString()}> <time datetime={sortedPosts[0].published_date.toLocaleString()}>
{sortedPosts[0].published_date.toLocaleString('en-US', { {sortedPosts[0].published_date.toLocaleString('en-US', {
@@ -93,7 +93,7 @@ const allTags = [...new Set(sortedPosts.flatMap((post) => post.tags || []))];
)} )}
</div> </div>
<h2 class="mb-3 text-center text-2xl font-bold text-zinc-900 transition-colors group-hover:text-zinc-700 dark:text-zinc-100 dark:group-hover:text-zinc-300 sm:mb-4 sm:text-3xl md:text-left"> <h2 class="mb-3 text-center text-2xl font-bold text-zinc-900 transition-colors group-hover:text-zinc-700 sm:mb-4 sm:text-3xl md:text-left dark:text-zinc-100 dark:group-hover:text-zinc-300">
<a <a
href={`/blog/${sortedPosts[0].slug}/`} href={`/blog/${sortedPosts[0].slug}/`}
class="before:absolute before:inset-0" class="before:absolute before:inset-0"
@@ -102,7 +102,7 @@ const allTags = [...new Set(sortedPosts.flatMap((post) => post.tags || []))];
</a> </a>
</h2> </h2>
<p class="mb-4 line-clamp-3 text-center text-sm text-zinc-600 dark:text-zinc-400 sm:mb-6 sm:text-base md:text-left"> <p class="mb-4 line-clamp-3 text-center text-sm text-zinc-600 sm:mb-6 sm:text-base md:text-left dark:text-zinc-400">
{sortedPosts[0].description} {sortedPosts[0].description}
</p> </p>
@@ -110,7 +110,7 @@ const allTags = [...new Set(sortedPosts.flatMap((post) => post.tags || []))];
{sortedPosts[0].tags && ( {sortedPosts[0].tags && (
<div class="flex flex-wrap justify-center gap-2 md:justify-start"> <div class="flex flex-wrap justify-center gap-2 md:justify-start">
{sortedPosts[0].tags.slice(0, 2).map((tag) => ( {sortedPosts[0].tags.slice(0, 2).map((tag) => (
<span class="border border-zinc-200 px-2 py-1 text-xs uppercase tracking-wider text-zinc-600 dark:border-zinc-800 dark:text-zinc-400 sm:px-3"> <span class="border border-zinc-200 px-2 py-1 text-xs tracking-wider text-zinc-600 uppercase sm:px-3 dark:border-zinc-800 dark:text-zinc-400">
{tag} {tag}
</span> </span>
))} ))}
@@ -128,7 +128,7 @@ const allTags = [...new Set(sortedPosts.flatMap((post) => post.tags || []))];
<div class="relative md:col-span-3"> <div class="relative md:col-span-3">
<div class="mb-8 space-y-4 md:sticky md:top-24 md:mb-0"> <div class="mb-8 space-y-4 md:sticky md:top-24 md:mb-0">
<h3 <h3
class="mb-4 text-center text-lg font-medium uppercase tracking-wider text-zinc-900 dark:text-zinc-100 md:text-left" class="mb-4 text-center text-lg font-medium tracking-wider text-zinc-900 uppercase md:text-left dark:text-zinc-100"
> >
Archive Archive
</h3> </h3>
@@ -141,12 +141,12 @@ const allTags = [...new Set(sortedPosts.flatMap((post) => post.tags || []))];
years.map((year, index) => ( years.map((year, index) => (
<a <a
href={`#year-${year}`} href={`#year-${year}`}
class={`mr-3 flex items-center whitespace-nowrap rounded-full border-b border-zinc-100 px-4 py-2 transition-colors hover:bg-zinc-50 dark:border-zinc-800 dark:hover:bg-zinc-900 md:mr-0 md:w-full md:whitespace-normal md:rounded-none md:px-0 md:py-3 ${index === 0 ? 'bg-zinc-50 dark:bg-zinc-800/50' : ''}`} class={`mr-3 flex items-center rounded-full border-b border-zinc-100 px-4 py-2 whitespace-nowrap transition-colors hover:bg-zinc-50 md:mr-0 md:w-full md:rounded-none md:px-0 md:py-3 md:whitespace-normal dark:border-zinc-800 dark:hover:bg-zinc-900 ${index === 0 ? 'bg-zinc-50 dark:bg-zinc-800/50' : ''}`}
> >
<span class="text-base font-medium text-zinc-900 dark:text-zinc-100 md:text-lg"> <span class="text-base font-medium text-zinc-900 md:text-lg dark:text-zinc-100">
{year} {year}
</span> </span>
<span class="ml-2 text-xs text-zinc-500 dark:text-zinc-400 md:ml-auto md:text-sm"> <span class="ml-2 text-xs text-zinc-500 md:ml-auto md:text-sm dark:text-zinc-400">
{postsByYear[year].length} post{postsByYear[year].length !== 1 ? 's' : ''} {postsByYear[year].length} post{postsByYear[year].length !== 1 ? 's' : ''}
</span> </span>
</a> </a>
@@ -161,7 +161,7 @@ const allTags = [...new Set(sortedPosts.flatMap((post) => post.tags || []))];
{ {
years.map((year) => ( years.map((year) => (
<div id={`year-${year}`} class="mb-12 scroll-mt-16 sm:mb-20"> <div id={`year-${year}`} class="mb-12 scroll-mt-16 sm:mb-20">
<h2 class="mb-6 border-b border-zinc-200 pb-3 text-center text-xl font-bold text-zinc-900 dark:border-zinc-800 dark:text-zinc-100 sm:mb-8 sm:pb-4 sm:text-2xl md:text-left"> <h2 class="mb-6 border-b border-zinc-200 pb-3 text-center text-xl font-bold text-zinc-900 sm:mb-8 sm:pb-4 sm:text-2xl md:text-left dark:border-zinc-800 dark:text-zinc-100">
{year} {year}
</h2> </h2>
@@ -175,14 +175,14 @@ const allTags = [...new Set(sortedPosts.flatMap((post) => post.tags || []))];
<img <img
src={`${process.env.DIRECTUS_URL ?? 'https://directus.alexlebens.dev'}/assets/${post.image}`} src={`${process.env.DIRECTUS_URL ?? 'https://directus.alexlebens.dev'}/assets/${post.image}`}
alt={post.title} alt={post.title}
class="h-full w-full object-cover grayscale transition-all duration-700 hover:grayscale-0 group-hover:scale-105" class="h-full w-full object-cover grayscale transition-all duration-700 group-hover:scale-105 hover:grayscale-0"
loading="lazy" loading="lazy"
/> />
</div> </div>
)} )}
<div class="flex flex-1 flex-col"> <div class="flex flex-1 flex-col">
<div class="mb-2 flex flex-wrap items-center justify-center gap-3 text-xs text-zinc-500 dark:text-zinc-400 sm:mb-3 sm:gap-4 sm:text-sm md:justify-start"> <div class="mb-2 flex flex-wrap items-center justify-center gap-3 text-xs text-zinc-500 sm:mb-3 sm:gap-4 sm:text-sm md:justify-start dark:text-zinc-400">
{post.pubDate && ( {post.pubDate && (
<time <time
datetime={post.published_date.toLocaleString()} datetime={post.published_date.toLocaleString()}
@@ -196,25 +196,25 @@ const allTags = [...new Set(sortedPosts.flatMap((post) => post.tags || []))];
)} )}
</div> </div>
<h3 class="mb-2 text-center text-lg font-semibold text-zinc-900 transition-colors group-hover:text-zinc-700 dark:text-zinc-100 dark:group-hover:text-zinc-300 sm:mb-3 sm:text-xl md:text-left"> <h3 class="mb-2 text-center text-lg font-semibold text-zinc-900 transition-colors group-hover:text-zinc-700 sm:mb-3 sm:text-xl md:text-left dark:text-zinc-100 dark:group-hover:text-zinc-300">
<a href={`/blog/${post.slug}/`} class="before:absolute before:inset-0"> <a href={`/blog/${post.slug}/`} class="before:absolute before:inset-0">
{post.title} {post.title}
</a> </a>
</h3> </h3>
<p class="mb-4 line-clamp-2 flex-grow text-center text-sm text-zinc-600 dark:text-zinc-400 md:text-left"> <p class="mb-4 line-clamp-2 flex-grow text-center text-sm text-zinc-600 md:text-left dark:text-zinc-400">
{post.description} {post.description}
</p> </p>
{post.tags && ( {post.tags && (
<div class="mt-auto flex flex-wrap justify-center gap-2 md:justify-start"> <div class="mt-auto flex flex-wrap justify-center gap-2 md:justify-start">
{post.tags.slice(0, 2).map((tag) => ( {post.tags.slice(0, 2).map((tag) => (
<span class="border border-zinc-200 px-2 py-1 text-xs uppercase tracking-wider text-zinc-600 dark:border-zinc-800 dark:text-zinc-400 sm:px-3"> <span class="border border-zinc-200 px-2 py-1 text-xs tracking-wider text-zinc-600 uppercase sm:px-3 dark:border-zinc-800 dark:text-zinc-400">
{tag} {tag}
</span> </span>
))} ))}
{post.tags.length > 2 && ( {post.tags.length > 2 && (
<span class="border border-zinc-200 px-2 py-1 text-xs uppercase tracking-wider text-zinc-600 dark:border-zinc-800 dark:text-zinc-400 sm:px-3"> <span class="border border-zinc-200 px-2 py-1 text-xs tracking-wider text-zinc-600 uppercase sm:px-3 dark:border-zinc-800 dark:text-zinc-400">
+{post.tags.length - 2} +{post.tags.length - 2}
</span> </span>
)} )}

View File

@@ -27,17 +27,17 @@ const allTags = [...new Set(posts.flatMap((post) => post.tags || []))].slice(0,
<div class="relative mx-auto max-w-2xl"> <div class="relative mx-auto max-w-2xl">
<!-- Adjusted blob positions and sizes for better mobile appearance --> <!-- Adjusted blob positions and sizes for better mobile appearance -->
<div <div
class="animate-blob theme-transition-bg absolute -left-10 -top-10 h-40 w-40 rounded-full bg-zinc-100 opacity-50 blur-3xl dark:bg-zinc-800/50 sm:-left-20 sm:-top-20 sm:h-64 sm:w-64" class="animate-blob theme-transition-bg absolute -top-10 -left-10 h-40 w-40 rounded-full bg-zinc-100 opacity-50 blur-3xl sm:-top-20 sm:-left-20 sm:h-64 sm:w-64 dark:bg-zinc-800/50"
> >
</div> </div>
<div <div
class="animate-blob animation-delay-2000 theme-transition-bg absolute -bottom-10 -right-10 h-40 w-40 rounded-full bg-zinc-200 opacity-30 blur-3xl dark:bg-zinc-800/30 sm:-bottom-20 sm:-right-20 sm:h-64 sm:w-64" class="animate-blob animation-delay-2000 theme-transition-bg absolute -right-10 -bottom-10 h-40 w-40 rounded-full bg-zinc-200 opacity-30 blur-3xl sm:-right-20 sm:-bottom-20 sm:h-64 sm:w-64 dark:bg-zinc-800/30"
> >
</div> </div>
<div class="relative text-center sm:text-left"> <div class="relative text-center sm:text-left">
<h1 <h1
class="theme-transition-color hero-text text-3xl font-bold tracking-tight text-zinc-900 dark:text-zinc-100 sm:text-4xl md:text-5xl lg:text-6xl" class="theme-transition-color hero-text text-3xl font-bold tracking-tight text-zinc-900 sm:text-4xl md:text-5xl lg:text-6xl dark:text-zinc-100"
> >
<span class="block">Writing on technology,</span> <span class="block">Writing on technology,</span>
<span class="mt-1 block">development, and</span> <span class="mt-1 block">development, and</span>
@@ -51,7 +51,7 @@ const allTags = [...new Set(posts.flatMap((post) => post.tags || []))].slice(0,
</span> </span>
</h1> </h1>
<p <p
class="theme-transition-color mx-auto mt-4 max-w-lg text-base leading-relaxed text-zinc-600 dark:text-zinc-400 sm:mx-0 sm:mt-6 sm:text-lg md:mt-8" class="theme-transition-color mx-auto mt-4 max-w-lg text-base leading-relaxed text-zinc-600 sm:mx-0 sm:mt-6 sm:text-lg md:mt-8 dark:text-zinc-400"
> >
{global.about} {global.about}
</p> </p>
@@ -87,20 +87,20 @@ const allTags = [...new Set(posts.flatMap((post) => post.tags || []))].slice(0,
<!-- Featured Post Section - Improved for mobile --> <!-- Featured Post Section - Improved for mobile -->
<section <section
class="theme-transition-all border-t border-zinc-100 px-4 py-10 dark:border-zinc-800 sm:px-6 sm:py-12 md:py-16" class="theme-transition-all border-t border-zinc-100 px-4 py-10 sm:px-6 sm:py-12 md:py-16 dark:border-zinc-800"
> >
<div class="mx-auto max-w-3xl"> <div class="mx-auto max-w-3xl">
<div <div
class="mb-6 flex flex-col justify-between gap-4 sm:mb-8 sm:flex-row sm:items-center md:mb-12" class="mb-6 flex flex-col justify-between gap-4 sm:mb-8 sm:flex-row sm:items-center md:mb-12"
> >
<h2 <h2
class="theme-transition-color text-center text-xl font-bold tracking-tight text-zinc-900 dark:text-zinc-100 sm:text-left sm:text-2xl md:text-3xl" class="theme-transition-color text-center text-xl font-bold tracking-tight text-zinc-900 sm:text-left sm:text-2xl md:text-3xl dark:text-zinc-100"
> >
Recent Posts Recent Posts
</h2> </h2>
<a <a
href="/blog" href="/blog"
class="theme-transition-color group relative flex min-h-[44px] items-center justify-center self-center text-sm font-medium text-zinc-900 hover:text-zinc-700 dark:text-zinc-100 dark:hover:text-zinc-300 sm:self-auto" class="theme-transition-color group relative flex min-h-[44px] items-center justify-center self-center text-sm font-medium text-zinc-900 hover:text-zinc-700 sm:self-auto dark:text-zinc-100 dark:hover:text-zinc-300"
> >
<span class="flex items-center gap-1"> <span class="flex items-center gap-1">
View all posts View all posts
@@ -129,7 +129,7 @@ const allTags = [...new Set(posts.flatMap((post) => post.tags || []))].slice(0,
{ {
recentPosts.map((post, index) => ( recentPosts.map((post, index) => (
<article class="hover-3d theme-transition-element group relative mx-auto flex w-full max-w-sm flex-col items-start sm:mx-0"> <article class="hover-3d theme-transition-element group relative mx-auto flex w-full max-w-sm flex-col items-start sm:mx-0">
<div class="theme-transition-bg absolute -inset-x-4 -inset-y-6 z-0 scale-95 bg-zinc-50 opacity-0 transition group-hover:scale-100 group-hover:opacity-100 dark:bg-zinc-800/50 sm:-inset-x-6 sm:rounded-2xl" /> <div class="theme-transition-bg absolute -inset-x-4 -inset-y-6 z-0 scale-95 bg-zinc-50 opacity-0 transition group-hover:scale-100 group-hover:opacity-100 sm:-inset-x-6 sm:rounded-2xl dark:bg-zinc-800/50" />
{post.image && ( {post.image && (
<div class="relative z-10 mb-4 aspect-video w-full overflow-hidden rounded-lg"> <div class="relative z-10 mb-4 aspect-video w-full overflow-hidden rounded-lg">
@@ -144,13 +144,13 @@ const allTags = [...new Set(posts.flatMap((post) => post.tags || []))].slice(0,
</div> </div>
)} )}
<div class="theme-transition-color relative z-10 flex w-full flex-wrap items-center justify-center gap-x-3 gap-y-2 text-xs text-zinc-500 dark:text-zinc-400 sm:justify-start sm:gap-x-4"> <div class="theme-transition-color relative z-10 flex w-full flex-wrap items-center justify-center gap-x-3 gap-y-2 text-xs text-zinc-500 sm:justify-start sm:gap-x-4 dark:text-zinc-400">
<time datetime={post.published_date.toLocaleString()} class="font-medium"> <time datetime={post.published_date.toLocaleString()} class="font-medium">
<FormattedDate date={post.published_date} /> <FormattedDate date={post.published_date} />
</time> </time>
</div> </div>
<h3 class="theme-transition-color relative z-10 mt-3 w-full text-center text-lg font-semibold tracking-tight text-zinc-900 transition-colors group-hover:text-zinc-700 dark:text-zinc-100 dark:group-hover:text-zinc-300 sm:text-left sm:text-xl"> <h3 class="theme-transition-color relative z-10 mt-3 w-full text-center text-lg font-semibold tracking-tight text-zinc-900 transition-colors group-hover:text-zinc-700 sm:text-left sm:text-xl dark:text-zinc-100 dark:group-hover:text-zinc-300">
<a <a
href={`/blog/${post.slug}`} href={`/blog/${post.slug}`}
class="flex min-h-[44px] items-center justify-center sm:justify-start" class="flex min-h-[44px] items-center justify-center sm:justify-start"
@@ -160,7 +160,7 @@ const allTags = [...new Set(posts.flatMap((post) => post.tags || []))].slice(0,
</a> </a>
</h3> </h3>
<p class="theme-transition-color relative z-10 mt-2 line-clamp-3 w-full text-center text-sm text-zinc-600 dark:text-zinc-400 sm:mt-3 sm:text-left"> <p class="theme-transition-color relative z-10 mt-2 line-clamp-3 w-full text-center text-sm text-zinc-600 sm:mt-3 sm:text-left dark:text-zinc-400">
{post.description} {post.description}
</p> </p>
@@ -169,7 +169,7 @@ const allTags = [...new Set(posts.flatMap((post) => post.tags || []))].slice(0,
{post.tags.slice(0, 3).map((tag) => ( {post.tags.slice(0, 3).map((tag) => (
<a <a
href={`/topics/${tag}`} href={`/topics/${tag}`}
class="theme-transition-all inline-flex min-h-[28px] items-center rounded-full bg-zinc-100 px-2 py-1 text-xs font-medium text-zinc-800 transition-colors hover:bg-zinc-200 dark:bg-zinc-800 dark:text-zinc-100 dark:hover:bg-zinc-700 sm:px-3" class="theme-transition-all inline-flex min-h-[28px] items-center rounded-full bg-zinc-100 px-2 py-1 text-xs font-medium text-zinc-800 transition-colors hover:bg-zinc-200 sm:px-3 dark:bg-zinc-800 dark:text-zinc-100 dark:hover:bg-zinc-700"
> >
#{tag} #{tag}
</a> </a>
@@ -184,13 +184,13 @@ const allTags = [...new Set(posts.flatMap((post) => post.tags || []))].slice(0,
<a <a
href={`/blog/${post.slug}`} href={`/blog/${post.slug}`}
class="theme-transition-color relative z-10 mx-auto mt-3 flex min-h-[44px] items-center text-sm font-medium text-zinc-700 transition-colors group-hover:text-zinc-900 dark:text-zinc-300 dark:group-hover:text-zinc-100 sm:mx-0 sm:mt-4" class="theme-transition-color relative z-10 mx-auto mt-3 flex min-h-[44px] items-center text-sm font-medium text-zinc-700 transition-colors group-hover:text-zinc-900 sm:mx-0 sm:mt-4 dark:text-zinc-300 dark:group-hover:text-zinc-100"
> >
<span class="relative inline-block overflow-hidden"> <span class="relative inline-block overflow-hidden">
<span class="block transition-transform duration-300 group-hover:-translate-y-full"> <span class="block transition-transform duration-300 group-hover:-translate-y-full">
Read article Read article
</span> </span>
<span class="absolute left-0 top-0 translate-y-full whitespace-nowrap transition-transform duration-300 group-hover:translate-y-0"> <span class="absolute top-0 left-0 translate-y-full whitespace-nowrap transition-transform duration-300 group-hover:translate-y-0">
Explore now Explore now
</span> </span>
</span> </span>
@@ -218,9 +218,9 @@ const allTags = [...new Set(posts.flatMap((post) => post.tags || []))].slice(0,
<!-- Topics/Tags Section - Improved for mobile --> <!-- Topics/Tags Section - Improved for mobile -->
{ {
allTags.length > 0 && ( allTags.length > 0 && (
<section class="theme-transition-all border-t border-zinc-100 px-4 py-10 dark:border-zinc-800 sm:px-6 sm:py-12 md:py-16"> <section class="theme-transition-all border-t border-zinc-100 px-4 py-10 sm:px-6 sm:py-12 md:py-16 dark:border-zinc-800">
<div class="mx-auto max-w-3xl"> <div class="mx-auto max-w-3xl">
<h2 class="theme-transition-color mb-6 text-center text-xl font-bold tracking-tight text-zinc-900 dark:text-zinc-100 sm:mb-8 sm:text-left sm:text-2xl md:text-3xl"> <h2 class="theme-transition-color mb-6 text-center text-xl font-bold tracking-tight text-zinc-900 sm:mb-8 sm:text-left sm:text-2xl md:text-3xl dark:text-zinc-100">
Explore Topics Explore Topics
</h2> </h2>
@@ -230,7 +230,7 @@ const allTags = [...new Set(posts.flatMap((post) => post.tags || []))].slice(0,
return ( return (
<a <a
href={`/topics/${tag}`} href={`/topics/${tag}`}
class="theme-transition-all group flex min-h-[80px] flex-col rounded-xl border border-zinc-200 p-3 transition-all duration-300 hover:bg-zinc-50 dark:border-zinc-800 dark:hover:bg-zinc-800/70 sm:min-h-[90px] sm:p-4 md:p-6" class="theme-transition-all group flex min-h-[80px] flex-col rounded-xl border border-zinc-200 p-3 transition-all duration-300 hover:bg-zinc-50 sm:min-h-[90px] sm:p-4 md:p-6 dark:border-zinc-800 dark:hover:bg-zinc-800/70"
> >
<div class="mb-2 flex items-start justify-between"> <div class="mb-2 flex items-start justify-between">
<span class="theme-transition-color mr-2 text-sm font-medium text-zinc-900 dark:text-zinc-100"> <span class="theme-transition-color mr-2 text-sm font-medium text-zinc-900 dark:text-zinc-100">

View File

@@ -52,11 +52,11 @@ const relatedTags = [
<!-- Header section --> <!-- Header section -->
<div class="relative mb-10 sm:mb-16"> <div class="relative mb-10 sm:mb-16">
<div <div
class="animate-blob absolute -left-20 -top-20 h-48 w-48 rounded-full bg-zinc-100 opacity-30 blur-3xl dark:bg-zinc-900/30 sm:h-64 sm:w-64" class="animate-blob absolute -top-20 -left-20 h-48 w-48 rounded-full bg-zinc-100 opacity-30 blur-3xl sm:h-64 sm:w-64 dark:bg-zinc-900/30"
> >
</div> </div>
<div <div
class="animate-blob animation-delay-2000 absolute -bottom-10 -right-10 h-36 w-36 rounded-full bg-zinc-200 opacity-20 blur-2xl dark:bg-zinc-900/20 sm:h-48 sm:w-48" class="animate-blob animation-delay-2000 absolute -right-10 -bottom-10 h-36 w-36 rounded-full bg-zinc-200 opacity-20 blur-2xl sm:h-48 sm:w-48 dark:bg-zinc-900/20"
> >
</div> </div>
@@ -88,7 +88,7 @@ const relatedTags = [
class="mb-2 flex flex-col justify-center gap-4 sm:flex-row sm:items-center sm:justify-start" class="mb-2 flex flex-col justify-center gap-4 sm:flex-row sm:items-center sm:justify-start"
> >
<div <div
class="tag-icon mx-auto flex h-12 w-12 items-center justify-center rounded-xl bg-zinc-100 shadow-sm dark:bg-zinc-800 sm:mx-0" class="tag-icon mx-auto flex h-12 w-12 items-center justify-center rounded-xl bg-zinc-100 shadow-sm sm:mx-0 dark:bg-zinc-800"
> >
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@@ -108,7 +108,7 @@ const relatedTags = [
</div> </div>
<h1 <h1
class="text-3xl font-bold tracking-tight text-zinc-900 dark:text-zinc-100 sm:text-4xl" class="text-3xl font-bold tracking-tight text-zinc-900 sm:text-4xl dark:text-zinc-100"
> >
<span class="relative"> <span class="relative">
#{tag} #{tag}
@@ -122,7 +122,7 @@ const relatedTags = [
</div> </div>
<p <p
class="mx-auto mt-4 max-w-2xl text-base text-zinc-600 dark:text-zinc-400 sm:mx-0 sm:text-lg" class="mx-auto mt-4 max-w-2xl text-base text-zinc-600 sm:mx-0 sm:text-lg dark:text-zinc-400"
> >
Exploring <span class="font-medium text-zinc-900 dark:text-zinc-100" Exploring <span class="font-medium text-zinc-900 dark:text-zinc-100"
>{sortedPosts.length}</span >{sortedPosts.length}</span
@@ -137,7 +137,7 @@ const relatedTags = [
{ {
relatedTags.length > 0 && ( relatedTags.length > 0 && (
<div class="hide-scrollbar mb-8 overflow-x-auto pb-4 sm:mb-12"> <div class="hide-scrollbar mb-8 overflow-x-auto pb-4 sm:mb-12">
<h2 class="mb-3 text-center text-lg font-medium text-zinc-900 dark:text-zinc-100 sm:text-left"> <h2 class="mb-3 text-center text-lg font-medium text-zinc-900 sm:text-left dark:text-zinc-100">
Related topics Related topics
</h2> </h2>
<div class="flex flex-nowrap justify-center gap-2 sm:justify-start"> <div class="flex flex-nowrap justify-center gap-2 sm:justify-start">
@@ -162,7 +162,7 @@ const relatedTags = [
<div class="relative space-y-6 sm:space-y-8"> <div class="relative space-y-6 sm:space-y-8">
{ {
sortedPosts.map((post) => ( sortedPosts.map((post) => (
<article class="hover-card group relative mx-auto flex max-w-2xl flex-col rounded-2xl border border-zinc-200 p-5 transition-all duration-300 hover:bg-zinc-50/80 hover:shadow-md dark:border-zinc-800 dark:hover:bg-zinc-900/50 sm:mx-0 sm:p-8"> <article class="hover-card group relative mx-auto flex max-w-2xl flex-col rounded-2xl border border-zinc-200 p-5 transition-all duration-300 hover:bg-zinc-50/80 hover:shadow-md sm:mx-0 sm:p-8 dark:border-zinc-800 dark:hover:bg-zinc-900/50">
<div class="absolute inset-0 rounded-2xl bg-gradient-to-br from-zinc-50/0 to-zinc-100/0 opacity-0 transition-opacity duration-500 group-hover:opacity-100 dark:from-zinc-900/0 dark:to-zinc-800/0" /> <div class="absolute inset-0 rounded-2xl bg-gradient-to-br from-zinc-50/0 to-zinc-100/0 opacity-0 transition-opacity duration-500 group-hover:opacity-100 dark:from-zinc-900/0 dark:to-zinc-800/0" />
<div class="flex flex-col gap-5 sm:flex-row sm:gap-6"> <div class="flex flex-col gap-5 sm:flex-row sm:gap-6">
@@ -178,7 +178,7 @@ const relatedTags = [
)} )}
<div class="flex-1"> <div class="flex-1">
<div class="mb-2 flex flex-wrap items-center justify-center gap-3 text-xs text-zinc-500 dark:text-zinc-400 sm:mb-3 sm:justify-start sm:gap-4 sm:text-sm"> <div class="mb-2 flex flex-wrap items-center justify-center gap-3 text-xs text-zinc-500 sm:mb-3 sm:justify-start sm:gap-4 sm:text-sm dark:text-zinc-400">
{post.published_date && ( {post.published_date && (
<time <time
datetime={post.published_date.toLocaleString()} datetime={post.published_date.toLocaleString()}
@@ -204,19 +204,19 @@ const relatedTags = [
)} )}
</div> </div>
<h2 class="mb-2 text-center text-xl font-semibold text-zinc-900 transition-colors group-hover:text-zinc-700 dark:text-zinc-100 dark:group-hover:text-zinc-300 sm:mb-3 sm:text-left sm:text-2xl"> <h2 class="mb-2 text-center text-xl font-semibold text-zinc-900 transition-colors group-hover:text-zinc-700 sm:mb-3 sm:text-left sm:text-2xl dark:text-zinc-100 dark:group-hover:text-zinc-300">
<a href={`/blog/${post.slug}/`} class="before:absolute before:inset-0"> <a href={`/blog/${post.slug}/`} class="before:absolute before:inset-0">
{post.title} {post.title}
</a> </a>
</h2> </h2>
<p class="mb-4 line-clamp-2 text-center text-sm text-zinc-600 dark:text-zinc-400 sm:line-clamp-3 sm:text-left sm:text-base"> <p class="mb-4 line-clamp-2 text-center text-sm text-zinc-600 sm:line-clamp-3 sm:text-left sm:text-base dark:text-zinc-400">
{post.description} {post.description}
</p> </p>
</div> </div>
</div> </div>
<div class="mt-4 flex flex-wrap items-end justify-center border-t border-zinc-100 pt-4 dark:border-zinc-800 sm:justify-between"> <div class="mt-4 flex flex-wrap items-end justify-center border-t border-zinc-100 pt-4 sm:justify-between dark:border-zinc-800">
{post.tags && post.tags.length > 0 && ( {post.tags && post.tags.length > 0 && (
<div class="mb-3 flex flex-wrap justify-center gap-2 sm:mb-0 sm:justify-start"> <div class="mb-3 flex flex-wrap justify-center gap-2 sm:mb-0 sm:justify-start">
{post.tags.slice(0, 3).map((postTag) => ( {post.tags.slice(0, 3).map((postTag) => (
@@ -239,7 +239,7 @@ const relatedTags = [
</div> </div>
)} )}
<div class="mx-auto sm:ml-auto sm:mr-0"> <div class="mx-auto sm:mr-0 sm:ml-auto">
<a <a
href={`/blog/${post.slug}/`} href={`/blog/${post.slug}/`}
class="inline-flex items-center text-sm font-medium text-zinc-700 transition-colors group-hover:text-zinc-900 dark:text-zinc-300 dark:group-hover:text-zinc-100" class="inline-flex items-center text-sm font-medium text-zinc-700 transition-colors group-hover:text-zinc-900 dark:text-zinc-300 dark:group-hover:text-zinc-100"
@@ -250,7 +250,7 @@ const relatedTags = [
<span class="block transition-transform duration-300 group-hover:-translate-y-full"> <span class="block transition-transform duration-300 group-hover:-translate-y-full">
Read article Read article
</span> </span>
<span class="absolute left-0 top-0 translate-y-full whitespace-nowrap transition-transform duration-300 group-hover:translate-y-0"> <span class="absolute top-0 left-0 translate-y-full whitespace-nowrap transition-transform duration-300 group-hover:translate-y-0">
Explore now Explore now
</span> </span>
</span> </span>
@@ -281,14 +281,14 @@ const relatedTags = [
{ {
sortedPosts.length === 0 && ( sortedPosts.length === 0 && (
<div class="py-12 text-center sm:py-20"> <div class="py-12 text-center sm:py-20">
<div class="mb-4 inline-flex h-16 w-16 items-center justify-center rounded-full bg-zinc-100 dark:bg-zinc-800 sm:mb-6 sm:h-20 sm:w-20"> <div class="mb-4 inline-flex h-16 w-16 items-center justify-center rounded-full bg-zinc-100 sm:mb-6 sm:h-20 sm:w-20 dark:bg-zinc-800">
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
fill="none" fill="none"
viewBox="0 0 24 24" viewBox="0 0 24 24"
stroke-width="1.5" stroke-width="1.5"
stroke="currentColor" stroke="currentColor"
class="h-8 w-8 text-zinc-500 dark:text-zinc-400 sm:h-10 sm:w-10" class="h-8 w-8 text-zinc-500 sm:h-10 sm:w-10 dark:text-zinc-400"
> >
<path <path
stroke-linecap="round" stroke-linecap="round"
@@ -297,7 +297,7 @@ const relatedTags = [
/> />
</svg> </svg>
</div> </div>
<h2 class="mb-2 text-xl font-semibold text-zinc-900 dark:text-zinc-100 sm:text-2xl"> <h2 class="mb-2 text-xl font-semibold text-zinc-900 sm:text-2xl dark:text-zinc-100">
No posts found No posts found
</h2> </h2>
<p class="text-zinc-600 dark:text-zinc-400">There are no posts with this tag yet.</p> <p class="text-zinc-600 dark:text-zinc-400">There are no posts with this tag yet.</p>

View File

@@ -34,20 +34,20 @@ const sortedTags = [...tagObjects].sort((a, b) => b.count - a.count);
<!-- Enhanced header section with animated elements - improved for mobile --> <!-- Enhanced header section with animated elements - improved for mobile -->
<div class="theme-transition-element relative mb-8 text-center sm:mb-12 md:mb-16"> <div class="theme-transition-element relative mb-8 text-center sm:mb-12 md:mb-16">
<div <div
class="animate-blob theme-transition-bg absolute -left-16 -top-16 h-36 w-36 rounded-full bg-zinc-100 opacity-50 blur-3xl dark:bg-zinc-800/50 sm:h-48 sm:w-48 md:h-72 md:w-72" class="animate-blob theme-transition-bg absolute -top-16 -left-16 h-36 w-36 rounded-full bg-zinc-100 opacity-50 blur-3xl sm:h-48 sm:w-48 md:h-72 md:w-72 dark:bg-zinc-800/50"
> >
</div> </div>
<div <div
class="animate-blob animation-delay-2000 theme-transition-bg absolute -bottom-16 -right-16 h-36 w-36 rounded-full bg-zinc-200 opacity-30 blur-3xl dark:bg-zinc-800/30 sm:h-48 sm:w-48 md:h-72 md:w-72" class="animate-blob animation-delay-2000 theme-transition-bg absolute -right-16 -bottom-16 h-36 w-36 rounded-full bg-zinc-200 opacity-30 blur-3xl sm:h-48 sm:w-48 md:h-72 md:w-72 dark:bg-zinc-800/30"
> >
</div> </div>
<div <div
class="animate-blob animation-delay-4000 theme-transition-bg absolute right-8 top-8 h-24 w-24 rounded-full bg-zinc-100/30 opacity-40 blur-2xl dark:bg-zinc-700/20 sm:h-32 sm:w-32 md:h-40 md:w-40" class="animate-blob animation-delay-4000 theme-transition-bg absolute top-8 right-8 h-24 w-24 rounded-full bg-zinc-100/30 opacity-40 blur-2xl sm:h-32 sm:w-32 md:h-40 md:w-40 dark:bg-zinc-700/20"
> >
</div> </div>
<h1 <h1
class="theme-transition-color relative mb-3 text-3xl font-bold tracking-tight text-zinc-900 dark:text-zinc-100 sm:mb-4 sm:text-4xl md:mb-6 md:text-5xl lg:text-6xl" class="theme-transition-color relative mb-3 text-3xl font-bold tracking-tight text-zinc-900 sm:mb-4 sm:text-4xl md:mb-6 md:text-5xl lg:text-6xl dark:text-zinc-100"
> >
<span class="relative inline-block"> <span class="relative inline-block">
<span class="relative inline-block"> <span class="relative inline-block">
@@ -60,13 +60,13 @@ const sortedTags = [...tagObjects].sort((a, b) => b.count - a.count);
<span class="relative inline-block"> <span class="relative inline-block">
Topics Topics
<span <span
class="animate-underline theme-transition-bg absolute -bottom-1 left-0 h-0.5 w-full origin-left transform bg-gradient-to-r from-zinc-400 to-zinc-600 dark:from-zinc-600 dark:to-zinc-400 sm:-bottom-2 sm:h-1" class="animate-underline theme-transition-bg absolute -bottom-1 left-0 h-0.5 w-full origin-left transform bg-gradient-to-r from-zinc-400 to-zinc-600 sm:-bottom-2 sm:h-1 dark:from-zinc-600 dark:to-zinc-400"
></span> ></span>
</span> </span>
</span> </span>
</h1> </h1>
<p <p
class="theme-transition-color relative mx-auto max-w-2xl text-sm text-zinc-600 dark:text-zinc-400 sm:text-base md:text-lg lg:text-xl" class="theme-transition-color relative mx-auto max-w-2xl text-sm text-zinc-600 sm:text-base md:text-lg lg:text-xl dark:text-zinc-400"
> >
Discover content organized by your interests Discover content organized by your interests
</p> </p>
@@ -75,14 +75,14 @@ const sortedTags = [...tagObjects].sort((a, b) => b.count - a.count);
{ {
tags.length === 0 ? ( tags.length === 0 ? (
<div class="theme-transition-element py-8 text-center sm:py-12 md:py-16"> <div class="theme-transition-element py-8 text-center sm:py-12 md:py-16">
<div class="theme-transition-bg mb-3 inline-flex h-16 w-16 items-center justify-center rounded-full bg-zinc-100 shadow-inner dark:bg-zinc-800 sm:mb-4 sm:h-20 sm:w-20 md:mb-6 md:h-24 md:w-24"> <div class="theme-transition-bg mb-3 inline-flex h-16 w-16 items-center justify-center rounded-full bg-zinc-100 shadow-inner sm:mb-4 sm:h-20 sm:w-20 md:mb-6 md:h-24 md:w-24 dark:bg-zinc-800">
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
fill="none" fill="none"
viewBox="0 0 24 24" viewBox="0 0 24 24"
stroke-width="1.5" stroke-width="1.5"
stroke="currentColor" stroke="currentColor"
class="theme-transition-color h-8 w-8 text-zinc-500 dark:text-zinc-400 sm:h-10 sm:w-10 md:h-12 md:w-12" class="theme-transition-color h-8 w-8 text-zinc-500 sm:h-10 sm:w-10 md:h-12 md:w-12 dark:text-zinc-400"
> >
<path <path
stroke-linecap="round" stroke-linecap="round"
@@ -92,21 +92,21 @@ const sortedTags = [...tagObjects].sort((a, b) => b.count - a.count);
<path stroke-linecap="round" stroke-linejoin="round" d="M6 6h.008v.008H6V6z" /> <path stroke-linecap="round" stroke-linejoin="round" d="M6 6h.008v.008H6V6z" />
</svg> </svg>
</div> </div>
<p class="theme-transition-color text-lg font-medium text-zinc-800 dark:text-zinc-200 sm:text-xl md:text-2xl"> <p class="theme-transition-color text-lg font-medium text-zinc-800 sm:text-xl md:text-2xl dark:text-zinc-200">
No tags found yet. No tags found yet.
</p> </p>
<p class="theme-transition-color mt-2 text-xs text-zinc-500 dark:text-zinc-500 sm:text-sm md:text-base"> <p class="theme-transition-color mt-2 text-xs text-zinc-500 sm:text-sm md:text-base dark:text-zinc-500">
Check back later for categorized content. Check back later for categorized content.
</p> </p>
</div> </div>
) : ( ) : (
<div class="flex w-full justify-center"> <div class="flex w-full justify-center">
<div class="tag-cloud hover-3d glass theme-transition-all relative w-full rounded-lg border border-zinc-100 bg-white/50 p-3 backdrop-blur-sm dark:border-zinc-800 dark:bg-zinc-900/50 sm:rounded-xl sm:p-4 md:rounded-2xl md:p-6 lg:rounded-3xl lg:p-8"> <div class="tag-cloud hover-3d glass theme-transition-all relative w-full rounded-lg border border-zinc-100 bg-white/50 p-3 backdrop-blur-sm sm:rounded-xl sm:p-4 md:rounded-2xl md:p-6 lg:rounded-3xl lg:p-8 dark:border-zinc-800 dark:bg-zinc-900/50">
<div class="bg-grid-pattern theme-transition-bg absolute inset-0 opacity-5 dark:opacity-10" /> <div class="bg-grid-pattern theme-transition-bg absolute inset-0 opacity-5 dark:opacity-10" />
<div class="theme-transition-bg absolute -right-8 -top-8 h-20 w-20 rounded-full bg-gradient-to-br from-zinc-200/30 to-zinc-300/20 blur-xl dark:from-zinc-700/20 dark:to-zinc-800/10 sm:h-24 sm:w-24 md:h-32 md:w-32 lg:h-40 lg:w-40" /> <div class="theme-transition-bg absolute -top-8 -right-8 h-20 w-20 rounded-full bg-gradient-to-br from-zinc-200/30 to-zinc-300/20 blur-xl sm:h-24 sm:w-24 md:h-32 md:w-32 lg:h-40 lg:w-40 dark:from-zinc-700/20 dark:to-zinc-800/10" />
<div class="theme-transition-bg absolute -bottom-8 -left-8 h-20 w-20 rounded-full bg-gradient-to-tl from-zinc-200/30 to-zinc-300/20 blur-xl dark:from-zinc-700/20 dark:to-zinc-800/10 sm:h-24 sm:w-24 md:h-32 md:w-32 lg:h-40 lg:w-40" /> <div class="theme-transition-bg absolute -bottom-8 -left-8 h-20 w-20 rounded-full bg-gradient-to-tl from-zinc-200/30 to-zinc-300/20 blur-xl sm:h-24 sm:w-24 md:h-32 md:w-32 lg:h-40 lg:w-40 dark:from-zinc-700/20 dark:to-zinc-800/10" />
<h2 class="theme-transition-color mb-3 text-center text-lg font-bold text-zinc-900 dark:text-zinc-100 sm:mb-4 sm:text-xl md:mb-6 md:text-2xl lg:mb-8 lg:text-3xl"> <h2 class="theme-transition-color mb-3 text-center text-lg font-bold text-zinc-900 sm:mb-4 sm:text-xl md:mb-6 md:text-2xl lg:mb-8 lg:text-3xl dark:text-zinc-100">
Popular Topics Popular Topics
</h2> </h2>
@@ -114,23 +114,23 @@ const sortedTags = [...tagObjects].sort((a, b) => b.count - a.count);
{sortedTags.map((tag) => ( {sortedTags.map((tag) => (
<a <a
href={`/topics/${tag.name}`} href={`/topics/${tag.name}`}
class="theme-transition-element theme-ripple group relative min-w-0 flex-grow overflow-hidden rounded-md border border-zinc-200 transition-all duration-300 hover:scale-[1.03] hover:border-zinc-300 hover:shadow-md active:scale-95 dark:border-zinc-800 dark:hover:border-zinc-700 sm:rounded-lg sm:hover:shadow-lg md:rounded-xl" class="theme-transition-element theme-ripple group relative min-w-0 flex-grow overflow-hidden rounded-md border border-zinc-200 transition-all duration-300 hover:scale-[1.03] hover:border-zinc-300 hover:shadow-md active:scale-95 sm:rounded-lg sm:hover:shadow-lg md:rounded-xl dark:border-zinc-800 dark:hover:border-zinc-700"
style={`--tag-hue: ${tag.hue};`} style={`--tag-hue: ${tag.hue};`}
> >
<div class="theme-transition-bg absolute inset-0 bg-gradient-to-br from-zinc-50/90 to-zinc-100/90 opacity-100 transition-opacity group-hover:opacity-95 dark:from-zinc-800/90 dark:to-zinc-900/90" /> <div class="theme-transition-bg absolute inset-0 bg-gradient-to-br from-zinc-50/90 to-zinc-100/90 opacity-100 transition-opacity group-hover:opacity-95 dark:from-zinc-800/90 dark:to-zinc-900/90" />
<div class="xxxs:px-2 xxs:px-2 xs:px-2 xxxs:py-2 xxs:py-2 xs:py-2 xxs:gap-2 relative flex w-full items-center gap-1.5 px-1.5 py-1.5 sm:px-3 sm:py-3 md:px-4 md:py-4"> <div class="xxxs:px-2 xxs:px-2 xs:px-2 xxxs:py-2 xxs:py-2 xs:py-2 xxs:gap-2 relative flex w-full items-center gap-1.5 px-1.5 py-1.5 sm:px-3 sm:py-3 md:px-4 md:py-4">
<div class="xxxs:w-6 xxxs:h-6 xxs:w-6 xxs:h-6 xs:w-7 xs:h-7 group-hover:bg-accent/20 dark:group-hover:bg-accent/20 group-hover:text-accent-dark dark:group-hover:text-accent-light theme-transition-all flex h-5 w-5 flex-shrink-0 items-center justify-center rounded-full bg-zinc-100 text-zinc-700 shadow-sm transition-all duration-300 dark:bg-zinc-800 dark:text-zinc-300 sm:h-8 sm:w-8 md:h-10 md:w-10"> <div class="xxxs:w-6 xxxs:h-6 xxs:w-6 xxs:h-6 xs:w-7 xs:h-7 group-hover:bg-accent/20 dark:group-hover:bg-accent/20 group-hover:text-accent-dark dark:group-hover:text-accent-light theme-transition-all flex h-5 w-5 flex-shrink-0 items-center justify-center rounded-full bg-zinc-100 text-zinc-700 shadow-sm transition-all duration-300 sm:h-8 sm:w-8 md:h-10 md:w-10 dark:bg-zinc-800 dark:text-zinc-300">
<span class="xxxs:text-xs xxs:text-xs xs:text-sm text-xs font-semibold sm:text-base md:text-lg"> <span class="xxxs:text-xs xxs:text-xs xs:text-sm text-xs font-semibold sm:text-base md:text-lg">
# #
</span> </span>
</div> </div>
<div class="min-w-0 flex-1 overflow-hidden"> <div class="min-w-0 flex-1 overflow-hidden">
<h3 class="xxxs:text-xs xxs:text-xs xs:text-xs theme-transition-color truncate hyphens-auto break-words text-[10px] font-bold text-zinc-900 transition-colors group-hover:text-zinc-700 dark:text-zinc-100 dark:group-hover:text-zinc-300 sm:text-sm md:text-base"> <h3 class="xxxs:text-xs xxs:text-xs xs:text-xs theme-transition-color truncate text-[10px] font-bold break-words hyphens-auto text-zinc-900 transition-colors group-hover:text-zinc-700 sm:text-sm md:text-base dark:text-zinc-100 dark:group-hover:text-zinc-300">
{tag.name} {tag.name}
</h3> </h3>
<p class="xxxs:text-[9px] xxs:text-[9px] xs:text-[10px] theme-transition-color truncate text-[8px] text-zinc-500 dark:text-zinc-400 sm:text-xs md:text-xs"> <p class="xxxs:text-[9px] xxs:text-[9px] xs:text-[10px] theme-transition-color truncate text-[8px] text-zinc-500 sm:text-xs md:text-xs dark:text-zinc-400">
{tag.count} article{tag.count !== 1 ? 's' : ''} {tag.count} article{tag.count !== 1 ? 's' : ''}
</p> </p>
</div> </div>

View File

@@ -1,5 +1,5 @@
/* Remove all the complex mobile menu styles and keep only what's necessary */ /* Remove all the complex mobile menu styles and keep only what's necessary */
@import "tailwindcss"; @import 'tailwindcss';
@layer base { @layer base {
:root { :root {