[{"data":1,"prerenderedAt":295},["ShallowReactive",2],{"project-case-taobao":3},[4,13,19,77,93,110,128,237,267,282,288],{"component":5,"data":6},"ProjectCaseHeader",{"index":7,"subtitle":8,"name":9,"headline":10,"url":11,"tone":12},"03","PURCHASE SERVICE · DELIVERY FROM CHINA AND HONG KONG","Taobao.at","600+ orders a month by handover","https:\u002F\u002Ftaobao.at\u002F","primary",{"component":14,"data":15},"ProjectCaseCover",{"image":16,"imageMobile":17,"imageAlt":18},"taobao\u002Fmedia\u002Fpreview.webp","taobao\u002Fmedia\u002Fpreview-mobile.webp","Home page of the Taobao.at website",{"component":20,"data":21},"ProjectCaseMeta",{"tags":22,"stack":25},[23,24],"E-commerce","Full-Stack",[26,29,31,33,35,37,39,41,43,45,47,49,51,53,55,57,59,61,63,65,67,69,71,73,75],{"label":27,"own":28},"Nuxt 4",true,{"label":30,"own":28},"Vue 3",{"label":32,"own":28},"Pinia",{"label":34,"own":28},"Nuxt i18n",{"label":36,"own":28},"Nuxt Icon",{"label":38,"own":28},"VueUse",{"label":40,"own":28},"Tailwind CSS",{"label":42,"own":28},"daisyUI",{"label":44},"Envoy",{"label":46,"own":28},"Laravel",{"label":48},"Go",{"label":50},"PostgreSQL",{"label":52},"Redis",{"label":54},"RabbitMQ",{"label":56},"S3 \u002F MinIO",{"label":58},"ClickHouse",{"label":60},"Elasticsearch",{"label":62},"Docker",{"label":64},"Traefik",{"label":66},"Kubernetes",{"label":68},"Argo CD",{"label":70},"GitLab CI",{"label":72},"ELK",{"label":74},"Grafana",{"label":76},"Prometheus",{"component":78,"data":79},"ProjectCaseFacts",{"facts":80},[81,84,87,90],{"key":82,"value":83},"role","Fullstack Developer",{"key":85,"value":86},"team","2 fullstack developers and a junior frontend developer",{"key":88,"value":89},"duration","January 2025 – March 2026",{"key":91,"value":92},"status","Completed, the site is live",{"component":94,"data":95},"ProjectCaseRole",{"id":82,"name":96,"items":97},"What I did",[98,101,104,107],{"title":99,"text":100},"Design and UI kit","The site design is entirely mine. The UI kit is built on Tailwind and daisyUI with a custom theme, so the look changes by switching the theme.",{"title":102,"text":103},"Storefront in Nuxt","I proposed making the storefront a separate Nuxt application with server-side rendering and built its client side myself: Pinia, Russian and English interface, the layer of API requests.",{"title":105,"text":106},"Admin panel","The client side of the operator workspace and its requests to the backend.",{"title":108,"text":109},"Storefront API","Laravel endpoints that feed the storefront.",{"component":111,"data":112},"ProjectCaseChapter",{"id":113,"name":114,"blocks":115},"context","Context",[116],{"component":111,"data":117},{"id":118,"name":119,"blocks":120},"business","Business",[121,125],{"component":122,"data":123},"ProjectCaseText",{"text":124},"The client purchases and delivers products from China and Hong Kong. Its customers live in Russia and order IKEA, Apple devices for the Hong Kong market, clothing and shoes from Farfetch, computer components.",{"component":122,"data":126},{"text":127},"If an item is not in the catalog, it can be ordered with a purchase request.",{"component":111,"data":129},{"id":130,"name":131,"blocks":132},"process","Process, architecture and decisions",[133,157,191,202,210],{"component":111,"data":134},{"id":135,"name":136,"blocks":137},"flow","The order flow",[138,141],{"component":122,"data":139},{"text":140},"The catalog price is in rubles right away and already includes duties, the service fee and delivery. After that an order goes through four steps.",{"component":142,"data":143},"ProjectCaseSteps",{"steps":144},[145,148,151,154],{"title":146,"text":147},"Order","From the catalog or with a purchase request. The cart and favorites work without signing up",{"title":149,"text":150},"Payment","By a MIR card or via SBP",{"title":152,"text":153},"Check","The order is checked for completeness before shipping",{"title":155,"text":156},"Delivery","17–28 days to Russia, the status is visible in the personal account. Pickup point or courier",{"component":111,"data":158},{"id":159,"name":160,"blocks":161},"architecture","Architecture",[162,165],{"component":122,"data":163},{"text":164},"The storefront lives separately from the backend. It is easier to develop, and mobile apps can be built from the same code by adding Capacitor.",{"component":166,"data":167},"ProjectCaseArchitecture",{"items":168},[169,173,180,183,187],{"label":170,"title":171,"text":172},"STOREFRONT","Storefront","Nuxt 4 with server-side rendering, Pinia and Nuxt i18n, a UI kit on Tailwind and daisyUI.",{"label":174,"title":175,"text":176,"code":177},"API","Public API","Cart, favorites and product blocks for the home page. The guest session relies on a signed cookie, so the customer does not have to sign up in advance.",[178,179],"\u002Fapi\u002Fpublic\u002Fv1","catalog\u002Fblock-products",{"label":181,"title":105,"text":182},"ADMIN","The workspace of the service operators.",{"label":184,"title":185,"text":186},"BACKEND","Services and data","Laravel and Go, queues on RabbitMQ. Data in PostgreSQL, Redis, Elasticsearch, ClickHouse and S3 \u002F MinIO.",{"label":188,"title":189,"text":190},"INFRA","Infrastructure","Docker and Kubernetes, rollout via GitLab CI and Argo CD, traffic through Traefik and Envoy. Monitoring on Grafana, Prometheus and ELK.",{"component":111,"data":192},{"id":193,"name":194,"blocks":195},"server-driven","Pages are built from the API",[196,199],{"component":122,"data":197},{"text":198},"The structure and content of a page can change without a storefront release. The backend returns a JSON array shaped like an abstract syntax tree, and the storefront builds the page from it.",{"component":122,"data":200},{"text":201},"The home page is built this way, and its product blocks come from catalog\u002Fblock-products. Any other page can be built the same way.",{"component":111,"data":203},{"id":204,"name":205,"blocks":206},"security","Data security",[207],{"component":122,"data":208},{"text":209},"For customs clearance the service stores customers' personal data. Sensitive fields are encrypted in the database with Laravel's built-in tools, and the key is stored separately from both the code and the database. Permissions are split between customers, operators and administrators.",{"component":111,"data":211},{"id":212,"name":213,"blocks":214},"quality","Quality and releases",[215,218,221,234],{"component":122,"data":216},{"text":217},"I was responsible for three kinds of tests: component tests on Vitest, visual regression tests that compare blocks against reference screenshots, and E2E tests on Playwright for critical scenarios. The junior frontend developer's code went through my review.",{"component":122,"data":219},{"text":220},"A task from its own branch goes into develop, passes the automated tests and code quality checks and is deployed to the test environment. On the planned release date the finished tasks are gathered into preprod, where final testing and acceptance run in an environment identical to production. Then the release is merged into master and updates production without downtime. If something breaks in production, it is possible to quickly return to the previous stable version.",{"component":222,"data":223},"ProjectCasePipeline",{"stages":224},[225,228,231],{"name":226,"next":227},"develop","test environment",{"name":229,"next":230},"preprod","acceptance",{"name":232,"next":233},"master","production without downtime",{"component":122,"data":235},{"text":236},"Sprints lasted two weeks. At the end of each one the client saw what was done, what was not and why, and what was planned for the next two weeks.",{"component":111,"data":238},{"id":239,"name":240,"blocks":241},"challenges","Challenges",[242],{"component":243,"data":244},"ProjectCaseChallenges",{"items":245},[246,256],{"id":247,"name":248,"rows":249},"a11y","Accessibility in the UI kit",[250,253],{"key":251,"text":252},"solution","Accessibility is built into the UI kit itself: semantic page regions, a visible focus and a logical keyboard order, alt text on images, accessible names on buttons and links. Zooming is allowed, and the screen notch on phones is taken into account.",{"key":254,"text":255},"result","An axe-core check against WCAG 2.2 AA and a manual keyboard pass on the home page, a category and a product page, on desktop and on a phone, found one violation. The brand red gives a contrast of 4.1:1 against the required 4.5:1, which is fixed by darkening the red a couple of shades in the daisyUI theme.",{"id":257,"name":258,"rows":259},"theming","A new look in a day",[260,263,265],{"key":261,"text":262},"problem","The client came with requests for a new storefront style, and it had to be shown and rolled out quickly.",{"key":251,"text":264},"I chose Tailwind and daisyUI: the UI kit components take their look from a theme, the custom taobao_v2 or the standard light and dark. The prototype of a new theme was generated with GPT-4.",{"key":254,"text":266},"By my estimate, without measurements: a prototype page in the new style is ready in under an hour after the request, and rebuilding the site takes no more than a day.",{"component":111,"data":268},{"id":269,"name":270,"blocks":271},"results","Metrics and results",[272],{"component":273,"data":274},"ProjectCaseResults",{"stats":275},[276,279],{"value":277,"label":278},"600+","orders a month at handover",{"value":280,"label":281},"2M+","products in the catalog at handover",{"component":283,"data":284},"ProjectCaseCta",{"id":285,"title":286,"text":287,"url":11},"cta","Need a cross-border delivery service or a storefront that can be restyled in a day?","I will design an accessible UI kit, build the storefront in Nuxt and the API behind it.",{"component":289,"data":290},"ProjectCaseNext",{"slug":291,"name":292,"index":293,"tone":294},"pochtoy-prostobox","Pochtoy & Prostobox","04","secondary",1792947429647]