[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"technology-uk-typescript":3,"technology-projects-uk-typescript":29,"mdc--2l9gm2-key":104},{"id":4,"title":5,"category":6,"content":7,"description":8,"extension":9,"faq":10,"icon":11,"links":12,"meta":21,"projects":22,"since":25,"stem":26,"updated":27,"__hash__":28},"technologies_uk\u002Fuk\u002Ftechnologies\u002Ftypescript.yml","TypeScript","frontend","TypeScript додає статичну перевірку типів до JavaScript. Я використовую його у Vue- і Nuxt-застосунках, зокрема VetCard та цьому портфоліо, щоб інтерфейси компонентів і моделі даних було простіше розуміти та змінювати.\n\n## Що я типізую\n\n- **Компоненти** — вхідні параметри, події та спільний стан.\n- **Моделі API** — очікувану структуру даних клінік і записів на прийом.\n- **Повторно використовувану логіку** — параметри та результати composable-функцій.\n\nУ цьому репозиторії також є перевірка типів у CI та схеми перекладеного контенту. Вони доповнюють одна одну, але виконують різні завдання.\n\n## Де закінчується статична перевірка\n\nТипи TypeScript видаляються зі згенерованого JavaScript. Анотація типу не перевіряє фактичну відповідь API. Для зовнішніх даних потрібна перевірка під час виконання, а неузгоджена зміна бекенду не з'явиться автоматично як помилка компілятора.\n\n## Зручніша підтримка\n\nКоли змінюється оголошена модель, перевірка типів може показати несумісні місця в коді. Це допомагає послідовно оновити форми й шаблони. Типізація доповнює тести та перевірку введених даних, а не усуває потребу в них.\n","TypeScript для Vue і Nuxt: типізовані компоненти, моделі API та безпечніший рефакторинг із перевіркою зовнішніх даних під час виконання.","yml",null,"i-simple-icons-typescript",[13,18],{"label":14,"to":15,"color":16,"icon":17},"typescriptlang.org","https:\u002F\u002Fwww.typescriptlang.org","neutral","i-heroicons-arrow-top-right-on-square",{"label":19,"to":20,"color":16,"icon":17},"Технічна документація","https:\u002F\u002Fwww.typescriptlang.org\u002Fdocs\u002Fhandbook\u002F2\u002Fbasic-types.html",{},[23,24],"vetcard","vetspace","2020","uk\u002Ftechnologies\u002Ftypescript","2026-09-20","FJAbnj5KfKiRML5YMQJdgMdA6IIuPBJO0-6oBsTQVAk",[30,67],{"id":31,"title":32,"content":33,"date":27,"description":34,"extension":9,"featured":35,"image":36,"links":37,"meta":46,"stack":47,"stem":61,"tags":62,"url":40,"__hash__":66},"projects_uk\u002Fuk\u002Fprojects\u002Fvetcard.yml","VetCard","Публічна частина VetSpace — мультитенантний каталог ветеринарних клінік. Один Nuxt SSR-деплой обслуговує всі клініки: SEO-сторінки клінік, онлайн-запис на прийом з проксуванням до tenant-бекенду кожної клініки, темізація під бренд клініки та підтримка філій.\n\n## Ключові особливості\n\n- **Один деплой — багато клінік** — застосунок маршрутизує за slug клініки; запити на запис і слоти проксуються до власного tenant-бекенду кожної клініки\n- **SEO-first каталог** — 590+ клінік з SSR-сторінками, структурованими даними та локалізованими маршрутами\n- **Брендинг кожної клініки** — сторінка клініки темізується її кольором, з бейджем \"Powered by VetSpace\"\n- **Реальний UX запису** — вільні слоти показують кількість вільних лікарів із кольоровим кодуванням дефіциту\n- **Повна локалізація** — українська, англійська та польська з prefix-маршрутизацією\n\n## Технології\n\n- **Фронтенд**: Nuxt 4 \u002F Vue 3, Tailwind CSS v4\n- **Бекенд**: Laravel catalog API + tenant-ендпоінти для запису\n- **Рендеринг**: SSR для SEO-сторінок, CSR для флоу запису\n- **Тестування**: Vitest юніт-тести + Cypress E2E проти реального бекенду\n","Мультитенантний каталог ветеринарних клінік: SEO-сторінки клінік, онлайн-запис на прийом, брендинг кожної клініки — один Nuxt-застосунок обслуговує всіх",true,"\u002Fhero\u002Fvetcard.avif",[38,42],{"label":39,"to":40,"color":41,"icon":17},"Live Demo","https:\u002F\u002Fvetcard.pro","primary",{"label":43,"to":44,"color":16,"icon":45},"Огляд проєкту","https:\u002F\u002Fgithub.com\u002FYurij2015\u002Fvetspace-vetcard","i-simple-icons-github",{},[48,51,54,55,58],{"name":49,"icon":50},"Nuxt","i-simple-icons-nuxtdotjs",{"name":52,"icon":53},"Vue","i-simple-icons-vuedotjs",{"name":5,"icon":11},{"name":56,"icon":57},"Tailwind CSS","i-simple-icons-tailwindcss",{"name":59,"icon":60},"Laravel API","i-simple-icons-laravel","uk\u002Fprojects\u002Fvetcard",[49,52,63,64,65],"Multi-tenant","SEO","SSR","RHyDtiD49495RNKUgIdwAcH8oiwELVMSL6Ik4JsT6H4",{"id":68,"title":69,"content":70,"date":71,"description":72,"extension":9,"featured":35,"image":73,"links":74,"meta":85,"stack":86,"stem":100,"tags":101,"url":76,"__hash__":103},"projects_uk\u002Fuk\u002Fprojects\u002Fvetspace.yml","VetSpace","Двостороння ветеринарна платформа — SEO-каталог клінік та CRM для підписки з призначеннями та записами пацієнтів. Публічний каталог клінік, побудований для SEO-first набуття клієнтів, та підписка на основі CRM (призначення, візити, записи пацієнтів) як окремі Vue\u002FNuxt додатки над одним Laravel API. Архітектура database-per-tenant, підписки Stripe через Cashier, GraphQL + REST, та аналіз візитів з допомогою AI через присвячений Go мікросервіс.\n\n## Ключові можливості\n\n- **Двостороння воронка** - SEO-каталог залучає клініки, а CRM за підпискою (візити, картки пацієнтів) їх утримує\n- **Справжня ізоляція тенантів** - database-per-tenant тримає дані кожної клініки окремо, а GDPR-експорт\u002Fвидалення — це операція на рівні бази\n- **Дві грані API** - GraphQL для складних запитів каталогу, REST для CRM — одна кодова база Laravel\n- **Білінг із коробки** - підписки Stripe через Cashier: тріали, зміна планів, dunning\n- **AI там, де допомагає** - аналіз візитів виконує окремий Go-мікросервіс, не навантажуючи основний API\n\n## Стек технологій\n\n- **Бекенд**: Laravel (API)\n- **Фронтенд**: Vue\u002FNuxt (окремі застосунки)\n- **Архітектура**: Database-per-tenant multi-tenancy\n- **Платежі**: Stripe через Cashier\n- **API**: GraphQL + REST\n- **AI**: Go-мікросервіс для аналізу візитів\n","2026-09-19","Двостороння ветеринарна платформа — SEO-каталог клінік та CRM для підписки з призначеннями та записами пацієнтів","\u002Fhero\u002Fvetspace.avif",[75,77,80,83],{"label":39,"to":76,"color":41,"icon":17},"https:\u002F\u002Fvetspace.pro",{"label":78,"to":79,"color":16,"icon":45},"Огляд API","https:\u002F\u002Fgithub.com\u002FYurij2015\u002Fvetspace-api",{"label":81,"to":82,"color":16,"icon":45},"Огляд фронтенду","https:\u002F\u002Fgithub.com\u002FYurij2015\u002Fvetspace-frontend",{"label":84,"to":44,"color":16,"icon":45},"Огляд VetCard",{},[87,89,90,91,94,97],{"name":88,"icon":60},"Laravel",{"name":52,"icon":53},{"name":49,"icon":50},{"name":92,"icon":93},"Stripe","i-simple-icons-stripe",{"name":95,"icon":96},"GraphQL","i-simple-icons-graphql",{"name":98,"icon":99},"AI","i-heroicons-sparkles","uk\u002Fprojects\u002Fvetspace",[102,88,52,63,92,98],"SaaS","DG_13GfOpIs-FP9mwOJDR33DOhZ0GdfeSK1u1JLzZt8",{"data":105,"body":106},{},{"type":107,"children":108},"root",[109,117,124,160,165,171,176,182],{"type":110,"tag":111,"props":112,"children":113},"element","p",{},[114],{"type":115,"value":116},"text","TypeScript додає статичну перевірку типів до JavaScript. Я використовую його у Vue- і Nuxt-застосунках, зокрема VetCard та цьому портфоліо, щоб інтерфейси компонентів і моделі даних було простіше розуміти та змінювати.",{"type":110,"tag":118,"props":119,"children":121},"h2",{"id":120},"що-я-типізую",[122],{"type":115,"value":123},"Що я типізую",{"type":110,"tag":125,"props":126,"children":127},"ul",{},[128,140,150],{"type":110,"tag":129,"props":130,"children":131},"li",{},[132,138],{"type":110,"tag":133,"props":134,"children":135},"strong",{},[136],{"type":115,"value":137},"Компоненти",{"type":115,"value":139}," — вхідні параметри, події та спільний стан.",{"type":110,"tag":129,"props":141,"children":142},{},[143,148],{"type":110,"tag":133,"props":144,"children":145},{},[146],{"type":115,"value":147},"Моделі API",{"type":115,"value":149}," — очікувану структуру даних клінік і записів на прийом.",{"type":110,"tag":129,"props":151,"children":152},{},[153,158],{"type":110,"tag":133,"props":154,"children":155},{},[156],{"type":115,"value":157},"Повторно використовувану логіку",{"type":115,"value":159}," — параметри та результати composable-функцій.",{"type":110,"tag":111,"props":161,"children":162},{},[163],{"type":115,"value":164},"У цьому репозиторії також є перевірка типів у CI та схеми перекладеного контенту. Вони доповнюють одна одну, але виконують різні завдання.",{"type":110,"tag":118,"props":166,"children":168},{"id":167},"де-закінчується-статична-перевірка",[169],{"type":115,"value":170},"Де закінчується статична перевірка",{"type":110,"tag":111,"props":172,"children":173},{},[174],{"type":115,"value":175},"Типи TypeScript видаляються зі згенерованого JavaScript. Анотація типу не перевіряє фактичну відповідь API. Для зовнішніх даних потрібна перевірка під час виконання, а неузгоджена зміна бекенду не з'явиться автоматично як помилка компілятора.",{"type":110,"tag":118,"props":177,"children":179},{"id":178},"зручніша-підтримка",[180],{"type":115,"value":181},"Зручніша підтримка",{"type":110,"tag":111,"props":183,"children":184},{},[185],{"type":115,"value":186},"Коли змінюється оголошена модель, перевірка типів може показати несумісні місця в коді. Це допомагає послідовно оновити форми й шаблони. Типізація доповнює тести та перевірку введених даних, а не усуває потребу в них."]