From dc66b66d9434d48b6a584324f2a7fe8bba5c3c21 Mon Sep 17 00:00:00 2001 From: Madhura68 Date: Tue, 14 Apr 2026 21:39:50 +0200 Subject: [PATCH] Initial commit --- .eslintrc.json | 3 + .gitignore | 36 + README.md | 87 + app/globals.css | 79 + app/layout.tsx | 49 + app/page.tsx | 21 + components/apps.tsx | 72 + components/contact.tsx | 86 + components/experience.tsx | 182 ++ components/fade-in.tsx | 46 + components/footer.tsx | 15 + components/hero.tsx | 150 + components/nav.tsx | 125 + components/skills.tsx | 113 + lib/cv-data.ts | 120 + next.config.ts | 5 + package-lock.json | 6285 ++++++++++++++++++++++++++++++++++++ package.json | 27 + postcss.config.mjs | 9 + public/images/portrait.jpg | Bin 0 -> 2550937 bytes tailwind.config.ts | 25 + tsconfig.json | 21 + 22 files changed, 7556 insertions(+) create mode 100644 .eslintrc.json create mode 100644 .gitignore create mode 100644 README.md create mode 100644 app/globals.css create mode 100644 app/layout.tsx create mode 100644 app/page.tsx create mode 100644 components/apps.tsx create mode 100644 components/contact.tsx create mode 100644 components/experience.tsx create mode 100644 components/fade-in.tsx create mode 100644 components/footer.tsx create mode 100644 components/hero.tsx create mode 100644 components/nav.tsx create mode 100644 components/skills.tsx create mode 100644 lib/cv-data.ts create mode 100644 next.config.ts create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 postcss.config.mjs create mode 100644 public/images/portrait.jpg create mode 100644 tailwind.config.ts create mode 100644 tsconfig.json diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..bffb357 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": "next/core-web-vitals" +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..38b9748 --- /dev/null +++ b/.gitignore @@ -0,0 +1,36 @@ +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/README.md b/README.md new file mode 100644 index 0000000..6ca8076 --- /dev/null +++ b/README.md @@ -0,0 +1,87 @@ +# jp-visser.nl + +Persoonlijke website van Janpeter Visser — Software Engineer. + +## Lokaal draaien + +```bash +npm install +npm run dev +``` + +Open [http://localhost:3000](http://localhost:3000). + +## Deployen naar Vercel + +### 1. Push naar GitHub + +```bash +git init +git add . +git commit -m "Initial commit" +git branch -M main +git remote add origin https://github.com/JOUW_USERNAME/jp-visser.git +git push -u origin main +``` + +### 2. Koppel aan Vercel + +1. Ga naar [vercel.com/new](https://vercel.com/new) +2. Importeer je GitHub repository +3. Klik op **Deploy** — Vercel detecteert Next.js automatisch + +### 3. Domein instellen + +1. Ga naar je project in Vercel → **Settings** → **Domains** +2. Voeg `jp-visser.nl` toe +3. Bij je domeinregistrar, stel in: + - **A-record**: `@` → `76.76.21.21` + - **CNAME**: `www` → `cname.vercel-dns.com` + +DNS-wijzigingen kunnen tot 48 uur duren, maar zijn meestal binnen een uur actief. + +## Apps toevoegen + +Om apps toe te voegen aan de portfolio: + +**Optie A — Als aparte Vercel projecten (subdomein):** +- Deploy een app als apart project op Vercel +- Voeg een subdomein toe: bijv. `app1.jp-visser.nl` + +**Optie B — Als routes binnen dit project:** +- Maak een nieuwe pagina aan in `app/apps/naam/page.tsx` +- De app is dan bereikbaar op `jp-visser.nl/apps/naam` + +Pas daarna `components/apps.tsx` aan om de links naar je apps te tonen. + +## Projectstructuur + +``` +jp-visser/ +├── app/ +│ ├── globals.css # Global styles + Tailwind +│ ├── layout.tsx # Root layout met fonts & metadata +│ └── page.tsx # Homepage +├── components/ +│ ├── nav.tsx # Navigatie (sticky) +│ ├── hero.tsx # Hero sectie met portret +│ ├── experience.tsx # Werkervaring +│ ├── skills.tsx # Skills & tools +│ ├── apps.tsx # Apps portfolio +│ ├── contact.tsx # Contact info +│ ├── footer.tsx # Footer +│ └── fade-in.tsx # Scroll-animatie component +├── lib/ +│ └── cv-data.ts # Alle CV data +├── public/ +│ └── images/ +│ └── portrait.jpg # Portretfoto +└── package.json +``` + +## Tech stack + +- **Next.js 15** (App Router) +- **TypeScript** +- **Tailwind CSS** +- Hosted op **Vercel** diff --git a/app/globals.css b/app/globals.css new file mode 100644 index 0000000..5dc6e96 --- /dev/null +++ b/app/globals.css @@ -0,0 +1,79 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +:root { + --accent: #c2339b; + --bg: #0f0f14; + --text: #e8e4df; + --text-muted: rgba(255, 255, 255, 0.5); + --text-dim: rgba(255, 255, 255, 0.35); + --surface: rgba(255, 255, 255, 0.03); + --border: rgba(255, 255, 255, 0.06); +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +html { + scroll-behavior: smooth; +} + +body { + background: var(--bg); + color: var(--text); + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +::selection { + background: rgba(194, 51, 155, 0.35); + color: #fff; +} + +::-webkit-scrollbar { + width: 6px; +} + +::-webkit-scrollbar-track { + background: var(--bg); +} + +::-webkit-scrollbar-thumb { + background: rgba(194, 51, 155, 0.3); + border-radius: 3px; +} + +a { + transition: opacity 0.2s; +} + +a:hover { + opacity: 0.85; +} + +/* Fade-in animation */ +@keyframes fadeUp { + from { + opacity: 0; + transform: translateY(28px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.fade-in { + opacity: 0; + transform: translateY(28px); + transition: opacity 0.7s ease, transform 0.7s ease; +} + +.fade-in.visible { + opacity: 1; + transform: translateY(0); +} diff --git a/app/layout.tsx b/app/layout.tsx new file mode 100644 index 0000000..0290cc9 --- /dev/null +++ b/app/layout.tsx @@ -0,0 +1,49 @@ +import type { Metadata } from "next"; +import { DM_Sans } from "next/font/google"; +import "./globals.css"; + +const dmSans = DM_Sans({ + subsets: ["latin"], + variable: "--font-sans", + display: "swap", +}); + +export const metadata: Metadata = { + title: "Janpeter Visser — Software Engineer", + description: + "Persoonlijke website van Janpeter Visser. Allround software engineer met 30 jaar ervaring in full-stack development, van C++ tot Angular en .NET.", + metadataBase: new URL("https://jp-visser.nl"), + openGraph: { + title: "Janpeter Visser — Software Engineer", + description: + "Allround software engineer met 30 jaar ervaring in full-stack development.", + url: "https://jp-visser.nl", + siteName: "Janpeter Visser", + locale: "nl_NL", + type: "website", + }, +}; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + + + + + + {children} + + ); +} diff --git a/app/page.tsx b/app/page.tsx new file mode 100644 index 0000000..88748bf --- /dev/null +++ b/app/page.tsx @@ -0,0 +1,21 @@ +import { Nav } from "@/components/nav"; +import { Hero } from "@/components/hero"; +import { ExperienceSection } from "@/components/experience"; +import { SkillsSection } from "@/components/skills"; +import { AppsSection } from "@/components/apps"; +import { ContactSection } from "@/components/contact"; +import { Footer } from "@/components/footer"; + +export default function Home() { + return ( + <> +