Zelly Checkout
Zelly Checkout is the customer-facing checkout UI. It is a React SPA that runs as a full-screen popup or desktop page embedded in merchant Shopify stores via an iframe. It is deployed on Cloudflare Pages and has no server-side compute — no ECS, no Terraform, no AWS.
| Property | Value |
|---|---|
| Repo | zelly-in/checkout-ui-build — cloned locally at zelly-checkout/app/ |
| Platform | Cloudflare Pages (static; no Workers runtime) |
| Live URL | https://checkout.zelly.in/popup.html |
| CF project name | checkout-ui-build-worker-new-test-debug |
| Build tool | Vite 5 · React 18 · vite-plugin-singlefile |
| Build output | app/dist/ — fully self-contained HTML files |
zelly-checkout/app/. The outer zelly-checkout folder is a separate legacy repo — the active checkout source lives in zelly-in/checkout-ui-build, cloned inside it. Run cd zelly-checkout/app && npm install once; everything else in this guide runs from that directory.How it works
A merchant installs the Zelly loader script into their Shopify theme. When a customer clicks a data-zelly-checkout button, the loader fetches the Shopify cart, creates an <iframe> pointing at checkout.zelly.in/popup.html, and passes the cart data in via postMessage. The iframe renders the full checkout flow, then signals back to the parent on success or close.
| Build target | File | Use case |
|---|---|---|
popup | dist/popup.html | Mobile-first full-screen iframe embedded by the loader script |
desktop | dist/desktop.html | Desktop variant shown in a side-panel layout |
theme-login | dist/theme-login.html | Login widget injected into the merchant's own theme pages |
Local development
Zelly Checkout does not run in the shared docker-compose stack. Run it standalone from the app/ directory with a mock API that ships in the repo — no backend required.
- Install dependenciesbash / PowerShell — run from app/
cd d:\zelly\zelly-checkout\app # Windows cd /path/to/zelly-checkout/app # Mac/Linux npm install
- Set up the local environment file (copy the example and leave defaults for mock mode)bash
cp .env.example .env # Default VITE_USE_MOCK=true — no backend needed # To hit staging API: set VITE_API_BASE=https://api-staging.zelly.in/v1
PowerShellCopy-Item .env.example .env
- Start the dev server for the target you're working onbash / PowerShell
npm run dev:popup # http://localhost:5173 — mobile popup UI npm run dev:desktop # http://localhost:5174 — desktop side-panel npm run dev:theme-login # http://localhost:5175 — theme login widget
Vite HMR is active — edits to any
src/file reflect instantly without a page reload.
VITE_USE_MOCK=true) is the default. The app ships a built-in mock data layer that simulates a full checkout session — cart with items, address lookup, payment flow, order confirmation. You never need a running backend to iterate on the UI.Testing against real staging data
To point local dev at the real staging API instead of mocks, edit app/.env:
Restart the dev server after changing .env. CORS is configured on the staging API to allow localhost:517x origins.
Build & deploy
Build
npm run build
This runs all three build targets in sequence and writes the output to app/dist/. Each output is a single self-contained HTML file — CSS and JS are inlined, no separate asset files to manage. The dist/ directory is what Cloudflare Pages serves.
Staging deploys — automatic
Connect the zelly-in/zelly-checkout repo to the CF Pages project in the Cloudflare dashboard (Pages → zelly-checkout → Settings → Build & deployments → Connect to Git). After that, every push to main triggers an automatic build and deploy to the production Pages deployment (which serves checkout.zelly.in).
Every push to any other branch gets an automatic preview URL:
Use preview URLs to QA a change on a real CF edge before merging.
main → live checkout.zelly.in. Any other branch → preview URL. For changes that must be tested before going live, develop on a feature branch, verify the preview URL, then merge to main.Production deploys — manual
Production deploys are intentionally manual to match the rest of the platform's release cadence. Two options:
Option A — Wrangler CLI (recommended)
# First time only npm install -g wrangler wrangler login # opens browser; authenticate with the zelly CF account # Build, then deploy to production npm run build wrangler pages deploy dist --project-name checkout-ui-build-worker-new-test-debug
npm install -g wrangler wrangler login npm run build wrangler pages deploy dist --project-name checkout-ui-build-worker-new-test-debug
checkout-ui-build-worker-new-test-debug, not zelly-checkout. This is the name of the existing CF Pages project — always use this exact string in the --project-name flag. If you run wrangler pages project create zelly-checkout, you will create a second, separate project.Option B — CF Dashboard
In the Cloudflare dashboard: Pages → checkout-ui-build-worker-new-test-debug → Deployments → Deploy. Upload the dist/ folder directly from your browser. Useful when you don't have Wrangler installed.
Cache purge after deploy
CF's edge caches popup.html and desktop.html for up to 5 minutes (s-maxage=300). For an urgent hotfix to be live immediately:
Shopify integration
The checkout UI is injected into any Shopify store by pasting a single loader script into the theme. The loader handles cart data, iframe lifecycle, and event bridging between the merchant page and the Zelly iframe.
Install the loader script
- In Shopify Admin, go to Online Store → Themes → Edit code.
- Open
layout/theme.liquidand paste the contents ofshopify-loader/zelly-loader.jsjust before</body>. - Set the two config variables at the top of the pasted script:
- Add
data-zelly-checkoutto the checkout button in the theme:
Data flow
Listening to checkout events
Merchants can hook into lifecycle events fired on the parent page:
public/_headers. popup.html has X-Frame-Options: ALLOWALL and Content-Security-Policy: frame-ancestors * so it can load inside any merchant's Shopify store. desktop.html keeps SAMEORIGIN. Do not change these without understanding the Shopify embedding requirement.Environment variables
Cloudflare Pages does not read .env files at build time or runtime. The .env file only works locally (Vite reads it via dotenv). On CF you must set variables in the dashboard or via Wrangler.
VITE_* variables are build-time — Vite bakes them into the HTML bundle during npm run build. They only work from .env locally; on Cloudflare Pages you must set them in the dashboard or via Wrangler (below).
Local dev variables (.env)
| Variable | Default | Notes |
|---|---|---|
VITE_API_BASE | https://api.zelly.in/v1 | API base URL. Change to https://api-staging.zelly.in/v1 or http://localhost:4000/v1 for local backend |
VITE_USE_MOCK | true | When true, returns hardcoded mock responses — no backend needed. Set to false to hit a real API |
VITE_DEV_STORE_ID | store_dev_001 | storeId used when none is supplied via URL param or postMessage |
VITE_DEV_CART_TOKEN | cart_dev_abc123 | cartToken used when none is supplied via URL param or postMessage |
VITE_DEV_SESSION_TOKEN | tok_dev_abc123 | Pre-set session token — bypasses the OTP flow so you land directly on address/payment screens |
VITE_PAYMENT_MODE | gateway | gateway opens Razorpay SDK directly; inline shows expanded in-popup forms |
VITE_DEV_THEME | blue | Accent colour: blue · lime · orange · violet |
VITE_DEV_DARK | false | Dark mode toggle |
VITE_DEV_DENSITY | regular | Layout density: compact · regular · comfy |
VITE_DEV_SHOW_SPEED_HERO | true | Show the "11-second checkout" speed hero banner |
Cloudflare Pages variables (staging / production)
| Variable | Preview (branches) | Production (main) |
|---|---|---|
VITE_API_BASE | https://api-staging.zelly.in/v1 | https://api.zelly.in/v1 |
VITE_USE_MOCK | false | false |
Set variables in CF dashboard
Pages → checkout-ui-build-worker-new-test-debug → Settings → Environment variables → Add variable. Set them for Production and Preview separately — preview covers all non-main branch deployments.
Set variables via Wrangler CLI
Repo notes
The active source lives in zelly-in/checkout-ui-build. It is cloned locally at d:\zelly\zelly-checkout\app\ (Mac/Linux: wherever you put your workspace). The outer zelly-checkout folder is a legacy repo that is not actively used — do not confuse the two.
zelly-in/checkout-ui-build into zelly-checkout/app/ so it matches the path the rest of this guide assumes.