Lighthouse
Under the hood

Kestra handles them.

Lighthouse is four steps: ingest, process, deliver, observe. Each one is a Kestra flow described in plain YAML — versioned, retried, replayed, observed. We did not invent any of that. Kestra handed it to us.

The pipeline

Four flows. One brief.

01 · Ingest

Read the open web

A Kestra flow per source — RSS, arXiv, GitHub trending, HN, Reddit, YouTube transcripts, Exa semantic search. Each one is idempotent, retried with backoff, and recorded for replay.

ingest.rss

02 · Process

Dedupe & classify

Documents are embedded into pgvector, near-duplicates are clustered, and an LLM classifies what matters for your topic. Cluster summaries are the source material for the brief.

process.embed_dedup

03 · Deliver

Write & ship the brief

Your AI provider drafts the Markdown brief from the cluster summaries. Lighthouse auto-formats and posts it to email (HTML), Slack (mrkdwn), Discord (native MD), Telegram (HTML), or Notion — whichever channels you configured.

deliver.brief

04 · Observe

Stay accountable

Kestra’s UI shows every step that ran, every retry, every artifact. We forward alerts and let you replay any execution if a source breaks or a model is down.

monitors.alerts

Declarative YAML

Adding a new source is a 20-line file you can review in a PR. No DSL, no framework lock-in.

Retries built in

Flaky RSS feed? Slow LLM call? Kestra retries with backoff and you wake up to a brief, not an outage.

Real observability

A namespace per stage, logs per task, a Gantt per execution. Debugging looks like a normal job.

Anatomy of a flow

A Kestra flow is just YAML.

Every ingestion source is a small flow with three or four tasks. Tasks call HTTP, run Python, talk to LLMs, and write to Postgres — orchestrated by Kestra’s engine.

  • · Idempotent — same input, same output.
  • · Retried — automatic backoff on transient failures.
  • · Observable — full Gantt and logs in Kestra UI.
  • · Replayable — one click re-runs any execution.
# flows/ingest/rss.yaml
id: rss
namespace: company.team.lighthouse.ingest

inputs:
  - id: topic_id
    type: STRING

triggers:
  - id: every-morning
    type: io.kestra.plugin.core.trigger.Schedule
    cron: "0 7 * * *"

tasks:
  - id: load_profile
    type: io.kestra.plugin.scripts.python.Script
    script: |
      profile = read_topic("{{ inputs.topic_id }}")

  - id: pull_feeds
    type: io.kestra.plugin.fs.http.Request
    uri: "{{ outputs.load_profile.vars.feed }}"
    retry:
      type: constant
      maxAttempt: 3
      interval: PT30S

  - id: upsert
    type: io.kestra.plugin.jdbc.postgresql.Query
    sql: "INSERT INTO lh.documents …"
Built on

Great open source, used gratefully.

Every box in Lighthouse is something somebody else figured out first. We borrow heavily and link out loudly — please go support these projects.

Kestra

Workflow orchestration

The reason this entire pipeline is YAML you can read. Replays, retries, scheduling, observability — out of the box.

Visit project

Supabase

Auth + Postgres + RLS

Sign-up, settings storage, row-level security and realtime. The whole user surface in one weekend.

Visit project

LiteLLM

One API, many models

BYOK works because LiteLLM speaks OpenAI on top of every provider you'd actually pick.

Visit project

Next.js

App Router + RSC

Server components for the slow parts, client components for the interactive parts. One Node host.

Visit project

Floating UI

Tooltips & popovers

The topic picker and every hover hint use Floating UI’s collision-aware positioning.

Visit project

Magic UI

Animated primitives

Aurora, ShineBorder, BorderBeam, MagicCard, AnimatedGridPattern — the visual layer of this page is shamelessly enabled by Magic UI.

Visit project

Tailwind CSS

Design system

Every pixel on this page. Utility-first, dark-first, a11y-friendly defaults.

Visit project

PostgreSQL + pgvector

Search + storage

Documents, embeddings and briefs live in the same database. One join away.

Visit project

Framer Motion

Animation runtime

The hero text, page transitions, marquee, magnet cursors — all backed by Framer Motion.

Visit project

react-markdown

Brief rendering

Renders the sample brief safely with custom components — no innerHTML.

Visit project

WebMCP

Agent-native dashboard

The dashboard exposes lighthouse-* tools via document.modelContext so browser agents can select topics, run briefs, and build custom profiles without scraping the DOM.

Visit project

The open web

Source material

RSS, arXiv, GitHub, HN, Reddit, YouTube transcripts — none of this works without their generous public surfaces.

Visit project

Now you know the boring parts.

The interesting part is the brief that lands tomorrow morning. Pick a topic and bring your AI key.