尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证AI-агрегатор новостей: RSS с 30+ изданий → саммари на русском через Gemini/Groq → дедупликация одинаковых новостей по эмбеддингам, Next.js фронтенд
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗Агрегатор: RSS 63 изданий → пересказ на русском → одна карточка на новость, сколько бы изданий о ней ни писали → треды для продолжающихся историй. Лента одной колонкой в духе редакторских журналов.
Продакшен: сайт на Vercel (dub1), база Supabase Postgres с pgvector (eu-west-1), сбор в GitHub Actions. Состояние каждого издания — в ../issues.md.
npm install
cp .env.example .env # заполнить переменные из таблицы ниже
npm run db:init # схема БД и издания из конфига
npm run fetch # собрать новости за последние сутки
npm run dev # http://localhost:3000
| Переменная | Где | Что |
|---|---|---|
DATABASE_URL | сайт, сбор | Postgres с pgvector |
RP_ORIGIN | сайт | адрес сайта для ссылок в превью |
SESSION_SECRET | сайт | проверка старых кук входа — до 24 января 2027 (см. src/lib/viewer.ts) |
THREADS_VIEW | сайт | 1 — лента с тредами (включено на проде; на preview-выкладках всегда) |
GEMINI_API_KEYS | сбор | ключи Google AI Studio через запятую, у каждого своя бесплатная квота |
GEMINI_MODELS | сбор | модели через запятую, в порядке перебора |
GROQ_API_KEY | сбор | запасная модель |
RETENTION_DAYS | сбор | сколько дней хранить статьи (7) |
DEDUPE_THRESHOLD | сбор | порог склейки по тексту (0.75) |
Для ручных прогонов: FETCH_SOURCES="Dezeen,Esquire" — только эти издания, FETCH_SINCE_DAYS=1 — окно на сутки шире, FETCH_LIMIT=N — не больше N статей, THREADS_SHADOW=0 — без раскладки по тредам.
После первого прогона с диагностикой сбор автоматически проверяет неизвестные ссылки за последние 72 часа, чтобы подхватывать запоздалые элементы RSS. Внутри каждого фида сначала идут статьи за последние сутки; догрузка ограничена 10 попытками на издание (суммарно для всех его фидов) и 50 на прогон. Лимиты применяются и к неудачным попыткам, чтобы не расходовать квоту на бесконечные повторы. Уже известные и окончательно отклонённые ссылки пропускаются. Ручной FETCH_SINCE_DAYS сохраняет прежнее поведение и не ограничивается бюджетом автоматической догрузки. Для Fast Company исходные ISO-даты без зоны явно трактуются как UTC через feedDateOffset в конфиге.
Каждый обработанный фид оставляет строку SOURCE_DIAGNOSTIC в логе: HTTP-статус, тип ответа, возраст CDN-кэша, SHA-256 RSS, свежесть элементов, число известных/сохранённых/отложенных ссылок, причины исключения и ошибки. При аномалии сохраняется снимок до 10 элементов с заголовками, ссылками, исходными датами и решениями — без полного текста RSS или дополнительных запросов к изданию. В GitHub запись содержит workflowRunId. Диагностика сохраняется одной пачкой за прогон в source_fetch_diagnostics; суточные счётчики по Москве — в source_volume_daily. Обе истории живут 56 дней независимо от очистки статей. Новые таблицы создаются db:init или автоматически при первом сборе из db/fetch-diagnostics.sql; ошибка диагностики выводится в лог и не останавливает сбор.
src/jobs/fetchAndProcess.ts)Запуск — каждые 30 минут через cron-job.org, который вызывает workflow_dispatch у .github/workflows/fetch-cron.yml; расписание в самом workflow — запасное. Прогон идёт 1–10 минут.
src/lib/adFilter.ts и правила издания), лайв-блоги и виды материалов, заданные в конфиге издания (src/config/sources.ts).src/lib/ogTags.ts). Текст — селектор издания, JSON-LD или абзацы страницы; у части изданий — сразу из RSS. Галерея — по правилам GALLERY_SITES для движка издания. Страницы NYT, WSJ и Bloomberg закрыты всегда и не запрашиваются; если страница закрыта, карточка строится по RSS.src/lib/embeddings.ts) — локально, Xenova/all-MiniLM-L6-v2: вектор заголовка с текстом и отдельно заголовка. Считаются от оригинала: пересказ стирает различия между похожими новостями.src/lib/grouping.ts). Статья сравнивается с первыми статьями карточек за 24 часа: первые 12 часов — по тексту или заголовку, дальше — только другие издания и строже. Запасные правила: парный материал издания, одновременные новости, общее имя в заголовке, одна и та же обложка.src/lib/summarizer.ts, промпты — src/lib/prompt.ts). Один запрос: главное, продолжение под «Читать» (если текста хватает) и до двух тем. Спорт и shopping в ленту не идут. Статья, приклеенная к готовой карточке, к модели не идёт.visible_at); статьи старше RETENTION_DAYS удаляются вместе с карточкой.src/lib/threads.ts). Новые карточки сравниваются с карточками за 72 часа (похожий заголовок или редкое имя в пересказе); модель решает, продолжение ли это той же истории, и пишет, что нового. Тред — одно событие и его прямые последствия, не больше 6 карточек; похожие треды модель сверяет и сливает. Ручные решения «не в этот тред» хранятся в thread_exclusions.Модели. Gemini (src/lib/gemini.ts) перебирает пары модель+ключ: при 429 — следующий ключ, при перегрузке — другая модель; последняя удачная пара запоминается в .gemini-state.json. Если Gemini недоступен везде — минута паузы, затем 3 минуты на Groq (суточный лимит 200 тыс. токенов, общий для всех прогонов). Кончились оба — прогон останавливается.
Отчёт о состоянии (src/jobs/healthReport.ts, DIS-81) — каждый день в Telegram: его отправляет первый прогон сбора после 10:00 по Москве (шаг в fetch-cron.yml, метка в кэше — раз в сутки; расписание GitHub пропускало запуски), вручную — health-report.yml (TELEGRAM_BOT_TOKEN, TELEGRAM_CHAT_ID в секретах GitHub). Ошибки сбора, RSS и обработки проверяются за последние сутки; объём статей, обложки, галереи и «Читать» — за предыдущий полный день по Москве. Для объёма используются два и более предыдущих таких же дня недели либо минимум три сопоставимых будних/выходных дня; пока истории недостаточно, отчёт это указывает. Отсутствие свежих публикаций в RSS само по себе не считается технической ошибкой: такие наблюдения перечисляются отдельно. Повторный отказ RSS, пустой фид, нераспознанные даты и сбой обработки различаются. Длинный отчёт разделяется на сообщения по границам строк. --dry не отправляет Telegram-сообщения и не изменяет БД.
app/)app/page.tsx, FeedList.tsx, FeedCard.tsx; данные — src/lib/feed.ts, JSON — GET /api/feed. Рубрики, вкладки «Новые» и «Прочитанные», плашка «N Новых», открытие с места, где читатель остановился. Карточка становится прочитанной через 2,5 секунды на экране.src/lib/imageHash.ts)./post/<номер статьи> с превью для мессенджеров./source/<слаг> (DIS-80): все карточки, где есть его статья, без вкладок и тредов; открывается по иконке издания в карточке.--chrome-offset, MobileChrome.tsx).app/manifest.ts) — с экрана «Домой» открывается на весь экран; viewport-fit=cover и отступы env(safe-area-inset-*); цвет статус-бара по теме (theme-color, theme.ts); без серой вспышки при тапе, :hover только при мыши, отклик на нажатие и запрет выделения у кнопок (globals.css)./api/image-proxy (только адреса из базы, до 15 МБ); если прокси не справился, браузер грузит напрямую.middleware.ts выдаёт куку yoten_browser со случайным номером на 400 дней, прочитанное и выключенные издания хранятся в базе под его хешем (src/lib/viewer.ts). Строка в users заводится при первой отметке или переключателе; браузеры, не заходившие год, удаляются при сборе./settings), тема и размер текста (/settings/display).| Команда | Что делает |
|---|---|
npm run fetch | сбор |
npm run threads | разложить по тредам непроверенные карточки (THREADS_SINCE_HOURS, по умолчанию 24) |
npm run db:init | применить db/schema.sql и добавить издания из конфига |
npm run favicons | скачать иконки новых изданий (-- --force — все заново) |
npm run feed | вывести ленту в консоль |
npm run health | отчёт о состоянии в Telegram (-- --dry — только напечатать) |
npm run dev / build / start | сайт |