Personal portfolio and CV site, built as a single-page profile with downloadable PDF CVs in English and Spanish.
Live: larabarijhoff.com
- Next.js 14 (App Router)
- TypeScript
- Tailwind CSS
- Motion (formerly Framer Motion) for nav indicator and section transitions
- lucide-react for icons
- Deployed on Vercel
- Content as data. All copy, experience, projects, skills, education and contact info live in
data/portfolio.json(English) anddata/portfolio.es.json(Spanish). Components are presentational — no content is hardcoded in JSX. - Manual i18n via context.
context/LanguageContext.tsxswaps the data object and UI strings (lib/translations.ts) at runtime, with a toggle in the navbar. No i18n library. - Two printable CV routes.
/cv-enand/cv-esrender print-optimized CVs with a "Download PDF" button. The exported PDFs inpublic/are what's linked from the hero section. - Active section tracking.
context/ActiveSectionContext.tsxusesIntersectionObserverto highlight the current section in the navbar as the user scrolls. - SEO. Metadata, OG image, robots, and sitemap all derive from
data/portfolio.jsonmeta.
app/
layout.tsx # Root layout, metadata, viewport
page.tsx # Single-page home
cv-en/, cv-es/ # Printable CV routes (noindex)
robots.ts # Generated robots.txt
sitemap.ts # Generated sitemap.xml
components/ # Hero, About, Experience, Projects, Skills, Education, Contact, Navbar, Footer
context/ # LanguageContext, ActiveSectionContext
data/ # portfolio.json (EN) + portfolio.es.json (ES)
lib/ # sections.ts, translations.ts
public/ # Logos, headshot, banners, PDF CVs
npm install
npm run devOpen http://localhost:3000.
| Script | Purpose |
|---|---|
npm run dev |
Local dev server |
npm run build |
Production build |
npm run start |
Run the production build |
npm run lint |
Lint with eslint-config-next |