LanguageShop is a modern, responsive Progressive Web App (PWA) built with React 19, React Router v7, and Vite. It simulates an online merchandise store for a language school, featuring hoodies, t-shirts, mugs, and more β all powered by mocked data.
- ποΈ Product Catalog: Hoodies, zip-up hoodies, t-shirts, mugs, and socks
- π Smart Filtering: By category, price range, size, color, and availability
- π Shopping Cart: Add, update quantity, remove β with
localStoragepersistence - π± Fully Responsive: Mobile-first design that works on all screen sizes
- π₯ Offline Support: PWA with service worker caching for UI and product data
- π§ͺ Comprehensive Testing: Unit, integration, and E2E tests with Vitest + Playwright
- π§Ό Clean Code: Built with SOLID, DRY, and KISS principles
- π¦ Zero Backend: Full REST API simulation using MSW (Mock Service Worker)
- π Conventional Commits: Use Conventional Commits for commit messages
- Node.js 20+
- pnpm 10+
-
Clone the repository:
git clone https://github.com/gsroka/languageshop.git cd languageshop -
Install dependencies:
pnpm install
-
Start the development server:
pnpm dev
-
Open your browser:
Navigate to http://localhost:5173
π‘ No environment setup needed! All data is mocked β no API keys or
.envfiles required.
- Framework: React 19 with
useOptimistic,useActionState - Routing & SSR: React Router v7
- Bundler: Vite 7 for lightning-fast HMR
- State Management: Zustand 5.x β minimal, typed, scalable
- Styling: Tailwind CSS v4
- Forms: React Hook Form v8 + Zod
- API Mocking: MSW (Mock Service Worker)
- PWA:
vite-plugin-pwa - Testing: Vitest, React Testing Library, Playwright
- Language: TypeScript 5.5
- Tooling: ESLint, Prettier
language-shop/
βββ app/ # Main application directory (replaces src/)
β βββ routes/ # File-based routing (e.g., routes.products.$id.tsx)
β βββ components/ # Shared UI and feature components
β β βββ ui/ # Button, Input, Badge
β β βββ layout/ # Header, Footer, Root layout
β β βββ features/ # ProductCard, CartItem, FilterPanel
β βββ hooks/ # useDebounce, useLocalStorage
β βββ stores/ # Zustand stores (cart, products, filters)
β βββ types/ # TypeScript interfaces (Product, CartItem)
β βββ utils/ # formatters, helpers
β βββ app.css # global styles
β βββ root.tsx # app root
βββ public/ # Static assets, PWA manifest, icons
β βββ manifest.webmanifest
βββ tests/ # Unit & integration tests
βββ e2e/ # Playwright E2E tests
βββ vite.config.ts # Vite + PWA config
βββ tsconfig.json # With path alias: ~ β app/
This project strictly follows modern software engineering best practices:
- SOLID: Each store and component has a single responsibility.
- DRY: Shared types, hooks, and UI components are reused across the app.
- KISS: No over-engineering β logic lives only where necessary.
- Conventional Commits: All commits follow the Conventional Commits 1.0.0 spec.
Example commits:
feat(cart): persist cart state in localStorage
fix(products): handle missing image with fallback
refactor(filters): extract price range logic to custom hookpnpm dev # Start dev server (Vite + React Router)
pnpm build # Build for production (SSR + PWA-ready)
pnpm start # Start production server
pnpm preview # Preview production build locally
pnpm lint # Run ESLint
pnpm format:write # Format code with Prettier
pnpm typecheck # Run TypeScript checks
pnpm test # Run Vitest (unit + integration)
pnpm test:e2e # Run Playwright E2E testsView Full Implementation Plan
- Initialize project with
pnpm create react-router@latest - Install
vite-plugin-pwafor PWA support - Configure shadcn/ui
- Set up
tsconfig.jsonwith path alias~/ - Create
README.mdwith project overview - Initialize Git + Conventional Commits
- Define core types:
Product,CartItem,ProductVariant - Create folder structure inside
app/:components/,types/, etc. - Implement root layout (
app/root.tsx) - Set up routes:
/,/products/:id,/cart,/checkout - Add loading and error boundaries (React Router v7 conventions)
- Create shared layout components:
Header,Footer
- Install MSW
- Create mock product data (5 categories, 20+ items)
- Implement
GET /api/productsandGET /api/products/:id - Integrate
apiClientabstraction inapp/api/client.ts - Add delay and error simulation in MSW
- Build
ProductListandProductCardcomponents - Implement
useProductStorewith Zustand (fetch + cache) - Create
FilterPanelwith React Hook Form + Zod - Add search, category, price, size, color, availability filters
- Connect filters to product store via
useFilterStore
- Create
useCartStorewith persistence via Zustandpersist - Implement
addToCart,updateQuantity,removeFromCart - Build
CartPagewith editable items - Add cart badge in
Header
- Create dynamic route
app/routes/products.$id.tsx - Fetch product by ID
- Display variants (size, color), image gallery, description
- Add βAdd to Cartβ button with variant selection
- Build
CheckoutPagewith contact form (RHF + Zod) - Validate name, email, address
- Show order summary
- On submit: show success modal, clear cart
- Configure
vite-plugin-pwato cache routes and API - Add an offline fallback page
- Test offline mode in DevTools
- Unit tests for Zustand stores (Vitest)
- Component tests (RTL):
ProductCard,Cart - E2E test: add to cart β checkout (Playwright)
- Lazy-load images (
loading="lazy") - Optimize re-renders (
React.memo,useCallback) - Add meta tags, favicon, PWA icons
- Lighthouse audit β fix accessibility/performance
Grzegorz Sroka - @gsroka89
Project Link: https://github.com/gsroka/languageshop