Заказчик развивает публичный видеохостинг на open-source платформе (Python/Django + React) и захотел собственную ленту коротких вертикальных видео — как Shorts: один экран — один ролик, бесконечная прокрутка, лайки, комментарии и шаринг прямо поверх видео.
Готового решения в платформе не было вообще — фичу нужно было спроектировать и построить с нуля, причём сразу на работающем продакшне с живыми пользователями. Отдельное требование появилось по ходу работы: лента должна крутиться по кругу бесконечно и без видимого «скачка» на границе списка — как в родных мобильных приложениях.
Построил отдельную страницу-ленту: один экран — один ролик, «прилипающая» прокрутка (scroll-snap), автовоспроизведение видимого ролика через IntersectionObserver, поверх видео — лайки, панель комментариев, шаринг, жалобы, редактирование и удаление своего ролика.
Самое сложное — бесконечная карусель без склеек. Классический путь (клонировать элементы по краям списка) даёт дубли видео, задвоенные просмотры и конфликтует со scroll-snap. Сделал иначе — кольцевой буфер: элемент с одного края ленты физически переезжает на другой, пока пользователь далеко от краёв. Ровно один DOM-элемент на ролик, ноль клонов.
Чтобы это работало на реальных устройствах, понадобились три неочевидных приёма: на время переноса снэп отключается и возвращается; отключена компенсация прокрутки браузером (overflow-anchor), иначе поправка применяется дважды; сама поправка позиции измеряется по фактическому положению якорного элемента, а не вычисляется из высот — дробные device-пиксели и «прыгающий» тулбар мобильного Safari ломают любую арифметику. Перестановки выполняются только когда лента остановилась.
Плюс интеграция в продукт: отдельный ряд портретных превью на главной, вертикальные видео исключены из обычных лент, SEO-разметка VideoObject на каждый ролик.
Бонусом на том же стеке (чистый JS, без фреймворка) сделал встроенный рекордер экрана: страница записи экрана/камеры прямо в браузере, обрезка записи, сворачивание в плавающее мини-окно (Document Picture-in-Picture) с адаптивным размером под реальные пропорции записи — записал и сразу загрузил на хостинг.
Стек: JavaScript (без фреймворка на этой странице), CSS scroll-snap, IntersectionObserver, Django, Docker.
Лента работает на продакшне с живыми пользователями: стык бесконечной прокрутки не виден ни на телефоне, ни на десктопе, просмотры не задваиваются, вертикальные ролики получили собственный раздел и разметку для поисковиков.
Живой результат можно посмотреть прямо сейчас: https://sawonce.com/shorts (и сам сайт — https://sawonce.com). Откройте с телефона и полистайте — это лучший способ оценить работу.