448 lines
19 KiB
Bash
448 lines
19 KiB
Bash
|
|
#!/bin/bash
|
||
|
|
# Update all landing pages with cross-links and synergies
|
||
|
|
|
||
|
|
set -e
|
||
|
|
|
||
|
|
PAGES=(
|
||
|
|
"bridge-inspection-sweden:🇸🇪 Sweden:Trafikverket Compliant"
|
||
|
|
"bridge-inspection-germany:🇩🇪 Germany:DIN Compliant"
|
||
|
|
"bridge-inspection-france:🇫🇷 France:CEREMA Aligned"
|
||
|
|
"bridge-inspection-uk:🇬🇧 UK:DfT Compliant"
|
||
|
|
"bridge-inspection-netherlands:🇳🇱 Netherlands:Rijkswaterstaat Compliant"
|
||
|
|
"infrastructure-monitoring-sweden:🇸🇪 Sweden:National Coverage"
|
||
|
|
"infrastructure-monitoring-germany:🇩🇪 Germany:Bundesweit"
|
||
|
|
"infrastructure-monitoring-france:🇫🇷 France:National Coverage"
|
||
|
|
"infrastructure-monitoring-uk:🇬🇧 UK:National Coverage"
|
||
|
|
"infrastructure-monitoring-netherlands:🇳🇱 Netherlands:National Coverage"
|
||
|
|
)
|
||
|
|
|
||
|
|
# Function to generate related services section
|
||
|
|
generate_related() {
|
||
|
|
local current_page="$1"
|
||
|
|
local current_type="$2"
|
||
|
|
local current_country="$3"
|
||
|
|
|
||
|
|
local related=""
|
||
|
|
|
||
|
|
# Add the opposite service type for same country
|
||
|
|
if [[ "$current_type" == "bridge-inspection" ]]; then
|
||
|
|
related+=" <a href=\"/infrastructure-monitoring/$current_country\" class=\"related-card\">\n"
|
||
|
|
related+=" <div class=\"related-flag\">$(get_flag "$current_country")</div>\n"
|
||
|
|
related+=" <h4>Infrastructure Monitoring — $(get_country_name "$current_country")</h4>\n"
|
||
|
|
related+=" <p>Continuous monitoring of roads, bridges, and utilities beyond single inspections.</p>\n"
|
||
|
|
related+=" <div class=\"related-arrow\">Explore →</div>\n"
|
||
|
|
related+=" </a>\n"
|
||
|
|
else
|
||
|
|
related+=" <a href=\"/bridge-inspection/$current_country\" class=\"related-card\">\n"
|
||
|
|
related+=" <div class=\"related-flag\">$(get_flag "$current_country")</div>\n"
|
||
|
|
related+=" <h4>Bridge Inspection — $(get_country_name "$current_country")</h4>\n"
|
||
|
|
related+=" <p>Professional bridge inspections with regulatory compliance.</p>\n"
|
||
|
|
related+=" <div class=\"related-arrow\">Explore →</div>\n"
|
||
|
|
related+=" </a>\n"
|
||
|
|
fi
|
||
|
|
|
||
|
|
# Add other countries for same service type
|
||
|
|
for page in "${PAGES[@]}"; do
|
||
|
|
local page_name=$(echo "$page" | cut -d: -f1)
|
||
|
|
local page_type=$(echo "$page_name" | cut -d- -f1-2)
|
||
|
|
local page_country=$(echo "$page_name" | sed 's/.*-//')
|
||
|
|
|
||
|
|
if [[ "$page_type" == "$current_type" && "$page_country" != "$current_country" && "$page_name" != "$current_page" ]]; then
|
||
|
|
related+=" <a href=\"/$page_type/$page_country\" class=\"related-card\">\n"
|
||
|
|
related+=" <div class=\"related-flag\">$(get_flag "$page_country")</div>\n"
|
||
|
|
related+=" <h4>$(echo "$current_type" | sed 's/-/ /g' | awk '{for(i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) substr($i,2)} 1') — $(get_country_name "$page_country")</h4>\n"
|
||
|
|
related+=" <p>$(get_compliance "$page")</p>\n"
|
||
|
|
related+=" <div class=\"related-arrow\">Explore →</div>\n"
|
||
|
|
related+=" </a>\n"
|
||
|
|
fi
|
||
|
|
done
|
||
|
|
|
||
|
|
# Add enterprise solutions
|
||
|
|
related+=" <a href=\"/for-organisations\" class=\"related-card\">\n"
|
||
|
|
related+=" <div class=\"related-flag\">🏢</div>\n"
|
||
|
|
related+=" <h4>Enterprise Solutions</h4>\n"
|
||
|
|
related+=" <p>Custom inspection programs with API integration and SLA guarantees.</p>\n"
|
||
|
|
related+=" <div class=\"related-arrow\">Learn more →</div>\n"
|
||
|
|
related+=" </a>\n"
|
||
|
|
|
||
|
|
echo "$related"
|
||
|
|
}
|
||
|
|
|
||
|
|
get_flag() {
|
||
|
|
case "$1" in
|
||
|
|
sweden) echo "🇸🇪" ;;
|
||
|
|
germany) echo "🇩🇪" ;;
|
||
|
|
france) echo "🇫🇷" ;;
|
||
|
|
uk) echo "🇬🇧" ;;
|
||
|
|
netherlands) echo "🇳🇱" ;;
|
||
|
|
*) echo "🌍" ;;
|
||
|
|
esac
|
||
|
|
}
|
||
|
|
|
||
|
|
get_country_name() {
|
||
|
|
case "$1" in
|
||
|
|
sweden) echo "Sweden" ;;
|
||
|
|
germany) echo "Germany" ;;
|
||
|
|
france) echo "France" ;;
|
||
|
|
uk) echo "UK" ;;
|
||
|
|
netherlands) echo "Netherlands" ;;
|
||
|
|
*) echo "$1" ;;
|
||
|
|
esac
|
||
|
|
}
|
||
|
|
|
||
|
|
get_compliance() {
|
||
|
|
echo "$1" | cut -d: -f3
|
||
|
|
}
|
||
|
|
|
||
|
|
# Update each page
|
||
|
|
for page in "${PAGES[@]}"; do
|
||
|
|
page_name=$(echo "$page" | cut -d: -f1)
|
||
|
|
page_flag=$(echo "$page" | cut -d: -f2 | cut -d' ' -f1)
|
||
|
|
page_country=$(echo "$page" | cut -d: -f2 | cut -d' ' -f2)
|
||
|
|
page_compliance=$(echo "$page" | cut -d: -f3)
|
||
|
|
page_type=$(echo "$page_name" | cut -d- -f1-2)
|
||
|
|
|
||
|
|
echo "Updating $page_name..."
|
||
|
|
|
||
|
|
# Download current page
|
||
|
|
aws s3 cp "s3://quixzoom-landing-prod/$page_name.html" "/tmp/$page_name.html" 2>/dev/null || continue
|
||
|
|
|
||
|
|
# Create updated version with cross-links
|
||
|
|
cat > "/tmp/${page_name}-new.html" << EOF
|
||
|
|
<!DOCTYPE html>
|
||
|
|
<html lang="en">
|
||
|
|
<head>
|
||
|
|
<meta charset="UTF-8">
|
||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
|
|
<meta name="theme-color" content="#f5f5f7">
|
||
|
|
<title>$(echo "$page_type" | sed 's/-/ /g' | awk '{for(i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) substr($i,2)} 1') in $(get_country_name "$page_country") — quiXzoom</title>
|
||
|
|
<meta name="description" content="Professional $(echo "$page_type" | sed 's/-/ /g') services across $(get_country_name "$page_country"). $(get_compliance "$page"). Fast deployment, verified data, digital reporting.">
|
||
|
|
<link rel="canonical" href="https://www.quixzoom.com/$page_type/$page_country">
|
||
|
|
|
||
|
|
<!-- hreflang for regional variants -->
|
||
|
|
<link rel="alternate" hreflang="en-se" href="https://www.quixzoom.com/$page_type/sweden">
|
||
|
|
<link rel="alternate" hreflang="en-de" href="https://www.quixzoom.com/$page_type/germany">
|
||
|
|
<link rel="alternate" hreflang="en-fr" href="https://www.quixzoom.com/$page_type/france">
|
||
|
|
<link rel="alternate" hreflang="en-gb" href="https://www.quixzoom.com/$page_type/uk">
|
||
|
|
<link rel="alternate" hreflang="en-nl" href="https://www.quixzoom.com/$page_type/netherlands">
|
||
|
|
<link rel="alternate" hreflang="x-default" href="https://www.quixzoom.com/$page_type">
|
||
|
|
|
||
|
|
<script type="application/ld+json">
|
||
|
|
{
|
||
|
|
"@context": "https://schema.org",
|
||
|
|
"@type": "Service",
|
||
|
|
"name": "$(echo "$page_type" | sed 's/-/ /g' | awk '{for(i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) substr($i,2)} 1') in $(get_country_name "$page_country")",
|
||
|
|
"provider": {
|
||
|
|
"@type": "Organization",
|
||
|
|
"name": "quiXzoom",
|
||
|
|
"url": "https://www.quixzoom.com/"
|
||
|
|
},
|
||
|
|
"areaServed": {
|
||
|
|
"@type": "Country",
|
||
|
|
"name": "$(get_country_name "$page_country")"
|
||
|
|
},
|
||
|
|
"description": "Professional $(echo "$page_type" | sed 's/-/ /g') services across $(get_country_name "$page_country"). $(get_compliance "$page"). Fast deployment, verified data, digital reporting."
|
||
|
|
}
|
||
|
|
</script>
|
||
|
|
<style>
|
||
|
|
:root {
|
||
|
|
--bg-dark: #f5f5f7;
|
||
|
|
--blue: #0066FF;
|
||
|
|
--blue-dark: #0052CC;
|
||
|
|
--blue-glow: rgba(0,102,255,0.10);
|
||
|
|
--text-dark: #1d1d1f;
|
||
|
|
--text-body: #3a3a3a;
|
||
|
|
--text-muted: #6e6e73;
|
||
|
|
--surface: #ffffff;
|
||
|
|
--surface-2: #f5f5f7;
|
||
|
|
--border: rgba(0,0,0,0.09);
|
||
|
|
--green: #00C853;
|
||
|
|
}
|
||
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||
|
|
body {
|
||
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Inter', 'Helvetica Neue', sans-serif;
|
||
|
|
background: var(--bg-dark);
|
||
|
|
color: var(--text-dark);
|
||
|
|
line-height: 1.6;
|
||
|
|
-webkit-font-smoothing: antialiased;
|
||
|
|
}
|
||
|
|
.container { max-width: 1200px; margin: 0 auto; padding: 0 24px; }
|
||
|
|
|
||
|
|
/* Nav */
|
||
|
|
nav {
|
||
|
|
position: sticky; top: 0; z-index: 300;
|
||
|
|
background: rgba(255,255,255,0.92);
|
||
|
|
backdrop-filter: blur(20px);
|
||
|
|
border-bottom: 1px solid var(--border);
|
||
|
|
}
|
||
|
|
.nav-inner { display: flex; align-items: center; justify-content: space-between; height: 64px; }
|
||
|
|
.nav-logo { font-size: 1.375rem; font-weight: 900; color: var(--text-dark); text-decoration: none; }
|
||
|
|
.nav-logo span { color: var(--blue); }
|
||
|
|
.nav-links { display: flex; gap: 32px; }
|
||
|
|
.nav-links a { color: var(--text-muted); text-decoration: none; font-weight: 500; transition: color 0.15s; }
|
||
|
|
.nav-links a:hover { color: var(--text-dark); }
|
||
|
|
.nav-links a.active { color: var(--blue); }
|
||
|
|
|
||
|
|
/* Hero */
|
||
|
|
.hero { padding: 80px 0 60px; text-align: center; background: var(--surface); }
|
||
|
|
.hero h1 { font-size: clamp(2rem, 5vw, 3.5rem); font-weight: 800; letter-spacing: -0.03em; line-height: 1.1; margin-bottom: 20px; }
|
||
|
|
.hero p { font-size: 1.25rem; color: var(--text-body); max-width: 600px; margin: 0 auto; }
|
||
|
|
.hero-badge {
|
||
|
|
display: inline-flex; align-items: center; gap: 8px;
|
||
|
|
background: var(--blue-glow); color: var(--blue);
|
||
|
|
border: 1px solid rgba(0,102,255,0.2); border-radius: 24px;
|
||
|
|
padding: 7px 18px; font-size: 0.8125rem; font-weight: 700; margin-bottom: 24px;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Content sections */
|
||
|
|
.section { padding: 60px 0; }
|
||
|
|
.section-title { text-align: center; margin-bottom: 48px; }
|
||
|
|
.section-title h2 { font-size: 2rem; font-weight: 700; margin-bottom: 12px; }
|
||
|
|
.section-title p { font-size: 1.1rem; color: var(--text-muted); }
|
||
|
|
|
||
|
|
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 24px; }
|
||
|
|
.card {
|
||
|
|
background: var(--surface); border: 1px solid var(--border); border-radius: 20px;
|
||
|
|
padding: 40px; transition: transform 0.2s, box-shadow 0.2s;
|
||
|
|
}
|
||
|
|
.card:hover { transform: translateY(-4px); box-shadow: 0 12px 40px rgba(0,0,0,0.08); }
|
||
|
|
.card h3 { font-size: 1.25rem; font-weight: 700; margin-bottom: 12px; }
|
||
|
|
.card p { font-size: 0.95rem; color: var(--text-muted); line-height: 1.6; }
|
||
|
|
.card .card-link {
|
||
|
|
display: inline-flex; align-items: center; gap: 6px;
|
||
|
|
color: var(--blue); font-size: 0.875rem; font-weight: 600;
|
||
|
|
margin-top: 16px; text-decoration: none;
|
||
|
|
}
|
||
|
|
.card .card-link:hover { gap: 10px; }
|
||
|
|
|
||
|
|
/* Related services */
|
||
|
|
.related-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 16px; }
|
||
|
|
.related-card {
|
||
|
|
background: var(--surface); border: 1.5px solid var(--border); border-radius: 16px;
|
||
|
|
padding: 28px; transition: all 0.2s; text-decoration: none; color: inherit;
|
||
|
|
display: flex; flex-direction: column;
|
||
|
|
}
|
||
|
|
.related-card:hover {
|
||
|
|
transform: translateY(-3px); box-shadow: 0 8px 30px rgba(0,0,0,0.08);
|
||
|
|
border-color: rgba(0,102,255,0.25);
|
||
|
|
}
|
||
|
|
.related-card .related-flag { font-size: 1.5rem; margin-bottom: 12px; }
|
||
|
|
.related-card h4 { font-size: 1rem; font-weight: 700; margin-bottom: 6px; color: var(--text-dark); }
|
||
|
|
.related-card p { font-size: 0.875rem; color: var(--text-muted); line-height: 1.5; }
|
||
|
|
.related-card .related-arrow {
|
||
|
|
margin-top: auto; padding-top: 16px;
|
||
|
|
color: var(--blue); font-size: 0.875rem; font-weight: 600;
|
||
|
|
display: flex; align-items: center; gap: 6px;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Country selector */
|
||
|
|
.country-bar {
|
||
|
|
background: var(--surface); border-bottom: 1px solid var(--border);
|
||
|
|
padding: 16px 0;
|
||
|
|
}
|
||
|
|
.country-bar-inner {
|
||
|
|
display: flex; align-items: center; gap: 8px;
|
||
|
|
overflow-x: auto; scrollbar-width: none;
|
||
|
|
}
|
||
|
|
.country-bar-inner::-webkit-scrollbar { display: none; }
|
||
|
|
.country-chip {
|
||
|
|
display: inline-flex; align-items: center; gap: 6px;
|
||
|
|
padding: 8px 16px; border-radius: 20px;
|
||
|
|
border: 1.5px solid var(--border); background: var(--surface);
|
||
|
|
color: var(--text-muted); font-size: 0.875rem; font-weight: 500;
|
||
|
|
text-decoration: none; white-space: nowrap; transition: all 0.15s;
|
||
|
|
}
|
||
|
|
.country-chip:hover { border-color: var(--blue); color: var(--blue); }
|
||
|
|
.country-chip.active { background: var(--blue); color: #fff; border-color: var(--blue); }
|
||
|
|
|
||
|
|
/* CTA */
|
||
|
|
.cta {
|
||
|
|
background: var(--surface); border: 1px solid var(--border); border-radius: 20px;
|
||
|
|
padding: 60px; text-align: center; margin: 40px 0;
|
||
|
|
}
|
||
|
|
.cta h2 { font-size: 2rem; font-weight: 700; margin-bottom: 16px; }
|
||
|
|
.cta p { font-size: 1.1rem; color: var(--text-muted); margin-bottom: 32px; }
|
||
|
|
.btn {
|
||
|
|
display: inline-block; background: var(--blue); color: #fff; text-decoration: none;
|
||
|
|
padding: 14px 32px; border-radius: 12px; font-weight: 600; transition: background 0.2s;
|
||
|
|
}
|
||
|
|
.btn:hover { background: var(--blue-dark); }
|
||
|
|
.btn-secondary {
|
||
|
|
display: inline-block; background: var(--surface); color: var(--blue);
|
||
|
|
text-decoration: none; padding: 14px 32px; border-radius: 12px;
|
||
|
|
font-weight: 600; border: 2px solid var(--blue); margin-left: 12px;
|
||
|
|
transition: all 0.2s;
|
||
|
|
}
|
||
|
|
.btn-secondary:hover { background: var(--blue); color: #fff; }
|
||
|
|
|
||
|
|
/* Breadcrumb */
|
||
|
|
.breadcrumb {
|
||
|
|
padding: 20px 0 0;
|
||
|
|
font-size: 0.875rem; color: var(--text-muted);
|
||
|
|
}
|
||
|
|
.breadcrumb a { color: var(--text-muted); text-decoration: none; }
|
||
|
|
.breadcrumb a:hover { color: var(--blue); }
|
||
|
|
.breadcrumb span { color: var(--text-dark); font-weight: 500; }
|
||
|
|
|
||
|
|
/* Footer */
|
||
|
|
footer { background: var(--surface); border-top: 1px solid var(--border); padding: 40px 0; }
|
||
|
|
.footer-inner { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 16px; }
|
||
|
|
.footer-links { display: flex; gap: 24px; }
|
||
|
|
.footer-links a { color: var(--text-muted); text-decoration: none; font-size: 0.875rem; }
|
||
|
|
.footer-links a:hover { color: var(--text-dark); }
|
||
|
|
|
||
|
|
@media (max-width: 768px) {
|
||
|
|
.nav-links { display: none; }
|
||
|
|
.cta { padding: 40px 24px; }
|
||
|
|
.btn-secondary { margin-left: 0; margin-top: 12px; }
|
||
|
|
.footer-inner { flex-direction: column; text-align: center; }
|
||
|
|
}
|
||
|
|
</style>
|
||
|
|
</head>
|
||
|
|
<body>
|
||
|
|
<nav>
|
||
|
|
<div class="container">
|
||
|
|
<div class="nav-inner">
|
||
|
|
<a href="/" class="nav-logo">qui<span>X</span>zoom</a>
|
||
|
|
<div class="nav-links">
|
||
|
|
<a href="/">Home</a>
|
||
|
|
<a href="/about">About</a>
|
||
|
|
<a href="/pricing">Pricing</a>
|
||
|
|
<a href="/features">Features</a>
|
||
|
|
<a href="/how-it-works">How It Works</a>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</nav>
|
||
|
|
|
||
|
|
<div class="country-bar">
|
||
|
|
<div class="container">
|
||
|
|
<div class="country-bar-inner">
|
||
|
|
<span style="font-size:0.8125rem;font-weight:600;color:var(--text-muted);white-space:nowrap;margin-right:8px;">$(echo "$page_type" | sed 's/-/ /g' | awk '{for(i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) substr($i,2)} 1'):</span>
|
||
|
|
<a href="/$page_type/sweden" class="country-chip $(if [[ "$page_country" == "sweden" ]]; then echo "active"; fi)">🇸🇪 Sweden</a>
|
||
|
|
<a href="/$page_type/germany" class="country-chip $(if [[ "$page_country" == "germany" ]]; then echo "active"; fi)">🇩🇪 Germany</a>
|
||
|
|
<a href="/$page_type/france" class="country-chip $(if [[ "$page_country" == "france" ]]; then echo "active"; fi)">🇫🇷 France</a>
|
||
|
|
<a href="/$page_type/uk" class="country-chip $(if [[ "$page_country" == "uk" ]]; then echo "active"; fi)">🇬🇧 UK</a>
|
||
|
|
<a href="/$page_type/netherlands" class="country-chip $(if [[ "$page_country" == "netherlands" ]]; then echo "active"; fi)">🇳🇱 Netherlands</a>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<section class="hero">
|
||
|
|
<div class="container">
|
||
|
|
<div class="breadcrumb">
|
||
|
|
<a href="/">Home</a> → <a href="/$page_type">$(echo "$page_type" | sed 's/-/ /g' | awk '{for(i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) substr($i,2)} 1')</a> → <span>$(get_country_name "$page_country")</span>
|
||
|
|
</div>
|
||
|
|
<div class="hero-badge">$page_flag $(get_country_name "$page_country") · $page_compliance</div>
|
||
|
|
<h1>$(echo "$page_type" | sed 's/-/ /g' | awk '{for(i=1;i<=NF;i++) $i=toupper(substr($i,1,1)) substr($i,2)} 1') in $(get_country_name "$page_country")</h1>
|
||
|
|
<p>Nationwide coverage. Deploy inspection missions in hours, not weeks.</p>
|
||
|
|
</div>
|
||
|
|
</section>
|
||
|
|
|
||
|
|
<section class="section">
|
||
|
|
<div class="container">
|
||
|
|
<div class="section-title">
|
||
|
|
<h2>Why choose quiXzoom</h2>
|
||
|
|
<p>Trusted by infrastructure operators across Europe</p>
|
||
|
|
</div>
|
||
|
|
<div class="grid">
|
||
|
|
<div class="card">
|
||
|
|
<h3>Regulatory Compliant</h3>
|
||
|
|
<p>All inspections follow local technical requirements and documentation standards. Digital reports ready for submission.</p>
|
||
|
|
<a href="/features/compliance" class="card-link">Learn about compliance →</a>
|
||
|
|
</div>
|
||
|
|
<div class="card">
|
||
|
|
<h3>Rapid Deployment</h3>
|
||
|
|
<p>Launch inspection missions across multiple sites simultaneously. Zoomers can be on-site within 24 hours.</p>
|
||
|
|
<a href="/how-it-works" class="card-link">See how deployment works →</a>
|
||
|
|
</div>
|
||
|
|
<div class="card">
|
||
|
|
<h3>Verified Data</h3>
|
||
|
|
<p>AI-powered quality control ensures every photo, measurement, and observation meets professional standards.</p>
|
||
|
|
<a href="/features/quality" class="card-link">Explore quality assurance →</a>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</section>
|
||
|
|
|
||
|
|
<section class="section" style="background: var(--surface);">
|
||
|
|
<div class="container">
|
||
|
|
<div class="section-title">
|
||
|
|
<h2>Coverage across $(get_country_name "$page_country")</h2>
|
||
|
|
<p>Comprehensive national coverage</p>
|
||
|
|
</div>
|
||
|
|
<div class="grid">
|
||
|
|
<div class="card">
|
||
|
|
<h3>Urban Areas</h3>
|
||
|
|
<p>Major cities and metropolitan regions with detailed analysis and high-frequency monitoring.</p>
|
||
|
|
</div>
|
||
|
|
<div class="card">
|
||
|
|
<h3>Rural Infrastructure</h3>
|
||
|
|
<p>Regional roads and smaller crossings with accessibility-focused inspection protocols.</p>
|
||
|
|
</div>
|
||
|
|
<div class="card">
|
||
|
|
<h3>Specialized Assets</h3>
|
||
|
|
<p>Railway bridges, tunnels, and critical infrastructure with specialized assessment protocols.</p>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</section>
|
||
|
|
|
||
|
|
<!-- Related Services -->
|
||
|
|
<section class="section">
|
||
|
|
<div class="container">
|
||
|
|
<div class="section-title">
|
||
|
|
<h2>Related services</h2>
|
||
|
|
<p>Complete infrastructure intelligence solutions</p>
|
||
|
|
</div>
|
||
|
|
<div class="related-grid">
|
||
|
|
$(generate_related "$page_name" "$page_type" "$page_country")
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</section>
|
||
|
|
|
||
|
|
<section class="section" style="background: var(--surface);">
|
||
|
|
<div class="container">
|
||
|
|
<div class="cta">
|
||
|
|
<h2>Start today</h2>
|
||
|
|
<p>Get a custom quote for your inspection programme. No minimum commitment.</p>
|
||
|
|
<a href="/pricing" class="btn">View pricing</a>
|
||
|
|
<a href="mailto:sales@quixzoom.com" class="btn-secondary">Contact sales</a>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</section>
|
||
|
|
|
||
|
|
<footer>
|
||
|
|
<div class="container">
|
||
|
|
<div class="footer-inner">
|
||
|
|
<div class="footer-links">
|
||
|
|
<a href="/">Home</a>
|
||
|
|
<a href="/about">About</a>
|
||
|
|
<a href="/pricing">Pricing</a>
|
||
|
|
<a href="/features">Features</a>
|
||
|
|
<a href="/how-it-works">How It Works</a>
|
||
|
|
</div>
|
||
|
|
<div class="footer-links">
|
||
|
|
<a href="/privacy">Privacy</a>
|
||
|
|
<a href="/terms">Terms</a>
|
||
|
|
<a href="/security">Security</a>
|
||
|
|
</div>
|
||
|
|
<p style="color:var(--text-muted);font-size:0.875rem;">© 2026 quiXzoom. Operated by Landvex AB.</p>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</footer>
|
||
|
|
</body>
|
||
|
|
</html>
|
||
|
|
EOF
|
||
|
|
|
||
|
|
# Upload updated page
|
||
|
|
aws s3 cp "/tmp/${page_name}-new.html" "s3://quixzoom-landing-prod/$page_name.html" --content-type "text/html" --cache-control "max-age=3600"
|
||
|
|
|
||
|
|
echo "✅ Updated $page_name"
|
||
|
|
done
|
||
|
|
|
||
|
|
echo ""
|
||
|
|
echo "All pages updated!"
|
||
|
|
echo "Invalidating CloudFront cache..."
|
||
|
|
aws cloudfront create-invalidation --distribution-id EE30B9WM5ZYM7 --paths "/*" --query 'Invalidation.Id' --output text
|