# Enable Shopify Menus

> Replace the hardcoded nav and footer menus with Shopify-powered menus.

- Skill: `vercel/enable-shopify-menus` (Agent Skill)
- Install (CLI): `npx skillmds@latest add vercel/enable-shopify-menus`
- Raw SKILL.md: https://api.skillmd.com/api/skills/vercel/enable-shopify-menus/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: vercel (https://skillmd.com/u/vercel)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/vercel/enable-shopify-menus

---


# Enable Shopify Menus

By default, the storefront's nav and footer render hardcoded fallback items: an inline `const items: MenuItem[] = [...]` in `Nav` (`components/nav/index.tsx`) and an empty `const items: MenuItem[] = []` in `Footer` (`components/footer/index.tsx`). The components themselves (`QuickLinks`, `MobileMenu`, `Footer`'s `FooterMenu`) already consume `MenuItem[]` in Shopify shape and render up to three levels of nesting. This skill swaps that inline default to a live Shopify menu fetched by handle, keeping the inline items as the fallback if the menu is missing or empty.

## Before you start

Ask the user two questions in order:

### 1. Which menus do you want to fetch from Shopify?

- **Nav menu** — replaces the hardcoded items used by the desktop quick links and mobile sheet.
- **Footer menu** — replaces the hardcoded footer columns.
- **Both**

### 2. What are the Shopify menu handles?

Ask for each selected menu. Defaults: `main-menu` for nav, `footer` for footer.

Wait for the user to answer before proceeding.

---

## Part A: Enable Shopify nav menu

Skip this section if the user did not select the nav menu.

Edit `components/nav/index.tsx`. Change the signature to `export async function Nav()` (preserving any existing props in a customized storefront), add the `getMenu` import, and swap the data source:

```tsx
import { getMenu } from "@/lib/shopify/operations/menu/server";
```

Inside `Nav`, keep the existing inline default and swap the data source so the Shopify menu takes precedence:

```tsx
const defaultItems: MenuItem[] = [
  { id: "default-nav-shop", title: "Shop", url: "/collections/all", type: "HTTP", items: [] },
];
const menu = await getMenu({ handle: "NAV_HANDLE" });
const items = menu?.items ?? defaultItems;
```

Replace `"NAV_HANDLE"` with the handle the user provided. `QuickLinks` and `MobileMenu` already accept `MenuItem[]`, so no other component changes are needed. Keep the inline default as the fallback.

---

## Part B: Enable Shopify footer menu

Skip this section if the user did not select the footer menu.

Edit `components/footer/index.tsx`. Make the component async, add the `getMenu` import, and swap the data source:

```tsx
import { getMenu } from "@/lib/shopify/operations/menu/server";
```

Change the signature to `async` and replace `const items: MenuItem[] = [];` with:

```tsx
const menu = await getMenu({ handle: "FOOTER_HANDLE" });
const items = menu?.items ?? [];
```

Replace `"FOOTER_HANDLE"` with the handle the user provided. `FooterMenu` already accepts `MenuItem[]`. The footer's default is empty (no columns), so falling back to `[]` simply hides the section when the Shopify menu is missing or empty.

Inspect the `Footer` callsite and `getMenu` operation instead of assuming a locale prop exists. The default uses explicit `shopConfig.localization` commerce settings and inline component copy; no `getLocale()` helper is needed. In an already localized or Markets-enabled store, preserve and pass its validated commerce context through menu operations and cache inputs. Keep existing cache directives and Suspense boundaries; do not change rendering policy just to enable a menu.

---

## Guardrails

- New fallback labels belong alongside the consuming domain component; preserve catalogs and translated fallbacks in an already localized installation. Shopify menu translations and storefront fallback copy are separate.
- The `getMenu()` operation in `lib/shopify/operations/menu/server.ts` already handles caching (`"use cache: remote"`, `cacheTag("menus")`) and URL transformation. Do not duplicate that logic.
- Always preserve the inline fallback so a missing or empty Shopify menu doesn't leave the user with a blank nav or footer.
- External links (URLs starting with `http`) are handled by the existing `MenuLink` helpers in each component — no change needed.

