Reorder homepage sections (journey above projects), refine component styles, update copy and data across projects, timeline, and homelab. Reviewed-on: #5
This commit was merged in pull request #5.
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
export default function Footer() {
|
||||
return (
|
||||
<footer className="border-t border-[var(--color-border)] py-5 mt-8">
|
||||
<div className="px-8 flex items-center justify-between">
|
||||
<footer className="border-t border-[var(--color-border)] py-1lh mt-2lh">
|
||||
<div className="px-4ch flex items-center justify-between">
|
||||
<span className="font-mono text-sm text-[var(--color-text-dim)]">
|
||||
© {new Date().getFullYear()} Tyler Koenig
|
||||
</span>
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex items-center gap-2ch">
|
||||
<a
|
||||
href="https://github.com/lerko96"
|
||||
target="_blank"
|
||||
@@ -15,6 +15,15 @@ export default function Footer() {
|
||||
>
|
||||
[github]
|
||||
</a>
|
||||
<a
|
||||
href="https://gitea.lerkolabs.com/lerko"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
aria-label="Gitea"
|
||||
className="font-mono text-sm text-[var(--color-text-label)] hover:text-[var(--color-text)]"
|
||||
>
|
||||
[gitea]
|
||||
</a>
|
||||
<a
|
||||
href="https://www.linkedin.com/in/tyler-koenig"
|
||||
target="_blank"
|
||||
@@ -24,6 +33,13 @@ export default function Footer() {
|
||||
>
|
||||
[linkedin]
|
||||
</a>
|
||||
<a
|
||||
href="mailto:tyler@lerkolabs.com"
|
||||
aria-label="Email"
|
||||
className="font-mono text-sm text-[var(--color-text-label)] hover:text-[var(--color-text)]"
|
||||
>
|
||||
[email]
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
+28
-9
@@ -1,10 +1,15 @@
|
||||
export default function Hero() {
|
||||
return (
|
||||
<section className="mb-16">
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="flex flex-col gap-1ch">
|
||||
<div>
|
||||
<p className="font-mono text-base font-bold text-[var(--color-text)]">
|
||||
<span className="text-[var(--color-accent-green)] select-none mr-2" aria-hidden="true">❯</span>
|
||||
<p className="font-mono text-sm font-bold text-[var(--color-text)]">
|
||||
<span
|
||||
className="text-[var(--color-accent-green)] select-none mr-1ch"
|
||||
aria-hidden="true"
|
||||
>
|
||||
❯
|
||||
</span>
|
||||
tyler koenig
|
||||
</p>
|
||||
<p className="font-mono text-sm text-[var(--color-text-label)] mt-0.5">
|
||||
@@ -12,15 +17,20 @@ export default function Hero() {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<p className="font-mono text-sm text-[var(--color-text)] leading-relaxed max-w-lg opacity-70">
|
||||
Security operations and self-hosted infrastructure. Homelab runs 37
|
||||
<p className="font-mono text-sm text-[var(--color-text)] leading-relaxed opacity-70">
|
||||
Homelab runs 30+
|
||||
services across segmented VLANs — pfSense, Authentik SSO, full
|
||||
observability stack. Write software too: mobile apps, Go backends,
|
||||
open protocols. Daily drivers, all of it.{' '}
|
||||
<span className="animate-cursor text-[var(--color-accent-green)]" aria-hidden="true">█</span>
|
||||
open protocols. Daily drivers, all of it.{" "}
|
||||
<span
|
||||
className="animate-cursor text-[var(--color-accent-green)]"
|
||||
aria-hidden="true"
|
||||
>
|
||||
█
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<div className="flex flex-wrap items-center gap-x-5 gap-y-1">
|
||||
<div className="flex flex-wrap items-center gap-x-1ch gap-y-half-lh">
|
||||
<span className="font-mono text-sm text-[var(--color-accent-green)]">
|
||||
● available
|
||||
</span>
|
||||
@@ -33,6 +43,15 @@ export default function Hero() {
|
||||
>
|
||||
[github]
|
||||
</a>
|
||||
<a
|
||||
href="https://gitea.lerkolabs.com/lerko"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
aria-label="Gitea"
|
||||
className="font-mono text-sm text-[var(--color-text-label)] hover:text-[var(--color-text)]"
|
||||
>
|
||||
[gitea]
|
||||
</a>
|
||||
<a
|
||||
href="https://www.linkedin.com/in/tyler-koenig"
|
||||
target="_blank"
|
||||
@@ -43,7 +62,7 @@ export default function Hero() {
|
||||
[linkedin]
|
||||
</a>
|
||||
<a
|
||||
href="mailto:tylerkoenig96@gmail.com"
|
||||
href="mailto:tyler@lerkolabs.com"
|
||||
aria-label="Email"
|
||||
className="font-mono text-sm text-[var(--color-text-label)] hover:text-[var(--color-text)]"
|
||||
>
|
||||
|
||||
@@ -15,7 +15,7 @@ export default function Nav() {
|
||||
const { isDark, toggle } = useTheme();
|
||||
return (
|
||||
<header className="sticky top-0 z-50 bg-[var(--color-surface)] border-b border-[var(--color-border)]">
|
||||
<nav className="max-w-[740px] mx-auto px-8 h-11 flex items-center justify-between">
|
||||
<nav className="max-w-[740px] mx-auto px-4ch h-11 flex items-center justify-between">
|
||||
<Link
|
||||
href="/"
|
||||
className="font-mono text-sm font-bold text-[var(--color-text)] hover:text-[var(--color-text-label)]"
|
||||
@@ -23,7 +23,7 @@ export default function Nav() {
|
||||
~/
|
||||
</Link>
|
||||
|
||||
<ul className="flex items-center gap-6">
|
||||
<ul className="flex items-center gap-2ch">
|
||||
{links.map(({ href, label }) => {
|
||||
const active =
|
||||
pathname === href || pathname === href.replace(/\/$/, "");
|
||||
|
||||
@@ -6,8 +6,8 @@ type Props = {
|
||||
|
||||
export default function ProjectCard({ project }: Props) {
|
||||
return (
|
||||
<article className="border border-[var(--color-border)] bg-[var(--color-surface)] flex flex-col gap-4 p-5 hover:bg-[var(--color-surface-raised)]">
|
||||
<div className="flex items-start justify-between gap-3">
|
||||
<article className="border border-[var(--color-border)] bg-[var(--color-surface)] flex flex-col gap-1lh p-2ch hover:bg-[var(--color-surface-raised)]">
|
||||
<div className="flex items-start justify-between gap-1ch">
|
||||
<a
|
||||
href={project.githubUrl}
|
||||
target="_blank"
|
||||
@@ -16,7 +16,7 @@ export default function ProjectCard({ project }: Props) {
|
||||
>
|
||||
{project.title}
|
||||
</a>
|
||||
<div className="flex items-center gap-3 shrink-0">
|
||||
<div className="flex items-center gap-1ch shrink-0">
|
||||
{project.stats && (
|
||||
<span className="font-mono text-sm text-[var(--color-text-dim)]">
|
||||
{project.stats}
|
||||
@@ -46,7 +46,7 @@ export default function ProjectCard({ project }: Props) {
|
||||
</div>
|
||||
|
||||
{project.statusBadge && (
|
||||
<span className="font-mono text-xs text-[var(--color-accent-amber,#d4a027)] border border-[var(--color-accent-amber,#d4a027)] px-1.5 py-0.5 w-fit opacity-80">
|
||||
<span className="font-mono text-sm text-[var(--color-accent-amber,#d4a027)] border border-[var(--color-accent-amber,#d4a027)] px-1ch py-0.5 w-fit opacity-80">
|
||||
{project.statusBadge}
|
||||
</span>
|
||||
)}
|
||||
@@ -55,9 +55,9 @@ export default function ProjectCard({ project }: Props) {
|
||||
{project.description}
|
||||
</p>
|
||||
|
||||
<div className="flex flex-wrap gap-x-3 gap-y-1 mt-1">
|
||||
<div className="flex flex-wrap gap-x-1ch gap-y-half-lh mt-half-lh">
|
||||
{project.tags.map((tag) => (
|
||||
<span key={tag} className="font-mono text-xs text-[var(--color-text-dim)]">
|
||||
<span key={tag} className="font-mono text-sm text-[var(--color-text-dim)]">
|
||||
{tag}
|
||||
</span>
|
||||
))}
|
||||
|
||||
+13
-13
@@ -1,6 +1,18 @@
|
||||
import Widget from "@/components/Widget";
|
||||
|
||||
const skillGroups = [
|
||||
{
|
||||
label: "Infrastructure",
|
||||
skills: ["Proxmox", "pfSense", "VLANs", "WireGuard", "Linux", "Caddy"],
|
||||
},
|
||||
{
|
||||
label: "Desktop & Tools",
|
||||
skills: ["Git", "Docker", "TDD", "Node.js", "REST APIs", ],
|
||||
},
|
||||
{
|
||||
label: "Practices",
|
||||
skills: ["Agile / Scrum", "Relational Databases", "Self-hosting"],
|
||||
},
|
||||
{
|
||||
label: "Languages",
|
||||
skills: ["Go", "JavaScript", "TypeScript", "HTML", "CSS"],
|
||||
@@ -9,18 +21,6 @@ const skillGroups = [
|
||||
label: "Frontend",
|
||||
skills: ["React", "React Native", "Expo", "Next.js", "Three.js"],
|
||||
},
|
||||
{
|
||||
label: "Desktop & Tools",
|
||||
skills: ["Electron", "Node.js", "REST APIs", "Git", "Docker", "TDD"],
|
||||
},
|
||||
{
|
||||
label: "Infrastructure",
|
||||
skills: ["Proxmox", "pfSense", "VLANs", "WireGuard", "Linux", "Caddy"],
|
||||
},
|
||||
{
|
||||
label: "Practices",
|
||||
skills: ["Agile / Scrum", "Relational Databases", "Self-hosting"],
|
||||
},
|
||||
];
|
||||
|
||||
const totalCount = skillGroups.reduce((n, g) => n + g.skills.length, 0);
|
||||
@@ -32,7 +32,7 @@ export default function Skills() {
|
||||
{skillGroups.map(({ label, skills }) => (
|
||||
<div
|
||||
key={label}
|
||||
className="flex flex-col xs:flex-row gap-1 xs:gap-6 py-3"
|
||||
className="flex flex-col xs:flex-row gap-1ch xs:gap-2ch py-half-lh"
|
||||
>
|
||||
<span className="font-mono text-sm text-[var(--color-text-dim)] w-28 shrink-0">
|
||||
{label}
|
||||
|
||||
@@ -54,9 +54,9 @@ export default function Timeline() {
|
||||
|
||||
return (
|
||||
<Widget title="tyler/journey">
|
||||
<ol ref={listRef} className="relative border-l border-[var(--color-border)] ml-1.5 flex flex-col gap-0">
|
||||
<ol ref={listRef} className="relative border-l border-[var(--color-border)] ml-[2px] flex flex-col gap-0">
|
||||
{timeline.map((entry, i) => (
|
||||
<li key={i} data-tl-entry className="pl-6 pb-8 last:pb-0 relative">
|
||||
<li key={i} data-tl-entry className="pl-[3ch] pb-2lh last:pb-0 relative">
|
||||
{/* Spine dot */}
|
||||
<span
|
||||
className="absolute -left-[7px] top-[3px] w-3 h-3 rounded-full border border-[var(--color-bg)] shrink-0"
|
||||
@@ -65,10 +65,10 @@ export default function Timeline() {
|
||||
/>
|
||||
|
||||
{/* Date + type badge */}
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<div className="flex items-center gap-1ch mb-half-lh">
|
||||
<span className="font-mono text-sm text-[var(--color-text-dim)]">{entry.date}</span>
|
||||
<span
|
||||
className="font-mono text-[10px] uppercase tracking-wider px-1 rounded-sm border"
|
||||
className="font-mono text-sm px-1 border"
|
||||
style={{
|
||||
color: typeColor[entry.type],
|
||||
borderColor: typeColor[entry.type],
|
||||
@@ -80,20 +80,20 @@ export default function Timeline() {
|
||||
</div>
|
||||
|
||||
{/* Title */}
|
||||
<p className="font-mono text-sm font-semibold text-[var(--color-text)] mb-1">
|
||||
<p className="font-mono text-sm font-semibold text-[var(--color-text)] mb-half-lh">
|
||||
{entry.title}
|
||||
</p>
|
||||
|
||||
{/* Description */}
|
||||
<p className="font-mono text-sm text-[var(--color-text)] opacity-70 leading-relaxed mb-2">
|
||||
<p className="font-mono text-sm text-[var(--color-text)] opacity-70 leading-relaxed mb-half-lh">
|
||||
{entry.description}
|
||||
</p>
|
||||
|
||||
{/* Tags */}
|
||||
{entry.tags && entry.tags.length > 0 && (
|
||||
<div className="flex flex-wrap gap-x-3 gap-y-1">
|
||||
<div className="flex flex-wrap gap-x-1ch gap-y-half-lh">
|
||||
{entry.tags.map((tag) => (
|
||||
<span key={tag} className="font-mono text-xs text-[var(--color-text-dim)]">
|
||||
<span key={tag} className="font-mono text-sm text-[var(--color-text-dim)]">
|
||||
{tag}
|
||||
</span>
|
||||
))}
|
||||
|
||||
@@ -20,17 +20,17 @@ export default function Widget({
|
||||
const name = slashIdx >= 0 ? title.slice(slashIdx + 1) : title;
|
||||
|
||||
return (
|
||||
<Tag className={`mb-16 ${className ?? ""}`}>
|
||||
<div className="flex items-center gap-2 mb-8">
|
||||
<Tag className={`mb-4lh ${className ?? ""}`}>
|
||||
<div className="flex items-center gap-1ch mb-2lh">
|
||||
{prefix && (
|
||||
<span className="font-mono text-sm text-[var(--color-text-dim)] select-none">{prefix}</span>
|
||||
)}
|
||||
<span className="font-mono text-sm font-semibold text-[var(--color-text)]">{name}</span>
|
||||
{badge !== undefined && (
|
||||
<span className="font-mono text-xs text-[var(--color-text-dim)]">[{badge}]</span>
|
||||
<span className="font-mono text-sm text-[var(--color-text-dim)]">[{badge}]</span>
|
||||
)}
|
||||
{meta && (
|
||||
<span className="font-mono text-xs text-[var(--color-text-dim)] ml-1">— {meta}</span>
|
||||
<span className="font-mono text-sm text-[var(--color-text-dim)]">— {meta}</span>
|
||||
)}
|
||||
</div>
|
||||
{children}
|
||||
|
||||
Reference in New Issue
Block a user