folx-tv/replit.md
sebastjanartic 4ece9e4ccd Add exclusive photos from recordings to the gallery and improve site metadata
Integrate AdSense ads into the photo gallery, introduce SSR meta tags for the gallery page, and improve layout stability by reserving space for ads and dynamic content.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 23852c00-4779-460a-9e0c-d09fee4b6c92
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 81f3d8bc-2328-4374-a06e-57257dbb713b
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/f209e72a-0939-48fa-84fc-57854de71967/23852c00-4779-460a-9e0c-d09fee4b6c92/OPD8Ro3
Replit-Helium-Checkpoint-Created: true
2026-03-08 07:33:00 +00:00

12 KiB
Raw Permalink Blame History

Folx Music Television - folx.tv

Overview

The official website for Folx Music Television (folx.tv). Dark-themed bento grid layout with content for folk music (Volksmusik/Schlager) fans. Features articles, videos, photo gallery, horoscope widget + subpage, recipe widget + subpage, Google News feed, and integrated AdSense ads. All content is hardcoded in seed for production deployments.

SEO

  • Primary keyword: "Volksmusik" — used across all page titles, meta descriptions, OG tags, and structured data
  • Dynamic canonical URLs via usePageMeta hook (updates <link rel="canonical"> per page)
  • SSR article pages: server-side meta tags (OG, Twitter, description, keywords, canonical) in both server/vite.ts (dev) and server/static.ts (prod)
  • SSR gallery page (/gallery): OG meta, Twitter card, description, canonical — emphasizes exclusive backstage/concert photos from recordings
  • stripExistingMeta() removes duplicate meta/canonical from base HTML before injecting article-specific ones
  • JSON-LD structured data: WebSite (home) with SearchAction, NewsArticle + BreadcrumbList (articles)
  • Sitemap at /sitemap.xml — includes all static pages, categories, horoscope signs, and articles
  • robots.txt disallows /api/, /search, /admin/
  • H1 tag on home page (sr-only): "FOLX TV Volksmusik & Schlager Fernsehsender"
  • Logo alt text includes "Volksmusik & Schlager Fernsehsender"

Architecture

  • Frontend: React + Vite + TailwindCSS + shadcn/ui (dark mode)
  • Backend: Express.js + Node.js
  • Database: PostgreSQL with Drizzle ORM
  • Routing: wouter (frontend), Express (backend API)

Key Features

  • MSN-style bento grid homepage with mixed article/widget layout
  • FeaturedCarousel with 5 article pages (page 2 = wide layout) + gallery page
  • Photo gallery widget (547 Dropbox images) with fullscreen lightbox carousel
  • Horoscope widget with element colors, star ratings, full /horoskop subpage
  • Recipe widget + full /rezepte subpage (21 recipes across 5 regions: Österreich, Bayern, Schwaben/Baden, Südtirol/Alpen, Norddeutschland) with AI-generated images
  • Google News RSS widget (Volksmusik/Schlager news, 5 items, auto-rotate)
  • Google AdSense integration (ca-pub-4465464714854276)
  • Interstitial overlay ad on article pages (3s delay, shows every other article visit, sessionStorage counter)
  • Parallax/reveal ad below article content (sticky background ad revealed on scroll)
  • Mobile sticky banner ad at bottom of screen (2s delay, session-dismissible, mobile-only via useIsMobile hook)
  • Web Push Notifications (bell icon in header, auto-send on new articles, admin panel at /admin/push)
  • Article listing with featured carousel and category filtering
  • HTML content supports embedded iframes (bunny.net, YouTube, Facebook, Instagram, TikTok)
  • DOMPurify sanitization for safe HTML rendering
  • Responsive design with mobile navigation

Data Model

  • articles: id (serial), title, slug (unique), excerpt, content (HTML), coverImage, category, author, featured, views, publishedAt
  • article_views: id (serial), articleId, ipHash (sha256 truncated to 16 chars), viewedAt — tracks unique IP views per article

Seed Behavior

  • server/seed.ts runs on startup and always syncs article content from seedArticles array to the database
  • Existing articles (matched by slug) are fully updated with latest title, excerpt, content, coverImage, category, author, featured, publishedAt
  • New articles are inserted; articles not in seed list are deleted
  • HTML entity „/“ in title/excerpt are auto-replaced with „/" after seeding
  • Any changes to article content in seed.ts will be reflected on next deployment
  • Currently all articles are under "News" category (+ "Video" for video-only articles)
  • Future subcategory plan: add subcategory field for "Porträt" label on portrait articles
  • Portrait articles (for future subcategory): die-edlseer, die-pagger-buam, anita-hofmann, oeschs-die-dritten

API Endpoints

  • GET /api/articles - All articles
  • GET /api/articles/featured - Featured articles
  • GET /api/articles/popular - Popular articles by views
  • GET /api/articles/category/:category - Filter by category
  • GET /api/articles/:slug - Single article (increments views)
  • POST /api/articles - Create article
  • PATCH /api/articles/:id - Update article
  • DELETE /api/articles/:id - Delete article
  • POST /api/upload - Upload image file
  • GET /api/push/vapid-key - Get VAPID public key for push subscriptions
  • POST /api/push/subscribe - Subscribe to push notifications
  • POST /api/push/unsubscribe - Unsubscribe from push notifications
  • GET /api/push/count - Get push subscriber count
  • POST /api/admin/push/send - Send push notification to all subscribers
  • GET /api/gallery - Shuffled gallery images from Cloudinary (with artist names from filenames + overrides)
  • GET /api/gallery/focal-points - Gallery image focal points (JSON)
  • PUT /api/gallery/focal-points/:fileName - Set focal point for gallery image
  • DELETE /api/gallery/focal-points/:fileName - Reset focal point for gallery image
  • GET /api/gallery/artists - Artist name overrides (JSON)
  • PUT /api/gallery/artists/:fileName - Set/update artist name override
  • POST /api/gallery/migrate-to-cloudinary - Migrate remaining Dropbox images to Cloudinary
  • GET /api/gallery/thumb - Proxy endpoint for Dropbox thumbnail resizing (sharp, 400x400, 30-min cache)
  • GET /api/news-feed - Google News RSS feed for Volksmusik/Schlager (15-min cache, stale-while-error)
  • GET /api/breaking-news - Google News RSS feed for general news (15-min cache, stale-while-error)
  • GET /api/videos - BunnyCDN video list (30-min cache, stale-while-error)
  • GET /api/videos/:guid - BunnyCDN video details

File Structure

  • shared/schema.ts - Drizzle schema + Zod validation
  • server/db.ts - Database connection
  • server/storage.ts - Storage interface + DatabaseStorage
  • server/routes.ts - API routes + gallery + news feed
  • server/seed.ts - Hardcoded seed data (articles)
  • server/gallery-data.json - Fallback gallery data (used when Dropbox/Cloudinary unavailable)
  • server/cloudinary-gallery-map.json - Cloudinary public ID map for 176 migrated images
  • server/gallery-focal-points.json - Manual focal point overrides for gallery images
  • server/gallery-artist-overrides.json - Manual artist name overrides for gallery images
  • server/cloudinary.ts - Cloudinary upload, URL generation, compression logic
  • client/src/pages/home.tsx - MSN-style bento grid homepage
  • client/src/pages/article.tsx - Article detail page
  • client/src/pages/category.tsx - Category listing page
  • client/src/pages/videos.tsx - Videos page
  • client/src/pages/gallery.tsx - Full gallery page
  • client/src/pages/horoscope.tsx - Full horoscope page (12 signs, love/career/health, weekly/monthly)
  • client/src/pages/recipes.tsx - Full recipes page (21 recipes, 5 regions, AI-generated images)
  • client/src/lib/horoscope-data.ts - Shared horoscope data (signs, texts, helpers)
  • client/src/components/header.tsx - Header with nav (Start, News, Video, Galerie, Horoskop, Rezepte)
  • client/src/components/footer.tsx - Footer with links
  • client/src/components/photo-gallery.tsx - Gallery widget + lightbox carousel + paginated gallery page (24/batch infinite scroll) + artist name display
  • client/src/pages/admin-gallery.tsx - Admin page for gallery management (focal points + artist names) at /admin/gallery
  • client/src/components/horoscope-widget.tsx - Horoscope widget with element colors
  • client/src/components/recipe-widget.tsx - Recipe widget with modal
  • client/src/components/news-widget.tsx - Google News RSS widget
  • client/src/components/adsense.tsx - AdSense ad components

Homepage Layout (MSN Bento Grid)

  • Row 1: FeaturedCarousel (hero + side articles + TopStorys, page 2 = wide hero)
  • Row 2: 2 articles + PhotoGalleryWidget + RecipeWidget (mixed)
  • Row 3: HoroscopeWidget + 2 articles + NewsWidget (mixed)
  • Row 4: 3 articles + NativeAdCard
  • Row 5: 3 articles + NativeAdCard

Branding

  • Dark theme (class="dark" on html)
  • Primary/brand color: crimson/red (RGB 218,35,77)
  • Background: 0 0% 5%, Card: 0 0% 9%
  • Font: Poppins
  • Logo: folx_MT_poz_b_1772296729169.png

External Services

  • Bunny.net: Library 476412, CDN vz-7982dfc4-cc8.b-cdn.net (NO autoplay)
  • Google AdSense: ca-pub-4465464714854276
  • Cloudinary: Gallery images (cloud_name: djqxt0pf3, 176 images migrated from Dropbox, face-aware cropping)
  • Dropbox: Original gallery source (fallback if Cloudinary map empty)
  • Google News RSS: Volksmusik/Schlager news feed

Publishing Workflow

Adding or Updating Articles

  1. Edit seed data: Update server/seed.ts with new article data
    • Add new articles to the articlesData array
    • Update existing articles as needed
    • Use unique slugs for SEO-friendly URLs
  2. Run seed locally (for development testing):
    • Execute: npm run seed
    • This populates the development database with article data
  3. Commit changes: Push code changes to the repository
  4. Deploy to production:
    • Deployment is configured as "autoscale" type in .replit
    • Build command: npm run build
    • Run command: node ./dist/index.cjs
    • The production database is separate from the development database
    • Important: Seed must run on every deploy to ensure the production database is updated with new/modified articles
    • To run seed on deploy, add seed execution to the deployment process or manually trigger seed after deployment

Database Management

  • Development: Local PostgreSQL database (populated by npm run seed)
  • Production: Separate PostgreSQL database on Replit deployment
  • All article content is hardcoded in server/seed.ts for reproducible deployments
  • The DATABASE_URL environment variable automatically points to the correct database (local for dev, production for deploy)

Deployment Checklist

  • Update server/seed.ts with new article data
  • Test locally: run npm run seed and verify articles appear in dev
  • Run npm run build to ensure no build errors
  • Commit all changes
  • Deploy via Replit deployment interface
  • After deployment, ensure seed runs on the production database (may require manual trigger or additional setup)
  • Verify live site at https://www.folx.tv shows updated content

Adding Articles Workflow

When adding new articles:

  1. Always optimize images first: Resize to max 1200px wide, quality 85%, target <300KB. Use convert command:
    convert input.jpg -resize 1200x -quality 85 output.jpg
    
    For OG/social sharing images, use 1200x630 crop:
    convert input.jpg -resize 1200x630^ -gravity center -extent 1200x630 -quality 85 output.jpg
    
  2. Copy optimized image to client/public/uploads/
  3. Add article to seedArticles array in server/seed.ts
  4. Add UPDATE migration at bottom of seedDatabase() function to update existing articles in production DB
  5. If article already exists in DB, seed won't update it — must add explicit UPDATE SQL migration
  6. Featured articles appear in homepage carousel; set featured: false for items that should not appear there
  7. Videos use category "Video", news uses category "News"
  8. Bunny CDN embeds: use https://player.mediadelivery.net/embed/476412/{video-id} — do NOT take text/title from Bunny, use user-provided text only
  9. Facebook embeds: copy the iframe code as-is from user
  10. After deploy, go to Facebook Sharing Debugger and click "Scrape Again" to refresh cache

Article Page Layout

  • Outer wrapper: max-w-7xl (for PageSideAds), inner content: max-w-4xl mx-auto
  • Cover image: max-h-[420px] with object-cover
  • Title: text-2xl md:text-3xl font-bold
  • Meta (author/date/views): text-xs with w-3.5 h-3.5 icons
  • Body text: prose-base with prose-p:text-[15px] and prose-headings:text-lg
  • In-article ad splits content at midpoint

Important Notes

  • Tailwind object-[center_25%] does NOT work — must use inline style={{ objectPosition: "center 25%" }}
  • Horoscope widget navigates to /horoskop on click (no modal)
  • News widget external links open in new tab (target="_blank")
  • FeaturedCarousel: page 1 = wide (5 cols, no side cards), last page = gallery
  • All images use objectPosition: "center 25%" for better face cropping