Ecommerce Template
Next.js·React 등으로 만든 최신 전자상거래 템플릿
남아프리카 식료품 쿠폰 코드, 무료 배송 및 할인 정보를 찾습니다
Find South African grocery coupon codes, free delivery and discounts. Read qualifying terms and expiry dates for Checkers, Pick n Pay, Woolworths, Shoprite, SPAR and Makro.
커머스TypeScript · CSSGitHub @thembaxx온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗A South African grocery-promotion explorer with offer terms, saved offers and three switchable interface designs.
Explore the live application · Browse the source
Persistent local preferences, PWA build tooling and a promotion-discovery pipeline; source freshness and retailer validation remain important.
Declared in package.json: Next.js 16.4.0 · React 19.3.0 · TypeScript ^7.0.2 · Tailwind CSS 4.3.3 · Three.js ^0.186.1 · Motion 14.0.0 · Zod ^4.1.0.
Quality tooling: lint, format:check, typecheck, test, test:e2e, check scripts are available. See the setup guide below for prerequisites; this documentation pass does not assert that those checks were run.
Captured from the live application on 17 October 2026. Capture details and limitations.
A little less at checkout.
A mobile-first app for finding South African grocery promotions, reading the terms, and copying a code in one tap. Built with Next.js 16, React 19, TypeScript, Tailwind CSS 4, Motion, Three.js, Hugeicons, oxlint, oxfmt and pnpm.
Three working designs are included. Open the header's settings gear to choose a view from illustrated previews, set a light, dark or system theme, and control animated backgrounds. The mobile sheet can be swiped down to close; desktop uses a side panel. Your preferences and saved offers persist in your browser.
| Wallet · default | Rewards | Orbit |
|---|---|---|
| Stacked brand-colour cards, mint accents and a dark canvas. | A bright blue hero, generous offer tiles and a light theme. | Editorial serif typography and a swipeable store carousel. |
Brand guidelines · Compare the designs · Settings preview · Desktop preview
Open settings to install the app on a phone or desktop. Supported browsers offer an Install app button; on iPhone and iPad, settings explains Share → Add to Home Screen → Add. Installation requires HTTPS in production (localhost is supported for development). The app includes 192px and 512px launcher icons, a separate maskable icon, an Apple touch icon, an install screenshot and shortcuts for delivery, discounts and saved offers.
After the first online visit, settings shows Ready offline when both the app shell and offer snapshot are saved. The installed app can cold-launch without a connection. Search, filters, store details, bookmarks, copying, themes and view switching continue to work. Expired promotions and records past their 24-hour freshness deadline stay hidden, including offline; an empty offline list never claims there are new offers. Discovery, source pages and reports need a connection. Reconnection loads current listings automatically, with a manual retry available.
Each production build generates a versioned service worker from the actual Next.js assets. It precaches a clean /offline shell, scripts, styles, fonts, icons and theme manifests; offer snapshots live separately in IndexedDB. It does not cache live HTML, API responses, RSC payloads, POST requests or retailer pages. A failed precache does not activate, and its partial cache is removed. The last working build remains available to older open tabs. An Update now / Later notice lets users choose when to reload; bookmarks and preferences survive updates. Development mode does not register the worker.
Installation controls · Offline preview
Public store pages at /stores and /stores/checkers (plus the other five store IDs) render qualifying criteria, exact expiry/review times and source links without JavaScript. /about explains the evidence and expiry policy; /privacy documents device storage, reports and external services. Footer links make these pages discoverable.
Set SITE_URL to the public HTTPS origin and INDEXING_ENABLED=true on production to enable canonical URLs, Open Graph/Twitter sharing, robots and the ten-page sitemap. On Vercel, the stable VERCEL_PROJECT_PRODUCTION_URL is the automatic fallback and indexing defaults on only for VERCEL_ENV=production; an explicit INDEXING_ENABLED overrides this. Other hosts and previews default to noindex and an empty sitemap. The app never substitutes a guessed domain or request Host for a canonical. Structured data describes the website/application and breadcrumbs without invented ratings or prices.
/llms.txt links to current information; /promotions.md provides request-time Markdown with the same expiry/freshness filtering as the UI. Records include source evidence links, qualifying criteria and validity deadlines. These are discovery aids, not a guarantee of search or AI-answer ranking.
pnpm check:production verifies required public URL, operator contact, scheduler secret and storage/provider configuration without printing credentials. /api/health checks storage readiness. Directory preview · Store details · Social card
Privacy and security audit · Production launch guide covers deployment, scheduling, privacy, monitoring, indexing and remaining operator steps.
CI/CD and repository protection documents required checks, Dependabot, CodeQL, secret scanning, CodeRabbit/GitGuardian connections and candidate deployment/promotion. Contributing explains the pull-request workflow. GitGuardian and CodeRabbit are connected; server protection and production promotion require owner-side setup.
Use Node.js 24 and pnpm 11.19.0:
pnpm install --frozen-lockfile
cp .env.example .env.local
pnpm dev
Open http://localhost:3000. You can link directly to /?design=wallet, /?design=rewards or /?design=orbit. Dark, light and system themes are supported; dark is the initial default. Rewards switches to light when selected, and settings can change it.
The document canvas, page, loading skeleton, browser theme colour and install manifest share the active background. A small inline head script applies saved preferences before React loads and keeps browser metadata in sync with theme and design changes. Light Orbit uses its lavender canvas throughout. Dynamic viewport heights and safe-area insets cover mobile browser bars, notches and landscape layouts. Browser chrome and installed splash-screen behaviour still depend on platform support; existing installs may keep their original launch colour until their manifest updates.
For a production Node server:
pnpm build
pnpm start
# Optional port:
pnpm start --port 4000
The build prepares Next's standalone server and its static assets. The start script loads standard production environment files and keeps local data outside the build directory.
The attached prototype contains placeholder coupon codes. None of those codes are used in live results. The initial data is a small, manually reviewed primary-source snapshot of recurring benefits, reviewed on 8 October 2026. Each record has a 24-hour freshness deadline; stale records disappear unless a successful source check renews them. An ongoing benefit is explicitly labelled with no listed end date. Availability depends on the retailer's terms and checkout.
The initial snapshot includes Checkers Xtra Savings Plus delivery, Woolworths MyDifference PLUS online delivery, and Makro's senior food discount. Woolworths online delivery is not presented as confirmed Dash free delivery. Offers requiring membership show that requirement. Stores without a confirmed offer remain visible at the bottom.
Gemini first: set the GitHub secret GEMINI_API_KEY. Projects with legacy access use Gemini 2.5 Flash/Flash-Lite grounded search. If those models return 404, Gemini 3.5 Flash-Lite uses free generation to prioritize existing links from permitted official pages. It selects indices into fetched links and cannot create new URLs or offers. This fallback is not web search; the collector still verifies every promotion independently. Use a free-tier AI Studio project; the API cannot force free billing on a paid project. Quota/authentication failures do not trigger model retries. See Gemini setup and limits.
Free collection: official HTML promotion blocks, JSON-LD, text PDFs and reviewed evidence are independently checked without mandatory search fees. Gemini supplies URLs only; generated codes or snippets are never published as evidence. Optional Brave Search discovers additional approved URLs when Gemini finds no official source. The GitHub collector can render permitted JavaScript-only pages using Playwright; coupon-site claims remain review candidates. Approved campaign links share a bounded page budget. Retailer protections and JavaScript-only pages can make a source unavailable. Partial failures retain only still-fresh listings with their original deadlines.
Optional web-search pilot: Treg Web Access can augment Brave Search with a
per-call cost ceiling and shared per-run budget, without changing the existing
source-validation rules. It requires a server-only TREG_TOKEN secret in the
Actions discovery environment and explicit DISCOVERY_SEARCH_MODE=treg or both opt-in; user-triggered refreshes never invoke paid
search. Optional Treg page extraction only creates unverified review
candidates, never live offers. See Treg integration and limits.
Optional free fallback: CJ Affiliate Link Search is queried when a store's official sources fail or yield no eligible coupon. It needs a free publisher account, an approved property, and approved South African advertiser IDs. Coverage is not assumed. Configure CJ_API_TOKEN, CJ_WEBSITE_ID and CJ_ADVERTISERS together, or leave all unset. The adapter validates advertiser identity, joined status, ZA targeting, merchant destination, eligibility and expiry. It uses bounded requests and does not follow tracking redirects.
Shared feed without a database subscription: the twice-daily Actions workflow publishes validated offers.json and unconfirmed candidates.json on a separate promotion-data branch. Vercel production reads this feed by default; on other hosts, set PROMOTION_FEED=github after the first successful scan. Browser Refresh loads the scheduled feed immediately and can optionally queue a rate-limited Actions scan when a server-only GitHub dispatch token is configured. Private reports/rate limits still need the existing persistent file or Supabase storage. Explicit PROMOTION_FEED=local keeps local/shared-database collection available.
Pick n Pay's public coupon-site JSON supplies review leads only. Unknown-expiry leads are not live offers. A reviewer can add exact retailer evidence to data/reviewed-promotions.json; every later scan rechecks it. Explicit recurring membership benefits can have no listed expiry, with fees and eligibility preserved. Read the collection and fallback guide for setup and limits.
All discovered codes are marked not tested at checkout. The app never generates or silently guesses a coupon code. Date-only expiry is interpreted as 23:59:59.999 in Africa/Johannesburg (UTC+2). Offers are deduplicated by retailer plus code or title. Every listing links to its source, shows its last review time, and supports reporting a problem.
| Endpoint | Behaviour |
|---|---|
GET /api/offers?filter=all&q=checkers | Fresh, unexpired offers. Filters: all, free_delivery, discount. Search matches retailer and loyalty names. |
POST /api/refresh | Checks public sources or reads the scheduled GitHub feed. With a configured dispatch token, GitHub mode also queues a rate-limited background scan; the response includes scan.status. No model key is required. |
POST /api/report | Saves a report for an existing listing. Body: { "offerId": "...", "reason": "The code didn't work" }. Also accepts The offer has ended and The terms are different. |
GET /api/cron | Authenticated collection/feed check. Header: Authorization: Bearer <CRON_SECRET>. |
Refresh and reports validate browser origin. Set TRUST_PROXY=true only when the deployment ingress overwrites x-forwarded-for; otherwise all local clients share a conservative refresh bucket. No raw IP addresses are stored by the app. Set a separate RATE_LIMIT_SECRET (32+ random characters) in production; address identifiers use daily rotating HMACs. Public discovery has a shared ten-minute cooldown. Reports are removed after 30 days during the next report write or scheduled cleanup, using the updated service-role-only Supabase RPCs. Apply the current supabase/schema.sql before enabling writes. The single-node development limiter is in memory; Supabase provides an atomic distributed limiter.
API responses are excluded from indexing and use no-store. Reports have a 2KB streamed-body limit, JSON validation and safe error responses. Browser mutations accept the configured origin behind ingress and reject cross-site requests.
For local development or a single Node server, the app writes cache and reports to .data/ using atomic cache-file replacement. Set DATA_DIR to a persistent volume in production. Without a persistent volume, data can be lost when an instance restarts.
For serverless or multiple instances, run supabase/schema.sql, then set:
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_ROLE_KEY=your_server_only_service_role_key
This stores the shared offer cache, reports and rate limits in Postgres through Supabase REST. Row level security is enabled; clients cannot read or mutate these tables. Reports are stored for review in promotion_reports or .data/reports.jsonl; there is no admin dashboard in this version.
A Dockerfile is included for a Node deployment. Mount /app/.data on a persistent volume, or configure Supabase. Provide discovery secrets at runtime, not during the build. A static-only host cannot run the discovery APIs.
The GitHub collector runs twice daily and supports manual dispatch on main. GEMINI_API_KEY enables primary free-tier-compatible grounded search; collection still works without model, paid search or database keys. It publishes a separate data branch; optional CJ credentials enable the fallback. A successful scan requires at least one source evaluation, not a positive coupon count. See the setup guide.
pnpm check:production # Check deployment configuration before launch
pnpm check # oxlint, oxfmt, TypeScript and Vitest
pnpm build
pnpm exec playwright install --with-deps chromium firefox webkit
pnpm test:e2e
Browser tests use an isolated server on port 3100 and temporary fixtures in .data/e2e. Their coupon is test-only and never enters production sources. Set PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH when using an existing Chromium binary.
Tests cover expiry/freshness, South African dates, deduplication, source boundaries and evidence; mobile and desktop tests cover search, filters, accordion behaviour, copy, saved offers, reports and refresh limits. Settings checks cover saved choices, focus return, Escape, sheet dragging, small and landscape screens, and changes to the device's motion preference. Automated axe checks scan all three designs in both themes on mobile and desktop, including the settings panel. Appearance and settings checks also run in Firefox and mobile WebKit. Software WebGL checks in Chromium verify all three scenes, a single canvas, context-loss recovery and the sparkle action; every engine tests the no-WebGL fallback. A GitHub CI workflow runs these checks on pushes and PRs.
PWA tests enable real service workers and drop network connections at an isolated local origin, covering cold launches, expired and corrupted snapshots, reconnecting, install controls, launch shortcuts, native sharing and explicit worker updates in Chromium, Firefox and WebKit. Ordinary UI tests block workers so network mocks remain isolated. Unit tests verify worker caching boundaries, outage fallback, previous-build retention and failed installation cleanup. Production tests cover canonical/preview isolation, structured-data escaping, AI feed expiry, strict extraction evidence, report byte limits, readiness and crawler/social endpoints. Store and information pages are checked without JavaScript and with automated accessibility scans.
The UI follows the attached Wallet handoff and card references: overlapping store cards, clear offer counts, full-width copy actions, no-code states, brand-responsive ambient colour, and a calm count-up. Hugeicons provide interface icons throughout; the grocery bag remains a custom illustration. Motion adds gentle pointer tilt, spring filters, press feedback, copy checkmarks and bookmark pops. Saving or copying an offer sends a small pulse through the background; the sparkle beside today's count invites the same delight. Pull-to-refresh distinguishes vertical movement from a horizontal carousel swipe.
Each view has its own transparent Three.js scene over the shared page colour: soft ribbons for Wallet, floating rounded tiles for Rewards, and orbiting rings for Orbit. The renderer loads separately after the useful content paints and the browser has idle time, caps rendering at 30fps and pixel ratio at 1.25 on phones or 1.5 on larger screens, and pauses in hidden tabs. Geometry and listeners are disposed when disabled. Reduced-motion and data-saving visits skip the renderer; unavailable WebGL keeps the static ambient background. All motion respects prefers-reduced-motion, including preference changes during a visit.
Controls are labelled; search and filters work on small screens; dialogs use native focus trapping, Escape and Back dismissal; keyboard focus is visible. Search inputs use 16px text on touch devices to avoid automatic iPhone zoom, while pinch zoom remains available. Installed mode respects safe areas, limits overscroll and adapts to the onscreen keyboard. Share actions use the system share sheet when available, with a clipboard fallback. Supported installed platforms can show the current offer count as an app badge. Saved offers and preferences stay on the device. Push notifications and background discovery are not enabled; the scheduled server discovery remains separate from offline browsing.
Fonts are self-hosted Plus Jakarta Sans, Bricolage Grotesque and Instrument Serif, with their OFL licences in public/fonts. Retailer names are rendered as typographic identifiers and fallbacks rather than claiming to be official logo assets. Verified retailer-supplied SVGs can replace StoreMark when provided. Retailer names and marks belong to their owners; the app is independent and uses no affiliate links.