Personal homepage and portfolio of Ryan Arnaudin — product designer in Austin, TX.
A static site built with Jekyll 4.4 and deployed to GitHub Pages via GitHub Actions (.github/workflows/jekyll.yml; Pages source must be set to "GitHub Actions").
The design is fully custom (2026 redesign) — a text-first, editorial layout with a technical/blueprint voice. The site was originally bootstrapped in 2022 from himatt.com (GPL v3), though essentially none of it remains.
- Typefaces (self-hosted variable fonts in
fonts/): Space Grotesk for display, Inter for body, IBM Plex Mono for metadata/labels. - Libraries: Sass (Dart Sass via jekyll-sass-converter 3), PhotoSwipe for image lightboxes, Headspace for the hide-on-scroll header, Normalize.css. No client-side frameworks.
- Forms: the contact form posts to FormKeep, protected by reCAPTCHA v3 (token fetched at submit time).
- Easter egg: type
blueprintanywhere (or use the footer switch) to flip the site into blueprint mode — white linework on cobalt paper. The theme is a single palette-layer swap in_sass/site/base/_variables.scss/_blueprint.scss.
bundle install
bundle exec jekyll serve --port 4001Notes:
_config.ymlchanges require a server restart; everything else hot-rebuilds.- Locally,
/projects/shows a WEBrick directory listing of built case studies — handy for browsing. In production GitHub Pages returns a 404 there (no index page exists by design). - A hidden style guide lives at
/styleguide/(not indexed, not linked).
_projects/— case studies (a Jekyll collection, output at/projects/:path/). Front matter drives everything:summary,role,outcomes(stat row), and acontent_layoutlist of sections (text,1col,2col,video, …) rendered by_includes/layout.html. Start new case studies from_projects/z-empty-template.md._posts/— blog posts, published at/blog/:title/._pages/— top-level pages (home/work, about, process, writing index, contact)._drafts/— unpublished drafts and archived content; never built (the local server doesn't run with--drafts).
After adding or changing images, run:
./tools/optimize-images.shIt generates (requires cwebp — brew install webp):
- a
.webpnext to every.png/.jpg/.jpegunderimages/(capped at 1600px wide; favicons skipped), - a
.900w.webpvariant for images wider than 1400px (mobile srcset), _data/image_dims.yml— the width/height index the templates use forsrcset, layout-shift-free<img>tags, and PhotoSwipe zoom targets.
GIFs are indexed for dimensions only (no WebP conversion). Templates lazy-load everything except the first image of a page, which gets fetchpriority="high".
The site-wide social-share fallback image lives at images/site/og-default.png (1200×630); pages with a thumbnail in front matter use that instead. robots.txt blocks /images in general but allows share images (/images/site/, *-thumbnail*) so link previews work.
Under the GNU General Public License v3.0, you can adapt and use the source code of this site (but not its content) for personal and commercial use, so long as you retain the same license for your own project.
© Ryan Arnaudin
Unauthorized use and/or duplication and adaptation of this material (all images, text, and media files) without express and written permission from this site's author and/or owner is strictly prohibited. Excerpts and links may be used, provided that full and clear credit is given to Ryan Arnaudin and linked to ryanarnaudin.com with appropriate and specific direction to the original content.