chore(ui): Formatted and cleaned up the code

This commit is contained in:
Cipher Vance 2025-08-31 13:25:12 -05:00
parent ffdc4cde38
commit 46093d2b56
5 changed files with 638 additions and 611 deletions

View file

@ -1,72 +1,94 @@
{% set is_home = is_home | default(false) %}
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta <meta
name="viewport" name="viewport"
content="width=device-width, initial-scale=1, viewport-fit=cover" content="width=device-width, initial-scale=1, viewport-fit=cover"
/> />
<title>{% block title %}RideAware{% endblock %}</title> <title>{% block title %}RideAware{% endblock %}</title>
<link <!-- Icons/Fonts -->
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" <link
rel="stylesheet" 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"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link <link
rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap"
href="{{ url_for('static', filename='css/styles.css') }}" rel="stylesheet"
/> />
<link <!-- Core CSS -->
rel="alternate icon" <link
type="image/png" rel="stylesheet"
sizes="32x32" href="{{ url_for('static', filename='css/styles.css') }}"
href="{{ url_for('static', filename='assets/32x32.png') }}" />
/>
<link
rel="apple-touch-icon"
sizes="180x180"
href="{{ url_for('static', filename='assets/apple-touch-icon.png') }}"
/>
<link
rel="manifest"
href="{{ url_for('static', filename='assets/site.webmanifest') }}"
/>
<meta
name="theme-color"
content="#0f172a"
/>
{% block extra_head %}{% endblock %} <!-- Favicons -->
</head> <link
<body> rel="icon"
<nav class="navbar"> type="image/png"
<div class="nav-container"> sizes="32x32"
<a href="/" class="logo">Ride<span class="logo-accent">Aware</span></a> href="{{ url_for('static', filename='assets/32x32.png') }}"
<ul class="nav-links"> />
{% if is_home %} <link
<li><a href="#features">Features</a></li> rel="alternate icon"
{% endif %} type="image/png"
<li><a href="/newsletters">Newsletters</a></li> sizes="32x32"
</ul> href="{{ url_for('static', filename='assets/32x32.png') }}"
</div> />
</nav> <link
rel="apple-touch-icon"
sizes="180x180"
href="{{ url_for('static', filename='assets/apple-touch-icon.png') }}"
/>
<link
rel="manifest"
href="{{ url_for('static', filename='assets/site.webmanifest') }}"
/>
<meta name="theme-color" content="#0f172a" />
{% block content %}{% endblock %} {% block extra_head %}{% endblock %}
</head>
<body>
{% set is_home = is_home | default(false) %}
<footer class="footer"> <nav class="navbar">
<p>&copy; 2025 RideAware. All rights reserved.</p> <div class="nav-container">
</footer> <a href="{{ url_for('index') }}" class="logo" aria-label="RideAware home">
<img
src="{{ url_for('static', filename='assets/logo.png') }}"
alt="RideAware"
class="logo-img"
width="140"
height="28"
decoding="async"
fetchpriority="high"
/>
</a>
<ul class="nav-links">
{% if is_home %}
<li><a href="#features">Features</a></li>
{% endif %}
<li><a href="{{ url_for('newsletters') }}">Newsletters</a></li>
</ul>
</div>
</nav>
<script {% block content %}{% endblock %}
defer
src="https://cdn.statically.io/gl/rideaware/landing/06d19988c7df53636277f945f9ed853bda76471b/static/js/main.min.js"
crossorigin="anonymous"
></script>
{% block extra_scripts %}{% endblock %} <footer class="footer">
</body> <p>&copy; 2025 RideAware. All rights reserved.</p>
</footer>
<!-- Core JS -->
<script
defer
src="https://cdn.statically.io/gl/rideaware/landing/06d19988c7df53636277f945f9ed853bda76471b/static/js/main.min.js"
crossorigin="anonymous"
></script>
{% block extra_scripts %}{% endblock %}
</body>
</html> </html>

View file

@ -1,392 +1,367 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Welcome to RideAware!</title> <meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<!--[if mso]> <!--[if mso]>
<noscript> <noscript>
<xml> <xml>
<o:OfficeDocumentSettings> <o:OfficeDocumentSettings>
<o:PixelsPerInch>96</o:PixelsPerInch> <o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings> <o:AllowPNG/>
</o:OfficeDocumentSettings>
</xml> </xml>
</noscript> </noscript>
<![endif]--> <![endif]-->
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Welcome to RideAware!</title>
<style> <style>
/* Reset and base styles */ /* Basic resets (email-safe) */
* { html,
margin: 0; body {
padding: 0; margin: 0 !important;
box-sizing: border-box; padding: 0 !important;
} height: 100% !important;
width: 100% !important;
body { }
margin: 0; * {
padding: 0; -ms-text-size-adjust: 100%;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; -webkit-text-size-adjust: 100%;
line-height: 1.6; }
color: #1a1a1a; table,
background-color: #f8fafc; td {
-webkit-text-size-adjust: 100%; mso-table-lspace: 0pt !important;
-ms-text-size-adjust: 100%; mso-table-rspace: 0pt !important;
} }
img {
table { -ms-interpolation-mode: bicubic;
border-collapse: collapse; border: 0;
mso-table-lspace: 0pt; outline: none;
mso-table-rspace: 0pt; text-decoration: none;
} display: block;
height: auto;
img { max-width: 100%;
border: 0; }
max-width: 100%; /* Wrapper/background */
height: auto; .bg {
line-height: 100%; background-color: #f8fafc;
outline: none; }
text-decoration: none; /* Container */
} .container {
width: 100%;
/* Email container */ max-width: 600px;
.email-wrapper { margin: 0 auto;
max-width: 600px; background-color: #ffffff;
margin: 0 auto; }
background-color: #ffffff; /* Header */
} .header {
background: #1e4e9c;
/* Header styles */ background-image: linear-gradient(135deg, #1e4e9c 0%, #337cf2 100%);
padding: 40px 24px;
text-align: center;
color: #ffffff;
}
.logo-text {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
Helvetica, Arial, sans-serif;
font-weight: 800;
font-size: 24px;
line-height: 1.2;
color: #ffffff;
margin: 0 0 8px 0;
}
.logo-accent {
color: #00d4ff;
}
.header-title {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
Helvetica, Arial, sans-serif;
font-size: 26px;
font-weight: 800;
margin: 6px 0 6px 0;
color: #ffffff;
}
.subtitle {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
Helvetica, Arial, sans-serif;
font-size: 15px;
color: rgba(255, 255, 255, 0.92);
margin: 0;
}
/* Content */
.content {
padding: 32px 24px;
text-align: center;
}
.main-message {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
Helvetica, Arial, sans-serif;
font-size: 18px;
color: #1a1a1a;
font-weight: 600;
margin: 0 0 16px 0;
}
.description {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
Helvetica, Arial, sans-serif;
font-size: 15px;
color: #6b7280;
line-height: 1.6;
margin: 0 0 24px 0;
}
/* Feature block */
.features-wrap {
padding: 0 24px 24px 24px;
}
.features {
border: 1px solid rgba(30, 78, 156, 0.12);
border-radius: 12px;
background-color: #ffffff;
padding: 20px;
}
.features-title {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
Helvetica, Arial, sans-serif;
color: #1e4e9c;
font-size: 18px;
font-weight: 700;
margin: 0 0 12px 0;
text-align: center;
}
.feature-item {
width: 100%;
text-align: left;
padding: 10px 12px;
border-radius: 10px;
background: #ffffff;
border: 1px solid rgba(2, 6, 23, 0.05);
margin-bottom: 10px;
}
.feature-title {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
Helvetica, Arial, sans-serif;
font-size: 14px;
font-weight: 600;
color: #1a1a1a;
margin: 0 0 4px 0;
}
.feature-desc {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
Helvetica, Arial, sans-serif;
font-size: 13px;
color: #6b7280;
margin: 0;
}
/* CTA */
.cta {
padding: 8px 24px 32px 24px;
text-align: center;
}
.cta-btn {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
Helvetica, Arial, sans-serif;
display: inline-block;
background: #1e4e9c;
background-image: linear-gradient(135deg, #1e4e9c 0%, #337cf2 100%);
color: #ffffff !important;
text-decoration: none;
padding: 14px 28px;
border-radius: 999px;
font-weight: 700;
font-size: 16px;
}
/* Social */
.social {
background-color: #f8fafc;
padding: 20px 24px;
text-align: center;
border-radius: 12px;
margin: 0 24px 24px 24px;
}
.social-title {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
Helvetica, Arial, sans-serif;
font-size: 15px;
font-weight: 700;
margin: 0 0 10px 0;
color: #1a1a1a;
}
.social-link {
display: inline-block;
width: 40px;
height: 40px;
text-decoration: none;
color: #ffffff !important;
border-radius: 50%;
line-height: 40px;
text-align: center;
margin: 0 6px;
background-image: linear-gradient(135deg, #1e4e9c 0%, #337cf2 100%);
}
/* Footer */
.footer {
background: #1a1a1a;
color: #ffffff;
text-align: center;
padding: 24px;
}
.footer p {
margin: 6px 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
Helvetica, Arial, sans-serif;
font-size: 13px;
}
.unsubscribe {
border-top: 1px solid rgba(255, 255, 255, 0.12);
margin-top: 14px;
padding-top: 14px;
}
.unsubscribe a {
color: #9ca3af !important;
text-decoration: none;
font-size: 13px;
}
.unsubscribe a:hover {
color: #00d4ff !important;
text-decoration: underline;
}
/* Mobile */
@media only screen and (max-width: 600px) {
.header { .header {
background: linear-gradient(135deg, #1e4e9c 0%, #337cf2 100%); padding: 32px 18px !important;
background-color: #1e4e9c; /* Fallback */
padding: 50px 30px;
text-align: center;
color: white;
} }
.welcome-icon {
font-size: 3rem;
margin-bottom: 20px;
display: block;
}
.logo {
font-size: 24px;
font-weight: 700;
color: white;
margin-bottom: 15px;
display: block;
}
.logo-accent {
color: #00d4ff;
}
.header h1 {
color: white;
font-size: 28px;
font-weight: 800;
margin: 0 0 10px;
}
.subtitle {
color: rgba(255, 255, 255, 0.9);
font-size: 16px;
font-weight: 300;
margin: 0;
}
/* Content styles */
.content { .content {
padding: 40px 30px; padding: 24px 18px !important;
text-align: center;
} }
.main-message {
font-size: 18px;
color: #1a1a1a;
margin-bottom: 25px;
font-weight: 500;
}
.description {
font-size: 16px;
color: #6b7280;
margin-bottom: 35px;
line-height: 1.7;
}
/* Feature highlights */
.features { .features {
background: linear-gradient(135deg, rgba(30, 78, 156, 0.05) 0%, rgba(0, 212, 255, 0.05) 100%); padding: 16px !important;
background-color: #f8fafc; /* Fallback */
border-radius: 12px;
padding: 30px 25px;
margin: 30px 0;
border: 1px solid rgba(30, 78, 156, 0.1);
}
.features h3 {
color: #1e4e9c;
font-size: 20px;
font-weight: 700;
margin-bottom: 20px;
}
.feature-grid {
width: 100%;
}
.feature-item {
text-align: center;
padding: 15px;
background: white;
border-radius: 10px;
margin-bottom: 15px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}
.feature-icon {
font-size: 2rem;
margin-bottom: 8px;
display: block;
}
.feature-title {
font-size: 14px;
font-weight: 600;
color: #1a1a1a;
margin-bottom: 5px;
}
.feature-desc {
font-size: 12px;
color: #6b7280;
line-height: 1.4;
}
/* CTA styles */
.cta-section {
margin: 35px 0;
padding: 25px;
}
.cta-button {
display: inline-block;
background: linear-gradient(135deg, #1e4e9c 0%, #337cf2 100%);
background-color: #1e4e9c; /* Fallback */
color: white !important;
text-decoration: none;
padding: 15px 35px;
border-radius: 25px;
font-weight: 600;
font-size: 16px;
box-shadow: 0 5px 15px rgba(30, 78, 156, 0.3);
}
.cta-button:hover {
background-color: #337cf2;
text-decoration: none;
}
/* Social section */
.social-section {
margin: 30px 0;
padding: 25px;
background: #f8fafc;
border-radius: 12px;
}
.social-section h4 {
color: #1a1a1a;
font-size: 16px;
font-weight: 600;
margin-bottom: 15px;
}
.social-links {
text-align: center;
}
.social-link {
display: inline-block;
width: 40px;
height: 40px;
background: linear-gradient(135deg, #1e4e9c 0%, #337cf2 100%);
background-color: #1e4e9c; /* Fallback */
color: white;
text-decoration: none;
border-radius: 50%;
line-height: 40px;
font-size: 16px;
margin: 0 7px;
text-align: center;
}
.social-link:hover {
background-color: #337cf2;
}
/* Footer styles */
.footer {
background: #1a1a1a;
color: white;
padding: 30px;
text-align: center;
}
.footer-content {
margin-bottom: 20px;
}
.footer-content p {
margin: 5px 0;
font-size: 14px;
}
.unsubscribe {
margin-top: 20px;
padding-top: 20px;
border-top: 1px solid rgba(255, 255, 255, 0.1);
}
.unsubscribe a {
color: #9ca3af;
text-decoration: none;
font-size: 13px;
}
.unsubscribe a:hover {
color: #00d4ff;
text-decoration: underline;
}
/* Mobile responsive */
@media only screen and (max-width: 600px) {
.email-wrapper {
width: 100% !important;
}
.header {
padding: 40px 20px !important;
}
.header h1 {
font-size: 24px !important;
}
.content {
padding: 30px 20px !important;
}
.features {
padding: 25px 20px !important;
}
.feature-item {
margin-bottom: 10px !important;
}
.social-link {
margin: 0 5px !important;
}
} }
}
</style> </style>
</head> </head>
<body> <body class="bg">
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" style="background-color: #f8fafc;"> <center role="article" aria-roledescription="email">
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr> <tr>
<td align="center"> <td align="center">
<div class="email-wrapper"> <table role="presentation" class="container" width="600" cellspacing="0" cellpadding="0" border="0">
<!-- Header --> <!-- Header -->
<div class="header"> <tr>
<div class="welcome-icon">🎉</div> <td class="header">
<div class="logo">Ride<span class="logo-accent">Aware</span></div> <!-- Optional image logo: replace src if you prefer image instead of text -->
<h1>Welcome Aboard!</h1> <!--
<p class="subtitle">You're now part of the RideAware community</p> <img src="https://your-cdn/rideaware-logo.png" alt="RideAware" width="140" height="28" />
</div> -->
<div class="logo-text">Ride<span class="logo-accent">Aware</span></div>
<div style="font-size: 36px; line-height: 1; margin-bottom: 10px;" aria-hidden="true">🎉</div>
<div class="header-title">Welcome Aboard!</div>
<div class="subtitle">You're now part of the RideAware community</div>
</td>
</tr>
<!-- Content --> <!-- Body -->
<div class="content"> <tr>
<p class="main-message">Thanks for subscribing to RideAware newsletter!</p> <td class="content">
<p class="main-message">Thanks for subscribing to the RideAware newsletter!</p>
<p class="description">
Were thrilled to have you with us. Expect training tips, performance insights,
product news, and community highlights—delivered straight to your inbox.
</p>
</td>
</tr>
<p class="description"> <!-- Features -->
We're absolutely thrilled to have you join our community of passionate cyclists. Get ready for exclusive insights, training tips, feature updates, and much more delivered straight to your inbox. <tr>
</p> <td class="features-wrap">
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" class="features">
<tr>
<td align="center" style="padding-bottom: 10px;">
<div class="features-title">What to expect from us</div>
</td>
</tr>
<tr>
<td>
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr>
<td class="feature-item">
<div class="feature-title">Training Tips</div>
<div class="feature-desc">Actionable advice to improve your performance.</div>
</td>
</tr>
<tr>
<td class="feature-item">
<div class="feature-title">Performance Insights</div>
<div class="feature-desc">Data-driven analysis for smarter rides.</div>
</td>
</tr>
<tr>
<td class="feature-item">
<div class="feature-title">Feature Updates</div>
<div class="feature-desc">Be first to know about new releases.</div>
</td>
</tr>
<tr>
<td class="feature-item" style="margin-bottom: 0;">
<div class="feature-title">Community Stories</div>
<div class="feature-desc">Inspiring journeys from fellow cyclists.</div>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<!-- Features --> <!-- CTA -->
<div class="features"> <tr>
<h3>What to expect from us:</h3> <td class="cta" align="center">
<div class="feature-grid"> <p style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; color:#1a1a1a; font-size:15px; margin: 0 0 12px 0;">
<div class="feature-item"> Ready to start your journey with RideAware?
<span class="feature-icon">🚴‍♂️</span> </p>
<div class="feature-title">Training Tips</div> <a href="https://rideaware.org" target="_blank" class="cta-btn">Explore RideAware →</a>
<div class="feature-desc">Expert advice to improve your performance</div> </td>
</div> </tr>
<div class="feature-item">
<span class="feature-icon">📊</span>
<div class="feature-title">Performance Insights</div>
<div class="feature-desc">Data-driven analysis for better rides</div>
</div>
<div class="feature-item">
<span class="feature-icon">🆕</span>
<div class="feature-title">Feature Updates</div>
<div class="feature-desc">Be first to know about new releases</div>
</div>
<div class="feature-item">
<span class="feature-icon">👥</span>
<div class="feature-title">Community Stories</div>
<div class="feature-desc">Inspiring journeys from fellow cyclists</div>
</div>
</div>
</div>
<!-- CTA --> <!-- Social -->
<div class="cta-section"> <tr>
<p style="margin-bottom: 20px;">Ready to start your journey with RideAware?</p> <td>
<a href="https://rideaware.com" target="_blank" class="cta-button"> <div class="social">
Explore RideAware → <div class="social-title">Stay Connected</div>
</a> <a href="https://twitter.com" class="social-link" title="Twitter" aria-label="Twitter">T</a>
</div> <a href="https://facebook.com" class="social-link" title="Facebook" aria-label="Facebook">f</a>
<a href="https://instagram.com" class="social-link" title="Instagram" aria-label="Instagram">IG</a>
</div>
</td>
</tr>
<!-- Social section --> <!-- Footer -->
<div class="social-section"> <tr>
<h4>Stay Connected</h4> <td class="footer">
<div class="social-links"> <p><strong>RideAware Team</strong></p>
<a href="#" class="social-link" title="Follow us on Twitter">🐦</a> <p>Empowering cyclists, one ride at a time</p>
<a href="#" class="social-link" title="Like us on Facebook">📘</a> <div class="unsubscribe">
<a href="#" class="social-link" title="Follow us on Instagram">📷</a> <p style="margin: 0;">
</div> <a href="{{ unsubscribe_link }}">Unsubscribe</a>
</div> &nbsp;|&nbsp;
<a href="mailto:support@rideaware.com">Contact Support</a>
<p style="color: #6b7280; font-size: 14px; margin-top: 30px;"> </p>
We're excited to share our journey with you and help you achieve your cycling goals. Welcome to the RideAware family! 🚴‍♀️ <p style="font-size: 12px; color: #9ca3af;">
</p> © 2025 RideAware. All rights reserved.
</div> </p>
<p style="font-size: 11px; color: #9ca3af;">
<!-- Footer --> You received this email because you subscribed to RideAware updates.
<div class="footer"> </p>
<div class="footer-content"> </div>
<p><strong>RideAware Team</strong></p> </td>
<p>Empowering cyclists, one ride at a time</p> </tr>
</div> </table>
</td>
<div class="unsubscribe">
<p>
<a href="{{ unsubscribe_link }}">Unsubscribe</a> |
<a href="mailto:support@rideaware.com">Contact Support</a>
</p>
<p style="font-size: 12px; color: #6b7280; margin-top: 10px;">
© 2025 RideAware. All rights reserved.
</p>
<p style="font-size: 11px; color: #9ca3af; margin-top: 8px;">
This email was sent to you because you subscribed to RideAware updates.
</p>
</div>
</div>
</div>
</td>
</tr> </tr>
</table> </table>
</body> </center>
</body>
</html> </html>

View file

@ -1,4 +1,3 @@
<!-- templates/index.html -->
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}RideAware - Smart Cycling Training Platform{% endblock %} {% block title %}RideAware - Smart Cycling Training Platform{% endblock %}
@ -10,8 +9,8 @@
<div class="hero-content"> <div class="hero-content">
<h1>Elevate Your Cycling Journey</h1> <h1>Elevate Your Cycling Journey</h1>
<p class="subtitle"> <p class="subtitle">
The ultimate smart training platform for cyclists who demand excellence The ultimate smart training platform for cyclists who demand
in every ride. excellence in every ride.
</p> </p>
<div class="cta-section"> <div class="cta-section">
@ -35,7 +34,18 @@
<div class="phone-mockup"> <div class="phone-mockup">
<div class="screen"> <div class="screen">
<div class="app-interface"> <div class="app-interface">
<div class="app-logo">RideAware</div> <div class="app-brand">
<img
src="{{ url_for('static', filename='assets/32x32.png') }}"
alt="RideAware icon"
class="app-brand-icon"
width="32"
height="32"
decoding="async"
/>
<div class="app-logo">RideAware</div>
</div>
<div class="stats-grid"> <div class="stats-grid">
<div class="stat-card"> <div class="stat-card">
<div class="stat-number">24.5</div> <div class="stat-number">24.5</div>
@ -62,143 +72,145 @@
</section> </section>
<!-- Features Section --> <!-- Features Section -->
<section class="features" id="features"> {% if is_home %}
<div class="section-header"> <section class="features" id="features">
<h2>Powerful Features for Every Cyclist</h2> <div class="section-header">
<p> <h2>Powerful Features for Every Cyclist</h2>
From beginners to professionals, RideAware provides comprehensive tools <p>
to optimize your training and performance. From beginners to professionals, RideAware provides comprehensive
</p> tools to optimize your training and performance.
</div> </p>
</div>
<div class="features-container"> <div class="features-container">
<div class="features-grid"> <div class="features-grid">
<div class="feature-card"> <div class="feature-card">
<div class="feature-icon"> <div class="feature-icon">
<i class="fas fa-calendar-alt"></i> <i class="fas fa-calendar-alt"></i>
</div>
<h3>Smart Training Plans</h3>
<ul class="feature-list">
<li>
<strong>AI-Powered Planning:</strong> Customized training plans
based on your goals and fitness level
</li>
<li>
<strong>Adaptive Scheduling:</strong> Smart workout scheduling
with automated reminders
</li>
<li>
<strong>Goal Tracking:</strong> Set and monitor your cycling
objectives in real-time
</li>
</ul>
</div> </div>
<h3>Smart Training Plans</h3>
<ul class="feature-list">
<li>
<strong>AI-Powered Planning:</strong> Customized training plans
based on your goals and fitness level
</li>
<li>
<strong>Adaptive Scheduling:</strong> Smart workout scheduling
with automated reminders
</li>
<li>
<strong>Goal Tracking:</strong> Set and monitor your cycling
objectives in real-time
</li>
</ul>
</div>
<div class="feature-card"> <div class="feature-card">
<div class="feature-icon"> <div class="feature-icon">
<i class="fas fa-chart-line"></i> <i class="fas fa-chart-line"></i>
</div>
<h3>Advanced Analytics</h3>
<ul class="feature-list">
<li>
<strong>Detailed Logging:</strong> Track exercises, sets, reps,
and performance metrics
</li>
<li>
<strong>Data Visualization:</strong> Interactive charts, graphs,
and progress statistics
</li>
<li>
<strong>Progress Insights:</strong> Monitor your improvement
over time with AI analysis
</li>
</ul>
</div> </div>
<h3>Advanced Analytics</h3>
<ul class="feature-list">
<li>
<strong>Detailed Logging:</strong> Track exercises, sets, reps,
and performance metrics
</li>
<li>
<strong>Data Visualization:</strong> Interactive charts, graphs,
and progress statistics
</li>
<li>
<strong>Progress Insights:</strong> Monitor your improvement over
time with AI analysis
</li>
</ul>
</div>
<div class="feature-card"> <div class="feature-card">
<div class="feature-icon"> <div class="feature-icon">
<i class="fas fa-bicycle"></i> <i class="fas fa-bicycle"></i>
</div>
<h3>Virtual Training</h3>
<ul class="feature-list">
<li>
<strong>Expert Coaching:</strong> Professional guidance to
achieve your cycling goals
</li>
<li>
<strong>Immersive Rides:</strong> Virtual training experiences
to boost performance
</li>
<li>
<strong>Structured Workouts:</strong> Designed programs for
fitness and performance gains
</li>
</ul>
</div> </div>
<h3>Virtual Training</h3>
<ul class="feature-list">
<li>
<strong>Expert Coaching:</strong> Professional guidance to achieve
your cycling goals
</li>
<li>
<strong>Immersive Rides:</strong> Virtual training experiences to
boost performance
</li>
<li>
<strong>Structured Workouts:</strong> Designed programs for
fitness and performance gains
</li>
</ul>
</div>
<div class="feature-card"> <div class="feature-card">
<div class="feature-icon"> <div class="feature-icon">
<i class="fas fa-heart"></i> <i class="fas fa-heart"></i>
</div>
<h3>Health & Recovery</h3>
<ul class="feature-list">
<li>
<strong>Nutrition Tracking:</strong> Plan and monitor your
dietary intake for optimal performance
</li>
<li>
<strong>Recovery Optimization:</strong> Tools and resources for
effective rest and recovery
</li>
<li>
<strong>Injury Prevention:</strong> Proactive measures to
prevent and manage injuries
</li>
</ul>
</div> </div>
<h3>Health & Recovery</h3>
<ul class="feature-list">
<li>
<strong>Nutrition Tracking:</strong> Plan and monitor your dietary
intake for optimal performance
</li>
<li>
<strong>Recovery Optimization:</strong> Tools and resources for
effective rest and recovery
</li>
<li>
<strong>Injury Prevention:</strong> Proactive measures to prevent
and manage injuries
</li>
</ul>
</div>
<div class="feature-card"> <div class="feature-card">
<div class="feature-icon"> <div class="feature-icon">
<i class="fas fa-users"></i> <i class="fas fa-users"></i>
</div>
<h3>Community & Social</h3>
<ul class="feature-list">
<li>
<strong>Social Sharing:</strong> Share achievements and progress
on social platforms
</li>
<li>
<strong>Active Community:</strong> Connect with fellow cyclists
and share experiences
</li>
<li>
<strong>Competitive Leaderboards:</strong> Challenge yourself
against the community
</li>
</ul>
</div> </div>
<h3>Community & Social</h3>
<ul class="feature-list">
<li>
<strong>Social Sharing:</strong> Share achievements and progress
on social platforms
</li>
<li>
<strong>Active Community:</strong> Connect with fellow cyclists
and share experiences
</li>
<li>
<strong>Competitive Leaderboards:</strong> Challenge yourself
against the community
</li>
</ul>
</div>
<div class="feature-card"> <div class="feature-card">
<div class="feature-icon"> <div class="feature-icon">
<i class="fas fa-sync-alt"></i> <i class="fas fa-sync-alt"></i>
</div>
<h3>Smart Integration</h3>
<ul class="feature-list">
<li>
<strong>Wearable Sync:</strong> Connect with fitness trackers
and smart devices
</li>
<li>
<strong>Music Integration:</strong> Seamlessly sync with your
favorite music services
</li>
<li>
<strong>Data Portability:</strong> Easy import/export to other
cycling platforms
</li>
</ul>
</div> </div>
<h3>Smart Integration</h3>
<ul class="feature-list">
<li>
<strong>Wearable Sync:</strong> Connect with fitness trackers and
smart devices
</li>
<li>
<strong>Music Integration:</strong> Seamlessly sync with your
favorite music services
</li>
<li>
<strong>Data Portability:</strong> Easy import/export to other
cycling platforms
</li>
</ul>
</div> </div>
</div> </div>
</div> </section>
</section> {% endif %}
{% endblock %} {% endblock %}

View file

@ -7,36 +7,41 @@
{% block content %} {% block content %}
<div class="article-wrap"> <div class="article-wrap">
<aside class="article-aside"> <aside class="article-aside">
<a href="/newsletters" class="back-link"> <a href="{{ url_for('newsletters') }}" class="back-link">
<i class="fas fa-arrow-left"></i> <i class="fas fa-arrow-left"></i>
Back to Newsletters Back to Newsletters
</a> </a>
<div class="article-meta"> <div class="article-meta">
<h2 class="article-title">{{ newsletter.subject if newsletter else 'Newsletter Title' }}</h2> <h2 class="article-title">
{{ newsletter.subject if newsletter else 'Newsletter Title' }}
</h2>
<div class="meta-row"> <div class="meta-row">
<i class="fas fa-calendar-alt"></i> <i class="fas fa-calendar-alt"></i>
<span>{{ newsletter.sent_at if newsletter else 'Published Date' }}</span> <span>{{ newsletter.sent_at if newsletter else 'Published Date' }}</span>
</div> </div>
{% if newsletter and newsletter.get('reading_time') %} {% if newsletter and newsletter.get('reading_time') %}
<div class="meta-row"> <div class="meta-row">
<i class="fas fa-clock"></i> <i class="fas fa-clock"></i>
<span>{{ newsletter.reading_time }} min read</span> <span>{{ newsletter.reading_time }} min read</span>
</div> </div>
{% endif %} {% endif %}
{% if newsletter and newsletter.get('author') %} {% if newsletter and newsletter.get('author') %}
<div class="meta-row"> <div class="meta-row">
<i class="fas fa-user"></i> <i class="fas fa-user"></i>
<span>{{ newsletter.author }}</span> <span>{{ newsletter.author }}</span>
</div> </div>
{% endif %} {% endif %}
{% if newsletter and newsletter.get('tags') %} {% if newsletter and newsletter.get('tags') %}
<div class="article-tags"> <div class="article-tags">
{% for tag in newsletter.tags %} {% for tag in newsletter.tags %}
<span class="tag">{{ tag }}</span> <span class="tag">{{ tag }}</span>
{% endfor %} {% endfor %}
</div> </div>
{% endif %} {% endif %}
</div> </div>
@ -48,7 +53,9 @@
<main class="article-main"> <main class="article-main">
<header class="article-hero"> <header class="article-hero">
<div class="newsletter-icon"><i class="fas fa-envelope-open-text"></i></div> <div class="newsletter-icon">
<i class="fas fa-envelope-open-text"></i>
</div>
<h1>{{ newsletter.subject if newsletter else 'Newsletter Title' }}</h1> <h1>{{ newsletter.subject if newsletter else 'Newsletter Title' }}</h1>
</header> </header>
@ -62,7 +69,7 @@
</article> </article>
<div class="newsletter-actions"> <div class="newsletter-actions">
<a href="/newsletters" class="action-btn primary"> <a href="{{ url_for('newsletters') }}" class="action-btn primary">
<i class="fas fa-list"></i> <i class="fas fa-list"></i>
View All Newsletters View All Newsletters
</a> </a>
@ -80,35 +87,41 @@
{% endblock %} {% endblock %}
{% block extra_scripts %} {% block extra_scripts %}
<script> <script>
function shareNewsletter() { function shareNewsletter() {
if (navigator.share) { if (navigator.share) {
navigator.share({ title: document.title, url: location.href }).catch(() => {}); navigator
} else { .share({ title: document.title, url: location.href })
navigator.clipboard.writeText(location.href); .catch(() => {});
alert('Link copied to clipboard!'); } else {
navigator.clipboard.writeText(location.href);
alert('Link copied to clipboard!');
}
} }
}
// Build TOC from h2/h3 inside the article // Build TOC from h2/h3 inside the article
(function buildTOC() { (function buildTOC() {
const article = document.getElementById('article'); const article = document.getElementById('article');
if (!article) return; if (!article) return;
const headings = article.querySelectorAll('h2, h3');
const list = document.getElementById('toc-list');
if (!headings.length || !list) return;
headings.forEach((h, idx) => { const headings = article.querySelectorAll('h2, h3');
const id = h.id || `h-${idx}`; const list = document.getElementById('toc-list');
h.id = id; if (!headings.length || !list) return;
const li = document.createElement('li');
li.className = h.tagName === 'H2' ? 'toc-h2' : 'toc-h3'; headings.forEach((h, idx) => {
const a = document.createElement('a'); const id = h.id || `h-${idx}`;
a.href = `#${id}`; h.id = id;
a.textContent = h.textContent;
li.appendChild(a); const li = document.createElement('li');
list.appendChild(li); li.className = h.tagName === 'H2' ? 'toc-h2' : 'toc-h3';
});
})(); const a = document.createElement('a');
</script> a.href = `#${id}`;
a.textContent = h.textContent;
li.appendChild(a);
list.appendChild(li);
});
})();
</script>
{% endblock %} {% endblock %}

View file

@ -29,7 +29,9 @@
</div> </div>
<div class="newsletter-info"> <div class="newsletter-info">
<h2> <h2>
<a href="/newsletter/{{ nl['id'] }}">{{ nl['subject'] }}</a> <a href="{{ url_for('newsletter_detail', newsletter_id=nl['id']) }}">
{{ nl['subject'] }}
</a>
</h2> </h2>
</div> </div>
</div> </div>
@ -43,12 +45,15 @@
{% if nl.get('preview') %} {% if nl.get('preview') %}
{{ nl['preview'][:150] }}... {{ nl['preview'][:150] }}...
{% else %} {% else %}
Get the latest updates on cycling training, performance tips, and Get the latest updates on cycling training, performance tips,
RideAware features in this newsletter edition. and RideAware features in this newsletter edition.
{% endif %} {% endif %}
</div> </div>
<a href="/newsletter/{{ nl['id'] }}" class="read-more-btn"> <a
href="{{ url_for('newsletter_detail', newsletter_id=nl['id']) }}"
class="read-more-btn"
>
Read Full Newsletter Read Full Newsletter
<i class="fas fa-arrow-right"></i> <i class="fas fa-arrow-right"></i>
</a> </a>
@ -65,7 +70,7 @@
We're working on some amazing content for you. Subscribe to be the We're working on some amazing content for you. Subscribe to be the
first to know when we publish our newsletters! first to know when we publish our newsletters!
</p> </p>
<a href="/" class="subscribe-prompt"> <a href="{{ url_for('index') }}" class="subscribe-prompt">
<i class="fas fa-bell"></i> <i class="fas fa-bell"></i>
Subscribe for Updates Subscribe for Updates
</a> </a>