## Three Issues Fixed ✅ ### 1. Backend hit on every keypress ❌ **Problem:** - Type "Bandung" → 7 API calls (B, Ba, Ban, Band, Bandu, Bandun, Bandung) - Expensive for live rate APIs (Rajaongkir, UPS) - Poor UX with constant loading **Solution - Debouncing:** ```ts const [debouncedCity, setDebouncedCity] = useState(city); useEffect(() => { const timer = setTimeout(() => { setDebouncedCity(city); }, 500); // Wait 500ms after user stops typing return () => clearTimeout(timer); }, [city]); // Use debouncedCity in query key queryKey: [..., debouncedCity] ``` **Result:** - Type "Bandung" → Wait 500ms → 1 API call ✅ - Much better UX and performance --- ### 2. Same rates for different provinces ❌ **Problem:** - Select "Jawa Barat" → JNE REG Rp31,000 - Select "Bali" → JNE REG Rp31,000 (wrong!) - Should be different rates **Root Cause:** ```ts staleTime: 5 * 60 * 1000 // Cache for 5 minutes ``` React Query was caching too aggressively. Even though query key changed (different state), it was returning cached data. **Solution:** ```ts gcTime: 0, // Don't cache in memory staleTime: 0, // Always refetch when key changes ``` **Result:** - Select "Jawa Barat" → Fetch → JNE REG Rp31,000 - Select "Bali" → Fetch → JNE REG Rp45,000 ✅ - Correct rates for each province --- ### 3. No Rajaongkir API hits ❌ **Problem:** - Check Rajaongkir dashboard → No new API calls - Rates never actually calculated - Using stale cached data **Root Cause:** Same as #2 - aggressive caching prevented real API calls **Solution:** Disabled caching completely for shipping calculations: ```ts gcTime: 0, // No garbage collection time staleTime: 0, // No stale time ``` **Result:** - Change province → Real Rajaongkir API call ✅ - Fresh rates every time ✅ - Dashboard shows API usage ✅ --- ## How It Works Now: ### User Types City: ``` 1. Type "B" → Timer starts (500ms) 2. Type "a" → Timer resets (500ms) 3. Type "n" → Timer resets (500ms) 4. Type "dung" → Timer resets (500ms) 5. Stop typing → Wait 500ms 6. ✅ API call with "Bandung" ``` ### User Changes Province: ``` 1. Select "Jawa Barat" 2. Query key changes 3. ✅ Fetch fresh rates (no cache) 4. ✅ Rajaongkir API called 5. Returns: JNE REG Rp31,000 6. Select "Bali" 7. Query key changes 8. ✅ Fetch fresh rates (no cache) 9. ✅ Rajaongkir API called again 10. Returns: JNE REG Rp45,000 (different!) ``` ## Benefits: - ✅ No more keypress spam - ✅ Correct rates per province - ✅ Real API calls to Rajaongkir - ✅ Fresh data always - ✅ Better UX with 500ms debounce
WooNooW
WooNooW is a modern experience layer for WooCommerce — enhancing UX, speed, and reliability without data migration.
It keeps WooCommerce as the core engine while providing a modern React-powered interface for both the storefront (cart, checkout, my‑account) and the admin (orders, dashboard).
Three Admin Modes:
- Normal Mode: Traditional wp-admin integration (
/wp-admin/admin.php?page=woonoow) - Fullscreen Mode: Distraction-free interface (toggle in header)
- Standalone Mode: Complete standalone app at
yoursite.com/adminwith custom login ✨
🔍 Background
WooCommerce is the most used e‑commerce engine in the world, but its architecture has become heavy and fragmented.
With React‑based blocks (Checkout, Cart, Product Edit) and HPOS now rolling out, many existing addons are becoming obsolete or unstable.
WooNooW bridges the gap between Woo’s legacy PHP system and the new modern stack — so users get performance and simplicity without losing compatibility.
🚀 Key Principles
- No Migration Needed – Woo data stays intact.
- Safe Activate/Deactivate – revert to native Woo anytime, no data loss.
- Hybrid by Default – SSR + React islands for Cart/Checkout/My‑Account.
- Full SPA Toggle – optional React‑only mode for max performance.
- HPOS Mandatory – optimized datastore and async operations.
- Compat Layer – hook mirror + slot rendering for legacy addons.
- Async Mail & Tasks – powered by Action Scheduler.
🧱 Tech Stack
| Layer | Technology |
|---|---|
| Backend | PHP 8.2+, WordPress, WooCommerce (HPOS), Action Scheduler |
| Frontend | React 18 + TypeScript, Vite, React Query, Tailwind (optional) |
| Build & Package | Composer, NPM, ESM scripts, Zip automation |
| Architecture | Modular PSR‑4 classes, REST‑driven SPA islands |
🧩 Project Structure
woonoow/
├── admin-spa/
│ ├── src/
│ │ ├── components/
│ │ │ ├── filters/
│ │ │ │ ├── DateRange.tsx
│ │ │ │ └── OrderBy.tsx
│ │ │ └── CommandPalette.tsx
│ │ ├── hooks/
│ │ │ └── useShortcuts.tsx
│ │ ├── lib/
│ │ │ ├── api.ts
│ │ │ ├── currency.ts
│ │ │ ├── dates.ts
│ │ │ ├── query-params.ts
│ │ │ ├── useCommandStore.ts
│ │ │ └── utils.ts
│ │ ├── pages/
│ │ │ └── orders/
│ │ │ ├── partials
│ │ │ │ └── OrderForm.tsx
│ │ │ ├── Orders.tsx
│ │ │ ├── OrdersNew.tsx
│ │ │ └── OrderShow.tsx
│ │ ├── routes/
│ │ │ └── Dashboard.tsx
│ │ ├── types/
│ │ │ └── qrcode.d.ts
│ │ ├── App.tsx
│ │ ├── index.css
│ │ └── main.tsx
│ └── vite.config.ts
├── includes/
│ ├── Admin/
│ │ ├── Assets.php
│ │ └── Menu.php
│ ├── Api/
│ │ ├── CheckoutController.php
│ │ ├── OrdersController.php
│ │ ├── Permissions.php
│ │ └── Routes.php
│ ├── Compat/
│ │ ├── HideWooMenus.php
│ │ └── HooksShim.php
│ └── Core/
│ ├── DataStores/
│ │ ├── OrderStore_HPOS.php
│ │ └── OrderStore.php
│ ├── Mail/
│ │ ├── MailQueue.php
│ │ └── WooEmailOverride.php
│ ├── Bootstrap.php
│ └── Features.php
├── woonoow.php
└── docs (project notes, SOP, etc.)
⚙️ Development Workflow
- LocalWP / Docker setup with WordPress + WooCommerce.
- Activate plugin:
WooNooWshould appear in the admin menu. - Build SPAs:
npm run build - Package zip:
npm run pack - Upload
dist/woonoow.zipinto WordPress → Plugins → Add New → Upload.
🧭 Vision
“WooCommerce, reimagined for now.”
WooNooW delivers modern speed and UX while keeping WooCommerce’s ecosystem alive.
No migration. No lock‑in. Just Woo, evolved.