Skip to content

Kevin-Mok/nextjs-portfolio-showcase

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

274 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Kevin Mok's Portfolio

Next.js TypeScript Tailwind CSS Content Collections Resend License

A production-ready developer portfolio built with Next.js 15, featuring a tiled window manager aesthetic inspired by Hyprland/Arch Linux. Showcases MDX-powered blog and projects, Cloudflare CDN integration, Resend contact form and parallax scrolling mobile layout. Deployed on Railway with zero-config Railpack builds.

Modern tech stack meets terminal aesthetics—designed for developers who appreciate both craft and performance.

kmok.aiReport Issue


Why This Repo Stands Out

  • It is not a generic portfolio shell. The site ships a Hyprland-inspired desktop UI, a distinct mobile layout, MDX-backed writing, and a resume system with automated PDF generation and layout validation in one repo.
  • The repo shows product thinking, not just frontend polish: contact delivery, spam protection, CDN-aware media handling, typed content pipelines, and recruiter-ready resume workflows are all versioned together.
  • The build pipeline proves more than “it compiles.” npm run build regenerates resume PDFs, and the resume verification scripts enforce page count, whitespace, and font consistency so role-specific resume links do not quietly drift.

🏗️ Tech Stack And Why Chosen

  • Next.js 15 + React 19: one deployable surface for the app shell, API routes, blog, project pages, and resume route without splitting the portfolio into multiple services.
  • TypeScript strict mode: keeps config, MDX-derived content, and resume data changes from silently drifting.
  • Content Collections + MDX: stores blog and project content in tracked files with build-time validation instead of a separate CMS.
  • Tailwind CSS v4 + modular CSS + Framer Motion: mixes fast utility styling with deliberately scoped stylesheet modules and animation control for the window-manager aesthetic.
  • Resend + Zod: gives the contact flow production email delivery plus schema-validated input handling.
  • Local resume PDF tooling: the repo generates and validates 13 resume variants with local Computer Modern fonts, layout baselines, and deterministic PDF checks.
  • Optional Cloudflare R2: keeps the project deployable without CDN setup while still supporting a faster production media path.

✨ Features

  • Desktop Layout: 6-tile Hyprland-inspired layout (Neofetch, Navigation, Content, Theme Preset, Accent Color, Background)
  • Keyboard Navigation: Vim-style hjkl movement + Tab cycling + workspace indicators via Polybar
  • Mobile Experience: Parallax scrolling with depth effects and scroll progress indicators
  • Theme System: 3 curated presets (Tokyo Night, Nord, Solarized Light) + 15 accent color swatches
  • Content Management: MDX-powered blog and projects with syntax highlighting and reading time
  • Audio Narration: Blog post audio with auto-detection, playback controls, and analytics tracking
  • Contact Form: Production-ready Resend integration with 5-layer spam protection (honeypot, rate limiting, validation)
  • CDN Integration: Optional Cloudflare R2 for optimized image delivery with automatic fallback
  • Modern Architecture: Next.js 15.5 + TypeScript strict mode + modular CSS (12 focused modules under 200 LOC each)
  • Zero-Config Deployment: Railway + Railpack auto-detection with intelligent caching

🚀 Quick Start

Prerequisites

node >= 18.0.0
npm >= 9.0.0

Setup

# Clone and install
git clone https://github.com/kmokdefi/kmok-portfolio.git
cd kmok-portfolio
npm install

# Configure environment
cp .env.example .env.local
# Edit .env.local with your RESEND_API_KEY and NEXT_PUBLIC_CONTACT_EMAIL

# Run development server
npm run dev

Visit http://localhost:3000

Build Commands

npm run build      # Production build
npm run start      # Start production server
npm run typecheck  # TypeScript validation
npm run lint       # Code linting

These top-level npm entrypoints are normally run exactly as shown here; the repo does not rely on extra README-level flags for day-to-day use.

Resume PDF Workflow

npm run build also regenerates resume PDFs in public/resume/. Resume PDF rendering uses local Computer Modern assets in public/fonts/cmu/ for deterministic layout metrics.

npm run measure:resume-layout   # Measure bottom whitespace for all generated resume PDFs
npm run calibrate:resume-layout # Auto-tune per-variant print settings toward legacy baseline
npm run verify:resume-layout    # Enforce legacy baseline bottom whitespace lock
npm run validate-resume-pdfs    # Full gate: page count, page size, fonts, bold, layout baseline

Layout rules and baseline source are documented in docs/resume/resume-generation-spec.md.


⚙️ Configuration

Environment Variables

Create .env.local from template and configure:

Variable Required Description
RESEND_API_KEY ✅ Yes Resend API key (resend.com - free: 100 emails/day, 3K/month)
RESEND_FROM_EMAIL ✅ Yes Verified domain email for Resend (e.g., contact@kmok.ai)
NEXT_PUBLIC_CONTACT_EMAIL ✅ Yes Email address to receive form submissions
NEXT_PUBLIC_CDN_URL Optional Cloudflare R2 CDN URL (e.g., https://cdn.kmok.ai)
NEXT_PUBLIC_NAME Recommended Your full name
NEXT_PUBLIC_TITLE Recommended Your professional title
NEXT_PUBLIC_SEO_TITLE Recommended Site or homepage SEO title
NEXT_PUBLIC_SEO_DESCRIPTION Recommended Site or homepage SEO description
NEXT_PUBLIC_GITHUB_URL Recommended GitHub profile URL
NEXT_PUBLIC_LINKEDIN_URL Optional LinkedIn profile URL
NEXT_PUBLIC_TWITTER_URL Optional Twitter/X profile URL
NEXT_PUBLIC_UPWORK_URL Optional Upwork profile URL used by homepage CTAs and neofetch
NEXT_PUBLIC_UPWORK_HANDLE Optional Upwork handle shown in neofetch

See .env.example for the complete environment variable list.

Homepage lead copy is versioned in config/portfolio.config.ts, so production deploys can pick it up from git without needing an untracked env override.

CDN Configuration (Optional)

This project supports Cloudflare R2 for image hosting:

Without CDN (default):

  • Images served from /public/images/
  • Works out-of-the-box, no setup required

With CDN (recommended for production):

Quick Setup:

  1. Create Cloudflare R2 bucket
  2. Upload images maintaining /images/ folder structure
  3. Connect custom domain (e.g., cdn.kmok.ai)
  4. Set NEXT_PUBLIC_CDN_URL in environment variables
  5. Deploy - images automatically load from CDN!

Content Customization

Edit config/portfolio.config.ts to customize:

  • Personal information and bio
  • Project portfolio with metrics
  • Skills and technologies
  • Blog posts
  • ASCII art and system info

See CLAUDE.md for detailed architecture documentation.


🚢 Deployment

Railway (Recommended)

Auto-deployment with Railpack builder:

  1. Visit railway.appNew ProjectDeploy from GitHub
  2. Select kmok-portfolio repository
  3. Add environment variables in Variables tab:
    • RESEND_API_KEY (required)
    • RESEND_FROM_EMAIL (required)
    • NEXT_PUBLIC_CONTACT_EMAIL (required)
    • NEXT_PUBLIC_CDN_URL (optional - for Cloudflare R2)
    • See .env.example for complete list
  4. Railway auto-detects Next.js and deploys with Railpack

Features:

  • Zero-config deployment (no Dockerfile needed)
  • Automatic NEXT_PUBLIC_* variable injection
  • Fast builds with intelligent caching

Vercel

npm i -g vercel
vercel

Add environment variables via Vercel dashboard → Settings → Environment Variables.


🧱 Implementation Snapshot

Framework: Next.js 15.5.4 with App Router and Turbopack Language: TypeScript 5.0 (strict mode) Styling: Tailwind CSS v4 + Modular CSS architecture (12 modules) Content: Content Collections + MDX (blog & projects) Animation: Framer Motion 12.23 Email: Resend API 6.1.2 + React Email Audio: HTML5 Audio API + Custom analytics (7 event types) CDN: Cloudflare R2 (image storage & delivery) Validation: Zod 4.1 (schema validation) State: React Context API (Theme, Focus) Icons: React Icons 5.5 + Custom ASCII art Fonts: JetBrains Mono, Geist, Geist Mono

Key Features

  • Modular CSS: 12 focused stylesheets organized by concern
  • MDX Content: Blog and projects powered by Content Collections with syntax highlighting
  • CDN Integration: Cloudflare R2 for optimized image delivery with fallback to local
  • Responsive: Desktop (≥1024px) tiled layout, Mobile (<1024px) dual-mode
  • Contact Security: 5-layer spam protection (honeypot, rate limiting, validation)
  • Theme System: CSS variables with localStorage persistence

📁 Project Structure

kmok-portfolio/
├── app/                    # Next.js App Router
│   ├── api/contact/       # Contact form API endpoint
│   ├── styles/            # 12 modular CSS files
│   └── globals.css        # CSS module imports
├── components/
│   ├── layout/            # Desktop & mobile layouts
│   ├── tiles/             # Desktop tile components
│   └── ui/                # Reusable UI components
├── config/
│   ├── portfolio.config.ts # Main configuration
│   ├── projects.config.ts  # Project definitions
│   └── types.ts           # TypeScript types
├── content/               # MDX content
│   ├── blog/             # Blog posts (*.mdx)
│   └── projects/         # Project pages (*.mdx)
├── contexts/              # React Context providers
├── hooks/                 # Custom React hooks
├── lib/                   # Utility libraries
├── public/                # Static assets
│   ├── audio/blog/       # Blog post audio files (MP3)
│   ├── fonts/            # Custom fonts
│   └── images/           # Local images (CDN fallback)
├── scripts/               # Build and utility scripts
├── docs/                  # Documentation
├── content-collections.ts # Content Collections config
├── next.config.ts         # Next.js configuration
├── tailwind.config.ts     # Tailwind CSS config
├── tsconfig.json          # TypeScript config
└── railway.toml           # Railway deployment config

📚 Documentation


📄 License

MIT License © 2025 David Leer

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.

🙏 Acknowledgments

Design Inspiration

Color Themes

Technologies


Resume-ready points by variant

ai-web-dev

  • Built a hybrid recruiter-facing resume that combines Next.js web delivery with an agentic engineering story, making /resume lead with the strongest current full-stack narrative by default.
  • Added a visible summary block for the default resume variant, so recruiters immediately see the stack and the 4 concurrent AI workflow angle before scanning project bullets.
  • Separated AI/devtools work into a dedicated Agentic Engineering section, keeping web projects and agentic systems distinct without losing one-page fit.
  • Kept homepage and PDF entry points in sync by deriving the CTA PDF link from the default variant instead of hard-coding an older web-only file.
  • Auto-generated and validated 13 resume variants and kept role-specific links consistent, so resume content stayed accurate whenever project details changed.

web-dev

  • Designed a portfolio experience with a 6-panel desktop layout and smooth mobile flow, so hiring managers could scan skills, projects, and resume links quickly without getting lost in navigation.
  • Added 3 themes and 15 accent colors to keep content readable across preferences, improving first impressions for recruiters and reducing friction for returning visitors.
  • Set up 5 spam checks on the contact form and cut low-quality submissions, so real recruiter outreach was easier to identify and respond to quickly.
  • Split styles into 12 small CSS modules (under 200 lines each), making edits safer and reducing accidental UI regressions during rapid updates.
  • Auto-generated and validated 13 resume variants and kept role-specific links consistent, so resume content stayed accurate whenever project details changed.

aws

  • Designed a portfolio experience with a 6-panel desktop layout and smooth mobile flow, so hiring managers could scan skills, projects, and resume links quickly without getting lost in navigation.
  • Added 3 themes and 15 accent colors to keep content readable across preferences, improving first impressions for recruiters and reducing friction for returning visitors.
  • Set up 5 spam checks on the contact form and cut low-quality submissions, so real recruiter outreach was easier to identify and respond to quickly.
  • Split styles into 12 small CSS modules (under 200 lines each), making edits safer and reducing accidental UI regressions during rapid updates.
  • Auto-generated and validated 13 resume variants and kept role-specific links consistent, so resume content stayed accurate whenever project details changed.

python

  • Designed a portfolio experience with a 6-panel desktop layout and smooth mobile flow, so hiring managers could scan skills, projects, and resume links quickly without getting lost in navigation.
  • Added 3 themes and 15 accent colors to keep content readable across preferences, improving first impressions for recruiters and reducing friction for returning visitors.
  • Set up 5 spam checks on the contact form and cut low-quality submissions, so real recruiter outreach was easier to identify and respond to quickly.
  • Split styles into 12 small CSS modules (under 200 lines each), making edits safer and reducing accidental UI regressions during rapid updates.
  • Auto-generated and validated 13 resume variants and kept role-specific links consistent, so resume content stayed accurate whenever project details changed.

aws-web-dev

  • Designed a portfolio experience with a 6-panel desktop layout and smooth mobile flow, so hiring managers could scan skills, projects, and resume links quickly without getting lost in navigation.
  • Added 3 themes and 15 accent colors to keep content readable across preferences, improving first impressions for recruiters and reducing friction for returning visitors.
  • Set up 5 spam checks on the contact form and cut low-quality submissions, so real recruiter outreach was easier to identify and respond to quickly.
  • Split styles into 12 small CSS modules (under 200 lines each), making edits safer and reducing accidental UI regressions during rapid updates.
  • Auto-generated and validated 13 resume variants and kept role-specific links consistent, so resume content stayed accurate whenever project details changed.

aws-python

  • Designed a portfolio experience with a 6-panel desktop layout and smooth mobile flow, so hiring managers could scan skills, projects, and resume links quickly without getting lost in navigation.
  • Added 3 themes and 15 accent colors to keep content readable across preferences, improving first impressions for recruiters and reducing friction for returning visitors.
  • Set up 5 spam checks on the contact form and cut low-quality submissions, so real recruiter outreach was easier to identify and respond to quickly.
  • Split styles into 12 small CSS modules (under 200 lines each), making edits safer and reducing accidental UI regressions during rapid updates.
  • Auto-generated and validated 13 resume variants and kept role-specific links consistent, so resume content stayed accurate whenever project details changed.

web-dev-django

  • Designed a portfolio experience with a 6-panel desktop layout and smooth mobile flow, so hiring managers could scan skills, projects, and resume links quickly without getting lost in navigation.
  • Added 3 themes and 15 accent colors to keep content readable across preferences, improving first impressions for recruiters and reducing friction for returning visitors.
  • Set up 5 spam checks on the contact form and cut low-quality submissions, so real recruiter outreach was easier to identify and respond to quickly.
  • Split styles into 12 small CSS modules (under 200 lines each), making edits safer and reducing accidental UI regressions during rapid updates.
  • Auto-generated and validated 13 resume variants and kept role-specific links consistent, so resume content stayed accurate whenever project details changed.

it-support

  • Built a portfolio that is easy to scan with a 6-panel desktop layout, so recruiters can find key information quickly on both desktop and mobile.
  • Added 3 themes and 15 color options to improve readability for different viewers and make longer browsing sessions more comfortable.
  • Used 5 spam checks in the contact form and reduced junk messages, so real hiring conversations received faster attention.
  • Kept 13 resume variants aligned automatically and avoided manual cleanup, so each role-focused resume stayed accurate after content updates.
  • Organized styles into 12 small modules (under 200 lines each) and made updates predictable, reducing avoidable rework during iterative changes.

it-support-aws

  • Built a portfolio that is easy to scan with a 6-panel desktop layout, so recruiters can find key information quickly on both desktop and mobile.
  • Added 3 themes and 15 color options to improve readability for different viewers and make longer browsing sessions more comfortable.
  • Used 5 spam checks in the contact form and reduced junk messages, so real hiring conversations received faster attention.
  • Kept 13 resume variants aligned automatically and avoided manual cleanup, so each role-focused resume stayed accurate after content updates.
  • Organized styles into 12 small modules (under 200 lines each) and made updates predictable, reducing avoidable rework during iterative changes.

sales

  • Built a portfolio that is easy to scan with a 6-panel desktop layout, so recruiters can find key information quickly on both desktop and mobile.
  • Added 3 themes and 15 color options to improve readability for different viewers and make longer browsing sessions more comfortable.
  • Used 5 spam checks in the contact form and reduced junk messages, so real hiring conversations received faster attention.
  • Kept 13 resume variants aligned automatically and avoided manual cleanup, so each role-focused resume stayed accurate after content updates.
  • Organized styles into 12 small modules (under 200 lines each) and made updates predictable, reducing avoidable rework during iterative changes.

call-centre

  • Built a portfolio that is easy to scan with a 6-panel desktop layout, so recruiters can find key information quickly on both desktop and mobile.
  • Added 3 themes and 15 color options to improve readability for different viewers and make longer browsing sessions more comfortable.
  • Used 5 spam checks in the contact form and reduced junk messages, so real hiring conversations received faster attention.
  • Kept 13 resume variants aligned automatically and avoided manual cleanup, so each role-focused resume stayed accurate after content updates.
  • Organized styles into 12 small modules (under 200 lines each) and made updates predictable, reducing avoidable rework during iterative changes.

📧 Contact

David Leer


Built with <3 by @kmokdefi

⬆ Back to Top

About

Personal portfolio site built with Next.js 15 + TypeScript + Tailwind. Showcases projects, resume variants, and production-minded frontend engineering.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors