JT
  • Home
  • Projects
  • Extras
  • Contact

© 2026 Joshua Tjhie. All rights reserved.

GitHubLinkedInEmail
Back to Projects
  1. Home
  2. Projects
  3. Personal Portfolio (Placeholder)
2024-05-12

Personal Portfolio (Placeholder)

The Next.js + Tailwind build powering this site.

Implementation notes for the portfolio you're browsing — design system, content pipeline, animation layer, and MDX authoring workflow.

Next.jsReactDesign Systems
Personal Portfolio (Placeholder)

Quick Stats

Role: Designer & Developer
Duration: Ongoing
Next.js 16 (App Router)React 19Tailwind CSS v4MDX + Zod

Links

Site Repository

Personal Portfolio

You're reading this on the site it describes. The write-up covers the design decisions, tech choices, and content pipeline that power what you're seeing right now.

My previous portfolio was a rigid single-page build that made adding experiments painful. This iteration puts extensibility first: every piece of content lives in an MDX file, every component inherits from a shared design system, and the whole thing generates statically at build time.

Design system

The site is dark-only, built on the Rose Pine palette. Committing to a single mode eliminates the conditional branching that makes theming tedious and lets the colour choices be deliberately atmospheric rather than merely accessible.

Design system colour tokens
Tailwind v4 @theme inline block — all Rose Pine tokens as CSS custom properties.

Colour palette

TokenHexRole
love#eb6f92Primary accent, headings
gold#f6c177Secondary accent, CTAs
pine#31748fTertiary accent, links
foam#9ccfd8Highlights
iris#c4a7e7Decorative
surface#1f1d2eCard backgrounds
overlay#26233aLayered elements

Typography

Three fonts, three roles:

  1. Space Grotesk — display headings, brand mark.
  2. Readex Pro — body text, paragraphs.
  3. Roboto Mono — code, ASCII art, monospace contexts.

All loaded via next/font/google with variable mode for font-family CSS custom property injection.

Stack

  • App shell: Next.js 16 App Router with React Server Components, streaming layouts, and generateMetadata helpers per route.
  • Design: Tailwind CSS v4 + shadcn-inspired UI primitives, gradient overlays, and canvas background layers (animated gears, matrix rain).
  • Content: MDX files in content/projects and content/extras, validated with Zod at load time and rendered via next-mdx-remote.
  • Media: Raw assets → Sharp WebP pipeline → assets.json manifests — images reference manifest entries, missing files fall back to a gear placeholder.
  • SEO: Structured data (JSON-LD), dynamic OG images (Edge runtime, @vercel/og), sitemap, and RSS feed.

Content pipeline


The Zod schema is the single source of truth for what frontmatter is valid. Missing required fields throw at startup — no silent failures rendering half-empty pages.

MDX component map

Every MDX file has access to the full set of custom components:

  • <Image> / <Gallery> — responsive media with blur placeholders.
  • <Video> / <AudioPlayer> — hosted asset embeds with consistent framing.
  • <Embed> — YouTube and arbitrary iframe embeds.
  • <LinkButton> — gradient CTAs to repos, demos, or contact.
  • <RelatedContent> — cross-links to other entries by slug and type.
  • <Callout>, <Quote>, <Code>, <Markdown> — narrative building blocks.

Animation layer

The site uses three distinct animation systems:

  1. Framer Motion — entry animations (fadeUp), carousel transitions, staggered card reveals.
  2. CSS keyframes — pulse-glow on CTA buttons, the ambient body::after radial gradients.
  3. Canvas / rAF — matrix rain effect (c-matrix-layer.tsx), gear rotation overlay (gear-layer.tsx), skills marquee.
Hero reveal, featured carousel autoplay, and skills marquee — all at 60 fps.

The canvas layers sit at z-0 behind a z-10 content wrapper, keeping decoration fully separate from interactive elements.

OG image generation

Each project and extra gets a dynamic OG image generated at the Edge:

/api/og/projects/[slug]  →  800×400 branded card
/api/og                  →  default fallback
The ambient background tone I listen to while building thisListen
Your browser does not support the audio element.

Deployment

The site deploys to Vercel. Static generation means the hosting bill is essentially zero — Edge functions only fire for OG image requests.

A portfolio is never finished. It's a living record of who you are right now, and an invitation to become someone different.

View Source

Have thoughts?

Curious what others see or think

Feel free to reach out or leave feedback

Share Feedback

Prefer email? joshuatjhie@pm.me