Add Amazona: Amazon-style e-commerce storefront (Next.js + Tailwind)#1
Open
hellokij wants to merge 4 commits into
Open
Add Amazona: Amazon-style e-commerce storefront (Next.js + Tailwind)#1hellokij wants to merge 4 commits into
hellokij wants to merge 4 commits into
Conversation
Full-storefront e-commerce demo with home, search/listing, product detail, cart, and mock checkout. Cart state via React Context + useReducer persisted to localStorage. Seed catalog with generated SVG placeholder assets. Original 'Amazona' branding (not affiliated with Amazon).
- Extract discountPercent() and MAX_CART_QTY to lib/format; dedupe discount computation across ProductCard and product detail - Add shared QuantitySelect component; dedupe quantity <select> - Clamp cart quantities to MAX_CART_QTY in reducer (add + setQuantity) - Validate/reconcile localStorage cart via normalizeStoredItems - Sync Header search inputs with URL params after client navigation; normalize invalid category to All - Add mobile-visible department selector on search page - Remove unused useRouter from CheckoutView; dedupe subtotal line - Add Vitest + unit tests for searchProducts and the cart reducer/ normalization (21 tests)
Guard the URL category param with categories.includes() so an out-of-range ?category value normalizes to All in both the header control and the results grid, keeping them in agreement.
- Add allowedDevOrigins for the Vorflux preview host so Next.js dev serves HMR/font resources to the proxied hostname; without it the app fails to hydrate on the public preview URL and all client handlers fall back to native browser behavior. - Track a mounted flag in the cart reducer and render the header cart count as 0 until after client mount, eliminating the SSR/client hydration mismatch on the cart badge (count is only known client-side after localStorage hydration). Guard the persist effect on mounted so the empty initial state never clobbers stored cart data.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Builds Amazona, an Amazon-style e-commerce storefront, as a new Next.js (App Router) + React + TypeScript + Tailwind CSS v4 app. This is the first code in the repo — the whole diff is new.
The goal was an Amazon-like storefront. Rather than copy Amazon's actual logo, product listings, and copy (which are trademarked/copyrighted), this uses original "Amazona" branding, a seeded placeholder catalog, and generated SVG product images, while closely mirroring Amazon's layout and UX.
Features
/search) — full-text search over the catalog with department filters, star-rating filters, and sort (featured / price low→high / price high→low / avg. rating). Includes a mobile-visible department selector since the filter sidebar is hidden on small screens./product/[id], statically generated) — image, ratings, discount + struck-through list price, feature bullets, quantity selector, Add to Cart / Buy Now, and related products./cart) — line items with quantity edit and remove, live subtotal, persisted tolocalStorageso it survives reloads./checkout) — shipping + payment form with native HTML5 validation, order summary with tax/shipping, and an order-confirmation state with a generated order number. No real payment is processed.Architecture
useReducer, persisted tolocalStorage. Quantities are clamped to a max of 10 (matching the UI selectors), and stored data is validated/reconciled against the current catalog on load (normalizeStoredItems) so malformed or stale entries can't crash rendering.formatPrice/discountPercentlive in a plain (non-client) module so both server and client components can use them.src/lib/products.ts; no backend/database.Testing
Automated + browser end-to-end testing, all passing.
Unit tests (Vitest, 21 tests,
npm run test):searchProducts/getProduct(query, brand, category, combined scoping, no-match) and the cart reducer +normalizeStoredItems(add/increment, MAX_CART_QTY clamp, setQuantity clamp + zero-removes, remove, clear, malformed/stale localStorage recovery).Checks:
npm run buildprerenders all 19 pages cleanly;npm run lintpasses with zero warnings.Browser E2E (all 7 planned flows + 2 bonus checks PASS):
normalizeStoredItems)AMZ-XXXXXX), cart clearedDuring testing a real preview-only defect was found and fixed: the Next.js dev server blocked cross-origin dev resources (HMR/fonts) from the preview proxy host, which prevented hydration on the public URL. Fixed via
allowedDevOriginsinnext.config.ts(Next.js drops this check in production builds). A cart-badge SSR/client hydration mismatch was also fixed by gating the count until after mount.Evidence:
Live preview: https://shf67bq5jzyg.preview.us1.vorflux.com
Notes
Original demo project for learning purposes — not affiliated with, endorsed by, or connected to Amazon.com, Inc. All branding, product names, and imagery are original placeholders.
Attached Videos
🎥 View recording: amazona_e2e.webm
🎥 View recording: amazona_flows5to7.webm
View in Vorflux Session
Session Details
(aside)to your comment to have me ignore it.