Files
com.gregkilmer.www/legacy
Claude a2f723ca2d Start the rebuild: note schema, vault kit and data migration
Phase 1 of the functional design plan.

- Move the old site into legacy/, unchanged, for reference. It still
  builds from there until cutover.
- Add packages/schema: the one definition of all 20 note types, with
  field titles and descriptions, note and vault checks, and JSON Schema
  export so later editing tools and the MCP server share it.
- Add vault-kit: Obsidian templates generated from the schema, and the
  Site guide for 24.01_PersonalWebsite.
- Add tools/migrate: turns the legacy JSON, collections, store data and
  page text into 545 Site folder notes and 84 images, and checks the
  result with the schema.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012aSbo2D1qP8cMFQCykf7kx
2026-10-11 18:40:55 +00:00
..

Greg Kilmer — Profile & Portfolio Site

A responsive, content-driven personal site for Greg Kilmer, built as two wings of the same house: a polished professional resume/portfolio on one side, and a warm, personality-driven interests hub on the other.

Built with Astro 7 + React Islands + TypeScript, served by a Node server with API routes, ready to deploy as a container on a homelab Cosmos system.


Highlights

  • Astro 7 static-first core with React Islands for interactivity (mobile menu, theme toggle, animated hero background, contact form).
  • Node backend (@astrojs/node, standalone) with a typed /api/contact endpoint (SMTP via nodemailer + webhook fallback, Zod validation, rate limit).
  • Section-aware theming: the Professional wing reads dark/polished, the Interests wing reads warm/inviting, plus a global light/dark toggle.
  • Rich motion: animated mesh-gradient hero with an optional canvas particle field, IntersectionObserver scroll reveals, View Transitions page swaps, scroll-triggered nav blur. All prefers-reduced-motion aware.
  • Content Collections (typed): add projects and experience by dropping markdown/MDX files.
  • mdi icons everywhere (no emojis, per the spec), inlined at build time from @iconify-json/mdi for zero runtime cost.
  • Self-hosted variable fonts (Inter, Plus Jakarta Sans, JetBrains Mono).
  • Accessible: semantic landmarks, skip link, keyboard-operable menu, focus-visible rings, ARIA on interactive bits, WCAG-AA contrast targets.
  • Deploy artifacts: multi-stage Dockerfile + docker-compose.yml.

Quickstart

# 1. Install dependencies (Node 20+)
npm install

# 2. Start the dev server with hot reload
npm run dev
#   -> http://localhost:4321

# 3. Production build (runs astro check + build)
npm run build

# 4. Run the built Node server
npm run serve
#   -> http://localhost:4321

Environment is optional for local dev. To enable contact-form delivery, copy .env.example to .env and fill in SMTP or webhook vars (see docs/DEPLOYMENT.md).


Project structure

src/
├── components/
│   ├── hero/            AnimatedBackground.tsx (gradient + canvas particles)
│   ├── motion/          Reveal.astro (IntersectionObserver scroll reveals)
│   ├── nav/             NavBar.astro, MobileMenu.tsx, ThemeToggle.tsx
│   ├── cards/           InterestCard.astro
│   ├── professional/    Timeline, SkillGrid, ProjectCard, SectionNav, ContactForm
│   ├── layout/          Footer, SectionHeader, SplitTransition, InterestHero,
│   │                    RelatedInterests, Placeholder
│   └── Icon.astro       Inline mdi icon renderer (build-time)
├── content/
│   ├── projects/        Project collection entries (markdown/MDX)
│   └── experience/      Experience collection entries
├── layouts/
│   └── BaseLayout.astro  <html> shell, head, fonts, theme init, nav, footer
├── pages/
│   ├── index.astro              Home (hero + snapshot grid)
│   ├── about.astro              About + split transition fork
│   ├── professional/index.astro Single long page: Summary, Experience,
│   │                            Skills, Projects, Education, Contact
│   ├── interests/               Hub + 5 sub-pages
│   │   ├── index.astro
│   │   ├── ttrpgs / gaming / reading / making / pokemon .astro
│   ├── contact.astro            Two-column connect page + contact form
│   └── api/contact.ts           POST endpoint -> SMTP / webhook
├── content.config.ts    Collection schemas (projects, experience)
├── lib/                 site.ts (nav/socials), motion.ts, content helpers
├── styles/              global.css, themes.css, animations.css
└── scripts/theme-init.ts  No-FOUC theme boot (inlined in <head>)

The two wings (theming model)

Theming has two independent axes (see docs/THEMING.md):

  1. Global light/dark on <html data-theme>, set before paint by an inline script, persisted to localStorage, toggleable via the nav button.
  2. Section tone via data-surface on <body>:
    • neutral (Home/About/Contact) — balanced middle ground
    • professional — dark slate, polished
    • interest — warm cream/amber, inviting

Components only reference semantic CSS variables (--surface, --text, --accent...), so changing either axis restyles everything automatically.


Adding content

  • Projects / Experience: drop a markdown or MDX file in src/content/projects/ or src/content/experience/. Schemas and field reference are in docs/CONTENT.md.
  • Interest pages: hand-built .astro files under src/pages/interests/, each following the spec's template (Header, Overview, Highlights, Currently, Related). Edit copy in place.
  • Placeholders: every [Greg to fill] gap from the spec is a styled Placeholder slot with a TODO badge so you can find and replace them.

Deployment (Cosmos homelab)

The site runs as a Node server inside a container. Full walkthrough in docs/DEPLOYMENT.md:

docker compose up -d --build
# Then point your reverse proxy at port 4321 with TLS for gregkilmer.com.

Scripts

Script Description
npm run dev Dev server with hot reload
npm run build Type-check (astro check) then build the Node server
npm run serve Run the built server (dist/server/entry.mjs)
npm run preview Preview the build locally
npm run check Type-check only

Tech stack

Astro 7, React 19, TypeScript 6, Tailwind CSS v4, Framer Motion, nodemailer, Zod, @iconify-json/mdi, Fontsource variable fonts, @astrojs/node standalone.


License

Personal site for Greg Kilmer. All rights reserved.