Add Dockerized LAMP stack and website skeleton for ALWISP

- Docker Compose orchestrating PHP 8.2/Apache web container and MySQL 8.0
- Dockerfile with GD, PDO, MySQLi extensions and security hardening
- Apache vhost with mod_rewrite, deflate, expires, and security headers
- PHP config with OPcache enabled and display_errors off
- MySQL init schema (contacts, coverage_zones tables)
- Front-controller PHP router (index.php → pages/)
- Responsive homepage: hero, stats bar, services cards, why section, coverage CTA
- Stub pages: services, coverage, about, contact (with working form skeleton), 404
- CSS design system using brand palette from logo (navy #0d1b3e → teal #00bcd4 + orange #f57c00 accents)
- JS: nav scroll/mobile toggle, IntersectionObserver counter animation, scroll reveal

https://claude.ai/code/session_015wpwmheufcxkBuXivrSHhd
This commit is contained in:
Claude
2026-02-28 21:39:21 +00:00
parent 69b567cf72
commit 3e26125afa
18 changed files with 1469 additions and 0 deletions

9
www/pages/404.php Normal file
View File

@@ -0,0 +1,9 @@
<?php http_response_code(404); ?>
<section class="section page-hero" style="text-align:center; min-height:60vh; display:flex; align-items:center;">
<div class="container">
<p class="hero__eyebrow">Error 404</p>
<h1 class="section__heading">Page Not Found</h1>
<p class="section__sub">The page you're looking for doesn't exist or has moved.</p>
<a href="/" class="btn btn--primary" style="margin-top:2rem">Back to Home</a>
</div>
</section>

14
www/pages/about.php Normal file
View File

@@ -0,0 +1,14 @@
<!-- ABOUT PAGE placeholder -->
<section class="section page-hero">
<div class="container">
<span class="section__eyebrow">Who We Are</span>
<h1 class="section__heading">About ALWISP</h1>
<p class="section__sub">Alabama's locally-owned wireless internet and mesh networking company.</p>
</div>
</section>
<section class="section">
<div class="container" style="max-width:800px">
<div class="placeholder-block">Company story, team bios, and mission statement will go here.</div>
</div>
</section>

96
www/pages/contact.php Normal file
View File

@@ -0,0 +1,96 @@
<?php
$success = false;
$errors = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$name = trim(htmlspecialchars($_POST['name'] ?? '', ENT_QUOTES));
$email = trim(htmlspecialchars($_POST['email'] ?? '', ENT_QUOTES));
$phone = trim(htmlspecialchars($_POST['phone'] ?? '', ENT_QUOTES));
$subject = trim(htmlspecialchars($_POST['subject'] ?? '', ENT_QUOTES));
$message = trim(htmlspecialchars($_POST['message'] ?? '', ENT_QUOTES));
if (!$name) $errors[] = 'Name is required.';
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) $errors[] = 'A valid email is required.';
if (!$message) $errors[] = 'Message is required.';
if (empty($errors)) {
// TODO: swap for DB insert + email once credentials are configured
$success = true;
}
}
?>
<section class="section page-hero">
<div class="container">
<span class="section__eyebrow">Reach Out</span>
<h1 class="section__heading">Contact Us</h1>
<p class="section__sub">Questions about service, coverage, or your account? We're here to help.</p>
</div>
</section>
<section class="section">
<div class="container contact__grid">
<div class="contact__info">
<h2 class="contact__heading">Get In Touch</h2>
<ul class="contact__details">
<li>📞 <a href="tel:+10000000000">(000) 000-0000</a></li>
<li>✉ <a href="mailto:info@alwisp.net">info@alwisp.net</a></li>
<li>🕐 MonFri 8am6pm CST<br>Emergency support 24/7</li>
</ul>
</div>
<div class="contact__form-wrap">
<?php if ($success): ?>
<div class="alert alert--success" role="alert">
Thanks! We'll be in touch within one business day.
</div>
<?php endif; ?>
<?php if (!empty($errors)): ?>
<div class="alert alert--error" role="alert">
<ul><?php foreach ($errors as $e) echo "<li>" . $e . "</li>"; ?></ul>
</div>
<?php endif; ?>
<form method="post" action="/contact" class="form" novalidate>
<div class="form__row form__row--2">
<div class="form__group">
<label for="name" class="form__label">Name <span aria-hidden="true">*</span></label>
<input type="text" id="name" name="name" class="form__input" required
value="<?= htmlspecialchars($_POST['name'] ?? '') ?>">
</div>
<div class="form__group">
<label for="email" class="form__label">Email <span aria-hidden="true">*</span></label>
<input type="email" id="email" name="email" class="form__input" required
value="<?= htmlspecialchars($_POST['email'] ?? '') ?>">
</div>
</div>
<div class="form__row form__row--2">
<div class="form__group">
<label for="phone" class="form__label">Phone</label>
<input type="tel" id="phone" name="phone" class="form__input"
value="<?= htmlspecialchars($_POST['phone'] ?? '') ?>">
</div>
<div class="form__group">
<label for="subject" class="form__label">Subject</label>
<select id="subject" name="subject" class="form__input">
<option value="">Select a topic…</option>
<option value="new-service">New Service Inquiry</option>
<option value="support">Technical Support</option>
<option value="billing">Billing Question</option>
<option value="coverage">Coverage Question</option>
<option value="other">Other</option>
</select>
</div>
</div>
<div class="form__group">
<label for="message" class="form__label">Message <span aria-hidden="true">*</span></label>
<textarea id="message" name="message" class="form__input form__textarea" rows="5" required><?= htmlspecialchars($_POST['message'] ?? '') ?></textarea>
</div>
<button type="submit" class="btn btn--primary">Send Message</button>
</form>
</div>
</div>
</section>

17
www/pages/coverage.php Normal file
View File

@@ -0,0 +1,17 @@
<!-- COVERAGE PAGE placeholder -->
<section class="section page-hero">
<div class="container">
<span class="section__eyebrow">Service Area</span>
<h1 class="section__heading">Coverage Map</h1>
<p class="section__sub">See where ALWISP service is available.</p>
</div>
</section>
<section class="section">
<div class="container">
<div class="placeholder-block" style="min-height:420px; display:flex; align-items:center; justify-content:center;">
Interactive coverage map will be embedded here.<br>
(Leaflet.js / Google Maps integration roadmap item)
</div>
</div>
</section>

170
www/pages/home.php Normal file
View File

@@ -0,0 +1,170 @@
<!-- ====================================================
HOME PAGE
===================================================== -->
<!-- HERO -->
<section class="hero" aria-labelledby="hero-heading">
<div class="hero__mesh-bg" aria-hidden="true"></div>
<div class="container hero__content">
<p class="hero__eyebrow">Alabama's Wireless Network Provider</p>
<h1 id="hero-heading" class="hero__heading">
Fast, Reliable Internet<br>
<span class="gradient-text">Built for Alabama</span>
</h1>
<p class="hero__sub">
Enterprise-grade mesh networking that reaches where fiber can't.
Residential plans, business solutions, and infrastructure buildouts across Alabama.
</p>
<div class="hero__actions">
<a href="/coverage" class="btn btn--primary">Check My Coverage</a>
<a href="/services" class="btn btn--ghost">View Plans</a>
</div>
</div>
<div class="hero__scroll-hint" aria-hidden="true">
<span class="hero__scroll-dot"></span>
</div>
</section>
<!-- STATS BAR -->
<section class="stats-bar" aria-label="Quick statistics">
<div class="container stats-bar__grid">
<div class="stat">
<span class="stat__value" data-count="500">0</span><span class="stat__unit">+</span>
<span class="stat__label">Active Subscribers</span>
</div>
<div class="stat">
<span class="stat__value" data-count="15">0</span><span class="stat__unit"> Counties</span>
<span class="stat__label">Coverage Area</span>
</div>
<div class="stat">
<span class="stat__value" data-count="99">0</span><span class="stat__unit">%</span>
<span class="stat__label">Uptime SLA</span>
</div>
<div class="stat">
<span class="stat__value" data-count="1">0</span><span class="stat__unit">Gbps</span>
<span class="stat__label">Backbone Capacity</span>
</div>
</div>
</section>
<!-- SERVICES PREVIEW -->
<section class="section services-preview" aria-labelledby="services-heading">
<div class="container">
<div class="section__header">
<span class="section__eyebrow">What We Offer</span>
<h2 id="services-heading" class="section__heading">Connectivity Solutions</h2>
<p class="section__sub">From home internet to full network infrastructure buildouts.</p>
</div>
<div class="cards">
<div class="card card--hover">
<div class="card__icon" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>
</div>
<h3 class="card__title">Residential Internet</h3>
<p class="card__body">High-speed wireless internet for homes and small properties. No contracts, transparent pricing.</p>
<a href="/services#residential" class="card__link">See Plans </a>
</div>
<div class="card card--hover">
<div class="card__icon" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="7" width="20" height="14" rx="2"/><path d="M16 7V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v2"/><line x1="12" y1="12" x2="12" y2="16"/><line x1="10" y1="14" x2="14" y2="14"/></svg>
</div>
<h3 class="card__title">Business Internet</h3>
<p class="card__body">Dedicated bandwidth, static IPs, and priority support for businesses of any size.</p>
<a href="/services#business" class="card__link">See Plans </a>
</div>
<div class="card card--hover">
<div class="card__icon" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="2"/><circle cx="12" cy="5" r="1"/><circle cx="19" cy="9" r="1"/><circle cx="19" cy="15" r="1"/><circle cx="12" cy="19" r="1"/><circle cx="5" cy="15" r="1"/><circle cx="5" cy="9" r="1"/><path d="M12 7v3m5.2.8-2.5 1.5m2.5 4.7-2.5-1.5M12 17v-3m-5.2-.8 2.5-1.5m-2.5-4.7 2.5 1.5"/></svg>
</div>
<h3 class="card__title">Mesh Infrastructure</h3>
<p class="card__body">Full network design, tower buildouts, and mesh deployments for communities and enterprises.</p>
<a href="/services#infrastructure" class="card__link">Learn More </a>
</div>
<div class="card card--hover">
<div class="card__icon" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/></svg>
</div>
<h3 class="card__title">Managed Networking</h3>
<p class="card__body">Ongoing monitoring, maintenance, and support so your network runs itself.</p>
<a href="/services#managed" class="card__link">Learn More </a>
</div>
</div>
</div>
</section>
<!-- WHY ALWISP -->
<section class="section section--alt why" aria-labelledby="why-heading">
<div class="container why__grid">
<div class="why__text">
<span class="section__eyebrow">Why ALWISP</span>
<h2 id="why-heading" class="section__heading">Local Team.<br>Enterprise Tech.</h2>
<p>We're an Alabama company solving Alabama's connectivity gap. We deploy the same equipment used by major carriers without the corporate red tape or out-of-state call centers.</p>
<ul class="why__list">
<li><span class="why__check" aria-hidden="true"></span> Local 24/7 technical support</li>
<li><span class="why__check" aria-hidden="true"></span> No data caps on most plans</li>
<li><span class="why__check" aria-hidden="true"></span> Month-to-month options available</li>
<li><span class="why__check" aria-hidden="true"></span> Self-healing mesh redundancy</li>
<li><span class="why__check" aria-hidden="true"></span> Transparent pricing no hidden fees</li>
</ul>
<a href="/about" class="btn btn--primary" style="margin-top:1.5rem">About Us</a>
</div>
<div class="why__visual" aria-hidden="true">
<div class="mesh-diagram">
<!-- SVG mesh nodes decorative -->
<svg viewBox="0 0 400 340" xmlns="http://www.w3.org/2000/svg" class="mesh-svg">
<defs>
<linearGradient id="lineGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#00bcd4" stop-opacity="0.6"/>
<stop offset="100%" stop-color="#1565c0" stop-opacity="0.3"/>
</linearGradient>
</defs>
<!-- Edges -->
<g stroke="url(#lineGrad)" stroke-width="1.5" fill="none">
<line x1="200" y1="60" x2="320" y2="140"/>
<line x1="200" y1="60" x2="80" y2="140"/>
<line x1="320" y1="140" x2="80" y2="140"/>
<line x1="320" y1="140" x2="280" y2="280"/>
<line x1="80" y1="140" x2="120" y2="280"/>
<line x1="280" y1="280" x2="120" y2="280"/>
<line x1="200" y1="60" x2="200" y2="200"/>
<line x1="200" y1="200" x2="320" y2="140"/>
<line x1="200" y1="200" x2="80" y2="140"/>
<line x1="200" y1="200" x2="280" y2="280"/>
<line x1="200" y1="200" x2="120" y2="280"/>
</g>
<!-- Nodes -->
<g>
<circle cx="200" cy="60" r="12" fill="#f57c00" opacity="0.9" class="mesh-node mesh-node--tower"/>
<circle cx="320" cy="140" r="9" fill="#00bcd4" opacity="0.85" class="mesh-node"/>
<circle cx="80" cy="140" r="9" fill="#00bcd4" opacity="0.85" class="mesh-node"/>
<circle cx="200" cy="200" r="10" fill="#1565c0" opacity="0.9" class="mesh-node"/>
<circle cx="280" cy="280" r="8" fill="#00acc1" opacity="0.8" class="mesh-node"/>
<circle cx="120" cy="280" r="8" fill="#00acc1" opacity="0.8" class="mesh-node"/>
</g>
</svg>
</div>
</div>
</div>
</section>
<!-- COVERAGE CTA -->
<section class="section cta-band" aria-labelledby="cta-heading">
<div class="container cta-band__content">
<h2 id="cta-heading" class="cta-band__heading">Are you in our coverage area?</h2>
<p class="cta-band__sub">Enter your address to see available plans in your area.</p>
<form class="cta-band__form" action="/coverage" method="get" role="search" aria-label="Coverage check">
<input type="text" name="address" placeholder="Enter your address…" class="cta-band__input" aria-label="Street address" required>
<button type="submit" class="btn btn--primary">Check Now</button>
</form>
</div>
</section>

45
www/pages/services.php Normal file
View File

@@ -0,0 +1,45 @@
<!-- SERVICES PAGE placeholder -->
<section class="section page-hero page-hero--services">
<div class="container">
<span class="section__eyebrow">What We Offer</span>
<h1 class="section__heading">Our Services</h1>
<p class="section__sub">Flexible plans for every need from a farmhouse to a full enterprise campus.</p>
</div>
</section>
<section class="section" id="residential">
<div class="container">
<div class="section__header">
<h2 class="section__heading">Residential Plans</h2>
<p class="section__sub">Content coming soon plan tiers will be displayed here.</p>
</div>
<div class="placeholder-block">Plan cards will go here.</div>
</div>
</section>
<section class="section section--alt" id="business">
<div class="container">
<div class="section__header">
<h2 class="section__heading">Business Plans</h2>
</div>
<div class="placeholder-block">Business plan cards will go here.</div>
</div>
</section>
<section class="section" id="infrastructure">
<div class="container">
<div class="section__header">
<h2 class="section__heading">Network Infrastructure</h2>
</div>
<div class="placeholder-block">Infrastructure service details will go here.</div>
</div>
</section>
<section class="section section--alt" id="managed">
<div class="container">
<div class="section__header">
<h2 class="section__heading">Managed Networking</h2>
</div>
<div class="placeholder-block">Managed service details will go here.</div>
</div>
</section>