Featured Projects

Whimsy Gossip
Entertainment / Fantasy Podcast & Fan Film ProductionWeb Application

Whimsy Gossip

A fantasy podcast and fan film site I built twice: first in React 18 / Vite as an SPA, then migrated to Next.js 15 App Router when the content-driven architecture started creating real friction for SEO and maintenance.

Next.js 15TypeScriptApp RouterReact 18Tailwind CSSSanity CMSISRVercelResendVercel AnalyticsGoogle Analytics 4Cloudflare TurnstylePlaywright
  • 11 Sanity data context providers (~3,500 lines of useEffect → fetch → setState plumbing) replaced by direct server-side fetch() calls in server components
  • generateMetadata() per route replaces react-helmet-async: OG tags and JSON-LD are in the initial HTML, not injected after hydration
L Vega Animations
Animation / Motion Graphics / Studio ArtMarketing Website

L Vega Animations

A portfolio site built with Next.js, Sanity v3, Tailwind CSS, Framer Motion, and Vercel, for an animation and motion graphics artist targeting studio and agency job applications.

Next.jsSanity v3Tailwind CSSFramer MotionResendVercel
Cookie Consent System
Internal ToolingAPI / Integration

Cookie Consent System

A GDPR and CCPA cookie consent system I built as a shared package and installed across several Next.js sites, with a serverless consent-logging API and a per-site cookie profile that decides whether a banner renders at all.

TypeScriptNext.js 15 (App Router)ReactRollupVercel Serverless FunctionsNeon PostgresUpstash RedisTailwind CSS
  • Shared package installed from GitHub with a CLI that scaffolds the UI in as editable components, so logic stays versioned while each site restyles its own banner and modal
  • A declarative per-site cookie profile is the single source of truth for the banner, modal, logging, and policy page; an essential-only site renders no banner and logs nothing
F.L.O.S.S. — Youth & Young Adult Empowerment
Youth Development NonprofitRedesign

F.L.O.S.S. — Youth & Young Adult Empowerment

A four-week redesign of a youth-development nonprofit's site on Next.js 15 (App Router), React 19, and TypeScript, with Sanity driving age-based pathway content and an interactive age-finder routing visitors to the right stage.

Next.js 15 (App Router)React 19TypeScript 5 (strict)Tailwind CSS 3Sanity CMSFramer MotionResendZodVercel
  • Age-finder maps a numeric input to one of four pathway ranges client-side, with explicit below-range and above-range messaging instead of a dead end
  • Pathway content modeled as a first-class Sanity collection, so the homepage cards, the /services Pathway Explorer, and the age-finder all read from one source
Triumvirate Financial
Business Valuation & Financial AdvisoryRedesign

Triumvirate Financial

A Next.js and Sanity rebuild of a boutique valuation firm's GoDaddy site, restructuring four pages into a seven-section architecture with a custom content model, JSON-LD across six schema types, and a scroll-driven editorial design system.

Next.js App RouterTypeScriptSanity CMSGROQPortable TextVercelJSON-LD / Schema.orgIntersectionObserverCSS Grid
  • Alt text enforced at the schema level via a reusable imageWithAlt object, so the old site's empty-alt problem is structurally impossible to reproduce
  • Six JSON-LD types wired to real content, with FAQPage fed directly from the Sanity faq documents rather than hand-maintained in markup
Professional Consulting of Louisiana LLC
Political & Business ConsultingMarketing Website

Professional Consulting of Louisiana LLC

A Next.js 15 monorepo for a political and business consulting firm: a customer-facing frontend, branded Sanity Studio CMS, shared React component library, and living style guide, all built with TypeScript and deployed to Vercel.

Next.jsTypeScriptTailwind CSSSanity CMSFramer MotionRadix UIReact Hook FormZodYarn WorkspacesVercel
  • Yarn Workspaces monorepo with four interdependent apps: Next.js frontend, Sanity Studio CMS, shared React component library, and living style guide
  • Shared component library with 50+ WCAG 2.1 AA compliant components, split server/client entry points, and tree-shakeable ESM/CJS output via tsup