diff --git a/.forgejo/workflows/deploy.yml b/.forgejo/workflows/deploy.yml
new file mode 100644
index 0000000..4daea37
--- /dev/null
+++ b/.forgejo/workflows/deploy.yml
@@ -0,0 +1,53 @@
+name: deploy
+
+on:
+ push:
+ branches:
+ - main
+ paths:
+ - src/**/*
+ - public/**/*
+ - .forgejo/workflows/deploy.yml
+ - astro.config.mjs
+ - tsconfig.json
+ - package.json
+ - bun.lock
+
+jobs:
+ build:
+ runs-on: trixie
+ env:
+ TERM: dumb
+ NIX_INSTALLER_INIT: "none"
+ NIX_INSTALLER_NO_CONFIRM: "true"
+ NIX_INSTALLER_ENABLE_FLAKES: "true"
+ steps:
+ - name: Checkout repository
+ uses: https://code.forgejo.org/actions/checkout@v6.0.1
+ - name: Setup lix toolchain
+ run: curl -sL https://install.lix.systems/lix | sh -s -- install linux
+ - name: Install bun dependencies
+ run: nix develop -c bun install --frozen-lockfile
+ - name: Build static files for website
+ run: nix develop -c bun run build
+ - name: Upload static files
+ uses: https://code.forgejo.org/forgejo/upload-artifact@v5
+ with:
+ name: website-${{ forge.sha }}
+ retention-days: 1
+ path: dist
+ deploy:
+ needs: [build]
+ runs-on: trixie
+ env: { TERM: "dumb" }
+ container: { image: "node:current" }
+ steps:
+ - name: Download static files
+ uses: https://code.forgejo.org/forgejo/download-artifact@v7
+ with: { name: "website-${{ forge.sha }}", path: "dist" }
+ - name: Deploy website to cloudflare
+ uses: https://github.com/cloudflare/wrangler-action@v3.14.1
+ with:
+ apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
+ accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
+ command: pages deploy dist --project-name=website
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
deleted file mode 100644
index d75f7cf..0000000
--- a/.gitlab-ci.yml
+++ /dev/null
@@ -1,41 +0,0 @@
-stages:
- - build
- - deploy
-
-workflow:
- rules:
- - changes:
- - src/**/*
- - public/**/*
- - astro.config.mjs
- - .gitlab-ci.yml
- - tsconfig.json
- - package.json
- - flake.lock
- - flake.nix
- - bun.lock
-
-build:
- stage: build
- image: alpine:edge
- variables:
- TERM: "dumb"
- NIX_INSTALLER_NO_CONFIRM: "true"
- NIX_INSTALLER_ENABLE_FLAKES: "true"
- before_script:
- - apk add --no-cache curl bash git xz
- - curl -sL https://install.lix.systems/lix | sh -s -- install linux --init none
- - source /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
- script:
- - nix develop -c bun install
- - nix develop -c bun run build
- artifacts:
- name: website-$CI_COMMIT_SHA
- expire_in: 1 day
- paths: [dist]
-
-deploy:
- stage: deploy
- image: node:alpine
- needs: [build]
- script: npx wrangler pages deploy dist --project-name=website
diff --git a/README.md b/README.md
index c9ed7b8..f1087c1 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# Website
+# website ![license] ![status]
The source code of my personal website and blog, made using the [Astro] static
site generator.
@@ -13,6 +13,9 @@ Due to the nature of the content in this repository, it uses multiple licenses.
All files that are in this repository must follow these licenses.
+[status]: https://badge.hanna.lol/build/hanna/website/main
+[license]: https://badge.hanna.lol/license/MPL-2.0
+
[astro]: https://astro.build
[mpl-2.0]: https://choosealicense.com/licenses/mpl-2.0
[cc by-nc-nd 4.0]: https://creativecommons.org/licenses/by-nc-nd/4.0
diff --git a/astro.config.mjs b/astro.config.mjs
index 370650a..be3c776 100644
--- a/astro.config.mjs
+++ b/astro.config.mjs
@@ -5,4 +5,7 @@ import mdx from '@astrojs/mdx';
export default defineConfig({
integrations: [mdx()],
+ image: {
+ service: { entrypoint: 'astro/assets/services/noop' },
+ },
});
diff --git a/flake.lock b/flake.lock
index 99afc80..4a3a29d 100644
--- a/flake.lock
+++ b/flake.lock
@@ -21,11 +21,11 @@
},
"nixpkgs": {
"locked": {
- "lastModified": 1765903799,
- "narHash": "sha256-1wbl0y7U8TvSHxDWME7o92bIspfuhjVaTOs27r54uc4=",
+ "lastModified": 1766025857,
+ "narHash": "sha256-Lav5jJazCW4mdg1iHcROpuXqmM94BWJvabLFWaJVJp0=",
"owner": "nixos",
"repo": "nixpkgs",
- "rev": "e8d16d2186d6ed9f047eb30948e97e7e01886d10",
+ "rev": "def3da69945bbe338c373fddad5a1bb49cf199ce",
"type": "github"
},
"original": {
diff --git a/public/img/calendar.svg b/public/img/calendar.svg
deleted file mode 100644
index 0bc0e04..0000000
--- a/public/img/calendar.svg
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/public/img/emoji.svg b/public/img/emoji.svg
deleted file mode 100644
index 7aa22b8..0000000
--- a/public/img/emoji.svg
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/public/img/envelope.svg b/public/img/envelope.svg
deleted file mode 100644
index 61a5570..0000000
--- a/public/img/envelope.svg
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/public/img/file-user.svg b/public/img/file-user.svg
deleted file mode 100644
index bdb1648..0000000
--- a/public/img/file-user.svg
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/public/img/games.svg b/public/img/games.svg
deleted file mode 100644
index a9a4425..0000000
--- a/public/img/games.svg
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/public/img/gitlab.svg b/public/img/gitlab.svg
deleted file mode 100644
index 1a36ff5..0000000
--- a/public/img/gitlab.svg
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/public/img/heart.svg b/public/img/heart.svg
deleted file mode 100644
index a6d708c..0000000
--- a/public/img/heart.svg
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/public/img/user-lock.svg b/public/img/user-lock.svg
deleted file mode 100644
index 2db0c0c..0000000
--- a/public/img/user-lock.svg
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/public/img/avatar.png b/src/images/avatar.png
similarity index 100%
rename from public/img/avatar.png
rename to src/images/avatar.png
diff --git a/src/images/calendar.svg b/src/images/calendar.svg
new file mode 100644
index 0000000..0ade821
--- /dev/null
+++ b/src/images/calendar.svg
@@ -0,0 +1 @@
+
diff --git a/src/images/emoji.svg b/src/images/emoji.svg
new file mode 100644
index 0000000..defdbc7
--- /dev/null
+++ b/src/images/emoji.svg
@@ -0,0 +1 @@
+
diff --git a/src/images/envelope.svg b/src/images/envelope.svg
new file mode 100644
index 0000000..f4046c9
--- /dev/null
+++ b/src/images/envelope.svg
@@ -0,0 +1 @@
+
diff --git a/src/images/file-user.svg b/src/images/file-user.svg
new file mode 100644
index 0000000..fe99ac6
--- /dev/null
+++ b/src/images/file-user.svg
@@ -0,0 +1 @@
+
diff --git a/src/images/games.svg b/src/images/games.svg
new file mode 100644
index 0000000..d811c37
--- /dev/null
+++ b/src/images/games.svg
@@ -0,0 +1 @@
+
diff --git a/src/images/git-branch.svg b/src/images/git-branch.svg
new file mode 100644
index 0000000..3e6d3ad
--- /dev/null
+++ b/src/images/git-branch.svg
@@ -0,0 +1 @@
+
diff --git a/src/images/heart.svg b/src/images/heart.svg
new file mode 100644
index 0000000..fc6135a
--- /dev/null
+++ b/src/images/heart.svg
@@ -0,0 +1 @@
+
diff --git a/src/images/user-lock.svg b/src/images/user-lock.svg
new file mode 100644
index 0000000..d5f30ab
--- /dev/null
+++ b/src/images/user-lock.svg
@@ -0,0 +1 @@
+
diff --git a/src/layouts/Page.astro b/src/layouts/Page.astro
index 064278c..4f1a36f 100644
--- a/src/layouts/Page.astro
+++ b/src/layouts/Page.astro
@@ -8,6 +8,7 @@ const { title, desc } = Astro.props;
{title}
+
@@ -16,13 +17,13 @@ const { title, desc } = Astro.props;
diff --git a/src/pages/blog/[slug].astro b/src/pages/blog/[slug].astro
index 4969959..ea10cf6 100644
--- a/src/pages/blog/[slug].astro
+++ b/src/pages/blog/[slug].astro
@@ -11,11 +11,12 @@ export async function getStaticPaths() {
}));
}
-const fmtDate = (date) => new Date(date).toLocaleString('en-US', {
- month: '2-digit',
- day: '2-digit',
- year: 'numeric'
-});
+const fmtDate = (date: Date) =>
+ new Date(date).toLocaleString('en-US', {
+ month: '2-digit',
+ day: '2-digit',
+ year: 'numeric',
+ });
const { post } = Astro.props;
const { Content, headings } = await post.render();
@@ -31,27 +32,33 @@ const { Content, headings } = await post.render();
-
- Table of Contents
-
- {headings.filter(h => h.depth > 1 && h.depth < 4).map(h => (
- -
- {h.text}
-
- ))}
-
-
+
-
- This article is licensed under the
-
- CC BY-NC-ND 4.0
-
- license.
-
+
+
+ This blog post is licensed under
+
+ CC BY-NC-ND 4.0.
+
@@ -102,16 +109,63 @@ const { Content, headings } = await post.render();
}
}
- .toc {
+ .sidebar {
position: fixed;
left: max(20px, calc(50% - 24rem - 300px));
max-height: calc(100vh - 140px);
+ width: 250px;
+ display: flex;
+ flex-direction: column;
+
+ & > .copyright {
+ color: rgba(194, 200, 204, 0.4);
+ padding-top: var(--space-sm);
+ font-size: 10px;
+
+ & > a {
+ color: var(--text-muted);
+ text-decoration: none;
+ }
+ }
+
+ @media only screen and (max-width: 1400px) {
+ position: relative;
+ max-height: none;
+ width: 100%;
+ left: 0;
+
+ & > .copyright {
+ display: none;
+ }
+ }
+ }
+
+ .copyright.mobile {
+ display: none;
+ color: rgba(194, 200, 204, 0.4);
+ font-size: 10px;
+ border-top: 1px solid rgba(194, 200, 204, 0.1);
+ padding-top: 8px;
+ margin-top: var(--space-sm);
+
+ & > a {
+ color: var(--text-muted);
+ text-decoration: none;
+ }
+
+ @media only screen and (max-width: 1400px) {
+ display: block;
+ }
+ }
+
+ .toc {
border: 1px solid var(--border);
background: var(--bg-secondary);
border-radius: var(--radius);
padding: var(--space-sm);
overflow-y: auto;
- width: 250px;
+ flex: 1;
+ max-height: calc(100vh - 200px);
& summary {
font-size: 14px;
@@ -147,7 +201,6 @@ const { Content, headings } = await post.render();
font-size: 13px;
display: block;
padding: 2px 0;
- transition: color 0.2s;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
@@ -171,12 +224,9 @@ const { Content, headings } = await post.render();
@media only screen and (max-width: 1400px) {
margin-top: 12px;
- position: relative;
overflow: visible;
max-height: none;
- width: calc(100% - 22px);
- left: 0;
- top: 0;
+ flex: none;
&:not([open]) {
margin-bottom: 0;
@@ -330,7 +380,8 @@ const { Content, headings } = await post.render();
text-decoration-color: transparent;
text-underline-offset: 2px;
color: var(--accent-blue);
- transition: text-decoration-color 0.25s ease-out;
+ -webkit-user-drag: none;
+ user-drag: none;
}
& :global(a:hover) {
@@ -399,17 +450,5 @@ const { Content, headings } = await post.render();
& :global(blockquote p) {
margin: 0px;
}
-
- & > .copyright {
- border-top: 1px solid rgba(194, 200, 204, 0.1);
- color: rgba(194, 200, 204, 0.4);
- padding-top: 8px;
- font-size: 10px;
-
- & > a {
- color: var(--text-muted);
- text-decoration: none;
- }
- }
}
diff --git a/src/pages/blog/index.astro b/src/pages/blog/index.astro
index 0381198..bbecc56 100644
--- a/src/pages/blog/index.astro
+++ b/src/pages/blog/index.astro
@@ -1,23 +1,25 @@
---
import { getCollection } from 'astro:content';
+import CalendarIcon from '../../images/calendar.svg';
import Page from '../../layouts/Page.astro';
const posts = (await getCollection('posts'))
- .filter(post => !post.data.draft)
+ .filter((post) => !post.data.draft)
.sort((a, b) => {
const firstDate = new Date(a.data.date).valueOf();
const secondDate = new Date(b.data.date).valueOf();
return secondDate - firstDate;
});
-const fmtDate = (date) => new Date(date).toLocaleString('en-US', {
- month: '2-digit',
- day: '2-digit',
- year: 'numeric'
-});
+const fmtDate = (date: Date) =>
+ new Date(date).toLocaleString('en-US', {
+ month: '2-digit',
+ day: '2-digit',
+ year: 'numeric',
+ });
---
-
+
Here be dragons.
@@ -31,11 +33,11 @@ const fmtDate = (date) => new Date(date).toLocaleString('en-US', {
{posts.map((post) => (
- -
+
-
@@ -127,9 +129,10 @@ const fmtDate = (date) => new Date(date).toLocaleString('en-US', {
max-height: 23px;
color: var(--text-muted);
- & > img {
+ & > .icon {
margin-right: var(--space-xs);
height: 12px;
+ width: 12px;
}
}
}
diff --git a/src/pages/index.astro b/src/pages/index.astro
index 57a5b4e..f70833a 100644
--- a/src/pages/index.astro
+++ b/src/pages/index.astro
@@ -1,42 +1,52 @@
---
+import { Image } from 'astro:assets';
import Page from '../layouts/Page.astro';
+import Avatar from '../images/avatar.png';
+import EmojiIcon from '../images/emoji.svg';
+import EnvelopeIcon from '../images/envelope.svg';
+import FileUserIcon from '../images/file-user.svg';
+import UserLockIcon from '../images/user-lock.svg';
+import GitBranchIcon from '../images/git-branch.svg';
+import GamesIcon from '../images/games.svg';
+import HeartIcon from '../images/heart.svg';
+
const links = [
{
- name: 'GitLab',
- icon: 'gitlab',
- url: 'https://gitlab.com/hqnna',
+ name: 'GitDab',
+ icon: GitBranchIcon,
+ url: 'https://gitdab.com/hanna',
},
{
name: 'Emojis',
- icon: 'emoji',
+ icon: EmojiIcon,
url: 'https://discord.gg/qZQmTM5Skk',
},
{
name: 'Steam',
- icon: 'games',
+ icon: GamesIcon,
url: 'https://steamcommunity.com/id/sapphicdoll',
},
{
name: 'GPG Key',
- icon: 'user-lock',
+ icon: UserLockIcon,
url: '/files/key.txt',
},
{
name: 'Resume',
- icon: 'file-user',
+ icon: FileUserIcon,
url: '/files/resume.pdf',
},
{
name: 'Contact',
- icon: 'envelope',
+ icon: EnvelopeIcon,
url: 'mailto:me@hanna.lol',
},
{
name: 'Donate',
- icon: 'heart',
+ icon: HeartIcon,
url: 'https://liberapay.com/hqnna',
- }
+ },
];
---
@@ -46,15 +56,15 @@ const links = [
-

+
Hanna Rose
Just your average software engineer