diff --git a/.env b/.env
index 89d3816..39aae27 100644
--- a/.env
+++ b/.env
@@ -11,5 +11,6 @@ SMTP_USER=your_username
SMTP_PASS=your_password
# Email 'From' and 'Reply-To' Addresses
+MAIL_TO=contact@avareed.design
MAIL_FROM=you@example.com
MAIL_FROM_NAME="Ava Reed Portfolio"
diff --git a/assets/css/custom.css b/assets/css/custom.css
new file mode 100644
index 0000000..6bfd596
--- /dev/null
+++ b/assets/css/custom.css
@@ -0,0 +1,84 @@
+
+/* Google Fonts */
+@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;600;700&family=Lato:wght@400;700&display=swap');
+
+:root {
+ --primary-color: #0d6efd;
+ --secondary-color: #6c757d;
+ --background-color: #f8f9fa;
+ --surface-color: #ffffff;
+ --heading-font: 'Poppins', sans-serif;
+ --body-font: 'Lato', sans-serif;
+ --border-radius: 0.5rem;
+}
+
+body {
+ font-family: var(--body-font);
+ background-color: var(--background-color);
+ color: #333;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ font-family: var(--heading-font);
+ font-weight: 600;
+}
+
+.navbar {
+ transition: background-color 0.3s ease-in-out;
+}
+
+.navbar-scrolled {
+ background-color: var(--surface-color);
+ box-shadow: 0 2px 4px rgba(0,0,0,0.05);
+}
+
+.hero {
+ background: linear-gradient(45deg, #0d6efd, #7aaaff);
+ color: white;
+ padding: 8rem 0;
+}
+
+.hero h1 {
+ font-size: 3.5rem;
+ font-weight: 700;
+}
+
+.section {
+ padding: 4rem 0;
+}
+
+.card {
+ border: none;
+ border-radius: var(--border-radius);
+ box-shadow: 0 4px 6px rgba(0,0,0,0.1);
+ transition: transform 0.2s ease-in-out;
+}
+
+.card:hover {
+ transform: translateY(-5px);
+}
+
+.form-control:focus {
+ box-shadow: 0 0 0 0.25rem rgba(13, 110, 253, 0.25);
+ border-color: #86b7fe;
+}
+
+.btn-primary {
+ background-color: var(--primary-color);
+ border-color: var(--primary-color);
+ border-radius: var(--border-radius);
+ padding: 0.75rem 1.5rem;
+ font-weight: 600;
+}
+
+.avatar {
+ width: 96px;
+ height: 96px;
+ border-radius: 50%;
+}
+
+.about-avatar {
+ width: 256px;
+ height: 256px;
+ border-radius: 50%;
+}
diff --git a/assets/js/main.js b/assets/js/main.js
new file mode 100644
index 0000000..3315690
--- /dev/null
+++ b/assets/js/main.js
@@ -0,0 +1,63 @@
+
+document.addEventListener('DOMContentLoaded', function () {
+ // Smooth scroll for anchor links
+ document.querySelectorAll('a[href^="#"]').forEach(anchor => {
+ anchor.addEventListener('click', function (e) {
+ e.preventDefault();
+ document.querySelector(this.getAttribute('href')).scrollIntoView({
+ behavior: 'smooth'
+ });
+ });
+ });
+
+ // Navbar scroll effect
+ const navbar = document.querySelector('.navbar');
+ window.addEventListener('scroll', () => {
+ if (window.scrollY > 50) {
+ navbar.classList.add('navbar-scrolled');
+ } else {
+ navbar.classList.remove('navbar-scrolled');
+ }
+ });
+
+ // Contact form validation
+ const form = document.querySelector('#contactForm');
+ const form = document.querySelector('#contactForm');
+ if (form) {
+ form.addEventListener('submit', function(event) {
+ let isValid = true;
+ // Clear previous errors
+ document.querySelectorAll('.invalid-feedback').forEach(el => el.style.display = 'none');
+ document.querySelectorAll('.form-control').forEach(el => el.classList.remove('is-invalid'));
+
+ // Name validation
+ const name = document.querySelector('#name');
+ if (name.value.trim() === '') {
+ isValid = false;
+ name.classList.add('is-invalid');
+ document.querySelector('#nameError').style.display = 'block';
+ }
+
+ // Email validation
+ const email = document.querySelector('#email');
+ const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
+ if (!emailPattern.test(email.value)) {
+ isValid = false;
+ email.classList.add('is-invalid');
+ document.querySelector('#emailError').style.display = 'block';
+ }
+
+ // Message validation
+ const message = document.querySelector('#message');
+ if (message.value.trim() === '') {
+ isValid = false;
+ message.classList.add('is-invalid');
+ document.querySelector('#messageError').style.display = 'block';
+ }
+
+ if (!isValid) {
+ event.preventDefault();
+ }
+ });
+ }
+});
diff --git a/index.php b/index.php
index e13ae95..9fe837b 100644
--- a/index.php
+++ b/index.php
@@ -1,131 +1,270 @@
'success', 'text' => 'Thank you! Your message has been sent.'];
+ } else {
+ // For security, don't expose detailed error messages to the user.
+ error_log($result['error']);
+ $_SESSION['message_status'] = ['type' => 'danger', 'text' => 'Sorry, there was an error sending your message. Please try again later.'];
+ }
+ } else {
+ $_SESSION['message_status'] = ['type' => 'danger', 'text' => 'Invalid input. Please check your form entries.'];
+ }
+
+ // Redirect to the same page to clear the POST data
+ header("Location: " . $_SERVER['PHP_SELF'] . "#contact");
+ exit();
+}
+
+if (isset($_SESSION['message_status'])) {
+ $message_status = $_SESSION['message_status'];
+ unset($_SESSION['message_status']);
+}
?>
-
+
-
-
- New Style
-
-
-
-
+
+
+ Ava Reed | Creative Developer & Designer
+
+
+
+
-
-
-
Analyzing your requirements and generating your website…
-
- Loading…
-
-
Flatlogic AI is collecting your requirements and applying the first changes.
-
This page will update automatically as the plan is implemented.
-
Runtime: PHP = htmlspecialchars($phpVersion) ?> — UTC = htmlspecialchars($now) ?>
-
-
-
- Page updated: = htmlspecialchars($now) ?> (UTC)
-
+
+
+
+
+
+
+
+
+
+
Ava Reed: Creative Developer & Designer
+
Building beautiful, functional websites and applications.
+
Contact Me
+
+
+
+
+
+
+
+
Selected Work
+
+
+
+
+
+
+
Project One
+
A brief description of the project goes here.
+
+
+
+
+
+
+
+
+
Project Two
+
A brief description of the project goes here.
+
+
+
+
+
+
+
+
+
Project Three
+
A brief description of the project goes here.
+
+
+
+
+
+
+
+
+
Project Four
+
A brief description of the project goes here.
+
+
+
+
+
+
+
+
+
Project Five
+
A brief description of the project goes here.
+
+
+
+
+
+
+
+
+
Project Six
+
A brief description of the project goes here.
+
+
+
+
+
+
+
+
+
+
+
What I Do
+
+
+
+
Web Design
+
Creating modern and responsive designs that are intuitive and user-friendly.
+
+
+
+
+
Web Development
+
Building fast, secure, and scalable web applications from the ground up.
+
+
+
+
+
UI/UX Consulting
+
Improving user satisfaction by enhancing the usability and accessibility of products.
+
+
+
+
+
+
+
+
+
+
What Clients Say
+
+
+
+
+
+
+
"Ava is a pleasure to work with. Her attention to detail is second to none."
+
+
+
+
+
+
+
+
+
+
+
"The final product exceeded our expectations. Highly recommended!"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
About Me
+
I'm Ava Reed, a passionate developer and designer with a knack for creating elegant solutions in the least amount of time. I specialize in front-end development and love bringing ideas to life in the browser.
+
When I'm not coding, you can find me exploring new technologies, hiking, or enjoying a good cup of coffee.
+
+
+
+
+
+
+
+
+
+
+
+
+
© 2025 Ava Reed. All Rights Reserved.
+
+
+
+
+
+
+
+
diff --git a/mail/MailService.php b/mail/MailService.php
index 0f655d5..8a2909a 100644
--- a/mail/MailService.php
+++ b/mail/MailService.php
@@ -144,7 +144,10 @@ class MailService
}
$transport = $cfg['transport'] ?? 'smtp';
- if ($transport === 'smtp' && class_exists('PHPMailer\\PHPMailer\\PHPMailer')) {
+ if ($transport === 'log') {
+ return self::sendViaLog($cfg, $name, $email, $message, $to, $subject);
+ }
+ if ($transport === 'smtp' && class_exists('PHPMailer\PHPMailer\PHPMailer')) {
return self::sendViaPHPMailer($cfg, $name, $email, $message, $to, $subject);
}
@@ -152,6 +155,40 @@ class MailService
return self::sendViaNativeMail($cfg, $name, $email, $message, $to, $subject);
}
+ private static function sendViaLog(array $cfg, string $name, string $email, string $body, $to, string $subject)
+ {
+ $logPath = __DIR__ . '/../storage/logs/mail.log';
+ $logDir = dirname($logPath);
+ if (!is_dir($logDir)) {
+ @mkdir($logDir, 0775, true);
+ }
+
+ $toList = [];
+ if ($to) {
+ if (is_string($to)) $toList = array_map('trim', explode(',', $to));
+ elseif (is_array($to)) $toList = $to;
+ } elseif (!empty(getenv('MAIL_TO'))) {
+ $toList = array_map('trim', explode(',', getenv('MAIL_TO')));
+ }
+ if (empty($toList)) {
+ $toList[] = $cfg['from_email'] ?? 'no-reply@localhost';
+ }
+
+ $log_message = sprintf(
+ "[%s] MAIL: To: %s, Subject: %s, From: %s <%s>\n---\n%s\n---",
+ date('Y-m-d H:i:s'),
+ implode(', ', $toList),
+ $subject,
+ $name,
+ $email,
+ $body
+ );
+
+ $ok = @file_put_contents($logPath, $log_message, FILE_APPEND);
+
+ return ['success' => $ok !== false];
+ }
+
private static function sendViaPHPMailer(array $cfg, string $name, string $email, string $body, $to, string $subject)
{
$mail = new PHPMailer\PHPMailer\PHPMailer(true);
diff --git a/mail/config.php b/mail/config.php
index c0ad9b9..cec6d46 100644
--- a/mail/config.php
+++ b/mail/config.php
@@ -45,6 +45,11 @@ $smtp_secure = env_val('SMTP_SECURE', 'tls'); // tls | ssl | null
$smtp_user = env_val('SMTP_USER');
$smtp_pass = env_val('SMTP_PASS');
+// If using SMTP but the host is the placeholder, fall back to 'log' transport
+if ($transport === 'smtp' && $smtp_host === 'smtp.example.com') {
+ $transport = 'log';
+}
+
$from_email = env_val('MAIL_FROM', 'no-reply@localhost');
$from_name = env_val('MAIL_FROM_NAME', 'App');
$reply_to = env_val('MAIL_REPLY_TO');