fix(seo): comprehensive SEO improvements per expert audit #4
No files matched your search
@@ -2,7 +2,7 @@ name: CI Pipeline
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, develop, feature/tests-and-ci, feature/multi-admin-roles]
|
||||
branches: [main, develop, feature/tests-and-ci, feature/multi-admin-roles, fix/seo-improvements]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -78,6 +78,11 @@ def _migrate_add_missing_columns(sync_conn):
|
||||
("station_config", "color_black", sa.String(7), "#1a1816"),
|
||||
# Multi-admin support: password_hash (nullable — existing rows stay NULL)
|
||||
("users", "password_hash", sa.String(255), None),
|
||||
# Social media columns
|
||||
("station_config", "social_facebook", sa.String(500), ""),
|
||||
("station_config", "social_twitter", sa.String(500), ""),
|
||||
("station_config", "social_instagram", sa.String(500), ""),
|
||||
("station_config", "social_youtube", sa.String(500), ""),
|
||||
]
|
||||
|
||||
# Determine dialect
|
||||
|
||||
@@ -97,6 +97,12 @@ class StationConfig(Base):
|
||||
# Donation
|
||||
donation_url = Column(String(500), nullable=False, default="")
|
||||
|
||||
# Social media
|
||||
social_facebook = Column(String(500), nullable=False, default="")
|
||||
social_twitter = Column(String(500), nullable=False, default="")
|
||||
social_instagram = Column(String(500), nullable=False, default="")
|
||||
social_youtube = Column(String(500), nullable=False, default="")
|
||||
|
||||
# Stream
|
||||
stream_url = Column(String(500), nullable=False, default="")
|
||||
stream_metadata_url = Column(String(500), nullable=False, default="")
|
||||
|
||||
@@ -78,6 +78,11 @@ class StationConfigResponse(BaseModel):
|
||||
play_store_icon_url: str
|
||||
play_store_url: str
|
||||
app_store_embed_html: str
|
||||
# Social media
|
||||
social_facebook: str
|
||||
social_twitter: str
|
||||
social_instagram: str
|
||||
social_youtube: str
|
||||
# Page content
|
||||
hero_subtitle: str
|
||||
about_intro: str
|
||||
@@ -129,6 +134,11 @@ class StationConfigUpdate(BaseModel):
|
||||
play_store_icon_url: Optional[str] = None
|
||||
play_store_url: Optional[str] = None
|
||||
app_store_embed_html: Optional[str] = None
|
||||
# Social media
|
||||
social_facebook: Optional[str] = None
|
||||
social_twitter: Optional[str] = None
|
||||
social_instagram: Optional[str] = None
|
||||
social_youtube: Optional[str] = None
|
||||
# Page content
|
||||
hero_subtitle: Optional[str] = None
|
||||
about_intro: Optional[str] = None
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
User-agent: *
|
||||
Allow: /
|
||||
|
||||
Disallow: /admin
|
||||
Disallow: /login
|
||||
|
||||
Sitemap: https://kmountainflower.org/sitemap.xml
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<url>
|
||||
<loc>https://kmountainflower.org/</loc>
|
||||
<changefreq>daily</changefreq>
|
||||
<priority>1.0</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://kmountainflower.org/about</loc>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://kmountainflower.org/schedule</loc>
|
||||
<changefreq>weekly</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://kmountainflower.org/events</loc>
|
||||
<changefreq>daily</changefreq>
|
||||
<priority>0.8</priority>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://kmountainflower.org/contact</loc>
|
||||
<changefreq>monthly</changefreq>
|
||||
<priority>0.5</priority>
|
||||
</url>
|
||||
</urlset>
|
||||
@@ -3,7 +3,7 @@
|
||||
<!-- Intro -->
|
||||
<div class="about-intro">
|
||||
<img [src]="resolveImageUrl(config().hero_icon_url)" alt="" class="about-flower-decor" aria-hidden="true">
|
||||
<h2>About <span class="text-accent">{{ config().name_primary }} {{ config().name_secondary }}</span></h2>
|
||||
<h1>About <span class="text-accent">{{ config().name_primary }} {{ config().name_secondary }}</span></h1>
|
||||
<p class="section-intro">{{ config().about_intro }}</p>
|
||||
</div>
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
@if (config().donation_url) {
|
||||
<div class="about-cta">
|
||||
<div class="about-flower-divider" aria-hidden="true">
|
||||
<img [src]="resolveImageUrl(config().logo_url)" alt="">
|
||||
<img [src]="resolveImageUrl(config().logo_url)" alt="" aria-hidden="true">
|
||||
</div>
|
||||
<h3>Become a Member</h3>
|
||||
<p class="section-intro">{{ config().about_donation_text }}</p>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="container">
|
||||
<div class="contact-header">
|
||||
<img src="svg/small-flower.svg" alt="" class="contact-flower" aria-hidden="true">
|
||||
<h2>Get in <span class="text-accent">Touch</span></h2>
|
||||
<h1>Get in <span class="text-accent">Touch</span></h1>
|
||||
<p class="section-intro">
|
||||
Have a song request, want to volunteer, or just want to say hello?
|
||||
We'd love to hear from you.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="container">
|
||||
<div class="events-header">
|
||||
<img src="svg/small-flower.svg" alt="" class="events-flower" aria-hidden="true">
|
||||
<h2>Upcoming <span class="text-accent">Events</span></h2>
|
||||
<h1>Upcoming <span class="text-accent">Events</span></h1>
|
||||
<p class="section-intro">{{ config().events_intro }}</p>
|
||||
</div>
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
@if (event.rsvp_url) {
|
||||
<a [href]="event.rsvp_url" class="event-rsvp" target="_blank" rel="noopener">RSVP →</a>
|
||||
} @else {
|
||||
<a href="#" class="event-rsvp">Learn More →</a>
|
||||
<a routerLink="/contact" [queryParams]="{subject: 'general'}" class="event-rsvp">Learn More →</a>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -35,18 +35,26 @@
|
||||
@if (config().donation_url) {
|
||||
<li><a [href]="config().donation_url" target="_blank" rel="noopener noreferrer">Become a Member</a></li>
|
||||
}
|
||||
<li><a href="#">Volunteer</a></li>
|
||||
<li><a href="#">Corporate Giving</a></li>
|
||||
<li><a href="#">Planned Giving</a></li>
|
||||
<li><a routerLink="/contact" [queryParams]="{subject: 'volunteer'}">Volunteer</a></li>
|
||||
<li><a routerLink="/contact" [queryParams]="{subject: 'advertising'}">Corporate Giving</a></li>
|
||||
<li><a routerLink="/contact" [queryParams]="{subject: 'general'}">Planned Giving</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="footer-col">
|
||||
<h4>Follow Us</h4>
|
||||
<div class="social-links">
|
||||
<a href="#" aria-label="Facebook" class="social-link">📘</a>
|
||||
<a href="#" aria-label="Twitter" class="social-link">🐦</a>
|
||||
<a href="#" aria-label="Instagram" class="social-link">📷</a>
|
||||
<a href="#" aria-label="YouTube" class="social-link">📺</a>
|
||||
@if (config().social_facebook) {
|
||||
<a [href]="config().social_facebook" target="_blank" rel="noopener noreferrer" aria-label="Facebook" class="social-link">📘</a>
|
||||
}
|
||||
@if (config().social_twitter) {
|
||||
<a [href]="config().social_twitter" target="_blank" rel="noopener noreferrer" aria-label="Twitter" class="social-link">🐦</a>
|
||||
}
|
||||
@if (config().social_instagram) {
|
||||
<a [href]="config().social_instagram" target="_blank" rel="noopener noreferrer" aria-label="Instagram" class="social-link">📷</a>
|
||||
}
|
||||
@if (config().social_youtube) {
|
||||
<a [href]="config().social_youtube" target="_blank" rel="noopener noreferrer" aria-label="YouTube" class="social-link">📺</a>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -23,6 +23,11 @@ export interface StationConfig {
|
||||
play_store_icon_url: string;
|
||||
play_store_url: string;
|
||||
app_store_embed_html: string;
|
||||
// Social media
|
||||
|
kfj001 marked this conversation as resolved
|
||||
social_facebook: string;
|
||||
social_twitter: string;
|
||||
social_instagram: string;
|
||||
social_youtube: string;
|
||||
// Page content
|
||||
hero_subtitle: string;
|
||||
about_intro: string;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="container">
|
||||
<div class="schedule-header">
|
||||
<img [src]="resolveImageUrl(config().logo_url)" alt="" class="schedule-flower" aria-hidden="true">
|
||||
<h2>Program <span class="text-accent">Schedule</span></h2>
|
||||
<h1>Program <span class="text-accent">Schedule</span></h1>
|
||||
<p class="section-intro">{{ config().schedule_intro }}</p>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in new issue
Block a user
I don't think we've added any admin UI to set these values.