This commit is contained in:
Flatlogic Bot 2025-10-21 23:13:27 +00:00
parent 186ac32e7c
commit e7d7877d01
7 changed files with 481 additions and 145 deletions

94
assets/css/custom.css Normal file
View File

@ -0,0 +1,94 @@
/* General Body Styles */
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
background-color: #F2F2F7;
color: #1D1D1F;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* Section Padding */
section {
padding: 80px 0;
}
/* Headings */
h1, h2, h3, h4, h5, h6 {
font-weight: 700;
}
h1 {
font-size: 3.5rem;
}
h2 {
font-size: 2.5rem;
margin-bottom: 40px;
}
/* Buttons */
.btn {
border-radius: 0.75rem;
padding: 12px 24px;
font-weight: 600;
transition: all 0.2s ease-in-out;
}
.btn-primary {
background-color: #007AFF;
border-color: #007AFF;
}
.btn-primary:hover {
background-color: #005ecb;
border-color: #005ecb;
transform: translateY(-2px);
}
/* Navbar */
.navbar {
background-color: rgba(255, 255, 255, 0.8);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
}
.navbar-brand {
font-weight: 700;
}
/* Hero Section */
#hero {
background: linear-gradient(180deg, #FFFFFF 0%, #F2F2F7 100%);
padding: 120px 0;
}
/* Card Styles */
.card {
border: none;
border-radius: 0.75rem;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.05);
transition: all 0.3s ease;
}
.card:hover {
transform: translateY(-5px);
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.08);
}
/* Form Styles */
.form-control {
border-radius: 0.75rem;
padding: 12px;
border: 1px solid #e5e5e5;
}
.form-control:focus {
border-color: #007AFF;
box-shadow: 0 0 0 0.25rem rgba(0, 122, 255, 0.25);
}
/* Footer */
footer {
background-color: #FFFFFF;
padding: 40px 0;
}

81
assets/js/main.js Normal file
View File

@ -0,0 +1,81 @@
document.addEventListener('DOMContentLoaded', function () {
// Smooth scrolling for anchor links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
document.querySelector(this.getAttribute('href')).scrollIntoView({
behavior: 'smooth'
});
});
});
// Contact form submission
const contactForm = document.getElementById('contactForm');
if (contactForm) {
contactForm.addEventListener('submit', function (e) {
e.preventDefault();
const formData = new FormData(contactForm);
const formButton = contactForm.querySelector('button[type="submit"]');
const initialButtonText = formButton.innerHTML;
formButton.disabled = true;
formButton.innerHTML = 'Sending...';
fetch('contact_handler.php', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
const alertPlaceholder = document.getElementById('form-feedback');
let alertClass = '';
let alertMessage = '';
if (data.success) {
alertClass = 'alert-success';
alertMessage = 'Thank you! Your message has been sent.';
contactForm.reset();
} else {
alertClass = 'alert-danger';
alertMessage = data.error || 'An unknown error occurred.';
}
const wrapper = document.createElement('div');
wrapper.innerHTML = [
`<div class="alert ${alertClass} alert-dismissible" role="alert">`,
` <div>${alertMessage}</div>`,
' <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>',
'</div>'
].join('');
alertPlaceholder.append(wrapper);
// Reset button
formButton.disabled = false;
formButton.innerHTML = initialButtonText;
// Auto-dismiss alert
setTimeout(() => {
wrapper.remove();
}, 5000);
})
.catch(error => {
console.error('Error:', error);
// Handle network errors
const alertPlaceholder = document.getElementById('form-feedback');
const wrapper = document.createElement('div');
wrapper.innerHTML = [
`<div class="alert alert-danger alert-dismissible" role="alert">`,
` <div>A network error occurred. Please try again.</div>`,
' <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>',
'</div>'
].join('');
alertPlaceholder.append(wrapper);
// Reset button
formButton.disabled = false;
formButton.innerHTML = initialButtonText;
});
});
}
});

56
contact_handler.php Normal file
View File

@ -0,0 +1,56 @@
<?php
ini_set('display_errors', 0); // Do not display errors to the user
header('Content-Type: application/json');
require_once __DIR__ . '/db/config.php';
require_once __DIR__ . '/mail/MailService.php';
$response = ['success' => false];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = trim($_POST['name'] ?? '');
$email = trim($_POST['email'] ?? '');
$message = trim($_POST['message'] ?? '');
// Server-side validation
if (empty($name) || empty($email) || empty($message)) {
$response['error'] = 'Please fill out all fields.';
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
$response['error'] = 'Please provide a valid email address.';
} else {
try {
// 1. Save to database
$pdo = db();
$stmt = $pdo->prepare('INSERT INTO contact_submissions (name, email, message) VALUES (?, ?, ?)');
$stmt->execute([$name, $email, $message]);
// 2. Send email notification
// The recipient email address should be configured in the .env file (MAIL_TO)
// For this example, we let the MailService use its default.
$mailResult = MailService::sendContactMessage($name, $email, $message);
if (!empty($mailResult['success'])) {
$response['success'] = true;
} else {
// Log the error, but don't expose it to the client
error_log('MailService Error: ' . ($mailResult['error'] ?? 'Unknown error'));
// Even if email fails, we saved the submission, so we can consider it a partial success.
// For the user, we'll report full success as their data is captured.
$response['success'] = true;
}
} catch (PDOException $e) {
error_log('Database Error: ' . $e->getMessage());
$response['error'] = 'A server error occurred. Please try again later.';
} catch (Exception $e) {
error_log('General Error: ' . $e->getMessage());
$response['error'] = 'A server error occurred. Please try again later.';
}
}
} else {
$response['error'] = 'Invalid request method.';
}
echo json_encode($response);

View File

@ -0,0 +1,7 @@
CREATE TABLE IF NOT EXISTS contact_submissions (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL,
message TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

17
db/run_migrations.php Normal file
View File

@ -0,0 +1,17 @@
<?php
require_once __DIR__ . '/config.php';
$pdo = db();
$migrations = glob(__DIR__ . '/migrations/*.sql');
sort($migrations);
foreach ($migrations as $file) {
try {
$sql = file_get_contents($file);
$pdo->exec($sql);
echo "Successfully ran migration: " . basename($file) . "\n";
} catch (PDOException $e) {
die("Migration failed: " . $e->getMessage() . "\n");
}
}

300
index.php
View File

@ -1,150 +1,162 @@
<?php
declare(strict_types=1);
@ini_set('display_errors', '1');
@error_reporting(E_ALL);
@date_default_timezone_set('UTC');
$phpVersion = PHP_VERSION;
$now = date('Y-m-d H:i:s');
?>
<!doctype html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>New Style</title>
<?php
// Read project preview data from environment
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? '';
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
?>
<?php if ($projectDescription): ?>
<!-- Meta description -->
<meta name="description" content='<?= htmlspecialchars($projectDescription) ?>' />
<!-- Open Graph meta tags -->
<meta property="og:description" content="<?= htmlspecialchars($projectDescription) ?>" />
<!-- Twitter meta tags -->
<meta property="twitter:description" content="<?= htmlspecialchars($projectDescription) ?>" />
<?php endif; ?>
<?php if ($projectImageUrl): ?>
<!-- Open Graph image -->
<meta property="og:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
<!-- Twitter image -->
<meta property="twitter:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
<?php endif; ?>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
<style>
:root {
--bg-color-start: #6a11cb;
--bg-color-end: #2575fc;
--text-color: #ffffff;
--card-bg-color: rgba(255, 255, 255, 0.01);
--card-border-color: rgba(255, 255, 255, 0.1);
}
body {
margin: 0;
font-family: 'Inter', sans-serif;
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
color: var(--text-color);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
text-align: center;
overflow: hidden;
position: relative;
}
body::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path d="M-10 10L110 10M10 -10L10 110" stroke-width="1" stroke="rgba(255,255,255,0.05)"/></svg>');
animation: bg-pan 20s linear infinite;
z-index: -1;
}
@keyframes bg-pan {
0% { background-position: 0% 0%; }
100% { background-position: 100% 100%; }
}
main {
padding: 2rem;
}
.card {
background: var(--card-bg-color);
border: 1px solid var(--card-border-color);
border-radius: 16px;
padding: 2rem;
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.1);
}
.loader {
margin: 1.25rem auto 1.25rem;
width: 48px;
height: 48px;
border: 3px solid rgba(255, 255, 255, 0.25);
border-top-color: #fff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.hint {
opacity: 0.9;
}
.sr-only {
position: absolute;
width: 1px; height: 1px;
padding: 0; margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap; border: 0;
}
h1 {
font-size: 3rem;
font-weight: 700;
margin: 0 0 1rem;
letter-spacing: -1px;
}
p {
margin: 0.5rem 0;
font-size: 1.1rem;
}
code {
background: rgba(0,0,0,0.2);
padding: 2px 6px;
border-radius: 4px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
footer {
position: absolute;
bottom: 1rem;
font-size: 0.8rem;
opacity: 0.7;
}
</style>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- SEO Meta Tags -->
<title>nomara - AI-Powered Marketing</title>
<meta name="description" content="AI-Powered Marketing Portal and Public Website built with Flatlogic Generator.">
<meta name="keywords" content="ai marketing, social media automation, client portal, content calendar, digital marketing, saas, marketing analytics, flatlogic">
<!-- Open Graph / Facebook -->
<meta property="og:type" content="website">
<meta property="og:title" content="nomara - AI-Powered Marketing">
<meta property="og:description" content="AI-Powered Marketing Portal and Public Website built with Flatlogic Generator.">
<meta property="og:image" content="<?php echo htmlspecialchars($_SERVER['PROJECT_IMAGE_URL'] ?? ''); ?>">
<!-- Twitter -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="nomara - AI-Powered Marketing">
<meta name="twitter:description" content="AI-Powered Marketing Portal and Public Website built with Flatlogic Generator.">
<meta name="twitter:image" content="<?php echo htmlspecialchars($_SERVER['PROJECT_IMAGE_URL'] ?? ''); ?>">
<!-- Stylesheets -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
<!-- Icons -->
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
</head>
<body>
<main>
<div class="card">
<h1>Analyzing your requirements and generating your website…</h1>
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
<span class="sr-only">Loading…</span>
</div>
<p class="hint"><?= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWizzy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.</p>
<p class="hint">This page will update automatically as the plan is implemented.</p>
<p>Runtime: PHP <code><?= htmlspecialchars($phpVersion) ?></code> — UTC <code><?= htmlspecialchars($now) ?></code></p>
</div>
</main>
<footer>
Page updated: <?= htmlspecialchars($now) ?> (UTC)
</footer>
<header class="sticky-top">
<nav class="navbar navbar-expand-lg navbar-light">
<div class="container">
<a class="navbar-brand" href="#">nomara</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item"><a class="nav-link" href="#about">About</a></li>
<li class="nav-item"><a class="nav-link" href="#portfolio">Portfolio</a></li>
<li class="nav-item"><a class="nav-link" href="#testimonials">Testimonials</a></li>
<li class="nav-item"><a class="nav-link" href="#contact">Contact</a></li>
</ul>
</div>
</div>
</nav>
</header>
<main>
<!-- Hero Section -->
<section id="hero" class="text-center">
<div class="container">
<h1 class="display-3">Automate Your Marketing with AI</h1>
<p class="lead col-lg-8 mx-auto">We build intelligent systems to scale your social media, content creation, and client management. Focus on strategy, not busywork.</p>
<a href="#contact" class="btn btn-primary btn-lg mt-4">Get a Demo</a>
</div>
</section>
<!-- About Section -->
<section id="about">
<div class="container">
<h2 class="text-center">The Future of Agency Operations</h2>
<div class="row mt-5 align-items-center">
<div class="col-lg-6">
<h3>A Central Hub for Growth</h3>
<p>Our platform provides a unified portal for your team and clients. Manage projects, approve content, and track performance—all in one place. We integrate with the tools you already love, like Stripe, Calendly, and Meta Ads, to create seamless, automated workflows.</p>
</div>
<div class="col-lg-6 text-center">
<!-- Placeholder for an illustration or screenshot -->
<img src="https://via.placeholder.com/500x350/007AFF/FFFFFF?text=Portal+Screenshot" class="img-fluid rounded shadow-sm" alt="Marketing Portal Screenshot">
</div>
</div>
</div>
</section>
<!-- Portfolio Section -->
<section id="portfolio" class="bg-white">
<div class="container">
<h2 class="text-center">Our Work</h2>
<div class="row g-4 mt-4">
<div class="col-md-4"><div class="card"><img src="https://via.placeholder.com/600x400/EFEFEF/1D1D1F?text=Project+One" class="card-img-top" alt="Project One"><div class="card-body"><h5 class="card-title">Client A</h5><p class="card-text">Social Media Growth</p></div></div></div>
<div class="col-md-4"><div class="card"><img src="https://via.placeholder.com/600x400/EFEFEF/1D1D1F?text=Project+Two" class="card-img-top" alt="Project Two"><div class="card-body"><h5 class="card-title">Client B</h5><p class="card-text">Content Automation</p></div></div></div>
<div class="col-md-4"><div class="card"><img src="https://via.placeholder.com/600x400/EFEFEF/1D1D1F?text=Project+Three" class="card-img-top" alt="Project Three"><div class="card-body"><h5 class="card-title">Client C</h5><p class="card-text">Ad Campaign Management</p></div></div></div>
</div>
</div>
</section>
<!-- Testimonials Section -->
<section id="testimonials">
<div class="container">
<h2 class="text-center">What Our Clients Say</h2>
<div class="row mt-5">
<div class="col-md-6 col-lg-4 mb-4">
<div class="card p-4 text-center h-100">
<p>"Working with this team has been a game-changer. Our efficiency has skyrocketed."</p>
<footer class="blockquote-footer mt-auto">Jane Doe, CEO of Company</footer>
</div>
</div>
<div class="col-md-6 col-lg-4 mb-4">
<div class="card p-4 text-center h-100">
<p>"The client portal is intuitive and saves us countless hours of back-and-forth."</p>
<footer class="blockquote-footer mt-auto">John Smith, Marketing Director</footer>
</div>
</div>
<div class="col-md-12 col-lg-4 mb-4">
<div class="card p-4 text-center h-100">
<p>"Finally, a single source of truth for all our marketing activities. Highly recommended."</p>
<footer class="blockquote-footer mt-auto">Sam Wilson, Founder</footer>
</div>
</div>
</div>
</div>
</section>
<!-- Contact Section -->
<section id="contact" class="bg-white">
<div class="container">
<h2 class="text-center">Let's Connect</h2>
<div class="row justify-content-center">
<div class="col-lg-6">
<p class="text-center mb-4">Fill out the form below to schedule a demo and learn how we can help you scale.</p>
<div id="form-feedback"></div>
<form id="contactForm">
<div class="mb-3">
<label for="name" class="form-label">Full Name</label>
<input type="text" class="form-control" id="name" name="name" required>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email Address</label>
<input type="email" class="form-control" id="email" name="email" required>
</div>
<div class="mb-3">
<label for="message" class="form-label">Message</label>
<textarea class="form-control" id="message" name="message" rows="5" required></textarea>
</div>
<div class="d-grid">
<button type="submit" class="btn btn-primary btn-lg">Send Message</button>
</div>
</form>
</div>
</div>
</div>
</section>
</main>
<footer class="text-center">
<div class="container">
<p class="mb-0">&copy; <?php echo date("Y"); ?> nomara. All Rights Reserved. | <a href="privacy.php">Privacy Policy</a></p>
</div>
</footer>
<!-- Scripts -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
<script>
feather.replace()
</script>
</body>
</html>

69
privacy.php Normal file
View File

@ -0,0 +1,69 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Privacy Policy - nomara</title>
<meta name="description" content="Privacy Policy for nomara.">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
</head>
<body>
<header class="sticky-top">
<nav class="navbar navbar-expand-lg navbar-light">
<div class="container">
<a class="navbar-brand" href="index.php">nomara</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav ms-auto">
<li class="nav-item"><a class="nav-link" href="index.php#about">About</a></li>
<li class="nav-item"><a class="nav-link" href="index.php#portfolio">Portfolio</a></li>
<li class="nav-item"><a class="nav-link" href="index.php#testimonials">Testimonials</a></li>
<li class="nav-item"><a class="nav-link" href="index.php#contact">Contact</a></li>
</ul>
</div>
</div>
</nav>
</header>
<main>
<section id="privacy-policy">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-8">
<h1 class="mb-4">Privacy Policy</h1>
<p class="lead">This is a placeholder for your privacy policy. It's important to outline how you collect, use, and protect your users' data.</p>
<h2 class="mt-5">1. Information We Collect</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam vel Risu commodo, vive tra libero et, consequat magna. Integer vitae ex et lectus imperdiet sollicitudin. Sed pulvinar, quam vitae vehicula semper, purus metus aliquam ex, non luctus neque dui vel nulla.</p>
<h2 class="mt-5">2. How We Use Your Information</h2>
<p>Suspendisse potenti. In hac habitasse platea dictumst. Aenean sed est a arcu tristique auctor. Proin in nulla eget ligula venenatis mattis. Vivamus aliquam, nunc at tincidunt scelerisque, nunc urna auctor eros, nec tincidunt mi ex vitae felis.</p>
<h2 class="mt-5">3. Data Security</h2>
<p>Cras interdum, nisl eget egestas dapibus, ipsum nulla consequat orci, non posuere libero nisi eu odio. Nam nec lectus ut quam facilisis bibendum. Aliquam erat volutpat. Sed sit amet dui quis elit laoreet feugiat.</p>
<h2 class="mt-5">4. Your Rights</h2>
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec ullamcorper, justo at pretium euismod, elit felis feugiat metus, non commodo odio justo sed magna.</p>
<p class="mt-4">Last updated: <?php echo date('F j, Y'); ?>.</p>
</div>
</div>
</div>
</section>
</main>
<footer class="text-center">
<div class="container">
<p class="mb-0">&copy; <?php echo date("Y"); ?> nomara. All Rights Reserved. | <a href="privacy.php">Privacy Policy</a></p>
</div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
</body>
</html>