My personal profile and resume site.
This repository builds my small static website for www.christhierer.com, including a profile homepage, an HTML resume, and a generated PDF resume. I want it to stay low-maintenance: content lives in Markdown, rendering is handled by a small React server-rendered build script, and GitHub Pages publishes the generated dist/ artifact.
- Background
- Install
- Usage
- Content Maintenance
- Architecture
- Deployment
- Troubleshooting
- Maintainer
- Contributing
- License
This is my personal web presence for engineering leadership job search, resume presentation, and small freelance credibility. It is built with React server rendering, TypeScript, Pico CSS, Lightning CSS, Markdown frontmatter, Zod validation, and WeasyPrint for the resume PDF.
The repository name matches the GitHub Pages convention. My production domain is configured in config.yaml.
Use Node.js 26 or newer and Python 3.13 or compatible local Python tooling for PDF generation.
npm ci
python3 -m venv .venv
.venv/bin/python -m pip install -r requirements.txtIf python3 -m venv .venv fails because ensurepip is unavailable on Debian/Ubuntu, install local venv support first:
sudo apt install python3-venvStart a local rebuilding server:
PATH="$PWD/.venv/bin:$PATH" npm run devBuild the site. The TypeScript build script renders HTML, bundles CSS, copies public
assets, writes the sitemap, and generates PDFs for pages configured with pdf: true:
PATH="$PWD/.venv/bin:$PATH" npm run buildBuild a private role-specific resume variant (for example, the ignored UMBC adjunct
variant). The preset infers the shared baseline and variant directory, builds only the
resume with analytics disabled, and writes its local submission PDF to
variants/output/<variant>/resume.pdf:
PATH="$PWD/.venv/bin:$PATH" npm run build:resume -- umbc-adjunct \
--contentDir variants/content-sensitiveRun the maintenance checks:
npm run checkFormat the repository:
npm run formatThe generated site is written to dist/. Treat dist/ as build output, not source. Public
--outputDir overrides must stay within dist/; private resume overrides must stay below
variants/output/.
Most routine updates I expect to make happen in content/:
content/singles/controls homepage hero, current focus, and at-a-glance copy.content/resume/controls ordered resume sections, including profile, metrics, skills, experience, and education.content/experience/controls work history for both the homepage and resume.content/education/controls education entries.content/contact/andcontent/social/control header, footer, CTA, and resume links.content/organizations/stores organization labels, locations, slugs, and logos used by experience entries.
Markdown frontmatter is validated during npm run build. Set published: true for entries that should render. See docs/maintenance.md for the practical update checklist and frontmatter notes.
Private resume patches belong under ignored variants/, where they can override the shared Markdown baseline without being deployed. See the private-variant workflow in docs/maintenance.md.
src/build/build.tsxresolves the public-build or resume-preset command options, whilesrc/build/buildSite.tsxprovides their shared pipeline: it cleans the selected safe output directory, loads configuration and resolved Markdown layers, copies public assets, bundles CSS, renders React pages to static HTML, generates configured PDFs, and writes a sitemap.config.yamlcontrols generated pages through itspageslist. Addpdf: trueto an HTML page entry to generate a PDF alongside it; for example,/resume.htmlproduces/resume.pdf.src/styles/main.cssis bundled and minified by Lightning CSS.src/pages/contains page-level composition for the homepage and resume.src/components/contains reusable page, profile, hero, link, site, and resume components.src/content/schemas/contains the Zod schemas for Markdown frontmatter.public/contains static assets copied intodist/.
GitHub Pages deployment is handled by .github/workflows/pages.yml on pushes to main and manual workflow_dispatch runs. The workflow installs Node and Python dependencies, runs npm run check, builds my site, and uploads dist/ to Pages.
If a configured page has pdf: true, the build requires WeasyPrint. If weasyprint
is not found locally, make sure the virtual environment is installed and prepended to
PATH when building:
PATH="$PWD/.venv/bin:$PATH" npm run buildIn some sandboxed environments, tsx may need approval because it opens an IPC pipe under /tmp.
I maintain this site. You can reach me at hello@christhierer.com.
This is my personal website, so I am not expecting unsolicited pull requests. If you are helping me maintain the site, open an issue or coordinate with me directly before changing positioning, resume content, analytics, dependencies, or deployment behavior.
Before merging meaningful changes, run:
npm run check
PATH="$PWD/.venv/bin:$PATH" npm run buildUNLICENSED, copyright Chris Thierer.