Conversation
✅ Deploy Preview for sleepy-chandrasekhar-717c3d ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Deploying woo with
|
| Latest commit: |
27c2575
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://cd103e5e.woo-ijf.pages.dev |
| Branch Preview URL: | https://feature-hooks.woo-ijf.pages.dev |
There was a problem hiding this comment.
Pull request overview
This PR introduces a comprehensive Location Hooks system to WooNuxt, providing WordPress-like extensibility for headless storefronts. The system allows developers to inject custom UI and logic at predefined extension points without overriding core components, making the codebase more maintainable and plugin-friendly.
Changes:
- Introduced a type-safe hooks system with 14 strategic extension points across the storefront
- Created reusable composable and component infrastructure for registering and rendering hooks
- Added example implementations demonstrating both component-based and render function approaches
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| woonuxt_base/app/composables/useHooks.ts | Core hook registry implementation with type-safe API for registering and retrieving hooks |
| woonuxt_base/app/components/HookOutlet.vue | Generic component that renders registered hooks with conditional logic and priority sorting |
| woonuxt_base/app/pages/product/[slug].vue | Added 5 hook outlets for product page extensibility (title, price, description, gallery, tabs) |
| woonuxt_base/app/pages/checkout.vue | Added 4 hook outlets for checkout flow extensibility (customer, shipping, payment, review) |
| woonuxt_base/app/components/shopElements/Cart.vue | Added 2 hook outlets for cart summary extensibility (before/after totals) |
| woonuxt_base/app/components/cartElements/CartCard.vue | Added 1 hook outlet after cart line item name |
| woonuxt_base/app/components/generalElements/AppHeader.vue | Added 2 hook outlets in header (before/after navigation) |
| woonuxt_base/app/components/generalElements/AppFooter.vue | Added 2 hook outlets in footer (top/bottom) |
| woonuxt_base/app/plugins/hooks-examples.ts | Example plugin demonstrating hook registration patterns with both component and render function approaches |
| woonuxt_base/app/components/examples/CartUpsell.vue | Example hook component showing free shipping threshold upsell |
| README.md | Documentation of the Location Hooks system with features, usage examples, and available hook locations |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } catch (error) { | ||
| return null; | ||
| } |
There was a problem hiding this comment.
Errors during hook rendering are silently caught and return null. While this prevents hooks from breaking the page, it makes debugging difficult. Consider logging errors in development mode so developers can identify and fix issues with their hook implementations.
| } catch (error) { | ||
| return false; |
There was a problem hiding this comment.
Errors during the when condition evaluation are silently caught and treated as false. This could hide bugs in conditional logic. Consider logging these errors in development mode to help developers identify issues with their conditional functions.
| /** Whether this outlet is required (warns in dev if no hooks registered) */ | ||
| required?: boolean; |
There was a problem hiding this comment.
The 'required' prop is defined in the Props interface with documentation stating it "warns in dev if no hooks registered", but this prop is never actually used in the component logic. Either implement the warning functionality or remove this unused prop to avoid confusion.
| }}</NuxtLink> | ||
|
|
||
| <!-- Hook: After cart line item name --> | ||
| <HookOutlet name="cart.lineItem.afterName" :ctx="{ item, cart: null }" as="span" /> |
There was a problem hiding this comment.
The cart property is passed as null in the hook context, which doesn't match the type definition in HookContextMap where 'cart.lineItem.afterName' expects { item: any; cart: any }. This could cause issues for hooks that need access to the full cart object. Consider either passing the actual cart object from the parent component or updating the type definition to reflect that cart may be null/optional for this hook location.
| const entries = hookRegistry.get(name) || []; | ||
|
|
||
| // Check for duplicate IDs | ||
| if (entries.some((entry) => entry.id === id)) { |
There was a problem hiding this comment.
When duplicate hook IDs are detected, the function silently returns without warning. This could make debugging difficult for developers who accidentally register the same hook ID multiple times. Consider adding a development-mode warning to help identify configuration issues early.
| if (entries.some((entry) => entry.id === id)) { | |
| const isDuplicate = entries.some((entry) => entry.id === id); | |
| if (isDuplicate) { | |
| if (process.env.NODE_ENV !== 'production') { | |
| console.warn( | |
| `[useHooks] Duplicate hook id "${id}" detected for hook "${name}".` + | |
| (source ? ` Source: ${source}.` : '') + | |
| ' This registration will be ignored.' | |
| ); | |
| } |
|
@copilot open a new pull request to apply changes based on the comments in this thread |
|
@scottyzen I've opened a new pull request, #357, to work on those changes. Once the pull request is ready, I'll request review from you. |
- Add dev mode logging for hook rendering errors (HookOutlet.vue:48-50) - Add dev mode logging for condition evaluation errors (HookOutlet.vue:33-34) - Implement 'required' prop functionality to warn when no hooks registered - Fix cart context type mismatch in CartCard.vue (pass actual cart object) - Add dev mode warning for duplicate hook IDs (useHooks.ts:107) Co-authored-by: scottyzen <5116925+scottyzen@users.noreply.github.com>
…or logging Co-authored-by: scottyzen <5116925+scottyzen@users.noreply.github.com>
Add developer debugging support to Location Hooks system
🪝 Location Hooks
This feature might look like nothing has changed — but under the hood, it unlocks a completely new level of extensibility.
WooNuxt now supports semantic hook locations across key parts of the storefront.
These allow UI and logic to be injected into predefined areas without overriding core components.
In practice, this means you can:
• Add trust badges without rewriting the product page
• Insert upsells into the cart without touching the core layout
• Extend checkout safely without forking templates
• Inject custom UI in a controlled, upgrade-safe way
Layers still handle full structural overrides.
Hooks handle additive extensions.
The result is a more maintainable, plugin-friendly architecture — designed for long-term growth.
Introduction of the Location Hooks System:
README.md, outlining its extensibility, SSR/SSG compatibility, and available hook locations.Core Implementation:
useHooks.tscomposable, defining hook types, registration/retrieval APIs, and context mapping for type safety and extensibility. This includesregisterHook,registerHooks, and the global registry.HookOutlet.vuecomponent that renders all registered hooks for a given location, supporting conditional rendering, priorities, and optional wrappers.Integration into Storefront Components:
HookOutletcomponents at key extension points in the UI, including: