A modern, standalone website for the "Agentic SaaS Talks" YouTube webcast series. Built with Next.js, TypeScript, Tailwind CSS, and shadcn/ui.
Deploy to Hostinger in one command:
./deploy.shYour site will be live at https://agentic-saas-talks.com
See DEPLOYMENT.md for detailed deployment instructions.
- Modern Design: Sleek grey/blue (slate) color scheme with glassmorphism backgrounds, gradient overlays, and smooth animations
- Full Episode Archive: Every Agentic SaaS Talks episode with featured YouTube thumbnails, individually crawlable detail pages, and clickable timestamps
- Auto-generated taxonomy:
/topics/<tag>,/guests/<name>, and/hosts/<name>pages are derived from the episode/host data β no manual maintenance - Search: Combined episode + article keyword search at
/search - Hosts & Guests: Host profiles with areas of expertise; guest profiles linking the episodes they appeared in
- Blog: Markdown-driven blog with related-posts linking
- Responsive Design: Mobile-first approach with hamburger navigation menu
- SEO + GEO Optimized: Meta/OG/Twitter tags, rich Schema.org JSON-LD (incl. per-episode FAQ), image sitemap,
llms.txt, and AI-crawler-friendlyrobots.txtβ see SEO / GEO Architecture in CLAUDE.md - Accessibility: ARIA labels, keyboard navigation, and WCAG 2.1 AA compliant
- Performance: Static site generation for fast page loads
- UX Enhanced: Image loading states, scroll-to-top button, enhanced hover effects, and active navigation states
- Framework: Next.js 16 (App Router with Static Export)
- Language: TypeScript
- Styling: Tailwind CSS 4
- Components: shadcn/ui (Radix UI primitives)
- Animations: Framer Motion
- Icons: Lucide React
- Testing: Vitest (unit) + Playwright (E2E)
- Deployment: Hostinger SSH/rsync, fronted by Cloudflare
agentic-saas-talks/
βββ app/
β βββ layout.tsx # Root layout (metadata, CSP, analytics, nav, footer)
β βββ page.tsx # Homepage (hero, featured episode, topics, FAQ)
β βββ episodes/
β β βββ page.tsx # Episodes archive (client search/filter)
β β βββ [id]/page.tsx # Episode detail (+ episode-detail-client.tsx)
β βββ topics/ # Topic index + /topics/[tag] (auto-generated)
β βββ guests/ # Guest index + /guests/[slug] (auto-generated)
β βββ hosts/ # Hosts page + /hosts/[slug] profiles
β βββ blog/ # Blog listing + /blog/[slug] posts
β βββ search/ # Combined episode+article search (noindex)
β βββ sitemap.ts # XML sitemap (+ image entries)
β βββ robots.ts # robots.txt (allows AI crawlers)
β βββ llms.txt/route.ts # llms.txt for AI engines
β βββ feed.xml/route.ts # RSS feed
β βββ globals.css # Global styles (slate/blue scheme)
βββ components/
β βββ ui/ # shadcn/ui components (button, card, badge, β¦)
β βββ navigation.tsx # Desktop nav (+ mobile-nav.tsx, nav-link.tsx)
β βββ footer.tsx # Site footer
β βββ episode-grid.tsx # Shared static episode-card grid
β βββ breadcrumb.tsx # Breadcrumb nav
β βββ image-with-loading.tsx # Images with loading states
βββ data/
β βββ episodes.ts # Episode data + Episode/Guest/Timestamp types
β βββ hosts.ts # Host data (+ expertise[])
βββ lib/
β βββ constants.ts # Site config + EPISODE_COUNT (derived)
β βββ seo.ts # Schema.org JSON-LD generators
β βββ helpers.ts # Dates, slugify, taxonomy + related-episode lookups
β βββ blog.ts # Markdown blog loading + related posts
β βββ utils.ts # cn() and misc utilities
βββ content/blog/ # Markdown blog posts
βββ tests/ # Playwright E2E specs
βββ test-server.js # Zero-dep static server for the E2E harness
βββ playwright.config.ts # E2E config (serves out/ on :3000 + :3001)
βββ deploy.sh # Build + rsync + IndexNow + Cloudflare purge
βββ CLAUDE.md # Agent guide (start here)
βββ DEPLOYMENT.md / TESTING.md / SEO.md # Detailed guides
βββ package.json
- Node.js 18+
- npm or yarn
- SSH access to Hostinger (for deployment)
# Navigate to project directory
cd /home/mcoop/projects/agentic-saas-talks
# Install dependencies
npm install
# Run development server
npm run devOpen http://localhost:3000 in your browser.
# Create production build (static export)
npm run build
# Test production build locally
npm start./deploy.shThis script:
- Builds your Next.js site
- Creates static HTML/CSS/JS files in
/out - Uploads to Hostinger via SSH/rsync
- Makes site live at agentic-saas-talks.com
./deploy.sh --skip-buildUse this when you haven't changed any code and just want to re-upload existing build.
./deploy.sh --dryPreview what files would be uploaded without making any changes.
See DEPLOYMENT_GUIDE.md for step-by-step manual deployment instructions.
All episodes are stored in /data/episodes.ts with this structure:
interface Episode {
id: number
title: string
description: string
date: string // ISO format: "YYYY-MM-DD"
videoUrl: string // Full YouTube URL
duration: string // e.g., "57 min"
tags: string[]
timestamps?: Timestamp[] // Optional timestamps
guests?: Guest[] // Optional special guests
}
interface Timestamp {
time: string // Format: "mm:ss" or "hh:mm:ss"
title: string
}
interface Guest {
name: string
linkedIn: string
bio: string
photo?: string
}All hosts are stored in /data/hosts.ts with this structure:
interface Host {
name: string
linkedIn: string
bio: string
photo?: string
role?: string // e.g., "Co-Host"
company?: string
companyUrl?: string
expertise?: string[] // surfaced as schema.org knowsAbout
}- Edit
data/episodes.ts - Add new episode at beginning of array
- Optionally add guests array for special guests
- Run
./deploy.sh
Topic and guest pages, the episode count, sitemap, and
llms.txtall regenerate automatically from the data on build β nothing else to touch. For the full workflow (fetching episode details from YouTube, validation, deploy), see CLAUDE.md.
Example:
{
id: 18,
title: "Your New Episode",
description: "Description...",
date: "2025-02-01",
videoUrl: "https://www.youtube.com/watch?v=VIDEO_ID",
duration: "60 min",
tags: ["Tag1", "Tag2"],
timestamps: [
{ time: "00:00", title: "Introduction" },
{ time: "05:30", title: "Main Topic" },
],
guests: [
{
name: "Guest Name",
linkedIn: "https://www.linkedin.com/in/username/",
bio: "Guest bio and expertise"
}
]
}- Edit
data/hosts.ts - Update host information or add new host
- Run
./deploy.sh
- β Smooth hover animations on cards and buttons
- β Active navigation state highlighting
- β Image loading states with skeleton loaders
- β Enhanced button interactions (scale effects)
- β Scroll-to-top button on long pages
- β Rich timestamp hover effects
- β Responsive hamburger navigation menu
- β Slide-in mobile menu with backdrop
- β Active page highlighting in mobile menu
- β Touch-friendly button sizes
- β Vertical content stacking
- β Mobile-optimized images
- β WCAG 2.1 AA compliant
- β Keyboard navigation support
- β ARIA labels throughout
- β Focus indicators for all interactive elements
- β Semantic HTML structure
- β Screen reader friendly
npm run test:unit # Vitest unit tests
npm run test:e2e # Playwright E2E (chromium / mobile / tablet)Run E2E via npm run test:e2e, not bare npx playwright test. The suite runs against the
static export (out/), served by test-server.js on :3000 (most suites) and :3001
(the Apache/.htaccess routing suite). npm run test:e2e builds out/ first. Running against
the dev server produces false failures (dev-only CSP/eval console errors + an HMR socket that
keeps networkidle from settling). See TESTING.md and the testing notes in
CLAUDE.md.
Route (app) Size First Load JS
β β / 6.91 kB 156 kB
β β /_not-found 993 B 103 kB
β β /episodes 6.6 kB 153 kB
+ First Load JS shared by all 102 kB
- β Static site generation (SSG)
- β Lazy loading images
- β Optimized YouTube thumbnails
- β Fast page loads
The site uses a slate/blue color scheme (changed from the original purple). Colors are defined in app/globals.css:
:root {
--primary: 240 5.9% 10%; # Slate primary
--secondary: 240 4.8% 95.9%; # Light slate secondary
/* ... other CSS variables ... */
}Gradient colors throughout the site use:
from-blue-500toto-slate-500orto-slate-600- These are applied in component files (page.tsx, hosts/page.tsx, etc.)
To change the color scheme:
- Update CSS variables in
app/globals.css - Search and replace gradient color classes across components
- Update badge backgrounds and accent colors
All UI components in components/ui/ can be customized using Tailwind classes.
Edit app/layout.tsx to modify site structure or navigation.
Current routes:
/- Homepage/episodes- Episodes archive;/episodes/[id]- episode detail/topics+/topics/[tag]- topic archives (auto-generated from tags)/guests+/guests/[slug]- guest profiles (auto-generated)/hosts+/hosts/[slug]- hosts page + profiles/blog+/blog/[slug]- blog/search- combined search
To add new routes, create folders under app/ with a page.tsx file.
- Domain: https://agentic-saas-talks.com
- YouTube Channel: @omnistrate
- Hosting: Hostinger
- README.md - This file - project overview and quick start
- CLAUDE.md - Agent guide: adding episodes, file map, SEO/GEO architecture, testing
- CHANGELOG.md - Version history and recent changes
- DEPLOYMENT.md - Complete deployment guide
- TESTING.md - Testing documentation
- SEO.md - SEO optimization details and maintenance
- PROJECT_SUMMARY.md - Complete project summary
- UX_IMPROVEMENTS_SUMMARY.md - UX enhancements details
Build Status: β SUCCESS Test Status: β ALL PASSING (50+ tests) Deployment: β READY
The site is fully built, tested, and ready to deploy to:
- Domain: agentic-saas-talks.com
- Hosting: Hostinger SSH
# Development
npm run dev # Start dev server
npm run build # Build for production
npm start # Test production build
# Deployment
./deploy.sh # Build and deploy to Hostinger
./deploy.sh --skip-build # Quick deploy (no build)
./deploy.sh --dry # Preview changes (no deploy)
# Testing
npm run test:unit # Vitest unit tests
npm run test:e2e # Playwright E2E against the static export
# Code Quality
npm run lint # Check for errorsReady to deploy? Just run:
./deploy.shYour site will be live at https://agentic-saas-talks.com in about 2-3 minutes!
Built with β€οΈ using Next.js, TypeScript, Tailwind CSS, shadcn/ui, and validated with Playwright