Migrate to Stack A: PHP-fpm + nginx + supervisord, drop flat HTML + Python API
- Remove old flat HTML pages (index, about, blog, contact, reviews, services/*, locations/*) - Remove Python/Flask API container (api/) - Remove old root nginx.conf and components/ - Add infra/: full nginx.conf (http block at /etc/nginx/nginx.conf), php-fpm-pool.conf (TCP listen), supervisord.conf, entrypoint.sh (auto-generates ALTCHA_HMAC_KEY) - Add src/: PHP router, page/service/location/blog templates, contact handler, altcha handler, promo endpoint, SQLite data files - Rewrite Dockerfile: single container, tini PID 1, healthcheck, all env vars declared - Update docker-compose.yml: port 8096, env_file, healthcheck - Update .dockerignore: exclude .env.*, include robots.txt/sitemap.xml/404.html/500.html - Update assets: tokens.css, promo-popup.css/js, altcha.min.js, refactored form.js/main.js Verified: all 17 routes 200, protection audit PASS, Resend confirmed working Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
$db = new SQLite3(__DIR__ . '/../data/locations.sqlite', SQLITE3_OPEN_READONLY);
|
||||
$db->busyTimeout(3000);
|
||||
$loc = $db->querySingle("SELECT * FROM locations WHERE slug='" . SQLite3::escapeString($slug) . "'", true);
|
||||
$db->close();
|
||||
|
||||
if (!$loc) {
|
||||
http_response_code(404);
|
||||
$page_title = '404: Location Not Found | Floor It Hardwood Floors';
|
||||
$page_meta = '';
|
||||
require __DIR__ . '/../components/_header.php';
|
||||
echo '<section class="section section--light"><div class="container"><h1>Location Not Found</h1><p><a href="/locations/">View all locations</a></p></div></section>';
|
||||
require __DIR__ . '/../components/_footer.php';
|
||||
exit;
|
||||
}
|
||||
|
||||
$page_title = $loc['title'];
|
||||
$page_meta = $loc['meta_description'];
|
||||
$body = json_decode($loc['body_json'] ?? '{}', true) ?? [];
|
||||
$faqs = json_decode($loc['faqs_json'] ?? '[]', true) ?? [];
|
||||
$city = $loc['city'];
|
||||
|
||||
require __DIR__ . '/../components/_header.php';
|
||||
?>
|
||||
|
||||
<section class="page-hero section section--dark">
|
||||
<div class="container">
|
||||
<div class="page-hero-content">
|
||||
<span class="eyebrow"><?= htmlspecialchars($loc['hero_eyebrow'] ?? '', ENT_QUOTES) ?></span>
|
||||
<h1><?= htmlspecialchars($loc['hero_h1'] ?? '', ENT_QUOTES) ?></h1>
|
||||
<p class="lead"><?= htmlspecialchars($loc['hero_lead'] ?? '', ENT_QUOTES) ?></p>
|
||||
<a href="/contact/" class="btn btn--primary btn--lg">Request a <?= htmlspecialchars($city, ENT_QUOTES) ?> Estimate</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php if (!empty($body['overview_h2'])): ?>
|
||||
<section class="section section--light">
|
||||
<div class="container">
|
||||
<div class="section-header">
|
||||
<?php if (!empty($body['overview_eyebrow'])): ?><span class="eyebrow"><?= htmlspecialchars($body['overview_eyebrow'], ENT_QUOTES) ?></span><?php endif; ?>
|
||||
<h2><?= htmlspecialchars($body['overview_h2'], ENT_QUOTES) ?></h2>
|
||||
<div class="divider"></div>
|
||||
<?php if (!empty($body['overview_body_1'])): ?><p><?= htmlspecialchars($body['overview_body_1'], ENT_QUOTES) ?></p><?php endif; ?>
|
||||
<?php if (!empty($body['overview_body_2'])): ?><p style="margin-top:1rem;color:var(--smoke);"><?= htmlspecialchars($body['overview_body_2'], ENT_QUOTES) ?></p><?php endif; ?>
|
||||
</div>
|
||||
<?php
|
||||
$stats = [];
|
||||
for ($i = 1; $i <= 3; $i++) {
|
||||
if (!empty($body["stat_{$i}_num"])) {
|
||||
$stats[] = ['num' => $body["stat_{$i}_num"], 'label' => $body["stat_{$i}_label"] ?? '', 'sub' => $body["stat_{$i}_sub"] ?? ''];
|
||||
}
|
||||
}
|
||||
if ($stats): ?>
|
||||
<div class="stats-row">
|
||||
<?php foreach ($stats as $stat): ?>
|
||||
<div class="stat-item">
|
||||
<strong><?= htmlspecialchars($stat['num'], ENT_QUOTES) ?></strong>
|
||||
<span><?= htmlspecialchars($stat['label'], ENT_QUOTES) ?></span>
|
||||
<?php if ($stat['sub']): ?><small><?= htmlspecialchars($stat['sub'], ENT_QUOTES) ?></small><?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (!empty($body['services_intro'])): ?>
|
||||
<section class="section section--dark">
|
||||
<div class="container">
|
||||
<div class="section-header">
|
||||
<span class="eyebrow">Services in <?= htmlspecialchars($city, ENT_QUOTES) ?></span>
|
||||
<h2>Hardwood Floor Services in <?= htmlspecialchars($city, ENT_QUOTES) ?>, NY</h2>
|
||||
<p class="lead"><?= htmlspecialchars($body['services_intro'], ENT_QUOTES) ?></p>
|
||||
</div>
|
||||
<div class="grid grid--3col services-local-grid">
|
||||
<?php for ($i = 1; $i <= 3; $i++): $tk = "service_{$i}_title"; $bk = "service_{$i}_body"; ?>
|
||||
<?php if (!empty($body[$tk])): ?>
|
||||
<div class="card card--service-local">
|
||||
<h3><?= htmlspecialchars($body[$tk], ENT_QUOTES) ?></h3>
|
||||
<p><?= htmlspecialchars($body[$bk] ?? '', ENT_QUOTES) ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endfor; ?>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ($faqs): ?>
|
||||
<section class="section section--light">
|
||||
<div class="container faq-section">
|
||||
<div class="section-header">
|
||||
<span class="eyebrow"><?= htmlspecialchars($city, ENT_QUOTES) ?> FAQs</span>
|
||||
<h2>Common Questions from <?= htmlspecialchars($city, ENT_QUOTES) ?> Homeowners</h2>
|
||||
</div>
|
||||
<div class="faq-list">
|
||||
<?php foreach ($faqs as $faq): ?>
|
||||
<details class="faq-item">
|
||||
<summary><?= htmlspecialchars($faq['q'] ?? '', ENT_QUOTES) ?></summary>
|
||||
<p><?= htmlspecialchars($faq['a'] ?? '', ENT_QUOTES) ?></p>
|
||||
</details>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
|
||||
<section class="section section--amber cta-section">
|
||||
<div class="container cta-section-inner">
|
||||
<div class="cta-section-text">
|
||||
<h2><?= htmlspecialchars($body['form_h2'] ?? "Request a {$city} Floor Estimate", ENT_QUOTES) ?></h2>
|
||||
<p>We respond to all <?= htmlspecialchars($city, ENT_QUOTES) ?> inquiries within 24 hours.</p>
|
||||
</div>
|
||||
<a href="/contact/" class="btn btn--primary btn--lg"><?= htmlspecialchars($body['form_submit'] ?? 'Send Estimate Request', ENT_QUOTES) ?></a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php require __DIR__ . '/../components/_footer.php'; ?>
|
||||
Reference in New Issue
Block a user