[{"data":1,"prerenderedAt":646},["ShallowReactive",2],{"api:\u002Fapi\u002Fconfig:ru":3,"api:\u002Fapi\u002Fstack:ru":8,"api:\u002Fapi\u002Fstats:":193,"api:\u002Fapi\u002Fprojects:ru":213},{"email":4,"lang":5,"name":6,"role":7},"hello@ewsirdev.example","ru","Ewsirdev","Веб-разработчик: сайты, лендинги и сервисы на Go",{"groups":9,"lang":5,"not":58,"stats":61},[10,25,34,43],{"name":11,"items":12},"Язык и сервер",[13,16,19,22],{"name":14,"note":15},"Go","стандартная библиотека: net\u002Fhttp, embed, log\u002Fslog, context",{"name":17,"note":18},"REST \u002F JSON","API под Bearer-токеном или сессией, ошибки в формате {\"error\": ...}",{"name":20,"note":21},"SSE","живые дашборды в мониторе и очереди задач",{"name":23,"note":24},"WebSocket","собственная реализация RFC 6455 в realtime-rooms",{"name":26,"items":27},"Данные",[28,31],{"name":29,"note":30},"SQLite (modernc.org\u002Fsqlite)","чистый Go, без CGO, режим WAL",{"name":32,"note":33},"SQL (no ORM)","атомарные UPDATE … RETURNING, частичные UNIQUE-индексы, транзакции",{"name":35,"items":36},"Фронтенд",[37,40],{"name":38,"note":39},"HTML, CSS, vanilla JS","без фреймворков в учебных проектах, встроены в бинарник",{"name":41,"note":42},"Canvas","общая доска в realtime-rooms",{"name":44,"items":45},"Качество и поставка",[46,49,52,55],{"name":47,"note":48},"go vet, gofmt, go test","проверяются в CI; go test -race запускается в CI",{"name":50,"note":51},"GitHub Actions","CI в репозиториях проектов",{"name":53,"note":54},"Docker","multi-stage образы проектов",{"name":56,"note":57},"Prometheus","метрики очереди задач на \u002Fmetrics в текстовом формате",[59,60],"Нет опыта, который здесь не показан: фронтенд-фреймворки, ORM, Kubernetes и облачные платформы на этом сайте не заявляются.","Нет распределённых систем: все сервисы рассчитаны на один процесс и один файл SQLite.",{"generated_at":62,"tests_method":63,"note":64,"totals":65,"projects":75},"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":66,"go_projects":67,"go_lines":68,"go_test_lines":69,"tests":70,"endpoints":71,"html":72,"css":73,"js":74},17,13,26503,12027,418,230,1973,3525,4815,[76,86,95,104,113,120,129,137,143,147,151,155,159,165,173,180,186],{"slug":77,"kind":78,"go_lines":79,"go_test_lines":80,"tests":81,"endpoints":82,"html":83,"css":84,"js":85},"api-gateway","go",2334,1179,48,11,115,139,163,{"slug":87,"kind":78,"go_lines":88,"go_test_lines":89,"tests":90,"endpoints":91,"html":92,"css":93,"js":94},"auth-service",2826,1393,50,35,23,166,500,{"slug":96,"kind":78,"go_lines":97,"go_test_lines":98,"tests":99,"endpoints":100,"html":101,"css":102,"js":103},"booking-slots",891,338,12,18,146,123,309,{"slug":105,"kind":78,"go_lines":106,"go_test_lines":107,"tests":108,"endpoints":109,"html":110,"css":111,"js":112},"finance-tracker",3741,1371,30,45,24,1148,72,{"slug":114,"kind":78,"go_lines":115,"go_test_lines":116,"tests":117,"endpoints":118,"html":119,"css":119,"js":119},"gitpulse",2133,735,32,3,0,{"slug":121,"kind":78,"go_lines":122,"go_test_lines":123,"tests":124,"endpoints":125,"html":126,"css":127,"js":128},"job-queue",2161,833,25,19,138,188,331,{"slug":130,"kind":78,"go_lines":131,"go_test_lines":132,"tests":133,"endpoints":100,"html":134,"css":135,"js":136},"kanban-tasks",871,272,7,102,156,328,{"slug":138,"kind":139,"go_lines":119,"go_test_lines":119,"tests":119,"endpoints":119,"html":140,"css":141,"js":142},"landing-3d","static",201,162,377,{"slug":144,"kind":139,"go_lines":119,"go_test_lines":119,"tests":119,"endpoints":119,"html":101,"css":145,"js":146},"landing-event",122,59,{"slug":148,"kind":139,"go_lines":119,"go_test_lines":119,"tests":119,"endpoints":119,"html":149,"css":150,"js":146},"landing-saas",172,136,{"slug":152,"kind":139,"go_lines":119,"go_test_lines":119,"tests":119,"endpoints":119,"html":153,"css":154,"js":146},"landing-studio",187,109,{"slug":156,"kind":78,"go_lines":97,"go_test_lines":136,"tests":99,"endpoints":82,"html":157,"css":141,"js":158},"link-shortener",119,317,{"slug":160,"kind":78,"go_lines":161,"go_test_lines":131,"tests":117,"endpoints":125,"html":162,"css":163,"js":164},"notes-search",2027,174,192,517,{"slug":166,"kind":78,"go_lines":167,"go_test_lines":168,"tests":169,"endpoints":170,"html":171,"css":163,"js":172},"pixel-wall",2715,1910,77,16,106,625,{"slug":174,"kind":78,"go_lines":175,"go_test_lines":176,"tests":177,"endpoints":67,"html":178,"css":162,"js":179},"raft-kv",2646,895,27,91,213,{"slug":181,"kind":78,"go_lines":182,"go_test_lines":183,"tests":81,"endpoints":133,"html":184,"css":185,"js":164},"realtime-rooms",1822,1313,103,184,{"slug":187,"kind":78,"go_lines":188,"go_test_lines":189,"tests":100,"endpoints":190,"html":191,"css":149,"js":192},"uptime-monitor",1445,589,15,126,369,{"generated_at":62,"tests_method":63,"note":64,"totals":194,"projects":195},{"projects":66,"go_projects":67,"go_lines":68,"go_test_lines":69,"tests":70,"endpoints":71,"html":72,"css":73,"js":74},[196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212],{"slug":77,"kind":78,"go_lines":79,"go_test_lines":80,"tests":81,"endpoints":82,"html":83,"css":84,"js":85},{"slug":87,"kind":78,"go_lines":88,"go_test_lines":89,"tests":90,"endpoints":91,"html":92,"css":93,"js":94},{"slug":96,"kind":78,"go_lines":97,"go_test_lines":98,"tests":99,"endpoints":100,"html":101,"css":102,"js":103},{"slug":105,"kind":78,"go_lines":106,"go_test_lines":107,"tests":108,"endpoints":109,"html":110,"css":111,"js":112},{"slug":114,"kind":78,"go_lines":115,"go_test_lines":116,"tests":117,"endpoints":118,"html":119,"css":119,"js":119},{"slug":121,"kind":78,"go_lines":122,"go_test_lines":123,"tests":124,"endpoints":125,"html":126,"css":127,"js":128},{"slug":130,"kind":78,"go_lines":131,"go_test_lines":132,"tests":133,"endpoints":100,"html":134,"css":135,"js":136},{"slug":138,"kind":139,"go_lines":119,"go_test_lines":119,"tests":119,"endpoints":119,"html":140,"css":141,"js":142},{"slug":144,"kind":139,"go_lines":119,"go_test_lines":119,"tests":119,"endpoints":119,"html":101,"css":145,"js":146},{"slug":148,"kind":139,"go_lines":119,"go_test_lines":119,"tests":119,"endpoints":119,"html":149,"css":150,"js":146},{"slug":152,"kind":139,"go_lines":119,"go_test_lines":119,"tests":119,"endpoints":119,"html":153,"css":154,"js":146},{"slug":156,"kind":78,"go_lines":97,"go_test_lines":136,"tests":99,"endpoints":82,"html":157,"css":141,"js":158},{"slug":160,"kind":78,"go_lines":161,"go_test_lines":131,"tests":117,"endpoints":125,"html":162,"css":163,"js":164},{"slug":166,"kind":78,"go_lines":167,"go_test_lines":168,"tests":169,"endpoints":170,"html":171,"css":163,"js":172},{"slug":174,"kind":78,"go_lines":175,"go_test_lines":176,"tests":177,"endpoints":67,"html":178,"css":162,"js":179},{"slug":181,"kind":78,"go_lines":182,"go_test_lines":183,"tests":81,"endpoints":133,"html":184,"css":185,"js":164},{"slug":187,"kind":78,"go_lines":188,"go_test_lines":189,"tests":100,"endpoints":190,"html":191,"css":149,"js":192},[214,236,252,267,287,303,318,334,350,366,389,410,433,459,483,507,526,548,572,597,612,628],{"slug":130,"title":215,"type":216,"stack":217,"description":219,"highlights":220,"run":225,"hue":226,"og":227,"shots":228},"Янтарь: канбан-доска","backend",[14,218,53],"SQLite","Многопользовательская канбан-доска: регистрация, доски, колонки, карточки с перетаскиванием. Go + SQLite без CGO, фронт встроен в бинарник.",[221,222,223,224],"PBKDF2 и сессии в HttpOnly-cookie","Изоляция данных пользователей","Тесты API","Docker multi-stage","cd kanban-tasks && go run .",344,"\u002Fog\u002Fkanban-tasks.jpg",{"desktop":229,"desktop_sm":230,"mobile":231,"dw":232,"dh":233,"mw":234,"mh":235},"\u002Fshots\u002Fkanban-tasks-desktop.webp","\u002Fshots\u002Fkanban-tasks-desktop-sm.webp","\u002Fshots\u002Fkanban-tasks-mobile.webp",1280,800,390,844,{"slug":156,"title":237,"type":216,"stack":238,"description":239,"highlights":240,"run":245,"hue":246,"og":247,"shots":248},"Короче: сократитель ссылок",[14,218,53],"Сокращение ссылок с алиасами и сроком жизни, статистика кликов по дням, браузерам и устройствам, дашборд под токеном. IP не хранятся.",[241,242,243,244],"Редирект и учёт кликов","Лимит запросов","Приватная статистика (хэш с солью)","Тесты и Docker","cd link-shortener && set SEED_DEMO=1&& go run .\u002Fcmd\u002Fserver",111,"\u002Fog\u002Flink-shortener.jpg",{"desktop":249,"desktop_sm":250,"mobile":251,"dw":232,"dh":233,"mw":234,"mh":235},"\u002Fshots\u002Flink-shortener-desktop.webp","\u002Fshots\u002Flink-shortener-desktop-sm.webp","\u002Fshots\u002Flink-shortener-mobile.webp",{"slug":96,"title":253,"type":216,"stack":254,"description":255,"highlights":256,"run":260,"hue":261,"og":262,"shots":263},"Запись на приём",[14,218,53],"Онлайн-запись на услуги: свободные слоты с учётом длительности и рабочих часов, защита от двойной записи, админ-панель. Вымышленная студия, демо.",[257,258,259,244],"Расчёт свободных слотов","Без двойных записей","Админка для услуг и расписания","cd booking-slots && go run .",65,"\u002Fog\u002Fbooking-slots.jpg",{"desktop":264,"desktop_sm":265,"mobile":266,"dw":232,"dh":233,"mw":234,"mh":235},"\u002Fshots\u002Fbooking-slots-desktop.webp","\u002Fshots\u002Fbooking-slots-desktop-sm.webp","\u002Fshots\u002Fbooking-slots-mobile.webp",{"slug":152,"title":268,"type":269,"stack":270,"description":274,"highlights":275,"run":280,"hue":281,"og":282,"shots":283},"Полутон: студия света","landing",[271,272,273],"HTML","CSS","JS","Лендинг вымышленной студии интерьерного света: тёплая палитра, засечный шрифт, SVG-иллюстрация, FAQ и демо-форма. Адаптивный, без внешних картинок.",[276,277,278,279],"Адаптив 390-1280","SVG вместо картинок","Доступные FAQ и форма","Честная демо-форма","cd landing-studio && python -m http.server 8091",212,"\u002Fog\u002Flanding-studio.jpg",{"desktop":284,"desktop_sm":285,"mobile":286,"dw":232,"dh":233,"mw":234,"mh":235},"\u002Fshots\u002Flanding-studio-desktop.webp","\u002Fshots\u002Flanding-studio-desktop-sm.webp","\u002Fshots\u002Flanding-studio-mobile.webp",{"slug":148,"title":288,"type":269,"stack":289,"description":290,"highlights":291,"run":296,"hue":297,"og":298,"shots":299},"Рубильник: трекер подписок",[271,272,273],"Лендинг вымышленного SaaS-продукта: тёмный градиентный hero, макет интерфейса на CSS, тарифы, FAQ, демо-форма. Все цены и названия придуманы.",[292,293,294,295],"Макет интерфейса на CSS","Тарифная сетка","Адаптив","Демо-форма без отправки данных","cd landing-saas && python -m http.server 8092",182,"\u002Fog\u002Flanding-saas.jpg",{"desktop":300,"desktop_sm":301,"mobile":302,"dw":232,"dh":233,"mw":234,"mh":235},"\u002Fshots\u002Flanding-saas-desktop.webp","\u002Fshots\u002Flanding-saas-desktop-sm.webp","\u002Fshots\u002Flanding-saas-mobile.webp",{"slug":144,"title":304,"type":269,"stack":305,"description":306,"highlights":307,"run":311,"hue":312,"og":313,"shots":314},"Малый масштаб: конференция",[271,272,273],"Лендинг вымышленной однодневной конференции: плакатная типографика, расписание, спикеры-заглушки, условия, демо-форма записи.",[308,309,294,310],"Расписание дня","Плакатная типографика","Без выдуманных имён спикеров","cd landing-event && python -m http.server 8093",124,"\u002Fog\u002Flanding-event.jpg",{"desktop":315,"desktop_sm":316,"mobile":317,"dw":232,"dh":233,"mw":234,"mh":235},"\u002Fshots\u002Flanding-event-desktop.webp","\u002Fshots\u002Flanding-event-desktop-sm.webp","\u002Fshots\u002Flanding-event-mobile.webp",{"slug":187,"title":319,"type":216,"stack":320,"description":322,"highlights":323,"run":327,"hue":328,"og":329,"shots":330},"Пульс: монитор доступности",[14,218,20,321,53],"REST API","Монитор доступности: HTTP и TCP проверки по расписанию, аптайм, p50\u002Fp95, детектор инцидентов, живой дашборд на SSE и публичная статус-страница. Go + SQLite без CGO.",[324,325,326,244],"Горутина-воркер на каждую проверку","Инциденты после серии падений","Дашборд на SSE и публичный \u002Fstatus","cd uptime-monitor && set SEED_DEMO=1&& go run .\u002Fcmd\u002Fserver",101,"\u002Fog\u002Fuptime-monitor.jpg",{"desktop":331,"desktop_sm":332,"mobile":333,"dw":232,"dh":233,"mw":234,"mh":235},"\u002Fshots\u002Fuptime-monitor-desktop.webp","\u002Fshots\u002Fuptime-monitor-desktop-sm.webp","\u002Fshots\u002Fuptime-monitor-mobile.webp",{"slug":121,"title":335,"type":216,"stack":336,"description":337,"highlights":338,"run":343,"hue":344,"og":345,"shots":346},"Конвейер: очередь задач",[14,218,321,20,56,53],"Очередь фоновых задач: приоритеты, отложенные и cron-задачи, ретраи с backoff и jitter, dead-letter, идемпотентные ключи, lease с fencing, метрики Prometheus.",[339,340,341,342],"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":347,"desktop_sm":348,"mobile":349,"dw":232,"dh":233,"mw":234,"mh":235},"\u002Fshots\u002Fjob-queue-desktop.webp","\u002Fshots\u002Fjob-queue-desktop-sm.webp","\u002Fshots\u002Fjob-queue-mobile.webp",{"slug":181,"title":351,"type":216,"stack":352,"description":353,"highlights":354,"run":359,"hue":360,"og":361,"shots":362},"Комнаты: чат и доска в реальном времени",[14,23,218,41,53],"Комнаты в реальном времени: чат с историей в SQLite, список «кто онлайн», индикатор «печатает», общая доска со штрихами и курсорами, анонимные ники. WebSocket (RFC 6455) написан на stdlib.",[355,356,357,358],"Свой слой 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":363,"desktop_sm":364,"mobile":365,"dw":232,"dh":233,"mw":234,"mh":235},"\u002Fshots\u002Frealtime-rooms-desktop.webp","\u002Fshots\u002Frealtime-rooms-desktop-sm.webp","\u002Fshots\u002Frealtime-rooms-mobile.webp",{"slug":77,"title":367,"type":216,"stack":368,"description":376,"highlights":377,"run":382,"hue":383,"og":384,"shots":385},"Шлюз: API-gateway",[14,369,370,371,372,20,56,373,374,375,53,50],"stdlib only","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.",[378,379,380,381],"Ноль зависимостей: только stdlib","Горячая перезагрузка конфига без обрыва соединений","Circuit breaker на узел и ретраи идемпотентных запросов","Нагрузочный тест: 4000 запросов, 40 клиентов (демо-замер)","cd api-gateway && set SEED_DEMO=1&& go run .\u002Fcmd\u002Fgateway",200,"\u002Fog\u002Fapi-gateway.jpg",{"desktop":386,"desktop_sm":387,"mobile":388,"dw":232,"dh":233,"mw":234,"mh":235},"\u002Fshots\u002Fapi-gateway-desktop.webp","\u002Fshots\u002Fapi-gateway-desktop-sm.webp","\u002Fshots\u002Fapi-gateway-mobile.webp",{"slug":160,"title":390,"type":216,"stack":391,"description":397,"highlights":398,"run":403,"hue":404,"og":405,"shots":406},"Картотека: заметки с поиском",[14,218,392,393,394,321,395,396,374,375,53,50],"FTS5","bm25","modernc.org\u002Fsqlite (без CGO)","Markdown (свой безопасный рендер)","SVG force-layout","База Markdown-заметок на Go и SQLite: вики-ссылки [[заметка]] с обратными ссылками и графом связей, полнотекстовый поиск FTS5 (bm25, подсветка, упрощённая русская морфология), история версий с собственным diff, автосохранение с разрешением конфликтов, экспорт и импорт .md.",[399,400,401,402],"Поиск FTS5 с bm25 и подсветкой","Вики-ссылки, backlinks и граф связей","История версий с собственным diff","Свой безопасный Markdown-рендер с тестом на XSS","cd notes-search && set SEED_DEMO=1&& go run .\u002Fcmd\u002Fserver",160,"\u002Fog\u002Fnotes-search.jpg",{"desktop":407,"desktop_sm":408,"mobile":409,"dw":232,"dh":233,"mw":234,"mh":235},"\u002Fshots\u002Fnotes-search-desktop.webp","\u002Fshots\u002Fnotes-search-desktop-sm.webp","\u002Fshots\u002Fnotes-search-mobile.webp",{"slug":138,"title":411,"type":269,"stack":412,"description":419,"highlights":420,"run":426,"hue":427,"og":428,"shots":429},"ОКСО Т1: 3D-лендинг",[413,414,374,415,416,417,418,50],"HTML5","CSS3","WebGL2","GLSL ES 3.00","Raymarching\u002FSDF","Scroll choreography","Лендинг вымышленного датчика воздуха (демо): объект рисуется одним фрагментным шейдером на чистом WebGL2 без библиотек, четыре SDF-формы перетекают по скроллу, есть SVG-фолбэк, reduced-motion и пауза вне экрана.",[421,422,423,424,425],"Один фрагментный шейдер","WebGL2 без библиотек","Четыре SDF-формы с морфингом по скроллу","SVG-фолбэк и prefers-reduced-motion","Пауза отрисовки вне экрана","cd landing-3d && python -m http.server 8094",90,"\u002Fog\u002Flanding-3d.jpg",{"desktop":430,"desktop_sm":431,"mobile":432,"dw":232,"dh":233,"mw":234,"mh":235},"\u002Fshots\u002Flanding-3d-desktop.webp","\u002Fshots\u002Flanding-3d-desktop-sm.webp","\u002Fshots\u002Flanding-3d-mobile.webp",{"slug":174,"title":434,"type":216,"stack":435,"description":444,"highlights":445,"run":452,"hue":453,"og":454,"shots":455},"Плот: KV на Raft",[14,436,437,438,369,439,20,440,441,442,443,374,53,50],"Raft","Distributed systems","Consensus","HTTP\u002FJSON","WAL + fsync","Snapshots","Linearizability","Deterministic simulation testing","Учебная реализация Raft с нуля на чистой stdlib: выборы лидера, репликация лога, коммит по кворуму, лог и term\u002Fvote на диске с fsync, снапшоты с компакцией, линеаризуемые чтения (read-index), редирект фолловера на лидера. Тестируется детерминированным симулятором сети и времени с проверкой линеаризуемости; дашборд умеет убивать лидера и рвать сеть (демо).",[446,447,448,449,450,451],"Raft с нуля на stdlib","без raft-библиотек","Детерминированный симулятор сети и времени + проверка линеаризуемости","Лог и term\u002Fvote с fsync","снапшоты и компакция","Дашборд: убить лидера и разорвать сеть (демо)","cd raft-kv && set SEED_DEMO=1&& go run .\u002Fcmd\u002Fraft-kv",290,"\u002Fog\u002Fraft-kv.jpg",{"desktop":456,"desktop_sm":457,"mobile":458,"dw":232,"dh":233,"mw":234,"mh":235},"\u002Fshots\u002Fraft-kv-desktop.webp","\u002Fshots\u002Fraft-kv-desktop-sm.webp","\u002Fshots\u002Fraft-kv-mobile.webp",{"slug":87,"title":460,"type":216,"stack":461,"description":470,"highlights":471,"run":476,"hue":477,"og":478,"shots":479},"Ключница: сервис аутентификации",[14,462,218,394,463,464,465,466,467,468,469,374,375,53,50],"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.",[472,473,474,475],"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":480,"desktop_sm":481,"mobile":482,"dw":232,"dh":233,"mw":234,"mh":235},"\u002Fshots\u002Fauth-service-desktop.webp","\u002Fshots\u002Fauth-service-desktop-sm.webp","\u002Fshots\u002Fauth-service-mobile.webp",{"slug":105,"title":484,"type":216,"stack":485,"description":494,"highlights":495,"run":500,"hue":501,"og":502,"shots":503},"Книга учёта: личные финансы",[14,218,394,321,486,487,488,489,490,491,492,53,50,465,493],"Nuxt 4","Vue 3","TypeScript","Pinia","SVG-графики","vitest","ESLint","CSV import\u002Fexport","Учёт личных финансов: счета в разных валютах с ручными курсами, доходы, расходы и переводы, бюджеты, платежи по cron-подобному расписанию, импорт CSV с превью, отчёты. Деньги только в целых минорных единицах, данные пользователей изолированы, графики нарисованы на SVG без библиотек. Go + SQLite и фронтенд на Nuxt 4.",[496,497,498,499],"Деньги только целыми минорными единицами","Мультивалютность с ручными курсами","Импорт CSV с превью и пробным прогоном","Свои SVG-графики без библиотек","cd finance-tracker && set SEED_DEMO=1&& go run .",140,"\u002Fog\u002Ffinance-tracker.jpg",{"desktop":504,"desktop_sm":505,"mobile":506,"dw":232,"dh":233,"mw":234,"mh":235},"\u002Fshots\u002Ffinance-tracker-desktop.webp","\u002Fshots\u002Ffinance-tracker-desktop-sm.webp","\u002Fshots\u002Ffinance-tracker-mobile.webp",{"slug":166,"title":508,"type":216,"stack":509,"description":513,"highlights":514,"run":519,"hue":520,"og":521,"shots":522},"Пиксельная стена: общий холст",[14,369,23,510,374,375,511,512,53,50],"Canvas 2D","Binary protocol","Snapshot + journal","Совместный холст 256×256 в духе r\u002Fplace: 16 цветов, кулдаун на сессию и IP, свой WebSocket-слой на stdlib (RFC 6455) с бинарным протоколом (4 бита на пиксель), снимок и дельты, снапшот плюс журнал с восстановлением, таймлапс, зум и пан, мини-карта, экспорт PNG, админ-инструменты. Пет-проект.",[515,516,517,518],"Свой 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":523,"desktop_sm":524,"mobile":525,"dw":232,"dh":233,"mw":234,"mh":235},"\u002Fshots\u002Fpixel-wall-desktop.webp","\u002Fshots\u002Fpixel-wall-desktop-sm.webp","\u002Fshots\u002Fpixel-wall-mobile.webp",{"slug":114,"title":527,"type":528,"stack":529,"description":536,"highlights":537,"run":542,"hue":133,"og":543,"shots":544},"GitPulse: аналитика git-репозиториев","cli",[14,369,530,531,532,533,534,535,50,53],"CLI","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. Пет-проект.",[538,539,540,541],"Только 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":545,"desktop_sm":546,"mobile":547,"dw":232,"dh":233,"mw":234,"mh":235},"\u002Fshots\u002Fgitpulse-desktop.webp","\u002Fshots\u002Fgitpulse-desktop-sm.webp","\u002Fshots\u002Fgitpulse-mobile.webp",{"slug":549,"title":550,"type":551,"stack":552,"description":557,"highlights":558,"run":565,"hue":566,"og":567,"shots":568},"legal-multipage-site","Многостраничный сайт юридической компании","site",[486,487,488,553,554,555,556,53,50],"Bootstrap 5","Zod","Vitest","Playwright","Реализованный сайт юридической и экспертной компании на Nuxt 4: 65 страниц с серверным рендерингом, JSON-LD разметка и 301-редиректы со старого сайта. Заявки уходят через серверный эндпоинт с проверкой Origin, лимитом размера тела и ограничением частоты запросов.",[559,560,561,562,563,564],"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",250,"\u002Fog\u002Flegal-multipage-site.jpg",{"desktop":569,"desktop_sm":570,"mobile":571,"dw":232,"dh":233,"mw":234,"mh":235},"\u002Fshots\u002Flegal-multipage-site-desktop.webp","\u002Fshots\u002Flegal-multipage-site-desktop-sm.webp","\u002Fshots\u002Flegal-multipage-site-mobile.webp",{"slug":573,"title":574,"type":575,"stack":576,"description":584,"highlights":585,"run":590,"hue":591,"og":592,"shots":593},"bad-club-booking-app","Bad Club: бронирование мест в игровом коворкинге","app",[487,577,489,578,579,580,581,582,583],"Vite","Vue Router","GSAP","Express","node:sqlite","JWT (httpOnly cookie)","Resend","Демо-приложение на Vue 3 и Express с SQLite: интерактивная карта зала с бронированием мест, личный кабинет и админ-панель с редактором расстановки. Вход без паролей, по одноразовому коду на e-mail.",[586,587,588,589],"Карта зала с зонами (обычные, тихая, VIP, два монитора), фильтром по типу и статусом мест","Админ-панель: обзор, брони, столы, компьютеры, пользователи и перетаскиваемая расстановка зала","Вход по OTP с ограничением попыток и частоты запросов, роль admin задаётся через переменную окружения","Данные для демо создаются сид-скриптом при первом запуске","npm install && npm run dev",150,"\u002Fog\u002Fbad-club-booking-app.jpg",{"desktop":594,"desktop_sm":595,"mobile":596,"dw":232,"dh":233,"mw":234,"mh":235},"\u002Fshots\u002Fbad-club-booking-app-desktop.webp","\u002Fshots\u002Fbad-club-booking-app-desktop-sm.webp","\u002Fshots\u002Fbad-club-booking-app-mobile.webp",{"slug":598,"title":599,"type":269,"stack":600,"description":601,"highlights":602,"run":590,"hue":606,"og":607,"shots":608},"dovod-concept","Довод: концепт лендинга экспертной организации",[486,487,488,272,50],"Концепт лендинга на Nuxt 4 для вымышленной экспертной организации: направления услуг, форма консультации с маской телефона, карусель отзывов и страница политики. Компания, отзывы, цифры и контакты придуманы; форма ничего не отправляет.",[603,604,605],"Форма с маской телефона, валидацией и подсказками по ошибкам; в демо показывает «данные не отправляются»","Бесконечная карусель отзывов со свайпом и автопрокруткой","Мобильная панель действий, адаптивная вёрстка, скелетон поверх серверного HTML",215,"\u002Fog\u002Fdovod-concept.jpg",{"desktop":609,"desktop_sm":610,"mobile":611,"dw":232,"dh":233,"mw":234,"mh":235},"\u002Fshots\u002Fdovod-concept-desktop.webp","\u002Fshots\u002Fdovod-concept-desktop-sm.webp","\u002Fshots\u002Fdovod-concept-mobile.webp",{"slug":613,"title":614,"type":551,"stack":615,"description":618,"highlights":619,"run":590,"hue":117,"og":623,"shots":624},"niche-landings","Каталог демо-лендингов под 10 ниш",[487,616,617,50],"Vue Router 4","Vite 8","Vue-каталог из десяти самостоятельных лендингов под разные ниши малого бизнеса: у каждого своя палитра, шрифты и структура секций. Каждый лендинг загружается отдельным чанком; весь контент демонстрационный.",[620,621,622],"10 ниш: медицина, мебель, ремонт, онлайн-школа, глэмпинг, юристы, автосервис, салон красоты, кафе, фитнес","Код-сплиттинг по маршрутам, общий набор SVG-иконок","Плашка «Демо-контент» на каталоге и каждом лендинге","\u002Fog\u002Fniche-landings.jpg",{"desktop":625,"desktop_sm":626,"mobile":627,"dw":232,"dh":233,"mw":234,"mh":235},"\u002Fshots\u002Fniche-landings-desktop.webp","\u002Fshots\u002Fniche-landings-desktop-sm.webp","\u002Fshots\u002Fniche-landings-mobile.webp",{"slug":629,"title":630,"type":269,"stack":631,"description":634,"highlights":635,"run":639,"hue":640,"og":641,"shots":642},"dental-concept","Кварц: концепт лендинга стоматологии",[271,272,632,510,633,50],"JavaScript","htmlhint","Концепт одностраничного лендинга вымышленной стоматологии в стиле Liquid Chrome Dark: стеклянные карточки, хромированные заголовки и 3D-блоб в виде зуба на canvas. Один HTML-файл без сборки и зависимостей.",[636,637,638],"Анимированный блоб на canvas с учётом prefers-reduced-motion и видимости на экране","Форма записи с маской телефона и доступными сообщениями об ошибках","CI: htmlhint и проверка локальных ссылок и якорей","python -m http.server 8080",190,"\u002Fog\u002Fdental-concept.jpg",{"desktop":643,"desktop_sm":644,"mobile":645,"dw":232,"dh":233,"mw":234,"mh":235},"\u002Fshots\u002Fdental-concept-desktop.webp","\u002Fshots\u002Fdental-concept-desktop-sm.webp","\u002Fshots\u002Fdental-concept-mobile.webp",1792697892477]