[{"data":1,"prerenderedAt":471},["ShallowReactive",2],{"cases-en-storelight":3,"published":369},{"doc":4,"versions":348,"related":351},{"id":5,"title":6,"body":7,"casePage":296,"client":308,"cover":309,"description":310,"draft":311,"extension":312,"lang":313,"lead":314,"meta":315,"minutes":316,"modified":317,"navigation":318,"path":319,"platform":320,"price":321,"published":322,"released":311,"role":323,"seo":324,"seoTitle":325,"services":326,"showcase":329,"stack":336,"status":341,"stem":342,"summary":343,"tagline":344,"theme":345,"year":346,"__hash__":347},"cases\u002Fen\u002Fcases\u002Fstorelight.md","Storelight: an AI editor for App Store and Google Play screenshots",{"type":8,"value":9,"toc":280},"minimark",[10,15,19,28,32,35,49,67,75,84,92,96,107,119,123,137,147,156,160,163,167,211,216,239,243,259,263,269,273],[11,12,14],"h2",{"id":13},"the-problem","The problem",[16,17,18],"p",{},"To publish an app you need promo screenshots: frames with headlines, phone frames and backgrounds, in the App Store's and Google Play's exact sizes, and in every language. It is usually done by hand in Figma: slow, and with every update it starts over.",[16,20,21,22,27],{},"I went through this myself with ",[23,24,26],"a",{"href":25},"\u002Fen\u002Fcases\u002Fbudgetra\u002F","Budgetra"," and built a tool that takes the work on. The screenshots in my Budgetra case study were made in it.",[11,29,31],{"id":30},"the-editor","The editor",[16,33,34],{},"The hardest part of Storelight is the editor. It is “Figma for app store screenshots”: everything promo frames need and nothing more, so you never have to open Figma or Canva for a set of screenshots.",[36,37,43,46],"case-scene",{"alt":38,"height":39,"src":40,"title":41,"width":42},"The editor: a canvas of Budgetra frames, the layers panel and the selected headline's properties",1066,"\u002Fcases\u002Fstorelight\u002Fen\u002Fs-layers.webp","Canvas and layers",1300,[16,44,45],{},"Each screenshot is its own artboard, and everything on it is a layer: the background, the screenshot in a phone frame, headlines, elements. You select and move them right on the canvas, snapping to edges and centres, with the selected layer's properties on the right.",[16,47,48],{},"Every action can be undone, and the project saves itself. For text you see at once whether it fits its place, in every language.",[36,50,54,64],{"alt":51,"height":39,"src":52,"title":53,"width":42},"The elements library: iPhone, iPad and Apple Watch frames, angled ones too","\u002Fcases\u002Fstorelight\u002Fen\u002Fs-elements.webp","The elements library",[16,55,56,57,63],{},"iPhone, iPad, Android and Apple Watch frames, angled ones too, plus arrows, badges, callouts and spotlights. The frames are drawn ",[58,59,62],"span",{"className":60},[61],"nowrap","in-house",", with no licensing risk.",[16,65,66],{},"The screenshot fits into the frame by itself, even one turned in perspective. The distortion is computed in a separate thread, so the canvas stays smooth.",[36,68,72],{"alt":69,"height":39,"src":70,"title":71,"width":42},"Backgrounds: AI background, your own images, gradients and mesh gradients","\u002Fcases\u002Fstorelight\u002Fen\u002Fs-background.webp","Backgrounds",[16,73,74],{},"Gradients, mesh gradients and your own images. The service picks the brand colours from the app's screenshots, and on Pro the AI draws a background in its style, with two options to choose from.",[36,76,81],{"alt":77,"height":78,"src":79,"title":80,"width":42},"The iPad 13″ format, built from the main iPhone format",889,"\u002Fcases\u002Fstorelight\u002Fen\u002Fs-ipad.webp","Formats",[16,82,83],{},"Frames are built once in the main iPhone 6.9″ format, and iPad 13″ and Android 9:16 are made from it in the stores' exact sizes. An edit in the main format shows up in all of them at once.",[36,85,89],{"alt":86,"height":39,"src":87,"title":88,"width":42},"Version history: autosaves, actions and named versions per language","\u002Fcases\u002Fstorelight\u002Fen\u002Fs-history.webp","Version history",[16,90,91],{},"Every autosave, AI action or deleted screen is a point you can go back to. Important states can be named and kept as versions, separately for each language.",[11,93,95],{"id":94},"the-ai-assistant","The AI assistant",[97,98,99],"ul",{},[100,101,102,106],"li",{},[103,104,105],"strong",{},"Upload your screens as they are",": the service recognises what is on each one and names them.",[36,108,113,116],{"alt":109,"height":110,"src":111,"title":112,"width":42},"The AI assistant: copy, styling, build screen, hierarchy, set review, decor, language",993,"\u002Fcases\u002Fstorelight\u002Fen\u002Fs-ai.webp","AI suggests, you decide",[16,114,115],{},"The AI writes headlines, picks styling and decor, builds a finished frame from a bare screenshot, sets the emphasis in the copy and reviews the whole set through a buyer's eyes: weak frames, repeats, whether the benefit is clear in 3 seconds.",[16,117,118],{},"Any result can be undone, or you can ask for another option. An AI action costs a credit; the editor, manual translations and export cost none.",[11,120,122],{"id":121},"languages-checks-and-publishing","Languages, checks and publishing",[97,124,125,131],{},[100,126,127,130],{},[103,128,129],{},"Translation that isn't word for word",": copy is adapted to each language, and each language is its own version of the frames.",[100,132,133,136],{},[103,134,135],{},"Store rules",": the name, subtitle, description and keywords are checked against the App Store's and Google Play's limits.",[36,138,144],{"alt":139,"height":140,"src":141,"title":142,"width":143},"“As in the store”: the set in App Store search",1054,"\u002Fcases\u002Fstorelight\u002Fen\u002Fs-store.webp","As in the store",1282,[16,145,146],{},"Before publishing you can see the set the way it will look in App Store search and on the app's page, and for Google Play in the Android format.",[36,148,153],{"alt":149,"height":150,"src":151,"title":152,"width":42},"Export: the set's languages and formats in one archive",1114,"\u002Fcases\u002Fstorelight\u002Fen\u002Fs-export.webp","Export for the stores",[16,154,155],{},"A ZIP with folders by language and format and a file with the store copy. On Pro, the screenshots and copy upload straight to App Store Connect and Google Play.",[11,157,159],{"id":158},"what-idid","What I did",[16,161,162],{},"The whole product: the idea, the design of the interface and the landing page, the frontend, the backend and payments. The interface is in Ukrainian, English and Russian.",[11,164,166],{"id":165},"how-it-works","How it works",[97,168,169,183,189,195,201],{},[100,170,171,174,175,178,179,182],{},[103,172,173],{},"Next.js and React"," on the frontend, ",[103,176,177],{},"tRPC"," between client and server, ",[103,180,181],{},"PostgreSQL"," through Prisma.",[100,184,185,188],{},[103,186,187],{},"One render engine",": what is on the canvas is what ends up in the PNG. Frames are drawn on the server (satori and resvg), so the export matches the editor to the pixel.",[100,190,191,194],{},[103,192,193],{},"Background jobs"," (rendering, AI, export) run in a BullMQ queue with a separate worker; files live in Cloudflare R2 storage.",[100,196,197,200],{},[103,198,199],{},"The AI layer isn't tied to one provider",": prompts are versioned and every answer is checked against a schema.",[100,202,203,210],{},[103,204,205,209],{},[58,206,208],{"className":207},[61],"Sign-in"," by email link"," (Auth.js), subscriptions through Paddle, errors and analytics in Sentry and PostHog.",[212,213,215],"h3",{"id":214},"from-canvas-to-finished-png","From canvas to finished PNG",[217,218,219],"case-system",{},[97,220,221,227,233],{},[100,222,223,226],{},[103,224,225],{},"In the browser"," the Next.js and React editor communicates with the server through tRPC.",[100,228,229,232],{},[103,230,231],{},"On the server"," PostgreSQL through Prisma, a BullMQ queue and rendering with satori and resvg.",[100,234,235,238],{},[103,236,237],{},"In storage"," finished files live in Cloudflare R2. Export uses the same rendering engine as the editor.",[11,240,242],{"id":241},"quality","Quality",[244,245,246],"case-highlights",{},[97,247,248,256],{},[100,249,250,251,255],{},"about 550 test files: unit tests, tests against a real database and ",[58,252,254],{"className":253},[61],"end-to-end"," Playwright flows;",[100,257,258],{},"dedicated accessibility checks (axe), plus type checking and linting on every change in CI.",[11,260,262],{"id":261},"status","Status",[264,265,266],"case-result",{},[16,267,268],{},"Storelight is at the final stage of development: the main features are done and working, and I'm finishing the details before launch. The project shows that I can build not just a website but a complex web service with AI, an editor and payments.",[11,270,272],{"id":271},"inside-the-service","Inside the service",[274,275],"app-shots",{":alts":276,"dir":277,"height":278,"width":279},"[\"The editor: a canvas of Budgetra frames, the layers panel and the selected headline's properties\",\"The AI assistant: copy, styling, build screen, hierarchy, set review, decor, language\",\"The elements library: iPhone, iPad and Apple Watch frames, angled ones too\",\"Backgrounds: AI background, your own images, gradients and mesh gradients\",\"The iPad 13″ format, built from the main iPhone format\",\"The Android 9:16 format, built from the main format\",\"Version history: autosaves, actions and named versions per language\",\"“As in the store”: the set in App Store search\",\"Export: the set's languages and formats in one archive\"]","\u002Fcases\u002Fstorelight\u002Fen\u002F",483,960,{"title":281,"searchDepth":282,"depth":282,"links":283},"",2,[284,285,286,287,288,289,293,294,295],{"id":13,"depth":282,"text":14},{"id":30,"depth":282,"text":31},{"id":94,"depth":282,"text":95},{"id":121,"depth":282,"text":122},{"id":158,"depth":282,"text":159},{"id":165,"depth":282,"text":166,"children":290},[291],{"id":214,"depth":292,"text":215},3,{"id":241,"depth":282,"text":242},{"id":261,"depth":282,"text":262},{"id":271,"depth":282,"text":272},{"name":297,"cta":298,"layout":299,"hero":300,"links":307},"Storelight","Need a similar web service?","studio",[301,303,305],{"src":302,"alt":38,"width":279,"height":278},"\u002Fcases\u002Fstorelight\u002Fen\u002F1.webp",{"src":304,"alt":109,"width":279,"height":278},"\u002Fcases\u002Fstorelight\u002Fen\u002F2.webp",{"src":306,"alt":149,"width":279,"height":278},"\u002Fcases\u002Fstorelight\u002Fen\u002F9.webp",[],"Own product","\u002Fcases\u002Fstorelight\u002Fen\u002Fcover.webp","My web service on Next.js: it builds an app's promo screenshots with AI, translates them and prepares a set for the App Store and Google Play.",false,"md","en","My second product of my own: a web service that turns raw app screens into finished promo screenshots and copy for the App Store and Google Play. It is now at the final stage of development.",{},6,"2026-11-03",true,"\u002Fen\u002Fcases\u002Fstorelight","Web app",null,"2026-11-02","Idea, design, development",{"title":6,"description":310},"Storelight — an AI screenshot editor for the app stores: case study",[327,328],"web-apps","full-stack",{"layout":299,"shots":330,"notes":333},[331,282,332],1,9,[334,335],"AI tools","Store export",[337,338,339,177,181,340],"Next.js","React","TypeScript","Prisma","Final stage of development","en\u002Fcases\u002Fstorelight","An AI editor for promo screenshots: from raw app screens to a set for the App Store and Google Play.","From app screens to a ready release.","blue","2026","n9KWBgYx-fBEgXJYt1Rmpf-ysTPq4GEjZHm2hGoOfyw",[313,349,350],"ru","uk",[352,357,362],{"path":353,"title":354,"description":355,"draft":311,"short":356},"\u002Fen\u002Fservices\u002Ffull-stack","Full-stack development","Full-stack development: interface, server and database from one person. Fewer middlemen, faster results. Vue, Nuxt, React. Remote, for clients anywhere.","Interface, server and database in one pair of hands. From design to launch.",{"path":358,"title":359,"description":360,"draft":311,"short":361},"\u002Fen\u002Fservices\u002Fweb-apps","Web apps and user accounts","A web app: user account, CRM, admin panel, service with roles. Vue 3, Nuxt, React. From idea to launch. Remote, for clients anywhere.","User accounts, admin panels, services: Vue, Nuxt, React.",{"path":363,"title":364,"description":365,"draft":311,"client":308,"status":366,"cover":367,"summary":368},"\u002Fen\u002Fcases\u002Fbudgetra","Budgetra: a budgeting app with a forecast","My own budgeting app built with Flutter: a forecast to the end of the month, voice input, receipt scanning. Published on the App Store and Google Play.","On the App Store and Google Play","\u002Fcases\u002Fbudgetra\u002Fen\u002Fcover.webp","A budget with a forecast to the end of the month. Say what you spent, or on iPhone add a receipt from a photo.",[370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,25,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470],"\u002Fen\u002Fservices\u002Fbusiness-card-site\u002F","\u002Fen\u002Fservices\u002Fcatalog-site\u002F","\u002Fen\u002Fservices\u002Fcorporate-site\u002F","\u002Fen\u002Fservices\u002Ffigma-to-html\u002F","\u002Fen\u002Fservices\u002Fflutter-apps\u002F","\u002Fen\u002Fservices\u002Ffull-stack\u002F","\u002Fen\u002Fservices\u002Flanding-page\u002F","\u002Fen\u002Fservices\u002Fonline-store\u002F","\u002Fen\u002Fservices\u002Fportal\u002F","\u002Fen\u002Fservices\u002Fredesign\u002F","\u002Fen\u002Fservices\u002Fsite-speed\u002F","\u002Fen\u002Fservices\u002Fsite-support\u002F","\u002Fen\u002Fservices\u002Fweb-apps\u002F","\u002Fen\u002Fservices\u002Fwordpress\u002F","\u002Fru\u002Fservices\u002Fbusiness-card-site\u002F","\u002Fru\u002Fservices\u002Fcatalog-site\u002F","\u002Fru\u002Fservices\u002Fcorporate-site\u002F","\u002Fru\u002Fservices\u002Ffigma-to-html\u002F","\u002Fru\u002Fservices\u002Fflutter-apps\u002F","\u002Fru\u002Fservices\u002Ffull-stack\u002F","\u002Fru\u002Fservices\u002Flanding-page\u002F","\u002Fru\u002Fservices\u002Fonline-store\u002F","\u002Fru\u002Fservices\u002Fportal\u002F","\u002Fru\u002Fservices\u002Fredesign\u002F","\u002Fru\u002Fservices\u002Fsite-speed\u002F","\u002Fru\u002Fservices\u002Fsite-support\u002F","\u002Fru\u002Fservices\u002Fweb-apps\u002F","\u002Fru\u002Fservices\u002Fwordpress\u002F","\u002Fservices\u002Fbusiness-card-site\u002F","\u002Fservices\u002Fcatalog-site\u002F","\u002Fservices\u002Fcorporate-site\u002F","\u002Fservices\u002Ffigma-to-html\u002F","\u002Fservices\u002Fflutter-apps\u002F","\u002Fservices\u002Ffull-stack\u002F","\u002Fservices\u002Flanding-page\u002F","\u002Fservices\u002Fonline-store\u002F","\u002Fservices\u002Fportal\u002F","\u002Fservices\u002Fredesign\u002F","\u002Fservices\u002Fsite-speed\u002F","\u002Fservices\u002Fsite-support\u002F","\u002Fservices\u002Fweb-apps\u002F","\u002Fservices\u002Fwordpress\u002F","\u002Fservices\u002F","\u002Fen\u002Fservices\u002F","\u002Fru\u002Fservices\u002F","\u002Fen\u002Fcases\u002Fstorelight\u002F","\u002Fru\u002Fcases\u002Fbudgetra\u002F","\u002Fru\u002Fcases\u002Fstorelight\u002F","\u002Fcases\u002Fbudgetra\u002F","\u002Fcases\u002Fstorelight\u002F","\u002Fcases\u002F","\u002Fen\u002Fcases\u002F","\u002Fru\u002Fcases\u002F","\u002Fen\u002Fblog\u002Fbusiness-card-site-price\u002F","\u002Fen\u002Fblog\u002Fcatalog-or-online-store\u002F","\u002Fen\u002Fblog\u002Fcorporate-site-cost\u002F","\u002Fen\u002Fblog\u002Ffigma-to-html-checklist\u002F","\u002Fen\u002Fblog\u002Ffull-stack-vs-team\u002F","\u002Fen\u002Fblog\u002Flanding-page-cost\u002F","\u002Fen\u002Fblog\u002Fmobile-app-cost\u002F","\u002Fen\u002Fblog\u002Fonline-store-cost\u002F","\u002Fen\u002Fblog\u002Fpersonal-account-guide\u002F","\u002Fen\u002Fblog\u002Fportal-where-to-start\u002F","\u002Fen\u002Fblog\u002Fredesign-without-losing-seo\u002F","\u002Fen\u002Fblog\u002Fsite-support-guide\u002F","\u002Fen\u002Fblog\u002Fslow-site-checklist\u002F","\u002Fen\u002Fblog\u002Fwordpress-or-custom-code\u002F","\u002Fru\u002Fblog\u002Fbusiness-card-site-price\u002F","\u002Fru\u002Fblog\u002Fcatalog-or-online-store\u002F","\u002Fru\u002Fblog\u002Fcorporate-site-cost\u002F","\u002Fru\u002Fblog\u002Ffigma-to-html-checklist\u002F","\u002Fru\u002Fblog\u002Ffull-stack-vs-team\u002F","\u002Fru\u002Fblog\u002Flanding-page-cost\u002F","\u002Fru\u002Fblog\u002Fmobile-app-cost\u002F","\u002Fru\u002Fblog\u002Fonline-store-cost\u002F","\u002Fru\u002Fblog\u002Fpersonal-account-guide\u002F","\u002Fru\u002Fblog\u002Fportal-where-to-start\u002F","\u002Fru\u002Fblog\u002Fredesign-without-losing-seo\u002F","\u002Fru\u002Fblog\u002Fsite-support-guide\u002F","\u002Fru\u002Fblog\u002Fslow-site-checklist\u002F","\u002Fru\u002Fblog\u002Fwordpress-or-custom-code\u002F","\u002Fblog\u002Fbusiness-card-site-price\u002F","\u002Fblog\u002Fcatalog-or-online-store\u002F","\u002Fblog\u002Fcorporate-site-cost\u002F","\u002Fblog\u002Ffigma-to-html-checklist\u002F","\u002Fblog\u002Ffull-stack-vs-team\u002F","\u002Fblog\u002Flanding-page-cost\u002F","\u002Fblog\u002Fmobile-app-cost\u002F","\u002Fblog\u002Fonline-store-cost\u002F","\u002Fblog\u002Fpersonal-account-guide\u002F","\u002Fblog\u002Fportal-where-to-start\u002F","\u002Fblog\u002Fredesign-without-losing-seo\u002F","\u002Fblog\u002Fsite-support-guide\u002F","\u002Fblog\u002Fslow-site-checklist\u002F","\u002Fblog\u002Fwordpress-or-custom-code\u002F","\u002Fblog\u002F","\u002Fen\u002Fblog\u002F","\u002Fru\u002Fblog\u002F","\u002Fbrief\u002F","\u002Fen\u002Fbrief\u002F","\u002Fru\u002Fbrief\u002F",1793673477530]