feat: added lots of work to landing page

This commit is contained in:
Blake Ridgway
2025-11-19 09:03:29 -06:00
parent 57e09ceea9
commit ac1d18f3a3
8 changed files with 1704 additions and 339 deletions

330
templates/about.html Normal file
View File

@@ -0,0 +1,330 @@
{{define "about"}}
<div class="contact-about-page">
<div class="hero-section">
<h1>About RideAware</h1>
<p>Smart cycling training for every level</p>
</div>
<div class="about-content">
<div class="about-text">
<h2>Our Mission</h2>
<p>
RideAware is dedicated to making cycling training accessible,
effective, and enjoyable for cyclists of all levels. We provide
intelligent training plans, real-time analytics, and community support
to help you achieve your cycling goals.
</p>
<p>
Every ride counts. We believe smart training combined with technology
can unlock your full potential as a cyclist.
</p>
<ul>
<li>AI-powered adaptive training plans</li>
<li>Real-time performance analytics</li>
<li>Expert coaching and guidance</li>
<li>Community-driven motivation</li>
<li>Seamless device integration</li>
</ul>
</div>
<div class="about-image">
<div style="
width: 100%;
height: 400px;
background: var(--gradient);
border-radius: 16px;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 4rem;
">
<i class="fas fa-bicycle"></i>
</div>
</div>
</div>
<div class="values-section">
<div class="section-header">
<h2>Our Values</h2>
<p>What drives our mission</p>
</div>
<div class="values-grid">
<div class="value-card">
<div class="value-icon">
<i class="fas fa-heart"></i>
</div>
<h3>Passion</h3>
<p>
We're cyclists ourselves. We understand the dedication it takes
to improve and achieve your goals.
</p>
</div>
<div class="value-card">
<div class="value-icon">
<i class="fas fa-brain"></i>
</div>
<h3>Intelligence</h3>
<p>
Our AI-driven platform learns from your performance to deliver
personalized training that actually works.
</p>
</div>
<div class="value-card">
<div class="value-icon">
<i class="fas fa-users"></i>
</div>
<h3>Community</h3>
<p>
Cycling is better together. Connect with other riders, share
achievements, and push each other forward.
</p>
</div>
<div class="value-card">
<div class="value-icon">
<i class="fas fa-chart-line"></i>
</div>
<h3>Transparency</h3>
<p>
See all your data clearly. We believe in giving you the insights
you need to understand your progress.
</p>
</div>
<div class="value-card">
<div class="value-icon">
<i class="fas fa-lightbulb"></i>
</div>
<h3>Innovation</h3>
<p>
Technology should enhance your cycling, not complicate it.
We're constantly improving to serve you better.
</p>
</div>
<div class="value-card">
<div class="value-icon">
<i class="fas fa-medal"></i>
</div>
<h3>Excellence</h3>
<p>
Whether you're training for a race or personal satisfaction,
we help you reach peak performance.
</p>
</div>
</div>
</div>
<div class="team-section">
<div class="team-container">
<div class="team-header">
<h2>Meet Our Team</h2>
<p>Cyclists and engineers building the future of training</p>
</div>
<div class="team-grid">
<div class="team-member">
<div class="team-member-image">
<i class="fas fa-user-circle"></i>
</div>
<div class="team-member-info">
<h3>Blake Ridgway</h3>
<p>Founder & CEO</p>
<div class="bio">
Building the future of cycling training with scalable infrastructure
and performant systems. Passionate about Infrastructure-as-Code,
cloud networking, and creating observable platforms that ship faster
with confidence.
</div>
</div>
</div>
<div class="team-member">
<div class="team-member-image">
<i class="fas fa-user-circle"></i>
</div>
<div class="team-member-info">
<h3>Cycling Experts</h3>
<p>Training Advisors</p>
<div class="bio">
Professional cyclists and coaches ensuring our training plans
are effective and science-based.
</div>
</div>
</div>
<div class="team-member">
<div class="team-member-image">
<i class="fas fa-user-circle"></i>
</div>
<div class="team-member-info">
<h3>You</h3>
<p>Community</p>
<div class="bio">
Every rider using RideAware is part of our team. Your feedback
shapes our future.
</div>
</div>
</div>
</div>
</div>
</div>
<div class="stats-section">
<div class="section-header">
<h2>By The Numbers</h2>
<p>Growth and impact</p>
</div>
<div class="stats-grid">
<div class="stat-box">
<div class="stat-number">Coming</div>
<div class="stat-label">Q4 2026</div>
</div>
<div class="stat-box">
<div class="stat-number"></div>
<div class="stat-label">Potential</div>
</div>
<div class="stat-box">
<div class="stat-number">100%</div>
<div class="stat-label">Passion</div>
</div>
<div class="stat-box">
<div class="stat-number">You</div>
<div class="stat-label">In Control</div>
</div>
</div>
</div>
<div class="faq-section">
<div class="section-header">
<h2>Frequently Asked Questions</h2>
</div>
<div class="faq-container">
<div class="faq-item">
<div class="faq-question">
<h3>When is RideAware launching?</h3>
<i class="fas fa-chevron-down"></i>
</div>
<div class="faq-answer">
<p>
We're launching Q4 2026! Sign up for our newsletter to get
early access and exclusive launch day bonuses.
</p>
</div>
</div>
<div class="faq-item">
<div class="faq-question">
<h3>How much will it cost?</h3>
<i class="fas fa-chevron-down"></i>
</div>
<div class="faq-answer">
<p>
Pricing details coming soon. We're committed to making RideAware
accessible to cyclists at all price points.
</p>
</div>
</div>
<div class="faq-item">
<div class="faq-question">
<h3>What devices does RideAware support?</h3>
<i class="fas fa-chevron-down"></i>
</div>
<div class="faq-answer">
<p>
RideAware works on iOS, Android, web, and integrates with all
major fitness trackers and cycling computers (Garmin, Wahoo, etc.).
</p>
</div>
</div>
<div class="faq-item">
<div class="faq-question">
<h3>Is my data private?</h3>
<i class="fas fa-chevron-down"></i>
</div>
<div class="faq-answer">
<p>
Yes. Your training data is yours alone. We'll never sell or share
your personal information with third parties.
</p>
</div>
</div>
<div class="faq-item">
<div class="faq-question">
<h3>Can I import my current training data?</h3>
<i class="fas fa-chevron-down"></i>
</div>
<div class="faq-answer">
<p>
Yes! RideAware will integrate with Strava, TrainingPeaks, and other
platforms so you can bring all your history with you.
</p>
</div>
</div>
</div>
</div>
<div class="cta-section" style="
background: var(--gradient);
padding: 4rem 2rem;
text-align: center;
color: white;
border-radius: 16px;
margin: 4rem 2rem;
">
<h2>Ready to Elevate Your Cycling?</h2>
<p style="opacity: 0.9; margin: 1rem 0 2rem;">
Join the waitlist and be first to know when we launch
</p>
<a href="/" class="action-btn primary" style="
background: white;
color: var(--primary);
display: inline-flex;
align-items: center;
gap: 0.5rem;
border-radius: 50px;
padding: 0.8rem 2rem;
text-decoration: none;
font-weight: 600;
">
Join the Waitlist
<i class="fas fa-arrow-right"></i>
</a>
</div>
</div>
<script>
// FAQ accordion toggle
document.querySelectorAll('.faq-question').forEach((question) => {
question.addEventListener('click', () => {
const item = question.parentElement;
const answer = item.querySelector('.faq-answer');
const isOpen = item.classList.contains('open');
// Close all other items
document.querySelectorAll('.faq-item').forEach((faq) => {
faq.classList.remove('open');
});
// Toggle current item
if (!isOpen) {
item.classList.add('open');
}
});
});
</script>
{{end}}

View File

@@ -1,136 +1,145 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, viewport-fit=cover"
/>
<title>{{block "title" .}}RideAware{{end}}</title>
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, viewport-fit=cover"
/>
<title>{{block "title" .}}RideAware{{end}}</title>
<!-- Icons/Fonts -->
<link
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"
rel="stylesheet"
/>
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap"
rel="stylesheet"
/>
<!-- Icons/Fonts -->
<link
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"
rel="stylesheet"
/>
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap"
rel="stylesheet"
/>
<!-- Core CSS -->
<link
rel="stylesheet"
href="/static/css/styles.css"
/>
<!-- Core CSS -->
<link rel="stylesheet" href="/static/css/styles.css" />
<!-- Favicons -->
<link
rel="icon"
type="image/png"
sizes="32x32"
href="/static/assets/32x32.png"
/>
<link
rel="alternate icon"
type="image/png"
sizes="32x32"
href="/static/assets/32x32.png"
/>
<link
rel="apple-touch-icon"
sizes="180x180"
href="/static/assets/apple-touch-icon.png"
/>
<link
rel="manifest"
href="/static/assets/site.webmanifest"
/>
<meta name="theme-color" content="#0f172a" />
<!-- Favicons -->
<link
rel="icon"
type="image/png"
sizes="32x32"
href="/static/assets/32x32.png"
/>
<link
rel="alternate icon"
type="image/png"
sizes="32x32"
href="/static/assets/32x32.png"
/>
<link
rel="apple-touch-icon"
sizes="180x180"
href="/static/assets/apple-touch-icon.png"
/>
<link rel="manifest" href="/static/assets/site.webmanifest" />
<meta name="theme-color" content="#0f172a" />
{{block "extra_head" .}}{{end}}
</head>
<body>
<nav class="navbar">
<div class="nav-container">
<a
href="/"
class="logo"
aria-label="RideAware home"
>
<img
src="/static/assets/logo.png"
alt="RideAware"
class="logo-img"
width="140"
height="28"
decoding="async"
fetchpriority="high"
/>
</a>
{{block "extra_head" .}}{{end}}
</head>
<body>
<nav class="navbar">
<div class="nav-container">
<a href="/" class="logo" aria-label="RideAware home">
<img
src="/static/assets/logo.png"
alt="RideAware"
class="logo-img"
width="140"
height="28"
decoding="async"
fetchpriority="high"
/>
</a>
<button
class="nav-toggle"
id="nav-toggle"
aria-label="Toggle navigation"
aria-controls="primary-nav"
aria-expanded="false"
>
<span class="bar"></span>
<span class="bar"></span>
<span class="bar"></span>
</button>
</div>
</nav>
<ul class="nav-links" id="primary-nav">
<li><a href="/#features">Features</a></li>
<li><a href="/newsletters">Newsletters</a></li>
<li><a href="/about">About</a></li>
<li><a href="/contact">Contact</a></li>
</ul>
{{block "content" .}}{{end}}
<button
class="nav-toggle"
id="nav-toggle"
aria-label="Toggle navigation"
aria-controls="primary-nav"
aria-expanded="false"
>
<span class="bar"></span>
<span class="bar"></span>
<span class="bar"></span>
</button>
</div>
</nav>
<footer class="footer">
<p>&copy; 2025 RideAware. All rights reserved.</p>
</footer>
{{block "content" .}}
{{if .IsContact}}
{{template "contact" .}}
{{else if .IsAbout}}
{{template "about" .}}
{{else if .IsHome}}
{{template "index" .}}
{{else}}
{{template "newsletters" .}}
{{end}}
{{end}}
<!-- Core JS -->
<script
defer
src="https://cdn.statically.io/gl/rideaware/landing/06d19988c7df53636277f945f9ed853bda76471b/static/js/main.min.js"
crossorigin="anonymous"
></script>
<footer class="footer">
<p>&copy; 2025 RideAware. All rights reserved.</p>
</footer>
{{block "extra_scripts" .}}
<script>
(function () {
const btn = document.getElementById("nav-toggle");
const menu = document.getElementById("primary-nav");
if (!btn || !menu) return;
<!-- Core JS -->
<script
defer
src="https://cdn.statically.io/gl/rideaware/landing/06d19988c7df53636277f945f9ed853bda76471b/static/js/main.min.js"
crossorigin="anonymous"
></script>
function closeMenu() {
btn.classList.remove("active");
btn.setAttribute("aria-expanded", "false");
menu.classList.remove("open");
{{block "extra_scripts" .}}
<script>
(function () {
const btn = document.getElementById("nav-toggle");
const menu = document.getElementById("primary-nav");
if (!btn || !menu) return;
function closeMenu() {
btn.classList.remove("active");
btn.setAttribute("aria-expanded", "false");
menu.classList.remove("open");
}
btn.addEventListener("click", () => {
const open = btn.classList.toggle("active");
btn.setAttribute("aria-expanded", String(open));
menu.classList.toggle("open", open);
});
menu.addEventListener("click", (e) => {
if (e.target.tagName === "A") closeMenu();
});
document.addEventListener("keydown", (e) => {
if (e.key === "Escape") closeMenu();
});
document.addEventListener("click", (e) => {
if (!menu.contains(e.target) && !btn.contains(e.target)) {
closeMenu();
}
btn.addEventListener("click", () => {
const open = btn.classList.toggle("active");
btn.setAttribute("aria-expanded", String(open));
menu.classList.toggle("open", open);
});
menu.addEventListener("click", (e) => {
if (e.target.tagName === "A") closeMenu();
});
document.addEventListener("keydown", (e) => {
if (e.key === "Escape") closeMenu();
});
document.addEventListener("click", (e) => {
if (!menu.contains(e.target) && !btn.contains(e.target)) {
closeMenu();
}
});
})();
</script>
{{end}}
</body>
});
})();
</script>
{{end}}
</body>
</html>

171
templates/contact.html Normal file
View File

@@ -0,0 +1,171 @@
{{define "contact"}}
<div class="contact-about-page">
<div class="hero-section">
<h1>Get in Touch</h1>
<p>We'd love to hear from you. Send us a message!</p>
</div>
<div class="about-content">
<div class="about-text">
<h2>Let's Connect</h2>
<p>
Have a question about RideAware? Want to collaborate?
Reach out and let us know how we can help.
</p>
<ul>
<li>Fast response times</li>
<li>Friendly support team</li>
<li>Multiple contact options</li>
<li>Always here to help</li>
</ul>
</div>
<form class="contact-form" id="contactForm">
<div class="form-success" id="successMessage">
<strong>Thank you!</strong> We've received your message
and will get back to you soon.
</div>
<h2>Send us a message</h2>
<div class="form-group">
<label for="name">
Full Name <span class="required">*</span>
</label>
<input
type="text"
id="name"
name="name"
required
autocomplete="name"
/>
</div>
<div class="form-group">
<label for="email">
Email Address <span class="required">*</span>
</label>
<input
type="email"
id="email"
name="email"
required
autocomplete="email"
/>
<small>We'll respond to this email address</small>
</div>
<div class="form-group">
<label for="subject">Subject <span class="required">*</span></label>
<select id="subject" name="subject" required>
<option value="">-- Select a subject --</option>
<option value="general">General Inquiry</option>
<option value="support">Support</option>
<option value="partnership">Partnership</option>
<option value="feedback">Feedback</option>
<option value="other">Other</option>
</select>
</div>
<div class="form-group">
<label for="message">
Message <span class="required">*</span>
</label>
<textarea
id="message"
name="message"
required
placeholder="Your message here..."
></textarea>
</div>
<div class="newsletter-opt-in">
<label for="subscribe" class="checkbox-label">
<input
type="checkbox"
id="subscribe"
name="subscribe"
class="checkbox-input"
/>
<span class="checkbox-text">
<i class="fas fa-bell"></i>
Subscribe to our newsletter for training tips and updates
</span>
</label>
</div>
<button type="submit" class="form-submit">
<i class="fas fa-paper-plane"></i>
Send Message
</button>
</form>
</div>
<div class="contact-info">
<div class="info-card">
<div class="info-card-icon">
<i class="fas fa-envelope"></i>
</div>
<h3>Email</h3>
<p>
<a href="mailto:hello@rideaware.com"
>hello@rideaware.com</a
>
</p>
</div>
<div class="info-card">
<div class="info-card-icon">
<i class="fas fa-map-marker-alt"></i>
</div>
<h3>Address</h3>
<p>1909 W Owen K Garriott Rd<br />Enid, OK 73703</p>
</div>
</div>
</div>
<script>
document.getElementById('contactForm').addEventListener(
'submit',
async (e) => {
e.preventDefault();
const form = e.target;
const formData = new FormData(form);
console.log('Form submitted');
console.log('Form data:', Object.fromEntries(formData));
try {
const response = await fetch('/contact', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams(formData),
});
console.log('Response status:', response.status);
const data = await response.json();
console.log('Response data:', data);
if (response.ok) {
document.getElementById('successMessage')
.classList.add('show');
form.reset();
setTimeout(() => {
document.getElementById('successMessage')
.classList.remove('show');
}, 5000);
} else {
alert('Error: ' + (data.error || 'Failed to send message'));
}
} catch (error) {
console.error('Error:', error);
alert('Failed to send message: ' + error.message);
}
}
);
</script>
{{end}}