[{"data":1,"prerenderedAt":834},["ShallowReactive",2],{"api:\u002Fapi\u002Fconfig:ru":3,"api:\u002Fapi\u002Fprofile:":8,"api:\u002Fapi\u002Fstats:":20,"api:\u002Fapi\u002Fcategories:ru":152,"api:\u002Fapi\u002Fprojects:ru":290},{"email":4,"lang":5,"name":6,"role":7},"hello@ewsirdev.example","ru","Ewsirdev","Веб-разработчик: сайты, лендинги и сервисы на Go",{"name":6,"handle":6,"contacts":9,"note":19},{"email":10,"github":13,"telegram":16},{"url":11,"label":4,"placeholder":12},"mailto:hello@ewsirdev.example",true,{"url":14,"label":15},"https:\u002F\u002Fgithub.com\u002Fewsir247","github.com\u002Fewsir247",{"url":17,"label":18},"https:\u002F\u002Ft.me\u002FEwsirdev","@Ewsirdev","email is a placeholder on a reserved domain: mail is not delivered. Telegram is the real channel. This file is the single source of contacts for the site, the contact block, JSON-LD sameAs, security.txt and llms.txt.",{"generated_at":21,"tests_method":22,"note":23,"totals":24,"projects":34},"2026-10-22","go test -list","Lines are non-blank lines. Endpoints are HandleFunc\u002FHandle route patterns (without \u002Fdemo\u002F*). Tests are top-level Test* functions.",{"projects":25,"go_projects":26,"go_lines":27,"go_test_lines":28,"tests":29,"endpoints":30,"html":31,"css":32,"js":33},17,13,26503,12027,418,230,1973,3525,4815,[35,45,54,63,72,79,88,96,102,106,110,114,118,124,132,139,145],{"slug":36,"kind":37,"go_lines":38,"go_test_lines":39,"tests":40,"endpoints":41,"html":42,"css":43,"js":44},"api-gateway","go",2334,1179,48,11,115,139,163,{"slug":46,"kind":37,"go_lines":47,"go_test_lines":48,"tests":49,"endpoints":50,"html":51,"css":52,"js":53},"auth-service",2826,1393,50,35,23,166,500,{"slug":55,"kind":37,"go_lines":56,"go_test_lines":57,"tests":58,"endpoints":59,"html":60,"css":61,"js":62},"booking-slots",891,338,12,18,146,123,309,{"slug":64,"kind":37,"go_lines":65,"go_test_lines":66,"tests":67,"endpoints":68,"html":69,"css":70,"js":71},"finance-tracker",3741,1371,30,45,24,1148,72,{"slug":73,"kind":37,"go_lines":74,"go_test_lines":75,"tests":76,"endpoints":77,"html":78,"css":78,"js":78},"gitpulse",2133,735,32,3,0,{"slug":80,"kind":37,"go_lines":81,"go_test_lines":82,"tests":83,"endpoints":84,"html":85,"css":86,"js":87},"job-queue",2161,833,25,19,138,188,331,{"slug":89,"kind":37,"go_lines":90,"go_test_lines":91,"tests":92,"endpoints":59,"html":93,"css":94,"js":95},"kanban-tasks",871,272,7,102,156,328,{"slug":97,"kind":98,"go_lines":78,"go_test_lines":78,"tests":78,"endpoints":78,"html":99,"css":100,"js":101},"landing-3d","static",201,162,377,{"slug":103,"kind":98,"go_lines":78,"go_test_lines":78,"tests":78,"endpoints":78,"html":60,"css":104,"js":105},"landing-event",122,59,{"slug":107,"kind":98,"go_lines":78,"go_test_lines":78,"tests":78,"endpoints":78,"html":108,"css":109,"js":105},"landing-saas",172,136,{"slug":111,"kind":98,"go_lines":78,"go_test_lines":78,"tests":78,"endpoints":78,"html":112,"css":113,"js":105},"landing-studio",187,109,{"slug":115,"kind":37,"go_lines":56,"go_test_lines":95,"tests":58,"endpoints":41,"html":116,"css":100,"js":117},"link-shortener",119,317,{"slug":119,"kind":37,"go_lines":120,"go_test_lines":90,"tests":76,"endpoints":84,"html":121,"css":122,"js":123},"notes-search",2027,174,192,517,{"slug":125,"kind":37,"go_lines":126,"go_test_lines":127,"tests":128,"endpoints":129,"html":130,"css":122,"js":131},"pixel-wall",2715,1910,77,16,106,625,{"slug":133,"kind":37,"go_lines":134,"go_test_lines":135,"tests":136,"endpoints":26,"html":137,"css":121,"js":138},"raft-kv",2646,895,27,91,213,{"slug":140,"kind":37,"go_lines":141,"go_test_lines":142,"tests":40,"endpoints":92,"html":143,"css":144,"js":123},"realtime-rooms",1822,1313,103,184,{"slug":146,"kind":37,"go_lines":147,"go_test_lines":148,"tests":59,"endpoints":149,"html":150,"css":108,"js":151},"uptime-monitor",1445,589,15,126,369,[153,179,208,234,264],{"slug":154,"title":155,"blurb":156,"variant":157,"palette":158,"layout":159,"count":160,"preview":161,"stack":174},"landings","Лендинги","Одна страница, одна задача. Вёрстка без фреймворков, где это возможно, и один WebGL-эксперимент.","ink","cold","shots",6,[162,166,170],{"slug":111,"title":163,"shot":164,"hue":165},"Полутон: студия света","\u002Fshots\u002Flanding-studio-desktop-sm.webp",212,{"slug":107,"title":167,"shot":168,"hue":169},"Рубильник: трекер подписок","\u002Fshots\u002Flanding-saas-desktop-sm.webp",182,{"slug":103,"title":171,"shot":172,"hue":173},"Малый масштаб: конференция","\u002Fshots\u002Flanding-event-desktop-sm.webp",124,[175,176,177,178],"CSS","HTML","GitHub Actions","JS",{"slug":180,"title":181,"blurb":182,"variant":183,"palette":184,"layout":185,"count":186,"langs":187,"preview":191,"stack":205},"sites","Многостраничные сайты","Сайты со своей структурой, маршрутами и формами: от клиентского проекта до набора нишевых страниц.","honey","mono","frames",4,[188],{"lang":189,"count":190},"TypeScript",1,[192,197,201],{"slug":193,"title":194,"shot":195,"hue":196},"legal-multipage-site","Многостраничный сайт юридической компании","\u002Fshots\u002Flegal-multipage-site-desktop-sm.webp",250,{"slug":198,"title":199,"shot":200,"hue":76},"niche-landings","Каталог демо-лендингов под 10 ниш","\u002Fshots\u002Fniche-landings-desktop-sm.webp",{"slug":202,"title":203,"shot":204,"hue":83},"docs-engine","Сверло: генератор документации на Node.js","\u002Fshots\u002Fdocs-engine-desktop-sm.webp",[177,189,206,207],"Vue 3","Astro",{"slug":209,"title":210,"blurb":211,"variant":212,"palette":213,"layout":214,"count":77,"langs":215,"preview":217,"stack":231},"apps","Веб-приложения","Интерфейс плюс сервер: авторизация, данные, письма. Приложения, в которые входят.","beads","warm","phone",[216],{"lang":189,"count":190},[218,223,227],{"slug":219,"title":220,"shot":221,"hue":222},"bad-club-booking-app","Bad Club: бронирование мест в игровом коворкинге","\u002Fshots\u002Fbad-club-booking-app-desktop-sm.webp",150,{"slug":224,"title":225,"shot":226,"hue":68},"typing-lab","typing-lab: тренажёр слепой печати","\u002Fshots\u002Ftyping-lab-desktop-sm.webp",{"slug":228,"title":229,"shot":230,"hue":68},"budget-split","budget-split: «Поровну», учёт общих расходов","\u002Fshots\u002Fbudget-split-desktop-sm.webp",[189,232,206,233],"Vite","axe",{"slug":235,"title":236,"blurb":237,"variant":238,"palette":239,"layout":240,"count":241,"langs":242,"preview":248,"stack":261},"backend","Бэкенды","Сервисы с API, базой и тестами: в основном на Go, есть и на Python и TypeScript. Фильтр по языку внутри раздела.","ferro","acid","list",14,[243,245,247],{"lang":244,"count":58},"Go",{"lang":246,"count":190},"Python",{"lang":189,"count":190},[249,253,257],{"slug":89,"title":250,"shot":251,"hue":252},"Янтарь: канбан-доска","\u002Fshots\u002Fkanban-tasks-desktop-sm.webp",344,{"slug":115,"title":254,"shot":255,"hue":256},"Короче: сократитель ссылок","\u002Fshots\u002Flink-shortener-desktop-sm.webp",111,{"slug":55,"title":258,"shot":259,"hue":260},"Запись на приём","\u002Fshots\u002Fbooking-slots-desktop-sm.webp",65,[262,244,263,177],"Docker","SQLite",{"slug":265,"title":266,"blurb":267,"variant":268,"palette":158,"layout":269,"count":77,"langs":270,"preview":274,"stack":287},"cli","CLI-утилиты","Программы для терминала: один бинарник, понятные флаги, код выхода, который можно проверить в скрипте.","film","terminal",[271,273],{"lang":244,"count":272},2,{"lang":246,"count":190},[275,278,283],{"slug":73,"title":276,"shot":277,"hue":92},"GitPulse: аналитика git-репозиториев","\u002Fshots\u002Fgitpulse-desktop-sm.webp",{"slug":279,"title":280,"shot":281,"hue":282},"logslice","logslice: анализ логов без зависимостей","\u002Fshots\u002Flogslice-desktop-sm.webp",160,{"slug":284,"title":285,"shot":286,"hue":50},"envguard","envguard: линтер и сейф .env-файлов","\u002Fshots\u002Fenvguard-desktop-sm.webp",[288,262,177,289],"CLI","stdlib only",[291,309,322,334,349,363,376,394,411,430,452,473,497,523,548,570,589,607,627,647,663,677,696,712,729,748,768,787,803,817],{"slug":89,"title":250,"type":235,"category":235,"lang":244,"kind":292,"stack":293,"description":294,"highlights":295,"run":300,"hue":252,"og":301,"shots":302},"api",[244,263,262],"Многопользовательская канбан-доска: регистрация, доски, колонки, карточки с перетаскиванием. Go + SQLite без CGO, фронт встроен в бинарник.",[296,297,298,299],"PBKDF2 и сессии в HttpOnly-cookie","Изоляция данных пользователей","Тесты API","Docker multi-stage","cd kanban-tasks && go run .","\u002Fog\u002Fkanban-tasks.jpg",{"desktop":303,"desktop_sm":251,"mobile":304,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Fkanban-tasks-desktop.webp","\u002Fshots\u002Fkanban-tasks-mobile.webp",1280,800,390,844,{"slug":115,"title":254,"type":235,"category":235,"lang":244,"kind":292,"stack":310,"description":311,"highlights":312,"run":317,"hue":256,"og":318,"shots":319},[244,263,262],"Сокращение ссылок с алиасами и сроком жизни, статистика кликов по дням, браузерам и устройствам, дашборд под токеном. IP не хранятся.",[313,314,315,316],"Редирект и учёт кликов","Лимит запросов","Приватная статистика (хэш с солью)","Тесты и Docker","cd link-shortener && set SEED_DEMO=1&& go run .\u002Fcmd\u002Fserver","\u002Fog\u002Flink-shortener.jpg",{"desktop":320,"desktop_sm":255,"mobile":321,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Flink-shortener-desktop.webp","\u002Fshots\u002Flink-shortener-mobile.webp",{"slug":55,"title":258,"type":235,"category":235,"lang":244,"kind":292,"stack":323,"description":324,"highlights":325,"run":329,"hue":260,"og":330,"shots":331},[244,263,262],"Онлайн-запись на услуги: свободные слоты с учётом длительности и рабочих часов, защита от двойной записи, админ-панель. Вымышленная студия, демо.",[326,327,328,316],"Расчёт свободных слотов","Без двойных записей","Админка для услуг и расписания","cd booking-slots && go run .","\u002Fog\u002Fbooking-slots.jpg",{"desktop":332,"desktop_sm":259,"mobile":333,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Fbooking-slots-desktop.webp","\u002Fshots\u002Fbooking-slots-mobile.webp",{"slug":111,"title":163,"type":335,"category":154,"live_url":336,"stack":337,"description":338,"highlights":339,"run":344,"hue":165,"og":345,"shots":346},"landing","https:\u002F\u002Fewsirdev-studio.pages.dev",[176,175,178],"Лендинг вымышленной студии интерьерного света: тёплая палитра, засечный шрифт, SVG-иллюстрация, FAQ и демо-форма. Адаптивный, без внешних картинок.",[340,341,342,343],"Адаптив 390-1280","SVG вместо картинок","Доступные FAQ и форма","Честная демо-форма","cd landing-studio && python -m http.server 8091","\u002Fog\u002Flanding-studio.jpg",{"desktop":347,"desktop_sm":164,"mobile":348,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Flanding-studio-desktop.webp","\u002Fshots\u002Flanding-studio-mobile.webp",{"slug":107,"title":167,"type":335,"category":154,"live_url":350,"stack":351,"description":352,"highlights":353,"run":358,"hue":169,"og":359,"shots":360},"https:\u002F\u002Fewsirdev-saas.pages.dev",[176,175,178],"Лендинг вымышленного SaaS-продукта: тёмный градиентный hero, макет интерфейса на CSS, тарифы, FAQ, демо-форма. Все цены и названия придуманы.",[354,355,356,357],"Макет интерфейса на CSS","Тарифная сетка","Адаптив","Демо-форма без отправки данных","cd landing-saas && python -m http.server 8092","\u002Fog\u002Flanding-saas.jpg",{"desktop":361,"desktop_sm":168,"mobile":362,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Flanding-saas-desktop.webp","\u002Fshots\u002Flanding-saas-mobile.webp",{"slug":103,"title":171,"type":335,"category":154,"live_url":364,"stack":365,"description":366,"highlights":367,"run":371,"hue":173,"og":372,"shots":373},"https:\u002F\u002Fewsirdev-event.pages.dev",[176,175,178],"Лендинг вымышленной однодневной конференции: плакатная типографика, расписание, спикеры-заглушки, условия, демо-форма записи.",[368,369,356,370],"Расписание дня","Плакатная типографика","Без выдуманных имён спикеров","cd landing-event && python -m http.server 8093","\u002Fog\u002Flanding-event.jpg",{"desktop":374,"desktop_sm":172,"mobile":375,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Flanding-event-desktop.webp","\u002Fshots\u002Flanding-event-mobile.webp",{"slug":146,"title":377,"type":235,"category":235,"lang":244,"kind":378,"stack":379,"description":382,"highlights":383,"run":387,"hue":388,"og":389,"shots":390},"Пульс: монитор доступности","infra",[244,263,380,381,262],"SSE","REST API","Монитор доступности: HTTP и TCP проверки по расписанию, аптайм, p50\u002Fp95, детектор инцидентов, живой дашборд на SSE и публичная статус-страница. Go + SQLite без CGO.",[384,385,386,316],"Горутина-воркер на каждую проверку","Инциденты после серии падений","Дашборд на SSE и публичный \u002Fstatus","cd uptime-monitor && set SEED_DEMO=1&& go run .\u002Fcmd\u002Fserver",101,"\u002Fog\u002Fuptime-monitor.jpg",{"desktop":391,"desktop_sm":392,"mobile":393,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Fuptime-monitor-desktop.webp","\u002Fshots\u002Fuptime-monitor-desktop-sm.webp","\u002Fshots\u002Fuptime-monitor-mobile.webp",{"slug":80,"title":395,"type":235,"category":235,"lang":244,"kind":378,"stack":396,"description":398,"highlights":399,"run":404,"hue":405,"og":406,"shots":407},"Конвейер: очередь задач",[244,263,381,380,397,262],"Prometheus","Очередь фоновых задач: приоритеты, отложенные и cron-задачи, ретраи с backoff и jitter, dead-letter, идемпотентные ключи, lease с fencing, метрики Prometheus.",[400,401,402,403],"At-least-once с lease и fencing","Ретраи с backoff и jitter + dead-letter","Собственный cron-парсер","Метрики Prometheus и graceful shutdown","cd job-queue && set API_TOKEN=demo&& set SEED_DEMO=1&& go run .\u002Fcmd\u002Fserver",249,"\u002Fog\u002Fjob-queue.jpg",{"desktop":408,"desktop_sm":409,"mobile":410,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Fjob-queue-desktop.webp","\u002Fshots\u002Fjob-queue-desktop-sm.webp","\u002Fshots\u002Fjob-queue-mobile.webp",{"slug":140,"title":412,"type":235,"category":235,"lang":244,"kind":413,"stack":414,"description":417,"highlights":418,"run":423,"hue":424,"og":425,"shots":426},"Комнаты: чат и доска в реальном времени","realtime",[244,415,263,416,262],"WebSocket","Canvas","Комнаты в реальном времени: чат с историей в SQLite, список «кто онлайн», индикатор «печатает», общая доска со штрихами и курсорами, анонимные ники. WebSocket (RFC 6455) написан на stdlib.",[419,420,421,422],"Свой слой WebSocket (RFC 6455) на stdlib","Отключение медленных клиентов и лимиты частоты","Graceful shutdown с кодом 1001","Нагрузочный тест: 360 соединений в 6 комнатах","cd realtime-rooms && set SEED_DEMO=1&& go run .\u002Fcmd\u002Fserver",46,"\u002Fog\u002Frealtime-rooms.jpg",{"desktop":427,"desktop_sm":428,"mobile":429,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Frealtime-rooms-desktop.webp","\u002Fshots\u002Frealtime-rooms-desktop-sm.webp","\u002Fshots\u002Frealtime-rooms-mobile.webp",{"slug":36,"title":431,"type":235,"category":235,"lang":244,"kind":378,"stack":432,"description":439,"highlights":440,"run":445,"hue":446,"og":447,"shots":448},"Шлюз: API-gateway",[244,289,433,434,435,380,397,436,437,438,262,177],"Reverse proxy","Circuit breaker","Token bucket","slog","Vanilla JS","embed","API-шлюз на чистой stdlib: маршруты по хосту\u002Fпрефиксу из JSON-конфига с горячей перезагрузкой без обрыва соединений, балансировка round-robin и least-conn, health-checks, circuit breaker на узел, ретраи идемпотентных запросов, rate limit, хэшированные API-ключи, метрики Prometheus, живой дашборд на SSE.",[441,442,443,444],"Ноль зависимостей: только stdlib","Горячая перезагрузка конфига без обрыва соединений","Circuit breaker на узел и ретраи идемпотентных запросов","Нагрузочный тест: 4000 запросов, 40 клиентов (демо-замер)","cd api-gateway && set SEED_DEMO=1&& go run .\u002Fcmd\u002Fgateway",200,"\u002Fog\u002Fapi-gateway.jpg",{"desktop":449,"desktop_sm":450,"mobile":451,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Fapi-gateway-desktop.webp","\u002Fshots\u002Fapi-gateway-desktop-sm.webp","\u002Fshots\u002Fapi-gateway-mobile.webp",{"slug":119,"title":453,"type":235,"category":235,"lang":244,"kind":454,"stack":455,"description":461,"highlights":462,"run":467,"hue":282,"og":468,"shots":469},"Картотека: заметки с поиском","data",[244,263,456,457,458,381,459,460,437,438,262,177],"FTS5","bm25","modernc.org\u002Fsqlite (без CGO)","Markdown (свой безопасный рендер)","SVG force-layout","База Markdown-заметок на Go и SQLite: вики-ссылки [[заметка]] с обратными ссылками и графом связей, полнотекстовый поиск FTS5 (bm25, подсветка, упрощённая русская морфология), история версий с собственным diff, автосохранение с разрешением конфликтов, экспорт и импорт .md.",[463,464,465,466],"Поиск FTS5 с bm25 и подсветкой","Вики-ссылки, backlinks и граф связей","История версий с собственным diff","Свой безопасный Markdown-рендер с тестом на XSS","cd notes-search && set SEED_DEMO=1&& go run .\u002Fcmd\u002Fserver","\u002Fog\u002Fnotes-search.jpg",{"desktop":470,"desktop_sm":471,"mobile":472,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Fnotes-search-desktop.webp","\u002Fshots\u002Fnotes-search-desktop-sm.webp","\u002Fshots\u002Fnotes-search-mobile.webp",{"slug":97,"title":474,"type":335,"category":154,"live_url":475,"stack":476,"description":483,"highlights":484,"run":490,"hue":491,"og":492,"shots":493},"ОКСО Т1: 3D-лендинг","https:\u002F\u002Fewsirdev-3d.pages.dev",[477,478,437,479,480,481,482,177],"HTML5","CSS3","WebGL2","GLSL ES 3.00","Raymarching\u002FSDF","Scroll choreography","Лендинг вымышленного датчика воздуха (демо): объект рисуется одним фрагментным шейдером на чистом WebGL2 без библиотек, четыре SDF-формы перетекают по скроллу, есть SVG-фолбэк, reduced-motion и пауза вне экрана.",[485,486,487,488,489],"Один фрагментный шейдер","WebGL2 без библиотек","Четыре SDF-формы с морфингом по скроллу","SVG-фолбэк и prefers-reduced-motion","Пауза отрисовки вне экрана","cd landing-3d && python -m http.server 8094",90,"\u002Fog\u002Flanding-3d.jpg",{"desktop":494,"desktop_sm":495,"mobile":496,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Flanding-3d-desktop.webp","\u002Fshots\u002Flanding-3d-desktop-sm.webp","\u002Fshots\u002Flanding-3d-mobile.webp",{"slug":133,"title":498,"type":235,"category":235,"lang":244,"kind":454,"stack":499,"description":508,"highlights":509,"run":516,"hue":517,"og":518,"shots":519},"Плот: KV на Raft",[244,500,501,502,289,503,380,504,505,506,507,437,262,177],"Raft","Distributed systems","Consensus","HTTP\u002FJSON","WAL + fsync","Snapshots","Linearizability","Deterministic simulation testing","Учебная реализация Raft с нуля на чистой stdlib: выборы лидера, репликация лога, коммит по кворуму, лог и term\u002Fvote на диске с fsync, снапшоты с компакцией, линеаризуемые чтения (read-index), редирект фолловера на лидера. Тестируется детерминированным симулятором сети и времени с проверкой линеаризуемости; дашборд умеет убивать лидера и рвать сеть (демо).",[510,511,512,513,514,515],"Raft с нуля на stdlib","без raft-библиотек","Детерминированный симулятор сети и времени + проверка линеаризуемости","Лог и term\u002Fvote с fsync","снапшоты и компакция","Дашборд: убить лидера и разорвать сеть (демо)","cd raft-kv && set SEED_DEMO=1&& go run .\u002Fcmd\u002Fraft-kv",290,"\u002Fog\u002Fraft-kv.jpg",{"desktop":520,"desktop_sm":521,"mobile":522,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Fraft-kv-desktop.webp","\u002Fshots\u002Fraft-kv-desktop-sm.webp","\u002Fshots\u002Fraft-kv-mobile.webp",{"slug":46,"title":524,"type":235,"category":235,"lang":244,"kind":525,"stack":526,"description":535,"highlights":536,"run":541,"hue":542,"og":543,"shots":544},"Ключница: сервис аутентификации","auth",[244,527,263,458,528,529,530,531,532,533,534,437,438,262,177],"stdlib crypto","JWT EdDSA\u002FEd25519","JWKS","PBKDF2","TOTP","RBAC","REST","OpenAPI 3","Сервис аутентификации и авторизации на Go: EdDSA-JWT с ротацией ключей и JWKS, refresh-токены с ротацией и обнаружением кражи, TOTP-2FA (RFC 6238) с резервными кодами, RBAC, блокировка при переборе, сброс пароля по одноразовому токену, журнал аудита, список устройств, openapi.yaml. Не прошёл независимый аудит, не production-IdP.",[537,538,539,540],"JWT EdDSA и ротация ключей с JWKS","Refresh-токены с ротацией и reuse-detection","TOTP по RFC 6238 с проверкой на векторах RFC","Журнал аудита только на дозапись (триггеры БД)","cd auth-service && set SEED_DEMO=1&& go run .\u002Fcmd\u002Fserver",20,"\u002Fog\u002Fauth-service.jpg",{"desktop":545,"desktop_sm":546,"mobile":547,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Fauth-service-desktop.webp","\u002Fshots\u002Fauth-service-desktop-sm.webp","\u002Fshots\u002Fauth-service-mobile.webp",{"slug":64,"title":549,"type":235,"category":235,"lang":244,"kind":292,"stack":550,"description":557,"highlights":558,"run":563,"hue":564,"og":565,"shots":566},"Книга учёта: личные финансы",[244,263,458,381,551,206,189,552,553,554,555,262,177,530,556],"Nuxt 4","Pinia","SVG-графики","vitest","ESLint","CSV import\u002Fexport","Учёт личных финансов: счета в разных валютах с ручными курсами, доходы, расходы и переводы, бюджеты, платежи по cron-подобному расписанию, импорт CSV с превью, отчёты. Деньги только в целых минорных единицах, данные пользователей изолированы, графики нарисованы на SVG без библиотек. Go + SQLite и фронтенд на Nuxt 4.",[559,560,561,562],"Деньги только целыми минорными единицами","Мультивалютность с ручными курсами","Импорт CSV с превью и пробным прогоном","Свои SVG-графики без библиотек","cd finance-tracker && set SEED_DEMO=1&& go run .",140,"\u002Fog\u002Ffinance-tracker.jpg",{"desktop":567,"desktop_sm":568,"mobile":569,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Ffinance-tracker-desktop.webp","\u002Fshots\u002Ffinance-tracker-desktop-sm.webp","\u002Fshots\u002Ffinance-tracker-mobile.webp",{"slug":125,"title":571,"type":235,"category":235,"lang":244,"kind":413,"stack":572,"description":576,"highlights":577,"run":582,"hue":583,"og":584,"shots":585},"Пиксельная стена: общий холст",[244,289,415,573,437,438,574,575,262,177],"Canvas 2D","Binary protocol","Snapshot + journal","Совместный холст 256×256 в духе r\u002Fplace: 16 цветов, кулдаун на сессию и IP, свой WebSocket-слой на stdlib (RFC 6455) с бинарным протоколом (4 бита на пиксель), снимок и дельты, снапшот плюс журнал с восстановлением, таймлапс, зум и пан, мини-карта, экспорт PNG, админ-инструменты. Пет-проект.",[578,579,580,581],"Свой WebSocket (RFC 6455) на stdlib","Бинарный протокол: 4 бита на пиксель","Снапшот + журнал с восстановлением после падения","Таймлапс по журналу изменений","cd pixel-wall && set SEED_DEMO=1&& set ADMIN_TOKEN=secret&& go run .\u002Fcmd\u002Fserver",320,"\u002Fog\u002Fpixel-wall.jpg",{"desktop":586,"desktop_sm":587,"mobile":588,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Fpixel-wall-desktop.webp","\u002Fshots\u002Fpixel-wall-desktop-sm.webp","\u002Fshots\u002Fpixel-wall-mobile.webp",{"slug":73,"title":276,"type":265,"category":265,"lang":244,"stack":590,"description":596,"highlights":597,"run":602,"hue":92,"og":603,"shots":604},[244,289,288,591,592,593,594,595,177,262],"git","html\u002Ftemplate","SVG","ANSI","os\u002Fexec","CLI на Go для анализа git-репозиториев без внешних зависимостей (нужен только git): stats с цветами и спарклайнами в терминале, report — самодостаточный HTML-отчёт с тепловой картой активности, churn и горячими файлами, вкладом авторов, bus factor по каталогам, ростом кода по языкам и периодами тишины (светлая и тёмная темы), diff-hotspots между ревизиями и локальный serve на 127.0.0.1. История читается потоком через git log -z --numstat -M. Пет-проект.",[598,599,600,601],"Только stdlib Go, внешний бинарник один: git","Поток git log -z --numstat -M с учётом .mailmap и переименований","Самодостаточный HTML-отчёт: тепловая карта, churn, bus factor, светлая и тёмная темы","Синтетическая история из 100 000 коммитов анализируется около 5 секунд","cd gitpulse && go run .\u002Fcmd\u002Fgitpulse stats .","\u002Fog\u002Fgitpulse.jpg",{"desktop":605,"desktop_sm":277,"mobile":606,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Fgitpulse-desktop.webp","\u002Fshots\u002Fgitpulse-mobile.webp",{"slug":193,"title":194,"type":608,"category":180,"stack":609,"description":614,"highlights":615,"run":622,"hue":196,"og":623,"shots":624},"site",[551,206,189,610,611,612,613,262,177],"Bootstrap 5","Zod","Vitest","Playwright","Реализованный сайт юридической и экспертной компании на Nuxt 4: 65 страниц с серверным рендерингом, JSON-LD разметка и 301-редиректы со старого сайта. Заявки уходят через серверный эндпоинт с проверкой Origin, лимитом размера тела и ограничением частоты запросов.",[616,617,618,619,620,621],"65 маршрутов с SSR, sitemap.xml и robots.txt; индексация включается явным флагом окружения","Форма заявок: серверный эндпоинт, проверка Origin, лимит тела 10 КБ, 3 запроса за 10 минут с одного IP, honeypot, опциональная капча","JSON-LD: LegalService, WebSite, BreadcrumbList","Одношаговые 301-редиректы со старых URL и со слешей на конце, заголовки безопасности (CSP, HSTS)","CI\u002FCD: lint, typecheck, Vitest, сборка, Playwright; затем Docker-образ и выкладка на сервер","210 модульных тестов в 13 файлах и 4 набора e2e-тестов","npm install && npm run build && node .output\u002Fserver\u002Findex.mjs","\u002Fog\u002Flegal-multipage-site.jpg",{"desktop":625,"desktop_sm":195,"mobile":626,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Flegal-multipage-site-desktop.webp","\u002Fshots\u002Flegal-multipage-site-mobile.webp",{"slug":219,"title":220,"type":628,"category":209,"stack":629,"description":636,"highlights":637,"run":642,"hue":222,"og":643,"shots":644},"app",[206,232,552,630,631,632,633,634,635],"Vue Router","GSAP","Express","node:sqlite","JWT (httpOnly cookie)","Resend","Демо-приложение на Vue 3 и Express с SQLite: интерактивная карта зала с бронированием мест, личный кабинет и админ-панель с редактором расстановки. Вход без паролей, по одноразовому коду на e-mail.",[638,639,640,641],"Карта зала с зонами (обычные, тихая, VIP, два монитора), фильтром по типу и статусом мест","Админ-панель: обзор, брони, столы, компьютеры, пользователи и перетаскиваемая расстановка зала","Вход по OTP с ограничением попыток и частоты запросов, роль admin задаётся через переменную окружения","Данные для демо создаются сид-скриптом при первом запуске","npm install && npm run dev","\u002Fog\u002Fbad-club-booking-app.jpg",{"desktop":645,"desktop_sm":221,"mobile":646,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Fbad-club-booking-app-desktop.webp","\u002Fshots\u002Fbad-club-booking-app-mobile.webp",{"slug":648,"title":649,"type":335,"category":154,"live_url":650,"stack":651,"description":652,"highlights":653,"run":642,"hue":657,"og":658,"shots":659},"dovod-concept","Довод: концепт лендинга экспертной организации","https:\u002F\u002Fewsirdev-dovod.pages.dev",[551,206,189,175,177],"Концепт лендинга на Nuxt 4 для вымышленной экспертной организации: направления услуг, форма консультации с маской телефона, карусель отзывов и страница политики. Компания, отзывы, цифры и контакты придуманы; форма ничего не отправляет.",[654,655,656],"Форма с маской телефона, валидацией и подсказками по ошибкам; в демо показывает «данные не отправляются»","Бесконечная карусель отзывов со свайпом и автопрокруткой","Мобильная панель действий, адаптивная вёрстка, скелетон поверх серверного HTML",215,"\u002Fog\u002Fdovod-concept.jpg",{"desktop":660,"desktop_sm":661,"mobile":662,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Fdovod-concept-desktop.webp","\u002Fshots\u002Fdovod-concept-desktop-sm.webp","\u002Fshots\u002Fdovod-concept-mobile.webp",{"slug":198,"title":199,"type":608,"category":180,"live_url":664,"stack":665,"description":668,"highlights":669,"run":642,"hue":76,"og":673,"shots":674},"https:\u002F\u002Fewsirdev-niche.pages.dev",[206,666,667,177],"Vue Router 4","Vite 8","Vue-каталог из десяти самостоятельных лендингов под разные ниши малого бизнеса: у каждого своя палитра, шрифты и структура секций. Каждый лендинг загружается отдельным чанком; весь контент демонстрационный.",[670,671,672],"10 ниш: медицина, мебель, ремонт, онлайн-школа, глэмпинг, юристы, автосервис, салон красоты, кафе, фитнес","Код-сплиттинг по маршрутам, общий набор SVG-иконок","Плашка «Демо-контент» на каталоге и каждом лендинге","\u002Fog\u002Fniche-landings.jpg",{"desktop":675,"desktop_sm":200,"mobile":676,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Fniche-landings-desktop.webp","\u002Fshots\u002Fniche-landings-mobile.webp",{"slug":678,"title":679,"type":335,"category":154,"live_url":680,"stack":681,"description":684,"highlights":685,"run":689,"hue":690,"og":691,"shots":692},"dental-concept","Кварц: концепт лендинга стоматологии","https:\u002F\u002Fewsirdev-dental.pages.dev",[176,175,682,573,683,177],"JavaScript","htmlhint","Концепт одностраничного лендинга вымышленной стоматологии в стиле Liquid Chrome Dark: стеклянные карточки, хромированные заголовки и 3D-блоб в виде зуба на canvas. Один HTML-файл без сборки и зависимостей.",[686,687,688],"Анимированный блоб на canvas с учётом prefers-reduced-motion и видимости на экране","Форма записи с маской телефона и доступными сообщениями об ошибках","CI: htmlhint и проверка локальных ссылок и якорей","python -m http.server 8080",190,"\u002Fog\u002Fdental-concept.jpg",{"desktop":693,"desktop_sm":694,"mobile":695,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Fdental-concept-desktop.webp","\u002Fshots\u002Fdental-concept-desktop-sm.webp","\u002Fshots\u002Fdental-concept-mobile.webp",{"slug":279,"title":280,"type":265,"category":265,"lang":246,"stack":697,"description":701,"highlights":702,"run":707,"hue":282,"og":708,"shots":709},[246,289,288,593,698,699,700,177,262],"pytest","ruff","mypy","CLI на Python 3.11+ только на стандартной библиотеке: потоково разбирает логи nginx\u002Fapache (combined), JSON-lines, logfmt и syslog (gz, bz2, xz тоже), считает статистику и топы, кластеризует похожие ошибки, ищет скачки нагрузки по z-score и EWMA и собирает один HTML-отчёт с SVG-графиками и тепловой картой. Пет-проект.",[703,704,705,706],"Только стандартная библиотека, pip install ничего не тянет","Кластеры ошибок по шаблону и аномалии двумя методами (z-score и EWMA)","Один самодостаточный HTML-отчёт: SVG, тепловая карта, светлая и тёмная темы","53 теста, ruff и mypy --strict; 1 млн строк combined за 8,2 с (один прогон, Windows, CPython 3.12.10)","logslice report access.log -o report.html","\u002Fog\u002Flogslice.jpg",{"desktop":710,"desktop_sm":281,"mobile":711,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Flogslice-desktop.webp","\u002Fshots\u002Flogslice-mobile.webp",{"slug":284,"title":285,"type":265,"category":265,"lang":244,"stack":713,"description":718,"highlights":719,"run":724,"hue":50,"og":725,"shots":726},[244,289,288,714,530,715,716,717,177,262],"AES-256-GCM","fuzzing","govulncheck","gitleaks","CLI на Go без внешних модулей: check сверяет .env со схемой, scan ищет секреты в дереве и git-истории, diff и doctor проверяют окружения и git-гигиену, seal и unseal шифруют .env в .env.sealed (AES-256-GCM, PBKDF2 600 тыс. итераций), run запускает команду с чистым окружением, report и serve строят отчёт. Значение секрета не попадает ни в вывод, ни в лог, ни в HTML. Пет-проект.",[720,721,722,723],"Значения секретов не печатаются нигде: только тип находки, файл, строка и маска из 4 символов","seal и unseal: AES-256-GCM, PBKDF2 600 тыс. итераций, подмена любого бита файла отвергается","Fuzz-тесты: 4 цели по 20 секунд без падений; govulncheck и gitleaks без находок","Сборки под windows, linux и darwin, только стандартная библиотека","go run .\u002Fcmd\u002Fenvguard check","\u002Fog\u002Fenvguard.jpg",{"desktop":727,"desktop_sm":286,"mobile":728,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Fenvguard-desktop.webp","\u002Fshots\u002Fenvguard-mobile.webp",{"slug":730,"title":731,"type":235,"category":235,"lang":246,"stack":732,"description":735,"highlights":736,"run":741,"hue":742,"og":743,"shots":744},"catalog-api","catalog-api: API каталога с поиском",[246,733,263,456,698,699,700,734,262,177],"FastAPI","bandit","API каталога товаров на Python 3.12 и FastAPI: SQLite с полнотекстовым поиском FTS5 (ранжирование bm25), фасеты по категории, цене, наличию, тегам и характеристикам, курсорная пагинация, ETag, импорт и экспорт CSV, история цен, API-ключи с ролями и аудит-лог. Витрина и админка без фреймворка отдаются самим приложением. Пет-проект.",[737,738,739,740],"Поиск FTS5 с bm25, фасеты и курсорная пагинация","API-ключи с ролями admin, editor и reader; в базе только хэши ключей","511 тестов, покрытие 96%; ruff, mypy --strict, bandit, pip-audit и gitleaks без замечаний","Нагрузка: 339 запросов\u002Fс, p95 50 мс при 8 соединениях (Windows, один процесс)","SEED_DEMO=1 python -m app   # http:\u002F\u002F127.0.0.1:8110",265,"\u002Fog\u002Fcatalog-api.jpg",{"desktop":745,"desktop_sm":746,"mobile":747,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Fcatalog-api-desktop.webp","\u002Fshots\u002Fcatalog-api-desktop-sm.webp","\u002Fshots\u002Fcatalog-api-mobile.webp",{"slug":749,"title":750,"type":235,"category":235,"lang":189,"live_url":751,"stack":752,"description":757,"highlights":758,"run":642,"hue":657,"og":763,"shots":764},"paste-vault","Конверт: записки с шифрованием в браузере","https:\u002F\u002Fewsirdev-paste.ewsirdev.workers.dev",[189,753,754,755,232,554,756,177],"Cloudflare Workers","D1","Web Crypto","fast-check","Сервис одноразовых записок на TypeScript, Cloudflare Workers и D1: текст шифруется в браузере (AES-256-GCM), ключ лежит только во фрагменте URL и на сервер не попадает. У записки есть срок жизни, пароль и сгорание после первого прочтения. Пет-проект.",[759,760,761,762],"Шифрование в браузере: AES-256-GCM, ключ только во фрагменте URL","Сгорание после прочтения атомарно: ровно один успех из 40 параллельных чтений","52 теста в рантайме workerd, включая property-тесты и фаззинг схемы","Живая версия на Cloudflare Workers + D1","\u002Fog\u002Fpaste-vault.jpg",{"desktop":765,"desktop_sm":766,"mobile":767,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Fpaste-vault-desktop.webp","\u002Fshots\u002Fpaste-vault-desktop-sm.webp","\u002Fshots\u002Fpaste-vault-mobile.webp",{"slug":202,"title":203,"type":608,"category":180,"live_url":769,"stack":770,"description":776,"highlights":777,"run":782,"hue":83,"og":783,"shots":784},"https:\u002F\u002Fewsirdev-docs.pages.dev",[771,772,773,774,775,177],"Node.js","JavaScript (ESM)","zero dependencies","Markdown","Cloudflare Pages","Генератор статических сайтов документации, написанный с нуля на Node.js без зависимостей: собственный Markdown-парсер, подсветка кода и офлайн-поиск. Демо-сайт про вымышленную библиотеку «Сверло» собран из 43 страниц на двух языках (RU и EN) и двух версиях (v1 и v2). Пет-проект.",[778,779,780,781],"Свой Markdown-парсер, подсветка кода и клиентский поиск без библиотек","43 страницы, RU и EN, версии v1 и v2, hreflang, sitemap и RSS","131 тест; в CI проверка битых ссылок и якорей","Сайт читается без JavaScript, поиск работает офлайн","npm test && npm run build","\u002Fog\u002Fdocs-engine.jpg",{"desktop":785,"desktop_sm":204,"mobile":786,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Fdocs-engine-desktop.webp","\u002Fshots\u002Fdocs-engine-mobile.webp",{"slug":224,"title":225,"type":628,"category":209,"live_url":788,"stack":789,"description":793,"highlights":794,"run":642,"hue":68,"og":799,"shots":800},"https:\u002F\u002Fewsirdev-typing.pages.dev",[551,206,189,790,791,792,593,554,233,775],"IndexedDB","WebAudio","PWA","Тренажёр слепой печати, который целиком работает в браузере и не обращается к серверу: Nuxt 4, история в IndexedDB, звук клавиш на WebAudio, офлайн через PWA. Режимы времени, слов, цитат, своего текста, кода и «слабых мест», шесть раскладок, метрики WPM, точность и консистентность, графики на чистом SVG. Пет-проект.",[795,796,797,798],"Без сервера и аккаунтов: история в IndexedDB, экспорт и импорт JSON","Шесть раскладок, режимы вплоть до адаптивных упражнений из ваших ошибок","59 unit-тестов и 65 e2e-проверок, axe без нарушений, CLS 0,000","PWA: работает офлайн после первого открытия","\u002Fog\u002Ftyping-lab.jpg",{"desktop":801,"desktop_sm":226,"mobile":802,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Ftyping-lab-desktop.webp","\u002Fshots\u002Ftyping-lab-mobile.webp",{"slug":228,"title":229,"type":628,"category":209,"lang":189,"live_url":804,"stack":805,"description":807,"highlights":808,"run":642,"hue":68,"og":813,"shots":814},"https:\u002F\u002Fewsirdev-budget.ewsirdev.workers.dev",[189,232,753,754,806,554,756,233,177],"WebGL","Веб-приложение учёта общих расходов группы без регистрации: комната по секретной ссылке, деление поровну, по долям, суммам и процентам, расчёт «кто кому» не более n−1 переводов. Пет-проект.",[809,810,811,812],"Без аккаунтов: комната по секретной ссылке в 128 бит, отдельные ссылки «просмотр» и «редактирование»","Четыре способа деления и мультивалюта с ручным курсом; расчёт «кто кому» не более n−1 переводов","Оптимистичная блокировка: из 4 одновременных правок одного расхода проходит одна","60 тестов (vitest в workerd, property-тесты fast-check), CI зелёный, npm audit 0, axe 0 нарушений","\u002Fog\u002Fbudget-split.jpg",{"desktop":815,"desktop_sm":230,"mobile":816,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Fbudget-split-desktop.webp","\u002Fshots\u002Fbudget-split-mobile.webp",{"slug":818,"title":819,"type":608,"category":180,"lang":189,"live_url":820,"stack":821,"description":823,"highlights":824,"run":642,"hue":68,"og":829,"shots":830},"kladka-site","kladka-site: «Кладка», демо-сайт студии каркасного строительства","https:\u002F\u002Fewsirdev-kladka.pages.dev",[207,189,822,593,806,233,683,177],"Content collections","Демо-сайт вымышленной студии каркасного строительства: 5 проектов с чертежами, услуги, цены с калькулятором-ориентиром, журнал. Компания, цены и сроки выдуманы, на каждой странице есть пометка.",[825,826,827,828],"24 страницы (19 RU, 4 EN, 404) на Astro 7 со статической сборкой и content collections","Все 20 чертежей рисует код: SVG по данным проекта; 24 картинки OG рендерятся скриптом","Строгий CSP без inline, robots, sitemap с hreflang, llms.txt, security.txt, JSON-LD Organization\u002FService\u002FArticle\u002FFAQPage","756 ссылок и якорей без ошибок, htmlhint 0, axe 0 по всем страницам на 390 и 1280, npm audit 0","\u002Fog\u002Fkladka-site.jpg",{"desktop":831,"desktop_sm":832,"mobile":833,"dw":305,"dh":306,"mw":307,"mh":308},"\u002Fshots\u002Fkladka-site-desktop.webp","\u002Fshots\u002Fkladka-site-desktop-sm.webp","\u002Fshots\u002Fkladka-site-mobile.webp",1793230266013]