Около года назад я открыл для себя замечательную игру Casual Crusade.
Это браузерный roguelike на HTML canvas, с полностью процедурной генерацией и отрисовкой графики, без богомерзких движков Unity и иже с ним.
Игра написана для конкурса js13k (лимит 13 килобайт) и переросла в одну из самых стройных и реиграбельных браузерных головоломок. С тех пор я возвращаюсь к ней почти каждый день.
Что в ней особенного? Механика проста: размещай цветные плитки на поле, собирай комбо, прокачивайся реликвиями и зельями, выживай против еретиков и боссов. Но за этой простотой скрывается удивительная глубина - каждый забег уникален, билды не повторяются, а случайные проклятия после боссов каждый раз ломают твою стратегию по-новому. Есть ежедневные испытания с набором случайных проклятий.
В игре есть незамысловатая "религиозная философия": герой бредёт вперёд без великой цели, собирая реликвии сомнительного происхождения, торгуясь с призрачными торговцами и принимая проклятия как данность. Никакого избранничества, никакого спасения мира - только Путь.
Игра с черным юмором обыгрывает историческую торговлю индульгенциями: грехи здесь прощаются за успешную резню, а божественное проклятие настигает не за жестокость, а за банальную жадность при вскрытии сундуков.
Есть и секретный квест, который, судя по таблице рекордов, никому еще не удалось разгадать.
Технически это показательная работа: весь игровой движок - рендер, физика, аудио, UI - написан с нуля на TS без единого фреймворка. Никакого Unity, никакого Phaser. Это делает код одновременно изящным и хрупким - идеальный материал для изучения и доработки.
Casual Crusade - это редкий пример игры, где минималистичный интерфейс и базовые правила порождают по-настоящему глубокий и интересный геймплей.
Меня игра, помимо необычной механики, зацепила также необходимостью самостоятельного изучения мира и правил. Есть наполеоновские планы углУбить эту ее строну.
Именно поэтому я деобфусцировал код и начал вносить мелкие правки. Игра затянула уже на уровне кода.
Сейчас я готовлю показать вам свою версию (будет готова в течение пары часов).
Список текущих правок за неделю:
- фикс нижнего отступа колоды/руки
- удалён устаревший код версий таблицы рекордов
- автоскрытие тултипа
- убрана тряска камеры при шаге Чувака
- случайное проклятие после убийства Босса
- добавлен экран проклятия (CurseScreen)
- никнейм скрыт в игре; тултип на полоске здоровья с именем и номером уровня
- режим паузы анимации (watchDog) со статичным экраном
- унификация обработки ввода (Pointer Events)
- максимум 10 карт в руке
- свайп вверх для перехода в полноэкранный режим
- обработка сетевых ошибок в таблице рекордов
- красный переход экрана перед уровнем Босса
- прочее
Для пикабушников будет доступно бесконечное количество попыток в ежедневном испытании (в оригинале только одна попытка).
Есть куча идей для новых механик, проклятий, заклинаний, врагов, ловушек, атласа-справочника по игре и системы ачивок.
В перспективе хочу сделать режим Прохождения с сюжетом.
Каждый раз, когда начинаешь новый веб-проект, встаёт один и тот же вопрос: как рендерить страницы? CSR, SSR, SSG — звучит как аббревиатуры из учебника, но на практике именно этот выбор определяет скорость сайта, позиции в поиске и удобство разработки.
CSR — Client-Side Rendering
Сервер отдаёт почти пустой HTML с одним тегом div и большим JS-бандлом. Браузер скачивает JavaScript, выполняет его, делает запросы к API — и только после этого пользователь видит контент.
Плюсы:
Быстрая навигация после загрузки
Богатые интерактивные интерфейсы
Минусы:
Долгая первая загрузка (Time to Interactive)Долгая первая загрузка (Time to Interactive)
Плохо для SEO — боты видят пустой HTML
Требует хорошего интернета у пользователя
Главная проблема CSR — поисковые боты. Googlebot умеет выполнять JavaScript, но делает это с задержкой и не всегда корректно. Яндекс справляется хуже. В итоге страницы индексируются медленнее и хуже.
Когда CSR — правильный выбор:
• Дашборды и админки за авторизацией — SEO не нужен
• SPA с богатой интерактивностью: редакторы, конструкторы, таблицы
• Внутренние инструменты компании
• Приложения, где пользователь авторизован и контент персональный
SSR — Server-Side Rendering
При каждом запросе сервер генерирует готовый HTML с данными и отдаёт его браузеру. Пользователь сразу видит контент — не надо ждать, пока выполнится JavaScript.
Плюсы:
Отличный SEO — боты видят готовый HTML
Актуальные данные на каждый запрос
Минусы:
Нагрузка на сервер при каждом запросе
Медленнее навигация, чем CSR
Нужен сервер — хостинг дороже
SSR — лучший выбор для SEO-важных страниц. Поисковик получает готовый HTML с контентом, мета-тегами и структурированными данными. Индексация быстрее и надёжнее, чем при CSR.
Когда SSR — правильный выбор:
• Интернет-магазины — карточки товаров должны индексироваться
• Новостные сайты и блоги с часто меняющимся контентом
• Страницы с персонализированным контентом (лента, рекомендации)
• Любые публичные страницы, где важен SEO и актуальность данных
SSG — Static Site Generation
HTML генерируется один раз — во время сборки проекта. Готовые файлы раздаются с CDN без участия сервера. Это самый быстрый способ доставить контент пользователю.
Плюсы:
Максимальная скорость
Отличный SEO
Дешёвый хостинг — просто файлы
Высокая надёжность — нет сервера
Минусы:
Данные могут быть устаревшими
Долгая сборка при большом числе страниц
Не подходит для часто меняющихся данных
Когда SSG — правильный выбор:
• Лендинги и маркетинговые сайты
• Документация и справочники
• Блоги и портфолио
• Сайты, где контент меняется редко или по расписанию
Главное про SEO
SEO — это часто решающий фактор при выборе рендеринга. Вот простое правило:
• Страница публичная и должна находиться в поиске → SSR или SSG
• Страница за авторизацией или контент персональный → CSR
• Контент меняется часто → SSR
• Контент меняется редко → SSG
Отдельно про Core Web Vitals — Google учитывает LCP, FID и CLS в ранжировании. SSG и SSR дают лучшие показатели, чем CSR по умолчанию, но и CSR можно оптимизировать через lazy loading, code splitting и prefetching.
Хорошая новость: Next.js позволяет миксовать все подходы в одном проекте. Лендинг — SSG, карточка товара — SSR, личный кабинет — CSR. Именно поэтому он стал стандартом индустрии.
Больше материалов про разработку и запуск своих продуктов — в Telegram-канале @deep_in_prod
Современный Frontend давно перестал быть слоем поверх API. В реальном продукте он решает те же вопросы, что и любая распределённая система: где живут данные, когда они считаются свежими, как пережить задержку сети, что показать при частичном отказе, где провести границу между сервером и клиентом, как не превратить локальное состояние в теневую базу данных.
Проблема в том, что мы всё ещё говорим о Frontend языком интерфейса, хотя строим уже не интерфейс. Мы строим систему доставки смысла пользователю.
Классическая схема была понятной. Сервер собирает страницу, браузер показывает HTML, пользователь кликает ссылку, сервер отдаёт новую страницу. Почти вся сложность жила на сервере: маршруты, права, данные, шаблоны, ошибки.
Потом интерфейсы стали богаче, и мы перенесли часть логики в браузер. Страница перестала быть документом и стала приложением. Браузер начал хранить состояние, валидировать формы, строить маршруты, кэшировать данные, оптимистично обновлять UI. Это дало скорость и интерактивность - и заодно растащило Frontend по нескольким слоям.
Часть живёт на сервере: рендеринг, подготовка данных, проверка прав. Часть - в браузере: интерактивность, ввод, мгновенная обратная связь. Часть - в кэше: CDN, query cache, prefetch, service worker. А часть вообще не выглядит как Frontend: она в контракте API, в схеме данных, в дизайн-системе, в правилах релиза.
Когда всё работает, пользователь видит простую вещь: страница открылась, кнопка нажалась, действие сохранилось. Когда ломается, выясняется, что «кнопка» была последним звеном в длинной цепочке решений.
Кнопка не просто вызывает onClick. Она может запускать optimistic update, инвалидировать кэш, отправлять событие аналитики, менять URL, зависеть от прав пользователя, показывать pending-состояние, откатывать UI после ошибки или повторять запрос.
Это уже не «покрасить кнопку». Это проектирование поведения системы в условиях неопределённости.
Ernest Peixotto (American, 1869–1940)
Компоненты не спасают архитектуру
Когда Frontend стал сложнее, мы нашли удобный ответ - компонентную модель. Разбей интерфейс на части, переиспользуй их, собери экран из маленьких элементов. Сильная идея, но без неё современные интерфейсы было бы трудно поддерживать.
Но компонентная модель хорошо описывает форму интерфейса и плохо описывает поведение продукта. Компонент может быть маленьким, типизированным и красивым, а архитектура всё равно слабой, потому что настоящая сложность живёт между компонентами.
Самая частая ошибка - смешать UI-состояние, серверные данные, процесс сохранения, ошибки и производные значения в одном месте. Тогда форма знает про API, кнопка - про бизнес-правила, таблица - про инвалидирование кэша, а страница хранит копию данных из query cache «на всякий случай». Дальше начинаются исключения, быстрые фиксы, дублирование, страх менять экран и фраза «проще переписать».
Redux, Zustand, React Query, SWR, Signals, Context - ни один инструмент не решит за команду главный вопрос: где источник правды.
Если правда на сервере, Frontend должен уважать сервер и не показывать пользователю фантомное состояние. Если правда в пользовательском вводе, нельзя терять его после refetch. Если правда в URL, состояние должно переживать перезагрузку и передаваться ссылкой. Плохая архитектура начинается там, где источник не выбран: сервер говорит одно, кэш помнит другое, форма хранит третье, URL показывает четвёртое, а компонент делает пятое, потому что «так быстрее».
Near Richmond, Yorkshire (1877)
Где должна жить логика
Главный вопрос: кто за что отвечает, и что произойдёт, когда что-то пойдёт не так.
Возьмём простой сценарий - пользователь переименовывает проект.
Слабая версия: Пользователь жмёт «Сохранить». Форма отправляет PATCH, показывает спиннер. Через 800 мс ответ приходит, спиннер исчезает, имя в форме обновляется. Хорошо. Но в сайдбаре имя меняется ещё через секунду, потому что список проектов перезапрашивается отдельно. А в соседней вкладке, открытой час назад, имя вообще старое. Пользователь видит три разных состояния одной сущности и не понимает, какому верить.
Сильная версия: То же действие. Имя в инпуте меняется мгновенно - здесь источник правды сам пользователь. После сабмита UI сразу показывает новое имя во всех местах: в сайдбаре, в заголовке, в хлебных крошках, но визуально помечает его как ещё не сохранённое (например, приглушённым цветом). Если сервер подтвердил, тогда пометка исчезает. Если вернул ошибку - UI откатывается к старому имени и показывает причину человеческим языком: «нет прав» или «имя уже занято». Список проектов в кэше обновляется по одному правилу, а не по совпадению.
Из этого вытекает несколько практических правил.
Источник правды - один на каждое значение. Если правда на сервере, Frontend читает её оттуда и не хранит копий «на всякий случай». Если правда в URL - фильтры, поиск, выбранная вкладка, она переживает перезагрузку и передаётся ссылкой. Если правда во вводе пользователя, её нельзя потерять при refetch. Дублирование источников - это не ускорение, это будущий баг.
Frontend не решает то, за что не отвечает. Он может скрыть кнопку под роль пользователя, но не должен сам определять, разрешено ли действие. Это решает сервер. Frontend может показать бизнес-правило и объяснить его, но само правило живёт в домене, а не в компоненте. Если правило про деньги, права или статусы случайно осело в JSX, его рано или поздно нарушат.
Кэш это договор, а не оптимизация. Когда мы держим данные в query cache, мы говорим пользователю: «верь этому, пока я не скажу обратное». У договора должны быть условия: сколько данным можно верить, кто их обновляет, когда инвалидировать, что показывать, если они устарели. Быстрый интерфейс не должен быстро врать.
Производительность и ошибки
Производительность часто сводят к Lighthouse, Core Web Vitals и размеру бандла. Метрики полезны, но не объясняют главного.
Пользователь не обязан ждать. Медленный Frontend почти всегда - сумма решений: слишком много клиентского кода, тяжёлая дизайн-система, водопад запросов, дорогой рендер, небрежная гидратация. Это нельзя починить в конце. Это проектируется в начале: что отдать с сервера, что загрузить заранее, что отложить, какой экран остаётся полезным при частичном отказе.
С ошибками то же самое. В продакшене сеть медленная, API отвечает не сразу, сессия истекает, пользователь кликает быстро, данные меняются в другой вкладке. Ошибка валидации должна жить рядом с формой. Ошибка прав - приходить от сервера. Ошибка сети - объяснять, можно ли повторить действие. Ошибка бизнес-правила должно быть написана по-человечески: не «400 Bad Request», а «Нельзя удалить проект, пока в нём есть активные задачи».
Надёжность Frontend - это не отсутствие ошибок в консоли. Это способность интерфейса вести себя предсказуемо, когда мир вокруг неидеален.
A Winter Scene (mid 1640s)
Что отличает сильного Frontend-инженера
Не количество выученных хуков и не скорость написания компонентов. Он понимает границы: где заканчивается серверное состояние и начинается клиентское, где данные можно кэшировать, где нужна мгновенная реакция, а где честный loading, где типы помогают, а где нужна runtime-проверка, где абстракция снижает стоимость изменений, а где делает код мутным.
Он проектирует не только компоненты, но и договоры: между клиентом и сервером, между страницей и компонентом, между системой и пользователем.
Плохая архитектура почти всегда выглядит нормально в первый месяц. Потом она начинает требовать всё больше энергии за всё меньший результат. Переписывать приходится не потому, что React плохой или Vue плохой. Чаще всего в начале никто не ответил на скучные вопросы: что является источником правды, какие данные могут устареть, что пользователь увидит при медленной сети, что произойдёт, если запрос выполнится дважды, какая логика принадлежит домену, а какая - интерфейсу.
Заключение
Frontend больше не тонкая оболочка вокруг API. Он стал местом, где техническая архитектура встречается с человеческим ожиданием. Пользователь не видит server components, query cache, hydration и source of truth. Он видит другое: страница открылась или нет, действие сохранилось или потерялось, ошибка объяснена или спрятана, интерфейс помогает или заставляет сомневаться.
Frontend - это слой доверия. Он отвечает за договор между человеком и системой: нажал - увидел реакцию, сохранил - понял результат, ошибся - понял, как исправить, вернулся - попал туда, где ожидал быть. Хорошая архитектура не убирает сложность. Она кладёт её туда, где её можно понять.
Этой вводной статьёй я хотел поделиться мыслями и начать этот блог. Всем спокойных релизов и поменьше багов в продакшене ❤
По сути это система, которая показывает на экранах (ТВ в коридоре, монитор, планшет) актуальное расписание, время, объявления и звонки. Всё работает в обычном браузере, без всяких специальных программ. Мне надоело смотреть как девчонки бегают с флешками между телевизорами.
Сделал так, чтобы после настройки можно было отключить интернет совсем — всё хранится локально и работает по сети (после сборки). Поставил старый мини-ПК или даже прямо на Smart TV заходит по адресу и показывает.
Сначала думал только про школы (уроки, перемены, звонки на Рупор-300 или используя собственный усилитель), но чем дальше, тем больше понимаю, что это можно использовать гораздо шире...
Сейчас уже стоит в паре мест, работает. Столкнулся с интересными моментами по интерфейсу и удобству, особенно когда пытаешься сделать так, чтобы и директору было понятно, и обычному человеку на телефоне.
Если кому-то интересно такое решение для своей задачи — могу показать, что получилось. Или иные вопросы или явные указания (по скринам) на проблемы. Основа - питон, FastApi и js.
Мой ТГ (личка): @GuardDoc
Не каналы, не продажи, просто если есть интерес поговорить что это такое. Ищу критики и предложений по интерефейсу (сложно в UI)
Особенно не откажусь от мыслей что можно добавить как "виджеты"
Предлагаю вашему вниманию программу «ТРЕНИРОВКА ПАМЯТИ»
Простой и эффективный инструмент для развития способности запоминать важную информацию.Простота и надёжность.Программа выполнена в лучших традициях DOS-эпохи: ничего лишнего, только функциональность. Минималистичный интерфейс, мгновенный запуск, отсутствие сложных настроек — всё работает быстро и понятно.
Это именно тот случай, когда простота означает качество.Что тренирует программа? Программа фокусируется на запоминании трёх типов информации, которые наиболее востребованы в повседневной жизни:
1 - Телефонные номера — для быстрого набора без подглядывания в контакты 2 - Адреса (улица, дом, корпус, квартира) — чтобы не теряться в незнакомых местах 3 - ФИО, организации и должности — для уверенного общения в деловой среде
Именно эти данные мы чаще всего забываем в самый неподходящий момент. Регулярные тренировки помогут довести запоминание до автоматизма.Принцип работы:Программа показывает информацию на ограниченное время (от 20 до 40 секунд в зависимости от сложности), после чего предлагает воспроизвести её по памяти.
За каждый правильный ответ начисляется балл, за ошибку — снимается. Цель — набрать 20 баллов.
Почему это работает?
Все временные интервалы рассчитаны таким образом, чтобы создать оптимальную нагрузку на кратковременную память. Это заставляет мозг концентрироваться и эффективно кодировать информацию. Регулярные занятия по 10-15 минут в день дадут заметный результат уже через 2-3 недели.
Технические требования:
Программа работает в любом современном браузере, не требует установки и интернета. Достаточно просто открыть HTML-файл.
Хочу добавить, что я, не имея навыков программирования на Java script написал ее при помощи нейросети. Я сформулировал архитектуру и логику этой программы и достаточно быстро получил работающий код.
Зачем это сделано, в современных браузерах есть ограничения от v8 на память в 2 гигабайта, обычно для обхода этого ограничения файлы можно читать и писать файлы частями, но моя pyoddide версия запуска https://github.com/nicoboss/nsz в браузере Написал тулкит для работы с файлами Nintendo Switch в форматах NSZ и NSP прямо в браузере не могла читать и писать файлы частями из-за ограничений pyoddide фреймворка, так что переписал все на чистый js, заодно сайт теперь весит в 5 раз меньше, было 10 мегабайт, теперь 2 мегабайта
ИГРАТЬ НА ПК (рекомендуется включить полноэкранный режим в главном меню игры)
Block Zero продолжает расти.
Сначала это был небольшой браузерный прототип: арена, волны, несколько пушек, враги, которые должны были просто давить игрока количеством. Потом появились боссы, синергии, мета-прогрессия, Зал Cлавы, музыка, новые эффекты, отдельное меню, полноэкранный режим и локализация. В какой-то момент стало понятно: если я хочу дальше развивать игру, волнам следует перестать быть простым приростом численности. Так начался этап Enemy Evolution. Первая фаза этого большого направления уже в игре. Главный новый участник - Рой.
Рой не похож на прежних противников. Отдельная особь слаба, умирает быстро и не выглядит серьезной угрозой. Но когда их восемь, десять, двенадцать, а потом еще одна стая выходит с другой стороны карты, темп боя неизбежно меняется. Игроку приходится двигаться иначе, держать дистанцию, думать о направлении отхода, чаще оценивать пространство вокруг себя. Рой не задумывался как "жирный" враг. Его задача другая: ломать привычный ритм, заполнять экран движением и заставлять игрока нервничать.
Вместе с Роем в игру пришла и Оружейная. Теперь постоянная прогрессия не ограничивается общими улучшениями персонажа. Отдельная вкладка отвечает за развитие оружия: урон, скорострельность, дальность и другие параметры, которые постепенно делают выбранный стиль боя ощутимее. Пистолет, дробовик, SMG и плазменная винтовка должны чувствоваться не как временные предметы с разными цифрами, а как основа будущих билдов.
Но новые враги и оружейные улучшения требуют ещё одной важной вещи - ясности. Синергии работали и раньше, но игрок не всегда понимал, куда ведет тот или иной выбор. В этом обновлении билд-система стала гораздо прозрачнее. Добавлен Справочник синергий, где можно посмотреть условия и эффекты. Бонусы, которые прямо сейчас открывают синергию, получают заметную подсветку. Активированные синергии объявляются крупным золотым баннером, чтобы такой момент не терялся в разгар боя. Теперь билд собирается не вслепую. Можно увидеть направление, рискнуть, добрать нужный бонус и почувствовать, как отдельные улучшения складываются в работающую боевую механику.
Ещё одна большая часть обновления - достижения. В игре появился отдельный экран достижений с прогрессом, красивыми иконками и всплывающими уведомлениями. Некоторые достижения открываются почти сразу, другие требуют долгой игры или конкретного стиля прохождения. Можно охотиться на Рой, проходить волны только с пистолетом, устраивать старую добрую бойню с дробовиком наперевес, взрывать бочки, собирать синергии, выживать без урона и постепенно закрывать все более тяжелые боевые рубежи. Достижения не меняют баланс. Они не добавляют урон, здоровье или кредиты. Это след, что остается после забегов. Маленькая летопись того, как игрок учился выживать в Block Zero.
Также было заметно улучшено представление боссов. Появилось крупное предупреждение перед появлением, отдельная шкала здоровья и более выразительное сообщение после победы. Босс должен ощущаться событием, а не просто большим врагом с длинной полоской HP.
Зал Славы тоже стал аккуратнее. Теперь это больше похоже на боевой архив: записи выглядят чище, детали забега читаются лучше, синергии отображаются отдельно, а результаты сохраняют больше информации о том, как именно прошёл забег.
В это обновление вошло много не самой заметной, но важной полировки: исправлена работа управления в русской раскладке, улучшено поведение игры вне полноэкранного режима, доработаны карточки бонусов, убраны лишние баннеры, скорректированы дроны (в очередной и явно не последний раз), обновлены визуальные элементы интерфейса и добавлены новые детали, которые делают игру понятнее.
Эта версия - не финал Enemy Evolution. Это лишь её первая фаза. Рой уже вышел на арену. Теперь у Block Zero есть фундамент для следующих врагов: Призывателя, Снайпера, элитных противников, более умных волн и будущих мегабоссов. Дальше волны должны становиться не только сложнее, но и разнообразнее, интереснее и злее.
Спасибо всем, кто играет, тестирует и пишет обратную связь. Block Zero всё ещё остаётся моей первой игрой, но с каждым обновлением она всё меньше похожа на прототип и всё больше — на настоящий маленький шутер, который хочет драться за своё место под солнцем.
P.S. Добавил несколько скриншотов для понимания игрового процесса и уровня графики.
SendCore получил пакет обновлений и улучшений мессенджера(^o^).
Всем привет. Спустя столько времени я наконец то выпустил большое обновление продукта.
Что нового:
1. Новый раздел - SendCore Gallery. Это внутренний аналог Pinterest. Можно свободно выкладывать фотографии, лайкать их и комментировать.
2. Добавление возможности комментирования постов и фотографий. Теперь вы можете комментировать и писать своё мнение прямо внутри SendCore.
3. Улучшение профилей. Теперь появилось модальное окошко профиля (нажмите на аватарку на главном экране и вы поймёте, о чём я).
4. Добавления возможности настроек своего аккаунта. Кнопка Settings уже доступна в модальное окошке профиля.
5. Добавления нового вида навигации. Теперь вы можете включить нижнее кнопки навигации (Как в Telegram), если вам не привычна навигация сверху. Включить можно в настройках. По умолчанию со т навигация сверху.
6. Принятие условий использования и введение правил сообщества (прочитать их можно тоже в настройках).
Следите за обновлениями на моих каналах и блогах в dtf, Pikabu.
Где скачать?
Насчёт скачивания новой версии есть беда - 4pda заблокировал страницу для установки SendCore по неизвестным нам причинам. Буду разбираться со страницей в 4pda.
Поэтому на данный момент единственный способ скачать обновление - через Google Drive.