Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
border-radius: var(--radius-md);
}

button:hover {
background-color: var(--color-gray-300);
}

/* svx post styling */
.post h1 {
@apply text-3xl;
Expand Down Expand Up @@ -83,6 +87,16 @@
@apply list-disc;
@apply pl-6;
}

.post ol {
@apply list-decimal;
@apply pl-7;
}

.post ol li::marker {
@apply font-semibold;
@apply text-black;
}
}

@layer components {
Expand Down
Binary file added src/lib/assets/making-of/inspiration.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/lib/assets/making-of/old.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 21 additions & 7 deletions src/lib/yap/_layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,27 @@ layout for posts, used by mdsvex
title,
date: _date,
posted: _posted,
minimized,
children,
}: { title: string; date: string; posted: string; children: Snippet } = $props();
let date = $derived(new Date(_date));
let posted = $derived(new Date(_posted));
let expanded = $state(true);
}: {
title: string;
date: string;
posted: string;
minimized?: boolean;
children: Snippet;
} = $props();

// commented out for now since I want to display og timezone, and I realized there's no sorting the list atm
// let date = $derived(new Date(_date));
// let posted = $derived(new Date(_posted));

// svelte-ignore state_referenced_locally
let expanded = $state(minimized ? false : true);
</script>

<!-- TODO: retain og timezone while using Date object -->
<!-- TODO: add id and share capabilities -->

<div class="w-full flex flex-col gap-4">
<div class="flex flex-col flex-wrap max-w-full items-end">
<div class="relative flex gap-2 items-center">
Expand All @@ -25,7 +39,7 @@ layout for posts, used by mdsvex
onclick={() => {
expanded = !expanded;
}}
class="aspect-square h-5 sm:absolute text-md sm:-right-7 sm:top-1"
class="aspect-square h-5 sm:absolute sm:-right-7 sm:top-1"
>
<div class="-mt-0.5 text-sm font-bold">
{#if expanded}
Expand All @@ -36,8 +50,8 @@ layout for posts, used by mdsvex
</div>
</button>
</div>
<h3 class="text-sm font-light text-gray-500">dated {date.toISOString()}</h3>
<h3 class="text-sm font-light text-gray-500">posted {posted.toISOString()}</h3>
<h3 class="text-sm font-light text-gray-500">dated {_date}</h3>
<h3 class="text-sm font-light text-gray-500">posted {_posted}</h3>
</div>
{#if expanded}
<div class="post">
Expand Down
24 changes: 24 additions & 0 deletions src/lib/yap/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import Welcome, { metadata as welcomeMeta } from "$lib/yap/welcome.svx";
import MakingOfPt1, { metadata as makingOfMetaPt1 } from "$lib/yap/making-of-pt1.svx";
import MakingOfPt2, { metadata as makingOfMetaPt2 } from "$lib/yap/making-of-pt2.svx";
import MakingOfPt3, { metadata as makingOfMetaPt3 } from "$lib/yap/making-of-pt3.svx";
import type { Component } from "svelte";

export type Post = {
Expand All @@ -17,6 +20,27 @@ const posts: Post[] = [
posted: new Date(welcomeMeta.posted),
raw: welcomeMeta.raw,
},
{
component: MakingOfPt1,
title: makingOfMetaPt1.title,
date: new Date(makingOfMetaPt1.date),
posted: new Date(makingOfMetaPt1.posted),
raw: makingOfMetaPt1.raw,
},
{
component: MakingOfPt2,
title: makingOfMetaPt2.title,
date: new Date(makingOfMetaPt2.date),
posted: new Date(makingOfMetaPt2.posted),
raw: makingOfMetaPt2.raw,
},
{
component: MakingOfPt3,
title: makingOfMetaPt3.title,
date: new Date(makingOfMetaPt3.date),
posted: new Date(makingOfMetaPt3.posted),
raw: makingOfMetaPt3.raw,
},
];

export default posts;
38 changes: 38 additions & 0 deletions src/lib/yap/making-of-pt1.svx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
title: making of (pt. 1)
date: !!str 2026-06-01T23:16:13+10:00
posted: !!str 2026-06-01T23:16:13+10:00
minimized: true
raw: >
So, for some context, if you're an og you may remember my old webpage:

![old]($lib/assets/making-of/old.png)

I built this page at the end of 2023 -- at the time my CS club, PROJECT Emory, had engineers that needed support in web design and development -- I knew my way around backend development, so I decided to tackle a personal portfolio project to learn the basics of frontend development, both in design best practices and in tools such as Figma and React. If you're interested in my processes at the time, you can still find the old dev logs [here](https://github.com/andrewtlu/andrewtlu.github.io/tree/v1/dev_log).

However, after making the website (which did land me my first internship!), I didn't touch it after ending said internship, and it's remained the same since then. I've grown/changed a lot, and so has what I want to communicate to recruiters and other people visiting my site. I designed my old site to be much more "demo-y," but I've found many of the old features no longer necessary/aesthetically pleasing to myself. I also figured that since I've graduated from Emory, it's about time to spruce up the site.

So, while browsing around and looking at PROJECT Emory/Emory Hack's team members' profiles, I found our [lead engineer (Ethan)'s personal site](https://taehoonlee.dev/):

![inspiration]($lib/assets/making-of/inspiration.png)

I loved how minimalistic yet sophisticated his page was, and decided I wanted to do something like this. I've also always wanted to have a blog of sorts. So, I settled on building a simple, monochrome(ish) webpage using spacing, text size, color, and weight to provide visual hierarchy and group content.

...
---

So, for some context, if you're an og you may remember my old webpage:

![old]($lib/assets/making-of/old.png)

I built this page at the end of 2023 -- at the time my CS club, PROJECT Emory, had engineers that needed support in web design and development -- I knew my way around backend development, so I decided to tackle a personal portfolio project to learn the basics of frontend development, both in design best practices and in tools such as Figma and React. If you're interested in my processes at the time, you can still find the old dev logs [here](https://github.com/andrewtlu/andrewtlu.github.io/tree/v1/dev_log).

However, after making the website (which did land me my first internship!), I didn't touch it after ending said internship, and it's remained the same since then. I've grown/changed a lot, and so has what I want to communicate to recruiters and other people visiting my site. I designed my old site to be much more "demo-y," but I've found many of the old features no longer necessary/aesthetically pleasing to myself. I also figured that since I've graduated from Emory, it's about time to spruce up the site.

So, while browsing around and looking at PROJECT Emory/Emory Hack's team members' profiles, I found our [lead engineer (Ethan)'s personal site](https://taehoonlee.dev/):

![inspiration]($lib/assets/making-of/inspiration.png)

I loved how minimalistic yet sophisticated his page was, and decided I wanted to do something like this. I've also always wanted to have a blog of sorts. So, I settled on building a simple, monochrome(ish) webpage using spacing, text size, color, and weight to provide visual hierarchy and group content.

...
74 changes: 74 additions & 0 deletions src/lib/yap/making-of-pt2.svx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---
title: making of (pt. 2)
date: !!str 2026-06-02T15:18:29+10:00
posted: !!str 2026-06-02T15:18:29+10:00
minimized: true
raw: >
...

To get started, I decided to ditch React entirely. I've always been a huge fan of Svelte, and I figured the minimal, ordered philosophy behind Svelte gave me a developing experience similar to what I was going for on the user experience side. Additionally, while building the page itself I found some cool tools to help make developing this blog a bit easier.

My tech stack ended up being pretty slim:

- Svelte, TypeScript, Vite
- [SvelteKit](https://svelte.dev/docs/kit/adapter-static) for cleaner routing (paired with the static adapter for deployment via GitHub Pages)
- [tailwindcss](https://tailwindcss.com/docs/installation/using-vite) for a cleaner CSS experience
- [mdsvex](https://mdsvex.pngwn.io/) for preprocessing markdown (in order to write posts in markdown)
- You can also find all the code in [this website's GitHub repository](https://github.com/andrewtlu/andrewtlu.github.io)

I didn't use any component/style libraries or icon libraries because I found them unnecessary for what I was trying to do here.

### The landing page

I decided to tackle the landing page first, as I was just going to do the bulk of the designing while setting up my pages. So, I set up the base page route (and a dummy blog route) and its layout, adding some filler content in order to mess with fonts, sizing, and spacing, before settling on a version similar to what is used now. I added some base global variables to reduce duplication (such as `<a>` styling or `<button>` effects) and finished up content.

Before moving on to the blog, I added a simple workflow to check code style and automatically build and deploy when pushed to main. I'm keeping things brief in this portion since the details were just standard Svelte development & debugging.

Then, I began working on the blog.

### The blog

I initially began working on blog posts thinking I could keep blog posts as JSON files which would then be passed to a `<Post>` component which would render relevant metadata and content, and so I began developing expecting to go down this route.

I firstly added some dummy text and quickly discovered that my minimalistic styling from the landing page would need to be ironed out as there was not enough visual distinctiveness between posts, and I finally needed to include elements such as buttons. There wasn't much inspiration at this part of the process, and I instead just tried different shapes, spacings and layouts until I found something I vibed with. One thing I really liked from this whole process was using right-aligned text to denote a new post, which gave me some more freedom with styling of post content as I wouldn't need to rely solely on text weight or size to separate groups of text.

I then began writing my first post before quickly discovering some limitations. One notable one was that my current setup made it very difficult for me to add elements to posts such as titles, links, and images. I'd have to write my own processor, and it'd be easier to write HTML and inject it using Svelte's `{@html ...}` tag, neither of which were easy, and I really didn't want to write posts in HTML or Svelte if I could help it.

That's when I realized I could just use Markdown, or some suitable enough superset of Markdown, and translate it into HTML for the Svelte compiler to do its thing. After a quick google search I found some tools to do just that and settled with mdsvex.

...
---

...

To get started, I decided to ditch React entirely. I've always been a huge fan of Svelte, and I figured the minimal, ordered philosophy behind Svelte gave me a developing experience similar to what I was going for on the user experience side. Additionally, while building the page itself I found some cool tools to help make developing this blog a bit easier.

My tech stack ended up being pretty slim:

- Svelte, TypeScript, Vite
- [SvelteKit](https://svelte.dev/docs/kit/adapter-static) for cleaner routing (paired with the static adapter for deployment via GitHub Pages)
- [tailwindcss](https://tailwindcss.com/docs/installation/using-vite) for a cleaner CSS experience
- [mdsvex](https://mdsvex.pngwn.io/) for preprocessing markdown (in order to write posts in markdown)
- You can also find all the code in [this website's GitHub repository](https://github.com/andrewtlu/andrewtlu.github.io)

I didn't use any component/style libraries or icon libraries because I found them unnecessary for what I was trying to do here.

### The landing page

I decided to tackle the landing page first, as I was just going to do the bulk of the designing while setting up my pages. So, I set up the base page route (and a dummy blog route) and its layout, adding some filler content in order to mess with fonts, sizing, and spacing, before settling on a version similar to what is used now. I added some base global variables to reduce duplication (such as `<a>` styling or `<button>` effects) and finished up content.

Before moving on to the blog, I added a simple workflow to check code style and automatically build and deploy when pushed to main. I'm keeping things brief in this portion since the details were just standard Svelte development & debugging.

Then, I began working on the blog.

### The blog

I initially began working on blog posts thinking I could keep blog posts as JSON files which would then be passed to a `<Post>` component which would render relevant metadata and content, and so I began developing expecting to go down this route.

I firstly added some dummy text and quickly discovered that my minimalistic styling from the landing page would need to be ironed out as there was not enough visual distinctiveness between posts, and I finally needed to include elements such as buttons. There wasn't much inspiration at this part of the process, and I instead just tried different shapes, spacings and layouts until I found something I vibed with. One thing I really liked from this whole process was using right-aligned text to denote a new post, which gave me some more freedom with styling of post content as I wouldn't need to rely solely on text weight or size to separate groups of text.

I then began writing my first post before quickly discovering some limitations. One notable one was that my current setup made it very difficult for me to add elements to posts such as titles, links, and images. I'd have to write my own processor, and it'd be easier to write HTML and inject it using Svelte's `{@html ...}` tag, neither of which were easy, and I really didn't want to write posts in HTML or Svelte if I could help it.

That's when I realized I could just use Markdown, or some suitable enough superset of Markdown, and translate it into HTML for the Svelte compiler to do its thing. After a quick google search I found some tools to do just that and settled with mdsvex.

...
54 changes: 54 additions & 0 deletions src/lib/yap/making-of-pt3.svx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
title: making of (pt. 3)
date: !!str 2026-06-02T15:41:40+10:00
posted: !!str 2026-06-02T15:41:40+10:00
minimized: true
raw: >
...

mdsvex wasn't without its quirks though, and I needed to do some tweaking.

##### mdsvex & Svelte 4

When I first installed mdsvex and tried displaying a dummy document, I ran into an issue where the Svelte compiler kept complaining about Svelte 4 incompatabilities. After doing some digging, I realized that the issue was that I'd forced the Svelte compiler to use runes across the project, only ignoring my `node_modules` folder. The issue was that the [mdsvex transformer is written in Svelte 4](https://github.com/pngwn/MDsveX/blob/950d624259985b42adad431507bf2bdc9adb58a2/packages/mdsvex/src/transformers/index.ts#L446), which when used by the mdsvex preprocesser generates perfectly fine Svelte 4 code but cannot be used in conjunction with Svelte 5 code.

Thankfully, this was easily fixed by excluding `*.svx` in the runes requirement, but there's some deeper underlying issues that may come into play later if I want to [include Svelte 5 components](https://github.com/pngwn/MDsveX/issues/485) into my posts. For now I'm planning on sticking with mdsvex but may have to either switch to something like markdoc-svelte or contribute to a Svelte 5 overhaul of mdsvex.

##### Typing

This was a minor inconenience, but I didn't get module types from `*.svx` files out of the box and had to define an ambient module as described [in the docs](https://mdsvex.pngwn.io/docs#extensions). I didn't mind this as it allowed me to define some set types for my posts' frontmatter. One thing I haven't spent time fixing is the duplication of types between my `_layout.svelte` file, `svx.d.ts`, and `$routes/yap/+page.svelte`. I'll probably fix this somewhere down the road.

##### Image Paths

The last memorable inconvenience was path resolutions in `*.svx` files. I discovered that in order to include images, I needed to include their paths from the `src/` directory. This was an easy fix via a [relative images plugin](https://github.com/mattjennings/mdsvex-relative-images).

### Conclusion

Overall, I'm very happy with how the new webpage is turning out already. There's probably still more work to be done (as described above), but I'll fix things once they get annoying enough since everything just works right now. If you're reading this and in the process of learning web dev and/or building your own blog, I'd be happy to share more!

Andrew
---

...

mdsvex wasn't without its quirks though, and I needed to do some tweaking.

##### mdsvex & Svelte 4

When I first installed mdsvex and tried displaying a dummy document, I ran into an issue where the Svelte compiler kept complaining about Svelte 4 incompatabilities. After doing some digging, I realized that the issue was that I'd forced the Svelte compiler to use runes across the project, only ignoring my `node_modules` folder. The issue was that the [mdsvex transformer is written in Svelte 4](https://github.com/pngwn/MDsveX/blob/950d624259985b42adad431507bf2bdc9adb58a2/packages/mdsvex/src/transformers/index.ts#L446), which when used by the mdsvex preprocesser generates perfectly fine Svelte 4 code but cannot be used in conjunction with Svelte 5 code.

Thankfully, this was easily fixed by excluding `*.svx` in the runes requirement, but there's some deeper underlying issues that may come into play later if I want to [include Svelte 5 components](https://github.com/pngwn/MDsveX/issues/485) into my posts. For now I'm planning on sticking with mdsvex but may have to either switch to something like markdoc-svelte or contribute to a Svelte 5 overhaul of mdsvex.

##### Typing

This was a minor inconenience, but I didn't get module types from `*.svx` files out of the box and had to define an ambient module as described [in the docs](https://mdsvex.pngwn.io/docs#extensions). I didn't mind this as it allowed me to define some set types for my posts' frontmatter. One thing I haven't spent time fixing is the duplication of types between my `_layout.svelte` file, `svx.d.ts`, and `$routes/yap/+page.svelte`. I'll probably fix this somewhere down the road.

##### Image Paths

The last memorable inconvenience was path resolutions in `*.svx` files. I discovered that in order to include images, I needed to include their paths from the `src/` directory. This was an easy fix via a [relative images plugin](https://github.com/mattjennings/mdsvex-relative-images).

### Conclusion

Overall, I'm very happy with how the new webpage is turning out already. There's probably still more work to be done (as described above), but I'll fix things once they get annoying enough since everything just works right now. If you're reading this and in the process of learning web dev and/or building your own blog, I'd be happy to share more!

Andrew
11 changes: 7 additions & 4 deletions src/lib/yap/svx.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ declare module "*.svx" {
title: string;
date: string;
posted: string;
minimized?: boolean;
raw: string;
};
}
Expand All @@ -18,8 +19,9 @@ Example svx post:
```svx
---
title: testing
date: 2026-05-30T18:06:00Z
posted: 2026-06-01T11:30:00Z;
date: !!str 2026-05-30T18:06:00Z
posted: !!str 2026-06-01T11:30:00Z;
minimized: true
raw: >
# foo

Expand All @@ -32,7 +34,8 @@ bar
```

title: string display title for the post
date: iso 8601 format string date of the post
posted: actual posting time
date: iso 8601 format string date of the post -- !!str forces parser to parse as string, otherwise default wipes timezone!
posted: actual posting time -- see above note
minimized: whether a post should start minimized or not
raw: indented content for the search functionality
*/
Loading
Loading