all posts
May 14, 2026·3 min read·portfoliouiperformance

The shareability pack: Konami, View Transitions, dynamic OG, sound

Phase 2 of zaidxshaikh was four small features designed for one big screenshot moment each. +3 KB total, zero new npm deps.

Phase 1 of v2 shipped the foundation — 3D hero, ⌘K, AI chat, audience switching. Phase 2 was about earning the share. Four small features, each designed to produce one specific "wait, did this site just do that?" moment.

Total bundle cost: +3 KB. New npm deps: zero.

1. Konami code easter egg

The classic sequence — ↑↑↓↓←→←→BA — unlocks a full-screen overlay with CRT scanlines, RGB-split text glitch, screen shake, and a stats grid.

The hook (~30 lines):

const SEQUENCE = ["ArrowUp", "ArrowUp", "ArrowDown", "ArrowDown",
                  "ArrowLeft", "ArrowRight", "ArrowLeft", "ArrowRight",
                  "b", "a"] as const;
 
export function useKonami(onUnlock: () => void) {
  const idx = useRef(0);
  useEffect(() => {
    const onKey = (e: KeyboardEvent) => {
      const expected = SEQUENCE[idx.current];
      const got = expected.length === 1 ? e.key.toLowerCase() : e.key;
      if (got === expected) {
        if (++idx.current === SEQUENCE.length) {
          idx.current = 0;
          onUnlock();
        }
      } else {
        idx.current = got === SEQUENCE[0] ? 1 : 0;
      }
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [onUnlock]);
}

The footer drops a hint — try ↑↑↓↓←→←→BA — so attentive readers find it.

2. View Transitions for orb → case study

When a user clicks a project orb, the page used to hard-cut to the case study. Now it crossfades smoothly via the View Transitions API — sub-50-line code change.

export function withViewTransition(cb: () => void) {
  if (typeof document === "undefined") return cb();
  type DocVT = Document & { startViewTransition?: (cb: () => void) => unknown };
  const d = document as DocVT;
  if (typeof d.startViewTransition === "function") {
    d.startViewTransition(cb);
  } else {
    cb();
  }
}

Wired into the orb click, palette navigation, and project card click. Browsers without support (Firefox, older Safari) get a no-op fallback — same code, same behavior, just no animation.

The CSS:

::view-transition-old(root),
::view-transition-new(root) {
  animation-duration: 0.45s;
  animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
}
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation: none !important;
  }
}

3. Per-route dynamic OG images

Every project + the services page gets its own social card via next/og. Edge runtime, no static PNG files, tinted per project category.

export default async function OG({ params }: { params: Promise<{ slug: string }> }) {
  const { slug } = await params;
  const project = projects.find((x) => x.slug === slug);
  const tint = CATEGORY_TINT[project.category];
  return new ImageResponse(
    <div style={{ background: "#050507", backgroundImage: `radial-gradient(..., ${tint}26, transparent)` }}>
      ...
    </div>,
    { width: 1200, height: 630 },
  );
}

LinkedIn and Twitter previews now look intentional instead of generic. Bonus: I'm re-using the same OG image as a hero banner inside the case study page itself, so the social card and the in-page hero are visually consistent.

4. UI sound design via WebAudio (no Howler)

Subtle ticks on palette open, item-select, chat dock toggle. Off by default — there's a "sound on / off" pill in the footer.

No howler dependency. Just OscillatorNode + GainNode envelope:

const o = ctx.createOscillator();
const g = ctx.createGain();
o.type = "triangle";
o.frequency.value = 880;
const now = ctx.currentTime;
g.gain.setValueAtTime(0.0001, now);
g.gain.exponentialRampToValueAtTime(0.05, now + 0.005);
g.gain.exponentialRampToValueAtTime(0.0001, now + 0.05);
o.connect(g).connect(ctx.destination);
o.start(now);
o.stop(now + 0.07);

Zero new deps. Single auto-resumed AudioContext per session. The state lives in Zustand and persists in localStorage.

Why these four?

Each feature is independently shareable but they layer on top of the existing site without changing its core experience:

  • A user who just wants to read the resume sees no difference.
  • A user who notices the "try ↑↑↓↓..." hint gets an unexpected reward.
  • A LinkedIn lurker sees a polished OG card.
  • A power user who turns sound on gets that satisfying tactile feedback.

Each one cost a few hundred bytes and zero new dependencies. None of them are load-bearing — if any failed silently, the site still works perfectly. That's the design rule for Phase 2 features: never block the core path.