Compare commits

...

4 Commits

Author SHA1 Message Date
792483232f added lightyears font to feed 2026-04-07 19:31:58 +02:00
224341e3e3 changed image gallery arrows 2026-04-07 18:46:20 +02:00
abdfc505d2 added page indicator 2026-04-07 18:37:54 +02:00
830b5163cb added functional pagination to feed 2026-04-07 17:33:25 +02:00
8 changed files with 182 additions and 130 deletions

View File

@@ -34,7 +34,7 @@
<div class="gallery-zone"> <div class="gallery-zone">
<div class="gallery-container blurred-background"> <div class="gallery-container blurred-background">
<div class="gallery-button-container"> <div class="gallery-button-container">
<button class="gallery-button" onclick={galleryBack}></button> <button class="gallery-button" onclick={galleryBack}>&lt;</button>
<div class="gallery-text-container"> <div class="gallery-text-container">
<p class="gallery-index">{currentIndex + 1} / {images.length} :: <a href={images[currentIndex].src}>full-size</a></p> <p class="gallery-index">{currentIndex + 1} / {images.length} :: <a href={images[currentIndex].src}>full-size</a></p>
<div class="gallery-desc-container"> <div class="gallery-desc-container">
@@ -44,7 +44,7 @@
{/each} {/each}
</div> </div>
</div> </div>
<button class="gallery-button" onclick={galleryForward}></button> <button class="gallery-button" onclick={galleryForward}>&gt;</button>
</div> </div>
<div class="gallery-img-container"> <div class="gallery-img-container">
<img class="gallery-img" loading="lazy" src={images[currentIndex].src} alt={images[currentIndex].alt}> <img class="gallery-img" loading="lazy" src={images[currentIndex].src} alt={images[currentIndex].alt}>

View File

@@ -2,32 +2,44 @@
import Content from "$lib/viewport/content.svelte"; import Content from "$lib/viewport/content.svelte";
import Banner2 from "$lib/banner2.svelte"; import Banner2 from "$lib/banner2.svelte";
import TableOfContents from "$lib/components/table-of-contents.svelte"; import TableOfContents from "$lib/components/table-of-contents.svelte";
import SubtitledImage from "$lib/components/subtitled-image.svelte";
import ImageGallery from "$lib/lists/image-gallery.svelte";
export let data; export let data;
// let a = load(0);
</script> </script>
<svelte:head> <svelte:head>
<title>Art Feed | denizk0461</title> <title>Art Feed | denizk0461</title>
</svelte:head> </svelte:head>
{#snippet pageButtons(currentIndex: number)}
<div class="page-button-container blurred-background">
{#if currentIndex == 1}
<p class="page-button page-button-left">x</p>
{:else}
<a class="page-button page-button-left page-button-clickable" href="?p={currentIndex - 1}">&lt;</a>
{/if}
{#each { length: data.maxPages }, index}
<a class="page-index" href="?p={index + 1}">{index + 1}</a>
{/each}
{#if currentIndex == data.maxPages}
<p class="page-button page-button-right">x</p>
{:else}
<a class="page-button page-button-right page-button-clickable" href="?p={currentIndex + 1}">&gt;</a>
{/if}
</div>
{/snippet}
<Content> <Content>
<Banner2 <Banner2
title="Art Feed" title="Art & Project Feed"
banner="banner.webp" banner="banner.webp"
bannerAlt="Mirror picture of me, pixelated beyond recognition" bannerAlt="Mirror picture of me, pixelated beyond recognition"
subtitle="subtitle missing" subtitle="subtitle missing"
date="2026-04-06" date="2026-04-06"
pixelated
/> />
{@render pageButtons(data.currentPage)}
{#each data.contents as post}
<svelte:component this={post} />
{/each}
<p>Welcome to my (new) art feed! It is heavily inspired by <a href="https://deathsurplus.com/">DeathSurplus' art blog</a> definitely go check out his page!</p> <p>Welcome to my (new) art feed! It is heavily inspired by <a href="https://deathsurplus.com/">DeathSurplus' art blog</a> definitely go check out his page!</p>
@@ -38,66 +50,60 @@
<p>I <b>MAY</b> merge this with the <a href="/projects">Projects</a> page, I've not yet decided.</p> <p>I <b>MAY</b> merge this with the <a href="/projects">Projects</a> page, I've not yet decided.</p>
<TableOfContents /> <TableOfContents />
{#each data.feedEntries as entry}
<h2>{entry.title}</h2>
<p class="subtitle">{entry.subtitle}</p>
<p class="subtitle">{entry.date}</p>
<svelte:component this={entry.content} />
{/each}
<h2>3DS USB-C mod</h2>
<p class="subtitle">DIY charging port mod</p>
<p class="subtitle">October 2024</p>
<SubtitledImage
image="electronics/3ds-usb-c/showcase.mp4"
subtitle="it charges via USB-C! also do you like my A Hat in Time theme?"
video
/>
<p>
I modded my New 3DS XL (SNES Edition) to give it a USB-C port to charge!
</p>
<ImageGallery
images={[
{
src: "electronics/3ds-usb-c/finished.webp",
alt: "A back view at a New Nintendo 3DS XL with a USB-C port added between the charging port and the right shoulder buttons.",
desc: ["the USB-C port in all its glory"],
},
{
src: "electronics/3ds-usb-c/hole.webp",
alt: "At the top is a view at a USB-C-shaped hole cut into the back half of a New 3DS XL. At the bottom is a look at the same hole from the inside of the case. There are rough cutouts where the stylus slides in.",
desc: [
"a closer look at the holes I cut, and how they affect the stylus slot",
],
},
]}
/>
<p>
I used a small USB-C breakout I had lying around that is wired straight
into the charging pads of the original charging port, which is left
completely intact. The breakout board also has a 5.1kΩ resistor between
ground and one of the CC pins (which I had to manually find because it's
unlabelled) to allow for using C-to-C cables.
</p>
<p>
What I wrecked in turn was the wrist strap loop, which I completely cut
out to create the hole for the port. The stylus port also got cut down
to make space, but my stylus is kind of broken and doesn't stay put when
I put it into the system, so I didn't really care about that.
</p>
<p>
It works well! The hole isn't the prettiest but it was pretty simple to
pull off, and extremely cheap as well. In turn I got a 3DS that I can
charge using any USB-C cable and I no longer need to lug around the
proprietary 3DS charger!
</p>
</Content> </Content>
<style> <style>
.page-button-container {
display: flex;
flex-direction: row;
align-items: stretch;
justify-content: center;
border-radius: var(--border-radius);
overflow: hidden;
width: fit-content;
margin: 12px auto;
border-top: var(--border-style) var(--border-dash-size) var(--color-highlight-alt);
border-bottom: var(--border-style) var(--border-dash-size) var(--color-highlight-alt);
}
.page-button, .page-index {
font-family: var(--font-mono);
padding: 8px 18px;
font-weight: 600;
margin: 0;
transition: background-color var(--duration-animation) var(--anim-curve);
}
.page-button {
color: var(--color-text);
}
.page-button-left {
border-right: var(--border-style) var(--border-dash-size) var(--color-highlight-alt);
}
.page-button-right {
border-left: var(--border-style) var(--border-dash-size) var(--color-highlight-alt);
}
.page-button-clickable:hover {
cursor: pointer;
}
.page-index:link, .page-index:visited {
color: var(--color-text)
}
.page-index:hover, .page-button-clickable:hover {
text-decoration: none;
background-color: var(--color-background-highlight-alt);
}
.subtitle { .subtitle {
font-family: var(--font-mono); font-family: var(--font-mono);
margin: 0; margin: 0;

View File

@@ -1,25 +1,50 @@
import { entries } from './feed'; import { entries } from './feed';
interface FeedEntry {
content: any;
title: string;
subtitle: string;
date: string;
}
let entriesPerPage = 8;
export async function load({ params, url }) { export async function load({ params, url }) {
// Get page index // Get page index
let pageIndex = Number(url.searchParams.get('p')); let pageIndex = Number(url.searchParams.get('p'));
if (pageIndex == null) { if (pageIndex == 0) {
pageIndex = 0; pageIndex = 1;
} }
let contents = []; // TODO check if index exceeds maximum permitted and redirect (to max page?)
for (let i = 0; i < 2; i += 1) { let feedEntries: FeedEntry[] = [];
let start = (pageIndex - 1) * entriesPerPage;
for (let i = start; i < start + entriesPerPage; i += 1) {
// Stop iterating when end reached
if (i >= entries.length) {
break;
}
// Vite complains if I don't do this even though it's stupid // Vite complains if I don't do this even though it's stupid
const path = entries[i].split("/"); const path = entries[i].split("/");
const page = await import(`./${path[0]}/${path[1]}.md`); const page = await import(`./${path[0]}/${path[1]}.md`);
const md = page.metadata;
contents.push(page.default); feedEntries.push({
content: page.default,
title: md.title,
subtitle: md.subtitle,
date: md.date,
});
} }
// const content = p.default; let currentPage = pageIndex;
let maxPages = Math.ceil(entries.length / entriesPerPage);
return { return {
contents, currentPage,
maxPages,
feedEntries,
}; };
} }

View File

@@ -1,13 +1,14 @@
---
title: My First Month Drawing
subtitle: self-imposed drawing challenge
date: February March 2026
---
<script lang="ts"> <script lang="ts">
import ImageGallery from "$lib/lists/image-gallery.svelte"; import ImageGallery from "$lib/lists/image-gallery.svelte";
</script> </script>
## My First Month Drawing Back in January, I was thinking to myself that I'd really like to learn to draw. It would have some practical benefits like potentially being able to draw concept art for my game, but ultimately I just liked the idea of drawing as a hobby. I doodled a few small things before deciding that I should challenge myself to draw something every single day for an entire month (4 weeks); [I documented the entire thing here](/blog/2026/0205), but spoiler alert: I think I succeeded in learning to draw and I am now able to sketch like I was never able to before!
<p class="subtitle">self-imposed drawing challenge</p>
<p class="subtitle">February March 2026</p>
Back in January, I was thinking to myself that I'd really like to learn to draw. It would have some practical benefits like potentially being able to draw concept art for my game, but ultimately I just liked the idea of drawing as a hobby. I doodled a few small things before deciding that I should challenge myself to draw something every single day for an entire month (4 weeks); <a href="/blog/2026/0205">I documented the entire thing here</a>, but spoiler alert: I think I succeeded in learning to draw and I am now able to sketch like I was never able to before!
Here are some of my favourite drawings from around that time, in chronological order: Here are some of my favourite drawings from around that time, in chronological order:

View File

@@ -0,0 +1,41 @@
---
title: 3DS USB-C mod
subtitle: DIY charging port mod
date: October 2024
---
<script lang="ts">
import SubtitledImage from "$lib/components/subtitled-image.svelte";
import ImageGallery from "$lib/lists/image-gallery.svelte";
</script>
<SubtitledImage
image="electronics/3ds-usb-c/showcase.mp4"
subtitle="it charges via USB-C! also do you like my A Hat in Time theme?"
video
/>
I modded my New 3DS XL (SNES Edition) to give it a USB-C port to charge!
<ImageGallery
images={[
{
src: "electronics/3ds-usb-c/finished.webp",
alt: "A back view at a New Nintendo 3DS XL with a USB-C port added between the charging port and the right shoulder buttons.",
desc: ["the USB-C port in all its glory"],
},
{
src: "electronics/3ds-usb-c/hole.webp",
alt: "At the top is a view at a USB-C-shaped hole cut into the back half of a New 3DS XL. At the bottom is a look at the same hole from the inside of the case. There are rough cutouts where the stylus slides in.",
desc: [
"a closer look at the holes I cut, and how they affect the stylus slot",
],
},
]}
/>
I used a small USB-C breakout I had lying around that is wired straight into the charging pads of the original charging port, which is left completely intact. The breakout board also has a 5.1kΩ resistor between ground and one of the CC pins (which I had to manually find because it's unlabelled) to allow for using C-to-C cables.
What I wrecked in turn was the wrist strap loop, which I completely cut out to create the hole for the port. The stylus port also got cut down to make space, but my stylus is kind of broken and doesn't stay put when I put it into the system, so I didn't really care about that.
It works well! The hole isn't the prettiest but it was pretty simple to pull off, and extremely cheap as well. In turn I got a 3DS that I can charge using any USB-C cable and I no longer need to lug around the proprietary 3DS charger!

View File

@@ -1,12 +1,14 @@
---
title: deej0461
subtitle: PC companion audio source controller
date: August 2024
---
<script lang="ts"> <script lang="ts">
import SubtitledImage from "$lib/components/subtitled-image.svelte"; import SubtitledImage from "$lib/components/subtitled-image.svelte";
import ImageGallery from "$lib/lists/image-gallery.svelte"; import ImageGallery from "$lib/lists/image-gallery.svelte";
</script> </script>
## deej0461
<p class="subtitle">PC companion audio source controller</p>
<p class="subtitle">August 2024</p>
<SubtitledImage <SubtitledImage
image="electronics/deej0461/finished.webp" image="electronics/deej0461/finished.webp"
altText="A golden 3D printed shell with a slider on its left, two LEDs recessed, and four black buttons on its right. The buttons have symbols of speakers, monitors, and headphones printed on them. Three screws at the top are visible. A USB-C cable is plugged into the back of it." altText="A golden 3D printed shell with a slider on its left, two LEDs recessed, and four black buttons on its right. The buttons have symbols of speakers, monitors, and headphones printed on them. Three screws at the top are visible. A USB-C cable is plugged into the back of it."
@@ -16,41 +18,19 @@
/> />
This little device was inspired by one a friend of mine built his own This little device was inspired by one a friend of mine built his own version of: a [deej](https://github.com/omriharel/deej) volume slider panel. This thing allows you to control different applications with individual, *physical*, sliders. Super cool thing.
version of: a <a href="https://github.com/omriharel/deej">deej</a>
volume slider panel. This thing allows you to control different
applications with individual, <i>physical</i>, sliders. Super cool
thing.
Except I didn't need all these sliders, really. A single slider would Except I didn't need all these sliders, really. A single slider would be cool, I thought. You know what I really wanted? Buttons to control the audio <i>source</i>, because I switch between speakers and headphones constantly, and that's at least 3 clicks every time I want to switch. So I built a device based on deej, but with some expansions.
be cool, I thought. You know what I really wanted? Buttons to control
the audio <i>source</i>, because I switch between speakers and
headphones constantly, and that's at least 3 clicks every time I want to
switch. So I built a device based on deej, but with some expansions.
I only used few components: a HID-enabled Arduino-compatible Pro Micro I only used few components: a HID-enabled Arduino-compatible Pro Micro with USB-C controls the whole thing. Hooked up to it are four Cherry switches and a Soldering slider I had lying around from my [Daisy project](/projects/daisy), and I added two LEDs for good measure. It's all packaged into a 3D-printed enclosure I designed myself. The slider is screwed in tightly, and so is the top of the case; the key switches are clipped in from the top so they don't fall out; the Arduino and the LEDs are just hot-glued in. For extra flair, the four output buttons are marked with symbols for my outputs: two monitors, a pair of loudspeakers, and a pair of headphones. In the final device, they're arranged so that my two most frequently-used buttons are at the bottom for easier reach.
with USB-C controls the whole thing. Hooked up to it are four Cherry
switches and a Soldering slider I had lying around from my <a href="/projects/daisy">Daisy project</a>, and I added two LEDs for good measure. It's all packaged into a
3D-printed enclosure I designed myself. The slider is screwed in
tightly, and so is the top of the case; the key switches are clipped in
from the top so they don't fall out; the Arduino and the LEDs are just
hot-glued in. For extra flair, the four output buttons are marked with
symbols for my outputs: two monitors, a pair of loudspeakers, and a pair
of headphones. In the final device, they're arranged so that my two most
frequently-used buttons are at the bottom for easier reach.
Software-wise, I set this up with the original deej software to control Software-wise, I set this up with the original deej software to control main volume. For the audio, I used a program called [SoundSwitch](https://soundswitch.aaflalo.me/). The program listened to key presses for the `F21-F24` keys, which the Arduino triggers when the output keys are pressed. The red LED lights up when a key is pressed; the white LED has no assigned function. This worked pretty well, but this is no longer the setup I use, since I switched to Fedora Linux, as I needed to adapt/change the software for the new OS!
main volume. For the audio, I used a program called <a href="https://soundswitch.aaflalo.me/">SoundSwitch</a>. The program listened to key presses for the <code>F21-F24</code> keys,
which the Arduino triggers when the output keys are pressed. The red LED
lights up when a key is pressed; the white LED has no assigned function.
This worked pretty well, but this is no longer the setup I use, since I switched
to Fedora Linux, as I needed to adapt/change the software for the new OS!
<ImageGallery <ImageGallery
@@ -69,27 +49,9 @@ to Fedora Linux, as I needed to adapt/change the software for the new OS!
/> />
When pressing a keyboard's volume button, Windows raises or lowers When pressing a keyboard's volume button, Windows raises or lowers volume in increments of 2. Fedora does 5. I found this much handier, so I stopped reaching for the slider and just defaulted to using my keyboard. This meant I didn't bother setting up the slider in Fedora. The buttons work, though, but they needed some adjustment. I think (and I might be wrong??) that Linux doesn't support function keys past F12, so I changed the Arduino script so the buttons trigger `Shift + F9-F12`. Instead of a separate program (which kept asking to be updated...), I now use KDE's built-in Shortcuts that trigger a script. The script is one line: `pactl set-default-sink [sink-name]`. The sink name is hard-coded into the file because, as extensive testing proved, Shortcuts does not allow arguments when entering a command. I currently only have two files set up: one for the primary monitor, one for the headphones.
volume in increments of 2. Fedora does 5. I found this much handier, so
I stopped reaching for the slider and just defaulted to using my
keyboard. This meant I didn't bother setting up the slider in Fedora.
The buttons work, though, but they needed some adjustment. I think (and
I might be wrong??) that Linux doesn't support function keys past F12,
so I changed the Arduino script so the buttons trigger <code>Shift + F9-F12</code>. Instead of a separate program (which kept asking to be updated...), I
now use KDE's built-in Shortcuts that trigger a script. The script is
one line: <code>pactl set-default-sink [sink-name]</code>. The sink name
is hard-coded into the file because, as extensive testing proved,
Shortcuts does not allow arguments when entering a command. I currently
only have two files set up: one for the primary monitor, one for the
headphones.
I much prefer the setup now because it doesn't rely on third-party I much prefer the setup now because it doesn't rely on third-party
software anymore. software anymore.
This thing is, no exaggeration, one of the handiest things I have ever This thing is, no exaggeration, one of the handiest things I have ever built, because I use it quite literally ***every single day***. I often switch between my monitor's speakers and my headphones, and being able to do that with the press of a single button is *unbelievably* handy. I don't even think about it anymore, I just reach for the buttons whenever I switch. It's a part of my routine now and I wouldn't want to miss it.
built, because I use it quite literally <i><b>every single day</b></i>.
I often switch between my monitor's speakers and my headphones, and
being able to do that with the press of a single button is
<i>unbelievably</i> handy. I don't even think about it anymore, I just reach
for the buttons whenever I switch. It's a part of my routine now and I wouldn't
want to miss it.

View File

@@ -1,4 +1,8 @@
export let entries: string[] = [ export let entries: string[] = [
// 2026
"misc/lightyears-font",
"drawings/firstmonth", "drawings/firstmonth",
// 2024
"electronics/3ds-usb-c",
"electronics/deej0461", "electronics/deej0461",
]; ];

View File

@@ -0,0 +1,13 @@
---
title: LIGHTYEARS font
subtitle: Stylised font
date: March 2026
---
<p class="lightyears-text">The world looks so different now. The world looks so different now. The world looks so different now.</p>
One of my favourite music artists, [Jaron](https://youtu.be/GXvqQ5-P82I), released his album LIGHTYEARS a little over a year ago. For his visuals, he uses a variety of symbols in place of Latin letters, and there's a converter on [his website](https://jaronsteele.com/) too. Only problem is that my browser can't seem to display most of the characters because the characters aren't included in most fonts. That's why I made a font! It allows you to type Latin characters from `A-Z` as well as numbers `0-9` and `!?` in the LIGHTYEARS style. Like this:
<p class="lightyears-text">trans rights!</p>
[Download the font here](https://files.natconf.dev/public/lightyears.woff2). It's in the web-optimised `woff2` format and has most characters stripped to minimise its file size it's less than 20 kilobytes in size! Uppercase and lowercase letters are the same. People can 'decrypt' text by copy-pasting it somewhere else!