Обновить
16K+
5

Пользователь

7
Рейтинг
Отправить сообщение

Агрегатор LLM, как выбирать живые free-модели и переживать сбои провайдера

Время на прочтение7 мин
Охват и читатели11K

Если в проекте появляется выбор LLM, почти сразу возникает соблазн сделать это как можно проще. Взять один большой список моделей, показать его в интерфейсе, выбрать первую free-модель по умолчанию и считать задачу закрытой. На короткой дистанции это выглядит рабочим вариантом. На длинной начинает ломаться сразу в нескольких местах.

Часть моделей числится бесплатными, но отвечает нестабильно. Часть внезапно исчезает из выдачи провайдера. Часть формально жива, но по качеству ответа годится только для демо. Иногда пользователь выбрал одну модель, а провайдер вернул ошибку. Иногда ответ пришел, но уже от другой модели. Иногда список моделей на фронте устарел, а backend уже живет в другой реальности.

То есть проблема тут не в том, как красиво показать список LLM. Проблема в том, как построить агрегатор, который умеет выбирать живые free-модели, переживать сбои провайдера и не врать интерфейсу о том, какая модель реально ответила.

В одном из своих проектов эта задача решалась не через бесконечный каталог моделей, а через более жесткий инженерный контур. Backend получает сырой список моделей от провайдера, очищает его, отбирает только подходящие free-варианты, оставляет по одной модели на бренд, отдает этот набор на фронт, а во время реального запроса умеет сделать fallback на модель другого бренда. При этом в ответе возвращается не только текст, но и actual_model, чтобы интерфейс знал, кто реально сгенерировал результат.

Читать далее

Кэширование в Next.js App Router, как увидеть, почему данные не обновились

Время на прочтение9 мин
Охват и читатели8.2K

С кэшированием в Next.js обычно случается одна и та же история. API уже отдаёт новые данные, страница открывается заново, а на экране всё ещё старая версия. После этого в код быстро добавляют cache: "no-store", данные начинают запрашиваться на каждый заход, и через пару минут появляется уже другой вопрос - зачем тогда вообще нужен встроенный механизм кэширования.

Проблема в том, что кэширование обычно звучит как одно явление, а на практике в App Router похожие ощущения могут давать разные уровни поведения. Навигация назад и вперёд может переиспользовать клиентский кэш маршрута, сам маршрут может рендериться по-разному, а серверный fetch в Next.js имеет собственные стратегии кэширования и перевалидации. В актуальной документации это уже разделено на новый режим с Cache Components и на прежнюю модель без них. В этой статье речь именно о привычной модели App Router без Cache Components, где поведение обычно задаётся через fetch, cache, next.revalidate и route segment config. (Next.js)

Полезнее всего разбирать такую тему не с теории, а с наблюдения. Не с вопроса как устроены все слои кэша в Next.js, а с вопроса почему на одном и том же маршруте иногда обновляется рендер страницы, а иногда обновляются данные, и это не всегда одно и то же.

Для примеров ниже используется проект Goods Finder и внешний API DummyJSON. Идея - сначала добавить на страницу штамп серверного рендера, потом отдельно показать момент получения данных, а уже после этого сравнить force-cache, no-store и revalidate.

Читать далее

Формы как контракт в Next.js: Zod, fieldErrors и одинаковые правила на client и server

Время на прочтение8 мин
Охват и читатели5.3K

С формами в Next.js проблема обычно начинается не на уровне кнопки submit. Кнопка как раз почти всегда работает. Настоящая путаница начинается позже, когда форма уже живёт в проекте какое-то время. В одном месте ошибка показывается под полем, в другом только общей строкой сверху. Где-то кнопка блокируется на pending, а где-то можно отправить запрос несколько раз подряд. Клиент считает данные валидными, а сервер отвечает, что правило нарушено. Поле уже зелёное, а сохранение всё равно не прошло. В этот момент становится видно, что форма была собрана как кусок UI, а не как контракт.

Используем как примеры паттерны из проекта Workbench. Полезно смотреть на форму не как на набор input и submit, а как на договор между UI, валидацией и местом записи данных. У такого договора есть простая форма - какие данные считаются допустимыми, где и как они проверяются, в каком виде ошибка возвращается в интерфейс, что происходит на pending, когда форма блокируется, что считается успехом, а что общей ошибкой, не привязанной к конкретному полю.

Как только форма описывается так, код перестаёт расползаться. И здесь Zod в Next.js даёт не просто удобную схему, а способ удерживать client и server в одном наборе правил.

Читать далее

NextAuth + Django JWT без второй авторизации и ручного хаоса токенов

Уровень сложностиСредний
Время на прочтение11 мин
Охват и читатели5.6K

Во многих fullstack-проектах на Next.js и Django авторизация разваливается в одном и том же месте. На фронте удобно использовать NextAuth, потому что он закрывает формы входа, OAuth, серверную сессию и клиентские хуки. На бэкенде хочется иметь обычный JWT-контур на Django REST Framework, чтобы защищать API, работать с access и refresh токенами и не привязывать бизнес-логику к фронту. В итоге часто получается неприятная схема: пользователь логинится через NextAuth, потом отдельно логинится в Django, потом где-то вручную перекладываются токены, а через пару недель вся эта связка начинает ломаться на refresh, logout и OAuth.

Что делаем. Пользователь проходит один вход на фронте, а дальше фронт уже работает с токенами Django как с единственным источником доступа к API. Без второй формы входа, без ручного хранения access token в localStorage, без отдельного костыля под Google OAuth.

Разберем рабочую схему, в которой NextAuth отвечает за пользовательскую сессию на фронте, а Django остается владельцем API-авторизации и выдает JWT. На credentials-входе NextAuth сразу получает access и refresh от Django. На Google OAuth фронт сначала пускает пользователя через провайдера, потом синхронизирует его с Django и тоже получает пару токенов. После этого все запросы идут через один axios-клиент, который сам подставляет access token, сам обновляет его через refresh и сам завершает сессию, если refresh уже недействителен.

Читать далее

TypeScript в Next.js как система контрактов, а не типизация ради типизации

Уровень сложностиПростой
Время на прочтение8 мин
Охват и читатели5.1K

Когда разработчик начинает писать на Next.js с TypeScript, первая реакция часто довольно холодная. Вместо того чтобы двигаться быстрее, он начинает чаще видеть ошибки. Где-то не совпал shape объекта, где-то строка не подходит в более узкий тип, где-то TypeScript напоминает, что значение может быть undefined. На этом месте легко сделать неправильный вывод. Кажется, что TS просто добавляет трение и требует больше служебного кода.

Обычно проблема не в TypeScript, а в способе мышления. Если использовать его как набор аннотаций поверх уже написанного кода, пользы действительно немного. Но если смотреть на типы как на систему контрактов между слоями приложения, картина меняется. Особенно в Next.js App Router, где у нас постоянно есть границы server и client, внешний ввод из URL, формы, мутации и разные состояния интерфейса.

В этот момент TypeScript перестаёт быть типизацией ради типизации. Он начинает отвечать на более важный вопрос: какие состояния в проекте вообще допустимы, а какие не должны пройти дальше границы. По такой модели я выстроил один из своих проектов Workbench. Не начинать с мысли давайте везде поставим типы, а начинать с мысли где у нас проходит граница, что в неё входит и что из неё может выйти. После этого многие решения в коде становятся почти очевидными.

Читать далее

URL как источник правды в Next.js App Router

Уровень сложностиПростой
Время на прочтение8 мин
Охват и читатели6.3K

Когда разработчик приходит в Next.js из обычного React SPA, он часто тащит с собой старую схему мышления. Есть поле ввода, значит будет useState. Есть поиск, значит будет useEffect. Есть список данных, значит будем следить за изменением состояния и вручную запускать новый запрос.

На маленьком экране это вроде работает. Но очень быстро выясняется, что в приложении уже не одно состояние, а три. Есть значение в поле, значение в URL, данные, загруженные по одному из этих значений. Потом появляется четвёртая проблема. Кнопки Back и Forward начинают вести себя странно. Ссылкой на результат поиска неудобно делиться. А отладка превращается в угадайку, потому что не до конца понятно, что именно сейчас считается главным источником правды.

В App Router это решается проще. Если фильтр является частью состояния страницы, его логично держать в URL. Тогда схема становится прямой: URL изменился -> сервер прочитал searchParams -> выполнил fetch -> отрендерил новый список. В этот момент Next.js начинает восприниматься как понятный инженерный инструмент.

Читать далее

Метрика на ключевое событие в MVP без тяжёлой аналитики

Уровень сложностиПростой
Время на прочтение6 мин
Охват и читатели5.2K

При запуске MVP считаем вначале не клики вообще, а деньги и время. Деньги потому, что до серьёзных вложений полезно быстро и по возможности бесплатно проверить, нужен ли проект рынку. Время потому, что его легко потратить не на сам MVP, а на подключение Яндекс.Метрики, Google Analytics, событий, воронок, отдельной базы и прочей обвязки. В итоге идея ещё не проверена, а вокруг неё уже начинает расти аналитическая система.

Рассмотрим простую схему с 1-2 быстрыми метрики, которые напрямую проверяют УТП или главный пользовательский сценарий. Пользователь нажал кнопку покупки. Начал создавать проект. Зарегистрировался. Перешёл в Telegram. Этого уже хватает, чтобы понять, работает ли сценарий и есть ли живой отклик.

Получаем сразу три плюса. Бесплатно проверяем гипотезу, экономим время на старте и делаем один универсальный инструмент, который потом можно использовать для любого количества своих MVP без новых подключений и переделок.

Разберем именно такой вариант. Маленький Django-бэк один раз деплоится на простом хостинге, принимает события через пиксель, хранит их в SQLite и отдаёт статистику JSON-ответом. Дальше во всех новых фронтах меняются только названия event и src.

Особенно удобно это в тех случаях, когда фронт живёт на бесплатном или засыпающем хостинге. У free web services на Render сервис уходит в spin-down после 15 минут простоя, а файловая система там ephemeral, поэтому локальный SQLite для таких счётчиков работать не будет. В качестве простого примера отдельного маленького бэка можно использовать PythonAnywhere, где есть бесплатный аккаунт с одним web app. Но сама идея не привязана к этим площадкам и повторяется практически где угодно.

Читать далее

Как собрать платный AI-микро-SaaS (Next.js + Django + ЮKassa + Web Stories) и не застрять в пет-проекте

Уровень сложностиСредний
Время на прочтение8 мин
Охват и читатели12K

Большинство наших «проектов мечты» умирают не потому, что идея плохая, а потому что мы останавливаемся на уровне «ну вот, фронт есть, бэк вроде тоже, как-нибудь допилю оплаты и выложу». Не допиливаем. Потому что платежи, вебхуки, витрина, SEO, публикации — это уже не «интересный код», а «организационная скука».

Проект как раз про то, чтобы скучное сделать готовым и многоразовым. Мы один раз собираем связку: AI → Django/DRF → ЮKassa → деплой → Web Stories → SEO, а дальше в неё можно подставлять вашу идею — не только Mermaid. Mermaid здесь как манекен: на нём удобно показывать, куда вешать оплату, куда прикручивать экспорт, где пускать трафик.

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

Читать далее

Информация

В рейтинге
872-й
Зарегистрирован
Активность