A personal portfolio website for Ahmad Rizal Khamdani, built with Next.js, React, TypeScript, and Tailwind CSS. The site highlights profile information, services, skills, selected projects, work experience, education, social links, and a contact form.
The project is designed to be easy to maintain: most portfolio content lives in JSON files under src/data, while the application shell, SEO metadata, and UI sections are handled by reusable React components.
next-themesUse a recent Node.js version that supports Next.js 16 and React 19. Node.js 20 or newer is recommended.
npm install
Create a .env file in the project root:
NEXT_PUBLIC_SITE_URL=http://localhost:3000
WEBFORM_ACCESS_KEY=your_web3forms_access_key
NEXT_PUBLIC_SITE_URL is used for canonical URLs, sitemap, robots metadata, Open Graph images, and structured data.
WEBFORM_ACCESS_KEY is used by the contact form. The form will show a configuration error if this value is missing.
npm run dev
Open http://localhost:3000 in your browser.
npm run build
npm run start
npm run lint
.
├── public/
│ └── assets/ # Images, icons, project thumbnails, skill logos
├── src/
│ ├── app/ # Next.js app routes, layout, metadata, sitemap, robots, manifest
│ ├── components/ # Page sections and reusable UI components
│ ├── data/ # Editable portfolio content
│ └── lib/ # Shared utilities, site config, metadata helpers
├── next.config.ts
├── package.json
├── postcss.config.mjs
└── tsconfig.json
Most content can be updated without touching component code.
| File | Purpose |
|---|---|
src/data/intro.json |
Hero intro text, availability, and quick stats |
src/data/about.json |
Profile description, email, Telegram, and social links |
src/data/service.json |
Services displayed on the site |
src/data/skill.json |
Skill categories and skill icons |
src/data/portfolio.json |
Project list, descriptions, technologies, images, and links |
src/data/employment.json |
Work experience timeline |
src/data/education.json |
Education timeline |
src/data/nav.json |
Navigation labels and anchors, if used directly |
The file src/data/portfolio.ts acts as a typed data layer. Components import portfolio data from this file, so keep JSON shape consistent when editing content.
Main site metadata is defined in src/lib/site.ts, including:
Next.js metadata is configured in src/app/layout.tsx. Sitemap, robots, and manifest output are generated by:
src/app/sitemap.tssrc/app/robots.tssrc/app/manifest.tsUpdate NEXT_PUBLIC_SITE_URL before deploying so all generated URLs point to the production domain.
Static files live in public/assets.
Common asset paths:
public/assets/projectspublic/assets/skillspublic/assets/servicespublic/assets/educationspublic/assets/workspublic/assets/imgWhen adding a new project, place the thumbnail in public/assets/projects and reference it from src/data/portfolio.json with a root-relative path, for example:
"/assets/projects/example.webp"
This project is ready to deploy on platforms that support Next.js, such as Vercel.
Before deploying:
NEXT_PUBLIC_SITE_URL to the production domain.WEBFORM_ACCESS_KEY if the contact form should be active.npm run build to verify the production build locally.This is a personal portfolio project. Add a license file if you plan to distribute, reuse, or open-source it publicly.