[{"data":1,"prerenderedAt":297},["ShallowReactive",2],{"project-case-pochtoy-prostobox":3},[4,13,19,74,90,107,136,239,261,285,291],{"component":5,"data":6},"ProjectCaseHeader",{"index":7,"subtitle":8,"name":9,"headline":10,"url":11,"tone":12},"04","DELIVERY FROM THE US · SUPPORT AND SPEED","Pochtoy & Prostobox","Speeding up the storefronts of two brands on one platform","https:\u002F\u002Fpochtoy.com\u002F","secondary",{"component":14,"data":15},"ProjectCaseCover",{"image":16,"imageMobile":17,"imageAlt":18},"pochtoy-prostobox\u002Fmedia\u002Fpreview.webp","pochtoy-prostobox\u002Fmedia\u002Fpreview-mobile.webp","Home page of the Pochtoy.com website",{"component":20,"data":21},"ProjectCaseMeta",{"tags":22,"stack":24},[23],"Full-Stack",[25,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72],{"label":26,"own":27},"PHP",true,{"label":29,"own":27},"Laravel",{"label":31},"nginx",{"label":33,"own":27},"jQuery",{"label":35,"own":27},"Vue 3",{"label":37,"own":27},"TypeScript",{"label":39,"own":27},"Laravel Mix",{"label":41,"own":27},"Tailwind CSS",{"label":43,"own":27},"Bootstrap",{"label":45,"own":27},"Popper",{"label":47,"own":27},"Select2",{"label":49,"own":27},"Swiper",{"label":51,"own":27},"SweetAlert2",{"label":53,"own":27},"AirDatepicker",{"label":55,"own":27},"Fancybox",{"label":57,"own":27},"Choices",{"label":59,"own":27},"moment",{"label":61,"own":27},"lodash",{"label":63,"own":27},"axios",{"label":65,"own":27},"vee-validate",{"label":67,"own":27},"Dropzone",{"label":69},"Bunny CDN",{"label":71,"own":27},"PostgreSQL",{"label":73},"Redis",{"component":75,"data":76},"ProjectCaseFacts",{"facts":77},[78,81,84,87],{"key":79,"value":80},"role","Fullstack Developer",{"key":82,"value":83},"team","3 fullstack developers and a PM",{"key":85,"value":86},"duration","10.2023 – 01.2025",{"key":88,"value":89},"status","The sites are live",{"component":91,"data":92},"ProjectCaseRole",{"id":79,"name":93,"items":94},"What I did",[95,98,101,104],{"title":96,"text":97},"Loading speed","Pagination, lazy-loaded images, separate JS and CSS for every page instead of one shared bundle, and a lighter library bundle for the Pochtoy home page.",{"title":99,"text":100},"Storefront frontend","Markup from a ready-made design in Tailwind CSS. The delivery calculator runs as a separate Vue 3 widget inside a server-rendered page.",{"title":102,"text":103},"Storefront database queries","Reviews with the list, pagination and the map, the calculator and rates, home page banners, city search. Only the needed fields are selected from the database.",{"title":105,"text":106},"Review Cashback","A TypeScript module that pays customers to their balance for a review of the service. The frontend and the queries are mine.",{"component":108,"data":109},"ProjectCaseChapter",{"id":110,"name":111,"blocks":112},"context","Context and starting point",[113,125],{"component":108,"data":114},{"id":115,"name":116,"blocks":117},"business","Business",[118,122],{"component":119,"data":120},"ProjectCaseText",{"text":121},"Pochtoy LLC delivers purchases from US stores. Parcels arrive at a warehouse in tax-free Delaware, an operator can buy the item on the customer's request, and then the parcel goes to Russia, Kazakhstan, Belarus, the Middle East or another country. The sites work in English, Russian, Arabic and Spanish.",{"component":119,"data":123},{"text":124},"The company runs two brands on one platform. Pochtoy.com has been operating since 2008. Prostobox is the budget brand with delivery from $3.99 per parcel, and 79% of its shipments come from resellers and entrepreneurs.",{"component":108,"data":126},{"id":127,"name":128,"blocks":129},"situation","The situation",[130,133],{"component":119,"data":131},{"text":132},"The team ran the sites under a support contract: the client paid monthly, and tasks were taken as they came. There were two main goals: keep the sites stable and make them load faster.",{"component":119,"data":134},{"text":135},"There are no speed measurements from before the work started, but by our estimate some pages took more than 5 seconds to load. The storefront had no pagination, no lazy loading of images and lacked other basics.",{"component":108,"data":137},{"id":138,"name":139,"blocks":140},"process","Process, architecture and decisions",[141,178,204,212],{"component":108,"data":142},{"id":143,"name":144,"blocks":145},"architecture","Architecture",[146,149],{"component":119,"data":147},{"text":148},"Both brands run on one Laravel backend: a shared session, the same paths and the same functions in the scripts. Each brand has its own domain, and its styles and scripts are layered on top of the shared ones.",{"component":150,"data":151},"ProjectCaseArchitecture",{"items":152},[153,161,165,174],{"label":154,"title":155,"text":156,"code":157},"BRANDS","Two brands","Pochtoy.com and Prostobox: their own styles and scripts on top of the shared ones.",[158,159,160],"assets\u002Fguest","assets\u002Fpochtoy","assets\u002Fprostobox",{"label":162,"title":163,"text":164},"STOREFRONT","Storefront","Server rendering and jQuery, Vue 3 as separate widgets. Built with Laravel Mix.",{"label":166,"title":167,"text":168,"code":169},"API","Storefront API","Rates and delivery calculation, the customer's region, home page banners, city search.",[170,171,172,173],"\u002Fapi\u002Fguest\u002Fcalculator\u002F*","\u002Fapi\u002Fguest\u002Fclient-region\u002Fget","\u002Fapi\u002Fguest\u002Findex-banners\u002Fget","\u002Fcity\u002Fsearch",{"label":175,"title":176,"text":177},"DATA","Data and static files","PostgreSQL, Redis for cache, static files on Bunny CDN.",{"component":108,"data":179},{"id":180,"name":105,"blocks":181},"review-cash",[182,185,201],{"component":119,"data":183},{"text":184},"A customer writes a review of the service on an external platform and gets money to their balance for it. I built this TypeScript module: the frontend and the queries.",{"component":186,"data":187},"ProjectCaseSteps",{"steps":188},[189,192,195,198],{"title":190,"text":191},"Review","200 characters or more, with a photo and a tracking number",{"title":193,"text":194},"Link","The customer pastes the link to the review into a form on the site",{"title":196,"text":197},"Check","An operator checks the review",{"title":199,"text":200},"Cashback","$3 or $5 to the balance depending on the platform",{"component":119,"data":202},{"text":203},"There are six platforms: Yandex Maps, VK, Otzovik, Trustpilot, Google Maps and Facebook, with one review counted on each. For all six the customer gets up to $22.",{"component":108,"data":205},{"id":206,"name":207,"blocks":208},"rum","Speed for real users",[209],{"component":119,"data":210},{"text":211},"I wrote the perf-rum.js script that collects speed metrics from real users. For 25% of visits it records TTFB, FCP, LCP, INP and CLS for each page, along with the page weight and the number of requests, images and XHR calls, and sends them to the server.",{"component":108,"data":213},{"id":214,"name":215,"blocks":216},"quality","Quality and releases",[217,220,223,236],{"component":119,"data":218},{"text":219},"I wrote three kinds of tests: component tests in Vitest, visual regression tests against reference screenshots of blocks and E2E tests in Playwright for the critical scenarios.",{"component":119,"data":221},{"text":222},"Each task is done in its own branch, passes CI checks and goes to a test stand. On the planned release date the finished tasks move to a preprod stand identical to production, and after acceptance they roll out to production without downtime. Production errors are tracked constantly, and in case of trouble the release is rolled back to the previous stable version.",{"component":224,"data":225},"ProjectCasePipeline",{"stages":226},[227,230,233],{"name":228,"next":229},"develop","test stand",{"name":231,"next":232},"preprod","acceptance",{"name":234,"next":235},"master","production without downtime",{"component":119,"data":237},{"text":238},"We worked in two-week sprints. At the end of each sprint we showed the client what was done, what was not and why, and what we were taking on for the next two weeks.",{"component":108,"data":240},{"id":241,"name":242,"blocks":243},"challenges","Challenges",[244],{"component":245,"data":246},"ProjectCaseChallenges",{"items":247},[248],{"id":249,"name":250,"rows":251},"speed","Slow page loading",[252,255,258],{"key":253,"text":254},"problem","Some pages took more than 5 seconds to load: lists had no pagination, all images loaded at once, and scripts and styles came in one shared bundle.",{"key":256,"text":257},"solution","I added pagination and lazy loading of images and split JS and CSS by page. For the Pochtoy home page I built a lighter library bundle: about 700 KB against 930 KB for the full one. I plugged in the delivery calculator as a separate Vue 3 widget. In the storefront database queries I selected only the needed fields instead of SELECT *.",{"key":259,"text":260},"result","Reviews are split into pages, images below the fold load as the user scrolls, and every page gets only its own scripts and styles. There were no before and after measurements, so the result is described as a list of what was done, without numbers.",{"component":108,"data":262},{"id":263,"name":264,"blocks":265},"results","Platform scale",[266,282],{"component":267,"data":268},"ProjectCaseResults",{"stats":269},[270,273,276,279],{"value":271,"label":272},"2.6M","parcels shipped by Pochtoy.com since 2008",{"value":274,"label":275},"200k+","parcels shipped by Prostobox",{"value":277,"label":278},"7,000+","parcels a month by the weekly counter on the sites",{"value":280,"label":281},"20,000+","Pochtoy.com customers",{"component":119,"data":283},{"text":284},"The numbers were taken from the sites in October 2026. They show the scale of the platform I worked on, not the result of my work.",{"component":286,"data":287},"ProjectCaseCta",{"id":288,"title":289,"text":290,"url":11},"cta","Your site already brings in orders but loads slowly?","I will find what slows it down, split scripts and styles by page, add pagination and lazy loading and set up speed tracking for real users.",{"component":292,"data":293},"ProjectCaseNext",{"slug":294,"name":295,"index":296,"tone":12},"cdek-shopping","CDEK.Shopping","05",1792947429698]