[{"data":1,"prerenderedAt":331},["ShallowReactive",2],{"project-case-brendmart":3},[4,13,19,78,94,111,129,262,294,318,324],{"component":5,"data":6},"ProjectCaseHeader",{"index":7,"subtitle":8,"name":9,"headline":10,"url":11,"tone":12},"02","ONLINE STORE · DELIVERY FROM EUROPE","Brendmart","600+ orders a month by the time of handover","https:\u002F\u002Fbrendmart.com\u002F","secondary",{"component":14,"data":15},"ProjectCaseCover",{"image":16,"imageMobile":17,"imageAlt":18},"brendmart\u002Fmedia\u002Fpreview.webp","brendmart\u002Fmedia\u002Fpreview-mobile.webp","Home page of the Brendmart website",{"component":20,"data":21},"ProjectCaseMeta",{"tags":22,"stack":26},[23,24,25],"E-commerce","Full-Stack","SEO",[27,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76],{"label":28,"own":29},"Nuxt 4",true,{"label":31,"own":29},"Vue 3",{"label":33,"own":29},"Pinia",{"label":35,"own":29},"Nuxt i18n",{"label":37,"own":29},"Nuxt Icon",{"label":39,"own":29},"zod",{"label":41,"own":29},"VueUse",{"label":43,"own":29},"Tailwind CSS",{"label":45,"own":29},"daisyUI",{"label":47,"own":29},"Laravel",{"label":49},"Go",{"label":51},"PostgreSQL",{"label":53},"Redis",{"label":55},"RabbitMQ",{"label":57},"S3 \u002F MinIO",{"label":59},"ClickHouse",{"label":61},"Elasticsearch",{"label":63},"Docker",{"label":65},"Traefik",{"label":67},"Kubernetes",{"label":69},"Argo CD",{"label":71},"GitLab CI",{"label":73},"ELK",{"label":75},"Grafana",{"label":77},"Prometheus",{"component":79,"data":80},"ProjectCaseFacts",{"facts":81},[82,85,88,91],{"key":83,"value":84},"role","Fullstack Developer",{"key":86,"value":87},"team","2 fullstack developers and a junior frontend developer",{"key":89,"value":90},"duration","January 2025 – March 2026, launched in May 2025",{"key":92,"value":93},"status","Handed over, the store is live",{"component":95,"data":96},"ProjectCaseRole",{"id":83,"name":97,"items":98},"What I did",[99,102,105,108],{"title":100,"text":101},"Design and UI kit","The whole site design is mine. The UI kit is built on daisyUI, so the look changes by switching the theme.",{"title":103,"text":104},"Nuxt storefront","Proposed and introduced Nuxt: the storefront runs as a separate server-rendered app rather than part of a monolith.",{"title":106,"text":107},"Admin panel and API","The client side of the operator's admin panel, the layer of backend requests for the admin panel and the storefront, Laravel API endpoints for the storefront.",{"title":109,"text":110},"Review","Reviewed the junior frontend developer's merge requests.",{"component":112,"data":113},"ProjectCaseChapter",{"id":114,"name":115,"blocks":116},"context","Context",[117],{"component":112,"data":118},{"id":119,"name":120,"blocks":121},"business","Business",[122,126],{"component":123,"data":124},"ProjectCaseText",{"text":125},"Brendmart sells clothing, shoes and accessories by global brands from European stores, luxury and mass market: Prada, Brunello Cucinelli, Max Mara, Etro, Swarovski. Its customers live in Russia, Belarus and Kazakhstan.",{"component":123,"data":127},{"text":128},"The client buys the item from a foreign seller on the customer's behalf and delivers it to the EAEU countries. The store launched in May 2025.",{"component":112,"data":130},{"id":131,"name":132,"blocks":133},"process","Process, architecture and decisions",[134,155,187,198,209,224,232],{"component":112,"data":135},{"id":136,"name":137,"blocks":138},"flow","How people buy",[139],{"component":140,"data":141},"ProjectCaseSteps",{"steps":142},[143,146,149,152],{"title":144,"text":145},"Catalog","The price already includes delivery and customs duties",{"title":147,"text":148},"Concierge","If an item is not in the catalog, the customer can leave a purchase request",{"title":150,"text":151},"Cart","The cart and favorites live in a guest session, no sign-up needed",{"title":153,"text":154},"Delivery","The item is bought from a seller in Europe, express delivery from 5 days",{"component":112,"data":156},{"id":157,"name":158,"blocks":159},"architecture","Architecture",[160],{"component":161,"data":162},"ProjectCaseArchitecture",{"items":163},[164,167,175,179,183],{"label":165,"title":103,"text":166},"STOREFRONT","A separate server-rendered app on Nuxt 4, Pinia, Tailwind and daisyUI. Page data arrives in _payload.json.",{"label":168,"title":169,"text":170,"code":171},"API","Public REST","Cart, favorites, a cached category tree. The guest session goes through a proxy and is kept in a signed cookie.",[172,173,174],"\u002Fapi\u002Fpublic\u002Fv1","\u002Fcached\u002Fcategories-tree","\u002Fproxy\u002Fsession\u002Fguest",{"label":176,"title":177,"text":178},"ADMIN","Operator admin panel","The private part where the operator runs the store.",{"label":180,"title":181,"text":182},"BACKEND","Services and data","Laravel and Go, queues on RabbitMQ. PostgreSQL, Redis, Elasticsearch, ClickHouse, S3 \u002F MinIO.",{"label":184,"title":185,"text":186},"INFRA","Infrastructure","Docker, Traefik, Kubernetes and Argo CD, builds in GitLab CI. Logs in ELK, metrics in Grafana and Prometheus.",{"component":112,"data":188},{"id":189,"name":190,"blocks":191},"server-driven","Pages are built from the API",[192,195],{"component":123,"data":193},{"text":194},"Changing the home page takes no release. The backend returns the page as a JSON array shaped like a tree, and the storefront builds the page from components according to it.",{"component":123,"data":196},{"text":197},"The home page is built this way, and any other page can be built the same way: content and structure change through the API.",{"component":112,"data":199},{"id":200,"name":201,"blocks":202},"storefront","Search, languages and accessibility",[203,206],{"component":123,"data":204},{"text":205},"Search engines get a ready page from the server, with its own title, description, Open Graph and schema.org WebSite and WebPage markup. The interface is translated into Russian, English and Spanish.",{"component":123,"data":207},{"text":208},"We started adding accessibility support to the storefront: semantic page landmarks, alt text on images, labels on buttons and links, zoom is not blocked.",{"component":112,"data":210},{"id":211,"name":212,"blocks":213},"integrations","Integrations",[214],{"component":215,"data":216},"ProjectCaseIntegrations",{"items":217},[218,220,222],{"label":219},"Card payments",{"label":221},"Jivo online chat",{"label":223},"Yandex Metrica",{"component":112,"data":225},{"id":226,"name":227,"blocks":228},"security","Data security",[229],{"component":123,"data":230},{"text":231},"For customs clearance the store keeps customers' personal data. Such fields are encrypted in the database with Laravel's built-in tools, and the key is stored apart from the code and the database. Access has two levels: customers and staff (operators and administrators).",{"component":112,"data":233},{"id":234,"name":235,"blocks":236},"quality","Quality and releases",[237,240,243,256,259],{"component":123,"data":238},{"text":239},"I wrote three kinds of tests: component tests in Vitest, visual regression tests that compare a block with a reference screenshot, and E2E tests in Playwright for critical scenarios.",{"component":123,"data":241},{"text":242},"Each task lives in its own branch and, once merged into develop, goes through CI checks and onto the test stand. On release day a preprod branch is assembled for acceptance in a production-like environment, then master updates the live server without downtime.",{"component":244,"data":245},"ProjectCasePipeline",{"stages":246},[247,250,253],{"name":248,"next":249},"develop","CI and test stand",{"name":251,"next":252},"preprod","final acceptance",{"name":254,"next":255},"master","zero-downtime release",{"component":123,"data":257},{"text":258},"Production errors are tracked continuously, and if something goes wrong the release is quickly rolled back to the previous stable version.",{"component":123,"data":260},{"text":261},"Sprints lasted two weeks. At the end of each one the client saw what was done, what was not and why, and together we planned the next two weeks.",{"component":112,"data":263},{"id":264,"name":265,"blocks":266},"challenges","Challenges",[267],{"component":268,"data":269},"ProjectCaseChallenges",{"items":270},[271,284],{"id":272,"name":273,"rows":274},"nuxt","A storefront apart from the monolith",[275,278,281],{"key":276,"text":277},"problem","A storefront inside a monolith is hard to develop separately from the backend and cannot be reused on other platforms.",{"key":279,"text":280},"solution","Proposed and introduced Nuxt. The storefront became a separate server-rendered app that takes its data from the backend's public API.",{"key":282,"text":283},"result","The storefront can grow without touching the backend, and mobile apps can be built from the same code by adding Capacitor.",{"id":285,"name":286,"rows":287},"themes","A new look in a day",[288,290,292],{"key":276,"text":289},"The look often had to change at the client's request, and drawing every variant in Figma takes a long time.",{"key":279,"text":291},"Built the styling on Tailwind and daisyUI so that the theme switches as a whole, with the store's look moved into its own daisyUI theme. A prototype and theme variants came quickly from GPT-4: we asked it to lay out a prototype and suggest several variants.",{"key":282,"text":293},"From the client's request to a page prototype in a new theme took no more than an hour. Rebuilding the whole project in a new style takes a day thanks to the daisyUI-based UI kit.",{"component":112,"data":295},{"id":296,"name":297,"blocks":298},"results","Metrics and results",[299,315],{"component":300,"data":301},"ProjectCaseResults",{"stats":302},[303,306,309,312],{"value":304,"label":305},"600+","orders a month at handover",{"value":307,"label":308},"2M+","products in the catalog",{"value":310,"label":311},"~4 mo.","from the start of development to launch",{"value":313,"label":314},"≤ 1 h","for a new theme prototype on the client's request",{"component":123,"data":316},{"text":317},"By handover the store was taking more than 600 orders a month from customers in Russia, Belarus and Kazakhstan.",{"component":319,"data":320},"ProjectCaseCta",{"id":321,"title":322,"text":323,"url":11},"cta","Need a store with a large catalog that is easy to restyle?","I will design the UI and the UI kit, build a server-rendered Nuxt storefront, the admin panel and the API.",{"component":325,"data":326},"ProjectCaseNext",{"slug":327,"name":328,"index":329,"tone":330},"taobao","Taobao.at","03","primary",1792947428891]