← All Posts
NuxtVueTailwindCSSPortfolio

Building a Modern Portfolio with Nuxt 4

A step-by-step guide on how I built this portfolio using Nuxt 4, NuxtUI v3, TailwindCSS v4, and i18n for multi-language support.


Building a Modern Portfolio with Nuxt 4

When I decided to rebuild my portfolio, I wanted something that felt fast, modern, and maintainable. After evaluating several options, I landed on Nuxt 4 — and I couldn't be happier.

Why Nuxt 4?

Nuxt 4 introduces a cleaner project structure with the app/ directory convention, improved TypeScript support, and better performance out of the box. Combined with @nuxt/ui (which bundles TailwindCSS v4), I get a powerful design system with zero setup friction.

Key Modules Used

Here's the stack that powers this portfolio:

  • @nuxt/ui — Components + TailwindCSS v4 + color mode (dark/light)
  • @nuxt/image — Automatic image optimization (WebP, AVIF, lazy loading)
  • @nuxtjs/i18n — Multi-language support (English + Bahasa Indonesia)
  • @nuxt/content — Blog posts & project data as Markdown/YAML files

The Design Philosophy

I took inspiration from the Canvas template — minimal, narrow, and focused on content. No sidebars, no distractions. The content max-width is set to 760px to keep reading comfortable.

.section-inner {
  max-width: 760px;
  margin: 0 auto;
}

Dark Mode Implementation

With @nuxt/ui, dark mode is trivial:

<script setup>
const colorMode = useColorMode()
const isDark = computed(() => colorMode.value === 'dark')

function toggle() {
  colorMode.preference = isDark.value ? 'light' : 'dark'
}
</script>

What's Next?

I'm planning to add:

  1. A works/projects section with full case studies
  2. A newsletter subscription using Resend
  3. View transitions API for smoother page changes

Stay tuned! 🚀