chetaika.md 24.06.2026

Chetaika. Книжный поисковик

Книжный поисковик поверх Google Books API: один HTML-файл, два serverless-прокси и чистый vanilla JS без зависимостей.

Задача

Сделать рабочий поисковик книг поверх Google Books API. Сложность не в запросах, а в том, что API отдаёт данные как попало: обложки по http://, рейтинги без возможности фильтрации, totalItems, который считает не всё, и молчаливый игнор maxResults больше 40.

Как делал

Два serverless-хендлера проксируют Google Books и держат ключ в переменной окружения, а не в браузере. Ответ отдаётся с s-maxage=600, stale-while-revalidate=1200 — платформа кэширует его на 10 минут и ещё 20 отдаёт устаревшую копию, пока обновляется фоновая. Для книг это бесплатный обход лимитов.

Обложки приходят по http:// и с размытым zoom=3, поэтому нормализуются цепочкой замен. Приоритет у smallThumbnail парадоксальный: с zoom=1 она отдаёт ту же картинку, что и thumbnail, но весит меньше. Если ссылки нет — рендерится SVG-плейсхолдер с градиентом.

Поиск запускается не на каждую букву, а через 500 мс после последнего нажатия и только от трёх символов — иначе на «а», «аб», «абв» улетели бы три запроса, и последний ответ мог бы прийти раньше среднего.

Фильтр по рейтингу Google Books не поддерживает вообще, поэтому применяется на клиенте после ответа. Плата — пагинация врёт: totalItems обещает тысячи, а на экране после фильтра может остаться пять книг.

Звёзды рисуются из целой части и дробной: полная — fill="currentColor", половина — та же звезда с opacity="0.5", пустая — fill="none". Порог rating % 1 >= 0.5, потому что 4.5 должно дать половину, а 4.4 — уже нет, и простое округление вниз тут не подходит.

Кнопка «Показать полностью» появляется только если описание действительно обрезано, а проверка идёт в requestAnimationFrame: -webkit-line-clamp применяется после рендера, и сразу после вставки в DOM scrollHeight ещё равен clientHeight.

Итог

Три статических файла и два хендлера, ноль зависимостей: ни React, ни Tailwind, ни Axios — только fetch, CSS-переменные и localStorage. Вся кривая оболочки Google Books — разбор http:// в ссылках, фильтрация без поддержки на стороне API, кэш в заголовке и пересчёт вёрстки после смены display — закрыт на стороне фронтенда.

// похожие проекты

Ещё работы

// проект 2026
Скриншот главной страницы лединга AROMA

Aroma. Лендинг кофейни

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

// проект 2026
Скриншот главной страницы лендинга пекарни "круассан"

«Круассан». Лендинг для пекарни

Лендинг пекарни: меню выпечки, отзывы, контакты и форма заказа торта.

// проект 2026
Скриншот главной страницы лендинга DRIVE24

DRIVE24. Лендинг сервиса каршеринга

Лендинг сервиса каршеринга на WordPress + Elementor: тарифы, автопарк, инструкция, приложение, отзывы и форма заявки.

// проект 2026
Нет изображения

Бот для сбора лидов из Telegram-каналов и RSS

Бот для Telegram: читает каналы и RSS-ленты, фильтрует заказы по ключевым словам с весами и присылает подходящие в личку.

// проект 2026
Нет изображения

Telegram парсер участников каналов

Консольный инструмент на Telethon: инвентаризация участников Telegram-групп с чекпоинтами и обходом FloodWait.

// проект 2026
Скриншот главной страницы сайта ayupov

Ayupov. Сайт-портфолио

Сайт-портфолио на своей теме WordPress с нуля: живой терминал, скрамбл-заголовок, CSS одним ответом.

> все проекты

// contact.php

Ну что, работаем?

Опишите задачу — разберусь и предложу решение.