روبات مارکت — Robot Market Landing
A cinematic, RTL, Persian-language landing page for Robot Market, a smart refrigerated vending-machine brand. Built with Next.js (App Router), Tailwind CSS, Ant Design, Redux Toolkit, Axios and GSAP + ScrollTrigger.
The centerpiece of the page is a scroll-driven hero animation: scattered SVG pieces fly together into a fully assembled vending machine as the user scrolls, followed by a three-act "scroll story" introducing each of the three product models.
Getting started
npm install
npm run dev
Open http://localhost:3000.
npm run build # production build
npm run start # serve the production build
npm run lint # eslint
Tech stack
| Concern | Library |
|---|---|
| Framework | Next.js 14 (App Router, JS only) |
| Styling | Tailwind CSS |
| Component library | Ant Design (RTL-configured) |
| State management | Redux Toolkit |
| HTTP client | Axios |
| Animation | GSAP + ScrollTrigger + @gsap/react |
| Icons | react-icons |
| Font | Vazirmatn (next/font/google) |
Project structure
src/
app/ Routes (App Router): layout, page, dashboard,
robots.js, sitemap.js, manifest.js, loading, 404
components/
common/ Container, Section, GlassCard, MagneticButton
layout/ Navbar, Footer, About, ContactCta
hero/ Hero, HeroBackground, MachineAssembly, FloatingProducts
products/ ProductsShowcase, ProductSection, MachineVisual
animations/ ScrollReveal (shared scroll-in wrapper)
ui/ AntThemeProvider (Ant Design RTL + token bridge)
redux/
store.js Store factory (per-request, App-Router-safe)
provider.jsx Client <StoreProvider>
slices/ auth, products, ui
services/
axios.js Shared Axios instance + interceptors
auth.service.js // TODO: Connect Login API
product.service.js // TODO: Connect Product API
dashboard.service.js // TODO: Connect Dashboard API
hooks/ useReducedMotion, useIsomorphicLayoutEffect
utils/ cn, formatPrice, gsapConfig, breakpoints
constants/ theme tokens, nav links
data/ products.json, floatingProducts.json (mock data)
public/
svg/machines/machine35|48|60/ Assembly pieces: base, body, door, panel, screen, shelves
svg/floating/ chip, cola, drink, cookie, snack, juice
icons/ Brand icon + OG image placeholders (SVG)
Replacing placeholder assets
Every visual asset in public/svg is a deliberately simple placeholder —
swap the files in place (same filenames) and nothing else needs to change:
public/svg/machines/<model>/*.svg— the 6 pieces GSAP assembles/positions. Keep the sameviewBox="0 0 400 700"coordinate space so pieces still line up when assembled, or update the piece list insrc/data/products.json.public/svg/floating/*.svg— the floating product icons around the hero.public/icons/*.svg— brand icon and Open Graph placeholder. Replace the OG placeholder with a real 1200×630 raster (.png/.jpg) before launch and update the reference insrc/app/layout.js.
Connecting the real API
Nothing here talks to a real backend yet. Each service method already has
the exact call commented out — uncomment and remove the mock Promise.resolve:
// src/services/product.service.js
async getAll() {
// TODO: Connect Product API
return apiClient.get("/products").then((res) => res.data);
}
Set NEXT_PUBLIC_API_BASE_URL in .env.local (see .env.example).
Motion & accessibility notes
- Scroll-locked product story. Each
ProductSectionreports its DOM nodes up toProductsShowcase, which builds and pins all three machines'ScrollTriggertimelines together in one place (fixing a bug where wide/desktop viewports could fail to reveal machines after the first one — see the comment at the top ofProductsShowcase.jsx), then callsScrollTrigger.refresh()once every measurement has settled. Scrolling literally cannot advance past a pinned section until its reveal finishes — only then does the next machine begin. - Vivid, temperature-coded background per machine. Each product
carries its own
bgColorinsrc/data/products.json, andProductsShowcasecross-fades a single fixed color layer to that color over the exact same scroll range the section uses to pin — so the backdrop finishes changing exactly as the machine settles into place. The three models deliberately alternate cool → warm → cool: a vivid icy cyan-blue (#12C4E0) for the entry model, a warm coral-orange (#FF7A45) for the mid-tier, and a cool emerald-teal (#12D6A8) for the flagship — all bright, cheerful tones rather than muted brand neutrals, chosen specifically for this section. - Floating drinks/snacks per section.
SectionFloatingItems.jsxplaces a small set of product icons (soda, mineral water, juice, snacks) drifting gently around each machine — which items appear is configurable per product viafloatingItemIdsinproducts.json. - All GSAP animations check
prefers-reduced-motionand degrade to simple opacity fades (or skip entirely) when it's set. gsap.matchMedia()is used in bothMachineAssembly(hero) andProductSectionto give desktop/tablet/mobile different scroll distances/intensity.- Focus states, semantic landmarks (
<header>,<main>,<footer>,<nav>), and ARIA labels are included throughout.
SEO / PWA
- Metadata API with OpenGraph, Twitter cards, and canonical URL in
src/app/layout.js. - JSON-LD
Organizationschema inlined in the root layout. robots.js,sitemap.js, andmanifest.jsare implemented as Next.js route handlers (App Router convention) rather than static files.