From dba6ebd497f0098262e493eb29fafe25d27e34b7 Mon Sep 17 00:00:00 2001 From: Atridad Lahiji Date: Sun, 18 May 2025 23:21:12 -0600 Subject: [PATCH] Finalized --- Dockerfile | 27 +++++++++++ docker-compose.yml | 8 ++++ src/components/NavigationBar.tsx | 2 +- src/components/PostCard.astro | 37 +++++++++------ src/components/ProjectCard.astro | 40 ++++++++++++++++ src/components/ScrollUpButton.tsx | 45 ++++++++++++++++++ src/content/config.ts | 6 +-- src/content/posts/favourite-tools.md | 29 ++++++++++++ src/content/{blog => posts}/welcome.md | 0 src/layouts/Layout.astro | 7 ++- src/pages/{blog => post}/[...slug].astro | 29 ++++-------- src/pages/posts.astro | 8 ++-- src/pages/projects.astro | 58 ++++++++++++++++++++++++ 13 files changed, 250 insertions(+), 46 deletions(-) create mode 100644 Dockerfile create mode 100644 docker-compose.yml create mode 100644 src/components/ProjectCard.astro create mode 100644 src/components/ScrollUpButton.tsx create mode 100644 src/content/posts/favourite-tools.md rename src/content/{blog => posts}/welcome.md (100%) rename src/pages/{blog => post}/[...slug].astro (61%) create mode 100644 src/pages/projects.astro diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..69b4ca2 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,27 @@ +FROM node:lts-alpine AS builder +WORKDIR /app + +RUN npm i -g pnpm + +COPY package.json pnpm-lock.yaml ./ + +RUN pnpm install + +COPY . . +RUN pnpm run build + +FROM node:lts-alpine AS runtime +WORKDIR /app + +RUN npm i -g pnpm + +COPY --from=builder /app/dist ./dist +COPY package.json pnpm-lock.yaml ./ + +RUN pnpm install --prod + +ENV HOST=0.0.0.0 +ENV PORT=4321 +EXPOSE 4321 + +CMD ["node", "./dist/server/entry.mjs"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..438bdf1 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,8 @@ +services: + app: + image: ${IMAGE} + ports: + - "${APP_PORT}:4321" + environment: + NODE_ENV: production + restart: unless-stopped diff --git a/src/components/NavigationBar.tsx b/src/components/NavigationBar.tsx index 8b26825..a75cf63 100644 --- a/src/components/NavigationBar.tsx +++ b/src/components/NavigationBar.tsx @@ -1,6 +1,6 @@ import { useComputed, useSignal } from "@preact/signals"; import { useEffect } from "preact/hooks"; -import { Home, NotebookPen, FileText, CodeXml, MessageCircle } from 'lucide-preact'; +import { Home, NotebookPen, FileText, CodeXml } from 'lucide-preact'; interface NavigationBarProps { currentPath: string; diff --git a/src/components/PostCard.astro b/src/components/PostCard.astro index 475dd1b..6a04fec 100644 --- a/src/components/PostCard.astro +++ b/src/components/PostCard.astro @@ -1,8 +1,8 @@ --- import type { CollectionEntry } from 'astro:content'; - +import { Icon } from 'astro-icon/components'; export interface Props { - post: CollectionEntry<'blog'>; + post: CollectionEntry<'posts'>; } const { post } = Astro.props; @@ -11,19 +11,17 @@ const { slug } = post; ---
-
-

+
+

{title}

-

+

{blurb || 'No description available.'}

-
- - - +
+ {new Date(pubDate).toLocaleDateString("en-us", { month: "long", @@ -33,15 +31,24 @@ const { slug } = post;
-
+ {post.data.tags && post.data.tags.length > 0 && ( +
+ {post.data.tags.map((tag: string) => ( + + + {tag} + + ))} +
+ )} + +
diff --git a/src/components/ProjectCard.astro b/src/components/ProjectCard.astro new file mode 100644 index 0000000..31b4eec --- /dev/null +++ b/src/components/ProjectCard.astro @@ -0,0 +1,40 @@ +--- +import { Icon } from 'astro-icon/components'; + +interface Project { + id: string; + name: string; + description: string; + link: string; +} + +export interface Props { + project: Project; +} + +const { project } = Astro.props; +--- + +
+
+

+ {project.name} +

+ +

+ {project.description} +

+ +
+ + + +
+
+
\ No newline at end of file diff --git a/src/components/ScrollUpButton.tsx b/src/components/ScrollUpButton.tsx new file mode 100644 index 0000000..2e2dc2c --- /dev/null +++ b/src/components/ScrollUpButton.tsx @@ -0,0 +1,45 @@ +import { useSignal } from "@preact/signals"; +import { useEffect } from "preact/hooks"; +import { ArrowUp } from 'lucide-preact'; + +export default function ScrollUpButton() { + const isVisible = useSignal(false); + + useEffect(() => { + const checkScroll = () => { + isVisible.value = window.scrollY > 300; + }; + + checkScroll(); + + window.addEventListener("scroll", checkScroll); + + return () => { + window.removeEventListener("scroll", checkScroll); + }; + }, []); + + const scrollToTop = () => { + window.scrollTo({ + top: 0, + behavior: "smooth", + }); + }; + + return ( + + ); +} \ No newline at end of file diff --git a/src/content/config.ts b/src/content/config.ts index 40aae2c..ae3fcd6 100644 --- a/src/content/config.ts +++ b/src/content/config.ts @@ -1,6 +1,6 @@ import { defineCollection, z } from 'astro:content'; -const blogCollection = defineCollection({ +const postsCollection = defineCollection({ type: 'content', schema: z.object({ title: z.string(), @@ -12,5 +12,5 @@ const blogCollection = defineCollection({ }); export const collections = { - 'blog': blogCollection, -}; \ No newline at end of file + 'posts': postsCollection, +}; \ No newline at end of file diff --git a/src/content/posts/favourite-tools.md b/src/content/posts/favourite-tools.md new file mode 100644 index 0000000..af9ba96 --- /dev/null +++ b/src/content/posts/favourite-tools.md @@ -0,0 +1,29 @@ +--- +title: "Current List of Favourite Tools" +description: "A running list of my favourite tools to use day-to-day." +pubDate: "2025-01-28" +tags: ["list"] +--- + +I change what I use _constantly_ in order to find something that feels just +right. I wanted to share them here and update them here so when someone asks, I +can just point them to this article. + +1. Sublime Text - Currently my favourite text editor. Fast, simple, and + extensible. Just a joy to use! +2. Sublime Merge - Honestly one of the fastest and best looking git GUIs around! + Awesome for visualizing changes when you have larger code changes. +3. Ghostty - A Zig based terminal emulator by one of the founders of Hashicorp. + Runs great on MacOS and Linux. No windows for those who are into that. +4. OrbStack - A faster alternative to Docker Desktop that also runs VMs! +5. Bitwarden - An open-source password manager. Easy to self host with + Vaultwarden and with the recent updates, it has SSH Agent support! +6. iA Writer - A minimalist Markdown editor. For MacOS and Windows only, but + really the MacOS version is the most mature. Awesome for focus. +7. Dataflare - A simple but powerful cross-platform database client. Supports + most common databases, including LibSQL which is rare! +8. Bruno - A simple and powerful API client, similar to Postman. An critical + tool to debug API endpoints. + +I hope you found this helpful! This will be periodically updated to avoid +outdated recommendations. diff --git a/src/content/blog/welcome.md b/src/content/posts/welcome.md similarity index 100% rename from src/content/blog/welcome.md rename to src/content/posts/welcome.md diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro index b47aa90..410b4b5 100644 --- a/src/layouts/Layout.astro +++ b/src/layouts/Layout.astro @@ -1,5 +1,7 @@ --- +import { ClientRouter } from "astro:transitions"; import NavigationBar from "../components/NavigationBar"; +import ScrollUpButton from "../components/ScrollUpButton"; const currentPath = Astro.url.pathname; import '../styles/global.css'; --- @@ -12,12 +14,13 @@ import '../styles/global.css'; Atridad Lahiji +
- - + + diff --git a/src/pages/blog/[...slug].astro b/src/pages/post/[...slug].astro similarity index 61% rename from src/pages/blog/[...slug].astro rename to src/pages/post/[...slug].astro index 0bcb9bc..716292d 100644 --- a/src/pages/blog/[...slug].astro +++ b/src/pages/post/[...slug].astro @@ -1,16 +1,17 @@ --- import { getCollection, type CollectionEntry } from 'astro:content'; +import { Icon } from 'astro-icon/components'; import Layout from '../../layouts/Layout.astro'; export async function getStaticPaths() { - const posts = await getCollection('blog'); - return posts.map((post: CollectionEntry<'blog'>) => ({ + const posts = await getCollection('posts'); + return posts.map((post: CollectionEntry<'posts'>) => ({ params: { slug: post.slug }, props: { post }, })); } -const { post }: { post: CollectionEntry<'blog'> } = Astro.props; +const { post }: { post: CollectionEntry<'posts'> } = Astro.props; const { Content } = await post.render(); --- @@ -24,9 +25,7 @@ const { Content } = await post.render();
- - - +
@@ -59,7 +45,8 @@ const { Content } = await post.render(); {post.data.tags && post.data.tags.length > 0 && (
{post.data.tags.map((tag: string) => ( - + + {tag} ))} diff --git a/src/pages/posts.astro b/src/pages/posts.astro index fc249d1..b83c432 100644 --- a/src/pages/posts.astro +++ b/src/pages/posts.astro @@ -3,12 +3,12 @@ import Layout from "../layouts/Layout.astro"; import { getCollection, type CollectionEntry } from "astro:content"; import PostCard from "../components/PostCard.astro"; -// Get all blog posts from the content collection -const posts = await getCollection("blog"); +// Get all posts from the content collection +const posts = await getCollection("posts"); // Sort posts by date, newest first const sortedPosts = posts.sort( - (a: CollectionEntry<"blog">, b: CollectionEntry<"blog">) => new Date(b.data.pubDate).valueOf() - new Date(a.data.pubDate).valueOf() + (a: CollectionEntry<"posts">, b: CollectionEntry<"posts">) => new Date(b.data.pubDate).valueOf() - new Date(a.data.pubDate).valueOf() ); --- @@ -18,7 +18,7 @@ const sortedPosts = posts.sort( Posts

- {sortedPosts.map((post: CollectionEntry<"blog">) => ( + {sortedPosts.map((post: CollectionEntry<"posts">) => ( ))}
diff --git a/src/pages/projects.astro b/src/pages/projects.astro new file mode 100644 index 0000000..e46c99a --- /dev/null +++ b/src/pages/projects.astro @@ -0,0 +1,58 @@ +--- +import Layout from "../layouts/Layout.astro"; +import ProjectCard from "../components/ProjectCard.astro"; + +const projects = [ + { + id: "bluesky-pds-manager", + name: "BlueSky PDS Manager", + description: + "A web-based BlueSky PDS Manager. Manage your invite codes and users with a simple web UI.", + link: "https://pdsman.atri.dad", + }, + { + id: "pollo", + name: "Pollo", + description: "A dead-simple real-time voting tool.", + link: "https://git.atri.dad/atridad/pollo", + }, + { + id: "goth-stack", + name: "GOTH Stack", + description: + "🚀 A Web Application Template Powered by HTMX + Go + Tailwind 🚀", + link: "https://git.atri.dad/atridad/goth.stack", + }, + { + id: "himbot", + name: "Himbot", + description: + "A discord bot written in Go. Loosly named after my username online (HimbothySwaggins).", + link: "https://git.atri.dad/atridad/himbot", + }, + { + id: "loadr", + name: "loadr", + description: + "A lightweight REST load testing tool with robust support for different verbs, token auth, and performance reports.", + link: "https://git.atri.dad/atridad/loadr", + }, +]; +--- + + +
+

+ Projects +

+
+ {projects.map((project) => ( + + ))} +
+ + {projects.length === 0 && ( +

No projects available yet. Check back soon!

+ )} +
+
\ No newline at end of file