Personal portfolio website and CV built with Nuxt 4, Vue 3, TypeScript, and Tailwind CSS v4.
It showcases my professional background, projects, and skills. A server-side PDF export generates a print-optimized CV via Puppeteer, with an optional ATS-compatible mode.
| Layer | Technology |
|---|---|
| Framework | Nuxt 4 + Vue 3 |
| Language | TypeScript |
| Styling | Tailwind CSS v4 |
| Internationalisation | @nuxtjs/i18n · DE / EN |
| PDF Generation | Puppeteer |
| Image Handling | @nuxt/image |
| Icons | @nuxt/icon |
| Animations | @vueuse/motion |
| Utilities | @vueuse/core · @vueuse/nuxt |
| Linting | ESLint + Prettier |
The project is split into three layers with a strict separation of concerns:
next-cv/
├── app/ # Frontend (Vue 3 / Nuxt app layer)
│ ├── app.vue # Root application component
│ ├── pages/
│ │ └── index.vue # Single-page app entry point
│ ├── components/
│ │ ├── Banner.vue # Hero / intro section
│ │ ├── About.vue # Skills & profile summary
│ │ ├── Experience.vue # Work history, consumes TimelineItem
│ │ ├── Education.vue # Academic history, consumes TimelineItem
│ │ ├── TimelineItem.vue # Reusable timeline entry component
│ │ ├── Projects.vue # Portfolio project cards
│ │ ├── Contact.vue # Contact section
│ │ ├── Navigation.vue # Sticky sidebar navigation
│ │ ├── SectionTitle.vue # Reusable section heading
│ │ ├── LangSwitch.vue # DE/EN language toggle
│ │ └── RightSide.vue # Social links sidebar
│ ├── assets/
│ │ ├── css/
│ │ │ └── main.css # Global Tailwind CSS styles
│ │ └── images/
│ │ └── profile.png # Personal profile picture
│ ├── composables/ # Reusable Vue composition functions
│ │ ├── useMotionPresets.ts # Custom animation presets for @vueuse/motion
│ │ └── usePersonal.ts # State management for personal details
│ └── types/
│ └── index.ts # Common TypeScript interfaces & types
│
├── server/ # Nuxt server layer (Node.js)
│ ├── api/
│ │ └── download-cv.get.ts # GET /api/download-cv, PDF generation endpoint
│ └── utils/
│ └── cv-template.ts # Type-safe HTML template for Puppeteer rendering
│
├── data/
│ └── personal.json # Centralised personal contact & social link data
│
└── i18n/
└── locales/
├── de.json # German translations (experience, education, skills)
└── en.json # English translations
Requires Node.js >= 20 (Node.js 24 is recommended, see .nvmrc).
npm install
npm run devOpen http://localhost:3000 in your browser.
npm run lint # Run ESLint
npm run lint:fix # Auto-fix ESLint issues
npm run format # Format all files with Prettier
npm run build # Build for production
npm run preview # Preview the production buildThe application is fully containerized for production deployment. The Dockerfile uses a multi-stage build targeting node:24-bookworm-slim and installs Chromium along with Noto and Liberation fonts, ensuring that server-side Puppeteer PDF generation works out-of-the-box.
# Build the Docker image
docker build -t stroessner-portfolio .
# Run the Docker container
docker run -p 3000:3000 stroessner-portfolioThe application will be accessible at http://localhost:3000.
The CV is generated server-side on demand:
GET /api/download-cv?lang=de # German CV (dark theme)
GET /api/download-cv?lang=en # English CV (dark theme)
GET /api/download-cv?lang=de&ats=true # German CV (ATS-compatible light theme)