Compare commits
17 Commits
0695ad26bd
...
main
Author | SHA1 | Date | |
---|---|---|---|
0509ce9d04
|
|||
3c1a33561e
|
|||
9243522261
|
|||
86919cd64d
|
|||
217f65b090
|
|||
897eb3b07a
|
|||
40b898d544
|
|||
f696554fee | |||
85f91aed49
|
|||
2936ab3384
|
|||
5dc7db36f8
|
|||
9d0e68f5f6
|
|||
35ba12de9e
|
|||
7a01764c0c
|
|||
72525c7f5b
|
|||
09d869e7c5
|
|||
b8d3aba4c0
|
2
.github/workflows/deploy.yml
vendored
2
.github/workflows/deploy.yml
vendored
@@ -33,7 +33,7 @@ jobs:
|
||||
- name: Deploy website
|
||||
run: |
|
||||
MACHINE_IP="$(tailscale ip -4 $MACHINE_NAME)"
|
||||
ssh -i ~/.ssh/key "$MACHINE_USER_NAME:@$MACHINE_IP" /bin/bash << EOF
|
||||
ssh -i ~/.ssh/key "$MACHINE_USER_NAME@$MACHINE_IP" /bin/bash << EOF
|
||||
cd /opt/website
|
||||
git pull
|
||||
cd ../
|
||||
|
@@ -4,12 +4,13 @@ import sitemap from "@astrojs/sitemap";
|
||||
import remarkMath from "remark-math";
|
||||
import rehypeKatex from "rehype-katex";
|
||||
|
||||
import tailwind from "@astrojs/tailwind";
|
||||
import tailwindcss from "@tailwindcss/vite";
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
site: "https://kennethnym.com",
|
||||
integrations: [mdx(), sitemap(), tailwind()],
|
||||
integrations: [mdx(), sitemap()],
|
||||
|
||||
markdown: {
|
||||
shikiConfig: {
|
||||
// Choose from Shiki's built-in themes (or add your own)
|
||||
@@ -19,4 +20,8 @@ export default defineConfig({
|
||||
remarkPlugins: [remarkMath],
|
||||
rehypePlugins: [rehypeKatex],
|
||||
},
|
||||
|
||||
vite: {
|
||||
plugins: [tailwindcss()],
|
||||
},
|
||||
});
|
||||
|
@@ -14,13 +14,13 @@
|
||||
"@astrojs/mdx": "^2.1.1",
|
||||
"@astrojs/rss": "^4.0.5",
|
||||
"@astrojs/sitemap": "^3.1.1",
|
||||
"@astrojs/tailwind": "^5.1.0",
|
||||
"@tailwindcss/vite": "^4.1.11",
|
||||
"astro": "^4.4.15",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"tailwindcss": "^4.1.11",
|
||||
"typescript": "^5.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@catppuccin/tailwindcss": "^0.1.6",
|
||||
"@catppuccin/tailwindcss": "1.0.0",
|
||||
"@flydotio/dockerfile": "latest",
|
||||
"@tailwindcss/typography": "^0.5.10",
|
||||
"prettier": "^3.2.5",
|
||||
|
7793
pnpm-lock.yaml
generated
7793
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
---
|
||||
// Import the global.css file here so that it is included on
|
||||
// all pages through the use of the <BaseHead /> component.
|
||||
import '../styles/global.css';
|
||||
import "../styles/global.css";
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
@@ -11,7 +11,7 @@ interface Props {
|
||||
|
||||
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
|
||||
|
||||
const { title, description, image = '/blog-placeholder-1.jpg' } = Astro.props;
|
||||
const { title, description, image = "/blog-placeholder-1.jpg" } = Astro.props;
|
||||
---
|
||||
|
||||
<!-- Global Metadata -->
|
||||
@@ -23,11 +23,19 @@ const { title, description, image = '/blog-placeholder-1.jpg' } = Astro.props;
|
||||
<link rel="canonical" href={canonicalURL} />
|
||||
|
||||
<!-- RSS autodiscovery -->
|
||||
<link rel="alternate" type="application/rss+xml" title={title} href={`${Astro.site}rss.xml`} />
|
||||
<link
|
||||
rel="alternate"
|
||||
type="application/rss+xml"
|
||||
title={title}
|
||||
href={`${Astro.site}rss.xml`}
|
||||
/>
|
||||
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Source+Serif+4:ital,opsz,wght@0,8..60,200..900;1,8..60,200..900&display=swap" rel="stylesheet">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Source+Serif+4:ital,opsz,wght@0,8..60,200..900;1,8..60,200..900&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
<!-- Primary Meta Tags -->
|
||||
<title>{title}</title>
|
||||
|
@@ -1,15 +1,15 @@
|
||||
<div id="command-line" class="w-full flex flex-row bg-base">
|
||||
<div id="command-line" class="w-full flex flex-row bg-ctp-base">
|
||||
<input
|
||||
aria-hidden="true"
|
||||
id="command-line-input"
|
||||
type="text"
|
||||
class="bg-base focus:outline-none active:outline-none cursor-default caret-transparent m-0"
|
||||
class="bg-ctp-base focus:outline-none active:outline-none cursor-default caret-transparent m-0"
|
||||
/>
|
||||
<div id="caret" aria-hidden="true" class="bg-text inline-block"> </div>
|
||||
<p
|
||||
aria-hidden="true"
|
||||
id="status-text"
|
||||
class="absolute w-full h-full bg-base hidden italic"
|
||||
class="absolute w-full h-full bg-ctp-base hidden italic"
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
@@ -94,7 +94,7 @@
|
||||
} else {
|
||||
statusText.innerHTML = `E492: Not an editor command: ${command}`;
|
||||
statusText.classList.remove("hidden");
|
||||
statusText.classList.add("text-red");
|
||||
statusText.classList.add("text-ctp-red");
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -6,5 +6,6 @@ import Link from "./Link.astro";
|
||||
<nav class="flex flex-row items-center space-x-4">
|
||||
<p class="font-bold text-lg">kennethnym</p>
|
||||
<Link href="/">home</Link>
|
||||
<Link href="/read">books</Link>
|
||||
</nav>
|
||||
</header>
|
||||
|
@@ -6,9 +6,9 @@ const { href, class: className, ...props } = Astro.props;
|
||||
href={href}
|
||||
class:list={[
|
||||
"underline",
|
||||
"text-blue",
|
||||
"hover:text-lavender",
|
||||
"visited:text-mauve",
|
||||
"text-ctp-blue",
|
||||
"hover:text-ctp-lavender",
|
||||
"visited:text-ctp-mauve",
|
||||
className,
|
||||
]}><slot /></a
|
||||
>
|
||||
|
@@ -4,10 +4,10 @@ import CommandLine from "./CommandLine.astro";
|
||||
---
|
||||
|
||||
<div class="hidden sm:block absolute w-full bottom-0">
|
||||
<footer class="w-full bg-crust flex flex-row leading-tight">
|
||||
<footer class="w-full bg-ctp-mantle flex flex-row leading-tight">
|
||||
<span
|
||||
id="status-indicator"
|
||||
class="bg-blue font-bold text-base inline-block leading-tight"
|
||||
class="bg-ctp-blue font-bold text-ctp-base inline-block leading-tight"
|
||||
> NORMAL </span
|
||||
>
|
||||
<div id="project-list" class="flex flex-row bg-surface0">
|
||||
@@ -40,14 +40,14 @@ import CommandLine from "./CommandLine.astro";
|
||||
|
||||
cmdLine.addEventListener("cmdmodeenabled", () => {
|
||||
statusIndicator.innerHTML = " COMMAND ";
|
||||
statusIndicator.classList.remove("bg-blue");
|
||||
statusIndicator.classList.add("bg-peach");
|
||||
statusIndicator.classList.remove("bg-ctp-blue");
|
||||
statusIndicator.classList.add("bg-ctp-peach");
|
||||
});
|
||||
|
||||
cmdLine.addEventListener("cmdmodedisabled", () => {
|
||||
statusIndicator.innerHTML = " NORMAL ";
|
||||
statusIndicator.classList.add("bg-blue");
|
||||
statusIndicator.classList.remove("bg-peach");
|
||||
statusIndicator.classList.add("bg-ctp-blue");
|
||||
statusIndicator.classList.remove("bg-ctp-peach");
|
||||
});
|
||||
|
||||
window.addEventListener("openhelp", () => {
|
||||
|
@@ -0,0 +1,53 @@
|
||||
---
|
||||
title: a gentle introduction to cloudflare tunnels
|
||||
description: A guide in using CloudFlare Tunnels to expose services to the Internet
|
||||
pubDate: May 28 2025
|
||||
---
|
||||
|
||||
CloudFlare Tunnel allows you to expose services within a network to the public without a publicly routable IP address. For example, you can expose a website to the public under a public hostname, without exposing your machine's IP address. You don't even need to deal with SSL for HTTPS, as this is automatically handled by CloudFlare! This can be beneficial because, for one, exposing your machine directly to the Internet poses a potential security risk; for another, it might not be feasible to do so. By exposing your services with Tunnel, you receive all the benefits of using CloudFlare network, including DDoS protection, caching, and more, without exposing your machines to the public.
|
||||
|
||||
CloudFlare Tunnels support many protocols, including HTTP/S, TCP, UDP, and even SSH. This unlocks many use cases beyond exposing HTTP services. As an example, you can expose a game server, such as a Minecraft server, over TCP, under a publicly accessible hostname.
|
||||
|
||||
## How does CloudFlare Tunnel work?
|
||||
|
||||
CloudFlare Tunnel relies on a persistent *connector* called `cloudflared` that establishes an **encrypted** connection between your machine and the global CloudFlare network. Each connector is bound to a tunnel, which maps a public hostname to an address the connector can access. As an example, [code.nym.sh](code.nym.sh), my public Gitea instance, is mapped to `http://localhost:3000`. Since the associated `cloudflared` is running on the same host, it can access `localhost`, and therefore any locally running service, including Gitea.
|
||||
|
||||
Suppose a service is exposed under `service-a.com` which is publicly accessible, and an HTTP request is made to it. The request will go through the following steps:
|
||||
|
||||
1. It is routed to CloudFlare's network
|
||||
2. Based on the hostname, it is then forwarded to the corresponding tunnel.
|
||||
3. The request is then forwarded to the appropriate connector, which then forwards it to the configured (local) address.
|
||||
|
||||
This is a high-level overview of CloudFlare tunnel's architecture. If you are interested in the details of Tunnel, including how it handles redundancy and failover, check out [this official reference document](https://developers.cloudflare.com/reference-architecture/architectures/sase/#tunnels-to-self-hosted-applications).
|
||||
|
||||
## Deploying `cloudflared`
|
||||
|
||||
There are different ways you can deploy `cloudflared`. I have tried the following approaches:
|
||||
|
||||
1. Running `cloudflared` on the same host where the services are running (this is my setup currently)
|
||||
2. Running `cloudflared` on a separate machine in the same network (for example, within the same Tailnet) where the services are running
|
||||
|
||||
In the first scenario, an instance of `cloudflared` is deployed on the machine that is running the service you wish to expose. In my case, I have 2 machines running different services I need to expose, so I deployed 2 instances of `cloudflared`, each responsible for exposing the services running on the same machine.
|
||||
|
||||
In the second scenario, an instance of `cloudflared` is deployed on a dedicated machine that acts as the "gateway" to services running in your network. This can look like one machine running `cloudflared` in a Tailnet that is responsible for the tunneling of services running in the same network, potentially on different machines.
|
||||
|
||||
There are no right or wrong approaches. I am providing these scenarios as reference points, but use your best judgment to adapt them to your needs.
|
||||
|
||||
## Configuring CloudFlare Tunnel
|
||||
|
||||
*Before creating a Tunnel, make sure that the domains you wish to use is added to CloudFlare ([guide here](https://developers.cloudflare.com/fundamentals/setup/manage-domains/add-site/)).*
|
||||
|
||||
Creating a Tunnel is straightforward. First, create a CloudFlare Tunnel in the Zero Trust CloudFlare dashboard. CloudFlare should then provide instructions on how to install and run `cloudflared` for different environments and operating systems.
|
||||
|
||||
Once the connector is online, add a public hostname to the tunnel. You can map a root domain name, subdomains, and even subpaths. Then, specify the type and the local address for the service that you want to expose. For example, if you want to expose your backend server running on `localhost:8000` under the URL `https://api.acme.com`, do the following:
|
||||
|
||||
- Specify `api` as subdomain
|
||||
- Specify `acme.com` as domain
|
||||
- Specify the service type as `HTTP` (not `HTTPS`, as this is from the perspective of the connector)
|
||||
- Specify the URL as `localhost:8000`
|
||||
|
||||
Save the settings, and voila! You have exposed your backend to the public Internet! How easy is that?
|
||||
|
||||
## Final Words
|
||||
|
||||
As always, feel free to shoot me an email or DM me on X if you have any questions about CloudFlare Tunnels.
|
25
src/content/blog/amor-fati.md
Normal file
25
src/content/blog/amor-fati.md
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
title: amor fati
|
||||
description: love of fate
|
||||
pubDate: Aug 25 2025
|
||||
---
|
||||
|
||||
I am slowing coming to terms that I have little to no control of what will.
|
||||
|
||||
The past few months were nothing short of surprises, good or bad. Through various twists and turns, fate took me to where I am now: living in a bustling city in a cozy flat, while having a fulfilling job in an environment where I can thrive and grow. Look back at the windy path behind me: puddles of tears I shed, stench of sweats that ran down from me, trails of blood from all the injuries that I endured. It is true: the only way out was through, and Fate was my navigator.
|
||||
|
||||
At times, I hated them. I could not understand why they would take me through such a strenuous path. Every moment of disappointments, exhaustions and heartbreaks felt like a dead end, and it would make me question whether Fate was sabotaging me. Fate is a patient one, however. Despite my doubts, they remained undeterred, and fought through all the troubles together.
|
||||
|
||||
Eventually, we saw light. The light came from a peaceful sanctuary where fellow travellers rest and heal before they move on. Before we could enter, Fate said:
|
||||
|
||||
"Before we could enter, you must give up something that is dear to you. What you give up changes the path that the Sanctuary leads you. I get to decide what it is, but you can trus that I will make the best decision for you."
|
||||
|
||||
Before I could open my mouth, Fate did it. They put their hands straight through my chest, and ripped away my heart. They placed it on the alter before the Sanctuary. The gates slowly widened as my heart evaporated into thin air.
|
||||
|
||||
Now, Fate and I are in the Sanctuary. I am healing from the missing heart that was forcefully ripped away and from the damages I took from the journey to here. I finally get to settle down and rest.
|
||||
|
||||
"We are slightly closer to the top of the mountain now." Fate told me, "enjoy your rest - you deserved it."
|
||||
|
||||
"Where are we going next?" I asked, to which they replied, "to your destination."
|
||||
|
||||
Fate is mysterious. Fate is unforgiving. Fate is also loyal, and only Fate knows the way. Tell Fate where you want to go, fight by them, and Fate will bring you there.
|
23
src/content/blog/ask-what-not-why.md
Normal file
23
src/content/blog/ask-what-not-why.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
title: ask what, not why
|
||||
description: stop questioning and start wondering
|
||||
pubDate: Jul 30 2025
|
||||
---
|
||||
|
||||
*Disclaimer: this is subjective, and may not apply to everyone*
|
||||
|
||||
One mindset shift I have been practicing is avoiding using "why" when asking questions, and instead ask "what". For example, in the context of software engineering, instead of asking, "why are you using framework *x* instead of *y*, ask "what led you to decide on using framework *x*?". This shift has caused me to question less and wonder more.
|
||||
|
||||
Firstly, it drives me away from putting blames. Asking "why" brings an undertone of questioning, whether intentional or not. The questionee, including myself, as a result of feeling questioned, may shift into defensive mode and subconsciously look for excuses first, rather than exploring something more productive. It may also make them feel invalidated or judge. As an example, consider the difference, as a listener, between "why are you sad?" and "what made you sad?" The former, subtly or otherwise, invalidates your feeling of sadness, while the latter demonstrates a level of rapport and understanding.
|
||||
|
||||
Secondly, asking "why" puts the subject under the spotlight, whereas asking "what" shifts the focus to the outside world, allowing both sides to view the situation at hand more objectively and holistically. Consider the two questions, "why did you do this?" and "what caused you to do this?" The first question focuses on the subjective intention of the person. Instead, the second question is looking for the external factors that effected their action. This is important if the situation at hand calls for an objective review, for example when dissecting architectural decisions in the context of engineering.
|
||||
|
||||
Here are more examples.
|
||||
- "Why is the bus delayed again?" turns into "what caused the delay of the bus?"
|
||||
- "Why can't we ship this feature by this Friday?" turns into "what are the blockers and challenges that prohibit us from shipping this feature by this Friday?"
|
||||
- "Why am I feeling anxious" turns into "what is the source of my anxiety?"
|
||||
- "Why do you like playing the piano?" turns into "what about piano makes you interested in it?"
|
||||
|
||||
This is a challenging practice that requires conscious effort. Every time I find myself using the word "why", I stop and think, "how can I rephrase this question so that I am not asking why?" As a result, however, I find that it not only fosters further discussions, but it also makes me less judgemental as a person.
|
||||
|
||||
If you do decide to give this a go, I would love to hear what you think about this, and how it shifts your mindset and perspective. Until then, thank you for reading, and see you in my next post.
|
13
src/content/blog/fear-of-falling-behind.md
Normal file
13
src/content/blog/fear-of-falling-behind.md
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
title: fear of falling behind
|
||||
description: The looming pressure of keeping up with everything
|
||||
pubDate: Oct 1 2025
|
||||
---
|
||||
|
||||
I am lucky enough to be in an [environment](https://kennethnym.com/blog/your-environment-dictates-everything/) where I am surrounded by bright-minded, high-achieving people that are doing incredible work every day, and they are nothing short of inspiring. Safe to say - I am the dumbest person in the room. On one hand, I get to learn from them every day, driving myself to get better. On the other, comparison inevitably arises within myself, and it has been slowly getting onto me recently: will I ever be good enough?
|
||||
|
||||
There is always a looming pressure within me to work hard to prove myself to people; to prove that I belong in the room; to prove that I am equally capable of brilliance. I always tell myself: if I ever slack off, I will fall behind, and I will be vacated from the room of smarts.
|
||||
|
||||
Truthfully, no matter how hard I work, it will never feel enough. In the same vein that [validations](https://kennethnym.com/blog/the-pathological-desire-for-validation/) numb my insecurity and my wounds, working numbs the fear (which stems from my insecurity.) Neither makes the source of the problems go away. The answer to this is obvious: one should work not out of insecurity, but for the love of the game; for self-improvement; for themselves and **themselves only**.
|
||||
|
||||
The problem now lies within addressing insecurities and wounds within each of us. For many, including myself, this is a life-long journey of self discovery: processing past events, learning from failures, powering through traumas, and sitting with discomforts. Regardless of what one does, always remember: symptom relieves are never the solution.
|
54
src/content/blog/kenneth-v24-released-today.md
Normal file
54
src/content/blog/kenneth-v24-released-today.md
Normal file
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: Kenneth v24.0 released today
|
||||
description: Release note for Kenneth v24.0
|
||||
pubDate: Oct 8 2025
|
||||
---
|
||||
|
||||
I am happy to announce that I have officially released v24.0 of myself today. Kenneth v24 is the biggest release ever, containing heaps of improvements and new features. This blog post serves as a release note of what has changed since v23. For the impatient, here are several notable breaking changes:
|
||||
|
||||
- New job @ [Ona](https://ona.com) working on coding agents
|
||||
- Migrated home location to /uk/london
|
||||
- Drastically improved appearance
|
||||
- Many important (heartbreaking) life lessons learned
|
||||
- Kenneth is about 20% more self-aware
|
||||
- Met many friends from x dot com
|
||||
|
||||
Please read on for more technical details.
|
||||
|
||||
---
|
||||
|
||||
Enough tech gibberish. I would like to use this blog post as a reflection of the past year since my last birthday.
|
||||
|
||||
## Software Engineer @ Ona
|
||||
|
||||
Last birthday, I made a wish that I would get another job and move to London. Little did I know that I smashed that wish.
|
||||
|
||||
Ever since I was a teenager, I have always wanted to work at a startup. The idea that I get full autonomy over my work and that I get to work on something that I deeply care about is what motivates me to get up to work every day. Since then, I had applied to numerous positions at various companies of varying sizes, but to no avail.
|
||||
|
||||
Everything changed in June. I went to a pub event in London hosted by the nice folks at (Scaling Devtools)[https://scalingdevtools.com/], expecting that I would get to meet like-minded people, chat about tech, and exchange details. Suddenly, 2 people at Ona (known as Gitpod back then) showed up, and my mind *lit up*. I have known Gitpod for a long time, and to be able to meet the people behind it in a pub was mind-blowing. "How on earth did Gitpod, out of all companies, manage to find us here??" I thought to myself. We began introducing ourselves, and I got to talk about [tesseract](https://github.com/kennethnym/tesseract), a CDE that I built for my own use. My enthusiasm touched them, and they decided to give me a chance. The rest is history.
|
||||
|
||||
This, for me, has been the biggest turning point of my career. Being able to work alongside like-minded and smart people on a product that I am passionate about is something that I deeply cherish. I am and will forever be grateful for Ona for having me on the team, and I am honored to be on the team.
|
||||
|
||||
## Important life lessons
|
||||
|
||||
I won't go into details here, but many, many life events have happened since my last birthday. I am processing and healing through them, and I have also learned several important lessons. The biggest of them all is that one should take action on addressing their insecurities and be gentle with them at the same time.
|
||||
|
||||
I am a deeply insecure person, and my insecurities show up in all kinds of places. With people, they show up as my anxiety and my constant chase for validation. This has ruined friendships that I very very very very highly valued, which further reinforces my core beliefs, forming a vicious cycle. With work, they put unnecessary stress on myself, leading me to think that I am not good enough or that I am not working enough.
|
||||
|
||||
I have since started therapy, and the biggest progress I have made is the fact that this blog post exists! It has made me a lot more self-reflective and identity thinking patterns, which helps me process traumas and events (in ways that I did not expect when I signed up for it initially.)
|
||||
|
||||
Even though they are painful, I am still glad that they happened, because they have fundamentally changed me as a person. I am more outgoing, more compassionate, and more mature. They are memories that I will forever cherish.
|
||||
|
||||
## Maybe friends are oomfs we met on x dot com
|
||||
|
||||
I managed to meet many oomfs on x dot com and somehow managed to convince one of them to be my neighbor. Every meet up is nothing short of awesomeness. Unfortunately, most of them are not based around London, so I won't be able to see them again any time soon. If you are reading this and you are one of them, I will come see you again!
|
||||
|
||||
## The one constant birthday wish
|
||||
|
||||
Yes... the Achilles heel. We all know what it is. This year is no different. This is a part of life where I genuinely feel stuck and helpless. Being single has its perks, but I also long for the someone. The person with whom I can be vulnerable. The person with whom I can experience life until the end of the universe. I have made so much progress in other parts of life, but when it comes to this, I am absolutely clueless. I will build literal rockets that take me to the Moon before I figure this out.
|
||||
|
||||
Oh to be loved.
|
||||
|
||||
## Plans for v25
|
||||
|
||||
Aside from the obvious answer, my big plan is to release the *very secret thing* that I have been building. I want to refrain myself from talking about it, because then it will demotivate me from actually finishing it. I also wish for the friends I have made along the way to stay with me.
|
23
src/content/blog/the-pathological-desire-for-validation.md
Normal file
23
src/content/blog/the-pathological-desire-for-validation.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
title: the pathological desire for validation
|
||||
description: the experience of someone who struggles with self perception
|
||||
pubDate: Jul 04 2025
|
||||
---
|
||||
|
||||
I have a pathological crave for validation, be it in my career, or in my relationships and friendships. Unfortunately, I am still suffering from this disease, and I do not yet have the solution, but I believe I have found the trace to the problem. This is a self reflection for people who are interested in the experience of being a person who has tragically low to no self worth and are struggling to crawl out of the trench. Even more tragically is the fact that I had normalized this for most of my life until recently.
|
||||
|
||||
I was raised in an environment where emotions were strictly suppressed (man are not supposed to show emotions, remember!), and where love was transactional. I was conditioned from a young age that achievement was an expectation. I was taught that love and affections are manifested as efforts made to raise me, and I have this looming pressure that I need to pay it back when I grow older. I would only receive minimal affections when i had made an achievement, such as getting good grades or winning a competition. On the other hand, mistakes would bring upon severe punishments. On top of that, I was under the care of someones who lacked the ability to openly communicate and have conversations. Talking to them was like walking on eggshells. I had to be hyper attuned to their moods and be careful with my words so as to not trigger them. When I was in school, I had to hide my grades from my parents, because i knew they would not be nearly satisfactory. It would not be long, however, until the truth would drop, and then I would be met with visceral reactions and punishments.
|
||||
|
||||
In school, even though I would not consider myself to be bullied, I would very often be the butt of the joke, or be the target to be pranked. back then, I brushed it off as my classmates being playful, but I most definitely did not enjoy the experience. I was also strictly prohibited from developing romantic relationships with anyone, which further stunned my emotional development. The only thing I was decent at was programming, but no one at school took it seriously.
|
||||
|
||||
Fast forward into my early adulthood, I managed to get myself into several romantic situations online. Each further tramped on my self worth, and made me question whether I would ever, ever, be worthy of love and affection, despite all the efforts I had put in.
|
||||
|
||||
To this day, I still don't know what love and affection is, and thus how it feels to be the receiving end of it. My past experience had taught me that love is something I need to fight for. I need to work in order to receive affection. I need to put in effort to receive validations and approvals. If I don't receive them, it means that i am not working hard enough, and therefore not worthy and deserving of anything. In career, it means doubting my software engineering ability. In relationships and friendships, it means doubting myself as a person, constantly questioning my place in another person. Hanging out with friends brings me anxiety about how they view me; romantic interests even more so. When I bring this up with a person (which I only do if they are a very very significant person), I will receive my dose of validation, but the high will wear off shortly, like nicotine or alcohol, then I will need it again. Not only do I struggle to trust and internalize that validation, I constantly desire more of it to soothe myself.
|
||||
|
||||
The thirst for validation also affects how i view others. I perceive myself as inferior to all my peers and friends. They write code better. They work on cooler things. They have more friends. They have way cooler interests. They have broader perspective of the world. They are cooler and smarter. They (you if you are reading this) may reject this, but I struggle to view myself in any other way.
|
||||
|
||||
This is why it is deeply pathological - it is excessive, uncontrollable, and projects onto other people. It is extremely crippling, and it is unsustainable in the long term. I only recently started therapy, and I don't know how long or what it will take to pull myself out of this misery.
|
||||
|
||||
Before then, I want to express my deepest gratitude to the person who I admire most admire, for revealing this deep rooted issue of mine that I have set aside for the longest time, for making me self reflect more, and for giving the reassurances when I needed them.
|
||||
|
||||
Finally, if you have made it to here, I hope you find my experience helpful, and thank you for following along.
|
@@ -14,4 +14,13 @@ const blog = defineCollection({
|
||||
}),
|
||||
});
|
||||
|
||||
export const collections = { blog };
|
||||
const read = defineCollection({
|
||||
type: "content",
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
author: z.string(),
|
||||
goodReadLink: z.string().optional(),
|
||||
}),
|
||||
});
|
||||
|
||||
export const collections = { blog, read };
|
||||
|
6
src/content/read/being-you.md
Normal file
6
src/content/read/being-you.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
title: Being You
|
||||
author: Anil Seth
|
||||
---
|
||||
|
||||
I am still organizing my notes for this book.
|
34
src/content/read/the-creative-act.md
Normal file
34
src/content/read/the-creative-act.md
Normal file
@@ -0,0 +1,34 @@
|
||||
---
|
||||
title: The Creative Act
|
||||
author: Rick Rubin
|
||||
goodReadLink: https://www.goodreads.com/book/show/60965426-the-creative-act
|
||||
---
|
||||
|
||||
## Everyone is a creator
|
||||
|
||||
- To live as an artist is a way of being in the world
|
||||
|
||||
## Tuning in
|
||||
|
||||
- We are all participating in a larger creative act we are not conducting. We are being conducted. The artist is on a cosmic timetable, just like all of nature.
|
||||
- In this great unfolding, ideas and thoughts, themes and songs and other works of art exist in the aether and ripen on schedule, ready to find expression in the physical world.
|
||||
As artists, it is our job to draw down this information, transmute it, and share it.
|
||||
- We are all antennae for creative thought.
|
||||
- To pick up on signals, don't look for it, or try to predict and analyze our way into it. Instead, create an open space that allows it. A space so free of the normal overpacked condition of our minds that it functions as a vacuum.
|
||||
- Practicing a way of being that allows you to see the world through uncorrupted, innocent eyes can free you to act in concert with the universe's timetable.
|
||||
|
||||
## The source of creativity
|
||||
|
||||
- The Source is out there. A wisdom surrounding us, an inexhaustible offering that is always available.
|
||||
- Art is a circulation of energetic ideas. What makes them appear new is that they are combining differently each time they come back.
|
||||
|
||||
## Awareness
|
||||
|
||||
- The universe is only as large as our perception of it. When we cultivate our awareness, we are expanding the universe.
|
||||
|
||||
## The Vessal and the Filter
|
||||
|
||||
- The vessel holds the sum of our thoughts, feelings, dreams, and experiences in the world.
|
||||
- Information is filtered uniquely for each person before entering the vessel.
|
||||
- Artists seek to restore childlike perceptions, a more innocent state of wonder and appreciation untethered to utility or survival.
|
||||
- One can think of the creative act as taking the sum of our vessel's contents as potential material, selecting for elements that seem useful or significant in the moment, and re-representing them.
|
7
src/content/read/user-friendly.md
Normal file
7
src/content/read/user-friendly.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: User Friendly
|
||||
author: Cliff Kuang, Robert Fabricant
|
||||
goodReadLink: https://www.goodreads.com/book/show/41940285-user-friendly
|
||||
---
|
||||
|
||||
I will start making notes here when I start reading this book.
|
7
src/content/read/zero-to-one.md
Normal file
7
src/content/read/zero-to-one.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Zero to One
|
||||
author: Peter Thiel, Blake Masters
|
||||
goodReadLink: https://www.goodreads.com/book/show/18050143-zero-to-one
|
||||
---
|
||||
|
||||
I will start making notes here when I start reading this book.
|
@@ -18,7 +18,7 @@ const {
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en" class="latte dark:mocha">
|
||||
<html lang="en" class="dark:mocha">
|
||||
<head>
|
||||
<BaseHead title={title} description={description} image={heroImage} />
|
||||
{
|
||||
@@ -31,11 +31,13 @@ const {
|
||||
}
|
||||
</head>
|
||||
|
||||
<body class="blog bg-base text-text max-w-prose m-auto p-8">
|
||||
<body class="blog bg-ctp-base text-ctp-text max-w-prose m-auto p-8">
|
||||
<Header />
|
||||
<main class="py-10">
|
||||
<article>
|
||||
<div class="prose prose-lg dark:prose-invert">
|
||||
<div
|
||||
class="prose prose-lg dark:prose-invert prose-headings:text-ctp-text prose-headings:font-medium"
|
||||
>
|
||||
<div>
|
||||
<div class="opacity-60">
|
||||
<FormattedDate date={pubDate} />
|
||||
|
58
src/layouts/BookRead.astro
Normal file
58
src/layouts/BookRead.astro
Normal file
@@ -0,0 +1,58 @@
|
||||
---
|
||||
import type { CollectionEntry } from "astro:content";
|
||||
import BaseHead from "../components/BaseHead.astro";
|
||||
|
||||
type Props = CollectionEntry<"read">["data"];
|
||||
|
||||
const { title, author, goodReadLink } = Astro.props;
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<BaseHead
|
||||
title={`Kenneth's Read - ${title}`}
|
||||
description={`Notes I made for the book ${title}`}
|
||||
/>
|
||||
</head>
|
||||
<body
|
||||
class="w-full reads -z-2 bg-stone-200 dark:bg-stone-900 flex justify-center dark:text-stone-300 pt-20 md:py-40"
|
||||
>
|
||||
<header
|
||||
class="fixed scroll-to-blur w-full -z-1 top-0 left-0 right-0 flex justify-center"
|
||||
>
|
||||
<div
|
||||
class="w-full max-w-[calc(65ch+var(--spacing)*24)] px-8 md:px-12 py-4 md:py-12 opacity-80"
|
||||
>
|
||||
<h1 class="font-bold text-sm">Kenneth's Read</h1>
|
||||
<h2 class="text-sm">Quotes and notes from my readings.</h2>
|
||||
</div>
|
||||
</header>
|
||||
<main
|
||||
class="relative w-full max-w-[calc(65ch+var(--spacing)*24)] px-8 md:px-12 py-10 rounded-t-2xl md:rounded-2xl shadow-lg border border-stone-300 dark:border-stone-600 bg-stone-100 dark:bg-stone-800 min-h-[calc(100vh-var(--spacing)*28)]"
|
||||
>
|
||||
<article>
|
||||
<div class="flex justify-between items-center w-full mb-10">
|
||||
<header class="flex flex-col">
|
||||
<h1 class="font-bold">{title}</h1>
|
||||
<h2 class="font-medium">{author}</h2>
|
||||
</header>
|
||||
<a href={goodReadLink} class="underline">GoodRead</a>
|
||||
</div>
|
||||
<div
|
||||
class="prose dark:prose-invert prose-headings:font-medium prose-headings:tracking-tight prose-h2:mb-0.5 dark:prose-headings:text-stone-300 dark:text-stone-300 dark:marker:text-stone-300 prose-ul:list-none prose-ul:p-0 prose-li:p-0 prose-li:before:content-['•'] prose-li:relative prose-li:before:absolute prose-li:before:left-0 prose-li:before:-translate-x-4"
|
||||
>
|
||||
<slot />
|
||||
</div>
|
||||
</article>
|
||||
<div
|
||||
class="absolute left-6 top-0 -translate-y-1/2 transition-all rounded-lg bg-stone-100 dark:bg-stone-800 border border-stone-300 dark:border-stone-700 shadow-lg h-min"
|
||||
>
|
||||
<a
|
||||
class="block px-2 py-0.5 text-sm opacity-80 transition-all"
|
||||
href="/read"><- All books</a
|
||||
>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
@@ -1,15 +1,15 @@
|
||||
---
|
||||
import { type CollectionEntry, getCollection } from 'astro:content';
|
||||
import BlogPost from '../../layouts/BlogPost.astro';
|
||||
import { type CollectionEntry, getCollection } from "astro:content";
|
||||
import BlogPost from "../../layouts/BlogPost.astro";
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const posts = await getCollection('blog');
|
||||
const posts = await getCollection("blog");
|
||||
return posts.map((post) => ({
|
||||
params: { slug: post.slug },
|
||||
props: post,
|
||||
}));
|
||||
}
|
||||
type Props = CollectionEntry<'blog'>;
|
||||
type Props = CollectionEntry<"blog">;
|
||||
|
||||
const post = Astro.props;
|
||||
const { Content } = await post.render();
|
||||
|
@@ -13,19 +13,23 @@ const posts = (await getBlogs()).sort(
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en" class="latte dark:mocha bg-base">
|
||||
<html lang="en" class="dark:mocha bg-ctp-base">
|
||||
<head>
|
||||
<BaseHead title={SITE_TITLE} description={SITE_DESCRIPTION} />
|
||||
</head>
|
||||
<body
|
||||
class="tilde-background text-text h-screen m-auto sm:flex items-center justify-center sm:overflow-hidden"
|
||||
class="tilde-background text-ctp-text h-screen m-auto sm:flex items-center justify-center sm:overflow-hidden"
|
||||
>
|
||||
<div class="visible p-8 sm:hidden">
|
||||
<header>
|
||||
<p class="font-bold text-2xl">kennethnym</p>
|
||||
</header>
|
||||
<main class="py-8">
|
||||
<p>dumping ground for my thoughts. all opinions are my own.</p>
|
||||
<p>
|
||||
software engineer @ <Link href="https://ona.com">ona</Link>. all
|
||||
opinions are my own.
|
||||
</p>
|
||||
<p>check out <Link href="/read">the books I am reading!</Link></p>
|
||||
<h1 class="font-bold mt-8 mb-2 text-lg visited">current projects:</h1>
|
||||
<ul class="not-prose space-y-4 md:space-y-2">
|
||||
<li>
|
||||
@@ -66,11 +70,16 @@ const posts = (await getBlogs()).sort(
|
||||
<main
|
||||
class="py-8 px-4 max-w-4xl flex flex-col items-center space-y-0 leading-tight"
|
||||
>
|
||||
<header class="font-bold text-center">KENNETHNYM v23.5</header>
|
||||
<header class="font-bold text-center">KENNETHNYM v24.0</header>
|
||||
<p class="leading-none"> </p>
|
||||
<p class="text-center">software engineer. unpaid hhkb salesman.</p>
|
||||
<p class="text-center">
|
||||
software engineer @ <Link href="https://ona.com">Ona</Link>. unpaid
|
||||
hhkb salesman.
|
||||
</p>
|
||||
<p> </p>
|
||||
<p> </p>
|
||||
<Link href="/read" class="w-full">books i am reading</Link>
|
||||
<p> </p>
|
||||
<ul
|
||||
aria-label="recent blog posts"
|
||||
class="w-full space-y-2 sm:space-y-0"
|
||||
|
94
src/pages/read.astro
Normal file
94
src/pages/read.astro
Normal file
@@ -0,0 +1,94 @@
|
||||
---
|
||||
import { getCollection } from "astro:content";
|
||||
import BaseHead from "../components/BaseHead.astro";
|
||||
|
||||
const nowReading = {
|
||||
title: "The Creative Act",
|
||||
slug: "the-creative-act",
|
||||
};
|
||||
const quote = {
|
||||
content:
|
||||
"Practicing a way of being that allows you to see the world through uncorrupted, innocent eyes can free you to act in concert with the universe's timetable.",
|
||||
bookTitle: "The Creative Act",
|
||||
};
|
||||
|
||||
const books = (await getCollection("read")).filter(
|
||||
(book) => book.slug !== nowReading.slug,
|
||||
);
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html
|
||||
lang="en"
|
||||
class="bg-stone-200 dark:bg-stone-900 text-stone-700 dark:text-stone-400"
|
||||
>
|
||||
<head>
|
||||
<BaseHead
|
||||
title="Kenneth's Reads"
|
||||
description="Quotes and notes from my readings."
|
||||
/>
|
||||
</head>
|
||||
<body class="reads px-8">
|
||||
<main class="mt-8 mb-20 md:mt-0 max-w-4xl grid grid-cols-11">
|
||||
<header class="col-span-11 grid grid-cols-11">
|
||||
<h1
|
||||
class="col-span-10 md:col-span-3 md:justify-self-end text-lg font-bold mt-8"
|
||||
>
|
||||
<a href="/" class="hover:underline">Kenneth</a>'s Reads
|
||||
</h1>
|
||||
<p
|
||||
class="col-span-10 md:col-span-8 text-lg font-medium mb-10 md:mb-20 md:ml-12 md:mt-8"
|
||||
>
|
||||
Quotes and notes from my readings.
|
||||
</p>
|
||||
</header>
|
||||
|
||||
<div class="md:justify-self-end col-span-10 md:col-span-3">
|
||||
<div class="flex items-center opacity-70 mb-2 md:mb-20">
|
||||
<div
|
||||
class="w-3 h-3 bg-green-500 border-green-200 dark:bg-green-500 border-2 dark:border-green-300 rounded-full animate-pulse mr-2"
|
||||
>
|
||||
</div>
|
||||
<h2 class="tracking-tight">Now Reading</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-span-10 md:col-span-8 md:ml-12 mb-16 md:mb-20">
|
||||
<a class="font-medium underline" href={`/read/${nowReading.slug}`}
|
||||
>{nowReading.title}</a
|
||||
>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="md:justify-self-end col-span-10 md:col-span-3 flex flex-col md:items-end opacity-70"
|
||||
>
|
||||
<p class="text-6xl leading-none font-black select-none">“</p>
|
||||
<h2 class="leading-none -translate-y-8 tracking-tight">
|
||||
{quote.bookTitle}
|
||||
</h2>
|
||||
</div>
|
||||
<p
|
||||
class="col-span-10 md:col-span-8 max-w-prose md:ml-12 text-2xl md:text-4xl tracking-tight mb-20"
|
||||
>
|
||||
{quote.content}
|
||||
</p>
|
||||
|
||||
<h2
|
||||
class="col-span-10 md:col-span-3 tracking-tight md:justify-self-end mb-4"
|
||||
>
|
||||
All Books
|
||||
</h2>
|
||||
<ul class="col-span-10 md:col-span-8 md:ml-12 space-y-2">
|
||||
{
|
||||
books.map((book) => (
|
||||
<li>
|
||||
<a class="underline" href={`/read/${book.slug}`}>
|
||||
{book.data.title}
|
||||
</a>
|
||||
</li>
|
||||
))
|
||||
}
|
||||
</ul>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
20
src/pages/read/[...slug].astro
Normal file
20
src/pages/read/[...slug].astro
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
import { type CollectionEntry, getCollection } from "astro:content";
|
||||
import BookRead from "../../layouts/BookRead.astro";
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const posts = await getCollection("read");
|
||||
return posts.map((post) => ({
|
||||
params: { slug: post.slug },
|
||||
props: post,
|
||||
}));
|
||||
}
|
||||
type Props = CollectionEntry<"read">;
|
||||
|
||||
const post = Astro.props;
|
||||
const { Content } = await post.render();
|
||||
---
|
||||
|
||||
<BookRead {...post.data}>
|
||||
<Content />
|
||||
</BookRead>
|
@@ -1,3 +1,11 @@
|
||||
@import "tailwindcss";
|
||||
@import "@catppuccin/tailwindcss/mocha.css";
|
||||
@import url("https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap");
|
||||
|
||||
@plugin "@tailwindcss/typography";
|
||||
|
||||
@source inline("text-ctp-red");
|
||||
|
||||
@font-face {
|
||||
font-family: "CommitMono";
|
||||
src: url("/fonts/CommitMono-400-Regular.otf") format("opentype");
|
||||
@@ -77,6 +85,34 @@ body.blog {
|
||||
font-family: "Source Serif 4", "Georgia", serif;
|
||||
}
|
||||
|
||||
body.reads * {
|
||||
font-family: "Inter", sans-serif;
|
||||
}
|
||||
|
||||
.nf {
|
||||
font-family: "NerdFont";
|
||||
}
|
||||
|
||||
.scroll-to-blur {
|
||||
animation-name: scroll-to-blur;
|
||||
animation-duration: 1ms; /* Firefox requires this to apply the animation */
|
||||
animation-timeline: scroll(block nearest);
|
||||
}
|
||||
|
||||
@keyframes scroll-to-blur {
|
||||
0% {
|
||||
filter: blur(0px);
|
||||
}
|
||||
|
||||
20% {
|
||||
filter: blur(5px);
|
||||
transform: scale(0.99);
|
||||
opacity: 0%;
|
||||
}
|
||||
|
||||
100% {
|
||||
filter: blur(5px);
|
||||
transform: scale(0.99);
|
||||
opacity: 0%;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user