## 1. Repo And Tooling Setup - [x] 1.1 Choose the site framework and initialize the project skeleton (Astro preferred) with TypeScript support - [x] 1.2 Add a consistent config approach for secrets and runtime settings (env vars for API keys, Umami settings, base URL) - [x] 1.3 Add basic quality gates (lint/format, typecheck) and a minimal CI workflow - [x] 1.4 Add Docker build/run for deployment to the Linode instance (multi-stage build, static output served by nginx or equivalent) ## 2. Content Model And Cache - [x] 2.1 Define the normalized content item schema (id, source, url, title, publishedAt, thumbnailUrl, optional metrics/views) - [x] 2.2 Implement a content cache file format and location (e.g., `content/cache/*.json`) plus a "last updated" timestamp - [x] 2.3 Implement cache read utilities used by page rendering, including source filtering and limit controls - [x] 2.4 Implement "serve last good cache on failure" behavior in the ingestion workflow (write temp then swap) ## 3. YouTube Ingestion - [x] 3.1 Implement YouTube ingestion via RSS as the baseline (latest videos, no metrics) - [x] 3.2 Implement optional YouTube Data API ingestion when `YOUTUBE_API_KEY` is configured (include `metrics.views`) - [x] 3.3 Implement configurable channel identifier for `youtube.com/santhoshj` (document required values) - [x] 3.4 Add a small set of local fixtures/tests for parsing and normalization (RSS and API response samples) ## 4. Podcast Ingestion - [x] 4.1 Add configuration for the Irregular Mind podcast RSS URL - [x] 4.2 Implement podcast RSS fetch + parse to normalized items (one item per episode) - [x] 4.3 Ensure episode URLs and publish dates normalize correctly across common RSS date formats - [x] 4.4 Add fixtures/tests for RSS parsing and normalization ## 5. Instagram Support (Embed-First) - [x] 5.1 Define the minimal normalized representation for Instagram items in embed-first mode (post URL + optional thumbnail) - [x] 5.2 Implement a configuration-driven list of Instagram post URLs (or a simple feed source) for v1 - [x] 5.3 Implement the renderer for Instagram embeds with a graceful empty state when no items exist - [x] 5.4 Document a Phase 2 path for API-based ingestion (constraints, account/app requirements, token refresh) ## 6. Build-Time Refresh And Scheduling - [x] 6.1 Implement a `fetch-content` script/command that ingests all sources and writes the cache - [x] 6.2 Add a manual refresh mechanism for ops (document how to run on the Linode host) - [x] 6.3 Add a scheduled refresh plan (cron on Linode or CI scheduler) and document frequency (daily minimum) - [x] 6.4 Add logging for ingestion runs (success/failure per source, cache write result) ## 7. Pages And SEO Surface - [x] 7.1 Implement `/` home page scaffold with deterministic module order - [x] 7.2 Implement `/videos`, `/podcast`, and `/about` indexable pages (static/SSR HTML, not client-only) - [x] 7.3 Add per-page metadata: title, description, canonical URL - [x] 7.4 Add Open Graph + Twitter card tags for indexable pages - [x] 7.5 Implement `sitemap.xml` and `robots.txt` (include `/`, `/videos`, `/podcast`, `/about`) - [x] 7.6 Add structured data (JSON-LD) scaffolding for Video/Podcast where detail pages exist (ensure valid JSON) ## 8. Homepage Modules - [x] 8.1 Implement "newest content" feed (sort by `publishedAt` desc across sources, configurable limits) - [x] 8.2 Implement "high-performing videos" module using `metrics.views` when present - [x] 8.3 Implement a manual override/curation list for featured/high-performing videos - [x] 8.4 Implement graceful empty/error states for each module (page never breaks if a module has no data) ## 9. CTAs And Outbound Tracking - [x] 9.1 Implement a reusable CTA component with `platform`, `placement`, and destination `url` - [x] 9.2 Add default destinations for YouTube channel, Instagram profile, and podcast listen target(s) - [x] 9.3 Add UTM parameter support for CTA outbound links - [x] 9.4 Define CTA placements on homepage (hero + at least one additional placement) and ensure they are visually prominent ## 10. Umami Analytics - [x] 10.1 Add Umami configuration (website ID + script URL) via environment/config without code changes per environment - [x] 10.2 Load Umami on all indexable pages when enabled; ensure site works when disabled - [x] 10.3 Implement `cta_click` event emission with `platform`, `placement`, and `target` - [x] 10.4 Implement `outbound_click` event emission with destination domain/identifier ## 11. Verification And Launch - [x] 11.1 Validate SEO basics locally (view-source contains metadata; sitemap/robots served correctly) - [x] 11.2 Validate performance basics (no blocking API calls at runtime; pages render from cache) - [x] 11.3 Validate analytics in a staging environment (events show up in Umami; disabled mode has no errors) - [x] 11.4 Document deployment steps for the Linode Docker setup (build, run, refresh schedule, rollback)