От идеи создания своего React‑проекта до столкновения с реальностью

Книжный тир-лист, SPA, боты и 55 запросов в месяц. Честная история пет-проекта: от «все обнимут меня» до пререндера и коллабораций с блогерами.

JavaScript-библиотека для создания интерфейсов

Книжный тир-лист, SPA, боты и 55 запросов в месяц. Честная история пет-проекта: от «все обнимут меня» до пререндера и коллабораций с блогерами.

В этой статье последовательно разобран полный цикл обновления React: от Virtual DOM до внутреннего устройства Fiber Reconciler.

React я использую совсем недавно и вообще я бэкенд разработчик, но жизнь завела меня во фронтенд. Получилось так, что времени на обучение и курсы у меня не было, пришлось обучаться прямо в процессе.
Мой принцип был "работает и ладно", но принципы нормального фронтенда явно отличались. Шишек я набила знатных с точки зрения чистоты и логики кода.
Это статья для таких же новичков, как я. Представляю вам сборник граблей, о которые я спотыкалась сама, и решений к этим граблям, которые родились после нескольких часов дебага и внимательного изучения документации (спустя пол года во фронтенде пора бы, да?)

Давай признаем, ты чуть ли не 90% кода пишешь с помощью клода, кодекса или еще какого агента. Ты выпускаешь несколько мр-ов в день, пушишь несколько тысяч строк кода, и быстро просматриваешь псевдо код на ревью, чтобы доказать самому себе, что это действительно ты напряг мозг и сделал задачу. Ты делаешь ровно то, что и всегда, думая, что агент просто ускоряет цикл разработки, который ты проводил ежедневно.
Однако не покидает ощущение, что это какой-то цирк. Ты просто осознанно повторяешь действия, которые раньше имели смысл, но в глубине души фрустрируешь от странности происходящего.

Optimistic update меняет клиентское состояние до ответа сервера. Autosave отправляет новую версию после паузы во вводе. До завершения action в приложении одновременно существуют локальные данные, запрос в работе и последняя подтверждённая версия на сервере.
При optimistic create клиент может показать сущность с временным id, а сервер вернуть другой id. Ошибка после частичной записи оставляет сущность на сервере и запускает локальный rollback. При autosave ответы приходят не в порядке отправки. Старый ответ меняет статус уже после сохранения новой версии. updatedAt может перейти вперёд до завершения записи.
В учебном проекте Workbench optimistic create использует clientId для одинакового id на клиенте и сервере. Autosave-демо передаёт requestId в каждый запрос. Редактор хранит статусы saving, saved и error отдельно от текста заметки.

localStorage существует только в браузере. App Router может подготовить HTML на сервере и для Client Component. Код с директивой use client получает состояние, эффекты и обработчики событий, но первый рендер всё ещё может пройти без window и localStorage. И возникают два сбоя. Прямое чтение localStorage падает на сервере. Проверка через typeof window возвращает разные данные на сервере и в браузере. Сервер строит пустое избранное, браузер видит сохранённые id, React получает разные деревья при hydration.

Поиск в Next.js App Router связывает несколько механизмов — Server Components, dynamic routes, searchParams, metadata и клиентские фильтры. Если в проекте одна форма и несколько результатов, состояние можно держать в useState. В каталоге или агрегаторе каждый фильтр меняет URL, набор данных и правила индексации.
В статье на примере учебного проекта EventMap — агрегатора событий, разберем, как спроектировать систему фильтрации, которая генерирует чистые, индексируемые URL для поисковых роботов и обновляет выдачу при изменении фильтров. Страницы вроде «Концерты в Москве» или «Выставки в Петербурге» могут работать как отдельные landing pages. Для них нужны серверный HTML, постоянный URL, свой title, description, h1, canonical и отдельная политика index или noindex. Произвольные запросы, сортировки и глубокая пагинация остаются частью поиска и не попадают автоматически в индекс. Поиск построен через App Router, optional catch‑all route, серверный рендер результатов и общий набор функций для URL, metadata, canonical и sitemap.
Поиск по каталогу создаёт отдельное состояние для каждой комбинации фильтров. Категория, город, дата, сортировка, поисковая строка и номер страницы попадают в URL. При десяти категориях, пятидесяти городах и пяти вариантах сортировки получается 2500 комбинаций без учёта пагинации и свободного текста. Интерфейс должен обработать все допустимые комбинации. В поисковый индекс обычно попадает только часть из них. Страница категории music, страница города london и сочетание music/london могут содержать устойчивую подборку. Запрос ?q=free+jazz+tonight, сортировка по цене и восьмая страница выдачи относятся к текущему действию пользователя. Фильтры без отдельной политики создают большое пространство URL. Google описывает эту проблему в документации по faceted navigation. Изменение каждого параметра создаёт новый адрес, краулер тратит запросы на многочисленные комбинации и позже обнаруживает, что многие из них не содержат самостоятельного материала. (Google for Developers)

Когда Atlassian объявила о завершении продаж Opsgenie, я сначала отреагировал как нормальный инженер: решил ничего не переписывать. Потом календарь напомнил, что нормальность имеет срок действия. Продажи Opsgenie прекратились 4 июня 2025 года, а поддержка завершится 5 апреля 2027 года. После этого сервис станет недоступен, а немигрированные данные будут удалены. Это не слух из рабочего чата, а официальная позиция Atlassian (условия и даты завершения Opsgenie).
Предлагаемый путь ведёт прежде всего в Jira Service Management, причём Atlassian описывает автоматизированную миграцию данных и конфигурации (официальная страница миграции). Для многих компаний это разумный маршрут. В моём случае требование было другим: сохранить существующую self-hosted Jira, не превращать замену on-call инструмента в миграцию всей сервисной модели и получить контроль над данными, интеграциями и deployment.
Я посмотрел альтернативы. Ближе всего по общей идее оказался OpsKnight: проект позиционирует себя как open-source self-hosted платформу для incident response, on-call, routing и status pages (официальный сайт OpsKnight). На бумаге соседство было почти семейным. Но мой набор требований включал автоматическое создание задач именно в нашей Jira, Slack и eXpress, прозрачную передачу L2 в L3, русский и английский интерфейс, простое развёртывание и предсказуемое поведение в небольшом внутреннем контуре. В моём тестировании OpsKnight с этим набором не совпал и не дал нужной уверенности. Это не универсальный вердикт проекту, а описание моего опыта и моей планки риска.

Каждые пять лет я слышу одно и то же: фронтенд больше не нужен, ему остался последний год. Сначала говорили про визуальные конструкторы - Wix, Tilda, все дела. Потом, когда ИИ выстрелил, начали хоронить разработчиков под флагом «AI напишет тебе кнопку за секунду». А сейчас новая мода - фулстекеры. Приходят такие ребята и говорят: «Да зачем нам отдельный фронт, я сам и бэк, и фронт на коленке соберу, проект сэкономит, все будут счастливы».
Давай просто выдохнем и разберемся, что на самом деле происходит, без паники и хайпа.

На планировании оценивают задачу: «добавить бейдж VIP на карточку клиента». Разработчик открывает CustomerCard.tsx, молчит и говорит: «Дня три». Никто не смеётся — все открывали этот файл. В нём почти семьсот строк, и он умеет всё: грузит клиента и его заказы, кэширует, валидирует форму, различает три роли, экспортирует CSV и не падает. Сцена собирательная, но файл — нет: для этой статьи я вырастил его сам, шаг за шагом, и каждый шаг сохранил.
Вопрос к такому файлу — не «почему он большой?». Вопрос — «сколько у него причин измениться и кто их считает, кроме ревьюера?»
За годы code review я много раз наблюдал рождение комбайна и ни разу — конкретный момент, когда обычный компонент становится неуправляемым. Такого момента нет: каждое отдельное изменение выглядит разумным, укладывается в дедлайн и проходит ревью. Поэтому статья устроена как хроника: один компонент, пятнадцать вредных советов, и после каждого — счёт, который выставляет машина.
Неуправляемость не измеряется строками — строки лишь симптом. Болезнь — число причин изменения, собранных в одном файле. Пока их никто не считает, комбайн растёт легально: каждый его шаг проходит code review.

Как измерить человеческую глупость? На первый взгляд, кажется, легко: измерить IQ, делов то! Но не все так однозначно. Как Вы сподвигнете человека на 2 часа интенсивных умственных нагрузок (а столько времени занимает прохождение теста)? Но даже замерив IQ, можно ли однозначно по нем делать вывод о глупости человека? К примеру, если замерить IQ Дон Кихоту и Санчо Пансо, у кого он окажется выше? А кто из них более глупый? В данной статье не только предлагается операциональное определение глупости, но и готовый бесплатный open source инструмент для ее измерения в течении 3-х минут. Поехали!

В этой статье я расскажу, как организовал свой проект на Next.js. На примере реального приложения рассмотрены структура проекта, организация маршрутизации, работа с данными через DAL, аутентификация, валидация, тестирование и другие подходы, которые я использовал в процессе разработки. Статья не претендует на универсальное руководство, а показывает один из возможных вариантов организации приложения.

Переезд в другую страну редко выглядит как последовательный карьерный план. Особенно если вам больше тридцати, с вами едет семья, сбережения быстро заканчиваются, прежний опыт плохо считывается местным рынком, а поиск первой работы растягивается на месяцы.
Я, Александр, автор телеграм-канала «Shulepov Code», поговорил с Виктором Богуцким — разработчиком, который переехал в США в 2016 году, прошёл путь от физической работы и десятков отказов до позиции в Apple и eBay, а сейчас основателем школы программирования PASV.
В этом выпуске мы разбираем, почему эмигранту важнее упорство, чем талант, как устроен найм в американском IT, почему высокая зарплата не гарантирует больших накоплений и зачем разработчику в эпоху вайбкодинга становиться «дирижёром-архитектором». Виктор делится реальным опытом переезда с семьёй, особенностями поиска работы после 30 и тем, как он построил свою школу программирования.

К концу второго месяца vibe coding на фронте моего пет-проекта жили пять компонентов кнопки, четыре спиннера, компонент страницы на 700 строк и шапка, которая показывала один баланс, пока модалка рядом показывала другой. LLM-агент писал всё это уверенно, быстро и с хорошим стилем кода. Фронтенд под LLM деградирует даже быстрее бэкенда — и тому есть причины: от качества обучающей выборки, где вперемешку лежат три поколения React, до самой природы JSX, где разметка, логика и состояние легально живут в одном файле.
Под катом — что в итоге сработало: Feature-Sliced Design, урезанный до трёх слоёв, как карта для агента; dependency-cruiser в роли архитектурного контракта, который нельзя нарушить; кодогенерация API-клиента из OpenAPI вместо доменной модели; за что я простил Tailwind; и честно — про самое слабое место конвейера: агент, который верстает вслепую. Это продолжение статьи про бэкенд, но читается и само по себе.

В прошлый раз я рассказывал, как в 15 лет с нуля написал российскую соцсеть для учеников, учителей и студентов «Агора» — тогда было 99 пользователей, около сотни SQL-миграций и куча энтузиазма. Статья неожиданно собрала 12 тысяч просмотров и почти 40 комментариев. Часть из них были просто добрыми словами, но был и один разбор — от PyXiion — на несколько экранов, по существу, без скидок на возраст. Отвечать на него сходу я тогда не стал, но за прошедшее время большая часть замечаний либо уже была исправлена, либо стала понятнее, почему сделано именно так.
С тех пор проект вырос — не столько по пользователям (~160 человек, аудитория та же — учащиеся, педагоги, студенты), сколько по тому, что под капотом. Расскажу и про рост, и по порядку разберу, что из той критики было верным, а что — нет.

Мы вынесли компактную карточку банковской карты в entities/card/ui: маска номера, баланс и статус — решение казалось очевидным.
Через два спринта в карточке появились действия «заблокировать карту» и «изменить лимит». В итоге entity начала импортировать features/block-card, features/change-card-limit и проверку прав доступа мимо public API. Когда ту же карточку понадобилось показать в выборе счёта списания, вместе с ней приехали ненужные зависимости и проверки ролей.
Пользовательских инцидентов не случилось, но исправление отняло время. В entity оставили чистый CardPreview, сценарии подключили выше, композицию дашборда перенесли в widgets/card-summary, затем заново прогнали ролевые тесты.
После этого на ревью мы стали обсуждать имя папки ближе к концу разговора. Сначала отвечали на другой вопрос:
Какие будущие изменения выбранная граница позволит оставить локальными?
В FSD 2.1 для подобных ситуаций рекомендуют начинать со страниц и извлекать код ниже по мере появления переиспользования. Это хороший вариант по умолчанию, хотя самостоятельный сценарий с близким вторым потребителем иногда оправдывает границу раньше.

Хочу сравнить фреймворк Point0 и библиотеку tRPC. Делаю это, потому что квери и мутации в Point0 очень похожи по DX на tRPC, но более удобны ввиду того, что всё же Point0 это фреймворк и он может обладать возможностями, которыми библиотека не может:
Объявлять квери вместе с серверным кодом прямо в клиентских файлах, или наоборот
Автоматически гидрировать и дегидрировать квери клиент при включении SSR
В мутациях отправлять файлы автоматически превращая данные в FormData и обратно
Иметь стабильные индивидуальные урлы для квери и мутаций
Не заставлять зависать редактор кода при увеличении количества эндпоинтов
Возвращать в ответах с сервера на клиент целые серверные компоненты или интерактивные острова
Управлять внешним видом состояний загрузки на страницах и в компонентах
Кроме того, что описано в этой статье, Point0 может много чего ещё, но об этом в других статьях. Сейчас фокусируемся на сравнении с tRPC. Предполагается, что вы с tRPC более менее знакомы, но ниже я всё равно буду показывать примеры реализации на tRPC, чтобы сравнения были видимыми.

потому что нельзя просто взять redux и начать использовать в React. Необходима некая «react-redux» библиотека. А в чём тогда смысл талдычить, что «Redux works with any UI layer»?

JWT не защищает от кражи. Подпись гарантирует, что токен не подделан, но не мешает злоумышленнику использовать его, если тот оказался в чужих руках. В 2026 году утечки токенов через XSS, логи и CDN-атаки входят в тройку самых частых векторов компрометации, а медианное время обнаружения такой кражи составляет 43 дня.
В этой статье разбираем полный жизненный цикл токена — от выдачи до отзыва. Сравниваем хранение в localStorage, HttpOnly-куках и BFF-прослойке. Объясняем, почему Refresh Token Rotation — это must-have, а не опция, и как детектировать кражу еще до того, как злоумышленник успеет навредить.

Копипаста редко выглядит как копипаста. После переименования переменных, строк и чисел два одинаковых блока спокойно проходят ревью как разный код. Я написал clone-alert, чтобы находить такие совпадения в TypeScript, JavaScript и шаблонах Vue, Svelte и Angular.