A modern, framework-free PHP portfolio β tiny router, reusable layout, responsive UI, and a secure contact form.
Zero external PHP dependencies β’ Deploy anywhere PHP runs π
- Lightweight: plain PHP, no frameworks
- Simple routing:
index.php?page=home|projects|about|contact - Reusable layout: shared
header.php/footer.php - Easy content editing: update one
data/projects.phparray - Secure contact form: CSRF token + server-side validation
- Reliable logging: saves messages to
storage/messages.csv(and attemptsmail()if available) - Modern UI: responsive layout, clean cards, accessible colors
- PHP 8.0+
- A server that can run PHP (local PHP server, shared hosting, VPS, etc.)
- Write permission for
/storage(for saving contact messages)
From the project root:
php -S localhost:8000Open:
http://localhost:8000
incredible-portfolio/
ββ index.php # Router (whitelists pages)
ββ config.php # Site config: name, tagline, owner, contact_email
ββ functions.php # Helpers: config(), e(), CSRF, mail, save_message
ββ header.php # Shared header/layout (top)
ββ footer.php # Shared footer/layout (bottom)
ββ assets/
β ββ css/
β β ββ style.css
β ββ js/
β β ββ main.js
β ββ img/
β ββ preview.png # Add your screenshot here
ββ pages/
β ββ home.php
β ββ projects.php
β ββ about.php
β ββ contact.php
ββ data/
β ββ projects.php # Your projects array
ββ storage/
β ββ messages.csv # Contact form CSV (auto-created)
ββ LICENSE
ββ README.md
Edit config.php:
return [
'site_name' => 'Incredible Portfolio',
'tagline' => 'Developer β’ Builder β’ Learner',
'owner' => 'Your Name',
'contact_email' => 'you@example.com', // used for mail(); CSV logging is always on
];Edit data/projects.php to update:
- title
- description
- tech
- links
featured
- Add a new file inside
pages/(example:pages/services.php) - Whitelist it in
index.php:
$allowed = ['home', 'projects', 'about', 'contact', 'services'];- Add it to navigation (in
header.php) if needed
- Page:
pages/contact.php - Security: CSRF token + server-side validation
- Delivery:
- Always logs to
storage/messages.csv - Attempts
mail()tocontact_email(if supported by hosting)
- Always logs to
Many hosts restrict
mail(). The CSV log is your reliable fallback.
For SMTP, adding a mailer (like PHPMailer) is a great future upgrade.
Shared Hosting (cPanel / Plesk)
- Upload the project where
index.phpis in the document root - Select PHP 8.0+ in hosting settings
- Ensure
/storageis writable
Apache (VPS) β Example VirtualHost
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/incredible-portfolio
<Directory /var/www/incredible-portfolio>
AllowOverride All
Require all granted
</Directory>
</VirtualHost>Nginx (VPS) β Example Server Block
server {
listen 80;
server_name example.com;
root /var/www/incredible-portfolio;
index index.php;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.2-fpm.sock; # adjust version/socket
}
}storage/messages.csv contains private messages.
Make sure /storage is not accessible from the public web.
Create storage/.htaccess:
Require all denied
Deny from alllocation ^~ /storage/ {
deny all;
return 404;
}If messages arenβt being saved, itβs usually storage permissions.
- Ensure
/storageis writable by the server user.
MIT β see LICENSE
Built with vanilla PHP + HTML + CSS + a little JS.