Каталог месцаў і арганізацый для часопіса Doberman Media
праект
Каталог на doberman.media/catalog — гэта карта і спіс з 295 ЛГБТК+-месцаў у 25 краінах: клубы, сауны, гатэлі, кавярні, медыцынская і юрыдычная дапамога. Я зрабіў яго цалкам як WordPress-плагін sdwski-directory (версія 1.28.0, каля 14 тысяч радкоў PHP, JS і CSS), без канструктараў і знешніх API-ключоў. Ніжэй — як уладкаваны каталог і што пра яго можна расказаць на старонцы праекта.
Пра праект. Часопісу Doberman.media быў патрэбны каталог месцаў, дзе чытач можа бяспечна і хутка знайсці клуб, сауну, лекара або юрыста ў любым горадзе. Я цалкам спраектаваў і напісаў яго: даныя, карту, мадэрацыю заявак, кабінет для ўладальнікаў месцаў і рэкламныя месцы.

Наведвальнік выбірае краіну, горад і катэгорыю і бачыць усе месцы на карце, а не толькі першую старонку спіса. Карта хутка адлюстроўвае тысячы пунктаў, а пры набліжэнні ператварае іх у значкі катэгорый. На старонцы месца — фота, гадзіны працы са статусам «адкрыта цяпер», маршрут у пяці картах, ацэнкі і водгукі без пароля, форма «Паведаміць пра памылку». Уладальнікі ўстаноў самі рэдагуюць свае старонкі праз асобны кабінет, а я бачу кожную змену.
- Фільтры. Выбар краіны, затым горада і катэгорыі; укладкі катэгорый з лічыльнікамі (на сёння: клубы і бары — 154, гатэлі — 58, сауны і лазні — 52, Cruising — 37, грамадскія арганізацыі — 25). Зверху вынік «Знойдзена: 295».
- Пошук па назве, у тым ліку па перакладзеных назвах на іншай мове сайта.
- Карткі. Фота, катэгорыя, назва, рэйтынг і колькасць водгукаў, адрас, графік працы, кнопкі тэлефона, Instagram, Facebook, сайта і «Водгукі».
- Пераключальнік «Спіс / Карта» на тэлефоне і плаваючая панэль фільтраў паверх карты.
- «Абнаўляць пры перамяшчэнні карты». Спіс падладжваецца пад бачную вобласць карты.
- «Паказаць, дзе я». Геапазіцыя наведвальніка і сартаванне спіса, пачынаючы з найбліжэйшых месцаў.
- Абранае. Захаваныя месцы захоўваюцца ў браўзеры без рэгістрацыі.
- Поўнаэкранны рэжым без шапкі і падвала сайта, а таксама кіёск-рэжым для дэманстрацыі на экране.
- Кнопка «Дадаць у каталог» і блок «Няма вашага месца ў каталогу?» у канцы спіса.
Рэклама. У каталог убудаваная рэклама: банер паміж карткамі пасля кожных N месцаў, вертыкальны банер каля карты і блокі на старонцы месца. Усё сумленна пазначана, банеры змяняюцца ў панэлі адміністратара без рэдагавання кода. Таксама рэклама ёсць на карце каталога.
Тэхналогіі. PHP і WordPress, Leaflet і MapLibre GL, OpenFreeMap, чысты JavaScript, REST API, schema.org, адаптыўная вёрстка без фрэймворкаў. Без ключоў API і лімітаў на паказы.
Карта і пошук
Карта — галоўная частка інтэрфейсу, і робіць яна не тое, што звычайны плагін з кропкамі. Яе рухавік — Leaflet, а вектарныя тайлы малюе MapLibre GL; уліковыя запісы і ключы API не патрэбныя, тайлы бяруцца з OpenFreeMap.
- Усе месцы на карце, а не толькі бягучая старонка. Асобны запыт без пагінацыі вяртае каардынаты ўсіх знойдзеных месцаў (ліміт — 5000), таму карта не залежыць ад таго, на якой старонцы спіса знаходзіцца карыстальнік.
- Тры ўзроўні дэталізацыі. Здалёк — маленькія каляровыя кропкі, намаляваныя адным canvas, што забяспечвае хуткую працу. Пачынаючы з сярэдняга маштабу правераныя месцы паказваюцца «пінамі»; зблізку піны са значком катэгорыі атрымліваюць усе месцы ў бачнай вобласці (не больш за 300 адначасова).
- Колер і значок катэгорыі. З бібліятэкі ўбудаваных значкоў выбіраецца прыдатны паводле назвы (полымя для саўн, келіх для бараў, крыж для медыцыны), і яго можна змяніць уручную.
- Пачатковы выгляд — Еўропа. Калі нічога не выбрана, карта адкрываецца на ЕС, а пасля прымянення фільтра падладжваецца пад знойдзеныя месцы. Карта не паўтарае свет па баках і не выходзіць за полюсы.
- Тры стылі («Каляровы», «Светлы», «Цёмны») з захаваннем выбару ў браўзеры; у цёмнай тэме сайта карта сама пераходзіць на светлы стыль. Калі ў наведвальніка няма WebGL або вектарныя тайлы не загрузіліся за 12 секунд, карта аўтаматычна пераключаецца на растр OpenStreetMap.
- Усплывальнае акно месца пры націсканні на пункт ён звязваецца са спісам: картка злева падсвечваецца, а спіс пракручваецца да патрэбнага месца.
- «Паказаць, дзе я». Месцазнаходжанне наведвальніка з колам дакладнасці паказваецца паверх карты, а спіс сартуецца паводле адлегласці з подпісам «км / м ад вас». Геапазіцыянаванне працуе толькі па запыце наведвальніка і толькі праз https.
- Спіс рухаецца ўслед за картай. Калі адзначана «Абнаўляць пры перамяшчэнні карты», у спісе застаюцца месцы з бачнай вобласці, з кнопкай «Паказаць яшчэ» і паведамленнем, калі ў гэтай частцы карты няма месцаў.
- Старонка на ўсю шырыню акна нават унутры вузкай калонкі тэмы; карта «прыліпае» пад шапкай сайта, а вышыню шапкі скрыпт вызначае сам.
Старонка месца
Кожнае месца — гэта асобная старонка са сваім шаблонам: у левай калонцы тэкст, фота і водгукі, у правай — кантакты, карта і гадзіны працы. Шаблон працуе і ў класічных, і ў блокавых тэмах WordPress; тэма можа замяніць яго сваім файлам.

- Галерэя з праглядам фота на ўвесь экран і тры відэа YouTube. Відэа спачатку паказваецца як постар, а плэер загружаецца пасля націскання, таму старонка не падгружае староннія скрыпты.
- Выгоды. Спіс таго, што ёсць, і таго, чаго няма: недаступнае пазначаецца чырвоным крыжыкам, напрыклад «няма безбар'ернага ўваходу».
- Гадзіны працы па днях тыдня (адкрыта, закрыта, кругласутачна). Статус «Зараз адкрыта» вылічваецца ў браўзеры паводле часавога пояса сайта, каб кэш старонкі не паказваў учарашні статус. Начныя графікі, калі клуб працуе да раніцы, улічаны.
- Маршрут. Наведвальнік выбірае «на аўтамабілі / грамадскім транспартам / пешшу», і спасылкі на Google Maps, Яндэкс Карты, Apple Maps, Waze і OpenStreetMap перабудоўваюцца пад гэты рэжым; пачатак — бягучае месцазнаходжанне чалавека.
- Карта месца — той жа рухавік, што і ў каталогу, з тымі ж стылямі і запасным варыянтам.
- «Захаваць» і «Падзяліцца». Раздзел «Абранае» агульны з галоўнай старонкай каталога: захаваныя месцы паказвае адна панэль у левым ніжнім куце.
- Плашка «Даныя не пацверджаны». Калі месца не пазначана як «Праверана», наведвальнік адкрыта ўбачыць, што гадзіны працы і кантактныя даныя могуць быць неактуальнымі, а побач будзе кнопка «Гэта мая арганізацыя».

Водгукі і рэйтынг
Ацэнкі і водгукі працуюць на базе плагіна каментарыяў SDWSKi Comments. Уваход без пароля: код прыходзіць на e-mail, адзін пацверджаны адрас — адна ацэнка месца, якую можна змяніць. Пасля выстаўлення ацэнкі адкрываецца форма водгуку. Рэйтынг бачны і ў картках спіса, а кнопка «Водгукі» вядзе непасрэдна да блока каментарыяў. Для асобнага месца ацэнкі можна адключыць.
Зваротная сувязь
У картцы «Зваротная сувязь» ёсць пяць прычын для звароту: паведаміць пра памылку, «гэта мая арганізацыя», «закрыта або пераехала», паскардзіцца, пакінуць каментарый. Паведамленні захоўваюцца ў панэлі адміністратара і прыходзяць на пошту; калі адпраўнік пакінуў адрас электроннай пошты, адказаць можна непасрэдна з ліста. Абарона ад спаму — схаванае поле-пастка, аднаразовы токен і абмежаванне ў 5 паведамленняў за гадзіну з аднаго IP (захоўваецца толькі хэш адраса).
Заяўкі, мадэрацыя і ўладальнікі месцаў
Каталог напаўняецца з трох крыніц: мною ўручную або з CSV, наведвальнікамі праз форму «Дадаць у каталог» і самімі ўладальнікамі. У публічным спісе і на карце паказваюцца толькі апублікаваныя запісы.
Форма «Дадаць месца»
- Наведвальнік запаўняе форму; ад ботаў абараняюць поле-пастка і абмежаванне — 3 заяўкі за гадзіну з аднаго IP.
- Заяўка захоўваецца са статусам «На зацвярджэнні», а адміністратару адпраўляецца ліст са спасылкай.
- Адрас у фонавым рэжыме ператвараецца ў каардынаты. Існыя краіна і горад прымацоўваюцца адразу, новыя толькі запамінаюцца і ствараюцца пры публікацыі — спіс гарадоў нельга засмеціць заяўкамі.
- Я правяраю заяўку, рэдагую, стаўлю адзнаку «Праверана» і публікую.
Уладальнікі месцаў
Рэстаратар, дырэктар клуба або прадстаўнік НКА націскае «Гэта мая арганізацыя». Гэтая падстава сама па сабе не дае ніякіх правоў: я правяраю чалавека і адным націсканнем даю доступ.
- Ствараецца акаўнт з роляй «Уладальнік месца» без доступу да адмінкі, і чалавеку прыходзіць ліст са спасылкай для задання пароля.
- У асабістым кабінеце ўладальнік бачыць свае месцы і змяняе назву, апісанне, кантакты, гадзіны працы, выгоды, пункт на карце і фота.
- Катэгорыя, краіна і горад, адзнака «Праверана» і ўключэнне водгукаў застаюцца ў кампетэнцыі адміністратара.
- Праўкі публікуюцца адразу, а я атрымліваю ліст «было → стала» па кожным полі: нічога не адбываецца незаўважна.
- Уладальнік можа публікаваць кароткія навіны месца: не больш за тры, чацвёртая выцясняе самую старую. Навіны паказваюцца на старонцы месца і ў любым блоку сайта з дапамогай шорткода.
Інструменты адміністратара
У панэлі кіравання ёсць убудаваная дакументацыя з хуткім стартам, усімі шорткодамі і гатовымі прыкладамі; раздзел «Групаванне гарадоў па краінах» і інструмент лацінскіх адрасоў; налады старонкі месца і рэкламы.
Рэкламныя месцы
Рэклама ўбудаваная ў плагін і наладжваецца ў адным раздзеле панэлі кіравання «Каталог → Рэклама». У каталогу ёсць тры тыпы размяшчэння, і кожны пазначаны надпісам «Рэклама», каб наведвальнік не блытаў яе з месцамі.
| Размяшчэнне | Дзе відаць | Як працуе |
|---|---|---|
| Банер у спісе | паміж карткамі месцаў, на ўсю шырыню калонкі | пасля кожных N картак (N ад 2 да 30, прадвызначана 4); банеры ідуць па крузе, пасля апошняй карткі рэкламы няма |
| Вертыкальны банер каля карты | высокая калонка каля правага краю карты, на экранах ад 1024 px | выява са спасылкай або гатовы HTML-файл; шырыня задаецца ўручную, у HTML-файла прадвызначана 300 px |
| Блок на старонцы месца | у правай калонцы і пад водгукамі | HTML-файлы sidebar.html і comments.html з папкі wp-content/lgbtd-ads/; той жа блок можна ўставіць дзе заўгодна на сайце |
Кожны банер у спісе — гэта або выява са спасылкай, або код рэкламнай сеткі. Пад банерам заўсёды размешчана кнопка «Размясціць банер тут» са спасылкай на старонку куплі рэкламы часопіса, таму каталог сам прыводзіць рэкламадаўцаў да медыяпрапановы.
Дэталі, вартыя асобнай згадкі
- Рэклама жыве разам са спісам. Калі наведвальнік фільтруе месцы, перамяшчае карту або сартуе паводле адлегласці, банеры нанова размяшчаюцца пасля кожных N бачных картак, а не застаюцца там, дзе іх пакінуў сервер.
- Блакіроўшчыкі рэкламы. Блок каля карты мае нейтральныя назвы CSS-класаў без слоў «ad» і «banner», каб яго не хавалі спісы фільтраў.
- Сумленная разметка. Спасылкі банераў адкрываюцца ў новай укладцы з
rel="sponsored nofollow noopener", выявы загружаюцца ляніва. - Кэш. Пасля змены рэкламы плагін sdwski-directory сам скідае кэш папулярных плагінаў (WP Rocket, W3 Total Cache, LiteSpeed, SG Optimizer і інш.), інакш наведвальнікі бачылі б стары банер.
- Дыягностыка для адміністратара. На старонцы налад паказана, што менавіта захавана і чаму банер можа не з'яўляцца; у зыходным кодзе старонкі для адміністратара застаецца службовы каментарый.
- Бяспека. Адвольны код у банерах можа захаваць толькі той, хто мае права
unfiltered_html; у астатніх скрыпты выразаюцца. - HTML-файлы праз FTP. Рэкламны блок можна не набіраць у адмінцы, а загрузіць гатовым файлам з анімацыяй і вёрсткай рэкламадаўца; імя файла правяраецца (лацінка, лічбы,
-і_), каб нельга было выйсці за межы папкі.
Тэхнічныя рашэнні
Увесь каталог — адзін плагін без залежнасцей ад канструктараў і цяжкіх фрэймворкаў: PHP для сервернай часткі, чысты JavaScript для карты і інтэрфейсу, уласны CSS. Са старонняга — толькі Leaflet і MapLibre GL, абодва знаходзяцца ўнутры плагіна.
| Слой | Што выкарыстоўваецца |
|---|---|
| Сервер | WordPress, PHP: тыпы запісаў, таксаноміі, метапалі, REST API, AJAX, уласная табліца рэйтынгаў |
| Карта | Leaflet 1.9.4, MapLibre GL 4.7.1, тайлы OpenFreeMap, рэзерв — OpenStreetMap |
| Геакадаванне | Nominatim (OpenStreetMap), фонавая задача WordPress |
| Кліент | без фрэймворкаў: directory.js (каля 1300 радкоў), single.js, абранае ў localStorage |
| Водгукі | плагін SDWSKi Comments, ацэнкі прывязаны да яго пацверджаных акаўнтаў |
| Пераклад | файлы перакладу ru_RU + інтэграцыя з плагінам перакладу сайта (пошук па перакладзеных назвах, параметр lang у API) |
Прадукцыйнасць
- Тысячы кропак малююцца на адным canvas, паўнавартасныя піны — толькі для бачнай вобласці і не больш за 300 штук.
- Стылі каталога (46 КБ) падключаюцца толькі на старонках, дзе ёсць шорткод каталога, месца або архіў; на астатніх старонках часопіса яны не загружаюцца.
- Версія файла скрыпта фарміруецца з версіі плагіна і часу змянення файла: браўзер не захоўвае старую копію пасля абнаўлення.
- Даныя, якія залежаць ад часу («Адкрыта цяпер»), разлічваюцца ў браўзеры, таму кэшаванне старонак не перашкаджае.
- Карта не залежыць ад платных API: не патрэбныя ключы Google або Mapbox і няма лімітаў на паказы.
Прыватнасць і бяспека
- Абранае і месцазнаходжанне наведвальніка не перадаюцца на сервер: першае захоўваецца ў браўзеры, а другое патрэбна толькі на карце і па запыце.
- Для абмежаванняў на формы захоўваецца толькі хэш IP; адказы формаў абаронены аднаразовымі токенамі і полем-пасткай.
- Уладальнікі месцаў не атрымліваюць доступу да панэлі адміністравання, а кожная ўнесеная імі змена дублюецца лістом адміністратару.
- Для непацверджаных месцаў на старонцы размешчана прамое папярэджанне; у каталогу дапускаюцца толькі пастаянныя даныя, без цэн і анонсаў падзей.
- Пры выдаленні плагіна месцы, катэгорыі і гарады захоўваюцца, пакуль я сам не ўключу поўнае выдаленне ў
wp-config.php. - Плагін пашыраецца фільтрамі WordPress (
lgbtd_rest_place,lgbtd_utm_params,lgbtd_schema_type,lgbtd_map_max_markers,lgbtd_kiosk_paramі іншымі), каб паводзіны змяняліся без рэдагавання ядра.