Loading

All projects

Creative Web · 2026

Itachi — Character Universe

A character-driven experience built around Itachi Uchiha. Instead of a wiki wall of text, the site opens on a moonlit portrait with rank, affiliation and kekkei genkai stats, then guides the visitor through chapters — Prodigy, Sacrifice, Brother — with a dedicated jutsu archive and timeline.

ReactTanStack StartTailwind CSS

Client

Snapz Labs (in-house product)

Industry

Anime / Fan Media

Timeline

3 weeks

My role

Designer & Front-End Engineer

The problem

Fan pages for the character were text dumps on ad-heavy wikis — no art direction, no story flow, and unreadable on mobile.

The solution

A cinematic character universe: moonlit dark theme, a stat panel, a searchable jutsu archive and scroll-driven chapters that unfold his story instead of listing it.

98

Lighthouse performance

3m 40s

Avg. time on site

0.8s

First contentful paint

What I built

Cinematic hero

Full-bleed portrait with layered crow particles, Japanese kanji typography and a soft moonlight vignette.

Stat panel

Rank, affiliation, kekkei genkai and village rendered as a responsive data strip under the hero.

Jutsu archive

Filterable /jutsu page with chakra nature tags, cost, and expandable technique descriptions.

Story chapters

Scroll-linked sections that fade and parallax as the reader moves through his timeline.

Architecture

  • React + TanStack Start with file-based routes (/, /about, /jutsu)
  • Tailwind CSS design tokens for the moonlit dark palette
  • Content authored as typed TS data modules — no CMS round-trip
  • Static prerender + edge caching for instant repeat visits
  • Per-route metadata and OG cards so shared links render a proper preview

Hard problems

Heavy artwork killed load time

Illustrations were 4MB+ each. AVIF/WebP variants with responsive srcset and blurred LQIP placeholders brought FCP to 0.8s with no visible pop-in.

Scroll effects janked on mobile

Rewrote the parallax on IntersectionObserver + transform-only animations and honoured prefers-reduced-motion, holding a steady 60fps on mid-range Android.

Code from the build

A few real excerpts from the repository.

src/lib/jutsu.ts
export type Jutsu = {
  name: string;
  reading: string;
  nature: "Fire" | "Genjutsu" | "Space-Time" | "Sealing";
  rank: "C" | "B" | "A" | "S";
  cost: number; // chakra units
  description: string;
};

export const jutsu: Jutsu[] = [
  {
    name: "Tsukuyomi",
    reading: "月読",
    nature: "Genjutsu",
    rank: "S",
    cost: 95,
    description:
      "Absolute control of the target's perception of time — days of torment inside a single second.",
  },
];

export const byNature = (nature: Jutsu["nature"]) =>
  jutsu.filter((j) => j.nature === nature);
src/components/reveal.tsx
export function Reveal({ children }: { children: React.ReactNode }) {
  const ref = useRef<HTMLDivElement>(null);
  const [shown, setShown] = useState(false);

  useEffect(() => {
    const el = ref.current;
    if (!el) return;
    if (matchMedia("(prefers-reduced-motion: reduce)").matches) {
      setShown(true);
      return;
    }
    const io = new IntersectionObserver(
      ([entry]) => entry.isIntersecting && (setShown(true), io.disconnect()),
      { rootMargin: "-12% 0px" },
    );
    io.observe(el);
    return () => io.disconnect();
  }, []);

  return (
    <div
      ref={ref}
      className={shown ? "translate-y-0 opacity-100" : "translate-y-6 opacity-0"}
      style={{ transition: "opacity .7s ease, transform .7s ease" }}
    >
      {children}
    </div>
  );
}
"It reads like a short film, not a fan page. Everyone I sent the link to scrolled all the way to the end."
Areeb K. · Community Manager, Snapz Labs

How it was built

  • Discovery call, scope and fixed timeline agreed up front
  • Custom design system built in Figma before development
  • Typed, reviewed codebase with CI checks on every commit
  • Deployed with monitoring, backups and post-launch support

Want something like this?

Start a Project