Model or dataset
KKKKhazix/AIHOT avatar
KKKKhazix/AIHOT

AIHOT: a self-hosted engine that curates an industry news site with an LLM

A website framework that finds its own trending topics and writes its own daily reports. Swap in your own sources and selection criteria and it becomes your own industry trend site.

7,365 stars1,776 forksTypeScriptMIT

At a glance

What is it?
Six source types, two independent scoring passes, event clustering and a daily edition, all driven by prompt files you can edit without touching code. Built by a designer who says so plainly in the README.
Who is it for?
AIHOT is unusual in how little of its behaviour is hardcoded. The prompts live as Markdown in `industry/prompts/`, the thresholds in `industry/selection.ts`, the site name and edition times in `site/site.ts`, and the source list in `industry/sources.json`, so adapting it to a different industry is configuration work rather than a fork.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 12, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the repository is, stated plainly by its author

AIHOT is the engine behind a Chinese-language AI news site, published under the MIT licence with 6,173 stars and 1,546 forks, and the README is unusually direct about what you are looking at. The author describes the repository as the engine and framework for a site that finds its own hot topics and writes its own daily report, and explains the reasoning: people working in law, HR, finance and precious metals kept asking for the same thing for their own industries, and he does not know which sources matter or what counts as news in a field he does not work in.

He also states his own background plainly, saying he is a designer by training, could not read much code six months ago, and rewrote the codebase together with an AI. That sentence matters when you are deciding whether to depend on it, and it is better to know it up front than to infer it from a changelog later. He asks for issues, apologises in advance for slow replies, and asks you not to reuse the AIHOT name or logo.

There is a second caveat about scope that is easy to miss. The repository ships eighteen public overseas AI news sources so the thing runs out of the box, but the real source list is deliberately not included. The code is the same engine the live site runs, synced by exporting from production rather than polished into a general framework, and updates are passed down on a best-effort basis. Features specific to the AI industry stay on the live site.

The last push was 2026-10-06, so this is actively worked on rather than a finished artifact.

Six source types, three trust tiers, and what gets promoted

The source layer supports RSS, scraped web listing pages, JSON endpoints, X accounts, WeChat public accounts, and an external push endpoint for your own scripts. That list is broader than most aggregators attempt, and the WeChat and X entries matter because they are where a lot of Chinese-language industry news actually surfaces first.

Sources are split into three tiers: official first-hand announcements, official accounts and quasi-official ones, then media and individuals. Each tier has its own inclusion threshold, so a rumor from a low-tier source does not compete with an official announcement on equal terms. Fetch frequency adapts to how much a source produces rather than running on a fixed cron for everything.

The promotion path has six steps, and the sequence is the interesting part. An item arrives from a source, gets deduplicated, then goes through a pre-filter. Anything that looks important is scored twice independently against the same standard. If those two passes agree, the item gets a Chinese title and a summary written for it, gets clustered with related reporting, and only then counts toward a hotness score. Cross-source duplicates phrased differently do not enter selection, which is the whole point of the design.

One deliberate exception is documented. When an X post has no body text or contains only a link, the pipeline keeps the original post's link and images and skips the writing and translation models entirely, saving two paid calls on content that has nothing to summarise.

Scoring twice and clustering the same story into one event

The double scoring pass is the mechanism that keeps a daily edition readable. Rather than trusting a single judgement, potentially important items are rated twice against the same standard, and the tier-specific threshold decides whether they pass. Prompts and thresholds are both public and both editable, and the README points at `industry/prompts/selection-score.md` as the file most worth your time.

Clustering is the other half. Reporting the same event from an official site, ten media outlets and a day of social discussion should appear once. The approach is two-stage: candidates are found by comparing vectors built from titles and summaries within the last two weeks, or by text overlap when no embedding service is configured, then a model decides whether two items are the same event, a follow-up development, or genuinely different things. Uncertain merges are merged and then reviewed by a model again before writing, and that review pass can point at a different provider through `GROUP_REVIEW_MODEL`. Manually corrected assignments are never overwritten.

Hotness is computed per event rather than per article, which is the design decision that makes the ranking meaningful. Within 48 hours each independent source counts once, and sources older than 24 hours count half. Repeated crawls therefore cannot inflate a score, and a single outlet publishing ten articles counts the same as one outlet publishing one.

The `.env.example` is candid about the cost of skipping embeddings: grouping falls back to text overlap, but discussion posts that only count as hotness signals mostly fail to attach to an event, so hotness runs low. That is a real tradeoff to know about rather than discover later.

Running it: four commands and an OpenAI-compatible key

The quick path needs Docker, Node.js 24 for the environment setup script, and a key for any OpenAI-compatible model API. DeepSeek, Qwen and Zhipu are all named as working options. The whole sequence is short:

bash
git clone https://github.com/KKKKhazix/AIHOT.git myhot
cd myhot
node scripts/init-env.ts --llm-key <你的模型 API Key>
docker compose up -d --build

The setup script generates `.env` with random secrets filled in, defaulting to DeepSeek configuration. Switching providers means editing `LLM_BASE_URL`, `LLM_MODEL` and `LLM_EXTRA_JSON`; the reasoning models need `LLM_REASONING_TOKENS` set as well, since their output allowance is shared between reasoning and answer. The site comes up on port 3000, the admin interface is at `/admin` with the password from `ADMIN_PASSWORD`, and the README says to expect a minute or two before content appears and about half an hour for the first import to finish processing.

The version requirements are stricter in one place than another, which is worth noting. The README badge says Node.js 24 and the setup step calls for it, while `package.json` declares the engines field as `>=24.11`, so a generic Node 24 install will do the setup step but the package manifest asks for a specific patch level.

Beyond Docker there is a path for a machine without Node, a server in mainland China, domain and HTTPS setup, or running directly on Linux and macOS with WSL2 on Windows, all documented in `docs/deploy.md`. The compose file also carries an optional HTTPS profile that fronts the site with Caddy for `SITE_DOMAIN`.

Postgres, three processes and one image

The stack is Node.js 24, TypeScript, React Router with server-side rendering, Fastify, PostgreSQL, pg-boss for job queueing, Tailwind and Docker Compose. The `package.json` is an npm workspaces monorepo covering `packages/*`, `apps/*`, `industry`, `site` and `modules/*`, and the version pins are notable: TypeScript 7.0.2 and Playwright 1.61.1 in devDependencies, and an override pinning `fflate` to 0.7.5.

The compose file defines a `db` service on `postgres:17-alpine` with a `pg_isready` healthcheck, a one-shot `setup` service that runs migrations and seeds the demo sources then exits, and separate `api` and `worker` services. The API waits for `setup` to complete successfully, and both wait for the database to be healthy. The worker runs with a graceful stop timeout of 195 seconds, chosen so a paid model call already in flight can finish rather than being killed mid-request and leaving an unknown outcome receipt.

The Dockerfile builds one image for every role, which is a neat way to keep the setup, API, worker and web entry points in sync. It installs `postgresql-client` for the optional backups, runs as the non-root `node` user, exposes 3000 and defaults to `apps/web/server.ts`. It also takes an `NPM_REGISTRY` build argument for installs behind a mirror.

The architecture documentation describes three processes with a small set of invariants, and `modules/` is the documented extension point for site-specific features that the framework does not ship, each with its own tests under `modules/*/tests/`.

What is exposed to readers, and to agents

The output side is broader than a typical news site, which is consistent with the AI topic tags and the stated intent of serving agents as well as people. The public surface includes RSS for selection, everything, full text, and each edition type, a public API, MCP, an Agent Markdown view, and `llms.txt`. The `/agent` page hands out the connection details, agents that can only read web pages should start at `/api/v1/agent`, and the interface description sits at `/openapi-v1.json`.

Editions are scheduled rather than generated on demand. The daily edition defaults to 08:00 and is assembled by rule: one item per event, follow-ups only when there is genuine new development, and no model call for the assembly step. Weekly and monthly editions compile from the daily output, with the model writing only the summary and section guides, defaulting to Monday at 10:00 and the first of the month at 10:30. The times live in `EDITION_TIMES` in `site/site.ts`.

There are also topic pages for companies, directions and content types, plus title and summary search alongside full-text relevance search. The admin side covers source management with a trial fetch, content diagnostics, selection evaluation, per-step model assignment, budget circuit breakers for paid services, and run records with alerts.

The site describes itself in English-facing terms in its topics, including `mcp` and `self-hosted`, and carries a Chinese-language README with an English one alongside it. The last push of 2026-10-06 came with only 5 open issues, which for a project this size suggests a small, steady maintainer rather than a broad support queue.

Editorial conclusion

AIHOT is unusual in how little of its behaviour is hardcoded. The prompts live as Markdown in `industry/prompts/`, the thresholds in `industry/selection.ts`, the site name and edition times in `site/site.ts`, and the source list in `industry/sources.json`, so adapting it to a different industry is configuration work rather than a fork. The two things to weigh before adopting it are that the maintainer describes the code as AI-assisted and asks for patience on issues, and that the shipped demo sources are eighteen public AI news feeds that exist to prove the pipeline runs, not to be useful to you. Start by running the Docker stack, then spend your first real effort in `docs/selection.md` calibrating the scoring prompt against a hundred or two of your own labelled items.

Frequently asked questions

What does AIHOT do and what kind of project is it?

It is a self-hosted engine for an industry news site. It pulls from RSS, web listings, JSON endpoints, X accounts and WeChat public accounts, filters and scores what comes in with a language model, clusters reporting of the same event, ranks events by how many independent sources discuss them, and publishes a daily edition with weekly and monthly compilations.

How do I change the news selection criteria for my own industry?

The prompts live as Markdown under `industry/prompts/` and the numeric thresholds in `industry/selection.ts`, so the criteria are edited without changing code. The README points at `industry/prompts/selection-score.md` as the highest-value file, and `docs/selection.md` describes calibrating it against a hundred or two of items you have labelled yourself using `scripts/eval-selection.ts`.

Which model providers does AIHOT support?

Any OpenAI-compatible API. The setup script defaults to DeepSeek, and the `.env.example` gives worked examples for Qwen and Zhipu through `LLM_BASE_URL`, `LLM_MODEL` and `LLM_EXTRA_JSON`. Individual pipeline steps can be pointed at different providers with the per-step variables such as `SCORE_MODEL` and `GROUP_REVIEW_MODEL`.

Why do I need an embedding service for good event grouping?

Without one, grouping falls back to text overlap to find candidates, and discussion posts that mainly count as hotness signals mostly fail to attach to an event, which pushes the hotness ranking low. Configure `EMBEDDING_BASE_URL`, `EMBEDDING_API_KEY` and `EMBEDDING_MODEL`, or supply a DashScope key to use `text-embedding-v4`.

Official sources

  1. Issues
  2. KKKKhazix/AIHOT on GitHub
  3. License: MIT
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/kkkkhazix-aihot.svg)](https://hysenlabs.com/projects/kkkkhazix-aihot)