Compare commits

..

1 Commits

Author SHA1 Message Date
69d83d5db6 chore(deps): update dependency typescript-eslint to v8.56.0
All checks were successful
renovate/stability-days Updates have met minimum release age requirement
test-build / guarddog (pull_request) Successful in 56s
test-build / build (pull_request) Successful in 1m49s
2026-02-18 00:02:30 +00:00
29 changed files with 424 additions and 504 deletions

View File

@@ -25,10 +25,8 @@ jobs:
RENOVATE_ENDPOINT: ${{ vars.INSTANCE_URL }} RENOVATE_ENDPOINT: ${{ vars.INSTANCE_URL }}
RENOVATE_REPOSITORIES: alexlebens/site-profile RENOVATE_REPOSITORIES: alexlebens/site-profile
RENOVATE_GIT_AUTHOR: Renovate Bot <renovate-bot@alexlebens.net> RENOVATE_GIT_AUTHOR: Renovate Bot <renovate-bot@alexlebens.net>
RENOVATE_REDIS_URL: ${{ vars.RENOVATE_REDIS_URL }}
LOG_LEVEL: info LOG_LEVEL: info
RENOVATE_TOKEN: ${{ secrets.RENOVATE_TOKEN }} RENOVATE_TOKEN: ${{ secrets.RENOVATE_TOKEN }}
RENOVATE_GIT_PRIVATE_KEY: ${{ secrets.RENOVATE_GIT_PRIVATE_KEY }} RENOVATE_GIT_PRIVATE_KEY: ${{ secrets.RENOVATE_GIT_PRIVATE_KEY }}
RENOVATE_GITHUB_COM_TOKEN: ${{ secrets.RENOVATE_GITHUB_COM_TOKEN }} RENOVATE_GITHUB_COM_TOKEN: ${{ secrets.RENOVATE_GITHUB_COM_TOKEN }}
RENOVATE_REGISTRY_ALIASES: '{"dhi.io": "dhi.io"}' RENOVATE_REDIS_URL: ${{ vars.RENOVATE_REDIS_URL }}
RENOVATE_HOST_RULES: '[{"matchHost":"dhi.io","hostType":"docker","username":"${{ secrets.RENOVATE_DHI_USER }}","password":"${{ secrets.RENOVATE_DHI_TOKEN }}"}]'

View File

@@ -22,7 +22,12 @@ WORKDIR /app
COPY --from=prod-deps /app/node_modules /app/node_modules COPY --from=prod-deps /app/node_modules /app/node_modules
COPY --from=build /app/dist /app/dist COPY --from=build /app/dist /app/dist
LABEL version="2.14.0" ENV HOST=0.0.0.0
ENV SITE_URL=https://www.alexlebens.dev
ENV DIRECTUS_URL=https://directus.alexlebens.net
ENV PORT=4321
LABEL version="2.12.0"
LABEL description="Astro based personal website" LABEL description="Astro based personal website"
EXPOSE $PORT EXPOSE $PORT

View File

@@ -9,16 +9,17 @@ import tailwindcss from '@tailwindcss/vite';
import icon from 'astro-icon'; import icon from 'astro-icon';
import swup from '@swup/astro'; import swup from '@swup/astro';
import { getSiteURL } from './src/support/url'; const getSiteURL = () => {
if (process.env.SITE_URL) {
return `https://${process.env.SITE_URL}`;
}
return 'http://localhost:4321';
};
export default defineConfig({ export default defineConfig({
site: getSiteURL(), site: getSiteURL(),
image: { image: {
remotePatterns: [
{ protocol: 'https', hostname: '*.alexlebens.net' },
{ protocol: 'https', hostname: '*.jsdelivr.net' },
],
service: { service: {
entrypoint: 'astro/assets/services/sharp', entrypoint: 'astro/assets/services/sharp',
} }

View File

@@ -1,7 +1,7 @@
{ {
"name": "site-profile", "name": "site-profile",
"type": "module", "type": "module",
"version": "2.14.0", "version": "2.12.0",
"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",

367
pnpm-lock.yaml generated
View File

@@ -13,7 +13,7 @@ importers:
version: 0.9.6(prettier-plugin-astro@0.14.1)(prettier@3.8.1)(typescript@5.9.3) version: 0.9.6(prettier-plugin-astro@0.14.1)(prettier@3.8.1)(typescript@5.9.3)
'@astrojs/node': '@astrojs/node':
specifier: ^9.5.3 specifier: ^9.5.3
version: 9.5.4(astro@5.17.3(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@2.79.2)(terser@5.44.1)(typescript@5.9.3)(yaml@2.8.2)) version: 9.5.3(astro@5.17.2(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@2.79.2)(terser@5.44.1)(typescript@5.9.3)(yaml@2.8.2))
'@astrojs/partytown': '@astrojs/partytown':
specifier: ^2.1.4 specifier: ^2.1.4
version: 2.1.4 version: 2.1.4
@@ -40,7 +40,7 @@ importers:
version: 1.2.15 version: 1.2.15
'@iconify-json/simple-icons': '@iconify-json/simple-icons':
specifier: ^1.2.70 specifier: ^1.2.70
version: 1.2.71 version: 1.2.70
'@playform/compress': '@playform/compress':
specifier: ^0.2.1 specifier: ^0.2.1
version: 0.2.1(@types/node@25.2.3)(jiti@2.6.1)(rollup@2.79.2)(typescript@5.9.3)(yaml@2.8.2) version: 0.2.1(@types/node@25.2.3)(jiti@2.6.1)(rollup@2.79.2)(typescript@5.9.3)(yaml@2.8.2)
@@ -49,10 +49,10 @@ importers:
version: 1.8.0(@types/babel__core@7.20.5) version: 1.8.0(@types/babel__core@7.20.5)
'@tailwindcss/postcss': '@tailwindcss/postcss':
specifier: ^4.1.18 specifier: ^4.1.18
version: 4.2.0 version: 4.1.18
'@tailwindcss/vite': '@tailwindcss/vite':
specifier: ^4.1.18 specifier: ^4.1.18
version: 4.2.0(vite@6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)) version: 4.1.18(vite@6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))
'@types/react': '@types/react':
specifier: ^19.2.14 specifier: ^19.2.14
version: 19.2.14 version: 19.2.14
@@ -61,16 +61,16 @@ importers:
version: 3.0.3 version: 3.0.3
astro: astro:
specifier: ^5.17.2 specifier: ^5.17.2
version: 5.17.3(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@2.79.2)(terser@5.44.1)(typescript@5.9.3)(yaml@2.8.2) version: 5.17.2(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@2.79.2)(terser@5.44.1)(typescript@5.9.3)(yaml@2.8.2)
astro-icon: astro-icon:
specifier: ^1.1.5 specifier: ^1.1.5
version: 1.1.5 version: 1.1.5
marked: marked:
specifier: ^17.0.2 specifier: ^17.0.2
version: 17.0.3 version: 17.0.2
marked-shiki: marked-shiki:
specifier: ^1.2.1 specifier: ^1.2.1
version: 1.2.1(marked@17.0.3)(shiki@3.22.0) version: 1.2.1(marked@17.0.2)(shiki@3.22.0)
mdast-util-to-string: mdast-util-to-string:
specifier: ^4.0.0 specifier: ^4.0.0
version: 4.0.0 version: 4.0.0
@@ -97,7 +97,7 @@ importers:
version: 3.22.0 version: 3.22.0
tailwindcss: tailwindcss:
specifier: ^4.1.18 specifier: ^4.1.18
version: 4.2.0 version: 4.1.18
ultrahtml: ultrahtml:
specifier: ^1.6.0 specifier: ^1.6.0
version: 1.6.0 version: 1.6.0
@@ -107,10 +107,10 @@ importers:
version: 2.13.0(eslint@10.0.0(jiti@2.6.1))(typescript@5.9.3) version: 2.13.0(eslint@10.0.0(jiti@2.6.1))(typescript@5.9.3)
'@tailwindcss/forms': '@tailwindcss/forms':
specifier: ^0.5.11 specifier: ^0.5.11
version: 0.5.11(tailwindcss@4.2.0) version: 0.5.11(tailwindcss@4.1.18)
'@tailwindcss/typography': '@tailwindcss/typography':
specifier: ^0.5.19 specifier: ^0.5.19
version: 0.5.19(tailwindcss@4.2.0) version: 0.5.19(tailwindcss@4.1.18)
eslint: eslint:
specifier: ^10.0.0 specifier: ^10.0.0
version: 10.0.0(jiti@2.6.1) version: 10.0.0(jiti@2.6.1)
@@ -190,10 +190,10 @@ packages:
'@astrojs/markdown-remark@6.3.10': '@astrojs/markdown-remark@6.3.10':
resolution: {integrity: sha512-kk4HeYR6AcnzC4QV8iSlOfh+N8TZ3MEStxPyenyCtemqn8IpEATBFMTJcfrNW32dgpt6MY3oCkMM/Tv3/I4G3A==} resolution: {integrity: sha512-kk4HeYR6AcnzC4QV8iSlOfh+N8TZ3MEStxPyenyCtemqn8IpEATBFMTJcfrNW32dgpt6MY3oCkMM/Tv3/I4G3A==}
'@astrojs/node@9.5.4': '@astrojs/node@9.5.3':
resolution: {integrity: sha512-AbPSZsMGu8hXPR2XxV79RaKy8h6wijhtoqZGeUf4OXg2w1mxXlx4VnIc1D+QvtsgauSz7P5PLhmvf6w/J41GJg==} resolution: {integrity: sha512-72jrSn0XtrD7COJVO6TxJmyU1yXdYK7MDdN/+fhqhf4YOhxuIPHclkXrJs8FbLCMx5ur56d/1ijX4XBeneqyXQ==}
peerDependencies: peerDependencies:
astro: ^5.17.3 astro: ^5.14.3
'@astrojs/partytown@2.1.4': '@astrojs/partytown@2.1.4':
resolution: {integrity: sha512-loUrAu0cGYFDC6dHVRiomdsBJ41VjDYXPA+B3Br51V5hENFgDSOLju86OIj1TvBACcsB22UQV7BlppODDG5gig==} resolution: {integrity: sha512-loUrAu0cGYFDC6dHVRiomdsBJ41VjDYXPA+B3Br51V5hENFgDSOLju86OIj1TvBACcsB22UQV7BlppODDG5gig==}
@@ -1258,8 +1258,8 @@ packages:
'@iconify-json/pajamas@1.2.15': '@iconify-json/pajamas@1.2.15':
resolution: {integrity: sha512-utUwcOZLNQQEmyY38lBw2VzAKIHg6sI+PuY42o73P67iEou2eafuZ4UQxHvRdcqf8h7sPm0JlsX2cWm/JkT06Q==} resolution: {integrity: sha512-utUwcOZLNQQEmyY38lBw2VzAKIHg6sI+PuY42o73P67iEou2eafuZ4UQxHvRdcqf8h7sPm0JlsX2cWm/JkT06Q==}
'@iconify-json/simple-icons@1.2.71': '@iconify-json/simple-icons@1.2.70':
resolution: {integrity: sha512-rNoDFbq1fAYiEexBvrw613/xiUOPEu5MKVV/X8lI64AgdTzLQUUemr9f9fplxUMPoxCBP2rWzlhOEeTHk/Sf0Q==} resolution: {integrity: sha512-CYNRCgN6nBTjN4dNkrBCjHXNR2e4hQihdsZUs/afUNFOWLSYjfihca4EFN05rRvDk4Xoy2n8tym6IxBZmcn+Qg==}
'@iconify/tools@4.2.0': '@iconify/tools@4.2.0':
resolution: {integrity: sha512-WRxPva/ipxYkqZd1+CkEAQmd86dQmrwH0vwK89gmp2Kh2WyyVw57XbPng0NehP3x4V1LzLsXUneP1uMfTMZmUA==} resolution: {integrity: sha512-WRxPva/ipxYkqZd1+CkEAQmd86dQmrwH0vwK89gmp2Kh2WyyVw57XbPng0NehP3x4V1LzLsXUneP1uMfTMZmUA==}
@@ -1833,69 +1833,69 @@ packages:
peerDependencies: peerDependencies:
tailwindcss: '>=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20 || >= 4.0.0-beta.1' tailwindcss: '>=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20 || >= 4.0.0-beta.1'
'@tailwindcss/node@4.2.0': '@tailwindcss/node@4.1.18':
resolution: {integrity: sha512-Yv+fn/o2OmL5fh/Ir62VXItdShnUxfpkMA4Y7jdeC8O81WPB8Kf6TT6GSHvnqgSwDzlB5iT7kDpeXxLsUS0T6Q==} resolution: {integrity: sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ==}
'@tailwindcss/oxide-android-arm64@4.2.0': '@tailwindcss/oxide-android-arm64@4.1.18':
resolution: {integrity: sha512-F0QkHAVaW/JNBWl4CEKWdZ9PMb0khw5DCELAOnu+RtjAfx5Zgw+gqCHFvqg3AirU1IAd181fwOtJQ5I8Yx5wtw==} resolution: {integrity: sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q==}
engines: {node: '>= 20'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [android] os: [android]
'@tailwindcss/oxide-darwin-arm64@4.2.0': '@tailwindcss/oxide-darwin-arm64@4.1.18':
resolution: {integrity: sha512-I0QylkXsBsJMZ4nkUNSR04p6+UptjcwhcVo3Zu828ikiEqHjVmQL9RuQ6uT/cVIiKpvtVA25msu/eRV97JeNSA==} resolution: {integrity: sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A==}
engines: {node: '>= 20'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
'@tailwindcss/oxide-darwin-x64@4.2.0': '@tailwindcss/oxide-darwin-x64@4.1.18':
resolution: {integrity: sha512-6TmQIn4p09PBrmnkvbYQ0wbZhLtbaksCDx7Y7R3FYYx0yxNA7xg5KP7dowmQ3d2JVdabIHvs3Hx4K3d5uCf8xg==} resolution: {integrity: sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw==}
engines: {node: '>= 20'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
'@tailwindcss/oxide-freebsd-x64@4.2.0': '@tailwindcss/oxide-freebsd-x64@4.1.18':
resolution: {integrity: sha512-qBudxDvAa2QwGlq9y7VIzhTvp2mLJ6nD/G8/tI70DCDoneaUeLWBJaPcbfzqRIWraj+o969aDQKvKW9dvkUizw==} resolution: {integrity: sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA==}
engines: {node: '>= 20'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [freebsd] os: [freebsd]
'@tailwindcss/oxide-linux-arm-gnueabihf@4.2.0': '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18':
resolution: {integrity: sha512-7XKkitpy5NIjFZNUQPeUyNJNJn1CJeV7rmMR+exHfTuOsg8rxIO9eNV5TSEnqRcaOK77zQpsyUkBWmPy8FgdSg==} resolution: {integrity: sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA==}
engines: {node: '>= 20'} engines: {node: '>= 10'}
cpu: [arm] cpu: [arm]
os: [linux] os: [linux]
'@tailwindcss/oxide-linux-arm64-gnu@4.2.0': '@tailwindcss/oxide-linux-arm64-gnu@4.1.18':
resolution: {integrity: sha512-Mff5a5Q3WoQR01pGU1gr29hHM1N93xYrKkGXfPw/aRtK4bOc331Ho4Tgfsm5WDGvpevqMpdlkCojT3qlCQbCpA==} resolution: {integrity: sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw==}
engines: {node: '>= 20'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
'@tailwindcss/oxide-linux-arm64-musl@4.2.0': '@tailwindcss/oxide-linux-arm64-musl@4.1.18':
resolution: {integrity: sha512-XKcSStleEVnbH6W/9DHzZv1YhjE4eSS6zOu2eRtYAIh7aV4o3vIBs+t/B15xlqoxt6ef/0uiqJVB6hkHjWD/0A==} resolution: {integrity: sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==}
engines: {node: '>= 20'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
libc: [musl] libc: [musl]
'@tailwindcss/oxide-linux-x64-gnu@4.2.0': '@tailwindcss/oxide-linux-x64-gnu@4.1.18':
resolution: {integrity: sha512-/hlXCBqn9K6fi7eAM0RsobHwJYa5V/xzWspVTzxnX+Ft9v6n+30Pz8+RxCn7sQL/vRHHLS30iQPrHQunu6/vJA==} resolution: {integrity: sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==}
engines: {node: '>= 20'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
'@tailwindcss/oxide-linux-x64-musl@4.2.0': '@tailwindcss/oxide-linux-x64-musl@4.1.18':
resolution: {integrity: sha512-lKUaygq4G7sWkhQbfdRRBkaq4LY39IriqBQ+Gk6l5nKq6Ay2M2ZZb1tlIyRNgZKS8cbErTwuYSor0IIULC0SHw==} resolution: {integrity: sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==}
engines: {node: '>= 20'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
libc: [musl] libc: [musl]
'@tailwindcss/oxide-wasm32-wasi@4.2.0': '@tailwindcss/oxide-wasm32-wasi@4.1.18':
resolution: {integrity: sha512-xuDjhAsFdUuFP5W9Ze4k/o4AskUtI8bcAGU4puTYprr89QaYFmhYOPfP+d1pH+k9ets6RoE23BXZM1X1jJqoyw==} resolution: {integrity: sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==}
engines: {node: '>=14.0.0'} engines: {node: '>=14.0.0'}
cpu: [wasm32] cpu: [wasm32]
bundledDependencies: bundledDependencies:
@@ -1906,32 +1906,32 @@ packages:
- '@emnapi/wasi-threads' - '@emnapi/wasi-threads'
- tslib - tslib
'@tailwindcss/oxide-win32-arm64-msvc@4.2.0': '@tailwindcss/oxide-win32-arm64-msvc@4.1.18':
resolution: {integrity: sha512-2UU/15y1sWDEDNJXxEIrfWKC2Yb4YgIW5Xz2fKFqGzFWfoMHWFlfa1EJlGO2Xzjkq/tvSarh9ZTjvbxqWvLLXA==} resolution: {integrity: sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA==}
engines: {node: '>= 20'} engines: {node: '>= 10'}
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
'@tailwindcss/oxide-win32-x64-msvc@4.2.0': '@tailwindcss/oxide-win32-x64-msvc@4.1.18':
resolution: {integrity: sha512-CrFadmFoc+z76EV6LPG1jx6XceDsaCG3lFhyLNo/bV9ByPrE+FnBPckXQVP4XRkN76h3Fjt/a+5Er/oA/nCBvQ==} resolution: {integrity: sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q==}
engines: {node: '>= 20'} engines: {node: '>= 10'}
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
'@tailwindcss/oxide@4.2.0': '@tailwindcss/oxide@4.1.18':
resolution: {integrity: sha512-AZqQzADaj742oqn2xjl5JbIOzZB/DGCYF/7bpvhA8KvjUj9HJkag6bBuwZvH1ps6dfgxNHyuJVlzSr2VpMgdTQ==} resolution: {integrity: sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A==}
engines: {node: '>= 20'} engines: {node: '>= 10'}
'@tailwindcss/postcss@4.2.0': '@tailwindcss/postcss@4.1.18':
resolution: {integrity: sha512-u6YBacGpOm/ixPfKqfgrJEjMfrYmPD7gEFRoygS/hnQaRtV0VCBdpkx5Ouw9pnaLRwwlgGCuJw8xLpaR0hOrQg==} resolution: {integrity: sha512-Ce0GFnzAOuPyfV5SxjXGn0CubwGcuDB0zcdaPuCSzAa/2vII24JTkH+I6jcbXLb1ctjZMZZI6OjDaLPJQL1S0g==}
'@tailwindcss/typography@0.5.19': '@tailwindcss/typography@0.5.19':
resolution: {integrity: sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==} resolution: {integrity: sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==}
peerDependencies: peerDependencies:
tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1' tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1'
'@tailwindcss/vite@4.2.0': '@tailwindcss/vite@4.1.18':
resolution: {integrity: sha512-da9mFCaHpoOgtQiWtDGIikTrSpUFBtIZCG3jy/u2BGV+l/X1/pbxzmIUxNt6JWm19N3WtGi4KlJdSH/Si83WOA==} resolution: {integrity: sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA==}
peerDependencies: peerDependencies:
vite: ^5.2.0 || ^6 || ^7 vite: ^5.2.0 || ^6 || ^7
@@ -2277,8 +2277,8 @@ packages:
engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0'} engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0'}
hasBin: true hasBin: true
astro@5.17.3: astro@5.17.2:
resolution: {integrity: sha512-69dcfPe8LsHzklwj+hl+vunWUbpMB6pmg35mACjetxbJeUNNys90JaBM8ZiwsPK689SAj/4Zqb1ayaANls9/MA==} resolution: {integrity: sha512-7jnMqGo53hOQNwo1N/wqeOvUp8wwW/p+DeerSjSkHNx8L/1mhy6P7rVo7EhdmF8DpKqw0tl/B5Fx1WcIzg1ysA==}
engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0'} engines: {node: 18.20.8 || ^20.3.0 || >=22.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0'}
hasBin: true hasBin: true
@@ -2729,8 +2729,8 @@ packages:
resolution: {integrity: sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ==} resolution: {integrity: sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ==}
engines: {node: '>=18'} engines: {node: '>=18'}
devalue@5.6.3: devalue@5.6.2:
resolution: {integrity: sha512-nc7XjUU/2Lb+SvEFVGcWLiKkzfw8+qHI7zn8WYXKkLMgfGSHbgCEaR6bJpev8Cm6Rmrb19Gfd/tZvGqx9is3wg==} resolution: {integrity: sha512-nPRkjWzzDQlsejL1WVifk5rvcFi/y1onBRxjaFMjZeR9mFpqu2gmAZ9xUB9/IEanEP/vBtGeGganC/GO1fmufg==}
devlop@1.1.0: devlop@1.1.0:
resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
@@ -3228,8 +3228,8 @@ packages:
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
engines: {node: 6.* || 8.* || >= 10.*} engines: {node: 6.* || 8.* || >= 10.*}
get-east-asian-width@1.5.0: get-east-asian-width@1.4.0:
resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} resolution: {integrity: sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==}
engines: {node: '>=18'} engines: {node: '>=18'}
get-intrinsic@1.3.0: get-intrinsic@1.3.0:
@@ -3699,60 +3699,30 @@ packages:
cpu: [arm64] cpu: [arm64]
os: [android] os: [android]
lightningcss-android-arm64@1.31.1:
resolution: {integrity: sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [android]
lightningcss-darwin-arm64@1.30.2: lightningcss-darwin-arm64@1.30.2:
resolution: {integrity: sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==} resolution: {integrity: sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
lightningcss-darwin-arm64@1.31.1:
resolution: {integrity: sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [darwin]
lightningcss-darwin-x64@1.30.2: lightningcss-darwin-x64@1.30.2:
resolution: {integrity: sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==} resolution: {integrity: sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
lightningcss-darwin-x64@1.31.1:
resolution: {integrity: sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [darwin]
lightningcss-freebsd-x64@1.30.2: lightningcss-freebsd-x64@1.30.2:
resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==} resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
cpu: [x64] cpu: [x64]
os: [freebsd] os: [freebsd]
lightningcss-freebsd-x64@1.31.1:
resolution: {integrity: sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [freebsd]
lightningcss-linux-arm-gnueabihf@1.30.2: lightningcss-linux-arm-gnueabihf@1.30.2:
resolution: {integrity: sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==} resolution: {integrity: sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
cpu: [arm] cpu: [arm]
os: [linux] os: [linux]
lightningcss-linux-arm-gnueabihf@1.31.1:
resolution: {integrity: sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==}
engines: {node: '>= 12.0.0'}
cpu: [arm]
os: [linux]
lightningcss-linux-arm64-gnu@1.30.2: lightningcss-linux-arm64-gnu@1.30.2:
resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==} resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
@@ -3760,13 +3730,6 @@ packages:
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
lightningcss-linux-arm64-gnu@1.31.1:
resolution: {integrity: sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
libc: [glibc]
lightningcss-linux-arm64-musl@1.30.2: lightningcss-linux-arm64-musl@1.30.2:
resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==} resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
@@ -3774,13 +3737,6 @@ packages:
os: [linux] os: [linux]
libc: [musl] libc: [musl]
lightningcss-linux-arm64-musl@1.31.1:
resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
libc: [musl]
lightningcss-linux-x64-gnu@1.30.2: lightningcss-linux-x64-gnu@1.30.2:
resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==} resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
@@ -3788,13 +3744,6 @@ packages:
os: [linux] os: [linux]
libc: [glibc] libc: [glibc]
lightningcss-linux-x64-gnu@1.31.1:
resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
libc: [glibc]
lightningcss-linux-x64-musl@1.30.2: lightningcss-linux-x64-musl@1.30.2:
resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==} resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
@@ -3802,45 +3751,22 @@ packages:
os: [linux] os: [linux]
libc: [musl] libc: [musl]
lightningcss-linux-x64-musl@1.31.1:
resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
libc: [musl]
lightningcss-win32-arm64-msvc@1.30.2: lightningcss-win32-arm64-msvc@1.30.2:
resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==} resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
lightningcss-win32-arm64-msvc@1.31.1:
resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [win32]
lightningcss-win32-x64-msvc@1.30.2: lightningcss-win32-x64-msvc@1.30.2:
resolution: {integrity: sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==} resolution: {integrity: sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
cpu: [x64] cpu: [x64]
os: [win32] os: [win32]
lightningcss-win32-x64-msvc@1.31.1:
resolution: {integrity: sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [win32]
lightningcss@1.30.2: lightningcss@1.30.2:
resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==} resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==}
engines: {node: '>= 12.0.0'} engines: {node: '>= 12.0.0'}
lightningcss@1.31.1:
resolution: {integrity: sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==}
engines: {node: '>= 12.0.0'}
lilconfig@2.1.0: lilconfig@2.1.0:
resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==}
engines: {node: '>=10'} engines: {node: '>=10'}
@@ -3930,8 +3856,8 @@ packages:
marked: '>=7.0.0' marked: '>=7.0.0'
shiki: '>=1.0.0' shiki: '>=1.0.0'
marked@17.0.3: marked@17.0.2:
resolution: {integrity: sha512-jt1v2ObpyOKR8p4XaUJVk3YWRJ5n+i4+rjQopxvV32rSndTJXvIzuUdWWIy/1pFQMkQmvTXawzDNqOH/CUmx6A==} resolution: {integrity: sha512-s5HZGFQea7Huv5zZcAGhJLT3qLpAfnY7v7GWkICUr0+Wd5TFEtdlRR2XUL5Gg+RH7u2Df595ifrxR03mBaw7gA==}
engines: {node: '>= 20'} engines: {node: '>= 20'}
hasBin: true hasBin: true
@@ -5212,8 +5138,8 @@ packages:
resolution: {integrity: sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==} resolution: {integrity: sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==}
engines: {node: ^14.18.0 || >=16.0.0} engines: {node: ^14.18.0 || >=16.0.0}
tailwindcss@4.2.0: tailwindcss@4.1.18:
resolution: {integrity: sha512-yYzTZ4++b7fNYxFfpnberEEKu43w44aqDMNM9MHMmcKuCH7lL8jJ4yJ7LGHv7rSwiqM0nkiobF9I6cLlpS2P7Q==} resolution: {integrity: sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==}
tapable@2.3.0: tapable@2.3.0:
resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==}
@@ -5862,10 +5788,10 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@astrojs/node@9.5.4(astro@5.17.3(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@2.79.2)(terser@5.44.1)(typescript@5.9.3)(yaml@2.8.2))': '@astrojs/node@9.5.3(astro@5.17.2(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@2.79.2)(terser@5.44.1)(typescript@5.9.3)(yaml@2.8.2))':
dependencies: dependencies:
'@astrojs/internal-helpers': 0.7.5 '@astrojs/internal-helpers': 0.7.5
astro: 5.17.3(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@2.79.2)(terser@5.44.1)(typescript@5.9.3)(yaml@2.8.2) astro: 5.17.2(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@2.79.2)(terser@5.44.1)(typescript@5.9.3)(yaml@2.8.2)
send: 1.2.1 send: 1.2.1
server-destroy: 1.0.1 server-destroy: 1.0.1
transitivePeerDependencies: transitivePeerDependencies:
@@ -7009,7 +6935,7 @@ snapshots:
dependencies: dependencies:
'@iconify/types': 2.0.0 '@iconify/types': 2.0.0
'@iconify-json/simple-icons@1.2.71': '@iconify-json/simple-icons@1.2.70':
dependencies: dependencies:
'@iconify/types': 2.0.0 '@iconify/types': 2.0.0
@@ -7590,90 +7516,90 @@ snapshots:
'@swup/plugin': 4.0.0 '@swup/plugin': 4.0.0
swup: 4.8.2 swup: 4.8.2
'@tailwindcss/forms@0.5.11(tailwindcss@4.2.0)': '@tailwindcss/forms@0.5.11(tailwindcss@4.1.18)':
dependencies: dependencies:
mini-svg-data-uri: 1.4.4 mini-svg-data-uri: 1.4.4
tailwindcss: 4.2.0 tailwindcss: 4.1.18
'@tailwindcss/node@4.2.0': '@tailwindcss/node@4.1.18':
dependencies: dependencies:
'@jridgewell/remapping': 2.3.5 '@jridgewell/remapping': 2.3.5
enhanced-resolve: 5.19.0 enhanced-resolve: 5.19.0
jiti: 2.6.1 jiti: 2.6.1
lightningcss: 1.31.1 lightningcss: 1.30.2
magic-string: 0.30.21 magic-string: 0.30.21
source-map-js: 1.2.1 source-map-js: 1.2.1
tailwindcss: 4.2.0 tailwindcss: 4.1.18
'@tailwindcss/oxide-android-arm64@4.2.0': '@tailwindcss/oxide-android-arm64@4.1.18':
optional: true optional: true
'@tailwindcss/oxide-darwin-arm64@4.2.0': '@tailwindcss/oxide-darwin-arm64@4.1.18':
optional: true optional: true
'@tailwindcss/oxide-darwin-x64@4.2.0': '@tailwindcss/oxide-darwin-x64@4.1.18':
optional: true optional: true
'@tailwindcss/oxide-freebsd-x64@4.2.0': '@tailwindcss/oxide-freebsd-x64@4.1.18':
optional: true optional: true
'@tailwindcss/oxide-linux-arm-gnueabihf@4.2.0': '@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18':
optional: true optional: true
'@tailwindcss/oxide-linux-arm64-gnu@4.2.0': '@tailwindcss/oxide-linux-arm64-gnu@4.1.18':
optional: true optional: true
'@tailwindcss/oxide-linux-arm64-musl@4.2.0': '@tailwindcss/oxide-linux-arm64-musl@4.1.18':
optional: true optional: true
'@tailwindcss/oxide-linux-x64-gnu@4.2.0': '@tailwindcss/oxide-linux-x64-gnu@4.1.18':
optional: true optional: true
'@tailwindcss/oxide-linux-x64-musl@4.2.0': '@tailwindcss/oxide-linux-x64-musl@4.1.18':
optional: true optional: true
'@tailwindcss/oxide-wasm32-wasi@4.2.0': '@tailwindcss/oxide-wasm32-wasi@4.1.18':
optional: true optional: true
'@tailwindcss/oxide-win32-arm64-msvc@4.2.0': '@tailwindcss/oxide-win32-arm64-msvc@4.1.18':
optional: true optional: true
'@tailwindcss/oxide-win32-x64-msvc@4.2.0': '@tailwindcss/oxide-win32-x64-msvc@4.1.18':
optional: true optional: true
'@tailwindcss/oxide@4.2.0': '@tailwindcss/oxide@4.1.18':
optionalDependencies: optionalDependencies:
'@tailwindcss/oxide-android-arm64': 4.2.0 '@tailwindcss/oxide-android-arm64': 4.1.18
'@tailwindcss/oxide-darwin-arm64': 4.2.0 '@tailwindcss/oxide-darwin-arm64': 4.1.18
'@tailwindcss/oxide-darwin-x64': 4.2.0 '@tailwindcss/oxide-darwin-x64': 4.1.18
'@tailwindcss/oxide-freebsd-x64': 4.2.0 '@tailwindcss/oxide-freebsd-x64': 4.1.18
'@tailwindcss/oxide-linux-arm-gnueabihf': 4.2.0 '@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.18
'@tailwindcss/oxide-linux-arm64-gnu': 4.2.0 '@tailwindcss/oxide-linux-arm64-gnu': 4.1.18
'@tailwindcss/oxide-linux-arm64-musl': 4.2.0 '@tailwindcss/oxide-linux-arm64-musl': 4.1.18
'@tailwindcss/oxide-linux-x64-gnu': 4.2.0 '@tailwindcss/oxide-linux-x64-gnu': 4.1.18
'@tailwindcss/oxide-linux-x64-musl': 4.2.0 '@tailwindcss/oxide-linux-x64-musl': 4.1.18
'@tailwindcss/oxide-wasm32-wasi': 4.2.0 '@tailwindcss/oxide-wasm32-wasi': 4.1.18
'@tailwindcss/oxide-win32-arm64-msvc': 4.2.0 '@tailwindcss/oxide-win32-arm64-msvc': 4.1.18
'@tailwindcss/oxide-win32-x64-msvc': 4.2.0 '@tailwindcss/oxide-win32-x64-msvc': 4.1.18
'@tailwindcss/postcss@4.2.0': '@tailwindcss/postcss@4.1.18':
dependencies: dependencies:
'@alloc/quick-lru': 5.2.0 '@alloc/quick-lru': 5.2.0
'@tailwindcss/node': 4.2.0 '@tailwindcss/node': 4.1.18
'@tailwindcss/oxide': 4.2.0 '@tailwindcss/oxide': 4.1.18
postcss: 8.5.6 postcss: 8.5.6
tailwindcss: 4.2.0 tailwindcss: 4.1.18
'@tailwindcss/typography@0.5.19(tailwindcss@4.2.0)': '@tailwindcss/typography@0.5.19(tailwindcss@4.1.18)':
dependencies: dependencies:
postcss-selector-parser: 6.0.10 postcss-selector-parser: 6.0.10
tailwindcss: 4.2.0 tailwindcss: 4.1.18
'@tailwindcss/vite@4.2.0(vite@6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))': '@tailwindcss/vite@4.1.18(vite@6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))':
dependencies: dependencies:
'@tailwindcss/node': 4.2.0 '@tailwindcss/node': 4.1.18
'@tailwindcss/oxide': 4.2.0 '@tailwindcss/oxide': 4.1.18
tailwindcss: 4.2.0 tailwindcss: 4.1.18
vite: 6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2) vite: 6.4.1(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)
'@trysound/sax@0.2.0': {} '@trysound/sax@0.2.0': {}
@@ -8158,7 +8084,7 @@ snapshots:
cssesc: 3.0.0 cssesc: 3.0.0
debug: 4.4.3 debug: 4.4.3
deterministic-object-hash: 2.0.2 deterministic-object-hash: 2.0.2
devalue: 5.6.3 devalue: 5.6.2
diff: 5.2.2 diff: 5.2.2
dlv: 1.1.3 dlv: 1.1.3
dset: 3.1.4 dset: 3.1.4
@@ -8240,7 +8166,7 @@ snapshots:
- uploadthing - uploadthing
- yaml - yaml
astro@5.17.3(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@2.79.2)(terser@5.44.1)(typescript@5.9.3)(yaml@2.8.2): astro@5.17.2(@types/node@25.2.3)(jiti@2.6.1)(lightningcss@1.30.2)(rollup@2.79.2)(terser@5.44.1)(typescript@5.9.3)(yaml@2.8.2):
dependencies: dependencies:
'@astrojs/compiler': 2.13.1 '@astrojs/compiler': 2.13.1
'@astrojs/internal-helpers': 0.7.5 '@astrojs/internal-helpers': 0.7.5
@@ -8260,7 +8186,7 @@ snapshots:
cssesc: 3.0.0 cssesc: 3.0.0
debug: 4.4.3 debug: 4.4.3
deterministic-object-hash: 2.0.2 deterministic-object-hash: 2.0.2
devalue: 5.6.3 devalue: 5.6.2
diff: 8.0.3 diff: 8.0.3
dlv: 1.1.3 dlv: 1.1.3
dset: 3.1.4 dset: 3.1.4
@@ -8824,7 +8750,7 @@ snapshots:
dependencies: dependencies:
base-64: 1.0.0 base-64: 1.0.0
devalue@5.6.3: {} devalue@5.6.2: {}
devlop@1.1.0: devlop@1.1.0:
dependencies: dependencies:
@@ -9535,7 +9461,7 @@ snapshots:
get-caller-file@2.0.5: {} get-caller-file@2.0.5: {}
get-east-asian-width@1.5.0: {} get-east-asian-width@1.4.0: {}
get-intrinsic@1.3.0: get-intrinsic@1.3.0:
dependencies: dependencies:
@@ -10061,69 +9987,36 @@ snapshots:
lightningcss-android-arm64@1.30.2: lightningcss-android-arm64@1.30.2:
optional: true optional: true
lightningcss-android-arm64@1.31.1:
optional: true
lightningcss-darwin-arm64@1.30.2: lightningcss-darwin-arm64@1.30.2:
optional: true optional: true
lightningcss-darwin-arm64@1.31.1:
optional: true
lightningcss-darwin-x64@1.30.2: lightningcss-darwin-x64@1.30.2:
optional: true optional: true
lightningcss-darwin-x64@1.31.1:
optional: true
lightningcss-freebsd-x64@1.30.2: lightningcss-freebsd-x64@1.30.2:
optional: true optional: true
lightningcss-freebsd-x64@1.31.1:
optional: true
lightningcss-linux-arm-gnueabihf@1.30.2: lightningcss-linux-arm-gnueabihf@1.30.2:
optional: true optional: true
lightningcss-linux-arm-gnueabihf@1.31.1:
optional: true
lightningcss-linux-arm64-gnu@1.30.2: lightningcss-linux-arm64-gnu@1.30.2:
optional: true optional: true
lightningcss-linux-arm64-gnu@1.31.1:
optional: true
lightningcss-linux-arm64-musl@1.30.2: lightningcss-linux-arm64-musl@1.30.2:
optional: true optional: true
lightningcss-linux-arm64-musl@1.31.1:
optional: true
lightningcss-linux-x64-gnu@1.30.2: lightningcss-linux-x64-gnu@1.30.2:
optional: true optional: true
lightningcss-linux-x64-gnu@1.31.1:
optional: true
lightningcss-linux-x64-musl@1.30.2: lightningcss-linux-x64-musl@1.30.2:
optional: true optional: true
lightningcss-linux-x64-musl@1.31.1:
optional: true
lightningcss-win32-arm64-msvc@1.30.2: lightningcss-win32-arm64-msvc@1.30.2:
optional: true optional: true
lightningcss-win32-arm64-msvc@1.31.1:
optional: true
lightningcss-win32-x64-msvc@1.30.2: lightningcss-win32-x64-msvc@1.30.2:
optional: true optional: true
lightningcss-win32-x64-msvc@1.31.1:
optional: true
lightningcss@1.30.2: lightningcss@1.30.2:
dependencies: dependencies:
detect-libc: 2.1.2 detect-libc: 2.1.2
@@ -10140,22 +10033,6 @@ snapshots:
lightningcss-win32-arm64-msvc: 1.30.2 lightningcss-win32-arm64-msvc: 1.30.2
lightningcss-win32-x64-msvc: 1.30.2 lightningcss-win32-x64-msvc: 1.30.2
lightningcss@1.31.1:
dependencies:
detect-libc: 2.1.2
optionalDependencies:
lightningcss-android-arm64: 1.31.1
lightningcss-darwin-arm64: 1.31.1
lightningcss-darwin-x64: 1.31.1
lightningcss-freebsd-x64: 1.31.1
lightningcss-linux-arm-gnueabihf: 1.31.1
lightningcss-linux-arm64-gnu: 1.31.1
lightningcss-linux-arm64-musl: 1.31.1
lightningcss-linux-x64-gnu: 1.31.1
lightningcss-linux-x64-musl: 1.31.1
lightningcss-win32-arm64-msvc: 1.31.1
lightningcss-win32-x64-msvc: 1.31.1
lilconfig@2.1.0: {} lilconfig@2.1.0: {}
lines-and-columns@1.2.4: {} lines-and-columns@1.2.4: {}
@@ -10240,12 +10117,12 @@ snapshots:
markdown-table@3.0.4: {} markdown-table@3.0.4: {}
marked-shiki@1.2.1(marked@17.0.3)(shiki@3.22.0): marked-shiki@1.2.1(marked@17.0.2)(shiki@3.22.0):
dependencies: dependencies:
marked: 17.0.3 marked: 17.0.2
shiki: 3.22.0 shiki: 3.22.0
marked@17.0.3: {} marked@17.0.2: {}
math-intrinsics@1.1.0: {} math-intrinsics@1.1.0: {}
@@ -11735,7 +11612,7 @@ snapshots:
string-width@7.2.0: string-width@7.2.0:
dependencies: dependencies:
emoji-regex: 10.6.0 emoji-regex: 10.6.0
get-east-asian-width: 1.5.0 get-east-asian-width: 1.4.0
strip-ansi: 7.1.2 strip-ansi: 7.1.2
string.prototype.matchall@4.0.12: string.prototype.matchall@4.0.12:
@@ -11867,7 +11744,7 @@ snapshots:
dependencies: dependencies:
'@pkgr/core': 0.2.9 '@pkgr/core': 0.2.9
tailwindcss@4.2.0: {} tailwindcss@4.1.18: {}
tapable@2.3.0: {} tapable@2.3.0: {}

View File

@@ -14,67 +14,81 @@ const currentYear = new Date().getFullYear();
--- ---
<footer <footer
class="bg-background-accent w-full overflow-hidden" class="w-full overflow-hidden bg-stone-300/40 dark:bg-stone-800/20"
transition:animate="none" transition:animate="none"
> >
<div class="relative px-4 sm:px-6 pt-16 pb-12"> <div class="relative px-4 pt-16 pb-12 sm:px-6">
<div class="max-w-340 mx-auto"> <div class="mx-auto max-w-340">
<div class="grid grid-cols-1 md:grid-cols-12 gap-10"> <div class="grid grid-cols-1 gap-10 md:grid-cols-12">
<!-- Brand section --> <!-- Brand section -->
<div class="col-span-1 md:col-span-3"> <div class="col-span-1 md:col-span-3">
<a href="/" class="group inline-block"> <a href="/" class="group inline-block">
<div class="flex items-center"> <div class="flex items-center">
<div class="mx-auto aspect-square overflow-hidden"> <div class="mx-auto aspect-square overflow-hidden rounded-lg">
<BrandLogo class="rounded-lg max-h-10 max-w-10"/> <BrandLogo class="max-h-10 max-w-10 rounded-full" />
</div> </div>
<span class="text-header text-lg lg:text-2xl font-semibold leading-tight tracking-tight text-balance ml-3">
<span class="ml-3 text-xl font-bold text-neutral-800 dark:text-neutral-200">
{global.name} {global.name}
</span> </span>
</div> </div>
</a> </a>
<p class="text-primary text-sm lg:text-base text-pretty leading-relaxed mt-4">
<p class="mt-4 text-sm leading-relaxed text-neutral-600 dark:text-neutral-400">
{global.about} {global.about}
</p> </p>
</div> </div>
<!-- Left links --> <!-- Left links -->
<div class="col-span-1 md:col-span-2"> <div class="col-span-1 md:col-span-2">
<h3 class="relative inline-block text-header after:bg-main text-sm uppercase font-semibold tracking-wider pb-2 after:absolute after:bottom-0 after:left-0 after:h-0.5 after:w-8 after:content-['']"> <h3
Site class="after:bg-steel dark:after:bg-bermuda relative inline-block pb-2 text-sm font-semibold tracking-wider text-neutral-800 uppercase after:absolute after:bottom-0 after:left-0 after:h-0.5 after:w-8 after:content-[''] dark:text-neutral-100"
>
Blog
</h3> </h3>
<ul class="mt-4 space-y-3"> <ul class="mt-4 space-y-3">
{NavigationLinks.map((link) => ( {
<li> NavigationLinks.map((link) => (
<a <li>
href={link.url} <a
class="inline-flex items-center text-secondary hover:text-secondary-hover text-base transition-all duration-300 overflow-hidden" href={link.url}
> class="group flex items-center text-base text-neutral-600 transition-colors hover:text-neutral-800 dark:text-neutral-400 dark:hover:text-neutral-200"
{link.name} >
</a> <span class="relative inline-block overflow-hidden">
</li> <span class="relative z-10">{link.name}</span>
))} </span>
</a>
</li>
))
}
</ul> </ul>
</div> </div>
<!-- Right links --> <!-- Right links -->
<div class="col-span-1 md:col-span-3"> <div class="col-span-1 md:col-span-3">
<h3 class="relative inline-block text-header after:bg-main text-sm uppercase font-semibold tracking-wider pb-2 after:absolute after:bottom-0 after:left-0 after:h-0.5 after:w-8 after:content-['']"> <h3
class="after:bg-steel dark:after:bg-bermuda relative inline-block pb-2 text-sm font-semibold tracking-wider text-neutral-800 uppercase after:absolute after:bottom-0 after:left-0 after:h-0.5 after:w-8 after:content-[''] dark:text-neutral-100"
>
Other Other
</h3> </h3>
<ul class="mt-4 space-y-3"> <ul class="mt-4 space-y-3">
{FooterLinks.map((link) => ( {
<li> FooterLinks.map((link) => (
<a <li>
href={link.url} <a
class="inline-flex items-center text-secondary hover:text-secondary-hover text-base transition-all duration-300 overflow-hidden" href={link.url}
> class="group flex items-center text-base text-neutral-600 transition-colors hover:text-neutral-800 dark:text-neutral-400 dark:hover:text-neutral-200"
{link.name} >
</a> <span class="relative inline-block overflow-hidden">
</li> <span class="relative z-10">{link.name}</span>
))} </span>
</a>
</li>
))
}
</ul> </ul>
</div> </div>
<!-- Right image --> <!-- Right image -->
<div class="flex justify-center col-span-4 mt-10 md:mt-0"> <div class="col-span-3 mt-10 flex justify-center md:mt-0">
<div class="md:block max-h-115 max-w-55 -mt-10 scale-80 hidden"> <div class="-mt-10 hidden max-h-[460px] max-w-[220px] scale-80 md:block">
<Image <Image
src={footerImg} src={footerImg}
alt={global.footer_image_alt} alt={global.footer_image_alt}
@@ -90,36 +104,37 @@ const currentYear = new Date().getFullYear();
</div> </div>
</div> </div>
<!-- Bottom section --> <!-- Bottom section -->
<div class="border-t border-divider pt-8 mt-12"> <div class="mt-12 border-t border-neutral-400/30 pt-8 dark:border-neutral-600/50">
<div class="flex flex-col md:flex-row items-center justify-between gap-4"> <div class="flex flex-col items-center justify-between gap-4 md:flex-row">
<p class="text-secondary text-sm"> <p class="text-sm text-neutral-600 dark:text-neutral-400">
&copy; {currentYear} All rights reserved. &copy; {currentYear} All rights reserved.
</p> </p>
<div class="flex items-center"> <div class="flex items-center">
<span class="text-secondary text-sm"> <p class="text-xs text-neutral-500 dark:text-neutral-400">
Weather provided by Weather provided by
</span> </p>
<a <a
href="https://open-meteo.com/" href="https://open-meteo.com/"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
class="group inline-flex items-center text-secondary hover:text-secondary-hover text-sm transition-all duration-300" class="group inline-flex items-center text-xs text-neutral-600 transition-colors hover:text-neutral-900 dark:text-neutral-400 dark:hover:text-neutral-100"
> >
<span class="relative underline ml-1"> <span class="relative ml-1">
Open-Meteo. Open-Meteo.
</span> </span>
</a> </a>
<div class="ml-4"/>
<span class="text-secondary text-sm"> <div class="ml-4"></div>
Built with
</span> <span class="text-xs text-neutral-500 dark:text-neutral-400">Built with </span>
<a <a
href="https://astro.build" href="https://astro.build"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
class="group inline-flex items-center text-secondary hover:text-secondary-hover text-sm transition-all duration-300" class="group inline-flex items-center text-xs text-neutral-600 transition-colors hover:text-neutral-900 dark:text-neutral-400 dark:hover:text-neutral-100"
> >
<span class="relative underline ml-1"> <span class="relative ml-1">
Astro. Astro.
</span> </span>
</a> </a>

View File

@@ -9,31 +9,31 @@ const currentPath = pathname.slice(1);
<header <header
id="nav" id="nav"
class="fixed flex flex-wrap md:flex-nowrap md:justify-start inset-x-0 top-0 w-full z-50" class="sticky inset-x-0 top-4 z-50 flex w-full flex-wrap text-sm transition-none md:flex-nowrap md:justify-start"
> >
<div class="bg-linear-to-b from-background from-65% to-transparent to-90% absolute top-0 bottom-0 left-0 w-full h-36 z-0"/>
<nav <nav
class="nav-base relative md:flex md:items-center md:justify-between rounded-[36px] w-full px-4 mx-2 py-3 mt-4" class="relative mx-2 w-full rounded-[36px] border border-neutral-100 bg-neutral-100 px-4 py-3 md:flex md:items-center md:justify-between md:px-6 lg:px-8 dark:border-neutral-700/40 dark:bg-neutral-800/80"
aria-label="Global" aria-label="Global"
> >
<div class="flex items-center justify-between ml-0"> <div class="flex items-center justify-between">
<a <a
class="flex-none rounded-full h-10.5" class="h-[42px] flex-none rounded-lg text-xl font-bold ring-neutral-500 outline-none focus-visible:ring dark:ring-neutral-200 dark:focus:outline-none"
href="/" href="/"
aria-label="Brand" aria-label="Brand"
> >
<BrandLogo class="h-full w-auto rounded-full object-cover"/> <BrandLogo class="h-full w-auto rounded-full object-cover" />
</a> </a>
<div class="md:hidden mr-auto ml-4">
<div class="ml-auto md:hidden">
<button <button
type="button" type="button"
class="hs-collapse-toggle flex items-center justify-center text-secondary text-sm font-bold hover:bg-neutral-200 dark:hover:bg-neutral-700 rounded-full transition duration-300 disabled:pointer-events-none disabled:opacity-50 h-8 w-8" class="hs-collapse-toggle flex h-8 w-8 items-center justify-center rounded-full text-sm font-bold text-neutral-600 transition duration-300 hover:bg-neutral-200 disabled:pointer-events-none disabled:opacity-50 dark:text-neutral-400 dark:hover:bg-neutral-700 dark:focus:outline-none"
data-hs-collapse="#navbar-collapse-with-animation" data-hs-collapse="#navbar-collapse-with-animation"
aria-controls="navbar-collapse-with-animation" aria-controls="navbar-collapse-with-animation"
aria-label="Toggle navigation" aria-label="Toggle navigation"
> >
<svg <svg
class="hs-collapse-open:hidden shrink-0 h-5 w-5" class="hs-collapse-open:hidden h-5 w-5 shrink-0"
width="24" width="24"
height="24" height="24"
viewBox="0 0 24 24" viewBox="0 0 24 24"
@@ -48,7 +48,7 @@ const currentPath = pathname.slice(1);
<line x1="3" x2="21" y1="18" y2="18"></line> <line x1="3" x2="21" y1="18" y2="18"></line>
</svg> </svg>
<svg <svg
class="hs-collapse-open:block shrink-0 h-5 w-5 hidden" class="hs-collapse-open:block hidden h-5 w-5 shrink-0"
width="24" width="24"
height="24" height="24"
viewBox="0 0 24 24" viewBox="0 0 24 24"
@@ -63,33 +63,33 @@ const currentPath = pathname.slice(1);
</svg> </svg>
</button> </button>
</div> </div>
<div class="md:hidden ml-2 mr-2">
<span class="">
<ThemeToggleButton />
</span>
</div>
</div> </div>
<div class="flex md:flex-row items-center justify-between">
<div
id="navbar-collapse-with-animation"
class="hs-collapse hidden grow basis-full overflow-hidden transition-all duration-300 md:block md:overflow-visible"
>
<div <div
id="navbar-collapse-with-animation" class="mt-5 flex flex-col gap-x-0 gap-y-4 md:mt-0 md:flex-row md:items-center md:justify-end md:gap-x-4 md:gap-y-0 md:ps-7 lg:gap-x-7"
class="hs-collapse grow basis-full md:block transition-all duration-300 ml-2 mb-2 md:mb-0 hidden overflow-hidden md:overflow-visible"
> >
<div class="flex flex-col md:flex-row md:items-center md:justify-end gap-x-0 md:gap-x-4 lg:gap-x-7 gap-y-4 md:gap-y-0 md:ps-7 mr-2 mt-5 md:mt-0"> {
{NavigationLinks.map((item) => { NavigationLinks.map((item) => {
const isActive = currentPath === (item.url === '/' ? '' : item.url.slice(1)); const isActive = currentPath === (item.url === '/' ? '' : item.url.slice(1));
return ( return (
<a <a
href={item.url} href={item.url}
class={`text-sm font-medium ${isActive ? 'text-active' : 'text-secondary hover:text-secondary-hover'}`} class={`text-sm font-medium ${
> isActive
{item.name} ? 'text-orange-500 dark:text-orange-300'
</a> : 'text-neutral-600 hover:text-neutral-900 dark:text-neutral-400 dark:hover:text-neutral-100'
); }`}
})} >
</div> {item.name}
</div> </a>
<div class="hidden md:flex ml-2"> );
<span class=""> })
}
<span class="md:inline-block">
<ThemeToggleButton /> <ThemeToggleButton />
</span> </span>
</div> </div>

View File

@@ -4,8 +4,7 @@ import { Icon } from 'astro-icon/components';
import type { Post } from '@lib/directusTypes'; import type { Post } from '@lib/directusTypes';
import Image from '@components/ui/images/Image.astro'; import Image from '@components/ui/images/Image.astro';
import { formatDate } from '@support/time'; import { getDirectusImageURL } from '@lib/directusFunctions';
import { getDirectusImageURL } from '@/support/url';
interface Props { interface Props {
post: Post; post: Post;
@@ -45,7 +44,11 @@ const { post } = Astro.props;
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"
/> />
<p class="card-text-description text-sm ml-auto"> <p class="card-text-description text-sm ml-auto">
{formatDate(post.published_date)} {new Date(post.published_date).toLocaleDateString('en-US', {
year: 'numeric',
month: 'short',
day: 'numeric',
})}
</p> </p>
</div> </div>
</div> </div>

View File

@@ -2,7 +2,7 @@
import { Icon } from 'astro-icon/components'; import { Icon } from 'astro-icon/components';
import Logo from '@components/ui/logos/Logo.astro'; import Logo from '@components/ui/logos/Logo.astro';
import { getDirectusImageURL } from '@/support/url'; import { getDirectusImageURL } from '@lib/directusFunctions';
interface Props { interface Props {
topic: string; topic: string;

View File

@@ -2,7 +2,7 @@
import { Icon } from 'astro-icon/components'; import { Icon } from 'astro-icon/components';
import Image from '@components/ui/images/Image.astro'; import Image from '@components/ui/images/Image.astro';
import { getDirectusImageURL } from '@/support/url'; import { getDirectusImageURL } from '@lib/directusFunctions';
interface Props { interface Props {
title: string; title: string;
@@ -15,15 +15,15 @@ interface Props {
const { title, subTitle, url, img, imgAlt } = Astro.props; const { title, subTitle, url, img, imgAlt } = Astro.props;
--- ---
<div class="smooth-reveal flex flex-col px-4 py-10 mx-auto"> <div class="smooth-reveal group">
<a <a
class="md:card-base-hidden group items-center md:grid md:grid-cols-2 lg:grid lg:grid-cols-2 gap-8 xl:gap-16 max-w-340 2xl:max-w-full md:px-8 md:py-8" class="card-base-hidden md:grid md:grid-cols-2 lg:grid lg:grid-cols-2 items-center gap-8 xl:gap-16 max-w-340 2xl:max-w-full px-4 sm:px-6 lg:px-8 py-10 sm:py-16 lg:py-14 mx-auto"
href={url} href={url}
data-astro-prefetch data-astro-prefetch
> >
<div> <div>
<Image <Image
class="rounded-2xl rounded-b-none md:rounded-2xl w-full h-full sm:max-h-80 md:max-h-90 object-cover" class="rounded-xl w-full h-full sm:max-h-80 md:max-h-90 object-cover"
src={getDirectusImageURL(img)} src={getDirectusImageURL(img)}
alt={imgAlt} alt={imgAlt}
draggable="false" draggable="false"
@@ -32,11 +32,11 @@ const { title, subTitle, url, img, imgAlt } = Astro.props;
height="420" height="420"
/> />
</div> </div>
<div class="bg-background-card md:bg-transparent group-hover:bg-neutral-100 md:group-hover:bg-transparent dark:group-hover:bg-neutral-800/90 md:dark:group-hover:bg-transparent rounded-b-2xl transition-all duration-300 p-6"> <div>
<h2 class="card-text-header mb-2"> <h2 class="card-text-header mb-4">
{title} {title}
</h2> </h2>
<p class="card-text-title font-light text-pretty sm:text-lg max-w-prose mb-8"> <p class="card-text-title font-light text-pretty sm:text-lg max-w-prose mb-4">
{subTitle} {subTitle}
</p> </p>
<div class="button-base button-bg-teal inline-flex rounded-lg gap-x-2"> <div class="button-base button-bg-teal inline-flex rounded-lg gap-x-2">

View File

@@ -2,7 +2,7 @@
import { Icon } from 'astro-icon/components'; import { Icon } from 'astro-icon/components';
import Image from '@components/ui/images/Image.astro'; import Image from '@components/ui/images/Image.astro';
import { getDirectusImageURL } from '@/support/url'; import { getDirectusImageURL } from '@lib/directusFunctions';
interface Props { interface Props {
title: string; title: string;
@@ -18,17 +18,17 @@ interface Props {
const { title, subTitle, url, single, imgOne, imgOneAlt, imgTwo, imgTwoAlt } = Astro.props; const { title, subTitle, url, single, imgOne, imgOneAlt, imgTwo, imgTwoAlt } = Astro.props;
--- ---
<div class="smooth-reveal flex flex-col px-5 py-10 mx-auto"> <div class="smooth-reveal group">
<a <a
class="md:card-base-hidden group flex flex-col-reverse md:items-center md:grid md:grid-cols-2 lg:grid lg:grid-cols-2 md:gap-8 xl:gap-16 max-w-340 2xl:max-w-full md:px-8 md:py-8" class="card-base-hidden items-center lg:grid lg:grid-cols-2 gap-16 max-w-340 2xl:max-w-full px-4 py-10 sm:px-6 lg:px-8 lg:py-14 mx-auto"
href={url} href={url}
data-astro-prefetch data-astro-prefetch
> >
<div class="bg-background-card md:bg-transparent group-hover:bg-neutral-100 md:group-hover:bg-transparent dark:group-hover:bg-neutral-800/90 md:dark:group-hover:bg-transparent rounded-b-2xl transition-all duration-300 p-6"> <div>
<h2 class="card-text-header mb-2"> <h2 class="card-text-header mb-4">
{title} {title}
</h2> </h2>
<p class="card-text-title font-light text-pretty sm:text-lg max-w-prose mb-8"> <p class="card-text-title font-light text-pretty sm:text-lg max-w-prose mb-4">
{subTitle} {subTitle}
</p> </p>
<div class="button-base button-bg-teal inline-flex rounded-lg gap-x-2"> <div class="button-base button-bg-teal inline-flex rounded-lg gap-x-2">
@@ -46,7 +46,7 @@ const { title, subTitle, url, single, imgOne, imgOneAlt, imgTwo, imgTwoAlt } = A
{single ? ( {single ? (
<div> <div>
<Image <Image
class="rounded-2xl rounded-b-none md:rounded-2xl w-full" class="rounded-xl w-full"
src={getDirectusImageURL(imgOne)} src={getDirectusImageURL(imgOne)}
alt={imgOneAlt} alt={imgOneAlt}
format="webp" format="webp"

View File

@@ -18,7 +18,7 @@ const experiences = ((await directus.request(
<h3 class="smooth-reveal card-text-header flex relative items-center w-full gap-3 pb-10"> <h3 class="smooth-reveal card-text-header flex relative items-center w-full gap-3 pb-10">
Experience Experience
</h3> </h3>
<ul class="flex flex-col w-full ml-8 pr-8"> <ul class="ml-8 w-full flex flex-col">
{experiences.map((experience: Experience) => { {experiences.map((experience: Experience) => {
const startYear = new Date(experience.startDate).getFullYear(); const startYear = new Date(experience.startDate).getFullYear();
const endYear = experience.endDate != null ? new Date(experience.endDate).getFullYear() : 'Present'; const endYear = experience.endDate != null ? new Date(experience.endDate).getFullYear() : 'Present';
@@ -36,7 +36,7 @@ const experiences = ((await directus.request(
</time> </time>
</header> </header>
<div class="relative flex flex-col sm:col-span-12 pb-6"> <div class="relative flex flex-col sm:col-span-12 pb-6">
<div class="absolute bg-accent -translate-x-[1.71rem] rounded-full h-2 w-2 mt-3"/> <div class="absolute bg-stone-400 -translate-x-[1.71rem] rounded-full h-2 w-2 mt-4"/>
<h3> <h3>
<div <div
class="inline-flex items-center text-2xl leading-tight font-semibold" class="inline-flex items-center text-2xl leading-tight font-semibold"
@@ -78,7 +78,7 @@ const experiences = ((await directus.request(
</div> </div>
)} )}
{(experience.responsibilities || experience.achievements) && ( {(experience.responsibilities || experience.achievements) && (
<div class="relative flex flex-col gap-4 after:absolute after:bottom-0 after:h-12 after:w-full after:bg-linear-to-t after:from-neutral-200 dark:after:from-stone-700 after:content-[''] " :class="expanded ? 'after:hidden' : ''" x-show="expanded" x-collapse.min.50px> <div class="relative flex flex-col gap-4 max-sm:h-auto! md:after:absolute md:after:bottom-0 md:after:h-12 md:after:w-full md:after:bg-linear-to-t md:after:from-neutral-200 dark:md:after:from-stone-700 md:after:content-[''] " :class="expanded ? 'after:hidden' : ''" x-show="expanded" x-collapse.min.50px>
{experience.responsibilities && ( {experience.responsibilities && (
<div class="flex flex-col gap-1"> <div class="flex flex-col gap-1">
<h4 class="text-header font-semibold"> <h4 class="text-header font-semibold">
@@ -129,7 +129,7 @@ const experiences = ((await directus.request(
</button> </button>
<ul <ul
class="flex print:hidden flex-wrap gap-2 mt-2" class="flex print:hidden flex-wrap gap-2"
aria-label="Technologies used" aria-label="Technologies used"
> >
{experience.skills && experience.skills.map(skill => { {experience.skills && experience.skills.map(skill => {

View File

@@ -17,7 +17,7 @@ interface Props {
const { title, subTitle, primaryBtn, primaryBtnURL, secondaryBtn, secondaryBtnURL, src, alt } = Astro.props; const { title, subTitle, primaryBtn, primaryBtnURL, secondaryBtn, secondaryBtnURL, src, alt } = Astro.props;
const roundedClasses = Astro.props.rounded ? "rounded-2xl" : null; const roundedClasses = Astro.props.rounded ? "rounded-xl" : null;
--- ---
<section class="mx-auto grid max-w-340 gap-4 px-4 py-14 sm:px-6 md:grid-cols-2 md:items-center md:gap-8 lg:px-8 2xl:max-w-full"> <section class="mx-auto grid max-w-340 gap-4 px-4 py-14 sm:px-6 md:grid-cols-2 md:items-center md:gap-8 lg:px-8 2xl:max-w-full">

View File

@@ -11,7 +11,7 @@ interface Props {
const { posts } = Astro.props; const { posts } = Astro.props;
--- ---
<section class="smooth-reveal flex flex-col gap-4"> <section class="smooth-reveal">
{posts.map((post, index) => index % 2 === 0 ? ( {posts.map((post, index) => index % 2 === 0 ? (
<LargeBlogLeftCard <LargeBlogLeftCard
title={post.title} title={post.title}

View File

@@ -2,13 +2,13 @@ import { readSingleton } from '@directus/sdk';
import directus from '@lib/directus'; import directus from '@lib/directus';
const global = await directus.request(readSingleton('site_global'));
export interface NavigationLink { export interface NavigationLink {
name: string; name: string;
url: string; url: string;
} }
const global = await directus.request(readSingleton('site_global'));
export const NavigationLinks: NavigationLink[] = [ export const NavigationLinks: NavigationLink[] = [
{ name: 'Home', url: '/' }, { name: 'Home', url: '/' },
{ name: 'Blog', url: '/blog/' }, { name: 'Blog', url: '/blog/' },

View File

@@ -2,10 +2,10 @@
import { ClientRouter } from 'astro:transitions'; import { ClientRouter } from 'astro:transitions';
import { readSingleton } from '@directus/sdk'; import { readSingleton } from '@directus/sdk';
import directus from '@lib/directus';
import BaseHead from '@components/BaseHead.astro'; import BaseHead from '@components/BaseHead.astro';
import Footer from '@components/Footer.astro'; import Footer from '@components/Footer.astro';
import Header from '@components/Header.astro'; import Header from '@components/Header.astro';
import directus from '@lib/directus';
import '@styles/global.css'; import '@styles/global.css';
@@ -20,16 +20,12 @@ interface Props {
const { title, description = 'Alex Lebens', ogImage, lang = 'en', structuredData } = Astro.props; const { title, description = 'Alex Lebens', ogImage, lang = 'en', structuredData } = Astro.props;
const global = await directus.request(readSingleton('site_global')); const global = await directus.request(readSingleton('site_global'));
const normalizeTitle = !title ? global.name : `${title} | ${global.name}`; const normalizeTitle = !title ? global.name : `${title} | ${global.name}`;
--- ---
<html lang={lang}> <html lang={lang}>
<head> <head>
<title> <title>{normalizeTitle}</title>
{normalizeTitle}
</title>
<BaseHead <BaseHead
title={normalizeTitle} title={normalizeTitle}
description={description} description={description}
@@ -38,9 +34,7 @@ const normalizeTitle = !title ? global.name : `${title} | ${global.name}`;
ogDescription={description} ogDescription={description}
structuredData={structuredData} structuredData={structuredData}
/> />
<ClientRouter fallback="swap" /> <ClientRouter fallback="swap" />
<script is:inline> <script is:inline>
const theme = (() => { const theme = (() => {
if (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) { if (typeof localStorage !== 'undefined' && localStorage.getItem('theme')) {
@@ -59,35 +53,30 @@ const normalizeTitle = !title ? global.name : `${title} | ${global.name}`;
} }
window.localStorage.setItem('theme', theme); window.localStorage.setItem('theme', theme);
</script> </script>
<!-- Rybbit Tracking Snippet --> <!-- Rybbit Tracking Snippet -->
<script <script
src="https://rybbit.alexlebens.dev/api/script.js" src="https://rybbit.alexlebens.dev/api/script.js"
data-site-id={global.rybbit_site_id} data-site-id={global.rybbit_site_id}
defer defer
/> ></script>
</head> </head>
<body class="bg-stone-200 selection:bg-yellow-400 selection:text-neutral-700 dark:bg-stone-700">
<body class="bg-background selection:bg-yellow-400"> <div class="mx-auto w-full max-w-(--breakpoint-2xl) grow px-4 sm:px-6 lg:px-8">
<!-- Disabled texture background for now
<div class="fixed inset-0 -z-10">
<div class="bg-grid-pattern absolute inset-0 mask-[radial-gradient(white,transparent_85%)] bg-position-[center_top_-1px]"/>
</div>
-->
<div class="grow w-full max-w-(--breakpoint-2xl) px-4 sm:px-6 lg:px-8 py-20 mx-auto">
<Header /> <Header />
<main class="min-h-screen"> <main class="min-h-screen">
<slot /> <slot />
</main> </main>
</div> </div>
<Footer /> <Footer />
<style>
.scrollbar-hide::-webkit-scrollbar {
display: none;
}
.scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
}
</style>
</body> </body>
</html> </html>

View File

@@ -12,7 +12,7 @@ import type {
Skill, Skill,
} from '@lib/directusTypes'; } from '@lib/directusTypes';
import { getDirectusURL } from '@/support/url'; import { getDirectusURL } from '@lib/directusFunctions';
type Schema = { type Schema = {
site_global: Global; site_global: Global;

View File

@@ -1,13 +1,12 @@
const getDirectusURL = () => { const getDirectusURL = () => {
if (process.env.DIRECTUS_URL) {
return `https://${process.env.DIRECTUS_URL}`;
}
return 'https://directus.alexlebens.net'; return 'https://directus.alexlebens.net';
}; };
const getSiteURL = () => {
return 'https://www.alexlebens.dev';
};
async function getDirectusImageURL(image: string) { async function getDirectusImageURL(image: string) {
return `${getDirectusURL()}/assets/${image}`; return `${getDirectusURL()}/assets/${image}`;
} }
export { getDirectusURL, getSiteURL, getDirectusImageURL }; export { getDirectusURL, getDirectusImageURL };

View File

@@ -1,10 +1,10 @@
--- ---
import { readSingleton } from '@directus/sdk'; import { readSingleton } from '@directus/sdk';
import directus from '@lib/directus';
import BaseLayout from '@layouts/BaseLayout.astro';
import GoBackButton from '@/components/buttons/GoBackButton.astro'; import GoBackButton from '@/components/buttons/GoBackButton.astro';
import GoHomeButton from '@/components/buttons/GoHomeButton.astro'; import GoHomeButton from '@/components/buttons/GoHomeButton.astro';
import BaseLayout from '@layouts/BaseLayout.astro';
import directus from '@lib/directus';
const global = await directus.request(readSingleton('site_global')); const global = await directus.request(readSingleton('site_global'));
--- ---
@@ -29,36 +29,39 @@ const global = await directus.request(readSingleton('site_global'));
}} }}
> >
<section class="grid place-content-center mt-20"> <section class="mt-20 grid place-content-center">
<div class="max-w-7xl px-4 lg:px-6 py-8 lg:py-16 mx-auto"> <div class="mx-auto max-w-7xl px-4 py-8 lg:px-6 lg:py-16">
<div class="text-center max-w-screen-sm mx-auto"> <div class="mx-auto max-w-screen-sm text-center">
<div class="glitch-wrapper smooth-reveal"> <div class="glitch-wrapper smooth-reveal">
<h1 <h1
class="glitch text-header text-9xl font-bold leading-none sm:text-[12rem]" class="glitch text-9xl leading-none font-bold text-neutral-900 sm:text-[12rem] dark:text-neutral-100"
data-text="404" data-text="404"
> >
Not Found Not Found
</h1> </h1>
</div> </div>
<h1 class="smooth-reveal text-yellow-500 dark:text-yellow-400 text-4xl md:text-5xl font-bold leading-tight tracking-tight text-balance mt-30">
Page Not Found: <h1
class="text-dark smooth-reveal mb-4 text-7xl font-extrabold text-yellow-500 lg:text-9xl dark:text-yellow-400"
>
{`Page Not Found - ${global.name}`}
</h1> </h1>
<h1 class="smooth-reveal card-text-header mt-8 mb-30"> <div
{Astro.url.pathname.replace('/', '')} class="smooth-reveal mx-auto mt-16 max-w-md rounded-xl bg-neutral-100 p-6 shadow-xs dark:border-neutral-700/50 dark:bg-stone-800"
</h1> >
<div class="smooth-reveal card-base max-w-md p-6 mx-auto mt-16"> <h3
<h3 class="card-text-title text-sm tracking-wider uppercase"> class="text-sm font-medium tracking-wider text-neutral-500 uppercase dark:text-neutral-400"
>
Did you know? Did you know?
</h3> </h3>
<p <p class="mt-2 text-sm text-neutral-600 dark:text-neutral-300" id="fun-fact">
id="fun-fact"
class="text-secondary text-sm mt-4 mb-2"
>
The 404 error code originated when CERN's web server displayed room 404 (their server The 404 error code originated when CERN's web server displayed room 404 (their server
room) as the error message when a file wasn't found. room) as the error message when a file wasn't found.
</p> </p>
</div> </div>
<div class="smooth-reveal flex flex-col sm:flex-row items-center justify-center gap-4 mt-10"> <div
class="smooth-reveal mt-10 flex flex-col items-center justify-center gap-4 sm:flex-row"
>
<GoBackButton/> <GoBackButton/>
<GoHomeButton url={global.site_url} /> <GoHomeButton url={global.site_url} />
</div> </div>

View File

@@ -1,13 +1,13 @@
--- ---
import { readSingleton } from '@directus/sdk'; import { readSingleton } from '@directus/sdk';
import directus from '@lib/directus';
import BaseLayout from '@layouts/BaseLayout.astro';
import HeroSection from '@components/sections/HeroSection.astro'; import HeroSection from '@components/sections/HeroSection.astro';
import ExperienceSection from '@components/sections/ExperienceSection.astro'; import ExperienceSection from '@components/sections/ExperienceSection.astro';
import EducationSection from '@components/sections/EducationSection.astro'; import EducationSection from '@components/sections/EducationSection.astro';
import ProjectSection from '@components/sections/ProjectSection.astro'; import ProjectSection from '@components/sections/ProjectSection.astro';
import SkillsSliderSection from '@components/sections/SkillsSliderSection.astro'; import SkillsSliderSection from '@components/sections/SkillsSliderSection.astro';
import BaseLayout from '@layouts/BaseLayout.astro';
import directus from '@lib/directus';
import portraitImg from '@images/portrait.avif'; import portraitImg from '@images/portrait.avif';
@@ -42,7 +42,7 @@ const global = await directus.request(readSingleton('site_global'));
rounded={true} rounded={true}
/> />
<section class="max-w-7xl px-4 sm:px-6 lg:px-8 py-10 lg:py-14 mx-auto"> <section class="mx-auto max-w-7xl px-4 py-10 sm:px-6 lg:px-8 lg:py-14">
<div class="flex flex-col gap-y-24 md:gap-y-32"> <div class="flex flex-col gap-y-24 md:gap-y-32">
<ExperienceSection className="smooth-reveal" /> <ExperienceSection className="smooth-reveal" />
<EducationSection className="smooth-reveal" /> <EducationSection className="smooth-reveal" />

View File

@@ -1,10 +1,10 @@
--- ---
import { readSingleton } from '@directus/sdk'; import { readSingleton } from '@directus/sdk';
import directus from '@lib/directus';
import BaseLayout from '@layouts/BaseLayout.astro';
import HeroSection from '@components/sections/HeroSection.astro'; import HeroSection from '@components/sections/HeroSection.astro';
import ApplicationSection from '@components/sections/ApplicationSection.astro'; import ApplicationSection from '@components/sections/ApplicationSection.astro';
import BaseLayout from '@layouts/BaseLayout.astro';
import directus from '@lib/directus';
import applicationImg from '@images/cedar_tree.png'; import applicationImg from '@images/cedar_tree.png';

View File

@@ -10,8 +10,8 @@ import Image from '@components/ui/images/Image.astro';
import SocialShareButton from '@components/buttons/SocialShareButton.astro'; import SocialShareButton from '@components/buttons/SocialShareButton.astro';
import BaseLayout from '@layouts/BaseLayout.astro'; import BaseLayout from '@layouts/BaseLayout.astro';
import directus from '@lib/directus'; import directus from '@lib/directus';
import { formatDate } from '@support/time'; import { getDirectusImageURL } from '@lib/directusFunctions';
import { getDirectusImageURL } from '@/support/url'; import { formatDateTime } from '@support/time';
const post = Astro.props; const post = Astro.props;
@@ -31,7 +31,7 @@ const category: CollectionEntry<'categories'> = (await getCollection('categories
const readingTime = getReadingTime(post.content); const readingTime = getReadingTime(post.content);
const highlighter = await createHighlighter({ const highlighter = await createHighlighter({
themes: ['github-light', 'github-dark'], themes: ['github-light', 'github-dark', 'monokai'],
langs: ['typescript', 'python', 'css', 'html', 'yaml', 'bash', 'json'], langs: ['typescript', 'python', 'css', 'html', 'yaml', 'bash', 'json'],
}); });
@@ -68,7 +68,9 @@ const content = marked.parse(post.content);
name: global.name, name: global.name,
description: global.about, description: global.about,
}, },
image: [], image: [
// post.data.banner,
],
headline: post.title, headline: post.title,
datePublished: post.published_date, datePublished: post.published_date,
dateModified: post.updated_date, dateModified: post.updated_date,
@@ -82,11 +84,11 @@ const content = marked.parse(post.content);
}} }}
> >
<section class="max-w-6xl px-4 sm:px-6 lg:px-8 pt-8 lg:pt-12 pb-12 mx-auto"> <section class="mx-auto max-w-6xl px-4 pt-8 pb-12 sm:px-6 lg:px-8 lg:pt-12">
<div class="smooth-reveal relative w-full"> <div class="smooth-reveal relative w-full">
<div class="sm:shadow-xs sm:dark:shadow-md rounded-2xl mt-4 sm:mt-0"> <div class="mt-4 rounded-2xl shadow-none sm:mt-0 sm:shadow-sm">
<Image <Image
class="rounded-2xl sm:rounded-b-none w-full max-h-150 object-cover" class="max-h-[600px] w-full rounded-t-2xl object-cover"
src={getDirectusImageURL(post.image)} src={getDirectusImageURL(post.image)}
alt={post.image_alt} alt={post.image_alt}
draggable="false" draggable="false"
@@ -94,54 +96,81 @@ const content = marked.parse(post.content);
loading="lazy" loading="lazy"
inferSize={true} inferSize={true}
/> />
<div class="sm:bg-background-card rounded-b-2xl px-0 sm:px-6 md:px-10 lg:px-14 py-6"> <div
<div class="text-center sm:text-left mt-4"> class="rounded-b-2xl px-0 py-6 sm:bg-neutral-100 sm:px-6 md:px-10 lg:px-14 sm:dark:bg-neutral-900/30"
<h2 class="card-text-header block"> >
<div class="mb-16">
<h2
class="mb-6 block text-3xl font-bold tracking-tight text-balance text-neutral-800 md:text-4xl lg:text-5xl dark:text-neutral-300"
>
{post.title} {post.title}
</h2> </h2>
<ol class="flex items-center justify-center sm:justify-start whitespace-nowrap gap-2 sm:gap-0 mt-6 sm:mt-4"> <ol class="mt-8 flex items-center whitespace-nowrap">
<li class="inline-flex items-center"> <li class="inline-flex items-center">
<a <a
class="inline-flex items-center text-secondary hover:text-secondary-hover text-sm transition-all duration-300" class="flex items-center text-sm text-neutral-500 transition-all duration-300 hover:text-neutral-700 dark:text-neutral-400 dark:hover:text-neutral-200"
href=`/categories/${category.slug}` href=`/categories/${category.slug}`
data-astro-prefetch
> >
{category?.data?.title} {category?.data?.title}
</a> </a>
<span class="shrink-0 text-secondary text-sm mx-2 sm:mx-4"> <svg
/ class="mx-2 size-5 flex-shrink-0 text-neutral-500 dark:text-neutral-500"
</span> width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
aria-hidden="true"
>
<path d="M6 13L10 3" stroke="currentColor" stroke-linecap="round"></path>
</svg>
</li> </li>
<li class="inline-flex items-center"> <li
<span class="shrink-0 text-secondary text-sm"> class="inline-flex items-center text-sm text-neutral-500 transition-all duration-300 hover:text-neutral-700 dark:text-neutral-400 dark:hover:text-neutral-200"
{formatDate(post.published_date)} >
</span> {formatDateTime(post.published_date)}
<span class="shrink-0 text-secondary text-sm mx-2 sm:mx-4"> <svg
/ class="mx-2 size-5 flex-shrink-0 text-neutral-500 dark:text-neutral-500"
</span> width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
aria-hidden="true"
>
<path d="M6 13L10 3" stroke="currentColor" stroke-linecap="round"></path>
</svg>
</li> </li>
<li class="inline-flex items-center"> <li
<span class="shrink-0 text-secondary text-sm"> class="inline-flex items-center text-sm text-neutral-500 transition-all duration-300 hover:text-neutral-700 dark:text-neutral-400 dark:hover:text-neutral-200"
{readingTime.minutes.toPrecision(1)} minutes to read aria-current="page"
</span> >
{readingTime.minutes.toPrecision(1)} minutes to read
</li> </li>
</ol> </ol>
</div> </div>
<div class="border-t border-divider mt-10 mb-10"/>
<article class="text-header prose prose-blog sm:prose-lg dark:prose-invert max-w-none"> <article
class="prose prose-blog sm:prose-lg dark:prose-invert max-w-none text-neutral-800 dark:text-neutral-200"
>
<div set:html={content} /> <div set:html={content} />
</article> </article>
<div class="grid sm:flex sm:items-center sm:justify-between gap-y-5 sm:gap-y-0 max-w-5xl mx-auto mt-10 md:mt-14"> <div
<div class="flex flex-wrap sm:flex-nowrap sm:items-center gap-x-2 gap-y-1 sm:gap-y-0"> class="mx-auto mt-10 grid max-w-screen-lg gap-y-5 sm:flex sm:items-center sm:justify-between sm:gap-y-0 md:mt-14"
{post.tags.map((tag: string) => ( >
<span class="inline-flex items-center button-base bg-cobalt dark:bg-turquoise text-neutral-100 text-xs font-bold rounded-lg gap-x-1.5 px-3 py-1.5"> <div class="flex flex-wrap gap-x-2 gap-y-1 sm:flex-nowrap sm:items-center sm:gap-y-0">
{tag} {
</span> post.tags.map((tag: string) => (
))} <span class="bg-steel/30 dark:bg-bermuda/60 inline-flex items-center gap-x-1.5 rounded-lg px-3 py-1.5 text-xs font-medium text-neutral-700 outline-none focus:outline-none focus-visible:ring focus-visible:outline-none dark:text-neutral-200">
{tag}
</span>
))
}
</div> </div>
<SocialShareButton pageTitle={post.title}/> <SocialShareButton
pageTitle={post.title}
/>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -4,13 +4,11 @@ import { readItems, readSingleton } from '@directus/sdk';
import type { Post } from '@lib/directusTypes'; import type { Post } from '@lib/directusTypes';
import HeaderSection from '@components/sections/HeaderSection.astro';
import BlogCard from '@components/cards/BlogCard.astro'; import BlogCard from '@components/cards/BlogCard.astro';
import HeaderSection from '@components/sections/HeaderSection.astro';
import BaseLayout from '@layouts/BaseLayout.astro'; import BaseLayout from '@layouts/BaseLayout.astro';
import directus from '@lib/directus'; import directus from '@lib/directus';
const { category } = Astro.props;
export async function getStaticPaths() { export async function getStaticPaths() {
const categories = await getCollection('categories'); const categories = await getCollection('categories');
return categories.map((category) => ({ return categories.map((category) => ({
@@ -19,6 +17,8 @@ export async function getStaticPaths() {
})); }));
} }
const { category } = Astro.props;
const global = await directus.request(readSingleton('site_global')); const global = await directus.request(readSingleton('site_global'));
const posts = await directus.request( const posts = await directus.request(
readItems('posts', { readItems('posts', {
@@ -62,8 +62,8 @@ const categoriesPosts = posts
btnURL="/categories" btnURL="/categories"
/> />
<section class="max-w-340 2xl:max-w-full mb-10 px-4 sm:px-6 lg:px-8 py-8 mx-auto mt-10"> <section class="max-w-340 2xl:max-w-full mx-auto mt-10 mb-10 px-4 py-8 sm:px-6 lg:px-8">
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6"> <div class="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
{categoriesPosts.map((b) => {categoriesPosts.map((b) =>
<BlogCard post={b} /> <BlogCard post={b} />
)} )}

View File

@@ -1,10 +1,10 @@
--- ---
import { readSingleton } from '@directus/sdk'; import { readSingleton } from '@directus/sdk';
import directus from '@lib/directus';
import BaseLayout from '@layouts/BaseLayout.astro';
import HeroSection from '@components/sections/HeroSection.astro'; import HeroSection from '@components/sections/HeroSection.astro';
import CategorySection from '@components/sections/CategorySection.astro'; import CategorySection from '@components/sections/CategorySection.astro';
import BaseLayout from '@layouts/BaseLayout.astro';
import directus from '@lib/directus';
import categoryImg from '@images/autumn_bench.png'; import categoryImg from '@images/autumn_bench.png';

View File

@@ -3,13 +3,13 @@ import { readSingleton, readItems } from '@directus/sdk';
import type { Post } from '@lib/directusTypes'; import type { Post } from '@lib/directusTypes';
import directus from '@lib/directus';
import BaseLayout from '@layouts/BaseLayout.astro';
import HeroSection from '@components/sections/HeroSection.astro'; import HeroSection from '@components/sections/HeroSection.astro';
import FeatureSection from '@components/sections/FeatureSection.astro'; import FeatureSection from '@components/sections/FeatureSection.astro';
import WeatherSection from '@components/sections/WeatherSection.astro'; import WeatherSection from '@components/sections/WeatherSection.astro';
import RecentPostsSection from '@components/sections/RecentPostsSection.astro'; import RecentPostsSection from '@components/sections/RecentPostsSection.astro';
import GiteaSection from '@components/sections/GiteaSection.astro'; import GiteaSection from '@components/sections/GiteaSection.astro';
import BaseLayout from '@layouts/BaseLayout.astro';
import directus from '@lib/directus';
import homeImg from '@images/autumn_mountain.png'; import homeImg from '@images/autumn_mountain.png';

View File

@@ -1,14 +1,31 @@
// https://docs.astro.build/en/guides/integrations-guide/sitemap/#usage // https://docs.astro.build/en/guides/integrations-guide/sitemap/#usage
import type { APIRoute } from 'astro'; import type { APIRoute } from 'astro';
const getRobotsTxt = (sitemapURL: URL) => `\ const robotsTxt = `
User-agent: Googlebot
Disallow:
Allow: /
Crawl-delay: 10
User-agent: Yandex
Disallow:
Allow: /
Crawl-delay: 2
User-agent: archive.org_bot
Disallow:
Allow: /
Crawl-delay: 2
User-agent: * User-agent: *
Allow: / Allow: /
Sitemap: ${sitemapURL.href} Sitemap: ${new URL('sitemap-index.xml', import.meta.env.SITE).href}`.trim();
`;
export const GET: APIRoute = ({ site }) => { export const GET: APIRoute = () => {
const sitemapURL = new URL('sitemap-index.xml', site); return new Response(robotsTxt, {
return new Response(getRobotsTxt(sitemapURL)); headers: {
'Content-Type': 'text/plain; charset=utf-8',
},
});
}; };

View File

@@ -9,8 +9,8 @@
/* https://tailwindcss.com/docs/dark-mode */ /* https://tailwindcss.com/docs/dark-mode */
@custom-variant dark (&:where(.dark, .dark *)); @custom-variant dark (&:where(.dark, .dark *));
/* Custom colors */
@theme { @theme {
/* Custom colors */
--color-midnight: #0c354d; --color-midnight: #0c354d;
--color-ocean: #134e70; --color-ocean: #134e70;
@@ -26,24 +26,13 @@
--color-gitea-primary: #609926; --color-gitea-primary: #609926;
--color-gitea-secondary: #4c7a33; --color-gitea-secondary: #4c7a33;
/* Theme colors */
--color-main: light-dark(var(--color-steel), var(--color-bermuda)); --color-main: light-dark(var(--color-steel), var(--color-bermuda));
--color-accent: light-dark(var(--color-bronze), var(--color-desert)); --color-accent: light-dark(var(--color-bronze), var(--color-desert));
--color-active: light-dark(var(--color-orange-500), var(--color-orange-300));
/* Text colors */
--color-header: light-dark(var(--color-neutral-800), var(--color-neutral-200)); --color-header: light-dark(var(--color-neutral-800), var(--color-neutral-200));
--color-primary: light-dark(var(--color-neutral-600), var(--color-neutral-200)); --color-primary: light-dark(var(--color-neutral-600), var(--color-neutral-200));
--color-primary-hover: light-dark(var(--color-neutral-800), var(--color-neutral-400)); --color-primary-hover: light-dark(var(--color-neutral-800), var(--color-neutral-400));
--color-secondary: light-dark(var(--color-neutral-500), var(--color-neutral-400)); --color-secondary: light-dark(var(--color-neutral-500), var(--color-neutral-400));
--color-secondary-hover: light-dark(var(--color-neutral-800), var(--color-neutral-200));
/* Object colors */
--color-background: light-dark(var(--color-neutral-200), var(--color-stone-700));
--color-background-accent: light-dark(color-mix(in srgb, var(--color-stone-300) 40%, transparent), color-mix(in srgb, var(--color-stone-800) 20%, transparent));
--color-background-card: light-dark(color-mix(in srgb, var(--color-neutral-100) 80%, transparent), color-mix(in srgb, var(--color-neutral-800) 60%, transparent));
--color-divider: light-dark(color-mix(in srgb, var(--color-neutral-400) 50%, transparent), color-mix(in srgb, var(--color-neutral-500) 50%, transparent));
} }
@layer base { @layer base {

View File

@@ -43,7 +43,7 @@
@utility button-bg-neutral { @utility button-bg-neutral {
@apply transition-all duration-300 @apply transition-all duration-300
border border-neutral-100 dark:border-stone-500/20 border border-neutral-100 dark:border-stone-500/20
bg-background-card hover:bg-neutral-100 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
} }
@utility button-bg-gitea { @utility button-bg-gitea {
@@ -56,13 +56,13 @@
@apply transition-all duration-300 @apply transition-all duration-300
rounded-xl rounded-xl
border border-neutral-100 dark:border-stone-500/20 border border-neutral-100 dark:border-stone-500/20
bg-background-card hover:bg-neutral-100 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
shadow-xs hover:shadow-md dark:shadow-md dark:hover:shadow-lg shadow-xs hover:shadow-md dark:shadow-md dark:hover:shadow-lg
} }
@utility card-base-hidden { @utility card-base-hidden {
@apply transition-all duration-300 @apply transition-all duration-300
rounded-2xl rounded-xl
border border-transparent border border-transparent
hover:bg-neutral-400/20 dark:hover:bg-neutral-800/40 hover:bg-neutral-400/20 dark:hover:bg-neutral-800/40
} }
@@ -113,11 +113,6 @@
group-hover:text-main group-hover:text-main
} }
@utility card-hover-text-neutral {
@apply transition-all duration-300
group-hover:text-primary-hover
}
@utility card-hover-text-gitea { @utility card-hover-text-gitea {
@apply transition-all duration-300 @apply transition-all duration-300
group-hover:text-gitea-primary group-hover:text-gitea-primary
@@ -126,10 +121,3 @@
@utility card-text-description { @utility card-text-description {
@apply text-secondary @apply text-secondary
} }
/* Misc */
@utility nav-base {
@apply border border-neutral-100 dark:border-stone-500/20
bg-neutral-100 dark:bg-neutral-800
shadow-xs dark:shadow-md
}

View File

@@ -17,6 +17,21 @@ const TimeAgoConfiguration: string[][] = [
['%s years ago', 'in %s years'], ['%s years ago', 'in %s years'],
]; ];
function formatDate(date: Date): string {
const year = new Date(date).getFullYear();
const month = String(new Date(date).getMonth() + 1).padStart(2, '0');
const day = String(new Date(date).getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
function formatDateTime(date: Date): string {
const hours = String(new Date(date).getHours()).padStart(2, '0');
const minutes = String(new Date(date).getMinutes()).padStart(2, '0');
return `${formatDate(date)} ${hours}:${minutes}`;
}
function timeago(date?: Date): string { function timeago(date?: Date): string {
if (!date) { if (!date) {
return 'today'; return 'today';
@@ -31,12 +46,4 @@ function timeago(date?: Date): string {
return format(date, 'timeago'); return format(date, 'timeago');
} }
function formatDate(date: Date): string { export { formatDate, timeago, formatDateTime };
return new Date(date).toLocaleDateString('en-US', {
year: 'numeric',
month: 'short',
day: 'numeric',
})
}
export { formatDate, timeago };