Compare commits
7 Commits
0911a8892f
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| d9045f23c2 | |||
| 816f9cefec | |||
| 94416f5779 | |||
| 7ab4a9a173 | |||
| 2d052acf91 | |||
| 5dee4fccc1 | |||
| d0d74becc5 |
@@ -1,5 +1,5 @@
|
||||
# pages-svelte
|
||||
|
||||
SvelteKit repository for my website hosted at [https://denizk0461.dev/](https://denizk0461.dev/)
|
||||
SvelteKit repository for my website hosted at [https://natconf.dev/](https://natconf.dev/)
|
||||
|
||||

|
||||
@@ -5,23 +5,11 @@ export interface IndieButton {
|
||||
}
|
||||
|
||||
export let buttons: IndieButton[] = [
|
||||
{
|
||||
img: "flag-progress.png",
|
||||
alt: "A button showing the progress pride flag.",
|
||||
},
|
||||
{
|
||||
img: "gnu-linux.gif",
|
||||
alt: "A button with the Linux penguin and the text 'Made on GNU/Linux'.",
|
||||
},
|
||||
{
|
||||
img: "iso8601.png",
|
||||
alt: "A button with the text 'ISO 8601 YYYY-MM-DD'.",
|
||||
link: "https://www.iso8601.com/",
|
||||
},
|
||||
{
|
||||
img: "notbyai.png",
|
||||
alt: "A button with the text 'created by a human, not by AI' and a smiley next to it.",
|
||||
},
|
||||
{
|
||||
img: "queercoded.png",
|
||||
alt: "A button with the text \"you're telling me a queer coded this\" on a rainbow background.",
|
||||
@@ -31,11 +19,6 @@ export let buttons: IndieButton[] = [
|
||||
alt: "A red button with the text 'MADE WITH SVELTEKIT'.",
|
||||
link: "https://svelte.dev",
|
||||
},
|
||||
{
|
||||
img: "sexno.png",
|
||||
alt: "A button with the text 'SEX? NO.' on a white background with a blue border.",
|
||||
link: "https://youtu.be/J4i0tuoYBG0?t=176",
|
||||
},
|
||||
{
|
||||
img: "trans-rights-now.png",
|
||||
alt: "A button with the text 'TRANS RIGHTS NOW!' next to a trans flag.",
|
||||
|
||||
@@ -80,10 +80,11 @@
|
||||
}
|
||||
|
||||
.toc-container {
|
||||
max-width: 650px;
|
||||
max-width: var(--width-toc);
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
margin-top: 12px;
|
||||
box-sizing: border-box;
|
||||
background-color: var(--color-background-highlight);
|
||||
padding: 16px 0;
|
||||
border: var(--border-style) var(--border-dash-size) var(--color-highlight);
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
</div>
|
||||
<span class="update-entry-timestamp-divider">::</span>
|
||||
<p>
|
||||
{entry.content}
|
||||
{@html entry.content}
|
||||
{#if entry.link}
|
||||
<a class="update-entry-link" href="{entry.link}">»</a>
|
||||
{/if}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<div class="content-container">
|
||||
<div class="content-box center-box">
|
||||
<p>〔 2023–2026 〕denizk0461</p>
|
||||
<p>Built from commit <a class="commit" href="https://code.denizk0461.dev/denizk0461/pages/src/commit/{version}">{version.substring(0, 6)}</a></p>
|
||||
<p>Built from commit <a class="commit" href="https://code.natconf.dev/denizk0461/pages/src/commit/{version}">{version.substring(0, 6)}</a></p>
|
||||
</div>
|
||||
<div class="content-box">
|
||||
<h6>Content</h6>
|
||||
@@ -35,7 +35,7 @@
|
||||
<a href="/meta/about">About</a>
|
||||
<a href="/meta/feeds">Feeds</a>
|
||||
<a href="/meta/updates">Updates</a>
|
||||
<a href="https://code.denizk0461.dev/denizk0461/pages">Page Source</a>
|
||||
<a href="https://code.natconf.dev/denizk0461/pages">Page Source</a>
|
||||
<a href="/meta/privacy">Privacy & Cookies</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -97,12 +97,19 @@
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "LIGHTYEARS";
|
||||
src: url("/fonts/lightyears.woff2");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* OpenMoji */
|
||||
@font-face {
|
||||
font-family: "OpenMoji";
|
||||
src: url("/fonts/openmoji/openmoji.woff2") format("woff2");
|
||||
unicode-range: U+23,U+2A,U+2D,U+30-39,U+A9,U+AE,U+200D,U+203C,U+2049,U+20E3,U+2117,U+2120,U+2122,U+2139,U+2194-2199,U+21A9,U+21AA,U+229C,U+231A,U+231B,U+2328,U+23CF,U+23E9-23F3,U+23F8-23FE,U+24C2,U+25A1,U+25AA-25AE,U+25B6,U+25C0,U+25C9,U+25D0,U+25D1,U+25E7-25EA,U+25ED,U+25EE,U+25FB-25FE,U+2600-2605,U+260E,U+2611,U+2614,U+2615,U+2618,U+261D,U+2620,U+2622,U+2623,U+2626,U+262A,U+262E,U+262F,U+2638-263A,U+2640,U+2642,U+2648-2653,U+265F,U+2660,U+2663,U+2665,U+2666,U+2668,U+267B,U+267E,U+267F,U+2691-2697,U+2699,U+269B,U+269C,U+26A0,U+26A1,U+26A7,U+26AA,U+26AB,U+26B0,U+26B1,U+26BD,U+26BE,U+26C4,U+26C5,U+26C8,U+26CE,U+26CF,U+26D1,U+26D3,U+26D4,U+26E9,U+26EA,U+26F0-26F5,U+26F7-26FA,U+26FD,U+2702,U+2705,U+2708-270D,U+270F,U+2712,U+2714,U+2716,U+271D,U+2721,U+2728,U+2733,U+2734,U+2744,U+2747,U+274C,U+274E,U+2753-2755,U+2757,U+2763,U+2764,U+2795-2797,U+27A1,U+27B0,U+27BF,U+2934,U+2935,U+2B05-2B07,U+2B0C,U+2B0D,U+2B1B,U+2B1C,U+2B1F-2B24,U+2B2E,U+2B2F,U+2B50,U+2B55,U+2B58,U+2B8F,U+2BBA-2BBC,U+2BC3,U+2BC4,U+2BEA,U+2BEB,U+3030,U+303D,U+3297,U+3299,U+E000-E009,U+E010,U+E011,U+E040-E06D,U+E080-E0B4,U+E0C0-E0CC,U+E0FF-E10D,U+E140-E14A,U+E150-E157,U+E181-E189,U+E1C0-E1C4,U+E1C6-E1D9,U+E200-E216,U+E240-E269,U+E280-E283,U+E2C0-E2C4,U+E2C6-E2DA,U+E300-E303,U+E305-E30F,U+E312-E316,U+E318-E322,U+E324-E329,U+E32B,U+E340-E348,U+E380,U+E381,U+F000,U+F77A,U+F8FF,U+FE0F,U+1F004,U+1F0CF,U+1F10D-1F10F,U+1F12F,U+1F16D-1F171,U+1F17E,U+1F17F,U+1F18E,U+1F191-1F19A,U+1F1E6-1F1FF,U+1F201,U+1F202,U+1F21A,U+1F22F,U+1F232-1F23A,U+1F250,U+1F251,U+1F260-1F265,U+1F300-1F321,U+1F324-1F393,U+1F396,U+1F397,U+1F399-1F39B,U+1F39E-1F3F0,U+1F3F3-1F3F5,U+1F3F7-1F4FD,U+1F4FF-1F53D,U+1F549-1F54E,U+1F550-1F567,U+1F56F,U+1F570,U+1F573-1F57A,U+1F587,U+1F58A-1F58D,U+1F590,U+1F595,U+1F596,U+1F5A4,U+1F5A5,U+1F5A8,U+1F5B1,U+1F5B2,U+1F5BC,U+1F5C2-1F5C4,U+1F5D1-1F5D3,U+1F5DC-1F5DE,U+1F5E1,U+1F5E3,U+1F5E8,U+1F5EF,U+1F5F3,U+1F5FA-1F64F,U+1F680-1F6C5,U+1F6CB-1F6D2,U+1F6D5-1F6D7,U+1F6DC-1F6E5,U+1F6E9,U+1F6EB,U+1F6EC,U+1F6F0,U+1F6F3-1F6FC,U+1F7E0-1F7EB,U+1F7F0,U+1F90C-1F93A,U+1F93C-1F945,U+1F947-1F9FF,U+1FA70-1FA7C,U+1FA80-1FA89,U+1FA8F-1FAC6,U+1FACE-1FADC,U+1FADF-1FAE9,U+1FAF0-1FAF8,U+1FBC5-1FBC9,U+E0061-E0067,U+E0069,U+E006C-E0079,U+E007F;
|
||||
}
|
||||
font-family: "OpenMoji";
|
||||
src: url("/fonts/openmoji/openmoji.woff2") format("woff2");
|
||||
unicode-range: U+23,U+2A,U+2D,U+30-39,U+A9,U+AE,U+200D,U+203C,U+2049,U+20E3,U+2117,U+2120,U+2122,U+2139,U+2194-2199,U+21A9,U+21AA,U+229C,U+231A,U+231B,U+2328,U+23CF,U+23E9-23F3,U+23F8-23FE,U+24C2,U+25A1,U+25AA-25AE,U+25B6,U+25C0,U+25C9,U+25D0,U+25D1,U+25E7-25EA,U+25ED,U+25EE,U+25FB-25FE,U+2600-2605,U+260E,U+2611,U+2614,U+2615,U+2618,U+261D,U+2620,U+2622,U+2623,U+2626,U+262A,U+262E,U+262F,U+2638-263A,U+2640,U+2642,U+2648-2653,U+265F,U+2660,U+2663,U+2665,U+2666,U+2668,U+267B,U+267E,U+267F,U+2691-2697,U+2699,U+269B,U+269C,U+26A0,U+26A1,U+26A7,U+26AA,U+26AB,U+26B0,U+26B1,U+26BD,U+26BE,U+26C4,U+26C5,U+26C8,U+26CE,U+26CF,U+26D1,U+26D3,U+26D4,U+26E9,U+26EA,U+26F0-26F5,U+26F7-26FA,U+26FD,U+2702,U+2705,U+2708-270D,U+270F,U+2712,U+2714,U+2716,U+271D,U+2721,U+2728,U+2733,U+2734,U+2744,U+2747,U+274C,U+274E,U+2753-2755,U+2757,U+2763,U+2764,U+2795-2797,U+27A1,U+27B0,U+27BF,U+2934,U+2935,U+2B05-2B07,U+2B0C,U+2B0D,U+2B1B,U+2B1C,U+2B1F-2B24,U+2B2E,U+2B2F,U+2B50,U+2B55,U+2B58,U+2B8F,U+2BBA-2BBC,U+2BC3,U+2BC4,U+2BEA,U+2BEB,U+3030,U+303D,U+3297,U+3299,U+E000-E009,U+E010,U+E011,U+E040-E06D,U+E080-E0B4,U+E0C0-E0CC,U+E0FF-E10D,U+E140-E14A,U+E150-E157,U+E181-E189,U+E1C0-E1C4,U+E1C6-E1D9,U+E200-E216,U+E240-E269,U+E280-E283,U+E2C0-E2C4,U+E2C6-E2DA,U+E300-E303,U+E305-E30F,U+E312-E316,U+E318-E322,U+E324-E329,U+E32B,U+E340-E348,U+E380,U+E381,U+F000,U+F77A,U+F8FF,U+FE0F,U+1F004,U+1F0CF,U+1F10D-1F10F,U+1F12F,U+1F16D-1F171,U+1F17E,U+1F17F,U+1F18E,U+1F191-1F19A,U+1F1E6-1F1FF,U+1F201,U+1F202,U+1F21A,U+1F22F,U+1F232-1F23A,U+1F250,U+1F251,U+1F260-1F265,U+1F300-1F321,U+1F324-1F393,U+1F396,U+1F397,U+1F399-1F39B,U+1F39E-1F3F0,U+1F3F3-1F3F5,U+1F3F7-1F4FD,U+1F4FF-1F53D,U+1F549-1F54E,U+1F550-1F567,U+1F56F,U+1F570,U+1F573-1F57A,U+1F587,U+1F58A-1F58D,U+1F590,U+1F595,U+1F596,U+1F5A4,U+1F5A5,U+1F5A8,U+1F5B1,U+1F5B2,U+1F5BC,U+1F5C2-1F5C4,U+1F5D1-1F5D3,U+1F5DC-1F5DE,U+1F5E1,U+1F5E3,U+1F5E8,U+1F5EF,U+1F5F3,U+1F5FA-1F64F,U+1F680-1F6C5,U+1F6CB-1F6D2,U+1F6D5-1F6D7,U+1F6DC-1F6E5,U+1F6E9,U+1F6EB,U+1F6EC,U+1F6F0,U+1F6F3-1F6FC,U+1F7E0-1F7EB,U+1F7F0,U+1F90C-1F93A,U+1F93C-1F945,U+1F947-1F9FF,U+1FA70-1FA7C,U+1FA80-1FA89,U+1FA8F-1FAC6,U+1FACE-1FADC,U+1FADF-1FAE9,U+1FAF0-1FAF8,U+1FBC5-1FBC9,U+E0061-E0067,U+E0069,U+E006C-E0079,U+E007F;
|
||||
}
|
||||
|
||||
/* #endregion */
|
||||
|
||||
@@ -121,6 +128,7 @@
|
||||
|
||||
--color-background: #111111;
|
||||
--color-background-highlight: color-mix(in srgb, var(--color-highlight) 20%, transparent);
|
||||
--color-background-highlight-alt: color-mix(in srgb, var(--color-highlight-alt) 20%, transparent);
|
||||
--color-background-highlight-hover: color-mix(in srgb, var(--color-highlight) 60%, transparent);
|
||||
--color-background-highlight-hover-dark: color-mix(in srgb, var(--color-highlight-dark) 60%, transparent);
|
||||
|
||||
@@ -154,6 +162,8 @@
|
||||
--font-mono: 'Kode Mono', 'OpenMoji', monospace;
|
||||
--font-size-mono: 0.9em;
|
||||
|
||||
--font-lightyears: 'LIGHTYEARS', sans-serif;
|
||||
|
||||
--font-size-h1: 2.0rem;
|
||||
--font-size-h2: 1.5rem;
|
||||
--font-size-h3: 1.3rem;
|
||||
@@ -164,6 +174,7 @@
|
||||
|
||||
/* sizing */
|
||||
--media-width: 80%;
|
||||
--width-toc: 650px;
|
||||
|
||||
/* page sizing */
|
||||
--page-width: 1200px;
|
||||
@@ -331,6 +342,10 @@
|
||||
border: var(--border-dash-size) var(--border-style) var(--color-highlight); */
|
||||
}
|
||||
|
||||
.lightyears-text {
|
||||
font-family: var(--font-lightyears);
|
||||
}
|
||||
|
||||
.horizontally-centre-aligned {
|
||||
width: var(--media-width);
|
||||
display: flex;
|
||||
@@ -460,5 +475,15 @@
|
||||
font-family: var(--font-sans-serif);
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.callout-warning {
|
||||
margin: 12px auto;
|
||||
max-width: var(--width-toc);
|
||||
padding: 12px 20px;
|
||||
box-sizing: border-box;
|
||||
backdrop-filter: blur(var(--blur-radius-background));
|
||||
background-color: var(--color-background-highlight-alt);
|
||||
border: var(--border-dash-size) var(--border-style) var(--color-highlight-alt);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,6 +1,5 @@
|
||||
<script lang="ts">
|
||||
import Content from "$lib/viewport/content.svelte";
|
||||
import SubtitledImage from "$lib/components/subtitled-image.svelte";
|
||||
import GalleryRow, { type GalleryRowEntry } from "$lib/lists/gallery-row.svelte";
|
||||
|
||||
import { posts as devlogPosts } from "./projects/projectn5/devlog/posts";
|
||||
@@ -52,14 +51,14 @@
|
||||
description: "Find things I've put for download on my Copyparty instance",
|
||||
img: "main/hypertext.webp",
|
||||
altText: "Screenshot of Hypertext Unity level. Crates are strewn across the floor, Waluigi is flying in front of the camera, and text such as 'COME AND TRY OUR ALL-NEW BLENDER' and 'omg! it's the brandenburg er tor!' is displayed.",
|
||||
link: "https://files.denizk0461.dev/public/",
|
||||
link: "https://files.natconf.dev/public/",
|
||||
},
|
||||
{
|
||||
title: "Gitea",
|
||||
description: "I now also self-host a Gitea instance where I am likely migrating all my projects to",
|
||||
img: "main/magic.webp",
|
||||
altText: "A 'magic' command written in Java. The command shuts down the computer when ran.",
|
||||
link: "https://code.denizk0461.dev/",
|
||||
link: "https://code.natconf.dev/",
|
||||
},
|
||||
];
|
||||
</script>
|
||||
@@ -71,10 +70,12 @@
|
||||
|
||||
<Content>
|
||||
<h1 class="gradient-title"><i>Moin!</i> ~ welcome to my website :)</h1>
|
||||
<a href="/blog/2026/0325" class="page-subtitle gradient-title lightyears-text">you can change the world from your bedroom!</a>
|
||||
|
||||
<hr>
|
||||
|
||||
<div>
|
||||
|
||||
<img class="me-img pixelated-img" src="me.webp" alt="Pixelated mirror selfie of the website creator wearing a green shirt, fitting the website theme. The face is obscured." title="hi!">
|
||||
|
||||
<p>Hi! I'm Deniz. Welcome to my website! I keep rewriting this introduction but I'm REALLY bad at this type of stuff.</p>
|
||||
@@ -129,12 +130,13 @@
|
||||
</div>
|
||||
|
||||
<div class="button-container">
|
||||
<h4 class="update-header">88x31 buttons</h4>
|
||||
<h4 class="update-header">button corner</h4>
|
||||
<div class="button-subcontainer">
|
||||
{#each buttons as button}
|
||||
<IndieButton button={button} />
|
||||
{/each}
|
||||
</div>
|
||||
<p>to be expanded!</p>
|
||||
<p class="small-supertext">my own 88x31 button is in the making. ETA: ???</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -243,6 +245,12 @@
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
padding-bottom: 12px;
|
||||
}
|
||||
|
||||
.page-subtitle {
|
||||
/* padding-bottom: 12px; */
|
||||
width: fit-content;
|
||||
margin: 4px 0 12px 0;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
@@ -1,3 +1,9 @@
|
||||
<div class="callout-warning">
|
||||
<p><b>Note</b>: as I'm constantly learning new things, this blog post is sort of outdated now. The information is still correct, but it feels inefficient and leads into a dead-end. I dislike this, as I wanted to write a guide that provides an expandable base. Therefore, I'll likely either update or replace this article and trim it down to focus on the important bits.</p>
|
||||
|
||||
<p>Expect a Go API.</p>
|
||||
</div>
|
||||
|
||||
*Hey!*
|
||||
|
||||
Do you want to develop a web application in SvelteKit? Do you want this application to access a PostgreSQL database on a remote server? Do you struggle with CORS (cross-origin resource sharing) and CSRF (cross-site request forgery) and keep receiving error 403? Well, I did, and I couldn't find ***ANYTHING*** on the internet going beyond a test running locally. This is why I'm writing this guide.
|
||||
@@ -40,7 +46,7 @@ services:
|
||||
PGRST_DB_URI: 'postgres://authenticator:password@database:5432/postgres'
|
||||
PGRST_DB_SCHEMAS: 'api'
|
||||
PGRST_DB_ANON_ROLE: 'web_anon'
|
||||
PGRST_SERVER_CORS_ALLOWED_ORIGINS: "https://app.denizk0461.dev"
|
||||
PGRST_SERVER_CORS_ALLOWED_ORIGINS: "https://app.natconf.dev"
|
||||
depends_on:
|
||||
- database
|
||||
database:
|
||||
@@ -72,7 +78,7 @@ Keep in mind that you will not need to open up any of these ports on your firewa
|
||||
|
||||
#### Nginx
|
||||
|
||||
I'm using Nginx as a reverse proxy here. What does this mean? It means that we can send a human-readable URL to Nginx, such as this: `https://files.denizk0461.dev`, and Nginx will *internally* route us to the place the service is actually running on: `http://localhost:3923`. This has several advantages: as the end user, we won't need to remember the IP address or the port of the services we connect to. As the server administrator, we will only need to expose a minimal number of ports. In this example, port 3923 is actually closed off from the public, meaning that bypassing Nginx and connecting to the service directly, e.g. by typing `https://denizk0461.dev:3923`, is impossible. The only open port is 443, which is a standard port for websites served over encrypted HTTPS. Your browser will always try to connect to a website starting with `https://` on port 443, unless you specify another port. Port 80 is actually also open on my server, as it accepts requests through the unsafe `http://`, but it only redirects to `https://` on 443.
|
||||
I'm using Nginx as a reverse proxy here. What does this mean? It means that we can send a human-readable URL to Nginx, such as this: `https://files.natconf.dev`, and Nginx will *internally* route us to the place the service is actually running on: `http://localhost:3923`. This has several advantages: as the end user, we won't need to remember the IP address or the port of the services we connect to. As the server administrator, we will only need to expose a minimal number of ports. In this example, port 3923 is actually closed off from the public, meaning that bypassing Nginx and connecting to the service directly, e.g. by typing `https://natconf.dev:3923`, is impossible. The only open port is 443, which is a standard port for websites served over encrypted HTTPS. Your browser will always try to connect to a website starting with `https://` on port 443, unless you specify another port. Port 80 is actually also open on my server, as it accepts requests through the unsafe `http://`, but it only redirects to `https://` on 443.
|
||||
|
||||
I configured Nginx to run both the SvelteKit app as well as the PostgREST backend from the same subdomain. You don't *need* to do this, and I *think* it should even work if you put, for example, the database on a different subdomain, but I can't guarantee it.
|
||||
|
||||
@@ -80,7 +86,7 @@ I configured Nginx to run both the SvelteKit app as well as the PostgREST backen
|
||||
<pre class="code-block">
|
||||
server {
|
||||
listen 443;
|
||||
server_name app.denizk0461.dev;
|
||||
server_name app.natconf.dev;
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:3000;
|
||||
@@ -94,12 +100,12 @@ server {
|
||||
|
||||
This `server` block serves two functions:
|
||||
|
||||
- it serves our SvelteKit app, which by default runs on port 3000, from the root directory of the subdomain (e.g. `https://app.denizk0461.dev`), and
|
||||
- it serves the table `customers` from our PostgreSQL database, which is accessible through PostgREST on port 3100, on the subpage `/customers` (`https://app.denizk0461.dev/customers`).
|
||||
- it serves our SvelteKit app, which by default runs on port 3000, from the root directory of the subdomain (e.g. `https://app.natconf.dev`), and
|
||||
- it serves the table `customers` from our PostgreSQL database, which is accessible through PostgREST on port 3100, on the subpage `/customers` (`https://app.natconf.dev/customers`).
|
||||
- If your table has a different name, replace `customers` with that table's name.
|
||||
- If you want multiple tables to be accessible, copy the entire `location /[tablename]` block and paste it in as often as you need, replacing `[tablename]` with the names of the tables.
|
||||
|
||||
Be sure to change `denizk0461.dev` to your own domain, as this will otherwise not work.
|
||||
Be sure to change `natconf.dev` to your own domain, as this will otherwise not work.
|
||||
|
||||
### Configure the Database
|
||||
|
||||
@@ -107,7 +113,7 @@ Once you have the database running, we need to create a table to store data in.
|
||||
|
||||
You're best off following [the official guide for PostgREST](https://docs.postgrest.org/en/v14/tutorials/tut0.html#step-3-create-database-for-api). Important steps: create the schema, name it `api` (that's the publicly-accessible schema because we set `PGRST_DB_SCHEMAS: 'api'` in the `compose.yml`), create a table (name has to start with `api.` but can be anything after that, e.g. `api.customers`), insert test data, create the roles `web_anon` and `authenticator` and then quit by typing `\q`. That's all. Welcome back!
|
||||
|
||||
You can now access the database data on `https://app.denizk0461.dev` (if you replace my domain with yours). Keep in mind that the PostgREST guide only grants read access (GET) to the database; in order to POST data to the database, you need to grant `INSERT` privileges to `web_anon`: `grant insert on api.customers to web_anon;`.
|
||||
You can now access the database data on `https://app.natconf.dev` (if you replace my domain with yours). Keep in mind that the PostgREST guide only grants read access (GET) to the database; in order to POST data to the database, you need to grant `INSERT` privileges to `web_anon`: `grant insert on api.customers to web_anon;`.
|
||||
|
||||
If you want a kind voice to guide you through this process, I found [Ian Wootten's video on setting up PostgREST](https://youtu.be/RxuofiZNhtU) to be very nice to follow along.
|
||||
|
||||
@@ -131,10 +137,10 @@ if (response.ok) {
|
||||
}
|
||||
</pre>
|
||||
|
||||
In this example, I set up two environment variables: `API_HOST` and `API_DB`. Those are secrets that won't be published to your Git provider when you push your changes (if your .gitignore is set up correctly!). `API_HOST` is the fully-qualified domain, e.g. `https://app.denizk0461.dev`, and `API_DB` is the name of the table, e.g. `customers`. Doing this is not necessary, but it's good practice to keep secrets, especially once you get to the stage of needing passwords or authentication keys. If you want to use environment variables, create a file named `.env` in the root directory of your application, add the variables as such:
|
||||
In this example, I set up two environment variables: `API_HOST` and `API_DB`. Those are secrets that won't be published to your Git provider when you push your changes (if your .gitignore is set up correctly!). `API_HOST` is the fully-qualified domain, e.g. `https://app.natconf.dev`, and `API_DB` is the name of the table, e.g. `customers`. Doing this is not necessary, but it's good practice to keep secrets, especially once you get to the stage of needing passwords or authentication keys. If you want to use environment variables, create a file named `.env` in the root directory of your application, add the variables as such:
|
||||
|
||||
<pre class="code-block">
|
||||
API_HOST="https://app.denizk0461.dev"
|
||||
API_HOST="https://app.natconf.dev"
|
||||
API_DB="customers"
|
||||
</pre>
|
||||
|
||||
@@ -162,7 +168,7 @@ kit: {
|
||||
adapter: adapter(),
|
||||
csrf: {
|
||||
trustedOrigins: [
|
||||
"https://app.denizk0461.dev"
|
||||
"https://app.natconf.dev"
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -200,7 +206,7 @@ I'm going to prove why you should avoid generative AI at all costs. Let's go thr
|
||||
|
||||
1. Use Relative Form Actions
|
||||
|
||||
This 'fix' describes using relative paths to access form URLs. Instead of `https://app.denizk0461.dev/customers`, I should just use `/customers`.
|
||||
This 'fix' describes using relative paths to access form URLs. Instead of `https://app.natconf.dev/customers`, I should just use `/customers`.
|
||||
|
||||
This doesn't work.
|
||||
|
||||
|
||||
32
src/routes/blog/2026/0325.md
Normal file
32
src/routes/blog/2026/0325.md
Normal file
@@ -0,0 +1,32 @@
|
||||
<p class="lightyears-text">The world looks so different now. The world looks so different now. The world looks so different now.</p>
|
||||
|
||||
## Background
|
||||
|
||||
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>
|
||||
|
||||
The font exclusively uses characters from the Noto font family. Many of the Noto varieties have been stitched together to recreate the whole LIGHTYEARS alphabet.
|
||||
|
||||
To create the font, I used [FontForge](https://fontforge.org). Finding this tool was both a blessing and a curse, as it was exactly what I needed, but it kept. crashing. all. the. time. I tried both the AppImage as well as the release on `dnf` and both had the same issues. I managed to make it work, but it took a lot of patience. Eventually I figured out that importing Noto Maths gave me a 3-8 second window before the editor crashed. The project file would forget the imported font, but if I had copied any glyphs it would keep those.
|
||||
|
||||
## Download & use
|
||||
|
||||
[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.
|
||||
|
||||
For use on your website, put the font into your resources/static/similar folder and then add this block of code to your CSS file:
|
||||
|
||||
<pre class="code-block">
|
||||
@font-face {
|
||||
font-family: "LIGHTYEARS";
|
||||
src: url("/fonts/lightyears.woff2");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
</pre>
|
||||
|
||||
Then you can change any element's font by setting `font-family: 'LIGHTYEARS', sans-serif;`. Because it's the Latin characters and Arabic numbers that have been changed, you can type text in regular English and people can 'decrypt' the messages by copy-pasting the text somewhere else!
|
||||
|
||||
You do **not** need Jaron's converter to type stylised text! The converter returns the actual symbols from other scripts, whereas this font only changes how letters look.
|
||||
7
src/routes/blog/2026/0326.md
Normal file
7
src/routes/blog/2026/0326.md
Normal file
@@ -0,0 +1,7 @@
|
||||
I'm switching my website domain from `denizk0461.dev` to `natconf.dev`!
|
||||
|
||||
All I can say for now about this change is that I came up with this domain name a while back and I liked it – more so than `denizk0461.dev` –, so I've been thinking about migrating.
|
||||
|
||||
I'm updating things as I go. All links on this website now point to the new domain, and all services have been moved over too. As of right now, they're also still accessible via the old domain, but I will be disabling that soon. Instead, I'll set up redirects, which will be in place until the domain expires on 2026-06-04.
|
||||
|
||||
I *may* change up some visual elements in the process, but it won't be a major redesign.
|
||||
@@ -4,7 +4,7 @@ import { posts } from "../posts";
|
||||
const xml = () => `<rss version="2.0">
|
||||
<channel>
|
||||
<title>denizk0461's Blog</title>
|
||||
<link>https://denizk0461.dev/blog/</link>
|
||||
<link>https://natconf.dev/blog/</link>
|
||||
<description><![CDATA[denizk0461 blogs about stuff here]]></description>${getEntries()}
|
||||
</channel>
|
||||
</rss>`;
|
||||
@@ -16,8 +16,8 @@ function getEntries(): String {
|
||||
<item>
|
||||
<title><![CDATA[${entry.post.title}]]></title>
|
||||
<description><![CDATA[${entry.post.description}]]></description>
|
||||
<link>https://denizk0461.dev/blog/${entry.key}</link>
|
||||
<guid isPermaLink="true">https://denizk0461.dev/blog/${entry.key}</guid>
|
||||
<link>https://natconf.dev/blog/${entry.key}</link>
|
||||
<guid isPermaLink="true">https://natconf.dev/blog/${entry.key}</guid>
|
||||
<pubDate><![CDATA[${new Date(`${entry.post.date}T${entry.post.time}`).toUTCString()}]]></pubDate>
|
||||
</item>`)
|
||||
entries.forEach(entry => {
|
||||
|
||||
@@ -23,6 +23,28 @@ export interface BlogPostLink {
|
||||
|
||||
|
||||
export const posts: BlogPostLink[] = [
|
||||
{
|
||||
key: "2026/0326",
|
||||
post: {
|
||||
date: "2026-03-26",
|
||||
time: "20:50",
|
||||
banner: "banner.webp",
|
||||
bannerAlt: "White light blurs on a darker background.",
|
||||
title: "Moving On",
|
||||
description: "It's time to switch domains.",
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "2026/0325",
|
||||
post: {
|
||||
date: "2026-03-25",
|
||||
time: "22:22",
|
||||
banner: "banner.webp",
|
||||
bannerAlt: "A sunset captured from an Autobahn exit.",
|
||||
title: "I made a LIGHTYEARS font",
|
||||
description: "I feel electric and it's only getting brighter!",
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "2026/0317",
|
||||
post: {
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
},
|
||||
{
|
||||
text: "Bluesky",
|
||||
link: "https://bsky.app/profile/denizk0461.dev",
|
||||
link: "https://bsky.app/profile/natconf.dev",
|
||||
},
|
||||
{
|
||||
text: "Codeberg",
|
||||
@@ -151,7 +151,7 @@
|
||||
|
||||
<img alt="Screenshot of the taskbar of a Fedora KDE setup. There are multiple icons. From left to right: Clank as the application launcher icon, Firefox, fooyin music player, Dolphin file explorer." src="taskbar.webp">
|
||||
|
||||
<p>As for the server infrastructure: the website is hosted on a Hetzner server instance I am renting. It's a relatively cheap CPX22 node that costs me 7,72€ a month, and besides my website, it's also hosting things such as a Nextcloud instance and a Minecraft server. In order to host and update the website, I wrote a small bash script that pulls the changes from the <a href="https://code.denizk0461.dev/denizk0461/pages">Git repository</a>, builds the website as a Node server, and then exposes it via Nginx.</p>
|
||||
<p>As for the server infrastructure: the website is hosted on a Hetzner server instance I am renting. It's a relatively cheap CPX22 node that costs me 7,72€ a month, and besides my website, it's also hosting things such as a Nextcloud instance and a Minecraft server. In order to host and update the website, I wrote a small bash script that pulls the changes from the <a href="https://code.natconf.dev/denizk0461/pages">Git repository</a>, builds the website as a Node server, and then exposes it via Nginx.</p>
|
||||
|
||||
<h4 id="software">Tools & Software</h4>
|
||||
|
||||
@@ -169,7 +169,7 @@
|
||||
|
||||
<p>The <a href="https://ratchetandclank.fandom.com/wiki/Ratchet">rat</a> in the bottom right of the screen is property of <a href="https://insomniac.games/">Insomniac Games</a>. Clicking it will bring you good fortune.</p>
|
||||
|
||||
<p>The style of the webring elements is adapted from a template provided by Rainbow Cemetery for the <a href="https://www.rainbowcemetery.com/devring/">Gamedev webring</a>. I adapted it into <a href="https://code.denizk0461.dev/denizk0461/pages/src/branch/master/src/lib/components/ring.svelte">a Svelte component</a> that allows setting the links, emojis, and arrows more easily.</p>
|
||||
<p>The style of the webring elements is adapted from a template provided by Rainbow Cemetery for the <a href="https://www.rainbowcemetery.com/devring/">Gamedev webring</a>. I adapted it into <a href="https://code.natconf.dev/denizk0461/pages/src/branch/master/src/lib/components/ring.svelte">a Svelte component</a> that allows setting the links, emojis, and arrows more easily.</p>
|
||||
|
||||
<h2 id="contact">Contact / Where to find me</h2>
|
||||
|
||||
@@ -177,7 +177,7 @@
|
||||
|
||||
<LinkList entries={links} />
|
||||
|
||||
<p>I removed my Discord username because I don't want to use Discord anymore, now that they <a href="https://www.zdnet.com/article/discord-age-verification-requirement/">ask for facial data and/or government ID that they force to be scanned by third-party AI</a> and then <a href="https://arstechnica.com/tech-policy/2026/02/discord-faces-backlash-over-age-checks-after-data-breach-exposed-70000-ids/">leak it...</a> Apparently they are also about to be <a href="https://www.zdnet.com/article/microsoft-may-be-poised-to-buy-its-next-community-discord/">bought up by Micro$lop</a>?? Discord is as good as dead to me.</p>
|
||||
<p>I removed my Discord username because I don't want to use Discord anymore, now that they <a href="https://www.zdnet.com/article/discord-age-verification-requirement/">ask for facial data and/or government ID that they force to be scanned by third-party AI</a> and then <a href="https://arstechnica.com/tech-policy/2026/02/discord-faces-backlash-over-age-checks-after-data-breach-exposed-70000-ids/">leak it...</a> Apparently they are also about to be <a href="https://www.zdnet.com/article/microsoft-may-be-poised-to-buy-its-next-community-discord/">bought up by Micro$lop</a>?? I prefer not to use Discord anymore, although I will admit I don't have any good alternative at the moment.</p>
|
||||
|
||||
<h2>Anything else?</h2>
|
||||
|
||||
@@ -201,7 +201,7 @@
|
||||
|
||||
<hr>
|
||||
|
||||
<p><i>Last updated: 2026-02-25</i></p>
|
||||
<p><i>Last updated: 2026-03-26</i></p>
|
||||
</Content>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
<p>This page uses <b>no cookies</b> as of now. No data will be stored on your device while browsing this website. <b>No trackers</b> are used either – <b>no analytics</b>, not even a visit counter of any kind. Not by a third-party, and currently, none I built myself either.</p>
|
||||
|
||||
<p>The Godot and Unity projects on the <code>apps.denizk0461.dev</code> subdomain <i>may</i> cache compiled shaders on your device, I'm not sure. These files would only be used by your GPU to render visual effects for the game they were compiled for.</p>
|
||||
<p>The Godot and Unity projects on the <code>apps.natconf.dev</code> subdomain <i>may</i> cache compiled shaders on your device, I'm not sure. These files would only be used by your GPU to render visual effects for the game they were compiled for.</p>
|
||||
|
||||
<p>Last updated: 2025-09-10</p>
|
||||
</Content>
|
||||
|
||||
@@ -1,6 +1,18 @@
|
||||
import { type UpdateEntry } from "$lib/components/update-entry.svelte";
|
||||
|
||||
export const entries: UpdateEntry[] = [
|
||||
{
|
||||
date: "2026-03-26",
|
||||
time: "20:50",
|
||||
content: "<b>Important</b>: my website is changing domains.",
|
||||
link: "/blog/2026/0326",
|
||||
},
|
||||
{
|
||||
date: "2026-03-25",
|
||||
time: "22:22",
|
||||
content: "I made a LIGHTYEARS font!",
|
||||
link: "/blog/2026/0325",
|
||||
},
|
||||
{
|
||||
date: "2026-03-17",
|
||||
time: "17:10",
|
||||
@@ -63,7 +75,7 @@ export const entries: UpdateEntry[] = [
|
||||
date: "2026-02-03",
|
||||
time: "15:48",
|
||||
content: "Now running my own Gitea instance! It now also hosts my website repository.",
|
||||
link: "https://code.denizk0461.dev/denizk0461/pages",
|
||||
link: "https://code.natconf.dev/denizk0461/pages",
|
||||
},
|
||||
{
|
||||
date: "2026-02-02",
|
||||
|
||||
@@ -4,19 +4,19 @@
|
||||
let builds: LinkEntry[] = [
|
||||
{
|
||||
text: "2023-10-07 (Protagonist #1)",
|
||||
link: "https://files.denizk0461.dev/public/projectn5/2023-10-07.zip",
|
||||
link: "https://files.natconf.dev/public/projectn5/2023-10-07.zip",
|
||||
},
|
||||
{
|
||||
text: "2023-12-23 (Protagonist #2)",
|
||||
link: "https://files.denizk0461.dev/public/projectn5/2023-12-23.zip",
|
||||
link: "https://files.natconf.dev/public/projectn5/2023-12-23.zip",
|
||||
},
|
||||
{
|
||||
text: "2024-03-25 (Protagonist #3 with jump animations)",
|
||||
link: "https://files.denizk0461.dev/public/projectn5/2024-03-25.zip",
|
||||
link: "https://files.natconf.dev/public/projectn5/2024-03-25.zip",
|
||||
},
|
||||
{
|
||||
text: "2025-08-16 (Laura era) [same build as the web version]",
|
||||
link: "https://files.denizk0461.dev/public/projectn5/2025-08-16.zip",
|
||||
link: "https://files.natconf.dev/public/projectn5/2025-08-16.zip",
|
||||
},
|
||||
];
|
||||
</script>
|
||||
@@ -33,9 +33,9 @@ The good news is that I'm done with all of this! The bachelor's thesis in partic
|
||||
|
||||
I decided to upload some playable builds of **Project N5**! Now that the website is running on my own server instead of being hosted by GitHub or Codeberg, I have a lot more freedom here.
|
||||
|
||||
The game, in its state from 2025-05-16 (before the reboot), is available to play in-browser [right here!](https://apps.denizk0461.dev/projectn5) It's not a terribly great experience, though. Loading times are significantly longer and shader compilation regularly freezes the game for longer than in a locally-saved copy. Some shaders are also not functioning as intended, though this only has a minor visual impact. The game was never optimised to work on the web, after all.
|
||||
The game, in its state from 2025-05-16 (before the reboot), is available to play in-browser [right here!](https://apps.natconf.dev/projectn5) It's not a terribly great experience, though. Loading times are significantly longer and shader compilation regularly freezes the game for longer than in a locally-saved copy. Some shaders are also not functioning as intended, though this only has a minor visual impact. The game was never optimised to work on the web, after all.
|
||||
|
||||
I've also uploaded old builds of the game [here](https://files.denizk0461.dev/public/projectn5). You'll find the following builds, one for each protagonist:
|
||||
I've also uploaded old builds of the game [here](https://files.natconf.dev/public/projectn5). You'll find the following builds, one for each protagonist:
|
||||
|
||||
<LinkList entries={builds} />
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { posts } from "../posts";
|
||||
const xml = () => `<rss version="2.0">
|
||||
<channel>
|
||||
<title>Project N5 Devlog</title>
|
||||
<link>https://denizk0461.dev/projects/projectn5/devlog/</link>
|
||||
<link>https://natconf.dev/projects/projectn5/devlog/</link>
|
||||
<description><![CDATA[Development log for the game Project N5 by denizk0461]]></description>${getEntries()}
|
||||
</channel>
|
||||
</rss>`;
|
||||
@@ -16,8 +16,8 @@ function getEntries(): String {
|
||||
<item>
|
||||
<title><![CDATA[${entry.post.title}]]></title>
|
||||
<description><![CDATA[${entry.post.description}]]></description>
|
||||
<link>https://denizk0461.dev/projects/projectn5/devlog/${entry.key}</link>
|
||||
<guid isPermaLink="true">https://denizk0461.dev/projects/projectn5/devlog/${entry.key}</guid>
|
||||
<link>https://natconf.dev/projects/projectn5/devlog/${entry.key}</link>
|
||||
<guid isPermaLink="true">https://natconf.dev/projects/projectn5/devlog/${entry.key}</guid>
|
||||
<pubDate><![CDATA[${new Date(entry.post.date).toUTCString()}]]></pubDate>
|
||||
</item>`)
|
||||
entries.forEach(entry => {
|
||||
|
||||
@@ -78,11 +78,11 @@ export const games: Project[] = [
|
||||
},
|
||||
{
|
||||
text: "Play an <b>old web build</b> (developed until 2025-05-16)",
|
||||
link: "https://apps.denizk0461.dev/projectn5",
|
||||
link: "https://apps.natconf.dev/projectn5",
|
||||
},
|
||||
{
|
||||
text: "Download the <b>old Windows builds</b>",
|
||||
link: "https://files.denizk0461.dev/public/projectn5",
|
||||
link: "https://files.natconf.dev/public/projectn5",
|
||||
},
|
||||
],
|
||||
status: ProjectStatus.ACTIVE,
|
||||
@@ -102,7 +102,7 @@ export const games: Project[] = [
|
||||
links: [
|
||||
{
|
||||
text: "View the latest <b>Magician</b> build",
|
||||
link: "https://apps.denizk0461.dev/magician",
|
||||
link: "https://apps.natconf.dev/magician",
|
||||
},
|
||||
],
|
||||
status: ProjectStatus.ABANDONED,
|
||||
@@ -139,7 +139,7 @@ export const games: Project[] = [
|
||||
links: [
|
||||
{
|
||||
text: "Play <b>Swords & Stuff</b>",
|
||||
link: "https://apps.denizk0461.dev/swordsnstuff",
|
||||
link: "https://apps.natconf.dev/swordsnstuff",
|
||||
},
|
||||
],
|
||||
status: ProjectStatus.ABANDONED,
|
||||
@@ -159,11 +159,11 @@ export const games: Project[] = [
|
||||
links: [
|
||||
{
|
||||
text: "Play <b>TADS 1</b>",
|
||||
link: "https://apps.denizk0461.dev/tads/1",
|
||||
link: "https://apps.natconf.dev/tads/1",
|
||||
},
|
||||
{
|
||||
text: "Play <b>TADS 2</b>",
|
||||
link: "https://apps.denizk0461.dev/tads/2",
|
||||
link: "https://apps.natconf.dev/tads/2",
|
||||
},
|
||||
],
|
||||
status: ProjectStatus.FINISHED,
|
||||
@@ -189,7 +189,7 @@ export const hardware: Project[] = [
|
||||
},
|
||||
{
|
||||
text: "Get the <b>PCB and STL files</b>",
|
||||
link: "https://files.denizk0461.dev/public/daisyfm/",
|
||||
link: "https://files.natconf.dev/public/daisyfm/",
|
||||
},
|
||||
{
|
||||
text: "View the code files on <b>Codeberg</b>",
|
||||
@@ -317,7 +317,7 @@ export const music: Project[] = [
|
||||
links: [
|
||||
{
|
||||
text: "Listen & download on my <b>copyparty</b> instance",
|
||||
link: "https://files.denizk0461.dev/public/my_tracks/Dreamworld/",
|
||||
link: "https://files.natconf.dev/public/my_tracks/Dreamworld/",
|
||||
},
|
||||
],
|
||||
status: ProjectStatus.FINISHED,
|
||||
@@ -337,7 +337,7 @@ export const music: Project[] = [
|
||||
links: [
|
||||
{
|
||||
text: "Listen & download on my <b>copyparty</b> instance",
|
||||
link: "https://files.denizk0461.dev/public/my_tracks/A%20New%20Beginning/",
|
||||
link: "https://files.natconf.dev/public/my_tracks/A%20New%20Beginning/",
|
||||
},
|
||||
],
|
||||
status: ProjectStatus.FINISHED,
|
||||
|
||||
BIN
static/blog/2026/0325/banner.webp
Normal file
BIN
static/blog/2026/0325/banner.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 51 KiB |
BIN
static/blog/2026/0326/banner.webp
Normal file
BIN
static/blog/2026/0326/banner.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.7 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 532 B |
Binary file not shown.
|
Before Width: | Height: | Size: 550 B |
Binary file not shown.
|
Before Width: | Height: | Size: 2.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 487 B |
BIN
static/fonts/lightyears.woff2
Normal file
BIN
static/fonts/lightyears.woff2
Normal file
Binary file not shown.
Reference in New Issue
Block a user