Skip to content

🪝 Location Hooks#354

Open
scottyzen wants to merge 5 commits intomasterfrom
feature/hooks
Open

🪝 Location Hooks#354
scottyzen wants to merge 5 commits intomasterfrom
feature/hooks

Conversation

@scottyzen
Copy link
Copy Markdown
Owner

🪝 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:

  • Added a comprehensive "Location Hooks" system, including a detailed overview and usage guide to the README.md, outlining its extensibility, SSR/SSG compatibility, and available hook locations.

Core Implementation:

  • Created useHooks.ts composable, defining hook types, registration/retrieval APIs, and context mapping for type safety and extensibility. This includes registerHook, registerHooks, and the global registry.
  • Added a generic HookOutlet.vue component that renders all registered hooks for a given location, supporting conditional rendering, priorities, and optional wrappers.

Integration into Storefront Components:

@netlify
Copy link
Copy Markdown

netlify bot commented Feb 16, 2026

Deploy Preview for sleepy-chandrasekhar-717c3d ready!

Name Link
🔨 Latest commit 27c2575
🔍 Latest deploy log https://app.netlify.com/projects/sleepy-chandrasekhar-717c3d/deploys/6993b48da08290000837a47a
😎 Deploy Preview https://deploy-preview-354--sleepy-chandrasekhar-717c3d.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages bot commented Feb 16, 2026

Deploying woo with  Cloudflare Pages  Cloudflare Pages

Latest commit: 27c2575
Status: ✅  Deploy successful!
Preview URL: https://cd103e5e.woo-ijf.pages.dev
Branch Preview URL: https://feature-hooks.woo-ijf.pages.dev

View logs

@scottyzen scottyzen marked this pull request as ready for review February 16, 2026 22:42
@scottyzen scottyzen requested a review from Copilot February 16, 2026 23:42
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +48 to +50
} catch (error) {
return null;
}
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +33 to +34
} catch (error) {
return false;
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +12 to +13
/** Whether this outlet is required (warns in dev if no hooks registered) */
required?: boolean;
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
}}</NuxtLink>

<!-- Hook: After cart line item name -->
<HookOutlet name="cart.lineItem.afterName" :ctx="{ item, cart: null }" as="span" />
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
const entries = hookRegistry.get(name) || [];

// Check for duplicate IDs
if (entries.some((entry) => entry.id === id)) {
Copy link

Copilot AI Feb 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
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 uses AI. Check for mistakes.
@scottyzen
Copy link
Copy Markdown
Owner Author

@copilot open a new pull request to apply changes based on the comments in this thread

Copy link
Copy Markdown

Copilot AI commented Feb 16, 2026

@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.

Copilot AI and others added 3 commits February 16, 2026 23:51
- 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants