Full stack разработчик: Vue, Laravel, JavaScript, Alpine.js, HTML, CSS
Открыт для удаленной работы
- Умение выполнить бизнес требования. Не требуется мелкая детализация, я сам уточню и формализую задачу, при необходимости предложу упрощение или укажу на то, что упущено.
- Предпочитаю решать задачи через правильную организацию данных, а не через усложнение алгоритмов.
- Довожу задачи до production-использования.
- Фронт: JavaScript, Vue 3/2, Alpine.js, Pinia, Vuex, Vite, WebSocket, PrimeVue, Element Plus, адаптивная вёрстка, HTML, CSS, Bootstrap 5.
- Бэк: Laravel, PHP, MySQL, PostgreSQL.
- Администрирование: Linux, Nginx, Docker, Git, Postman.
- Посмотреть код на Github
- Опыт интеграций: AWS, Mailchimp, Telegram, Ably, Google, Trello, DashaMail, Scaleway.
- Прочее: Photoshop (всё для вёрстки HTML), слепая десятипальцевая печать.
- Смежные специальности: управление проектами,маркетинг
Последние проекты, сделанные полностью, под ключ
Solnushkov.ru — онлайн-тренинги
- Весь контент, структура и дизайн хранятся в БД. Контентная структура и вёрстка статей под SEO.
- Вебинарная комната как инструмент продаж: два и более видеоплеера на выбор (YouTube или Boomstream), собственный WebSocket-чат. По команде ведущего выводится оффер с переходом к оплате — пользователь покупает, не покидая вебинар, контекст не теряется, трение перед оплатой ниже. Вебинар, общение, оффер и оплата — в одном сценарии.
- Тренинг-кабинет: просмотр видео на сайте без возможности скачать (Boomstream по API), переписка с тренером.
- Email-рассылки: сквозной процесс с редактором текста и графической заставки (выпускающий → автор → редактор → дизайнер); стили заменяются на инлайновые, публикация уходит через API (AWS, DashaMail).
- Email по расписанию: серия писем формируется списком с датами и уходит сама в нужный момент; сюда же уведомления о вебинарах; отдельные cron-задачи не нужны.
- Регистрация/авторизация на Vue: фоновая Google reCAPTCHA, подтверждение по email (ссылка или код), восстановление пароля. OAuth: Яндекс, Google, Mail.ru — или Telegram-бот (сейчас отключён из-за блокировки Telegram).
- Оплата: приём платежей через Тинькофф и Яндекс, подсистема персональных рассрочек.
MagijaSapuna.com — интернет-магазин, полностью самописный (PostgreSQL)
- Весь контент, структура и дизайн хранятся в БД. Активно используется кеш.
- Гибкая структура каталога товаров: настройка структуры товара через JSON-схему.
- Карточка товара на Alpine.js — для лучшего SEO; корзина на Vue и Vue-компонентах.
- Автоматический рендер загруженных видео в нужный битрейт и размер через системный cron.
- Аккуратная разметка JSON-LD (SEO в топе).
Magalif.ru — медицинская клиника
Весь контент, структура и дизайн хранятся в БД. Вместо кеша — генерация в статические HTML-файлы (сайт меняется редко). Мгновенная отдача.
MagicPro
Надстройка над Laravel: скорость CMS + гибкость фреймворка.
Опенсорсный пакет, опубликован на Packagist, MIT, в активной разработке, v1.6.5 Идея — перенести структуру кода в данные: контроллеры, роуты, вьюхи, страницы и меню управляются из единой модели в базе, а не разбросаны по десяткам файлов. Это мой принцип «сначала данные потом код», доведённый до инструмента.
Больше декларативности и читаемости. Древовидная структура позволяет держать перед глазами взаимосвязь компонентов.
Внутри: генерация контроллеров/вью/роутов, динамическая маршрутизация, статический генератор с пауком (Nginx отдаёт готовый HTML, иначе — динамический роут), файловый менеджер с редактором (ACE) и форматтерами, мультиязычность, тёмная тема, горячие клавиши.
Стек: Laravel 12/13, Vue 3, Bootstrap 5, PrimeVue, SQLite/MySQL/PostgreSQL.
На нём работают боевые сайты, в том числе проекты из этого портфолио.
Принимал участие в создании проектов
- Онлайн-радио 101.ru — первое российское интернет-радио.
- Авторадио — сайт радиостанции.
- Радио ENERGY (NRG) — сайт радиостанции.
- TSW — туроператор.
- Корпоративный портал.
- И другие.
Вопросы и ответы
— В чём ваша инженерная сила?
— Структуры данных. Многие упираются в алгоритмы и экономят на данных. Правильная структура часто убирает нужду в хитром алгоритме вообще: данные сами диктуют простой код. Поэтому прежде, чем писать, я думаю, как разложить данные. Пример — magijasapuna.com: там меньше десятка таблиц, но в основе лежит JSON-схема, и за счёт неё реализованы разные схемы товаров и групп.
— Как вы ставите тире? Вы ИИ?
— Использую раскладку клавиатуры Ильи Бирмана.
— Используете ли вы ИИ в работе?
— Да, сегодня без этого никуда. Но за годы руководства у меня выработался рефлекс всё проверять, и на ИИ он распространяется в первую очередь. Его ответ для меня черновик: смотрю, анализирую, задаю наводящие вопросы, пишу комментарии, отправляю на доработку — отношусь как к сотруднику. Один из приёмов — прогнать решение одной модели через другую: у них разные слепые зоны, и одна нередко ловит ошибку второй. Например, код от Claude отправить на рецензию GPT, а потом ещё раз проверить.
— Какую ошибку в интерфейсах вы видите чаще всего?
— Путают, для кого интерфейс. Публичную часть, которую человек видит раз, перегружают, а рабочую панель, где специалист сидит весь день, упрощают. Я проектирую каждую часть под её настоящего пользователя: витрину — простой и ведущей за руку, рабочий инструмент — плотным и быстрым, с горячими клавишами и массовыми операциями.
— Как у вас устроена обработка ошибок на фронте?
— Обращение к API идёт через одну асинхронную функцию: она получает данные и проверяет статус ответа (все API сделаны по единому шаблону). Если API вернул ошибку, прямо из этой функции показывается тост и выбрасывается исключение. Это сильно сокращает обработку ошибок.
— А обработка ошибок и сам API на бэке?
— Одна точка входа — общий контроллер: проверяет входные параметры и вызывает нужную функцию. Функция при любой проблеме выбрасывает исключение, контроллер его ловит и формирует ответ. До конца функция доходит только при полном успехе. Один контроллер, единообразные запрос и ответ. try/catch как основной механизм.
— Рассматриваете ли долгосрочную работу или только проекты?
— И долгосрочную работу, и проекты. Только удалённо.
— Сможете встроиться в команду, где техлид моложе и ставит вам задачи?
— Без проблем. Я сам руководил, поэтому знаю эту работу с другой стороны: понимаю, зачем нужны оценки, статусы и договорённости. Если решение рабочее — поддерживаю. Если вижу риск для сроков и качества, избыточность или недостаточность — аргументирую и предлагаю другой вариант.
— Как с часовыми поясами и асинхронной работой?
— Работаю на результат; если чего-то не знаю, время на изучение в счёт не ставлю. Задачи и договорённости фиксирую в тексте, могу перевести в текст и аудио — чтобы не было разночтений и меньше зависеть от того, кто когда онлайн.
— Как закрыли скачивание видео в solnushkov?
— Через Boomstream. Защита контента — давно решённая задача, под неё есть специализированные сервисы; городить свой DRM или самостоятельно разбивать видео на чанки смысла нет. Интегрировал готовое по API — надёжнее и дешевле, чем изобретать велосипед.
— Приём оплаты: что будет, если платёж прошёл, а сервер в этот момент лежал?
— Вебхук делает ровно одно: принимает уведомление и ставит задачу в очередь. Вся обработка — в фоновом воркере, который при сбое повторяет попытку. Банк всегда получает быстрый ответ, а платёж не теряется, даже если обработка временно недоступна.
— OAuth через три провайдера — как свели личности в одну?
— В общем случае никак — это известная нерешаемая проблема (вошёл на десктопе через Яндекс, на телефоне через Google — для системы это два разных человека). Поэтому я ставлю прагматичные ограждения: после оплаты шлётся письмо, где в ссылке зашит зашифрованный email оплаты, и если человек заходит с почты, не совпадающей с почтой оплаты, он получает предупреждение. В админке — ручное слияние и переименование.
— Чат на WebSocket: сколько держит соединений и что при обрыве?
— Тестировал на 1000 одновременных. При обрыве — перезагрузка страницы у пользователя, и вся история приходит стартовым пакетом, контекст не теряется.
— Как в чате решаете бан?
— Сначала мягко: удаляем сообщение — оно пропадает у всех — и пишем предупреждение в личку. Не помогает — теневой бан. Забаненный не знает, что забанен: пишет, видит свои сообщения, «праздник жизни продолжается», сервер их принимает и никому не транслирует. Обычно запала хватает минут на десять, потом уходит сам. Работает лучше открытого бана — не даёт повода для эскалации.
— У сайта клиники статика из админки Laravel. Почему статика, а не обычный рендер?
— Система работает в обоих режимах, динамический чуть медленнее. В админке есть кнопка-паук: обходит сайт, собирает страницы и заодно показывает ошибки. Потом кнопка «Опубликовать». Nginx настроен так, что сначала ищет URL в статической папке, не находит — уходит в динамический роут и собирает страницу из базы. Внесли изменения, прогнали пауком, опубликовали — дальше месяцы работы без изменений, и всё онлайн.
— Расскажите про ваш пет-проект.
— MagicPro, мой пакет для Laravel. Меня раздражала россыпь контроллеров и блейдов, где контроллер часто только дёргает API и отдаёт шаблон. А многим страницам контроллер вообще не нужен: «О проекте», «Контакты» — это чистый шаблон; новость — одно обращение к базе, которое через API спокойно живёт прямо в блейде. При этом Laravel раскладывает всё по типам файлов: контроллеры в одном месте, блейды в другом, роуты в третьем — и одна логическая страница размазана по папкам. Я свёл это воедино: в MagicPro страницы — иерархическое дерево, и каждая определяется своим местом в структуре проекта, а не принадлежностью к контроллеру или блейду. Роуты, вьюхи, контроллеры (там, где они нужны) и контент лежат в одной модели и правятся из админки. Это мой принцип «сначала данные, потом код» в чистом виде — и он же кратно ускоряет разработку.
— За какие задачи не возьмётесь?
— За то, что сделаю плохо. Компилятор, например, — пробовал, налетел на рифы :) То же с нативной мобильной разработкой и серьёзным ML. И не берусь за то, что вредит пользователям, нарушает закон или на грани, — парсинг чужих сайтов, спам, накрутки, обман.
— Делаете ли вы тестовое задание?
— Да, присылайте.
Напишите в двух словах, какие у вас задачи — что надо сделать, починить или оценить.
TelegramС уважением, Михаил Каневский.