marcusjenshaug.no
This website: portfolio and CV with a built-in admin panel, built as a source of identity for search engines and language models, with a WebGL hero that degrades gracefully.

This website is both portfolio and CV, and a project in its own right. All content, from the projects to the Now page, is edited in a built-in admin panel. Drafts can be previewed on the public routes without being published, and are marked noindex for as long as they are drafts. Scheduled publishing lives as cron jobs in the database, not in the application.
Source of identity
The site is built as a home for my identity online, both for search engines and for language models. A JSON-LD graph ties WebSite, Person, Article, CreativeWork and BreadcrumbList together, with sameAs pointing to Wikidata, and machine-readable feeds are available as RSS, JSON Feed and llms.txt. Google indexed the site and gave it its own Knowledge Panel within a few days of launch.
The technical side
The hero is a WebGL shader with simplex noise, mouse-driven ripple and chromatic aberration, written in GLSL. It degrades in four steps: viewport threshold, prefers-reduced-motion, pausing via IntersectionObserver when it's out of view, and a permanent fallback to a plain image if the browser loses the WebGL context. The crossfade between project images is a two-texture shader with a guard against interrupted transitions, so the preview doesn't get stuck on the wrong image.
All writes go through server actions with schema validation. No POST route handlers.
Hand-written design system without a UI kit. Custom components, colour tokens in oklch, and light and dark mode without flicker on load.
Stack
Next.js 15, React 19 and TypeScript, Tailwind CSS 4, Supabase, GSAP and Lenis for motion, three.js with React Three Fiber for the hero, MDX for text, and Vercel.
This text is machine translated and has not been reviewed yet.