# Set up mentions tracking (Hacker News, Bluesky, and beyond)

Who's talking about you, next to who's visiting you. Hacker News works today; Bluesky needs two environment variables; anything else is a function you add.

The Mentions tab watches whatever terms you track — your product name, your domain, a campaign name — across the sources this deployment can reach, and shows what it found next to the traffic that same mention produced. It's a poll, not a live feed: a background job checks each tracked term once an hour.

> **In a hurry? Let your AI do it** — The Mentions tab has a 'Copy setup instructions for AI' button. It's aimed at whoever operates this deployment, not a customer's app — Bluesky's session lives in this app's own environment, not anyone else's. Paste it into an AI coding agent with this repo open and it walks through the Bluesky app-password setup below.

## Hacker News — works with no setup

Hacker News is searched through Algolia's public HN endpoint (hn.algolia.com), which needs no API key and no login. Add a tracked term on the Mentions tab and it starts showing up on the next hourly poll — there's nothing to configure.

## Bluesky — needs an app password

Bluesky's search API answers 403 to a request with no session, so this source is opt-in behind two environment variables on this deployment:

```
BLUESKY_IDENTIFIER=<a Bluesky handle or email>
BLUESKY_APP_PASSWORD=<an app password for that account>
```

1. Use an existing Bluesky account, or make a dedicated one — it only searches, it never posts.
2. Bluesky app -> Settings -> Privacy and Security -> App Passwords -> Add App Password.
3. Put the app password (never the account's real login password) in BLUESKY_APP_PASSWORD, and the handle or email in BLUESKY_IDENTIFIER.
4. Restart the app so the new environment variables are read. The next poll picks up Bluesky results automatically — no code change, no redeploy of anything else.

> **Why an app password, not the real one** — An app password can be revoked on its own without touching the account's login, and it's scoped to API access rather than full account control — the same reasoning as a database credential or an API key. Never put a real account password in an environment file.

## X / Twitter — not covered, on purpose

X's search API is paid and rate-limited in a way that would need its own billing decision, so it's deliberately left out rather than half-supported. If a future plan wants it, the fastest path is a Search Tweets v2 subscription and a searcher function that follows the same shape as the two below.

## Adding a provider this page doesn't cover

The system is built to add a source without a schema change: src/lib/mentions.ts holds a SEARCHERS list, each entry a source name plus a function that takes a tracked term and returns normalised mentions (author, text, url, postedAt). A new provider — Reddit, Mastodon, Product Hunt, a changelog aggregator, anything with a search endpoint — is one more function with that same shape, registered in that list.

- Every mention is deduplicated on (site, source, the provider's own id for that post) — a poller that runs every hour will see the same post again and again, so this key is what keeps it from being stored twice.
- One source failing (a timeout, a changed API) must never take down the others — the existing HN/Bluesky pair already runs each source independently and logs a failure rather than aborting the whole poll.
- Keep new sources unauthenticated where the provider allows it (like Hacker News) — a source that needs a login is real setup cost for whoever runs this deployment, worth it only when the source itself is worth it.
