Skip to content

gpx75/giancarlopapa.com

Repository files navigation

giancarlopapa.com

Personal portfolio site for Giancarlo Papa — Senior Full Stack Engineer.

Stack: Nuxt 4 · Nuxt UI v4 · Nuxt Content v3 · Cal.com · Resend · Vercel

Pages

Route Description
/ Homepage — hero, about, services
/resume Full CV rendered from JSON Resume
/blog Blog listing (Markdown via @nuxt/content)
/blog/[slug] Individual post with prose styling
/book Cal.com booking flow
/contact Contact form (Resend)
/skillmatrix Tech skills with proficiency levels
/colophon About this site

Development

npm install
npm run dev

Environment variables

Create a .env file in the project root:

# Cal.com booking integration
CAL_API_KEY=cal_live_...
CAL_USERNAME=your-cal-username
CAL_BASE_URL=https://api.cal.com

# Site
SITE_URL=https://giancarlopapa.com
CONTACT_EMAIL=hello@giancarlopapa.com

# Contact form (resend.com)
RESEND_API_KEY=re_...
RESEND_TO_EMAIL=giancarlo.papa@gmail.com

Commands

npm run dev           # Start dev server
npm run build         # Production build
npm run preview       # Preview production build locally
npm run generate-pdf  # Regenerate static PDF resume (also runs pre-commit via Husky)
npm run typecheck     # TypeScript check
npm run lint          # ESLint
npm run deploy        # Deploy to Vercel (prod)

PDF resume

The resume is available as a downloadable PDF generated from content/giancarlo_papa_resume.json.

  • Static PDF (public/giancarlo_papa_resume.pdf): generated by scripts/generate-pdf.mjs, auto-runs pre-commit via Husky when the JSON is staged.
  • Dynamic PDF (/api/resume/pdf): server route (server/api/resume/pdf.get.ts) that renders on demand — same HTML/CSS as the script.
  • Requires CHROMIUM_EXECUTABLE_PATH in .env pointing to a local Chrome binary.
  • Style reference: public/giancarlo_papa_vitae.pdf — the design bible for fonts, icons, colors, and layout.

Content

Blog posts live in content/blog/*.md with this frontmatter:

---
title: "Post title"
description: "Short description"
date: "2026-02-22"
tags: ["tag1", "tag2"]
draft: false
---

The resume is content/giancarlo_papa_resume.json (JSON Resume format).

Contact form

Sends email via Resendserver/api/contact.post.ts.

The from address is noreply@giancarlopapa.com. Verify the domain at resend.com/domains before going to production. For local testing use onboarding@resend.dev.

Booking

Cal.com integration in server/utils/cal.ts and server/api/cal/:

  • Event types: GET /v1/event-types
  • Available slots: GET /v2/slots (cal-api-version: 2024-09-04)
  • Create booking: POST /v2/bookings (cal-api-version: 2024-08-13)

Deployment

Hosted on Vercel. Nitro preset: vercel.

Deployment is fully automated via GitHub Actions (.github/workflows/deploy.yml):

git push origin main  →  GitHub Actions builds + deploys to Vercel

Set all env vars in GitHub → Settings → Secrets (for CI build) and in Vercel → Settings → Environment Variables (for runtime).

Project structure

app/
  pages/           # index.vue, resume.vue, book.vue, contact.vue, blog/, ...
  components/cv/   # CV section components
  composables/     # useCalBooking.ts, useProfileData.ts, useResumeContent.ts
  data/            # Static profile data
  types/           # TypeScript types (cal.ts, resume.ts)
  assets/css/      # Tailwind theme, Snazzy colours, typography
server/
  api/             # contact.post.ts, profile.get.ts, cal/
  utils/cal.ts     # Cal.com API client
content/
  blog/            # Markdown blog posts
  giancarlo_papa_resume.json
content.config.ts  # @nuxt/content collection schema

About

sito

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors