<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: shurichu</title>
    <description>The latest articles on DEV Community by shurichu (@shurichu).</description>
    <link>https://dev.to/shurichu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4033249%2Faf94204e-4f31-4c82-9e7f-c3546b935c32.png</url>
      <title>DEV Community: shurichu</title>
      <link>https://dev.to/shurichu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shurichu"/>
    <language>en</language>
    <item>
      <title>Shelpy: агрегатор приютов для животных — кейс с хакатона Kodik Launchpad</title>
      <dc:creator>shurichu</dc:creator>
      <pubDate>Fri, 17 Jul 2026 06:30:56 +0000</pubDate>
      <link>https://dev.to/shurichu/shelpy-aghrieghator-priiutov-dlia-zhivotnykh-kieis-s-khakatona-kodik-launchpad-4faf</link>
      <guid>https://dev.to/shurichu/shelpy-aghrieghator-priiutov-dlia-zhivotnykh-kieis-s-khakatona-kodik-launchpad-4faf</guid>
      <description>&lt;p&gt;Идею подсказал случайный TikTok: приют просил помощи, в комментариях люди спрашивали «куда переводить», а реквизитов не было ни в шапке профиля, ни в описании. Проверил ситуацию по России шире — у большинства приютов либо нет сайта вообще, либо есть, но старый и неудобный. Единой точки, где можно посмотреть питомцев из разных приютов и написать напрямую, не нашлось. На хакатоне Kodik Launchpad решил закрыть именно эту дыру — так появился Shelpy.&lt;/p&gt;

&lt;p&gt;Что это&lt;/p&gt;

&lt;p&gt;Shelpy — веб-сервис-агрегатор: карта приютов, каталог питомцев с фильтрами, чат приют↔пользователь, донаты и личный кабинет приюта для управления карточками животных.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F551s4hxzoba8q0fsoj3f.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F551s4hxzoba8q0fsoj3f.webp" alt=" " width="800" height="510"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ключевой сценарий с обеих сторон:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Пользователь находит приют на карте или в каталоге, фильтрует питомцев по виду/возрасту/породе.&lt;/li&gt;
&lt;li&gt;Открывает карточку животного, пишет приюту в чат внутри сервиса — без перехода в мессенджер и поиска контактов.&lt;/li&gt;
&lt;li&gt;Либо нажимает «Пожертвовать» — и видит реальные реквизиты приюта (телефон для перевода по СБП с указанием банка, либо номер карты), которые приют один раз ввёл в своём профиле. Это прямое решение исходной проблемы: больше не нужно искать реквизиты в комментариях под постом — они всегда на странице приюта.&lt;/li&gt;
&lt;li&gt;Приют со своей стороны заходит в панель управления и добавляет питомца: имя, возраст, тип, фото, описание — без сложной админки.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frtwhpufpqgmt88f3wsma.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frtwhpufpqgmt88f3wsma.webp" alt=" " width="800" height="510"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Архитектура и стек&lt;/p&gt;

&lt;p&gt;Технически это классический монолит на Node.js, без лишней сложности — на хакатонных сроках она того не стоила.&lt;/p&gt;

&lt;p&gt;Backend: Express 4, роуты разложены по доменам — &lt;code&gt;auth&lt;/code&gt;, &lt;code&gt;shelters&lt;/code&gt;, &lt;code&gt;pets&lt;/code&gt;, &lt;code&gt;favorites&lt;/code&gt;, &lt;code&gt;chat&lt;/code&gt;, &lt;code&gt;donate&lt;/code&gt;. Каждый модуль отвечает за свою зону, никакого «всё в одном файле».&lt;/p&gt;

&lt;p&gt;src/&lt;br&gt;
  routes/     — auth, shelters, pets, favorites, chat, donate&lt;br&gt;
  middleware/ — auth, rateLimiter, upload&lt;br&gt;
  config/     — db.js (слой доступа к данным)&lt;br&gt;
  validators/&lt;/p&gt;

&lt;p&gt;Хранилище: сейчас JSON-файлы через собственный слой доступа (&lt;code&gt;src/config/db.js&lt;/code&gt;). Сознательно вынес его в отдельный модуль, чтобы миграция на SQLite/PostgreSQL потребовала переписать только этот слой, а не бизнес-логику в роутах.&lt;/p&gt;

&lt;p&gt;Frontend: SPA на vanilla JS с hash-роутингом, без сборки и фреймворков — Tailwind CDN для стилей, Leaflet для карты. Решение осознанно простое: для объёма фронтенда, который нужен был к дедлайну, сборка и React дали бы больше накладных расходов, чем пользы.&lt;/p&gt;

&lt;p&gt;Файлы: Multer с ограничением по размеру и MIME-типу — под фотографии питомцев.&lt;/p&gt;

&lt;p&gt;При регистрации приют указывает адрес не произвольным текстом, а выбирает его из подсказок геокодера, так что на сервер уходят реальные координаты — раньше все новые приюты по умолчанию попадали в Москву с захардкоженными координатами, что на карте выглядело как баг.&lt;/p&gt;

&lt;p&gt;Безопасность&lt;/p&gt;

&lt;p&gt;Сервис работает с персональными данными и (пока в виде заглушки) с донатами, так что закрыл базовые пункты сразу, а не потом:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;пароли — только через bcrypt-хеши, plain text не хранится; политика пароля — минимум 8 символов, обязательно буквы и цифры;&lt;/li&gt;
&lt;li&gt;Helmet — стандартные защитные HTTP-заголовки;&lt;/li&gt;
&lt;li&gt;rate-limit на логин — ограничение попыток за 15 минут против брутфорса;&lt;/li&gt;
&lt;li&gt;реквизиты приюта (телефон+банк для СБП или номер карты) валидируются на бэкенде отдельной функцией — формат телефона (11 цифр), длина номера карты (16–19 цифр), обязательное поле банка при указании телефона;&lt;/li&gt;
&lt;li&gt;валидация остальных входных данных (email, телефон, длины строк) на бэкенде — фронтовая валидация не единственный барьер;&lt;/li&gt;
&lt;li&gt;секреты и конфиг только через &lt;code&gt;.env&lt;/code&gt;, ничего не захардкожено в репозитории.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Что не успел и куда двигаться дальше&lt;/p&gt;

&lt;p&gt;Это прототип с демо-данными (26 приютов, 21 питомец, роли «приют» и «пользователь» для входа), а не production-сервис. В приоритете после хакатона:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;миграция хранения с JSON на нормальную БД;&lt;/li&gt;
&lt;li&gt;приём донатов сейчас работает как прямая передача проверенных реквизитов приюта — без реального платёжного шлюза; следующий шаг — подключить эквайринг или СБП-интеграцию, чтобы перевод происходил прямо в интерфейсе;&lt;/li&gt;
&lt;li&gt;модерация карточек приюта при регистрации — чтобы в базу не попадали фейковые профили.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Как использовал Kodik&lt;/p&gt;

&lt;p&gt;Разворачивал Shelpy на хостинге Kodik — не пришлось отдельно настраивать сервер и деплой с нуля, что для хакатонных сроков было критично.&lt;/p&gt;

&lt;p&gt;Репозиторий: &lt;a href="https://github.com/3xstar/Shelpy" rel="noopener noreferrer"&gt;https://github.com/3xstar/Shelpy&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>showdev</category>
    </item>
  </channel>
</rss>
