// статьи / статья
#статья #проекты#github#readme#демо

> Как показывать проекты: README, демо и скриншоты

GitHub-интеграция, нормализация README, интерактивные демо вроде GLSSH и InINetWin.

SkilinPur 25.10.2026 4 мин чтения серия: как это устроено 👁
Как показывать проекты: README, демо и скриншоты

Проект — это не только карточка с названием. Это README, скриншоты, демо и ссылка на код. Чем меньше человеку нужно додумывать, тем лучше.

Страница проекта

Сначала проекты были карточками на главной. Потом появилась страница /project/?id=N: описание, теги, скриншоты, README, ссылки.

Карточка отвечает на вопрос «что это?». Страница — на вопрос «как это устроено и где попробовать?».

На странице есть:

  • название, иконка, язык;
  • краткое описание;
  • теги;
  • ссылка на репозиторий и демо;
  • скриншоты;
  • README, подтянутый с GitHub;
  • статистика: звёзды, форки, обновления;
  • кнопка «Попробовать», если есть демо.

Проекты бывают разные: игра, утилита, сайт, форк. Универсального шаблона нет, но общий каркас работает.

GitHub без ручного копирования

README хранится в GitHub. Дублировать его в базе — значит забыть обновить. Поэтому страница тянет README из репозитория и нормализует.

Что делает нормализация:

  • убирает бейджи и лишнюю HTML-разметку;
  • превращает относительные ссылки в абсолютные;
  • подставляет raw.githubusercontent.com для картинок;
  • форматирует заголовки, списки, таблицы;
  • экранирует опасный HTML;
  • для терминальной темы делает ASCII-версию.

Для HTML используется marked + DOMPurify. Для терминала — свой readme-format.js: заголовки, списки, таблицы, код, ссылки.

Это не идеальный парсер Markdown. Но он позволяет показать README, не копируя его вручную.

Урок: если данные уже есть в GitHub, не надо делать их вторую копию. Надо научиться их показывать.

Кэш репозиториев

GitHub API имеет лимиты. Если дёргать его на каждый запрос, можно получить 403. Поэтому есть кэш:

code/repos-cache.json

Он обновляется периодически и при изменениях. Если GitHub недоступен, показываем кэш.

Грабля: когда добавили нового участника, его репозитории не появились, потому что кэш был старый. Пришлось сбрасывать repos-cache.json вручную.

Урок: кэш — это хорошо, но у него должен быть способ сброса. Особенно когда появляются новые данные.

Форки

Не все форки очевидны. GitHub может не помечать репозиторий как форк, если он был создан иначе. Поэтому есть ручной список $forkParents:

  • SkilinPur/zapret-GUI → Sergeydigl3/zapret-discord-youtube-linux;
  • SkilinPur/zapret-GUI-Windows → Flowseal/zapret-discord-youtube.

Бейдж «⑂ форк» ведёт на оригинал. Это честно: читатель видит, что проект не с нуля.

Урок: если платформа не даёт нужный флаг, не ври. Добавь ручную пометку.

Демо

Кнопка «Попробовать» ведёт на демо-страницу в components/:

  • glssh.html — симуляция SSH;
  • ininet.html — TUI и CLI для сети;
  • steam-gen.html, tt-saver.html — другие проекты.

Демо открывается в новой вкладке. demo_url хранится абсолютным (/components/...), иначе на /project/ относительный путь ломается.

Сначала кнопка «Назад к проектам» вела на /#projects. Если демо открыто в новой вкладке, это выглядело как «сайт открылся в новой вкладке». Сделали demo-back.js: если демо открыто с сайта, вкладка закрывается; если напрямую — ведёт на страницу проекта.

Урок: демо — это отдельный сценарий. Продумай, как из него выйти.

Честность демо

Была история с GLSSH. Сначала демо было красивым, с CRT-эффектом и выдуманными фичами. Выглядело эффектно, но не соответствовало проекту.

Потом переделали по реальному репозиторию: реальные команды, реальные события, реальный сценарий. Стало менее «киношно», но честно.

Урок: демо должно показывать продукт, а не рекламный ролик. Если фичи нет — не рисуй её.

Скриншоты

Скриншоты — это не украшение. Они:

  • показывают интерфейс;
  • дают представление о масштабе;
  • работают в OG-карточках;
  • помогают, если демо недоступно.

Я делаю скриншоты вручную или через Playwright, кладу в uploads/, привязываю к проекту. Для профилей есть OG-картинки, для статей — обложки.

Урок: скриншот стареет быстрее кода. Если интерфейс изменился, обнови картинку.

Где были грабли

README затёрли тестом

Тестировал обработчик через CLI, передал readme => 'x'. Он сохранил. README проекта GLSSH превратился в x. Восстанавливали из бэкапа.

Урок: тест, который пишет в базу, — это не тест, а изменение. Для проверок — отдельная запись или снапшот.

Форки скрывались

Сначала форки не показывались на /code/. Потом решили показывать, но с пометкой. Это изменило логику списка: теперь форк — не «мусор», а часть портфолио.

Урок: «скрыть» — это решение, а не свойство. Если передумал, придётся менять не только фильтр, но и текст.

README в модалке и PJAX

Модалки README лежали вне <main>, после скриптов. PJAX их ломал. От PJAX отказались, но урок остался: структура страницы важна.

Урок: перед тем как «оптимизировать переходы», проверь, где живут модалки.

Что бы улучшил

  • Автоматическое обновление README по webhook или cron.
  • Нормальный Markdown-парсер с подсветкой кода.
  • Галерею скриншотов с лайтбоксом.
  • Проверку ссылок на демо.
  • Кэш с TTL и ручным сбросом в админке.
  • Больше демо, которые работают без сервера.

Вместо вывода

Показывать проекты — это не «сделать красивую карточку». Это собрать историю: что это, зачем, как выглядит, где код, где попробовать.

Если человеку нужно открывать GitHub, чтобы понять проект, — страница недоделана. Если демо врёт — лучше его не показывать. Если README устарел — обнови, а не прячь.

Проект — это продукт. Показывай его как продукт.

// реакции
SkilinPurучастник InIProject