Compare commits

...
4 Commits
Author SHA1 Message Date
SirBlob d993634fbe Link ARC GitHub as code 2026-11-01 01:38:51 -05:00
SirBlob c21160711b Mark PokemonTCGAPI as deprecated 2026-11-01 01:38:51 -05:00
SirBlob 5d7e9857ca Open startup terminal as a floating window 2026-11-01 01:38:51 -05:00
SirBlob 722e182076 Add setup section to about page 2026-11-01 01:38:51 -05:00
10 changed files with 221 additions and 3 deletions

No files matched your search

+33
View File
@@ -1,6 +1,39 @@
{ {
"anilistUsername": "SirBlob", "anilistUsername": "SirBlob",
"lastfmUsername": "Sir_Blob_", "lastfmUsername": "Sir_Blob_",
"setup": {
"user": "blob",
"host": "blomarchy",
"steam": [
" ( ) (",
" ) ( ) )",
" ( ) ( ("
],
"art": [
" ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄",
" ██ ██▄▄▄▄▄",
" ██ ██ ██",
" ██ ██ ██",
" ██ ██▀▀▀▀▀",
" ██ ██",
" ▀█▄▄▄▄▄▄▄▄▄▄▄█▀",
"▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄",
" ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀"
],
"specs": [
{ "label": "host", "value": "Lenovo IdeaPad Flex 5i" },
{ "label": "os", "value": "Arch Linux x86_64" },
{ "label": "kernel", "value": "Linux (arch)" },
{ "label": "shell", "value": "bash" },
{ "label": "wm", "value": "Hyprland (Wayland)" },
{ "label": "term", "value": "foot" },
{ "label": "display", "value": "2x 1920x1080 24\", 60 Hz + 75 Hz" },
{ "label": "cpu", "value": "Intel Core i5-1335U (4+8) @ 4.60 GHz" },
{ "label": "gpu", "value": "Intel Iris Xe Graphics" },
{ "label": "memory", "value": "16 GB" }
],
"dotfilesUrl": "https://github.com/SirBlobby/dotfiles"
},
"hobbies": [ "hobbies": [
{ "name": "Swimming", "icon": "proicons:person-swim", "description": "I enjoy swimming as a way to relax and stay active. It is my favorite sport." }, { "name": "Swimming", "icon": "proicons:person-swim", "description": "I enjoy swimming as a way to relax and stay active. It is my favorite sport." },
{ "name": "Baking", "icon": "proicons:cake", "description": "I love baking pastries and experimenting with new dessert recipes." }, { "name": "Baking", "icon": "proicons:cake", "description": "I love baking pastries and experimenting with new dessert recipes." },
+1 -1
View File
@@ -9,10 +9,10 @@
"gallery": ["/organizations/arc-1.jpg", "/organizations/arc-2.jpg", "/organizations/arc-3.jpg"], "gallery": ["/organizations/arc-1.jpg", "/organizations/arc-2.jpg", "/organizations/arc-3.jpg"],
"links": { "links": {
"website": "https://gmu.autonomousrobotics.club/", "website": "https://gmu.autonomousrobotics.club/",
"code": "https://github.com/ARC-GMU",
"article": "https://www.gmu.edu/news/2026-05/george-mason-students-fly-first-place-no-gps-no-grade-and-almost-no-problems" "article": "https://www.gmu.edu/news/2026-05/george-mason-students-fly-first-place-no-gps-no-grade-and-almost-no-problems"
}, },
"socials": [ "socials": [
{ "name": "GitHub", "icon": "mdi:github", "url": "https://github.com/ARC-GMU" },
{ "name": "Instagram", "icon": "mdi:instagram", "url": "https://www.instagram.com/arc.gmu/" }, { "name": "Instagram", "icon": "mdi:instagram", "url": "https://www.instagram.com/arc.gmu/" },
{ "name": "LinkedIn", "icon": "mdi:linkedin", "url": "https://www.linkedin.com/company/arcgmu/" }, { "name": "LinkedIn", "icon": "mdi:linkedin", "url": "https://www.linkedin.com/company/arcgmu/" },
{ "name": "CREATE Lab", "icon": "ph:flask-duotone", "url": "https://create.autonomousrobotics.club/projects/autonomous-robotics-club" } { "name": "CREATE Lab", "icon": "ph:flask-duotone", "url": "https://create.autonomousrobotics.club/projects/autonomous-robotics-club" }
+1
View File
@@ -10,6 +10,7 @@
"name": "PokemonTCGAPI", "name": "PokemonTCGAPI",
"description": "Unofficial NPM package wrapper for the PokemonTCG API.", "description": "Unofficial NPM package wrapper for the PokemonTCG API.",
"tags": ["TypeScript", "Node.js"], "tags": ["TypeScript", "Node.js"],
"deprecated": true,
"links": { "package": "https://www.npmjs.com/package/@bosstop/pokemontcgapi", "code": "https://github.com/SirBlobby/PokemonTCGAPI" } "links": { "package": "https://www.npmjs.com/package/@bosstop/pokemontcgapi", "code": "https://github.com/SirBlobby/PokemonTCGAPI" }
}, },
{ {
@@ -0,0 +1,141 @@
<script lang="ts">
import type { DesktopSetup } from '#lib/content/types';
let { setup }: { setup: DesktopSetup } = $props();
const title = $derived(`${setup.user}@${setup.host}`);
const dotfilesLabel = $derived(setup.dotfilesUrl.replace(/^https?:\/\//, ''));
const paletteColors = ['red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'foreground'];
</script>
<div class="fetch">
<div class="art" aria-hidden="true">
<pre class="steam">{#each setup.steam as line, index (index)}<span style:animation-delay="{index * 0.4}s">{line}</span>
{/each}</pre>
<pre class="cup">{setup.art.join('\n')}</pre>
</div>
<div class="info">
<div class="heading">
<span class="accent">{setup.user}</span><span class="muted">@</span><span class="accent">{setup.host}</span>
</div>
<div class="muted">{'-'.repeat(title.length)}</div>
{#each setup.specs as spec (spec.label)}
<div class="row"><span class="label">{spec.label}</span><span>{spec.value}</span></div>
{/each}
<div class="row">
<span class="label">dotfiles</span>
<a class="link" href={setup.dotfilesUrl} target="_blank" rel="noopener noreferrer">{dotfilesLabel}</a>
</div>
<div class="palette" aria-hidden="true">
{#each paletteColors as color (color)}
<span style:background="var(--{color})"></span>
{/each}
</div>
</div>
</div>
<style>
.fetch {
display: flex;
align-items: flex-start;
gap: 1.5rem;
}
.art {
flex-shrink: 0;
align-self: center;
}
.art pre {
margin: 0;
font-size: 1.2rem;
line-height: 1.2;
}
.steam {
color: var(--muted);
}
.steam span {
display: inline-block;
animation: steam-rise 2.4s ease-in-out infinite;
}
.steam {
font-weight: 700;
}
.cup {
color: var(--accent);
line-height: 1;
}
@keyframes steam-rise {
0%,
100% {
opacity: 0.35;
transform: translateY(2px);
}
50% {
opacity: 1;
transform: translateY(-2px);
}
}
@media (prefers-reduced-motion: reduce) {
.steam span {
animation: none;
}
}
.info {
display: flex;
flex-direction: column;
min-width: 0;
line-height: 1.5;
}
.accent {
color: var(--accent);
font-weight: 700;
}
.row {
display: grid;
grid-template-columns: 5.5rem minmax(0, 1fr);
gap: 0.5rem;
}
.label {
color: var(--blue);
font-weight: 700;
}
.link {
overflow: hidden;
color: var(--green);
white-space: nowrap;
text-overflow: ellipsis;
}
.link:hover {
text-decoration: underline;
}
.palette {
display: flex;
margin-top: 0.6rem;
}
.palette span {
width: 1.5rem;
height: 0.9rem;
}
@container (max-width: 700px) {
.art {
display: none;
}
}
</style>
@@ -0,0 +1,11 @@
<script lang="ts">
import type { DesktopSetup } from '#lib/content/types';
import Panel from '../../ui/Panel.svelte';
import SetupFetch from './SetupFetch.svelte';
let { setup }: { setup: DesktopSetup } = $props();
</script>
<Panel title="fastfetch" icon="mdi:console">
<SetupFetch {setup} />
</Panel>
@@ -42,6 +42,9 @@
{#if project.featured} {#if project.featured}
<span class="badge featured">Featured</span> <span class="badge featured">Featured</span>
{/if} {/if}
{#if project.deprecated}
<span class="badge deprecated">Deprecated</span>
{/if}
{#if project.version} {#if project.version}
<span class="badge version">v{project.version}</span> <span class="badge version">v{project.version}</span>
{/if} {/if}
@@ -255,6 +258,10 @@
background: var(--orange); background: var(--orange);
} }
.deprecated {
background: var(--red);
}
.version { .version {
background: var(--blue); background: var(--blue);
} }
+16
View File
@@ -81,6 +81,7 @@ export interface Project {
links: ProjectLinks; links: ProjectLinks;
image?: string; image?: string;
featured?: boolean; featured?: boolean;
deprecated?: boolean;
version?: string; version?: string;
organization?: string; organization?: string;
period?: string; period?: string;
@@ -137,9 +138,24 @@ export interface RatedTitle {
url: string; url: string;
} }
export interface LabeledValue {
label: string;
value: string;
}
export interface DesktopSetup {
user: string;
host: string;
steam: string[];
art: string[];
specs: LabeledValue[];
dotfilesUrl: string;
}
export interface AboutContent { export interface AboutContent {
anilistUsername?: string; anilistUsername?: string;
lastfmUsername?: string; lastfmUsername?: string;
setup?: DesktopSetup;
hobbies: Hobby[]; hobbies: Hobby[];
games: Game[]; games: Game[];
shows: RatedTitle[]; shows: RatedTitle[];
+2 -1
View File
@@ -52,9 +52,10 @@ class WindowManager {
return id in this.floatingRects; return id in this.floatingRects;
} }
openTerminal(startupCommand = '') { openTerminal(startupCommand = '', options: { floating?: boolean } = {}) {
const terminal = { id: `kitty-${this.nextTerminalNumber++}`, startupCommand }; const terminal = { id: `kitty-${this.nextTerminalNumber++}`, startupCommand };
this.terminals.push(terminal); this.terminals.push(terminal);
if (options.floating) this.floatingRects[terminal.id] = null;
this.focus(terminal.id); this.focus(terminal.id);
} }
+1 -1
View File
@@ -28,7 +28,7 @@
onMount(() => { onMount(() => {
themeState.restore(); themeState.restore();
const isWideScreen = window.innerWidth >= 768; const isWideScreen = window.innerWidth >= 768;
if (!pageOpen && isWideScreen && desktop.startupCommand) windowManager.openTerminal(desktop.startupCommand); if (!pageOpen && isWideScreen && desktop.startupCommand) windowManager.openTerminal(desktop.startupCommand, { floating: true });
window.addEventListener('click', handleImageClick, true); window.addEventListener('click', handleImageClick, true);
return () => window.removeEventListener('click', handleImageClick, true); return () => window.removeEventListener('click', handleImageClick, true);
}); });
+8
View File
@@ -8,6 +8,7 @@
import AnimeSection from '#lib/components/about/AnimeSection.svelte'; import AnimeSection from '#lib/components/about/AnimeSection.svelte';
import MediaGrid from '#lib/components/about/MediaGrid.svelte'; import MediaGrid from '#lib/components/about/MediaGrid.svelte';
import GameCard from '#lib/components/about/GameCard.svelte'; import GameCard from '#lib/components/about/GameCard.svelte';
import SetupSection from '#lib/components/about/setup/SetupSection.svelte';
import ListeningSection from '#lib/components/about/listening/ListeningSection.svelte'; import ListeningSection from '#lib/components/about/listening/ListeningSection.svelte';
import type { PageProps } from './$types'; import type { PageProps } from './$types';
@@ -23,6 +24,7 @@
const sections = $derived([ const sections = $derived([
{ id: 'hobbies', label: 'Hobbies', color: 'blue' }, { id: 'hobbies', label: 'Hobbies', color: 'blue' },
...(about.setup ? [{ id: 'setup', label: 'Setup', color: 'cyan' }] : []),
{ id: 'games', label: 'Games', color: 'orange' }, { id: 'games', label: 'Games', color: 'orange' },
{ id: 'shows', label: 'Shows', color: 'yellow' }, { id: 'shows', label: 'Shows', color: 'yellow' },
{ id: 'movies', label: 'Movies', color: 'green' }, { id: 'movies', label: 'Movies', color: 'green' },
@@ -47,6 +49,12 @@
</div> </div>
</Section> </Section>
{#if about.setup}
<Section title="Setup" id="setup">
<SetupSection setup={about.setup} />
</Section>
{/if}
<Section title="Games" id="games"> <Section title="Games" id="games">
<div class="game-grid"> <div class="game-grid">
{#each about.games as game (game.name)} {#each about.games as game (game.name)}