Inspiration

A programming chief’s Monday problem: which three titles do we push this week—and can we defend the slate with numbers?

Catalog Greenlight answers with catalog economics measured in ClickHouse: genre gaps, week-over-week momentum, cannibalization, and language holes. Ranking stays in TypeScript so a judge can audit the formula even when Gemini is down.

This is a different job than Chloe (screenplay to film) and a different ClickHouse story than Flashframe (photosensitivity QC). We optimize for a repeatable weekly programming ritual: measure, score, explain—not cinematic generation. Remove ClickHouse and mcp-clickhouse and the product disappears: no gap scores, no WoW revenue, no cannibal pairs, nothing for the scorer to rank.

What it does

Catalog Greenlight helps a streaming programming chief pick three catalog titles to push each week—from measured data, not LLM vibes.

  1. Greenlight this week three ranked titles with provenance strips (score, genre_gap, wow_pct, cannibal), weekly ritual table, CSV/JSON export, and ClickHouse analytics panels.
  2. Ask the Catalog — natural language to a 6-step agent to ClickHouse SQL plus evidence rows (for example, an under-represented genre with live gap_score; currently often Thriller ~0.071 — the winning genre is measured and can move after ingest)

  3. Dashboard stats catalog size, genre mix, and revenue from ClickHouse via MCP.

  4. For judges (/judge) — pitch, competitive wedge, live slate preview, 2-minute verify checklist, and jury-evidence JSON.

  5. Ingest — optional title ingest with Gemini enrichment plus MCP INSERT.

Greenlight path: four parallel MCP SELECTs to TypeScript scorer to optional Gemini memo. Ask path: Gemini plans SQL; MCP executes; answers cite returned rows.

How we built it

Built with: ClickHouse, mcp-clickhouse, Google Gemini API (@google/genai), MCP, TypeScript, React, Vite, Docker, and Render.

ClickHouse is used only through the official mcp-clickhouse connector at runtime (McpClickHouseConnector to run_query). There is no direct Node ClickHouse client in product code.

Greenlight runs four fixed SELECTs in parallel: A_genre_inventory, B_title_momentum, C_cannibalization, and D_slate_holes. A deterministic TypeScript GreenlightScorer ranks candidates and enforces genre diversity:

opportunity = 0.4 x genre_gap + 0.4 x wow_momentum - 0.2 x cannibalization_penalty + 0.05 x language_gap

Gemini (@google/genai on Google Cloud—not Agent Builder or ADK) writes the narrative only. It does not invent the ranking and does not plan greenlight SQL. Gemini synthesizeGreenlight has a 25-second timeout. On timeout, 429, or error, the dashboard still returns three scorer picks with measured opportunity_score, wow_pct, and genre_gap using HTTP 200.

Ask uses Gemini to classify intent and produce guarded NL-to-SQL, MCP to execute it, and a grounded answer with SQL, evidence, and a 6-step timeline. Google AI is used only via @google/genai (GoogleGenAI and generateContent), not Agent Builder, ADK, or LangChain.

Hosted on Render and ClickHouse Cloud. Honest warm p50s: greenlight cached approximately 11 seconds, refresh approximately 37 seconds, and ask approximately 33 seconds (see BENCHMARKS.md). MCP stdio plus ClickHouse Cloud remain in the demo path.

Challenges we ran into

Keeping Gemini optional on the critical path: greenlight must still return three measured picks on timeout or 429. Enforcing genre diversity without starving the candidate pool. Honest hosted latency on Render free tier (cold starts) while keeping MCP stdio plus ClickHouse Cloud in the demo path.

Accomplishments that we’re proud of

Live hosted demo with mcp-clickhouse in runtime. Deterministic scorer and published formula. Provenance UI makes clear that Gemini did not invent the ranking. Ask is grounded with SQL plus gap_score. Judge page includes a competitive wedge and jury-evidence export. Diversity fix verified in production with three unique genres.

What’s next

Keep-alive during judging week, richer language-gap slate holes, and an optional A/B test of scorer weights without moving ranking into the LLM.

Try it yourself

Live: https://catalog-greenlight.onrender.com Judges: https://catalog-greenlight.onrender.com/judge

git clone https://github.com/armandobecerraro/catalog-greenlight
cd catalog-greenlight
cp .env.example .env
npm install && npm run dev

Force a fresh slate: GET /api/v1/greenlight?refresh=1

Pitch: ClickHouse measures. TypeScript scores. Gemini explains.

Built With

Share this project:

Updates

Submission history