The checkout request carries product IDs, quantities, the delivery choice and the language, and nothing else. The server looks each ID up in its own catalogue, refuses an unknown product or a quantity that is not a whole number from 1 to 99, and works out the subtotal and the shipping from its own prices. An edited request can change what is ordered, never what it costs. Line items are built per request in Australian cents rather than registered in Stripe as fixed prices, so the site's catalogue is the only place a price lives.
06 — Commerce / Sake for Australia / 2026
AMACHIHOSHISORA
A store selling Amachi Hoshisora, a junmai daiginjo brewed at the foot of Mt Fuji, to customers in Australia. Prices are in Australian dollars, and each order is either delivered within Australia or handed over in person with no shipping charge.
2026Australia
- CLIENT
- Kondo Pharmacy Co., Ltd. — 株式会社近藤薬局
- SECTOR
- Commerce / Sake for Australia
- ROLE
- Design, development, payments, bilingual, SEO, operation
- YEAR
- 2026
01 / PROJECT
WHAT THE
PROJECT IS.
Amachi Hoshisora is made by Fujinishiki, a brewery at the foot of Mt Fuji founded in the Genroku era (1688–1704), from Yamada Nishiki rice polished to 40% and spring water that takes around seventy years to filter through the mountain. The store sells it in 720 ml and 500 ml alongside Fuji no Shizuku, a 180 ml junmai ginjo, and carries a page on the water and the rice, the brewery's three hundred years with a timeline, and common questions, in English and Japanese.
An order goes from the cart to Stripe's payment page. Before paying, the customer chooses delivery or handover in person: delivery asks for an address in Australia and a phone number and costs A$50, free from A$600; handover costs nothing extra. Stripe emails the receipt. The site asks for age on arrival — 18 or over under Australian law on the English pages, 20 or over on the Japanese ones — and publishes a privacy policy, terms and the disclosures Japan's specified commercial transactions law requires.
The site launched in 2025. In 2026 I redesigned it around a night timelapse of Mt Fuji, added a page on the two sakes and one on the brewery's history, and rebuilt the code so that pages render on the server and only what needs the browser — the cart, the age check, the motion — is split out as small pieces. I handled it end to end: design, implementation, payments, the bilingual structure, SEO, deployment to Vercel and operation.
02 / HOW IT WORKS
THE DECISIONS
UNDER IT.
FROM THE IMPLEMENTATION
Choosing delivery makes the checkout session collect a shipping address, limited to Australia, and a phone number, and adds A$50 as its own line unless the subtotal has reached A$600. Handover in person collects neither and adds nothing. The choice is written onto the payment and its invoice as the order type, so each payment in the Stripe dashboard says how the bottles are to reach the customer. Invoice creation is switched on, which is what sends the receipt.
Going to Stripe and back is a full page load, so the cart cannot live in React state. It lives in a small store synced with local storage and read through useSyncExternalStore: the server renders an empty cart, the browser restores it after hydration, and a change in one tab reaches the others. What is read back is checked item by item, and a malformed item is dropped on its own instead of breaking the cart. The success page empties it and reads the payment from Stripe on the server, with the secret key in a server-only module. A customer who comes back from Stripe with the back button gets the page from the browser's cache, so the checkout button is reset rather than left saying it is processing.
Whether a visitor has passed is kept in local storage, which the server cannot read, so the server's HTML carries a dark cover in place of the check. A line of script in the head, run before the first paint, marks the page for anyone who has already passed, and CSS removes the cover for them: a returning visitor never sees the check flash up, and a new one never sees the page before it. The opening animation waits for the pass instead of playing out behind the check. Where storage is blocked, the pass holds for the rest of the tab.
Pages are Server Components that say what moves with a data-motion attribute — a heading set a character at a time, a photograph revealed behind a rising edge, an archive photograph that develops, a timeline whose line grows with the scroll, a number that counts up — and a single client hook attaches GSAP to all of them. On a direct visit, anything already on screen is left exactly as the server drew it, so the motion never holds back the largest paint; of the opening animations, only the home page's hero plays. The night timelapse is not preloaded: the HTML shows its first frame, and the video is fetched only for visitors who have not asked for reduced motion.
03 / DELIVERED
WHAT WAS
BUILT.
- 01
Pages for three bottles, a page on the two sakes' water and rice, the brewery's history with a timeline and Meiji-era photographs, and an FAQ, in Japanese / English
- 02
A catalogue with category filter and sorting, and a cart kept across the Stripe round trip, a language switch and other tabs
- 03
Stripe Checkout in Australian dollars, with delivery within Australia or handover in person chosen per order
- 04
Amounts and shipping calculated on the server — A$50, free from A$600, none for handover — with receipts sent by Stripe
- 05
An order confirmation page that reads the payment from Stripe on the server and empties the cart
- 06
Age confirmation on arrival — 18 or over in English, 20 or over in Japanese — with the privacy policy, terms and specified commercial transactions disclosures
- 07
Scroll motion with GSAP driven from the markup, and a night timelapse of Mt Fuji that holds still for anyone who prefers reduced motion
- 08
The language always in the URL, per-page canonical and hreflang, a sitemap covering both languages, noindex on the payment result pages and a permanent redirect from the old FAQ address
04 / TECHNOLOGY
THE STACK
BEHIND IT.
- Next.js
- React
- TypeScript
- next-intl
- Stripe
- GSAP
- Tailwind CSS
- Radix UI
- Vercel

