Nami Smart LLC

arukutomaru: a cross-border shop whose main market is now Korea

A small shop selling around 30 products worldwide. After we rebuilt it around five languages and multilingual SEO, it went from 80% Japanese buyers to Korea leading on both visits and revenue.

Period
In development and production use
Stack
Astro (static output) React + Tailwind CSS Hono / Cloudflare Workers Cloudflare D1 + R2 d1zzle Better Auth Stripe Storyblok (headless CMS)

The problem it solves

The problem this project set out to solve was not cost. It was which country’s customers find the shop. arukutomaru used to run on STORES, and back then 80% of its buyers were Japanese. The products themselves sell perfectly well abroad, so we took the view that they simply were not being found, and made multilingual support and multilingual SEO the centre of the rebuild.

Customers from Korea grew from there, and today Korea leads on both visits and revenue. People who never saw the shop while it was Japanese-only now arrive on it straight from search.

Cost was the second goal. For a shop with a few dozen products, the monthly fee of a hosted commerce platform is heavy relative to what it sells, so the new stack costs nothing beyond Cloudflare usage and Stripe’s payment fees.

Multilingual support and multilingual SEO

The shop serves Japanese, English, Korean, Chinese and Thai. Three decisions mattered.

Give each language its own URLs. Japanese sits at the root (/products/2) and every other language under a code prefix (/en/products/2). If one URL merely switches what it displays, a search engine has no separate page to index for that language. hreflang only means something once the URLs are split.

Do not ship a language before its copy exists. The moment a language joins the active list, any page without a translation goes out with English content instead. That fills the index with pages nearly identical to /en/, which Google treats as duplicates and declines to index. A language joins the list only once its copy is ready.

Serve product pages as static HTML. Astro generates them ahead of time, so a crawler reads the text in each language without waiting for JavaScript. They come from a CDN edge, which keeps them fast from abroad, and for a cross-border shop that difference turns directly into orders.

How it is put together

It is a pnpm workspaces and Turborepo monorepo, split into three applications.

AppWhat it is
apps/webThe public storefront. Astro (static) with React and Tailwind
apps/adminThe product-management SPA. Vite and React, protected by Cloudflare Access
apps/apiA Hono REST API on Cloudflare Workers, talking to D1 and R2

The API is REST, and the front end calls it through Hono’s typed RPC client (hc<AppType>). As long as route handlers are written as a method chain, the API’s types are the front end’s types, and a changed endpoint fails the build.

Product images live in R2. Only editorial content such as blog posts goes through Storyblok, a headless CMS; the product data itself deliberately stays out of the CMS.

Contact us