← Все проекты

Карточка профиля одной картинкой

Вводите имя пользователя на GitHub, Twitch или в Telegram — получаете аккуратную PNG-карточку со статистикой: подписчики, репозитории, звёзды, «зелёные квадратики» вкладов, языки, стрим и последний пост канала. Оформление настраивается целиком: темы, градиенты, скругления, шрифты, форма аватара и список видимых блоков. Ничего устанавливать не надо, регистрации нет, картинка собирается прямо в браузере.

  • 3 сети
  • PNG до 2400 px
  • Без регистрации
  • MIT
  • 3сети в одном интерфейсе
  • 2400пикселей по ширине на 3×
  • 0аккаунтов и установок
  • 5 минкэш — повтор ничего не стоит

// попробуйте прямо здесь

Соберите карточку прямо на этой странице

Ровно те ручки, с которых начинают в самом генераторе. Выключайте блоки — карточка ужимается по высоте, как и настоящая. Данные здесь образцовые; в приложении на их месте будет живой профиль.

Сеть
Тема
Аватар
Блоки карточки
Выгрузка
Bormotoon @Bormotoon Пишет инструменты, которые считают локально GitHub

    card.png · ширина 2400 px · 3 блока · высота — по содержимому

    В генераторе к этому добавляются градиенты под своим углом, три шрифта, скругление самой карточки, переключатель каждого поля по отдельности и настоящая кнопка «Скачать PNG».

    // источники

    Три сети, три разных набора данных

    Каждая отдаёт своё, и карточка подстраивается: лишние блоки просто не рисуются, а высота ужимается под включённые. Щёлкните по колонке, чтобы разглядеть одну сеть.

    Таблица прокручивается вбок →

    Что попадает в карточку
    • Аватар, имя, ник
    • Описание профиля через официальный Helix
    • Подписчики
    • Числовая статистика репозитории, звёзды, форки, гисты, год зрители и аптайм
    • График вкладов и стрики
    • Языковая полоса
    • Ачивки и метки Pro, GitHub Star, множители Партнёр / Компаньон канал, группа, бот
    • Организации
    • Блок репозиториев пины, топ по звёздам или свой список
    • Эфир: LIVE, зрители, игра
    • Баннер обложкой или фоном только offline-заставка
    • Последний пост текст, дата, просмотры, фото
    • Привязанный канал юзернейм вводится руками

    Чего здесь честно нет. Публичный API Twitch отдаёт только offline-баннер: шапку-«обложку» из профиля знает лишь неофициальный API, и мы им не пользуемся. Привязку канала к пользователю Telegram публичная страница t.me тоже не раскрывает — юзернейм канала вводится руками. Значок «~» в таблице стоит ровно там, где данные приходят с такой оговоркой.

    // устройство

    Работу делает ваш браузер

    Главное решение здесь такое: всё, что отдаёт заголовок CORS, браузер забирает сам, минуя наш сервер. Это не экономия на хостинге — это то, почему сервису не нужен ни один ключ.

    1. Ваш браузер api.github.com профиль, репозитории, организации CORS: *
    2. Ваш браузер CDN картинок аватарки, ачивки, баннеры — сразу в data-URL CORS: *
    3. Наш сервер github.com · t.me календарь вкладов, ачивки и весь Telegram CORS нет

    Два потока из трёх идут мимо нас. Лимит GitHub — 60 запросов в час — тратится с вашего адреса, а не с общего на всех посетителей.

    • график вкладов
    • ачивки и метки
    • Telegram целиком
    что видно во вкладке «Сеть»
    # одна карточка GitHub целиком
    GET api.github.com/users/torvalds       → браузер, без токена
    GET api.github.com/users/torvalds/repos → браузер
    GET avatars.githubusercontent.com/…  → браузер, CORS *
    GET /api/github/torvalds              → наш сервер: только календарь и ачивки
    
    # сервер лежит? карточка всё равно соберётся — просто без квадратиков
    GET /healthz                          {"ok":true}

    // публичный деплой

    Ни одного ключа и почти ничего о вас

    Сервис не хранит токенов — их попросту нечему утекать. А то немногое, что всё же уходит с нашего адреса, обложено защитой: скрейпинг чужих страниц — ровно то, за что банят по IP.

    • Токен GitHub не нуженREST API дёргает ваш браузер, и лимит 60 в час — ваш личный, а не общий на всех посетителей
    • Наружу не уходит ни одного ключаотдельный тест следит, чтобы с сервера никогда не ушёл заголовок Authorization
    • Кэш на 5 минутповторная загрузка того же профиля не стоит ничего
    • Кэш хранит промис, а не значениедесять одновременных запросов на холодный ключ дают ОДИН поход наверх, а не десять
    • 30 запросов / 5 мин на адресчеловеку хватает с запасом, перебору по чужим никам — нет
    • Таймаут 8 секунд наружузависший чужой сервер не держит наш сокет вечно
    48 тестов на node:test — без единой новой зависимости — плюс сквозной прогон в браузере до настоящей выгрузки PNG. Отдельно закрыты разборщики чужой вёрстки: GitHub и Telegram меняют разметку молча, и карточка тогда теряет блок без всякой ошибки. Тест ловит это раньше пользователя.

    // о проекте

    Зачем вообще карточка картинкой

    Картинка едет туда, куда не едет виджет

    Статистику профиля показывают десятком способов: динамические бейджи в README, виджеты для сайта, встраиваемые ифреймы. Все они живут только там, где есть браузер и разрешена подгрузка со стороннего домена. Как только карточка нужна в презентации, в резюме в формате PDF, в шапке telegram-канала или просто в чате — виджет не подходит, а скриншот куска страницы выглядит именно скриншотом: чужие поля, обрезанные края, случайный масштаб.

    PNG снимает этот вопрос целиком. Файл лежит у вас, ничего не запрашивает при показе, не протухает вместе с чужим сервисом и одинаково выглядит в любом просмотрщике. Обратная сторона честная: картинка не обновляется сама. Поэтому генератор и сделан так, чтобы пересобрать её заново стоило полминуты — ник уже введён, оформление помнится, остаётся нажать «скачать».

    Почему PNG собирается в браузере, а не на сервере

    Обычный путь для такого сервиса — рисовать картинку на сервере: headless-браузер или библиотека вроде sharp собирают PNG и отдают его ссылкой. Это удобно ровно до момента публичного запуска: рендер стоит памяти и процессорного времени, а карточка — вещь, которую легко попросить тысячу раз подряд, просто перебирая чужие ники в адресной строке.

    Здесь холст рисуется у вас в браузере, и повторить его тысячу раз можно только за свой счёт. Сервер остаётся тонким: он ходит лишь туда, куда браузеру не пускает политика домена, — за календарём вкладов на github.com и за всем Telegram. Отсюда и вся конструкция: кэш на пять минут, лимит на адрес, таймаут наружу. Не потому что «так принято», а потому что это единственные три места, где чужой запрос вообще может нам чего-то стоить.

    Что оказалось сложным

    Главная засада была не в API, а в холсте. Библиотека, снимающая PNG с вёрстки, отказывается работать, если внутри есть картинка с чужого домена без разрешающего заголовка: холст считается «испорченным», и выгрузка молча падает. Классическое лечение — гонять все картинки через свой прокси, и первая версия так и делала, вместе с белым списком доменов и защитой от подсунутого SVG.

    Прокси оказался не нужен: все CDN, из которых берутся аватарки, ачивки и баннеры, отдают Access-Control-Allow-Origin: *. Вместо проксирования картинки вплавляются в data-URL до отрисовки — к моменту снимка в разметке уже нет ни одной внешней ссылки, и холст чист при любом кэше и редиректе. Вместе с прокси из проекта уехал и токен GitHub: раз запросы делает браузер посетителя, лимит считается на его адрес, и хранить на сервере нечего.

    Своя карточка — за полминуты

    Ник, тема, кнопка «скачать». Картинка годится в шапку профиля, в презентацию, в резюме или просто в чат — хвастаться стриком.

    Поддержать автораИнструмент бесплатный и без рекламы. Если пригодился — купите кофе.donationalerts.com/r/bormotoon