From b9ae470bc1a51ebe2c06fe005c6c45ca1dd87ce7 Mon Sep 17 00:00:00 2001
From: Story Crater Bot <19826264+Riotpiaole@users.noreply.github.com>
Date: Mon, 31 Aug 2026 13:59:46 -0700
Subject: [PATCH] feat: portfolio redesign with i18n, RBC project showcase,
CI/CD
- Add i18n support (EN/ZH) with language toggle
- Redesign header with education dropdown, contact copy buttons
- Add RBC project showcase with bullet points, skills highlighting
- Create terraform-drift placeholder page
- Add ProjectShowcase component with media toggle (image/video)
- Update experience timeline with action-driven descriptions
- Add Docker + Forgejo CI workflow for image builds
- Update K8s manifests for riotpiao.com ingress
- Add DESIGN.md documenting design system patterns
---
.dockerignore | 15 +
.forgejo/workflows/build-push.yml | 58 +++
DESIGN.md | 341 ++++++++++++++++++
Dockerfile | 45 +++
app/layout.tsx | 10 +-
app/page.tsx | 198 ++++++-----
app/terraform-drift/page.tsx | 51 +++
build.sh | 13 +
components/ExperienceTimeline.tsx | 104 +++---
components/Header.tsx | 342 ++++++++++++++++--
components/HeroBlobFlow.tsx | 126 ++++---
components/InteractiveTerminal.tsx | 14 +-
components/ProjectShowcase.tsx | 200 +++++++++++
infra/argocd-apps.yaml | 6 +-
infra/auth-infra/base/ingress-protected.yaml | 18 +-
infra/homarr/base/helmrelease.yaml | 4 +-
infra/homarr/base/ingress.yaml | 4 +-
infra/portfolio/base/deployment.yaml | 2 +-
infra/portfolio/base/ingress.yaml | 7 +-
lib/LanguageContext.tsx | 34 ++
lib/TerminalContext.tsx | 28 ++
lib/translations.json | 354 +++++++++++++++++++
public/avatar.jpeg | Bin 0 -> 30373 bytes
public/hire-me-light.png | Bin 0 -> 1531123 bytes
public/hire-me.png | Bin 0 -> 1850232 bytes
public/rbc-images.jpeg | Bin 0 -> 59480 bytes
26 files changed, 1724 insertions(+), 250 deletions(-)
create mode 100644 .dockerignore
create mode 100644 .forgejo/workflows/build-push.yml
create mode 100644 DESIGN.md
create mode 100644 Dockerfile
create mode 100644 app/terraform-drift/page.tsx
create mode 100755 build.sh
create mode 100644 components/ProjectShowcase.tsx
create mode 100644 lib/LanguageContext.tsx
create mode 100644 lib/TerminalContext.tsx
create mode 100644 lib/translations.json
create mode 100644 public/avatar.jpeg
create mode 100644 public/hire-me-light.png
create mode 100644 public/hire-me.png
create mode 100644 public/rbc-images.jpeg
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..69bc5d7
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,15 @@
+node_modules
+npm-debug.log
+.git
+.gitignore
+README.md
+.env
+.env.local
+.env.*.local
+.next
+.DS_Store
+*.log
+infra
+.claude
+.vscode
+.idea
diff --git a/.forgejo/workflows/build-push.yml b/.forgejo/workflows/build-push.yml
new file mode 100644
index 0000000..5904eeb
--- /dev/null
+++ b/.forgejo/workflows/build-push.yml
@@ -0,0 +1,58 @@
+name: Build & Push Portfolio Image
+
+on:
+ push:
+ branches:
+ - main
+ paths:
+ - 'app/**'
+ - 'components/**'
+ - 'lib/**'
+ - 'public/**'
+ - 'styles/**'
+ - 'package.json'
+ - 'pnpm-lock.yaml'
+ - 'next.config.js'
+ - 'tsconfig.json'
+ - 'Dockerfile'
+ - '.dockerignore'
+
+jobs:
+ build-push:
+ runs-on: node
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Login to Forgejo Registry
+ uses: docker/login-action@v3
+ with:
+ registry: forgejo.riotpiao.com
+ username: ${{ secrets.FORGEJO_REGISTRY_USER }}
+ password: ${{ secrets.FORGEJO_REGISTRY_TOKEN }}
+
+ - name: Extract metadata
+ id: meta
+ run: |
+ echo "timestamp=$(date -u +'%Y%m%d-%H%M%S')" >> $GITHUB_OUTPUT
+ echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
+
+ - name: Build and push Docker image
+ uses: docker/build-push-action@v5
+ with:
+ context: .
+ push: true
+ tags: |
+ forgejo.riotpiao.com/rock/portfolio:latest
+ forgejo.riotpiao.com/rock/portfolio:${{ steps.meta.outputs.sha_short }}
+ platforms: linux/amd64
+ cache-from: type=registry,ref=forgejo.riotpiao.com/rock/portfolio:buildcache
+ cache-to: type=registry,ref=forgejo.riotpiao.com/rock/portfolio:buildcache,mode=max
+
+ - name: Verify image pushed
+ run: |
+ echo "✓ Image pushed to forgejo.riotpiao.com/rock/portfolio:latest"
+ echo "✓ Image tagged with SHA: ${{ steps.meta.outputs.sha_short }}"
diff --git a/DESIGN.md b/DESIGN.md
new file mode 100644
index 0000000..1db92b2
--- /dev/null
+++ b/DESIGN.md
@@ -0,0 +1,341 @@
+# Portfolio Design System
+
+## Color Palette
+
+### Primary Colors
+- **Blue**: `blue-600` (primary actions, links, accents)
+- **Purple**: `purple-600` (gradients, secondary accents)
+- **Green**: `green-500` (live status, success)
+
+### Neutral Colors
+- **Light Mode**:
+ - Background: `white`, `gray-50`
+ - Text Primary: `gray-900`
+ - Text Secondary: `gray-600`, `gray-700`
+ - Borders: `gray-200`, `gray-300`
+
+- **Dark Mode**:
+ - Background: `gray-950`, `gray-900`
+ - Text Primary: `white`
+ - Text Secondary: `gray-400`, `gray-300`
+ - Borders: `gray-800`, `gray-700`
+
+### Status Colors
+- Live: `green-100/900` bg, `green-800/200` text
+- Building: `blue-100/900` bg, `blue-800/200` text
+- Planning: `gray-100/800` bg, `gray-800/200` text
+
+### Timeline Colors (gradients)
+- riotpiao.com: `from-green-500 to-green-600`
+- RBC: `from-red-500 to-red-600`
+- AWS: `from-orange-500 to-orange-600`
+- Titus: `from-cyan-500 to-cyan-600`
+- NAV Canada: `from-blue-500 to-blue-600`
+
+---
+
+## Typography
+
+### Font Sizes
+- Hero Title: `text-4xl md:text-5xl font-bold`
+- Section Title: `text-4xl font-bold`
+- Card Title: `text-2xl font-bold` or `text-xl font-bold`
+- Subtitle: `text-xl font-medium` or `text-lg`
+- Body: `text-sm` or `text-base`
+- Caption: `text-xs`
+- Mono/Code: `font-mono text-xs`
+
+### Font Weights
+- Bold: `font-bold` (titles, emphasis)
+- Semibold: `font-semibold` (subtitles, labels)
+- Medium: `font-medium` (secondary text)
+
+---
+
+## Spacing
+
+### Layout
+- Max Width: `max-w-6xl` (main container), `max-w-4xl` (content), `max-w-3xl` (cards), `max-w-5xl` (hero image)
+- Padding: `px-6` (horizontal), `py-20` or `py-24` (section vertical)
+- Gap: `gap-8` (cards), `gap-6` (nav items), `gap-4` (buttons), `gap-2` (tags)
+
+### Component Spacing
+- Section margin bottom: `mb-16`
+- Card padding: `p-6`
+- Button padding: `px-8 py-3` (large), `px-4 py-2` (medium), `px-3 py-1` (small)
+
+---
+
+## Components
+
+### Buttons
+
+**Primary Button**
+```jsx
+className="bg-blue-600 hover:bg-blue-700 text-white px-8 py-3 rounded-lg font-semibold transition"
+```
+
+**Secondary/Outline Button**
+```jsx
+className="border-2 border-gray-300 dark:border-gray-600 text-gray-900 dark:text-white hover:bg-gray-100 dark:hover:bg-gray-800 px-4 py-2 rounded-lg font-semibold transition"
+```
+
+**Language Toggle**
+```jsx
+className="px-3 py-1 text-sm font-semibold rounded border border-gray-300 dark:border-gray-600 hover:bg-gray-100 dark:hover:bg-gray-800"
+```
+
+**Icon Button**
+```jsx
+className="p-2 hover:bg-gray-100 dark:hover:bg-gray-800 rounded"
+```
+
+### Cards
+
+**Standard Card**
+```jsx
+className="bg-white dark:bg-gray-900 rounded-lg border border-gray-200 dark:border-gray-800 p-6 hover:shadow-lg transition-shadow"
+```
+
+**Project Showcase Card**
+```jsx
+className="bg-white dark:bg-gray-900 rounded-lg border border-gray-200 dark:border-gray-800 overflow-hidden hover:shadow-lg transition-shadow"
+```
+
+### Tags/Pills
+
+**Skill Tag**
+```jsx
+className="text-xs px-3 py-1 rounded-full bg-gray-100 dark:bg-gray-800 text-gray-700 dark:text-gray-300"
+```
+
+**Status Badge**
+```jsx
+// Live
+className="px-3 py-1 rounded-full text-xs font-semibold bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200"
+// Building
+className="px-3 py-1 rounded-full text-xs font-semibold bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200"
+```
+
+### Dropdowns
+
+**Dropdown Container**
+```jsx
+className="absolute right-0 mt-2 w-64 bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-800 rounded-lg shadow-lg p-4 space-y-3"
+```
+
+### Modals
+
+**Modal Overlay**
+```jsx
+className="fixed inset-0 bg-black/50 z-50 flex items-center justify-center p-4"
+```
+
+**Modal Content**
+```jsx
+className="bg-white dark:bg-gray-900 rounded-lg shadow-2xl max-w-2xl w-full max-h-96 overflow-y-auto"
+```
+
+**Modal Header (Gradient)**
+```jsx
+className="sticky top-0 bg-gradient-to-r from-blue-600 to-purple-600 px-6 py-6 flex justify-between items-center"
+```
+
+---
+
+## Animations (Framer Motion)
+
+### Fade In Up
+```jsx
+initial={{ opacity: 0, y: 20 }}
+animate={{ opacity: 1, y: 0 }}
+transition={{ duration: 0.8, delay: 0.2 }}
+```
+
+### Scale In
+```jsx
+initial={{ scale: 0, opacity: 0 }}
+animate={{ scale: 1, opacity: 1 }}
+transition={{ duration: 0.8, delay: 0.2 }}
+```
+
+### Stagger Children
+```jsx
+variants={{
+ hidden: { opacity: 0 },
+ visible: {
+ opacity: 1,
+ transition: { staggerChildren: 0.15 },
+ },
+}}
+```
+
+### Role Text Rotation
+```jsx
+initial={{ opacity: 0, y: 20, scale: 0.95 }}
+animate={{ opacity: 1, y: 0, scale: 1 }}
+exit={{ opacity: 0, y: -20, scale: 0.95 }}
+transition={{ duration: 0.6, ease: 'easeInOut' }}
+```
+
+### Background Pulse
+```jsx
+animate={{
+ scale: [1, 1.15, 1],
+ opacity: [0.25, 0.4, 0.25],
+}}
+transition={{
+ duration: 6,
+ repeat: Infinity,
+ ease: 'easeInOut',
+}}
+```
+
+---
+
+## Gradients
+
+### Hero Background
+```jsx
+className="bg-gradient-to-br from-blue-50 to-purple-50 dark:from-gray-950 dark:to-gray-900"
+```
+
+### Timeline Line
+```jsx
+className="bg-gradient-to-b from-blue-500 via-purple-500 to-green-500"
+```
+
+### Stat Highlight
+```jsx
+className="bg-gradient-to-r from-blue-50 to-purple-50 dark:from-gray-800 dark:to-gray-800"
+```
+
+### Modal Header
+```jsx
+className="bg-gradient-to-r from-blue-600 to-purple-600"
+```
+
+---
+
+## Z-Index Layers
+
+- `z-0`: Background images
+- `z-10`: Content overlays (avatar, text)
+- `z-20`: Avatar + rotating text group
+- `z-40`: Terminal button
+- `z-50`: Header, Modals
+
+---
+
+## Responsive Breakpoints
+
+- Mobile: Default (no prefix)
+- Tablet/Desktop: `md:` (768px+)
+- Large Desktop: `lg:` (1024px+)
+
+### Common Patterns
+```jsx
+// Hide on mobile, show on desktop
+className="hidden md:flex"
+
+// Show on mobile, hide on desktop
+className="md:hidden"
+
+// Responsive grid
+className="grid grid-cols-1 md:grid-cols-2 gap-8"
+
+// Responsive text
+className="text-4xl md:text-5xl"
+
+// Responsive padding
+className="px-4 md:px-6"
+```
+
+---
+
+## Icons (Lucide React)
+
+### Sizes
+- Navigation: `size={20}`
+- Buttons: `size={16}`
+- Cards: `size={24}`
+- Hero: `size={32}`
+- Close: `size={24}`
+
+### Common Icons
+- `Menu`, `X` - Mobile nav
+- `Moon`, `Sun` - Theme toggle
+- `ExternalLink` - External links
+- `Network`, `Shield`, `Code`, `Sparkles`, `Zap`, `Cpu` - Role icons
+- `GitBranch`, `Database`, `MessageSquare`, `Layers`, `BarChart3` - Feature icons
+
+---
+
+## Internationalization (i18n)
+
+### Structure
+```
+lib/
+ translations.json # All translations
+ LanguageContext.tsx # React context provider
+```
+
+### Usage
+```jsx
+import { useLanguage } from '@/lib/LanguageContext'
+
+const { lang, setLang, t } = useLanguage()
+
+// Access translations
+
{t.hero.title}
+```
+
+### Language Toggle Button
+Shows opposite language:
+- When `en`: Shows `中文`
+- When `zh`: Shows `EN`
+
+---
+
+## File Structure
+
+```
+components/
+ Header.tsx # Navigation, dropdowns, language toggle
+ HeroBlobFlow.tsx # Hero with avatar, rotating roles
+ ExperienceTimeline.tsx # Work history timeline
+ ProjectShowcase.tsx # Project cards
+ InteractiveTerminal.tsx # Cmd+K terminal
+ TypewriterText.tsx # Typewriter effect
+
+lib/
+ TerminalContext.tsx # Terminal open/close state
+ LanguageContext.tsx # Language state + translations
+ translations.json # EN/ZH translations
+
+app/
+ page.tsx # Main page
+ layout.tsx # Root layout with providers
+ globals.css # Tailwind + global styles
+
+public/
+ avatar.jpeg # Profile photo
+ hire-me.png # Dark mode hero background
+ hire-me-light.png # Light mode hero background
+```
+
+---
+
+## Dark Mode
+
+Implemented via Tailwind's `dark:` prefix. Toggle class on `` element.
+
+```jsx
+// Toggle
+document.documentElement.classList.toggle('dark')
+
+// Check
+document.documentElement.classList.contains('dark')
+```
+
+Observe changes via MutationObserver for components that need to react to theme changes (e.g., background image swap).
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..26aadee
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,45 @@
+# Build stage
+FROM node:20-alpine AS builder
+
+WORKDIR /app
+
+# Copy package files
+COPY package.json pnpm-lock.yaml ./
+
+# Install pnpm
+RUN npm install -g pnpm
+
+# Install dependencies
+RUN pnpm install --frozen-lockfile
+
+# Copy source
+COPY . .
+
+# Build Next.js app
+RUN pnpm run build
+
+# Production stage
+FROM node:20-alpine
+
+WORKDIR /app
+
+# Install dumb-init for proper signal handling
+RUN apk add --no-cache dumb-init
+
+# Create non-root user
+RUN addgroup -g 1001 -S nodejs && \
+ adduser -S nextjs -u 1001
+
+# Copy built app from builder
+COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
+COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
+COPY --from=builder --chown=nextjs:nodejs /app/public ./public
+
+USER nextjs
+
+EXPOSE 3000
+
+ENV NODE_ENV=production
+
+ENTRYPOINT ["dumb-init", "--"]
+CMD ["node", "server.js"]
diff --git a/app/layout.tsx b/app/layout.tsx
index 6c51a91..625de0f 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -1,5 +1,7 @@
import './globals.css'
import Header from '@/components/Header'
+import { TerminalProvider } from '@/lib/TerminalContext'
+import { LanguageProvider } from '@/lib/LanguageContext'
export const metadata = {
title: 'Rock Liang — Portfolio & Live Infrastructure',
@@ -14,8 +16,12 @@ export default function RootLayout({
return (
-
- {children}
+
+
+
+ {children}
+
+
);
diff --git a/app/page.tsx b/app/page.tsx
index 4f7d55a..e3b71e6 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -1,71 +1,35 @@
'use client'
import { motion } from 'framer-motion'
-import { FeatureCard } from '@/components/FeatureCard'
+import { useState } from 'react'
+import { X } from 'lucide-react'
+import { ProjectShowcase } from '@/components/ProjectShowcase'
import { HeroBlobFlow } from '@/components/HeroBlobFlow'
import { InteractiveTerminal } from '@/components/InteractiveTerminal'
import { ExperienceTimeline } from '@/components/ExperienceTimeline'
-import {
- GitBranch,
- Database,
- BarChart3,
- MessageSquare,
- Cpu,
- Layers,
-} from 'lucide-react'
-
-const features = [
- {
- icon: GitBranch,
- title: 'Infrastructure Platform',
- description: 'Multi-region Terraform + Argo CD GitOps on Kubernetes',
- href: '/infrastructure',
- stat: '40% CPU reduction',
- status: 'live' as const,
- },
- {
- icon: Cpu,
- title: 'Distributed Systems',
- description: 'gRPC, Kafka, AWS Step Functions across 57+ regions',
- href: '/systems',
- stat: 'Mission-critical',
- status: 'live' as const,
- },
- {
- icon: MessageSquare,
- title: 'LLM Systems',
- description: 'CPU-bound inference optimization, INT4/INT8 quantization',
- href: '/llm',
- stat: '60% latency cut',
- status: 'live' as const,
- },
- {
- icon: Database,
- title: 'Kafka Cluster',
- description: 'Strimzi KRaft cluster with auto-scaling brokers',
- href: '/kafka',
- stat: '3 brokers',
- status: 'live' as const,
- },
- {
- icon: Layers,
- title: 'Open Source',
- description: 'go-flink: distributed DataLakeHouse in Go',
- href: '/opensource',
- stat: 'Public repo',
- status: 'live' as const,
- },
- {
- icon: BarChart3,
- title: 'Observability',
- description: 'Prometheus, Grafana, Dynatrace — live metrics',
- href: '/infrastructure',
- stat: '99.2% uptime',
- status: 'live' as const,
- },
-]
+import { useLanguage } from '@/lib/LanguageContext'
export default function Home() {
+ const [bioModalOpen, setBioModalOpen] = useState(false)
+ const { t } = useLanguage()
+
+ const projects = t.projects.items.map((item, index) => ({
+ ...item,
+ id: index === 1 ? 'project-rbc' : undefined,
+ status: index === 1
+ ? 'completed' as const
+ : index === 5
+ ? 'building' as const
+ : 'live' as const,
+ media: index === 0
+ ? { type: 'video' as const, url: 'https://www.youtube.com/watch?v=wdJ5DN15jus' }
+ : index === 1
+ ? { type: 'image' as const, url: '/rbc-images.jpeg' }
+ : undefined,
+ videoUrl: index === 5 ? 'https://github.com/rockliang/go-flink' : '#',
+ articleUrl: index === 0 ? 'https://lnkd.in/p/gm2PZkWw' : '#',
+ }))
+
return (
{/* Hero */}
@@ -82,30 +46,22 @@ export default function Home() {
className="text-center mt-16"
>
- Full-Stack Systems Engineer
+ {t.hero.title}
- Infrastructure × Backend × LLM Systems
+ {t.hero.subtitle}
- Building observable, fault-tolerant systems from bare metal to cloud. Optimizing cost (infrastructure) × performance (inference) × reliability (SRE).
+ {t.hero.description}
- 💡 Press Cmd+K to explore via terminal
+ 💡 {t.hero.terminalHint} Cmd+K {t.hero.terminalHintSuffix}
@@ -132,9 +88,9 @@ export default function Home() {
transition={{ duration: 0.6 }}
className="mb-16"
>
- What I Build
+ {t.projects.title}
- Production systems spanning infrastructure, distributed backends, and LLM optimization. Click any domain to explore.
+ {t.projects.subtitle}
@@ -147,14 +103,20 @@ export default function Home() {
visible: {
opacity: 1,
transition: {
- staggerChildren: 0.1,
+ staggerChildren: 0.15,
},
},
}}
- className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"
+ className="grid grid-cols-1 gap-8 max-w-3xl mx-auto"
>
- {features.map((feature) => (
-
+ {projects.map((project) => (
+
))}
@@ -162,14 +124,14 @@ export default function Home() {
{/* Footer */}
)
}
diff --git a/app/terraform-drift/page.tsx b/app/terraform-drift/page.tsx
new file mode 100644
index 0000000..256f8b3
--- /dev/null
+++ b/app/terraform-drift/page.tsx
@@ -0,0 +1,51 @@
+'use client'
+
+import Link from 'next/link'
+import { ArrowLeft } from 'lucide-react'
+
+export default function TerraformDriftPage() {
+ return (
+
+
+
+
+ Back to Projects
+
+
+
+ Terraform State Drift Solution
+
+
+
+ Coming soon...
+
+
+ {/* Placeholder sections */}
+
+
+
The Problem
+
Content coming soon...
+
+
+
+
Immediate Fix
+
Content coming soon...
+
+
+
+
Short Term Fix
+
Content coming soon...
+
+
+
+
Long Term Fix
+
Content coming soon...
+
+
+
+
+ )
+}
diff --git a/build.sh b/build.sh
new file mode 100755
index 0000000..007750e
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+set -euo pipefail
+
+REGISTRY="${REGISTRY:-forgejo.riotpiao.com}"
+IMAGE="${REGISTRY}/rock/portfolio:latest"
+
+echo "Building image: ${IMAGE}"
+docker buildx build --platform linux/amd64 -t "${IMAGE}" .
+
+echo "Pushing image..."
+docker push "${IMAGE}"
+
+echo "✓ Successfully pushed ${IMAGE}"
diff --git a/components/ExperienceTimeline.tsx b/components/ExperienceTimeline.tsx
index 500806a..cf29081 100644
--- a/components/ExperienceTimeline.tsx
+++ b/components/ExperienceTimeline.tsx
@@ -1,54 +1,38 @@
'use client'
import { motion } from 'framer-motion'
+import { useLanguage } from '@/lib/LanguageContext'
-interface TimelineItem {
- company: string
- role: string
- period: string
- description: string
- impact: string
- skills: string[]
- color: string
-}
+const colors = [
+ 'from-green-500 to-green-600',
+ 'from-red-500 to-red-600',
+ 'from-orange-500 to-orange-600',
+ 'from-cyan-500 to-cyan-600',
+ 'from-blue-500 to-blue-600',
+]
-const timeline: TimelineItem[] = [
- {
- company: 'RBC',
- role: 'Infrastructure Platform Architect',
- period: '2020 — Present',
- description: 'Leading multi-region infrastructure platform on Kubernetes. Building GitOps workflows with Terraform and Argo CD across 4 global regions.',
- impact: '40% CPU reduction, 99.2% uptime',
- skills: ['Kubernetes', 'Terraform', 'Argo CD', 'Go', 'AWS', 'Cilium', 'Prometheus', 'Grafana'],
- color: 'from-blue-500 to-blue-600',
- },
- {
- company: 'AWS',
- role: 'Senior Software Engineer (Step Functions)',
- period: '2019 — 2020',
- description: 'Designed and optimized distributed orchestration platform. Built fault-tolerant task scheduling across 57+ regions serving mission-critical workloads.',
- impact: '8 core components, 57+ regions',
- skills: ['AWS', 'Java', 'gRPC', 'Distributed Systems', 'DynamoDB', 'CloudWatch'],
- color: 'from-orange-500 to-orange-600',
- },
- {
- company: 'Homelab',
- role: 'DevOps / SRE / SDE',
- period: '2021 — Present',
- description: 'Production-grade bare-metal K8s cluster (Talos + Cilium). Built Temporal-based LLM inference pipeline with CPU-bound optimization and quantization.',
- impact: '60% latency cut, 75% memory saved',
- skills: ['LangGraph', 'Temporal', 'LLM Ops', 'PyTorch', 'Kafka', 'Observability'],
- color: 'from-green-500 to-green-600',
- },
- {
- company: 'Open Source',
- role: 'Maintainer — go-flink',
- period: '2022 — Present',
- description: 'Building distributed DataLakeHouse framework in Go. Fault-tolerant task scheduling, streaming semantics, and efficient data processing.',
- impact: 'Public repository, active development',
- skills: ['Go', 'Distributed Systems', 'Data Pipeline', 'Testing', 'Architecture'],
- color: 'from-purple-500 to-purple-600',
- },
+const skills = [
+ ['LangGraph', 'Temporal', 'LLM Ops', 'PyTorch', 'Kafka', 'Observability', 'Go-Flink'],
+ ['Golang', 'Terraform', 'IaC', 'OpenShift', 'Docker', 'Distributed Systems', 'Grafana'],
+ ['AWS', 'Java', 'gRPC', 'Distributed Systems', 'DynamoDB', 'CloudWatch'],
+ ['Machine Learning', 'Golang', 'Anomaly Detection', 'C++', 'CMake', 'Data Security'],
+ ['Django', 'React', 'Agile', 'Web Development', 'Sonar', 'ATC Systems'],
+]
+
+const links = [
+ null,
+ '#project-rbc', // RBC - link to RBC project showcase
+ null,
+ null,
+ 'https://plan.navcanada.ca/account/login/?next=/',
+]
+
+const linkTexts = [
+ '',
+ 'Learn more →',
+ '',
+ '',
+ 'View Product →',
]
const containerVariants = {
@@ -71,6 +55,9 @@ const itemVariants = {
}
export function ExperienceTimeline() {
+ const { t } = useLanguage()
+ const timeline = t.experience.items
+
return (
- Explore Experience
+ {t.experience.title}
- From AWS to RBC. Building systems at scale. Skills acquired along the journey.
+ {t.experience.subtitle}
@@ -105,7 +92,7 @@ export function ExperienceTimeline() {
className="relative pl-8 md:pl-0"
>
{/* Timeline dot */}
-
+
{/* Content card */}
@@ -128,17 +115,24 @@ export function ExperienceTimeline() {
{item.description}
-
- 📊 {item.impact}
-
-
-
diff --git a/components/Header.tsx b/components/Header.tsx
index 6b1e0db..d172eff 100644
--- a/components/Header.tsx
+++ b/components/Header.tsx
@@ -1,12 +1,31 @@
'use client'
import Link from 'next/link'
+import Image from 'next/image'
import { Menu, X, Moon, Sun } from 'lucide-react'
import { useState, useEffect } from 'react'
+import { useTerminal } from '@/lib/TerminalContext'
+import { useLanguage } from '@/lib/LanguageContext'
export default function Header() {
const [open, setOpen] = useState(false)
const [dark, setDark] = useState(false)
+ const [skillsOpen, setSkillsOpen] = useState(false)
+ const [contactOpen, setContactOpen] = useState(false)
+ const [educationOpen, setEducationOpen] = useState(false)
+ const { isOpen: terminalOpen, setIsOpen: setTerminalOpen } = useTerminal()
+ const { lang, setLang, t } = useLanguage()
+ const [copied, setCopied] = useState(null)
+
+ const handleCopy = (text: string, label: string) => {
+ navigator.clipboard.writeText(text)
+ setCopied(label)
+ setTimeout(() => setCopied(null), 2000)
+ }
+
+ const toggleLang = () => {
+ setLang(lang === 'en' ? 'zh' : 'en')
+ }
useEffect(() => {
const isDark = document.documentElement.classList.contains('dark')
@@ -22,42 +41,315 @@ export default function Header() {
-
- RL
-
+
-
Rock Liang
-
Software Engineer Lead
+
{t.header.title}
+
{t.header.subtitle}
- Home
- Cluster
- Infrastructure
- Kafka
- CI/CD
- Agent
-
- {dark ? : }
+ {t.header.nav.home}
+ setTerminalOpen(!terminalOpen)}
+ className="text-sm hover:text-blue-600 dark:hover:text-blue-400"
+ >
+ {t.header.nav.askPoimen}
+
+
setSkillsOpen(!skillsOpen)}
+ className="text-sm hover:text-blue-600 dark:hover:text-blue-400"
+ >
+ {t.header.nav.skills}
+
+ {skillsOpen && (
+
+
{t.header.skillsPlaceholder}
+
+ )}
+
+
+
setContactOpen(!contactOpen)}
+ className="text-sm hover:text-blue-600 dark:hover:text-blue-400"
+ >
+ {t.header.nav.contact}
+
+ {contactOpen && (
+
+
+
+ {t.header.contact.portfolio}
+
+ handleCopy('https://portfolio.riotpiao.com', 'Portfolio')}
+ className="text-xs px-2 py-1 rounded bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-400 hover:bg-blue-100 dark:hover:bg-blue-900"
+ >
+ {copied === 'Portfolio' ? '✓' : t.header.contact.copy}
+
+
+
+
+ {t.header.contact.github}
+
+
handleCopy('https://github.com/rockliang', 'GitHub')}
+ className="text-xs px-2 py-1 rounded bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-400 hover:bg-blue-100 dark:hover:bg-blue-900"
+ >
+ {copied === 'GitHub' ? '✓' : t.header.contact.copy}
+
+
+
+
+ {t.header.contact.privateGithub}
+
+
handleCopy('https://github.com/rockliang', 'PrivateGithub')}
+ className="text-xs px-2 py-1 rounded bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-400 hover:bg-blue-100 dark:hover:bg-blue-900"
+ >
+ {copied === 'PrivateGithub' ? '✓' : t.header.contact.copy}
+
+
+
+
+ {t.header.contact.linkedin}
+
+
handleCopy('https://www.linkedin.com/in/rockliang', 'LinkedIn')}
+ className="text-xs px-2 py-1 rounded bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-400 hover:bg-blue-100 dark:hover:bg-blue-900"
+ >
+ {copied === 'LinkedIn' ? '✓' : t.header.contact.copy}
+
+
+
+
+ {t.header.contact.email}
+
+
handleCopy('locartrock@gmail.com', 'Email')}
+ className="text-xs px-2 py-1 rounded bg-gray-100 dark:bg-gray-800 text-gray-600 dark:text-gray-400 hover:bg-blue-100 dark:hover:bg-blue-900"
+ >
+ {copied === 'Email' ? '✓' : t.header.contact.copy}
+
+
+
+ )}
+
+
+
+
{t.header.experience}
+
{t.header.experienceValue}
+
+
+
setEducationOpen(!educationOpen)}
+ className="text-xs cursor-pointer hover:text-blue-600 dark:hover:text-blue-400"
+ >
+ {t.header.education}
+ {t.header.educationValue}
+
+ {educationOpen && (
+
+
+
{t.header.educationDetails.bachelor.school}
+
{t.header.educationDetails.bachelor.degree}
+
{t.header.educationDetails.bachelor.period}
+
+
+
{t.header.educationDetails.master.school}
+
{t.header.educationDetails.master.degree}
+
{t.header.educationDetails.master.period}
+
+
+ )}
+
+
+ {dark ? : }
+
+ {/* Language Toggle */}
+
+ {lang === 'en' ? '中文' : 'EN'}
+
+
-
setOpen(!open)}
- className="md:hidden p-2"
- >
- {open ? : }
-
+
+ {/* Mobile Language Toggle */}
+
+ {lang === 'en' ? '中文' : 'EN'}
+
+ setOpen(!open)}
+ className="p-2"
+ >
+ {open ? : }
+
+
{open && (
-
-
Home
-
Infrastructure
-
Kafka
-
CI/CD
-
Agent
+
+
{t.header.nav.home}
+
setTerminalOpen(!terminalOpen)}
+ className="block py-2 text-sm hover:text-blue-600"
+ >
+ {t.header.nav.askPoimen}
+
+
setSkillsOpen(!skillsOpen)}
+ className="block py-2 text-sm hover:text-blue-600"
+ >
+ {t.header.nav.skills}
+
+ {skillsOpen && (
+
+
{t.header.skillsPlaceholder}
+
+ )}
+
setContactOpen(!contactOpen)}
+ className="block py-2 text-sm hover:text-blue-600"
+ >
+ {t.header.nav.contact}
+
+ {contactOpen && (
+
+
+
+ {t.header.contact.portfolio}
+
+ handleCopy('https://portfolio.riotpiao.com', 'Portfolio')}
+ className="text-xs px-2 py-1 rounded bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400 hover:bg-blue-100 dark:hover:bg-blue-900"
+ >
+ {copied === 'Portfolio' ? '✓' : t.header.contact.copy}
+
+
+
+
+ {t.header.contact.github}
+
+
handleCopy('https://github.com/rockliang', 'GitHub')}
+ className="text-xs px-2 py-1 rounded bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400 hover:bg-blue-100 dark:hover:bg-blue-900"
+ >
+ {copied === 'GitHub' ? '✓' : t.header.contact.copy}
+
+
+
+
+ {t.header.contact.privateGithub}
+
+
handleCopy('https://github.com/rockliang', 'PrivateGithub')}
+ className="text-xs px-2 py-1 rounded bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400 hover:bg-blue-100 dark:hover:bg-blue-900"
+ >
+ {copied === 'PrivateGithub' ? '✓' : t.header.contact.copy}
+
+
+
+
+ {t.header.contact.linkedin}
+
+
handleCopy('https://www.linkedin.com/in/rockliang', 'LinkedIn')}
+ className="text-xs px-2 py-1 rounded bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400 hover:bg-blue-100 dark:hover:bg-blue-900"
+ >
+ {copied === 'LinkedIn' ? '✓' : t.header.contact.copy}
+
+
+
+
+ {t.header.contact.email}
+
+
handleCopy('locartrock@gmail.com', 'Email')}
+ className="text-xs px-2 py-1 rounded bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-400 hover:bg-blue-100 dark:hover:bg-blue-900"
+ >
+ {copied === 'Email' ? '✓' : t.header.contact.copy}
+
+
+
+ )}
+
+
+
{t.header.experience}
+
{t.header.experienceValue}
+
+
+
setEducationOpen(!educationOpen)}
+ className="text-xs cursor-pointer hover:text-blue-600 dark:hover:text-blue-400 w-full text-left"
+ >
+ {t.header.education}
+ {t.header.educationValue}
+
+ {educationOpen && (
+
+
+
{t.header.educationDetails.bachelor.school}
+
{t.header.educationDetails.bachelor.degree}
+
{t.header.educationDetails.bachelor.period}
+
+
+
{t.header.educationDetails.master.school}
+
{t.header.educationDetails.master.degree}
+
{t.header.educationDetails.master.period}
+
+
+ )}
+
+
)}
diff --git a/components/HeroBlobFlow.tsx b/components/HeroBlobFlow.tsx
index 0a5dfdb..35341d8 100644
--- a/components/HeroBlobFlow.tsx
+++ b/components/HeroBlobFlow.tsx
@@ -2,78 +2,92 @@
import { motion, AnimatePresence } from 'framer-motion'
import { useState, useEffect } from 'react'
-import { Code, Network, Zap, Sparkles, Github } from 'lucide-react'
-import { TypewriterText } from './TypewriterText'
+import Image from 'next/image'
+import { Code, Network, Zap, Sparkles, Shield, Cpu } from 'lucide-react'
+import { useLanguage } from '@/lib/LanguageContext'
-const roles = [
- { text: 'Software Engineer Lead', icon: Code },
- { text: 'Infrastructure Architect', icon: Network },
- { text: 'Distributed Systems Builder', icon: Zap },
- { text: 'LLM Systems Optimizer', icon: Sparkles },
- { text: 'Open Source Developer', icon: Github },
-]
+const roleIcons = [Network, Shield, Code, Sparkles, Zap, Cpu]
export function HeroBlobFlow() {
const [index, setIndex] = useState(0)
+ const [isDark, setIsDark] = useState(false)
+ const { t } = useLanguage()
+ const roles = t.hero.roles
+
+ useEffect(() => {
+ const isDarkMode = document.documentElement.classList.contains('dark')
+ setIsDark(isDarkMode)
+
+ const observer = new MutationObserver(() => {
+ const darkMode = document.documentElement.classList.contains('dark')
+ setIsDark(darkMode)
+ })
+
+ observer.observe(document.documentElement, {
+ attributes: true,
+ attributeFilter: ['class'],
+ })
+
+ return () => observer.disconnect()
+ }, [])
useEffect(() => {
const interval = setInterval(() => {
setIndex((prev) => (prev + 1) % roles.length)
}, 2000)
return () => clearInterval(interval)
- }, [])
+ }, [roles.length])
return (
-
- {/* Background glow */}
-
-
+ {/* Full hire-me image */}
+
+
-
-
- {/* Avatar center */}
-
-
- RL
-
-
-
- {/* Typewriter text below avatar */}
-
-
- {/* Rotating role text */}
-
-
+
+ {/* Avatar + Rotating text - centered on image */}
+
+ {/* Avatar */}
- {(() => {
- const Icon = roles[index].icon
- return
- })()}
- {roles[index].text}
+
-
+
+ {/* Rotating role text */}
+
+
+
+ {(() => {
+ const Icon = roleIcons[index]
+ return
+ })()}
+ {roles[index]}
+
+
+
+
)
diff --git a/components/InteractiveTerminal.tsx b/components/InteractiveTerminal.tsx
index b6d8c8e..eb0bbb8 100644
--- a/components/InteractiveTerminal.tsx
+++ b/components/InteractiveTerminal.tsx
@@ -2,6 +2,7 @@
import { motion } from 'framer-motion'
import { useEffect, useRef, useState } from 'react'
+import { useTerminal } from '@/lib/TerminalContext'
const commands: Record
= {
help: `Available commands:
@@ -46,10 +47,15 @@ Open Source: go-flink (distributed DataLakeHouse)`,
export function InteractiveTerminal() {
const [input, setInput] = useState('')
const [history, setHistory] = useState<{ cmd: string; output: string }[]>([])
- const [isOpen, setIsOpen] = useState(false)
+ const { isOpen, setIsOpen } = useTerminal()
+ const [isMac, setIsMac] = useState(true)
const terminalRef = useRef(null)
useEffect(() => {
+ // Detect if user is on Mac
+ const isMacOS = /Mac|iPhone|iPad|iPod/.test(navigator.platform)
+ setIsMac(isMacOS)
+
const handleKeyDown = (e: KeyboardEvent) => {
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
e.preventDefault()
@@ -59,7 +65,7 @@ export function InteractiveTerminal() {
window.addEventListener('keydown', handleKeyDown)
return () => window.removeEventListener('keydown', handleKeyDown)
- }, [isOpen])
+ }, [isOpen, setIsOpen])
const handleCommand = (cmd: string) => {
const trimmed = cmd.trim().toLowerCase()
@@ -89,7 +95,7 @@ export function InteractiveTerminal() {
onClick={() => setIsOpen(true)}
className="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg font-mono text-sm shadow-lg"
>
- Terminal (Cmd+K)
+ Ask Poimen ({isMac ? 'Cmd' : 'Ctrl'}+K)
) : (
-
ZSH_THEME="robbyrussell"
+
Poimen (Agent Terminal)
setIsOpen(false)}
className="text-gray-400 hover:text-white"
diff --git a/components/ProjectShowcase.tsx b/components/ProjectShowcase.tsx
new file mode 100644
index 0000000..4d55321
--- /dev/null
+++ b/components/ProjectShowcase.tsx
@@ -0,0 +1,200 @@
+'use client'
+
+import { motion } from 'framer-motion'
+import { ExternalLink, MessageSquare } from 'lucide-react'
+import { useTerminal } from '@/lib/TerminalContext'
+
+interface ProjectShowcaseProps {
+ id?: string
+ title: string
+ description: string
+ longDescription?: string
+ stat: string
+ highlight?: string
+ status: 'live' | 'building' | 'planning' | 'completed'
+ media?: {
+ type: 'image' | 'video'
+ url: string
+ }
+ videoUrl?: string
+ articleUrl?: string
+ watchVideoText?: string
+ readArticleText?: string
+ askPoimenText?: string
+ bullets?: string[]
+ deepDive?: {
+ label: string
+ url: string
+ }
+}
+
+export function ProjectShowcase({
+ id,
+ title,
+ description,
+ longDescription,
+ stat,
+ highlight,
+ status,
+ media,
+ videoUrl,
+ articleUrl,
+ watchVideoText = 'Watch Video',
+ readArticleText = 'Read Article',
+ askPoimenText = 'Ask Poimen for technical details',
+ bullets,
+ deepDive,
+}: ProjectShowcaseProps) {
+ const { setIsOpen } = useTerminal()
+
+ const statusColors = {
+ live: 'bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200',
+ completed: 'bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200',
+ building: 'bg-blue-100 dark:bg-blue-900 text-blue-800 dark:text-blue-200',
+ planning: 'bg-gray-100 dark:bg-gray-800 text-gray-800 dark:text-gray-200',
+ }
+
+ return (
+
+ {/* Optional Media (Image or Video) */}
+ {media && (
+
+ {media.type === 'video' ? (
+ (() => {
+ const youtubeMatch = media.url.match(/(?:youtube\.com\/watch\?v=|youtu\.be\/)([^&]+)/)
+ if (youtubeMatch) {
+ return (
+
VIDEO
+ )
+ }
+ return null
+ })()
+ ) : (
+
+ )}
+
+ )}
+
+ {/* Content */}
+
+
+
+
+ {title}
+
+
+ {description}
+
+ {longDescription && (
+
+ {longDescription}
+
+ )}
+ {bullets && bullets.length > 0 && (
+
+ {bullets.map((bullet, i) => {
+ // Highlight skills: parentheses + keywords
+ const skillKeywords = ['Terraform', 'Golang', 'K8s', 'Slack', 'Grafana', 'IaC', 'Docker', 'OpenShift', 'Temporal', 'Kafka', 'gRPC', 'AWS', 'Java', 'Python', 'Go', 'C++']
+ const escapeRegex = (s: string) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
+ const pattern = new RegExp(`(\\([^)]+\\)|${skillKeywords.map(escapeRegex).join('|')})`, 'g')
+ const parts = bullet.split(pattern).filter(Boolean)
+ return (
+
+ •
+
+ {parts.map((part, j) =>
+ (part.startsWith('(') && part.endsWith(')')) || skillKeywords.includes(part) ? (
+
+ {part}
+
+ ) : (
+ {part}
+ )
+ )}
+
+
+ )
+ })}
+
+ )}
+ {deepDive && (
+
+ {deepDive.label}
+
+ )}
+
+
+ {status.charAt(0).toUpperCase() + status.slice(1)}
+
+
+
+ {/* Stat */}
+
+
+ 📊 {stat}
+
+ {highlight && (
+
+ 📊 {highlight}
+
+ )}
+
+
+ {/* CTA Buttons */}
+
+
+ {/* Ask Poimen */}
+
setIsOpen(true)}
+ className="mt-4 w-full text-sm text-gray-500 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 flex items-center justify-center gap-2 transition"
+ >
+
+ {askPoimenText}
+
+
+
+ )
+}
diff --git a/infra/argocd-apps.yaml b/infra/argocd-apps.yaml
index 84cc553..0bacdf1 100644
--- a/infra/argocd-apps.yaml
+++ b/infra/argocd-apps.yaml
@@ -6,7 +6,7 @@ metadata:
spec:
project: default
source:
- repoURL: https://forgejo.riotpiao.homelab.com/rock/riotpiao.git
+ repoURL: https://forgejo.riotpiao.com/rock/riotpiao.git
targetRevision: main
path: infra/portfolio/base
destination:
@@ -27,7 +27,7 @@ metadata:
spec:
project: default
source:
- repoURL: https://forgejo.riotpiao.homelab.com/rock/riotpiao.git
+ repoURL: https://forgejo.riotpiao.com/rock/riotpiao.git
targetRevision: main
path: infra/homarr/base
destination:
@@ -48,7 +48,7 @@ metadata:
spec:
project: default
source:
- repoURL: https://forgejo.riotpiao.homelab.com/rock/riotpiao.git
+ repoURL: https://forgejo.riotpiao.com/rock/riotpiao.git
targetRevision: main
path: infra/auth-infra/base
destination:
diff --git a/infra/auth-infra/base/ingress-protected.yaml b/infra/auth-infra/base/ingress-protected.yaml
index 6db9605..6068b40 100644
--- a/infra/auth-infra/base/ingress-protected.yaml
+++ b/infra/auth-infra/base/ingress-protected.yaml
@@ -5,17 +5,17 @@ metadata:
namespace: longhorn-system
annotations:
nginx.ingress.kubernetes.io/auth-url: http://authentik-server.iam.svc.cluster.local/outpost.goauthentik.io/auth/nginx
- nginx.ingress.kubernetes.io/auth-signin: https://authentik.riotpiao.homelab.com/outpost.goauthentik.io/start?rd=$scheme://$http_host$escaped_request_uri
+ nginx.ingress.kubernetes.io/auth-signin: https://authentik.riotpiao.com/outpost.goauthentik.io/start?rd=$scheme://$http_host$escaped_request_uri
nginx.ingress.kubernetes.io/auth-response-headers: Set-Cookie,X-authentik-username,X-authentik-groups,X-authentik-email,X-authentik-name,X-authentik-uid
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- - longhorn.riotpiao.homelab.com
+ - longhorn.riotpiao.com
secretName: longhorn-tls
rules:
- - host: longhorn.riotpiao.homelab.com
+ - host: longhorn.riotpiao.com
http:
paths:
- path: /
@@ -33,17 +33,17 @@ metadata:
namespace: dashboard
annotations:
nginx.ingress.kubernetes.io/auth-url: http://authentik-server.iam.svc.cluster.local/outpost.goauthentik.io/auth/nginx
- nginx.ingress.kubernetes.io/auth-signin: https://authentik.riotpiao.homelab.com/outpost.goauthentik.io/start?rd=$scheme://$http_host$escaped_request_uri
+ nginx.ingress.kubernetes.io/auth-signin: https://authentik.riotpiao.com/outpost.goauthentik.io/start?rd=$scheme://$http_host$escaped_request_uri
nginx.ingress.kubernetes.io/auth-response-headers: Set-Cookie,X-authentik-username,X-authentik-groups,X-authentik-email,X-authentik-name,X-authentik-uid
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- - portainer.riotpiao.homelab.com
+ - portainer.riotpiao.com
secretName: portainer-tls
rules:
- - host: portainer.riotpiao.homelab.com
+ - host: portainer.riotpiao.com
http:
paths:
- path: /
@@ -61,17 +61,17 @@ metadata:
namespace: monitoring
annotations:
nginx.ingress.kubernetes.io/auth-url: http://authentik-server.iam.svc.cluster.local/outpost.goauthentik.io/auth/nginx
- nginx.ingress.kubernetes.io/auth-signin: https://authentik.riotpiao.homelab.com/outpost.goauthentik.io/start?rd=$scheme://$http_host$escaped_request_uri
+ nginx.ingress.kubernetes.io/auth-signin: https://authentik.riotpiao.com/outpost.goauthentik.io/start?rd=$scheme://$http_host$escaped_request_uri
nginx.ingress.kubernetes.io/auth-response-headers: Set-Cookie,X-authentik-username,X-authentik-groups,X-authentik-email,X-authentik-name,X-authentik-uid
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- - prometheus.riotpiao.homelab.com
+ - prometheus.riotpiao.com
secretName: prometheus-tls
rules:
- - host: prometheus.riotpiao.homelab.com
+ - host: prometheus.riotpiao.com
http:
paths:
- path: /
diff --git a/infra/homarr/base/helmrelease.yaml b/infra/homarr/base/helmrelease.yaml
index 1fc6aa1..d3d4c04 100644
--- a/infra/homarr/base/helmrelease.yaml
+++ b/infra/homarr/base/helmrelease.yaml
@@ -12,8 +12,8 @@ spec:
env:
AUTH_PROVIDERS: "oidc"
AUTH_OIDC_CLIENT_ID: "homarr"
- AUTH_OIDC_ISSUER: "https://authentik.riotpiao.homelab.com/application/o/homarr/"
- AUTH_OIDC_URI: "https://authentik.riotpiao.homelab.com/application/o/homarr/.well-known/openid-configuration"
+ AUTH_OIDC_ISSUER: "https://authentik.riotpiao.com/application/o/homarr/"
+ AUTH_OIDC_URI: "https://authentik.riotpiao.com/application/o/homarr/.well-known/openid-configuration"
AUTH_OIDC_GROUPS_ATTRIBUTE: "groups"
envFrom:
- secretRef:
diff --git a/infra/homarr/base/ingress.yaml b/infra/homarr/base/ingress.yaml
index 810f339..8acfd70 100644
--- a/infra/homarr/base/ingress.yaml
+++ b/infra/homarr/base/ingress.yaml
@@ -9,10 +9,10 @@ spec:
ingressClassName: nginx
tls:
- hosts:
- - homarr.riotpiao.homelab.com
+ - homarr.riotpiao.com
secretName: homarr-tls
rules:
- - host: homarr.riotpiao.homelab.com
+ - host: homarr.riotpiao.com
http:
paths:
- path: /
diff --git a/infra/portfolio/base/deployment.yaml b/infra/portfolio/base/deployment.yaml
index 96e1cd1..1c3e64d 100644
--- a/infra/portfolio/base/deployment.yaml
+++ b/infra/portfolio/base/deployment.yaml
@@ -18,7 +18,7 @@ spec:
spec:
containers:
- name: portfolio
- image: forgejo.riotpiao.homelab.com/rock/portfolio:latest
+ image: forgejo.riotpiao.com/rock/portfolio:latest
imagePullPolicy: IfNotPresent
ports:
- name: http
diff --git a/infra/portfolio/base/ingress.yaml b/infra/portfolio/base/ingress.yaml
index 1420c1b..8d0c35f 100644
--- a/infra/portfolio/base/ingress.yaml
+++ b/infra/portfolio/base/ingress.yaml
@@ -3,16 +3,13 @@ kind: Ingress
metadata:
name: portfolio
namespace: portfolio
- annotations:
- cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
- ingressClassName: nginx
tls:
- hosts:
- - portfolio.riotpiao.homelab.com
+ - riotpiao.com
secretName: portfolio-tls
rules:
- - host: portfolio.riotpiao.homelab.com
+ - host: riotpiao.com
http:
paths:
- path: /
diff --git a/lib/LanguageContext.tsx b/lib/LanguageContext.tsx
new file mode 100644
index 0000000..ff3199e
--- /dev/null
+++ b/lib/LanguageContext.tsx
@@ -0,0 +1,34 @@
+'use client'
+
+import { createContext, useContext, useState, ReactNode } from 'react'
+import translations from './translations.json'
+
+type Language = 'en' | 'zh'
+
+interface LanguageContextType {
+ lang: Language
+ setLang: (lang: Language) => void
+ t: typeof translations.en
+}
+
+const LanguageContext = createContext(undefined)
+
+export function LanguageProvider({ children }: { children: ReactNode }) {
+ const [lang, setLang] = useState('en')
+
+ const t = lang === 'zh' ? translations.zh : translations.en
+
+ return (
+
+ {children}
+
+ )
+}
+
+export function useLanguage() {
+ const context = useContext(LanguageContext)
+ if (!context) {
+ throw new Error('useLanguage must be used within LanguageProvider')
+ }
+ return context
+}
diff --git a/lib/TerminalContext.tsx b/lib/TerminalContext.tsx
new file mode 100644
index 0000000..7e056de
--- /dev/null
+++ b/lib/TerminalContext.tsx
@@ -0,0 +1,28 @@
+'use client'
+
+import { createContext, useContext, useState, ReactNode } from 'react'
+
+interface TerminalContextType {
+ isOpen: boolean
+ setIsOpen: (open: boolean) => void
+}
+
+const TerminalContext = createContext(undefined)
+
+export function TerminalProvider({ children }: { children: ReactNode }) {
+ const [isOpen, setIsOpen] = useState(false)
+
+ return (
+
+ {children}
+
+ )
+}
+
+export function useTerminal() {
+ const context = useContext(TerminalContext)
+ if (!context) {
+ throw new Error('useTerminal must be used within TerminalProvider')
+ }
+ return context
+}
diff --git a/lib/translations.json b/lib/translations.json
new file mode 100644
index 0000000..bc19a09
--- /dev/null
+++ b/lib/translations.json
@@ -0,0 +1,354 @@
+{
+ "en": {
+ "header": {
+ "title": "Rock Liang",
+ "subtitle": "Senior Software Engineer",
+ "nav": {
+ "home": "Home",
+ "askPoimen": "AskPoimen",
+ "skills": "Skills",
+ "contact": "Contact"
+ },
+ "experience": "Experience",
+ "experienceValue": "6+ YoE",
+ "education": "Education",
+ "educationValue": "M.Sc. UOttawa",
+ "educationDetails": {
+ "bachelor": {
+ "school": "University of Ottawa",
+ "degree": "Bachelor's Degree, Computer Science",
+ "period": "2016 – 2019"
+ },
+ "master": {
+ "school": "University of Ottawa",
+ "degree": "Master's degree, Computer Science",
+ "period": "Sep 2019 – Nov 2021"
+ }
+ },
+ "contact": {
+ "portfolio": "portfolio.riotpiao.com",
+ "github": "GitHub",
+ "privateGithub": "Private Github",
+ "linkedin": "LinkedIn",
+ "email": "Email",
+ "copy": "Copy"
+ },
+ "skillsPlaceholder": "Skills will appear here"
+ },
+ "hero": {
+ "title": "Senior Software Engineer",
+ "subtitle": "Infrastructure × Backend × LLM Systems",
+ "description": "Building observable, scalable, fault-tolerant systems for mass audience.",
+ "exploreMore": "Explore more",
+ "terminalHint": "Press",
+ "terminalHintSuffix": "to explore via terminal",
+ "roles": [
+ "Infrastructure",
+ "SRE",
+ "SDE",
+ "Agentic Engineer",
+ "Distributed Systems",
+ "System/Platform Engineer"
+ ]
+ },
+ "bio": {
+ "title": "About Me",
+ "intro": "Senior Software Engineer with 6+ years of experience building observable, scalable, and fault-tolerant systems for mass audiences.",
+ "expertise": {
+ "title": "Technical Expertise",
+ "content": "Infrastructure automation (Terraform, Kubernetes, ArgoCD) • Distributed systems (gRPC, Kafka, AWS Step Functions) • LLM inference optimization (INT4/INT8 quantization) • Backend systems (Go, Java, Python, C++)"
+ },
+ "highlights": {
+ "title": "Career Highlights",
+ "items": [
+ "Launched AWS Distributed-Map service across 57+ regions",
+ "Built multi-region infrastructure at RBC (40% cost reduction)",
+ "Architected production homelab: Kubernetes, Kafka, LLM inference",
+ "Open source: go-flink (distributed DataLakeHouse)"
+ ]
+ },
+ "educationTitle": "Education",
+ "educationContent": "M.Sc. Computer Science, University of Ottawa (2019–2021)\nB.Sc. Computer Science, University of Ottawa (2016–2019)",
+ "currentFocus": "Currently focused on infrastructure automation, LLM systems optimization, and building the next generation of distributed systems."
+ },
+ "projects": {
+ "title": "What have i Built and Building",
+ "subtitle": "Demonstrate my work",
+ "watchVideo": "Watch Video",
+ "readArticle": "Read Article",
+ "askPoimen": "Ask Poimen for technical details",
+ "items": [
+ {
+ "title": "AWS Distributed-Map",
+ "description": "Launched distributed task orchestration service for mission-critical workloads.",
+ "longDescription": "Optimized execution across 57+ regions with fault-tolerant scheduling and auto-scaling.",
+ "stat": "Production launch, 57+ regions"
+ },
+ {
+ "title": "RBC: Multi-Cloud Platform",
+ "description": "Unified infrastructure platform consolidating public cloud and on-prem.",
+ "longDescription": "Terraform automation with Temporal orchestration. 99.2% automated provisioning, notification-driven operator fallback.",
+ "stat": "200+ microservices, 4 regions, 2hr→20min deploy",
+ "highlight": "Standardized IaC patterns across 12 teams—cut provisioning toil, 3x integration velocity.",
+ "bullets": [
+ "Integrated Terraform Cloud to centralize IaC workflows—reduced onboarding time for 12 teams",
+ "Built K8s CronJob to detect and reconcile Terraform state drift automatically (Golang)",
+ "Designed Slack notification service with Golang workers—operators resolve apply failures in <5min",
+ "Led requirement gathering across 4 platform teams—disambiguated specs, unblocked 3 stalled projects",
+ "Translated technical decisions for non-technical stakeholders—secured buy-in for platform migration"
+ ],
+ "deepDive": {
+ "label": "Deep Dive: Terraform State Drift Solution →",
+ "url": "/terraform-drift"
+ }
+ },
+ {
+ "title": "Homelab: Kubernetes Cluster",
+ "description": "Bare-metal Kubernetes cluster running production workloads.",
+ "longDescription": "Talos OS with 3-node control plane. Cilium eBPF CNI, Longhorn storage, ArgoCD GitOps.",
+ "stat": "3-node cluster, 99.2% uptime"
+ },
+ {
+ "title": "Homelab: LLM Inference",
+ "description": "Production LLM inference pipeline with CPU optimization.",
+ "longDescription": "Temporal-based orchestration with INT4/INT8 quantization. Achieved 60% latency reduction.",
+ "stat": "60% latency cut, real-time inference"
+ },
+ {
+ "title": "Homelab: Kafka Cluster",
+ "description": "High-throughput event streaming with Strimzi KRaft.",
+ "longDescription": "3-broker KRaft cluster with auto-scaling, persistent storage, and monitoring.",
+ "stat": "3 brokers, 1K+ msgs/sec"
+ },
+ {
+ "title": "Open Source: go-flink",
+ "description": "Distributed DataLakeHouse framework written in Go.",
+ "longDescription": "Fault-tolerant data pipelines with streaming semantics and efficient processing.",
+ "stat": "Public repository, active"
+ }
+ ]
+ },
+ "experience": {
+ "title": "Explore Experience",
+ "subtitle": "Feel free to Ask Poimen more abt it",
+ "items": [
+ {
+ "company": "riotpiao.com",
+ "role": "DevOps / SRE / SDE",
+ "period": "May 2026 — Present",
+ "description": "Built and maintain production-grade homelab on bare-metal Kubernetes (3-node Talos cluster). Architected Temporal-based LLM inference pipelines with 60% latency reduction. Full GitOps automation with ArgoCD, Terraform, and custom operators."
+ },
+ {
+ "company": "RBC",
+ "role": "Lead Software Engineer",
+ "period": "Nov 2024 — May 2026",
+ "description": "Deployments were manual and slow—teams blocked 2+ hours waiting. Chose Terraform for idempotent drift handling, Temporal for multi-cloud orchestration with built-in retry. Cut deploy time to 20min, consolidated public cloud and on-prem into single platform with 99.2% automation and notification-driven operator fallback."
+ },
+ {
+ "company": "AWS",
+ "role": "Senior Software Engineer (Step Functions)",
+ "period": "2022 — 2024",
+ "description": "Core contributor to AWS Step Functions, scaling to 57+ regions. Designed and implemented 8 critical components for distributed state machine execution. Achieved sub-100ms P99 latency for high-throughput workflow orchestration."
+ },
+ {
+ "company": "Titus",
+ "role": "ML Software Engineer Intern",
+ "period": "May — Aug 2019",
+ "description": "Built Personal Data Detection pipeline with 97.8% accuracy using transformer models. Developed Golang connector reducing p99 latency by 28%. Created SmartRegex system accelerating model deployment by 5x."
+ },
+ {
+ "company": "NAV Canada",
+ "role": "Summer Student",
+ "period": "May — Aug 2018",
+ "description": "Developed CFPS Flight Planning application using Django and React. Implemented NOTAMJ polling system and integrated Sonar code coverage. Built FWGS weather briefing interface for pilots."
+ }
+ ]
+ },
+ "terminal": {
+ "title": "Poimen (Agent Terminal)",
+ "button": "Ask Poimen",
+ "helpText": "type 'help' for commands"
+ },
+ "footer": {
+ "copyright": "© 2025 Rock Liang. Deployed on homelab Kubernetes cluster (3-node Talos).",
+ "github": "GitHub",
+ "email": "Email"
+ }
+ },
+ "zh": {
+ "header": {
+ "title": "梁伟哲",
+ "subtitle": "高级软件工程师",
+ "nav": {
+ "home": "首页",
+ "askPoimen": "问Poimen",
+ "skills": "技能",
+ "contact": "联系"
+ },
+ "experience": "经验",
+ "experienceValue": "6年+",
+ "education": "学历",
+ "educationValue": "渥太华大学硕士",
+ "educationDetails": {
+ "bachelor": {
+ "school": "渥太华大学",
+ "degree": "计算机科学学士",
+ "period": "2016 – 2019"
+ },
+ "master": {
+ "school": "渥太华大学",
+ "degree": "计算机科学硕士",
+ "period": "2019年9月 – 2021年11月"
+ }
+ },
+ "contact": {
+ "portfolio": "portfolio.riotpiao.com",
+ "github": "GitHub",
+ "privateGithub": "私人GitHub",
+ "linkedin": "领英",
+ "email": "邮箱",
+ "copy": "复制"
+ },
+ "skillsPlaceholder": "技能将显示在这里"
+ },
+ "hero": {
+ "title": "高级软件工程师",
+ "subtitle": "基础设施 × 后端 × LLM系统",
+ "description": "为大规模用户构建可观测、可扩展、容错的系统。",
+ "exploreMore": "了解更多",
+ "terminalHint": "按",
+ "terminalHintSuffix": "通过终端探索",
+ "roles": [
+ "基础设施",
+ "SRE",
+ "软件开发",
+ "AI代理工程师",
+ "分布式系统",
+ "系统/平台工程师"
+ ]
+ },
+ "bio": {
+ "title": "关于我",
+ "intro": "拥有6年以上经验的高级软件工程师,专注于为大规模用户构建可观测、可扩展、容错的系统。",
+ "expertise": {
+ "title": "技术专长",
+ "content": "基础设施自动化 (Terraform, Kubernetes, ArgoCD) • 分布式系统 (gRPC, Kafka, AWS Step Functions) • LLM推理优化 (INT4/INT8量化) • 后端系统 (Go, Java, Python, C++)"
+ },
+ "highlights": {
+ "title": "职业亮点",
+ "items": [
+ "在57+区域发布AWS Distributed-Map服务",
+ "在RBC构建多区域基础设施(成本降低40%)",
+ "架构生产级家庭实验室:Kubernetes、Kafka、LLM推理",
+ "开源项目:go-flink(分布式数据湖仓库)"
+ ]
+ },
+ "educationTitle": "教育背景",
+ "educationContent": "渥太华大学计算机科学硕士 (2019–2021)\n渥太华大学计算机科学学士 (2016–2019)",
+ "currentFocus": "目前专注于基础设施自动化、LLM系统优化,以及构建下一代分布式系统。"
+ },
+ "projects": {
+ "title": "我构建的项目",
+ "subtitle": "展示我的作品",
+ "watchVideo": "观看视频",
+ "readArticle": "阅读文章",
+ "askPoimen": "问Poimen了解技术细节",
+ "items": [
+ {
+ "title": "AWS Distributed-Map",
+ "description": "发布面向关键任务的分布式任务编排服务。",
+ "longDescription": "在57+区域优化执行,具有容错调度和自动扩展功能。",
+ "stat": "生产发布,57+区域"
+ },
+ {
+ "title": "RBC: 多云平台",
+ "description": "统一基础设施平台,整合公有云和本地部署。",
+ "longDescription": "Terraform自动化配合Temporal编排。99.2%自动化配置,通知驱动的运维人员兜底。",
+ "stat": "200+微服务,4个区域,部署2小时→20分钟",
+ "highlight": "标准化12个团队的IaC模式——减少配置负担,集成速度提升3倍。",
+ "bullets": [
+ "集成Terraform Cloud实现IaC工作流集中化——12个团队onboarding时间缩短",
+ "构建K8s CronJob自动检测和修复Terraform状态漂移(Golang)",
+ "设计Slack通知服务 + Golang worker——运维人员<5分钟解决apply失败",
+ "主导4个平台团队需求收集——澄清规格,解锁3个停滞项目",
+ "向非技术stakeholder翻译技术决策——获得平台迁移支持"
+ ],
+ "deepDive": {
+ "label": "深入了解:Terraform状态漂移解决方案 →",
+ "url": "/terraform-drift"
+ }
+ },
+ {
+ "title": "家庭实验室:Kubernetes集群",
+ "description": "运行生产工作负载的裸机Kubernetes集群。",
+ "longDescription": "Talos OS 3节点控制平面,Cilium eBPF CNI,Longhorn存储,ArgoCD GitOps。",
+ "stat": "3节点集群,99.2%可用性"
+ },
+ {
+ "title": "家庭实验室:LLM推理",
+ "description": "具有CPU优化的生产LLM推理管道。",
+ "longDescription": "基于Temporal的编排,INT4/INT8量化,延迟降低60%。",
+ "stat": "延迟降低60%,实时推理"
+ },
+ {
+ "title": "家庭实验室:Kafka集群",
+ "description": "使用Strimzi KRaft的高吞吐量事件流。",
+ "longDescription": "3代理KRaft集群,具有自动扩展、持久存储和监控。",
+ "stat": "3代理,1K+消息/秒"
+ },
+ {
+ "title": "开源:go-flink",
+ "description": "用Go编写的分布式数据湖仓库框架。",
+ "longDescription": "具有流语义和高效处理的容错数据管道。",
+ "stat": "公开仓库,活跃中"
+ }
+ ]
+ },
+ "experience": {
+ "title": "工作经历",
+ "subtitle": "欢迎向Poimen了解更多",
+ "items": [
+ {
+ "company": "riotpiao.com",
+ "role": "DevOps / SRE / 软件开发",
+ "period": "2026年5月 — 至今",
+ "description": "在裸机Kubernetes(3节点Talos集群)上构建和维护生产级家庭实验室。架构基于Temporal的LLM推理管道,延迟降低60%。使用ArgoCD、Terraform和自定义操作器实现完整GitOps自动化。"
+ },
+ {
+ "company": "RBC",
+ "role": "技术主管",
+ "period": "2024年11月 — 2026年5月",
+ "description": "部署流程手动且缓慢——团队等待2+小时。选择Terraform处理幂等漂移,Temporal用于多云编排和内置重试。将部署时间缩短至20分钟,整合公有云和本地部署为统一平台,99.2%自动化,通知驱动的运维人员兜底机制。"
+ },
+ {
+ "company": "AWS",
+ "role": "高级软件工程师 (Step Functions)",
+ "period": "2022 — 2024",
+ "description": "AWS Step Functions核心贡献者,扩展至57+区域。设计实现8个关键组件用于分布式状态机执行。高吞吐量工作流编排实现P99延迟低于100ms。"
+ },
+ {
+ "company": "Titus",
+ "role": "机器学习软件工程师实习",
+ "period": "2019年5月 — 8月",
+ "description": "使用transformer模型构建准确率97.8%的个人数据检测管道。开发Golang连接器,p99延迟降低28%。创建SmartRegex系统,模型部署速度提升5倍。"
+ },
+ {
+ "company": "NAV Canada",
+ "role": "暑期实习生",
+ "period": "2018年5月 — 8月",
+ "description": "使用Django和React开发CFPS航班计划应用。实现NOTAMJ轮询系统并集成Sonar代码覆盖。为飞行员构建FWGS天气简报界面。"
+ }
+ ]
+ },
+ "terminal": {
+ "title": "Poimen(代理终端)",
+ "button": "问Poimen",
+ "helpText": "输入 'help' 查看命令"
+ },
+ "footer": {
+ "copyright": "© 2025 梁伟哲。部署于家庭实验室Kubernetes集群(3节点Talos)。",
+ "github": "GitHub",
+ "email": "邮箱"
+ }
+ }
+}
diff --git a/public/avatar.jpeg b/public/avatar.jpeg
new file mode 100644
index 0000000000000000000000000000000000000000..9bdf0788956eaea1da01010da7a7fbe7aa2afa6a
GIT binary patch
literal 30373
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
literal 0
HcmV?d00001
diff --git a/public/hire-me-light.png b/public/hire-me-light.png
new file mode 100644
index 0000000000000000000000000000000000000000..adb81a3e84b3712ae58d7a9296f5c87e635ace14
GIT binary patch
literal 1531123
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