Skip to content

Commit 77ff5fd

Browse files
committed
Flesh out w/ empty subjects
1 parent 427e90d commit 77ff5fd

5 files changed

Lines changed: 254 additions & 24 deletions

File tree

‎.claude/launch.json‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
{
55
"name": "dev",
66
"runtimeExecutable": "cmd",
7-
"runtimeArgs": ["/c", "set PATH=C:\\Program Files\\nodejs;%PATH%&& npx astro dev"],
8-
"port": 4321,
7+
"runtimeArgs": ["/c", "set PATH=C:\\Program Files\\nodejs;%PATH%&& npx astro dev --port 4350"],
8+
"port": 4350,
99
"autoPort": true
1010
}
1111
]

‎src/consts.ts‎

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,25 @@
1-
export const SITE_TITLE = "CodyKN";
2-
export const SITE_DESCRIPTION = "";
1+
export const SITE_TITLE = "Cody Nguyen";
2+
export const SITE_DESCRIPTION =
3+
"Software engineer building at the intersection of medicine, robotics, ML, and finance.";
34
export const COPYRIGHT =
4-
"© " + new Date().getFullYear() + " CodyKN All Rights Reserved";
5+
"© " + new Date().getFullYear() + " Cody Nguyen. All rights reserved.";
56
export const ICP_NUMBER = "";
67

78
export const SOCIAL_LINKS = {
89
Github: "https://github.com/codykn",
9-
// Twitter: "https://twitter.com/yourusername",
10-
// LinkedIn: "https://www.linkedin.com/in/yourusername",
11-
// Instagram: "https://www.instagram.com/yourusername",
12-
// Facebook: "https://www.facebook.com/yourusername",
13-
// YouTube: "https://www.youtube.com/yourusername",
10+
LinkedIn: "https://www.linkedin.com/in/codykn",
1411
};
1512

1613
export const SEO_CONFIG = {
1714
ogImage: "/hero-img.png",
18-
keywords: "blog, tech, programming",
15+
keywords:
16+
"Cody Nguyen, software engineer, medicine, robotics, machine learning, finance",
1917
};
2018

2119
export const NAV_ITEMS = [
2220
{ text: "Home", link: "/" },
23-
{ text: "Medical", link: "/medical" },
21+
{ text: "Projects", link: "/projects" },
22+
{ text: "About", link: "/about" },
2423
];
2524

2625
export const BLOG_CONFIG = {
@@ -33,3 +32,13 @@ export const BLOG_CONFIG = {
3332
description: "All the tags used in posts.",
3433
},
3534
};
35+
36+
export const DOMAINS = [
37+
{
38+
name: "Medicine",
39+
slug: "medical",
40+
description:
41+
"Health-tech tools and platforms — from study aids to clinical decision support.",
42+
icon: "medical",
43+
},
44+
] as const;

‎src/pages/about.astro‎

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
---
2+
import Layout from "../layouts/Layout.astro";
3+
import { SOCIAL_LINKS, BLOG_CONFIG } from "../consts";
4+
import icons, { getSizedIcon } from "../assets/icons";
5+
---
6+
7+
<Layout title="About — Cody Nguyen" description="About Cody Nguyen — background, interests, and contact.">
8+
<section>
9+
<h1>About</h1>
10+
<div class="prose max-w-prose">
11+
<p>
12+
I'm Cody — a software engineer interested in problems that span
13+
disciplines. Most of my work sits at the boundary between software and
14+
another field: medicine, robotics, machine learning, or finance.
15+
</p>
16+
<p>
17+
I care about building things that are genuinely useful — tools that
18+
solve real problems rather than impressive demos. That usually means
19+
spending as much time understanding the domain as writing the code.
20+
</p>
21+
<p>
22+
When I'm not writing code, you'll find me reading about whatever
23+
rabbit hole I've fallen into, tinkering with hardware projects, or
24+
trying to explain something I just learned to someone who didn't ask.
25+
</p>
26+
</div>
27+
</section>
28+
29+
<section>
30+
<h2>Interests</h2>
31+
<div class="interests-grid">
32+
<div>
33+
<h5>Medicine &amp; Health Tech</h5>
34+
<p class="text-sm">
35+
Clinical decision support, medical education tools, health data
36+
platforms.
37+
</p>
38+
</div>
39+
<div>
40+
<h5>Machine Learning</h5>
41+
<p class="text-sm">
42+
Applied ML — prediction models, NLP, and data pipelines that solve
43+
specific problems.
44+
</p>
45+
</div>
46+
<div>
47+
<h5>Robotics</h5>
48+
<p class="text-sm">
49+
Embedded systems, control software, and bridging the gap between
50+
hardware and software.
51+
</p>
52+
</div>
53+
<div>
54+
<h5>Finance</h5>
55+
<p class="text-sm">
56+
Quantitative analysis, algorithmic strategies, and financial
57+
modeling tools.
58+
</p>
59+
</div>
60+
</div>
61+
</section>
62+
63+
<section>
64+
<h2>Get in Touch</h2>
65+
<p>
66+
Want to collaborate or just say hello? Reach out through any of the
67+
channels below.
68+
</p>
69+
<div class="flex flex-wrap gap-4 mt-4">
70+
{
71+
Object.entries(SOCIAL_LINKS).map(([key, value]) => {
72+
if (!value) return null;
73+
return (
74+
<a
75+
href={value}
76+
rel="noopener noreferrer"
77+
target="_blank"
78+
aria-label={key}
79+
title={key}
80+
class="inline-flex items-center gap-2 text-secondary text-sm no-underline hover:text-primary transition-colors"
81+
>
82+
<Fragment
83+
set:html={getSizedIcon(key as keyof typeof icons, 18) ?? ""}
84+
/>
85+
<span>{key}</span>
86+
</a>
87+
);
88+
})
89+
}
90+
{
91+
BLOG_CONFIG.email && (
92+
<a
93+
href={BLOG_CONFIG.email}
94+
aria-label="Email"
95+
title="Email"
96+
class="inline-flex items-center gap-2 text-secondary text-sm no-underline hover:text-primary transition-colors"
97+
>
98+
<Fragment set:html={getSizedIcon("Email", 18)} />
99+
<span>Email</span>
100+
</a>
101+
)
102+
}
103+
</div>
104+
</section>
105+
</Layout>
106+
107+
<style>
108+
.interests-grid {
109+
display: grid;
110+
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
111+
gap: 1.5rem;
112+
}
113+
</style>

‎src/pages/index.astro‎

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,27 @@
11
---
22
import Layout from "../layouts/Layout.astro";
3-
import FormattedDate from "../components/FormattedDate.astro";
4-
import { SITE_DESCRIPTION, SOCIAL_LINKS, BLOG_CONFIG } from "../consts";
3+
import { SITE_DESCRIPTION, SOCIAL_LINKS, BLOG_CONFIG, DOMAINS } from "../consts";
54
import icons, { getSizedIcon } from "../assets/icons";
65
import { getCollection } from "astro:content";
76
import { generateURL } from "../utils";
7+
import FormattedDate from "../components/FormattedDate.astro";
88
99
const posts = (await getCollection("medical")).sort(
1010
(a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf()
1111
);
1212
---
1313

1414
<Layout>
15-
<section>
15+
<!-- Hero -->
16+
<section class="hero">
17+
<h1>Cody Nguyen</h1>
1618
<p class="text-lg leading-relaxed max-w-prose">
17-
I like working on problems that sit between fields — software, medicine,
18-
robotics, finance. Mostly building things and figuring out what's useful.
19+
{SITE_DESCRIPTION}
20+
</p>
21+
<p class="leading-relaxed max-w-prose">
22+
I like working on problems that sit between fields — finding where
23+
software can unlock something useful in medicine, robotics, ML, or
24+
finance.
1925
</p>
2026
<div class="flex flex-wrap gap-4 mt-4">
2127
{
@@ -54,24 +60,49 @@ const posts = (await getCollection("medical")).sort(
5460
</div>
5561
</section>
5662

63+
<!-- Domains -->
64+
<section>
65+
<h2>What I Work On</h2>
66+
<div class="domain-grid">
67+
{
68+
DOMAINS.map(domain => (
69+
<a
70+
href={generateURL(`/projects#${domain.slug}`)}
71+
class="card group no-underline hover:no-underline"
72+
>
73+
<h4 class="mb-2 group-hover:text-secondary transition-colors">
74+
{domain.name}
75+
</h4>
76+
<p class="text-sm mb-0">{domain.description}</p>
77+
</a>
78+
))
79+
}
80+
</div>
81+
</section>
82+
83+
<!-- Recent Work -->
5784
{
5885
posts.length > 0 && (
5986
<section>
60-
<h3>Projects</h3>
87+
<div class="flex items-baseline justify-between mb-4">
88+
<h2 class="mb-0">Recent Projects</h2>
89+
<a
90+
href={generateURL("/projects")}
91+
class="text-sm text-secondary no-underline hover:underline"
92+
>
93+
View all &rarr;
94+
</a>
95+
</div>
6196
<ul class="blog-posts">
62-
{posts.map(post => (
97+
{posts.slice(0, 5).map(post => (
6398
<li>
6499
<span>
65100
<i>
66101
<FormattedDate date={post.data.pubDate} />
67102
</i>
68103
</span>
69104
<a
70-
href={generateURL(
71-
`/medical/${post.id}/`,
72-
undefined,
73-
true
74-
)}
105+
href={generateURL(`/medical/${post.id}/`, undefined, true)}
75106
>
76107
{post.data.title}
77108
</a>
@@ -82,3 +113,14 @@ const posts = (await getCollection("medical")).sort(
82113
)
83114
}
84115
</Layout>
116+
117+
<style>
118+
.hero h1 {
119+
margin-bottom: 0.5rem;
120+
}
121+
.domain-grid {
122+
display: grid;
123+
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
124+
gap: 1rem;
125+
}
126+
</style>

‎src/pages/projects/index.astro‎

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
---
2+
import Layout from "../../layouts/Layout.astro";
3+
import { getCollection } from "astro:content";
4+
import { DOMAINS } from "../../consts";
5+
import FormattedDate from "../../components/FormattedDate.astro";
6+
import { generateURL } from "../../utils";
7+
8+
const posts = (await getCollection("medical")).sort(
9+
(a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf()
10+
);
11+
12+
const projectsByDomain: Record<string, typeof posts> = {
13+
medical: posts,
14+
ml: [],
15+
robotics: [],
16+
finance: [],
17+
};
18+
---
19+
20+
<Layout title="Projects — Cody Nguyen" description="Projects across medicine, ML, robotics, and finance.">
21+
<section>
22+
<h1>Projects</h1>
23+
<p class="max-w-prose">
24+
A collection of things I've built or am building — organized by the
25+
domain they live in.
26+
</p>
27+
</section>
28+
29+
{
30+
DOMAINS.map(domain => {
31+
const items = projectsByDomain[domain.slug] || [];
32+
return (
33+
<section id={domain.slug}>
34+
<h2>{domain.name}</h2>
35+
<p class="text-sm mb-4">{domain.description}</p>
36+
{items.length > 0 ? (
37+
<ul class="blog-posts">
38+
{items.map(post => (
39+
<li>
40+
<span>
41+
<i>
42+
<FormattedDate date={post.data.pubDate} />
43+
</i>
44+
</span>
45+
<a
46+
href={generateURL(
47+
`/medical/${post.id}/`,
48+
undefined,
49+
true
50+
)}
51+
>
52+
{post.data.title}
53+
</a>
54+
</li>
55+
))}
56+
</ul>
57+
) : (
58+
<p class="text-sm italic text-gray/60">
59+
Projects coming soon.
60+
</p>
61+
)}
62+
</section>
63+
);
64+
})
65+
}
66+
</Layout>

0 commit comments

Comments
 (0)