Santhosh Janardhanan 7bd51837de
Some checks failed
ci / site (push) Has been cancelled
publish-image / publish (push) Has been cancelled
add favicon
2026-02-10 07:09:12 -05:00
2026-02-10 06:17:21 -05:00
2026-02-10 04:54:05 -05:00
2026-02-10 04:54:05 -05:00
2026-02-10 06:46:29 -05:00
2026-02-10 07:09:12 -05:00
2026-02-10 02:52:14 -05:00
2026-02-10 06:17:21 -05:00
2026-02-10 06:17:21 -05:00
2026-02-10 02:52:14 -05:00

fast-website

Lightweight, SEO-first website for SanthoshJ that aggregates YouTube + Instagram + podcast content and tracks conversion events via Umami.

Local Setup

cd site
cp .env.example .env
npm install
npm run fetch-content
npm run dev

Open http://localhost:4321.

Configuration

All configuration is via environment variables (see site/.env.example).

YouTube

  • YOUTUBE_CHANNEL_ID is required for ingestion.
  • Optional: YOUTUBE_API_KEY enables view-count ingestion for high-performing ranking.

Notes:

  • The channel ID looks like UC... and can be found by viewing the channel page source or via YouTube Studio settings.
  • If YOUTUBE_API_KEY is not set, ingestion falls back to the public channel RSS feed and metrics will be missing.

Podcast

  • PODCAST_RSS_URL is required to ingest episodes.

Instagram (Embed-First)

Edit site/content/instagram-posts.json:

{
  "posts": [
    { "url": "https://www.instagram.com/p/<id>/", "publishedAt": "2026-02-01T00:00:00Z", "title": "Movie post" }
  ]
}

Phase 2 (API ingestion) path:

  • Requires Meta developer app setup, correct account type, token issuance + refresh, and platform policy compliance.
  • Recommended approach: keep embed-first for v1, then add an optional API ingest module when constraints are clear.

If YouTube metrics are not available, curate high-performing videos in site/content/featured-videos.json:

{ "videoIds": ["abc123", "def456"] }

Analytics (Umami)

Set:

  • PUBLIC_UMAMI_SCRIPT_URL
  • PUBLIC_UMAMI_WEBSITE_ID

If either is missing, analytics is disabled and the site still functions.

Event tracking is implemented using Umami's data-umami-event and data-umami-event-* attributes.

Click Tracking Taxonomy (Umami-Compatible)

All tracked clickables MUST set:

  • data-umami-event: the event name (max 50 chars), e.g. click, cta_click, outbound_click
  • data-umami-event-target_id: stable unique identifier for the clickable element (namespaced like nav.*, cta.*, card.*)
  • data-umami-event-placement: where the clickable appears (e.g. nav, hero, section_header, home.newest)

For links, also set:

  • data-umami-event-target_url: destination URL (can be relative for internal navigation)

Common additional properties:

  • data-umami-event-domain: destination domain (for outbound links)
  • data-umami-event-source: youtube / instagram / podcast where applicable
  • data-umami-event-ui_placement: a sub-placement for UI grouping (e.g. content_card)

Instrumentation checklist:

  • Every clickable should have a unique target_id so it can be segmented in Umami.
  • Use categorical ids and placements only (no PII).

Deployment (Linode + Docker)

The production host is intentionally minimal and only needs Docker (no Node.js on the server).

Local Docker

docker compose build
docker compose up -d

The container serves the static output on port 8080 (map or proxy as needed).

Production (Docker-Only Host)

In production, CI builds and publishes a Docker image (nginx serving the static output). The server updates by pulling that image and restarting the service.

Runbook: deploy/runbook.md.

Refreshing Content (Manual, Docker-Only)

Content is fetched at build time into site/content/cache/content.json (typically in CI), then packaged into the image.

On the server host:

./scripts/refresh.sh

This:

  1. Pulls the latest published image
  2. Restarts the service (no build on the host)

Refreshing Content (Scheduled)

Install a daily cron using deploy/cron.example as a starting point.

Rollback:

  • Re-deploy a known-good image tag/digest (see deploy/runbook.md).
Description
No description provided
Readme 11 MiB
Languages
Astro 44.2%
TypeScript 33.5%
CSS 17.4%
JavaScript 3.4%
Dockerfile 1.1%
Other 0.4%