folx-tv/replit.md
sebastjanartic 354ea959ae Add automatic push notifications for new blog articles
Implement automatic web push notifications for new articles via `seed.ts`, and update `replit.md` to reflect this feature alongside manual notification capabilities.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 23852c00-4779-460a-9e0c-d09fee4b6c92
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: fdec50e9-4e94-4779-9307-d1bee9c5c3cd
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/f209e72a-0939-48fa-84fc-57854de71967/23852c00-4779-460a-9e0c-d09fee4b6c92/ICRgny1
Replit-Helium-Checkpoint-Created: true
2026-03-07 15:22:56 +00:00

11 KiB

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.

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)
  • 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