The problem
Small merchants in Malaysia spend an enormous amount of effort maintaining a digital presence across half a dozen platforms — Instagram, TikTok, WhatsApp Business, Google Business Profile, Grab, Foodpanda — and yet most of them have no single canonical page that they can hand to a customer. Their printed flyers point to an Instagram handle. Their WhatsApp bio points to a Google Maps pin. Their TikTok bio points back to Instagram. There is no centre.
At the same time, almost all of these merchants struggle with the same secondary problem: their public profiles look thinner than they deserve. The food is good. The service is real. But the profile has three photos, no description, and zero reviews — because nobody has the time to ask customers to leave one.
JuuLinkAI was designed around that pair of problems. One profile, many links — and a calm, considered way to populate the empty fields.
The approach
We framed the product around three deliberately narrow capabilities:
- A canonical merchant page. One URL the merchant can paste anywhere, with their logo, a short description, and an ordered list of channel links.
- A QR code, generated automatically. Designed to be printed on a small acrylic stand for the counter. We obsessed over making the QR scannable from across a noisy shop.
- An AI co-pilot for review drafting. The merchant types a few real things customers have said, and the product produces three publishable review drafts the merchant can copy, edit, and share.
Everything else — analytics, multi-team, custom domains, embedded widgets, themes — was on the cutting-room floor. The first version of the product had to do these three things well before it earned the right to do anything else.
Design choices that mattered
Mobile-first, mobile-old
Most of our merchants use four-to-five-year-old Android phones while standing in their shop. We designed every flow assuming a 5.5-inch screen, mid-range processor, scratched glass, phone case on. Tap targets are 56 pixels minimum. Forms are single-column even on desktop. Errors are inline and persistent — never toast — because nobody is watching the screen when they pop up.
Bilingual copy, hand-written
Every label in the product exists in English and Malay. We wrote the Malay ourselves rather than machine-translating it. The difference shows: machine-translated labels are technically correct and emotionally cold, while hand-written copy sounds like a human wrote it for another human.
AI without the chatbot
Our review drafting feature is a single button labelled Generate. No chat, no persona, no "Hi, I'm Juu, how can I help you?" The model output runs through a small style filter that removes exclamation marks, strips boilerplate openers, and normalises capitalisation. The result looks like text a careful person wrote, not text a model produced. We wrote more about this approach in our journal post on soft-spoken AI.
Defaults that do the work
When a new merchant signs up, we ask one question — what kind of business — and use the answer to set sensible defaults for everything else. Channel order. Recommended description length. Suggested review tone. The user can override everything, and most don't.
The build
The product runs on Next.js (App Router) with Postgres for relational data and Cloudflare R2 for media. The AI features call Google's Gemini API behind a thin server-side wrapper that handles prompt construction, rate limiting, and the post- processing style filter. We host on Vercel for the frontend and Fly.io for the long-running background jobs.
The whole stack was chosen with two constraints in mind: it should be something one person can operate, and it should degrade gracefully. If Gemini is down, the rest of the product keeps working — the AI button just shows a calm "back in a minute" state. If R2 is slow, image uploads queue. Nothing is critical-path on a single external dependency.
Outcomes
We launched JuuLinkAI quietly to friends-of-friends in early 2026 and grew it through word of mouth in the months after. Some of the things we have seen since:
- Profile creation completion rate of 84% from sign-up — a number we attribute almost entirely to the single-column form and the sensible defaults.
- AI review feature adoption: 71% of active merchants generate at least one review draft per week. The post-processing style filter is, we think, why merchants trust the output enough to publish it.
- Average page load on the public merchant page: 1.2 seconds on 4G, 0.4 seconds on cable. We were aggressive about static generation and image compression.
- Support load: about 30 minutes a day, mostly answering merchant questions over WhatsApp rather than email — because that is the medium they actually use.
What we would do differently
We started building before we started talking to merchants. We spent three weeks on a backend architecture that the eventual product did not need, because the eventual product turned out to be different from the imagined one. If we did it again, we would interview ten merchants before writing a line of application code.
We also under-invested in onboarding for the first month. We had a clean dashboard, but no narrative for what to do first. The merchants who got the most out of the product were the ones we had personally walked through it. We have since added a short, inline onboarding pass that brings the rest of the user base closer to that experience.
Where it goes next
The roadmap is short and deliberate. We are adding two capabilities in the next two quarters: a lightweight booking link for services-based merchants (hairdressers, tailors, tuition centres), and a way to share the AI-drafted reviews directly to a Google Business Profile via the supported API. Both are real merchant requests, surfaced repeatedly in support conversations.
We are also intentionally not doing several things. We are not building an analytics dashboard beyond a simple page-view count. We are not adding team accounts. We are not building themes. None of these have been asked for by enough real merchants to earn a spot on the roadmap.
