diff --git a/public/images/ttrpg-dice.jpg b/public/images/ttrpg-dice.jpg index c968e41..930364a 100644 Binary files a/public/images/ttrpg-dice.jpg and b/public/images/ttrpg-dice.jpg differ diff --git a/src/components/layout/SplitTransition.astro b/src/components/layout/SplitTransition.astro index f3f204d..45e1823 100644 --- a/src/components/layout/SplitTransition.astro +++ b/src/components/layout/SplitTransition.astro @@ -9,7 +9,7 @@ * Left -> Professional (polished tone) * Right -> Interests (warm tone) */ -import Icon from '@components/Icon.astro'; +import Icon from "@components/Icon.astro"; interface Props { /** Optional override copy for each side. Defaults to spec phrasing. */ @@ -20,10 +20,10 @@ interface Props { } const { - leftHref = '/professional', - rightHref = '/interests', - leftText = 'See where I apply that curiosity professionally', - rightText = 'See where it takes me outside of work', + leftHref = "/professional", + rightHref = "/interests", + leftText = "See where I apply that curiosity professionally", + rightText = "See where it takes me outside of work", } = Astro.props; --- @@ -32,15 +32,25 @@ const { href={leftHref} class="card card-interactive group flex items-center justify-between gap-4" > + - + The professional wing - + {leftText} - - + The personal wing - + {rightText} - + diff --git a/src/components/mystic/CelestialFrame.astro b/src/components/mystic/CelestialFrame.astro index bf74cc3..4c99aae 100644 --- a/src/components/mystic/CelestialFrame.astro +++ b/src/components/mystic/CelestialFrame.astro @@ -17,67 +17,65 @@ * * ... */ -import StarBurst from './StarBurst.astro'; +import StarBurst from "./StarBurst.astro"; interface Props { class?: string; /** Corner rounding. */ - rounded?: 'lg' | 'xl' | '2xl' | 'none'; + rounded?: "lg" | "xl" | "2xl" | "none"; /** Stroke emphasis on the frame border. */ - emphasis?: 'subtle' | 'strong'; + emphasis?: "subtle" | "strong"; } const { - class: className = '', - rounded = '2xl', - emphasis = 'subtle', + class: className = "", + rounded = "2xl", + emphasis = "subtle", } = Astro.props; const radius = { - none: 'rounded-none', - lg: 'rounded-lg', - xl: 'rounded-xl', - '2xl': 'rounded-2xl', + none: "rounded-none", + lg: "rounded-lg", + xl: "rounded-xl", + "2xl": "rounded-2xl", }[rounded]; -const borderStyle = - emphasis === 'strong' - ? 'border-2' - : 'border'; +const borderStyle = emphasis === "strong" ? "border-2" : "border"; --- +
{/* Faint sacred-geometry tint behind the image. */} {/* The media itself, clipped to the frame. */} -
+
{/* Corner star-burst flourishes (sit on the border corners). */}
diff --git a/src/components/mystic/CelestialImage.astro b/src/components/mystic/CelestialImage.astro index 6e062a0..bd3d80c 100644 --- a/src/components/mystic/CelestialImage.astro +++ b/src/components/mystic/CelestialImage.astro @@ -14,8 +14,8 @@ * * */ -import CelestialFrame from './CelestialFrame.astro'; -import StarField from './StarField.astro'; +import CelestialFrame from "./CelestialFrame.astro"; +import StarField from "./StarField.astro"; interface Props { src?: string; @@ -23,8 +23,8 @@ interface Props { /** Aspect ratio, e.g. "4/3", "3/4", "16/9". */ aspect?: string; /** Image fit. object-cover by default. */ - fit?: 'cover' | 'contain'; - rounded?: 'lg' | 'xl' | '2xl' | 'none'; + fit?: "cover" | "contain"; + rounded?: "lg" | "xl" | "2xl" | "none"; class?: string; /** When true, render only the frame + placeholder (no ). */ placeholder?: boolean; @@ -33,61 +33,68 @@ interface Props { const { src, alt, - aspect = '4/3', - fit = 'cover', - rounded = '2xl', - class: className = '', + aspect = "4/3", + fit = "cover", + rounded = "2xl", + class: className = "", placeholder = false, } = Astro.props; const showPlaceholder = placeholder || !src; -const objectFit = fit === 'contain' ? 'object-contain' : 'object-cover'; +const objectFit = fit === "contain" ? "object-contain" : "object-cover"; --- - + +
- {showPlaceholder ? ( - // Themed SVG placeholder: starfield + moon glyph over the surface tone. -
- + { + showPlaceholder ? ( + // Themed SVG placeholder: starfield + moon glyph over the surface tone. - - {alt} - -
- ) : ( - {alt} - )} + ) : ( + {alt} + ) + }
diff --git a/src/lib/site.ts b/src/lib/site.ts index e7b3f36..a927366 100644 --- a/src/lib/site.ts +++ b/src/lib/site.ts @@ -63,22 +63,22 @@ export const allNavItems: NavItem[] = navGroups.flatMap((g) => g.items); export const socials = { github: { label: 'GitHub', - handle: '[Greg to fill]', - href: 'https://github.com/', + handle: 'Patiun', + href: 'https://github.com/patiun', icon: 'github', }, linkedin: { label: 'LinkedIn', - handle: '[Greg to fill]', - href: 'https://www.linkedin.com/', + handle: 'Gregory Kilmer', + href: 'https://www.linkedin.com/in/gregory-kilmer-36646bb5/', icon: 'linkedin', }, - discord: { + /*discord: { label: 'Discord', handle: '[Greg to fill]', href: '#', icon: 'discord', - }, + },*/ } as const; /** Spec footer microcopy. */ diff --git a/src/pages/about.astro b/src/pages/about.astro index e674305..da6a31e 100644 --- a/src/pages/about.astro +++ b/src/pages/about.astro @@ -7,23 +7,29 @@ * quick facts (spec emojis mapped to mdi icons). Ends with the SplitTransition * fork into Professional / Interests. */ -import BaseLayout from '@layouts/BaseLayout.astro'; -import Reveal from '@components/motion/Reveal.astro'; -import Icon from '@components/Icon.astro'; -import SectionHeader from '@components/layout/SectionHeader.astro'; -import SplitTransition from '@components/layout/SplitTransition.astro'; -import CelestialImage from '@components/mystic/CelestialImage.astro'; -import AlchemicalDivider from '@components/mystic/AlchemicalDivider.astro'; -import ConstellationField from '@components/mystic/ConstellationField.tsx'; +import BaseLayout from "@layouts/BaseLayout.astro"; +import Reveal from "@components/motion/Reveal.astro"; +import Icon from "@components/Icon.astro"; +import SectionHeader from "@components/layout/SectionHeader.astro"; +import SplitTransition from "@components/layout/SplitTransition.astro"; +import CelestialImage from "@components/mystic/CelestialImage.astro"; +import AlchemicalDivider from "@components/mystic/AlchemicalDivider.astro"; +import ConstellationField from "@components/mystic/ConstellationField.tsx"; // Spec "Quick Facts", emojis -> mdi icons. const quickFacts = [ - { icon: 'map-marker', text: 'Philadelphia, PA' }, - { icon: 'briefcase', text: 'Software Developer at Implico Inc.' }, - { icon: 'dog', text: 'Dog dad to Kashi the mini dachshund' }, - { icon: 'dice-multiple', text: 'Running D&D & Daggerheart campaigns' }, - { icon: 'book-open-variant', text: 'Currently reading: Heir of Fire by Sarah J. Maas' }, - { icon: 'tea', text: 'Fueled by loose-leaf Chinese tea and Mountain Dew' }, + { icon: "map-marker", text: "Philadelphia, PA" }, + { + icon: "briefcase", + text: "BTP, Cloud, and Mobile App Lead at Implico Inc.", + }, + { icon: "dog", text: "Dog dad to Kashi the mini dachshund" }, + { icon: "dice-multiple", text: "Running D&D & Daggerheart campaigns" }, + { + icon: "book-open-variant", + text: "Currently reading: Heir of Fire by Sarah J. Maas", + }, + { icon: "tea", text: "Fueled by loose-leaf Chinese tea and Mountain Dew" }, ]; --- @@ -33,7 +39,12 @@ const quickFacts = [ >
- +
- I am Greg — a software developer based in Philadelphia who spends - his free time running tabletop RPGs, making resin dice, 3D printing - miniatures and props, and reading his way through fantasy series at an - alarming rate. I live with my partner Krystina, our mini dachshund + I am Greg: a software developer based in Philadelphia who spends his + free time running tabletop RPGs, making resin dice and custom cards, 3D + printing anything I can, and reading his way through fantasy series at + an alarming rate. I live with my partner Krystina, our mini dachshund Kashi, and more board games than any reasonable apartment should hold.

@@ -66,22 +77,25 @@ const quickFacts = [

The longer arc

-
+

- I grew up surrounded by books and games, and not much has changed. - Technology pulled me into a career building cloud and mobile - applications, but I never stopped collecting dice, designing - campaigns, or losing weekends to Sanderson rereads. I am currently - expanding into SAP's Business Technology Platform, exploring AI and - machine learning, and trying to convince my group that yes, we - can fit one more board game into game night. + I grew up loving books and games, and not much has changed. Technology + pulled me into a career building cloud and mobile applications, but I + never stopped collecting dice, designing campaigns, or losing weekends + to Sanderson reads. I am currently expanding into SAP's Business + Technology Platform, exploring AI and machine learning, and trying to + convince my group that yes, we + can fit one more board game into game night.

- I believe the best work happens when curiosity isn't compartmentalized. - The same system-thinking that makes a good developer makes a good - gamemaster. The patience that produces a clean resin cast is the same - patience that debugs a stubborn deployment. This site is where I don't - have to pretend those things are separate. + I believe the best work happens when curiosity isn't + compartmentalized. The same system-thinking that makes a good + developer makes a good gamemaster. The patience that produces a clean + resin cast is the same patience that debugs a stubborn deployment. + This site is where I don't have to pretend those things are separate.

@@ -97,16 +111,28 @@ const quickFacts = [ @@ -115,7 +141,10 @@ const quickFacts = [
- +
diff --git a/src/pages/contact.astro b/src/pages/contact.astro index 885c3de..9658e2c 100644 --- a/src/pages/contact.astro +++ b/src/pages/contact.astro @@ -10,24 +10,48 @@ * Spec items Greg still needs to fill (email, Discord, etc.) appear as * Placeholder slots. */ -import BaseLayout from '@layouts/BaseLayout.astro'; -import Reveal from '@components/motion/Reveal.astro'; -import Icon from '@components/Icon.astro'; -import SectionHeader from '@components/layout/SectionHeader.astro'; -import Placeholder from '@components/layout/Placeholder.astro'; -import ContactForm from '@components/professional/ContactForm.tsx'; +import BaseLayout from "@layouts/BaseLayout.astro"; +import Reveal from "@components/motion/Reveal.astro"; +import Icon from "@components/Icon.astro"; +import SectionHeader from "@components/layout/SectionHeader.astro"; +import Placeholder from "@components/layout/Placeholder.astro"; +import ContactForm from "@components/professional/ContactForm.tsx"; const professional = [ - { icon: 'email-outline', label: 'Email', hint: 'Greg professional email address.' }, - { icon: 'linkedin', label: 'LinkedIn', hint: 'LinkedIn profile URL.' }, - { icon: 'github', label: 'GitHub', hint: 'GitHub profile URL.' }, + { + icon: "email-outline", + label: "Email", + hint: 'Kilmer.GM@Gmail.com', + }, + { + icon: "linkedin", + label: "LinkedIn", + hint: 'LinkedIn', + }, + { + icon: "github", + label: "GitHub", + hint: 'GitHub', + }, ]; const social = [ - { icon: 'discord', label: 'Discord', hint: 'Handle or invite link.' }, - { icon: 'twitter', label: 'Twitter / X', hint: 'Profile link, if applicable.' }, - { icon: 'paw', label: 'Pokémon', hint: 'Showdown or Trainer name, if shared.' }, - { icon: 'cube-outline', label: 'Foundry VTT', hint: 'Server link, if public.' }, + { icon: "discord", label: "Discord", hint: "Handle or invite link." }, + { + icon: "twitter", + label: "Twitter / X", + hint: "Profile link, if applicable.", + }, + { + icon: "paw", + label: "Pokémon", + hint: "Showdown or Trainer name, if shared.", + }, + { + icon: "cube-outline", + label: "Foundry VTT", + hint: "Server link, if public.", + }, ]; --- @@ -52,52 +76,81 @@ const social = [ {/* Professional */}
-

+

Professional

    - {professional.map((item) => ( -
  • - - - {item.label} - {item.hint} - -
  • - ))} + { + professional.map((item) => ( +
  • + + + + {item.label} + + + {item.hint} + + +
  • + )) + }
-
{/* Social / personal */}
-

+

Personal / Social

    - {social.map((item) => ( -
  • - - - {item.label} - {item.hint} - -
  • - ))} + { + social.map((item) => ( +
  • + + + + {item.label} + + + {item.hint} + + +
  • + )) + }
@@ -108,7 +161,9 @@ const social = [ class="rounded-xl border-l-2 p-4 text-sm" style="border-color: var(--color-accent); background: color-mix(in srgb, var(--color-accent) 8%, transparent); color: var(--color-text-muted);" > - Availability: Open to opportunities in cloud development, SAP BTP, and technical leadership. + Availability: Open to + opportunities in AI/ML, app and cloud development, SAP BTP, and technical + leadership.

@@ -117,7 +172,9 @@ const social = [
-

Send a message

+

+ Send a message +

Prefer a form? Drop a note and it will land in my inbox.

@@ -134,7 +191,8 @@ const social = [ class="mx-auto max-w-2xl border-l-2 pl-5 text-center font-sans text-lg italic" style="border-color: var(--color-accent); color: var(--color-text-muted);" > - Whether you want to talk cloud architecture, debate the best Gundam series, or need a fourth for game night, reach out. + Whether you want to talk cloud architecture, debate the best Gundam + series, or need a fourth for game night, reach out.
diff --git a/src/pages/index.astro b/src/pages/index.astro index 2cf1e8f..1dd90bf 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -1,84 +1,94 @@ --- /** -* index.astro — Home (Landing) -* --------------------------------------------------------------------------- -* First impression page. Full-width hero with the animated background, the spec -* headline/subheadline/intro paragraph, and the two CTA buttons. Below the fold -* is the 3-column snapshot grid (Professional, Tabletop, Making) plus the wider -* Reading & Media strip. All copy is verbatim from the spec. -* -* Emojis from the spec table are rendered as mdi icons (no emojis per spec). -*/ -import BaseLayout from '@layouts/BaseLayout.astro'; -import Reveal from '@components/motion/Reveal.astro'; -import AnimatedBackground from '@components/hero/AnimatedBackground.tsx'; -import Icon from '@components/Icon.astro'; -import SectionHeader from '@components/layout/SectionHeader.astro'; -import CelestialImage from '@components/mystic/CelestialImage.astro'; -import AlchemicalDivider from '@components/mystic/AlchemicalDivider.astro'; -import SacredGeometry from '@components/mystic/SacredGeometry.astro'; -import ConstellationField from '@components/mystic/ConstellationField.tsx'; + * index.astro — Home (Landing) + * --------------------------------------------------------------------------- + * First impression page. Full-width hero with the animated background, the spec + * headline/subheadline/intro paragraph, and the two CTA buttons. Below the fold + * is the 3-column snapshot grid (Professional, Tabletop, Making) plus the wider + * Reading & Media strip. All copy is verbatim from the spec. + * + * Emojis from the spec table are rendered as mdi icons (no emojis per spec). + */ +import BaseLayout from "@layouts/BaseLayout.astro"; +import Reveal from "@components/motion/Reveal.astro"; +import AnimatedBackground from "@components/hero/AnimatedBackground.tsx"; +import Icon from "@components/Icon.astro"; +import SectionHeader from "@components/layout/SectionHeader.astro"; +import CelestialImage from "@components/mystic/CelestialImage.astro"; +import AlchemicalDivider from "@components/mystic/AlchemicalDivider.astro"; +import SacredGeometry from "@components/mystic/SacredGeometry.astro"; +import ConstellationField from "@components/mystic/ConstellationField.tsx"; // Snapshot grid content from the spec, with spec emojis mapped to mdi icons. // Each card now carries a vibe-matched stock image (swap for real photos later). const cards = [ -{ -icon: 'briefcase', -title: 'Professional', -copy: 'From SAP-adjacent cloud apps to full-stack mobile — a decade of building software that businesses actually use.', -href: '/professional', -image: '/images/pro-workspace.jpg', -alt: 'Developer workspace with code on screen', -}, -{ -icon: 'dice-multiple', -title: 'Tabletop', -copy: "Currently running two campaigns in Foundry VTT and playtesting MCDM's Crows. Always rolling dice.", -href: '/interests/ttrpgs', -image: '/images/ttrpg-dice.jpg', -alt: 'Polyhedral dice on a dark surface', -}, -{ -icon: 'palette', -title: 'Making', -copy: 'Resin dice, 3D prints, and whatever else catches my eye. If it involves layers and precision, I am in.', -href: '/interests/making', -image: '/images/making-resin.jpg', -alt: 'Resin crafting in progress', -}, + { + icon: "briefcase", + title: "Professional", + copy: "From SAP-adjacent cloud apps to full-stack mobile — a decade of building software that businesses actually use.", + href: "/professional", + image: "/images/pro-workspace.jpg", + alt: "Developer workspace with code on screen", + }, + { + icon: "dice-multiple", + title: "Tabletop", + copy: "Currently running two campaigns in Foundry VTT and playtesting MCDM's Crows. Always rolling dice.", + href: "/interests/ttrpgs", + image: "/images/ttrpg-dice.jpg", + alt: "Polyhedral dice on a dark surface", + }, + { + icon: "palette", + title: "Making", + copy: "Resin dice, 3D prints, and whatever else catches my eye. If it involves layers and precision, I am in.", + href: "/interests/making", + image: "/images/making-resin.jpg", + alt: "Resin crafting in progress", + }, ]; --- -
+
-
+
- + style="border-color: var(--color-border); color: var(--color-text-muted); background: color-mix(in srgb, var(--color-surface-raised) 60%, transparent);" + > + Developer. Maker. Storyteller. -

- Greg Kilmer -

+

Greg Kilmer

-

+

Software Developer · Maker · Tabletop Gamemaster

-
+
I build things with code during the day and with resin, plastic, and - imagination at night. I lead cloud and mobile development at Implico, - run D&D campaigns that span years, and fill my shelves with Brandon - Sanderson novels, custom dice, and board games. This is the place - where all of those worlds meet. + imagination at night. I lead cloud and mobile development at + Implico, run D&D campaigns that span years, and fill my shelves with + Brandon Sanderson novels, custom dice, and board games. This is the + place where all of those worlds meet.
@@ -93,89 +103,145 @@ alt: 'Resin crafting in progress',
- {/* Hero portrait — framed in celestial ornament. Swap for a real photo of Greg. */} + {/* Hero portrait — framed in celestial ornament. */} - +
-
- {/* Slow-rotating constellation field behind the section — a slice of sky. */} + { + /* Slow-rotating constellation field behind the section — a slice of sky. */ + } {/* Faint sacred-geometry ornament behind the section. */} - +
- \ No newline at end of file + diff --git a/src/pages/professional/index.astro b/src/pages/professional/index.astro index 39fd61e..76338f6 100644 --- a/src/pages/professional/index.astro +++ b/src/pages/professional/index.astro @@ -10,24 +10,24 @@ * `projects` collection. Both are sorted by `order`. Education is a placeholder * block (spec leaves it to Greg). */ -import BaseLayout from '@layouts/BaseLayout.astro'; -import Reveal from '@components/motion/Reveal.astro'; -import Icon from '@components/Icon.astro'; -import SectionHeader from '@components/layout/SectionHeader.astro'; -import Placeholder from '@components/layout/Placeholder.astro'; -import SectionNav from '@components/professional/SectionNav.astro'; -import Timeline from '@components/professional/Timeline.astro'; -import SkillGrid from '@components/professional/SkillGrid.astro'; -import ProjectCard from '@components/professional/ProjectCard.astro'; -import AlchemicalDivider from '@components/mystic/AlchemicalDivider.astro'; -import Astrolabe from '@components/mystic/Astrolabe.astro'; -import CircuitField from '@components/mystic/CircuitField.tsx'; -import { getCollection } from 'astro:content'; +import BaseLayout from "@layouts/BaseLayout.astro"; +import Reveal from "@components/motion/Reveal.astro"; +import Icon from "@components/Icon.astro"; +import SectionHeader from "@components/layout/SectionHeader.astro"; +import Placeholder from "@components/layout/Placeholder.astro"; +import SectionNav from "@components/professional/SectionNav.astro"; +import Timeline from "@components/professional/Timeline.astro"; +import SkillGrid from "@components/professional/SkillGrid.astro"; +import ProjectCard from "@components/professional/ProjectCard.astro"; +import AlchemicalDivider from "@components/mystic/AlchemicalDivider.astro"; +import Astrolabe from "@components/mystic/Astrolabe.astro"; +import CircuitField from "@components/mystic/CircuitField.tsx"; +import { getCollection } from "astro:content"; -const experience = (await getCollection('experience')).sort( +const experience = (await getCollection("experience")).sort( (a, b) => a.data.order - b.data.order, ); -const projects = (await getCollection('projects')).sort( +const projects = (await getCollection("projects")).sort( (a, b) => a.data.order - b.data.order, ); --- @@ -39,9 +39,11 @@ const projects = (await getCollection('projects')).sort( >
- {/* Circuit-board field. Shares view-transition-name "sky" with the star + { + /* Circuit-board field. Shares view-transition-name "sky" with the star fields on other pages, so navigating here morphs constellations into - circuitry. */} + circuitry. */ + } {/* Slowly rotating astrolabe ornament behind the header. */} @@ -67,7 +69,11 @@ const projects = (await getCollection('projects')).sort( {/* ===== 1. Summary ===== */}
- +
- + {/* ===== 2. Experience ===== */} @@ -129,7 +138,7 @@ const projects = (await getCollection('projects')).sort( @@ -147,11 +156,13 @@ const projects = (await getCollection('projects')).sort( />
- {projects.map((project, i) => ( - - - - ))} + { + projects.map((project, i) => ( + + + + )) + }
- - + +
@@ -189,16 +206,49 @@ const projects = (await getCollection('projects')).sort(