React + Vite portfolio · Deep blue & silver enterprise design FR default · EN / AR (RTL) · Formspree contact · Resume download · Netlify CI/CD
npm install
npm run dev
# → http://localhost:5173Edit src/data/projects.json
Each project has:
| Field | Description |
|---|---|
title |
Object with fr, en, ar keys |
description |
Object with fr, en, ar keys |
stack |
Array of tech strings |
impact |
Object with fr, en, ar keys |
previewUrl |
Live URL → enables Preview button opening in new tab |
githubUrl |
GitHub repo URL |
color |
cyan / blue / indigo / silver / green / amber |
icon |
Any emoji |
Edit src/data/experience.json — same multilingual structure.
Place your PDF at public/resume.pdf
The download button in the Hero works automatically.
git init
git add .
git commit -m "🚀 Portfolio launch"
# Create a repo on github.com first, then:
git remote add origin https://github.com/YOUR_USERNAME/houyem-portfolio.git
git push -u origin main- Go to https://app.netlify.com → Sign up free
- Click Add new site → Import an existing project → GitHub
- Authorize GitHub → select your repo
- Build settings are auto-read from
netlify.toml✅ - Click Deploy site
- ✅ Live at
https://random-name.netlify.app
Custom subdomain (free):
Site settings → Domain management → Options → Edit site name
→ e.g. houyem-noomen.netlify.app
Get your Netlify tokens:
- Netlify → avatar → User settings → Applications → Personal access tokens → New token → Copy it (save it, shown once!)
- Netlify → your site → Site configuration → General → copy the Site ID
Add secrets to GitHub:
- GitHub → your repo → Settings → Secrets and variables → Actions
- Click New repository secret twice:
- Name:
NETLIFY_AUTH_TOKEN→ Value: (your token) - Name:
NETLIFY_SITE_ID→ Value: (your site ID)
- Name:
From now on:
git add . && git commit -m "update projects" && git push
→ GitHub Actions builds → deploys to Netlify → live in ~60 seconds
On Pull Requests: Netlify posts a preview URL in the PR comments automatically.
- Go to https://formspree.io → free account (50 submissions/month)
- Click + New Form → name it "Portfolio Contact"
- Copy your Form ID (e.g.
xpwzgkqr) - Open
src/components/Contact.jsxline ~10 - Replace
YOUR_FORMSPREE_ID:const FORMSPREE_ID = 'xpwzgkqr' // ← your real ID
- Push → auto-deploys → every form submission (+ file attachment) arrives in
noomene.houyem@gmail.com
| Code | Language | Direction |
|---|---|---|
fr |
Français (default) | LTR |
en |
English | LTR |
ar |
العربية | RTL (auto) |
The page dir attribute switches automatically when Arabic is selected.
src/
├── components/
│ ├── Navbar.jsx ← Language switcher
│ ├── Hero.jsx ← Typewriter + stats
│ ├── Skills.jsx
│ ├── Experience.jsx ← Expandable bullet cards
│ ├── Projects.jsx ← Preview / GitHub buttons
│ ├── Education.jsx ← + Organisations + Languages
│ ├── Contact.jsx ← Formspree form + file upload
│ └── Footer.jsx
├── data/
│ ├── projects.json ← ✏️ Edit to update projects
│ └── experience.json ← ✏️ Edit to update experience
├── i18n/
│ ├── fr.json ← French translations
│ ├── en.json ← English translations
│ └── ar.json ← Arabic translations
└── styles.css ← Deep blue/silver design tokens
public/
└── resume.pdf ← ✏️ Place your CV here