Compare commits

...

2 commits

Author SHA1 Message Date
Cipher Vance
46093d2b56 chore(ui): Formatted and cleaned up the code 2025-08-31 13:25:12 -05:00
Cipher Vance
ffdc4cde38 feat(ui): added Logo! 2025-08-31 13:24:45 -05:00
6 changed files with 638 additions and 611 deletions

BIN
static/assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

View file

@ -1,72 +1,94 @@
{% set is_home = is_home | default(false) %}
<!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{% endblock %}</title>
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, viewport-fit=cover"
/>
<title>{% block title %}RideAware{% endblock %}</title>
<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">
<link
rel="stylesheet"
href="{{ url_for('static', filename='css/styles.css') }}"
/>
<!-- 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"
/>
<link
rel="alternate icon"
type="image/png"
sizes="32x32"
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"
/>
<!-- Core CSS -->
<link
rel="stylesheet"
href="{{ url_for('static', filename='css/styles.css') }}"
/>
{% block extra_head %}{% endblock %}
</head>
<body>
<nav class="navbar">
<div class="nav-container">
<a href="/" class="logo">Ride<span class="logo-accent">Aware</span></a>
<ul class="nav-links">
{% if is_home %}
<li><a href="#features">Features</a></li>
{% endif %}
<li><a href="/newsletters">Newsletters</a></li>
</ul>
</div>
</nav>
<!-- Favicons -->
<link
rel="icon"
type="image/png"
sizes="32x32"
href="{{ url_for('static', filename='assets/32x32.png') }}"
/>
<link
rel="alternate icon"
type="image/png"
sizes="32x32"
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 content %}{% endblock %}
{% block extra_head %}{% endblock %}
</head>
<body>
{% set is_home = is_home | default(false) %}
<footer class="footer">
<p>&copy; 2025 RideAware. All rights reserved.</p>
</footer>
<nav class="navbar">
<div class="nav-container">
<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
defer
src="https://cdn.statically.io/gl/rideaware/landing/06d19988c7df53636277f945f9ed853bda76471b/static/js/main.min.js"
crossorigin="anonymous"
></script>
{% block content %}{% endblock %}
{% block extra_scripts %}{% endblock %}
</body>
<footer class="footer">
<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>

View file

@ -1,392 +1,367 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Welcome to RideAware!</title>
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0"
/>
<!--[if mso]>
<noscript>
<noscript>
<xml>
<o:OfficeDocumentSettings>
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
<o:OfficeDocumentSettings>
<o:PixelsPerInch>96</o:PixelsPerInch>
<o:AllowPNG/>
</o:OfficeDocumentSettings>
</xml>
</noscript>
</noscript>
<![endif]-->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Welcome to RideAware!</title>
<style>
/* Reset and base styles */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
line-height: 1.6;
color: #1a1a1a;
background-color: #f8fafc;
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}
table {
border-collapse: collapse;
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
}
img {
border: 0;
max-width: 100%;
height: auto;
line-height: 100%;
outline: none;
text-decoration: none;
}
/* Email container */
.email-wrapper {
max-width: 600px;
margin: 0 auto;
background-color: #ffffff;
}
/* Header styles */
/* Basic resets (email-safe) */
html,
body {
margin: 0 !important;
padding: 0 !important;
height: 100% !important;
width: 100% !important;
}
* {
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
}
table,
td {
mso-table-lspace: 0pt !important;
mso-table-rspace: 0pt !important;
}
img {
-ms-interpolation-mode: bicubic;
border: 0;
outline: none;
text-decoration: none;
display: block;
height: auto;
max-width: 100%;
}
/* Wrapper/background */
.bg {
background-color: #f8fafc;
}
/* Container */
.container {
width: 100%;
max-width: 600px;
margin: 0 auto;
background-color: #ffffff;
}
/* Header */
.header {
background: #1e4e9c;
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 {
background: linear-gradient(135deg, #1e4e9c 0%, #337cf2 100%);
background-color: #1e4e9c; /* Fallback */
padding: 50px 30px;
text-align: center;
color: white;
padding: 32px 18px !important;
}
.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 {
padding: 40px 30px;
text-align: center;
padding: 24px 18px !important;
}
.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 {
background: linear-gradient(135deg, rgba(30, 78, 156, 0.05) 0%, rgba(0, 212, 255, 0.05) 100%);
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;
}
padding: 16px !important;
}
}
</style>
</head>
<body>
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" style="background-color: #f8fafc;">
</head>
<body class="bg">
<center role="article" aria-roledescription="email">
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr>
<td align="center">
<div class="email-wrapper">
<!-- Header -->
<div class="header">
<div class="welcome-icon">🎉</div>
<div class="logo">Ride<span class="logo-accent">Aware</span></div>
<h1>Welcome Aboard!</h1>
<p class="subtitle">You're now part of the RideAware community</p>
</div>
<td align="center">
<table role="presentation" class="container" width="600" cellspacing="0" cellpadding="0" border="0">
<!-- Header -->
<tr>
<td class="header">
<!-- Optional image logo: replace src if you prefer image instead of text -->
<!--
<img src="https://your-cdn/rideaware-logo.png" alt="RideAware" width="140" height="28" />
-->
<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 -->
<div class="content">
<p class="main-message">Thanks for subscribing to RideAware newsletter!</p>
<p class="description">
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.
</p>
<!-- Body -->
<tr>
<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>
<!-- Features -->
<div class="features">
<h3>What to expect from us:</h3>
<div class="feature-grid">
<div class="feature-item">
<span class="feature-icon">🚴‍♂️</span>
<div class="feature-title">Training Tips</div>
<div class="feature-desc">Expert advice to improve your performance</div>
</div>
<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>
<!-- Features -->
<tr>
<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>
<!-- CTA -->
<div class="cta-section">
<p style="margin-bottom: 20px;">Ready to start your journey with RideAware?</p>
<a href="https://rideaware.com" target="_blank" class="cta-button">
Explore RideAware →
</a>
</div>
<!-- CTA -->
<tr>
<td class="cta" align="center">
<p style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; color:#1a1a1a; font-size:15px; margin: 0 0 12px 0;">
Ready to start your journey with RideAware?
</p>
<a href="https://rideaware.org" target="_blank" class="cta-btn">Explore RideAware →</a>
</td>
</tr>
<!-- Social section -->
<div class="social-section">
<h4>Stay Connected</h4>
<div class="social-links">
<a href="#" class="social-link" title="Follow us on Twitter">🐦</a>
<a href="#" class="social-link" title="Like us on Facebook">📘</a>
<a href="#" class="social-link" title="Follow us on Instagram">📷</a>
</div>
</div>
<!-- Social -->
<tr>
<td>
<div class="social">
<div class="social-title">Stay Connected</div>
<a href="https://twitter.com" class="social-link" title="Twitter" aria-label="Twitter">T</a>
<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>
<p style="color: #6b7280; font-size: 14px; margin-top: 30px;">
We're excited to share our journey with you and help you achieve your cycling goals. Welcome to the RideAware family! 🚴‍♀️
</p>
</div>
<!-- Footer -->
<div class="footer">
<div class="footer-content">
<p><strong>RideAware Team</strong></p>
<p>Empowering cyclists, one ride at a time</p>
</div>
<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>
<!-- Footer -->
<tr>
<td class="footer">
<p><strong>RideAware Team</strong></p>
<p>Empowering cyclists, one ride at a time</p>
<div class="unsubscribe">
<p style="margin: 0;">
<a href="{{ unsubscribe_link }}">Unsubscribe</a>
&nbsp;|&nbsp;
<a href="mailto:support@rideaware.com">Contact Support</a>
</p>
<p style="font-size: 12px; color: #9ca3af;">
© 2025 RideAware. All rights reserved.
</p>
<p style="font-size: 11px; color: #9ca3af;">
You received this email because you subscribed to RideAware updates.
</p>
</div>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</table>
</center>
</body>
</html>

View file

@ -1,4 +1,3 @@
<!-- templates/index.html -->
{% extends "base.html" %}
{% block title %}RideAware - Smart Cycling Training Platform{% endblock %}
@ -10,8 +9,8 @@
<div class="hero-content">
<h1>Elevate Your Cycling Journey</h1>
<p class="subtitle">
The ultimate smart training platform for cyclists who demand excellence
in every ride.
The ultimate smart training platform for cyclists who demand
excellence in every ride.
</p>
<div class="cta-section">
@ -35,7 +34,18 @@
<div class="phone-mockup">
<div class="screen">
<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="stat-card">
<div class="stat-number">24.5</div>
@ -62,143 +72,145 @@
</section>
<!-- Features Section -->
<section class="features" id="features">
<div class="section-header">
<h2>Powerful Features for Every Cyclist</h2>
<p>
From beginners to professionals, RideAware provides comprehensive tools
to optimize your training and performance.
</p>
</div>
{% if is_home %}
<section class="features" id="features">
<div class="section-header">
<h2>Powerful Features for Every Cyclist</h2>
<p>
From beginners to professionals, RideAware provides comprehensive
tools to optimize your training and performance.
</p>
</div>
<div class="features-container">
<div class="features-grid">
<div class="feature-card">
<div class="feature-icon">
<i class="fas fa-calendar-alt"></i>
<div class="features-container">
<div class="features-grid">
<div class="feature-card">
<div class="feature-icon">
<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>
<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-icon">
<i class="fas fa-chart-line"></i>
<div class="feature-card">
<div class="feature-icon">
<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>
<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-icon">
<i class="fas fa-bicycle"></i>
<div class="feature-card">
<div class="feature-icon">
<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>
<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-icon">
<i class="fas fa-heart"></i>
<div class="feature-card">
<div class="feature-icon">
<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>
<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-icon">
<i class="fas fa-users"></i>
<div class="feature-card">
<div class="feature-icon">
<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>
<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-icon">
<i class="fas fa-sync-alt"></i>
<div class="feature-card">
<div class="feature-icon">
<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>
<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>
</section>
</section>
{% endif %}
{% endblock %}

View file

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

View file

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