A modern, fully data-driven portfolio website for a senior game developer. Built with React 19, TypeScript, Vite, and Tailwind CSS, it features a cyberpunk/game-dev aesthetic, smooth GSAP animations, and a built-in visual JSON editor so you can update every piece of content without touching code.
π Live site: omar92.github.io
- Single-file content management β All portfolio data lives in
src/data/portfolio.json. Edit it directly or use the in-app editor. - Built-in Portfolio Editor β Navigate to
/editorin development to edit every section through a form UI that writes back toportfolio.jsonin real time. - Game-dev aesthetic β Glassmorphism, neon glow, parallax animated background, GSAP scroll-triggered reveals, and a glitch text effect.
- Project showcase β Filterable grid of projects with lightbox screenshots, tags, stats, and external links.
- Responsive design β Mobile-first layout built with Tailwind CSS utility classes.
- Dark theme β A consistent cyan / violet / gold neon color palette defined via CSS variables.
- Automated deployment β GitHub Actions builds the site and deploys to GitHub Pages on every push to
main.
| Layer | Technology |
|---|---|
| Framework | React 19, TypeScript 5 |
| Build tool | Vite 7 |
| Styling | Tailwind CSS 3, shadcn/ui, Radix UI |
| Animations | GSAP 3 + ScrollTrigger |
| Forms | React Hook Form 7 + Zod 4 |
| Icons | Lucide React |
| Deployment | GitHub Pages via GitHub Actions |
- Node.js 18+ (Node.js 22 is used in CI)
- npm (comes with Node.js)
git clone https://github.com/omar92/omar92.github.io.git
cd omar92.github.ionpm installnpm run devCreate a .env.local file in the project root:
VITE_GITHUB_TOKEN=your_github_personal_access_tokenThis enables authenticated GitHub API requests, which significantly reduces the chance of 403 API rate limit exceeded for project stats.
The site is now available at http://localhost:5173.
The Portfolio Editor is available at http://localhost:5173/editor.
| Command | Description |
|---|---|
npm run dev |
Start the Vite development server with HMR |
npm run build |
Type-check and build for production (output β docs/) |
npm run preview |
Serve the production build locally for testing |
npm run lint |
Run ESLint on all TypeScript/TSX files |
All portfolio content is stored in a single JSON file:
src/data/portfolio.json
You can edit it directly or use the built-in editor UI (see below).
{
"personal": {
"name": "Your Name",
"title": "Your Title",
"subtitle": "Your Subtitle",
"location": "Your Location",
"tagline": "Your tagline",
"about": "Your bio paragraph",
"avatar": "URL to your profile picture",
"resume": "URL to your resume or GitHub profile",
"contacts": {
"email": "you@example.com",
"phone": "+1 234 567 8900",
"links": [
{ "label": "github", "url": "https://github.com/you", "icon": "Github" },
{ "label": "linkedin", "url": "https://linkedin.com/in/you", "icon": "Linkedin" }
]
}
},
"stats": [
{ "value": 5, "suffix": "+", "label": "Years Experience" }
],
"skills": [
{ "category": "Languages", "items": ["TypeScript", "Python"] }
],
"experience": [
{
"id": "job-1",
"company": "Acme Corp",
"url": "https://acme.com",
"position": "Senior Developer",
"location": "Remote",
"startDate": "2020-01",
"endDate": "Present",
"description": ["Bullet point 1", "Bullet point 2"],
"skills": ["React", "Node.js"],
"projectIds": []
}
],
"education": [
{
"id": "edu-1",
"school": "University Name",
"degree": "B.Sc.",
"field": "Computer Science",
"startYear": 2014,
"endYear": 2018
}
],
"projects": [
{
"id": "project-1",
"name": "My Project",
"category": "Game",
"image": "https://example.com/image.png",
"featured": true,
"tags": ["Unity", "C#"],
"filterTags": ["Unity"],
"shortDescription": "A short description",
"description": "A longer description of the project.",
"links": [
{ "label": "GitHub", "url": "https://github.com/you/project", "icon": "Github" }
],
"features": ["Feature 1", "Feature 2"],
"platforms": ["PC", "Mobile"],
"skills": ["Unity", "C#"]
}
]
}- Run
npm run dev. - Open http://localhost:5173/editor in your browser.
- Edit any field in the form UI β changes are validated in real time.
- Click Save to write the updated JSON back to
src/data/portfolio.json. - The development server hot-reloads automatically so you can see changes instantly.
Note: The editor only works in development mode. It uses a custom Vite middleware (
/__portfolio-jsonendpoint) to read and write the JSON file on disk.
portfolio/
βββ src/
β βββ sections/ # Page sections (Hero, About, Projects, Experience, Contact, Footer)
β βββ components/
β β βββ ui/ # shadcn/ui component library
β β βββ AnimatedBackground.tsx
β βββ pages/
β β βββ PortfolioEditor.tsx # In-app JSON editor
β βββ lib/
β β βββ portfolio.ts # Data types and parsing helpers
β β βββ editorSchema.ts # Zod schema for editor validation
β β βββ utils.ts # Shared utilities (cn, etc.)
β βββ data/
β β βββ portfolio.json # β Edit this file to update all content
β βββ Assets/ # Static images and other assets
β βββ App.tsx # Route definitions
β βββ main.tsx # React entry point
β βββ index.css # Global styles and CSS variables
βββ docs/ # Production build output (deployed to GitHub Pages)
βββ vite.config.ts # Vite configuration + custom plugins
βββ tailwind.config.js # Tailwind CSS configuration
βββ components.json # shadcn/ui configuration
βββ .github/workflows/
βββ deploy-pages.yml # Automated GitHub Pages deployment
The repository is configured for automatic deployment via GitHub Actions:
- Push to the
mainbranch. - The workflow (
.github/workflows/deploy-pages.yml) runsnpm ci && npm run build. - The contents of the
docs/directory are deployed to GitHub Pages. - The live site is updated at
https://<your-username>.github.io/.
npm run buildThe production-ready site is written to the docs/ directory. You can host this folder on any static hosting provider (Netlify, Vercel, Cloudflare Pages, etc.).
| Environment variable | Default | Description |
|---|---|---|
VITE_BASE |
/ |
Base URL path of the deployed site |
VITE_OUT_DIR |
docs |
Build output directory |
To deploy to a custom sub-path, set VITE_BASE before building:
VITE_BASE=/my-portfolio/ npm run build- Colors β CSS custom properties are defined in
src/index.css. Look for the:rootblock to change the primary, secondary, and accent colors. - Fonts β Font families are configured in
tailwind.config.js. - Section layout β Each section is a standalone component in
src/sections/. You can reorder, hide, or modify sections insrc/App.tsx. - Animations β GSAP timelines are co-located with each section component for easy adjustment.
This project is open source. Feel free to fork it and adapt it for your own portfolio.