← Back to web work
UX/UI Design · Web Development · Case Study · 2026

Wyatt Spicer
Portfolio Site — Design,
Build, and Deployment

10 pages, 4 disciplines, a functional Netlify contact form, a verified CSP, a downloadable resume, and a site that holds up to the same technical scrutiny as the client work it showcases.

10Pages
4Disciplines
45Lines of JS
7CSP directives
Overview

A portfolio that practices what it presents.

The most credible thing a web designer can do is build their own portfolio to the same standard they apply to client work. Wyatt Spicer's portfolio site does exactly that. The same accessibility practices demonstrated in the Adams Internal Medicine case study are present here — skip links, aria-current, focus-visible states, semantic landmarks. The same deployment readiness demonstrated in the Keyboard Board case study is here — canonical tags, OG metadata, CSP, Netlify Forms, robots.txt, sitemap. The same attention to content that characterizes every project in the portfolio is present in how the portfolio describes itself.

This isn't accidental. The portfolio was built and audited iteratively against the same checklists used for client projects. It passed the same security, accessibility, and SEO reviews. It would be embarrassing to showcase meticulous work on a medical practice website and then have your own portfolio missing a viewport meta tag or posting a form to nowhere.


The Site

10 pages across 4 disciplines, built to be evaluated by people who know what they're looking at.

The portfolio covers UX/UI design, web design, 3D fabrication, and art/audio/visual work. Each discipline has its own dedicated page with project content — case studies, embedded prototypes, slide decks, video work, and galleries — rather than everything compressed onto a single scrolling home page. The structure is honest about the breadth: this is not one thing, it's four things that share a designer.

PageContentKey feature
HomeThree featured projects, four discipline cards, working style sectionVideo motion reel hero, hero-meta availability status
UXGoCapital Auto Quest case study, MovieHouse, research decksFigma embed (renamed from "Untitled"), aria-labeled walkthrough videos
WebAdams Internal Medicine, VisitSPI, HP Concert Series, Keyboard BoardLive site links, real screenshot preview replacing SVG placeholder
3DPineapple Cart, Spike Tower, Butterfly Lamp, Spike LightCanva and Google Slides embeds, all with title attributes
Art / AVVisual gallery, TouchDesigner visualizers, short film, infomercialYouTube embeds with loading="lazy" and title
AboutBiography, skills, resume snapshot, personal statement, availabilityOne-click resume PDF download
ContactEmail, phone, LinkedIn, GitHub, resume link, inquiry formNetlify form with honeypot, contact-success redirect
Contact SuccessConfirmation with email fallback and nav paths backExists and renders correctly
404On-brand error with two navigation paths"That page wandered off."
threed.htmlRedirect stub301 to 3d.html via netlify.toml

Design System

Electric blue, warm orange, and a type system built for two registers.

The palette pairs a vivid electric blue accent (#315efb) with a warm coral secondary (#f27d42) against an off-white blue-tinted background. The combination reads as energetic and contemporary without tipping into aggressive — right for a creative technologist who works across UX, code, and fabrication, and needs a personal brand that signals range without noise.

Typography uses Space Grotesk for body and UI text and Oswald for the logo mark. Both are loaded from Google Fonts. The CSS is 178 lines — a deliberately minimal stylesheet that handles the full design system without accumulating technical debt. All interactive components use CSS transitions, and the `prefers-reduced-motion` media query disables transitions and scroll behavior for users who've requested it.

Space Grotesk — body Oswald — logo mark Google Fonts (CDN) prefers-reduced-motion IntersectionObserver reveals 178 lines CSS

The JavaScript

45 lines that do exactly what's needed and nothing more.

The portfolio's entire JavaScript is 45 lines in a single IIFE. It handles four things: mobile menu toggle with `aria-expanded` management, active nav state detection with `aria-current="page"` and `.active` class, copyright year auto-population via `[data-year]`, and scroll-triggered reveal animations via `IntersectionObserver` with a graceful fallback for browsers that don't support it.

That's the right amount of JavaScript for a portfolio site. No framework. No build step. No dependencies. No supply chain. The `defer` attribute on the script tag means it doesn't block rendering. The IIFE wrapping means nothing leaks to global scope. The IntersectionObserver fallback means content is still visible even when the animation system is unavailable.

45
Total JS lines
4
Functions
0
External deps
0
Global scope leaks

Accessibility

The site passes the same checks it applies to client work.

Skip link before <header> on all 10 pages. The `<a class="skip-link" href="#main">` is the first child of `<body>` — before `<header>` opens — on every page. Keyboard users skip directly to main content without tabbing through five nav links.
aria-current="page" set by JavaScript. `setActiveNav()` reads `window.location.pathname`, matches the current file to the correct nav link, and sets both `.active` and `aria-current="page"`. Screen readers announce which page the user is currently on.
Focus-visible on every interactive element. `.btn`, `.main-nav a`, `.logo-link`, `.menu-toggle`, `.card a`, `.gallery-link`, `.text-link`, `.contact-card a`, and `.footer-links a` all have explicit `:focus-visible` styles. The skip link gets both `:focus` and `:focus-visible` to ensure compatibility across browsers.
Walkthrough videos have aria-label. The two MP4 walkthrough videos on the UX page (originally named `25.mp4` and `26.mp4`, renamed to descriptive filenames) use `aria-label="GoCapital prototype walkthrough 1"` and `"...walkthrough 2"` on the `<video>` elements. Screen readers can identify them meaningfully.
All iframes have title attributes. Figma, Google Slides, Canva, and YouTube embeds all carry unique title attributes. Zero iframes are anonymous.
All images have descriptive alt text. Zero images missing alt across all 10 pages. Project images describe actual visual content rather than repeating the heading text.
lang="en" on all pages. Screen readers select the correct pronunciation engine for every page.

Security

A Content Security Policy that covers every external resource the site actually uses.

The final build ships with a comprehensive Content Security Policy in `_headers`. It was the last gap between the portfolio's own security posture and the standard set by the AIM client project — and it required precision because the portfolio loads from more external sources than a typical static site:

What the CSP covers.

script-src 'self' — the single IIFE in script.js is local. No external scripts, so no CDN allowances needed. Fully enforceable.

style-src 'self' https://fonts.googleapis.com — Google Fonts requires fonts.googleapis.com for the stylesheet. This is the minimum needed.

font-src 'self' https://fonts.gstatic.com — actual font files served from gstatic. Both Fonts directives are required; one without the other breaks font loading.

img-src 'self' data: https: — `data:` allows favicon SVG inline data URIs. `https:` allows OG images and any external image content referenced by embedded slides.

frame-src https://embed.figma.com https://docs.google.com https://www.canva.com https://www.youtube.com — four specific origins covering every embed on the site. No wildcard. No extra allowances.

media-src 'self' — the GoCapital walkthrough MP4 files are local. Required for <video> elements with a CSP present.

frame-ancestors 'none' — the modern equivalent of X-Frame-Options: DENY. Both are set (belt-and-suspenders), but frame-ancestors in CSP is the current standard.

The CSP was deliberately crafted rather than generated — every directive has a reason, every origin in frame-src corresponds to an actual embed on a specific page. Getting this right on a portfolio with five different embed types (Figma, Google Slides, Canva, YouTube, and local video) required auditing each page individually before writing the policy.


SEO and Deployment

The same launch-readiness checklist applied to every client project.

Canonical tags on all 10 pages. Pointing to `https://wyattspicer.com/[page].html`. No relative canonicals.
OG tags on all 10 pages. `og:title`, `og:description`, `og:image`, `og:url`, `og:type` all present. `og:image` points to the absolute URL of `social-preview.jpg`. Twitter Card tags present. Link previews render correctly on every platform.
Sitemap with 7 content page entries. Absolute URLs on wyattspicer.com. Utility pages (404, contact-success, redirect stub) excluded correctly.
robots.txt with Sitemap reference. `Sitemap: https://wyattspicer.com/sitemap.xml` on line 3. Search engines find the sitemap without manual submission.
Netlify form wired correctly. `data-netlify="true"`, `data-netlify-honeypot="bot-field"`, hidden form-name field, `type="email"` on the email input, `type="submit"` on the submit button. The form posts to `/contact-success.html` on submission.
LinkedIn URL matches the professional name. `linkedin.com/in/wyatt-spicer-5b5566221` — updated from the legacy matthew-spicer URL. Name consistency across the site.
Figma embed renamed from "Untitled." The GoCapital prototype Figma file URL now contains `GoCapital-Auto-Quest` instead of `Untitled`. A recruiter viewing the page source sees a named, intentional file.
Resume PDF downloadable from About and Contact. `documents/wyatt-spicer-resume-2026.pdf` — versioned by year so the cache-busting happens automatically on update. Linked with `target="_blank" rel="noopener noreferrer"`. `/documents/*` has a 24-hour cache (correct — the resume may be updated).
AIM preview replaced with real screenshot. The Adams Internal Medicine card on the home and web pages previously used an SVG placeholder graphic. It now uses `aim-homepage-preview.jpg` — an actual screenshot of the live site, which is more credible than a generic illustration.
theme-color consistent across all 10 pages. Including the 404 and contact-success utility pages, which previously had no theme-color meta tag.

One Remaining Note

The contact form has a minor attribute duplication worth cleaning.

The contact form opening tag currently reads:

<form ... data-netlify="true" netlify data-netlify-honeypot="bot-field" netlify-honeypot="bot-field" ...>

`netlify` (bare attribute) duplicates `data-netlify="true"`. `netlify-honeypot="bot-field"` duplicates `data-netlify-honeypot="bot-field"`. Netlify accepts both forms, so this works — but the clean version is just `data-netlify="true" data-netlify-honeypot="bot-field"`. One line to fix, zero functional impact either way.


Takeaway

The portfolio is the most reviewed site in the portfolio.

Every project in this portfolio went through a rigorous audit process. The Adams Internal Medicine site was evaluated against 19 lenses. The Keyboard Board was QA'd across multiple builds. The VisitSPI rebuild was checked against accessibility, SEO, and technical standards before being documented as a case study. The portfolio itself went through the same process — iterative builds, specific issues identified, specific fixes applied, verified against source before closing.

The result is a portfolio site that can be sent to a UX hiring manager, a front-end engineering lead, and a creative director simultaneously and hold up to each of their different scrutiny axes. The UX people can read the GoCapital case study and see structured research process. The front-end people can view source and see semantic HTML, correct ARIA, a real CSP, and 45 lines of clean vanilla JavaScript. The creative directors can look at the visual design and see a coherent system with intention behind it.

That's the goal of a portfolio: not to impress everyone in the same way, but to survive the scrutiny of whoever looks at it most carefully.

The portfolio is the most reviewed site in the portfolio — and it shows.

WYATT SPICER PORTFOLIO · WEB DEVELOPMENT CASE STUDY · 2026