trongpham.dev — Portfolio
This site. Designed and engineered from scratch in Next.js 16.
export const project = {
type: "fullstack",
stack: [
"Next.js 16",
"React 19",
"TypeScript",
"Tailwind v4",
"Motion",
"next-intl",
"MDX",
"Resend",
"Vercel",
],
shipped: true,
};- Năm
- 2026
- Vai trò
- Designer & engineer
- Thời gian
- Ongoing
Kiến trúc
Frontend
- Next.js 16 App Router
- React 19 Server Components
- Tailwind v4
- Motion (Framer)
Content
- MDX for case studies
- TypeScript metadata
- next-intl (vi / en)
Backend & infra
- Resend for the contact form
- Vercel hosting + analytics
- Speed Insights
Ghi chú kỹ thuật
Why build it from scratch
I could have used a template. Templates are great. But this site is also a working sandbox for me to try Next.js 16, React 19 server components, Tailwind v4 and Motion v12 against each other on something I actually own.
How it's put together
The site is a single page on / with anchored sections, plus per-project detail pages under /projects/[slug]. Project metadata lives in a typed TypeScript file; the long-form body lives in MDX. The page picks one of four layouts based on the project's type field — webapp, mobile, enterprise or fullstack — so a code-heavy project and an editorial case study don't have to share the same template.
Things I cared about
- Motion that knows when to stop. Every animation respects
prefers-reduced-motionand defaults to a single, calm timing curve. - i18n that stays out of the way.
next-intlcarries Vietnamese and English in the same source tree without complicating the route shape. - Boring deploys. Pushed to
main, deployed to Vercel, no surprises.
The numbers I check
```ts
// app/[locale]/projects/[slug]/page.tsx
const Layout = {
webapp: WebappLayout,
mobile: MobileLayout,
enterprise: EnterpriseLayout,
fullstack: FullstackLayout,
}[project.type];
```
That switch is the only thing standing between "boring portfolio" and "the case studies feel made for the work." Worth it.