Ordering Menu Carousel Design & Implementation Plan
- Onifade R. E. Colbert III

- May 5
- 5 min read
🍪 Ordering Menu Carousel — Design & Implementation Plan
This document outlines the full analysis, design decisions, and Velo (Wix Code) implementation for transforming the Onifade's Bakery ordering menu into an interactive, visually engaging carousel format.
📋 Step 1: Current Menu Layout Analysis
The site currently uses the Wix Restaurants Menus app with the following structure:
5 Active Menus: YUMMIES!!!, Wet Your Whistle (Drinks), Holiday Menu, Delivery & Pickup, Meet the Community Behind the Counter
YUMMIES!!! Menu — 6 Sections: COOKKIESSSS!!!! (15 items), Boogie Bites (4 items), Let Them Eat Cake!! (9 items), Bars on Bars on Bars (9 items), Who Wants Pie? (8 items), The Wonderful World of Cupcakes!! (2 items)
Current Layout: Standard vertical list/grid — items displayed in a static scrollable list per section
Pain Points: Long scroll required to browse all items; no visual hierarchy between featured and regular items; mobile experience requires excessive scrolling
🎨 Step 2: Carousel Interface Design
The carousel design transforms each menu section into a horizontally scrollable card carousel. Here are the design specifications:
Card Design (per item)
Card Size: 280px wide × 360px tall (desktop); 240px × 320px (mobile)
Image Area: Top 60% of card — full-width product photo with rounded top corners (12px radius)
Content Area: Bottom 40% — item name (bold, 18px), short description (2-line truncated, 14px gray), price badge (pink/rose accent, bottom-right)
CTA Button: 'Add to Order' button — full width, brand pink (#c837a6), white text, rounded corners
Hover Effect: Subtle lift shadow (box-shadow elevation) + slight scale(1.02) transform
Navigation Controls
Left/Right Arrow Buttons: Circular buttons (48px), semi-transparent white background, positioned at vertical center of carousel
Dot Indicators: Row of dots below carousel showing current position; active dot uses brand pink color
Touch/Swipe Support: Native swipe gestures on mobile devices
Auto-scroll: Optional 5-second auto-advance (pauses on hover/touch)
Section Tabs: Horizontal tab bar at top to jump between menu sections (COOKIES, BOOGIE BITES, CAKES, BARS, PIES, CUPCAKES)
Responsiveness
Desktop (1024px+): Shows 3 cards at a time
Tablet (768px–1023px): Shows 2 cards at a time
Mobile (< 768px): Shows 1.2 cards (peek of next card to indicate scrollability)
⚙️ Step 3: Velo (Wix Code) Implementation
To implement the carousel on your Wix site, follow these steps in the Wix Editor with Velo enabled:
A. Page Setup in Wix Editor
Open Wix Editor → Go to your Ordering/Menu page
Enable Velo: Click 'Dev Mode' in the top bar → Turn on Dev Mode
Add a Repeater element (ID: #menuCarousel) — this will serve as the carousel container
Inside the Repeater item template, add: Image (#itemImage), Text (#itemName), Text (#itemDescription), Text (#itemPrice), Button (#addToOrderBtn)
Add a HorizontalMenu or Tabs element (ID: #sectionTabs) above the carousel for section navigation
Add Previous/Next buttons (IDs: #prevBtn, #nextBtn) flanking the carousel
B. Velo Page Code (paste into Page Code editor)
// ============================================================
// Onifade's Bakery — Menu Carousel Implementation (Velo)
// ============================================================
import wixWindow from 'wix-window';
// --- Menu Data (fetched from Wix Restaurants API) ---
const MENU_SECTIONS = [
{ id: 'a1e247ea-0c57-498e-a9be-4044ed48bda8', label: '🍪 Cookies' },
{ id: 'be9330c1-c3c0-4f76-96cc-b69eac8d88da', label: '🎉 Boogie Bites' },
{ id: 'dab968ad-5aa1-487d-9de5-69bd80cdbc41', label: '🎂 Cakes' },
{ id: '5eee8a25-fb16-4489-811d-a4c15d6a5a91', label: '🍫 Bars' },
{ id: '9ea7135d-c232-437f-a9c3-33dd87265542', label: '🥧 Pies' },
{ id: '70f12b79-cd30-4750-91ab-1021a16cbbfa', label: '🧁 Cupcakes' }
];
let currentSectionIndex = 0;
let currentItemIndex = 0;
let allSectionItems = {}; // Cache: sectionId -> items[]
let autoScrollTimer = null;
$w.onReady(async function () {
// Build section tab labels
buildSectionTabs();
// Load first section
await loadSection(0);
// Wire navigation buttons
$w('#prevBtn').onClick(() => navigateCarousel(-1));
$w('#nextBtn').onClick(() => navigateCarousel(1));
// Start auto-scroll
startAutoScroll();
});
function buildSectionTabs() {
// Populate tab labels from MENU_SECTIONS
const tabItems = MENU_SECTIONS.map((s, i) => ({ label: s.label, value: String(i) }));
$w('#sectionTabs').options = tabItems;
$w('#sectionTabs').value = '0';
$w('#sectionTabs').onChange(async (event) => {
const idx = parseInt(event.target.value);
await loadSection(idx);
});
}
async function loadSection(sectionIndex) {
currentSectionIndex = sectionIndex;
currentItemIndex = 0;
const section = MENU_SECTIONS[sectionIndex];
// Use cached items if available
if (!allSectionItems[section.id]) {
$w('#loadingSpinner').show();
// Fetch items via Wix HTTP Functions (backend)
const result = await fetch(`/_functions/getMenuItems?sectionId=${section.id}`);
const data = await result.json();
allSectionItems[section.id] = data.items.filter(item => item.visible);
$w('#loadingSpinner').hide();
}
renderCarousel(allSectionItems[section.id]);
}
function renderCarousel(items) {
// Map items to Repeater data format
const repeaterData = items.map(item => ({
_id: item.id,
name: item.name,
description: item.description ? item.description.substring(0, 80) + '...' : '',
price: item.priceInfo ? item.priceInfo.formattedPrice : (item.priceVariants ? 'From ' + item.priceVariants.variants[0].priceInfo.formattedPrice : 'See options'),
imageUrl: item.image ? item.image.url : 'https://static.wixstatic.com/media/b0e7dd_9dee316920b04b73876bd37c86ff6da0~mv2.jpg'
}));
$w('#menuCarousel').data = repeaterData;
$w('#menuCarousel').onItemReady(($item, itemData) => {
$item('#itemImage').src = itemData.imageUrl;
$item('#itemName').text = itemData.name;
$item('#itemDescription').text = itemData.description;
$item('#itemPrice').text = itemData.price;
$item('#addToOrderBtn').onClick(() => {
// Navigate to the Wix Restaurants ordering page with item pre-selected
wixWindow.openLightbox('ItemDetailLightbox', { itemId: itemData._id });
});
});
updateDotIndicators(items.length);
}
function navigateCarousel(direction) {
const section = MENU_SECTIONS[currentSectionIndex];
const items = allSectionItems[section.id] || [];
const visibleCount = getVisibleCardCount();
const maxIndex = Math.max(0, items.length - visibleCount);
currentItemIndex = Math.min(Math.max(currentItemIndex + direction, 0), maxIndex);
// Scroll the repeater to show currentItemIndex
$w('#menuCarousel').scrollTo(currentItemIndex);
updateNavButtons(items.length, visibleCount);
resetAutoScroll();
}
function getVisibleCardCount() {
const width = wixWindow.formFactor === 'Mobile' ? 1 : (wixWindow.formFactor === 'Tablet' ? 2 : 3);
return width;
}
function updateNavButtons(totalItems, visibleCount) {
currentItemIndex === 0 ? $w('#prevBtn').disable() : $w('#prevBtn').enable();
currentItemIndex >= totalItems - visibleCount ? $w('#nextBtn').disable() : $w('#nextBtn').enable();
}
function updateDotIndicators(totalItems) {
// Update dot repeater to show correct number of dots
const dots = Array.from({length: totalItems}, (_, i) => ({ _id: String(i), active: i === currentItemIndex }));
$w('#dotIndicators').data = dots;
$w('#dotIndicators').onItemReady(($item, dotData) => {
$item('#dot').style.backgroundColor = dotData.active ? '#c837a6' : '#ddd';
});
}
function startAutoScroll() {
autoScrollTimer = setInterval(() => navigateCarousel(1), 5000);
}
function resetAutoScroll() {
clearInterval(autoScrollTimer);
startAutoScroll();
}
C. Backend HTTP Function (http-functions.js)
Create a file at backend/http-functions.js with the following code to securely proxy the Wix Restaurants API:
import { ok, badRequest } from 'wix-http-functions';
import { fetch } from 'wix-fetch';
export async function get_getMenuItems(request) {
const sectionId = request.query.sectionId;
if (!sectionId) return badRequest({ body: JSON.stringify({ error: 'Missing sectionId' }) });
// Query sections to get itemIds
const sectionRes = await fetch(`https://www.wixapis.com/restaurants/menus-section/v1/sections/query`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query: { filter: { id: { '$eq': sectionId } } } })
});
const sectionData = await sectionRes.json();
const itemIds = sectionData.sections[0]?.itemIds || [];
// Fetch items by IDs
const params = itemIds.map(id => `itemIds=${id}`).join('&');
const itemsRes = await fetch(`https://www.wixapis.com/restaurants/menus-item/v1/items?${params}&onlyVisible=true`, {
headers: { 'Content-Type': 'application/json' }
});
const itemsData = await itemsRes.json();
return ok({ body: JSON.stringify({ items: itemsData.items || [] }) });
}
📱 Step 4: Responsiveness Testing Checklist
Desktop Chrome/Firefox/Safari: 3-card view, arrow navigation, dot indicators
iPad/Tablet: 2-card view, touch swipe works
iPhone/Android: 1.2-card peek view, swipe navigation, auto-scroll pauses on touch
Section tabs: All 6 sections load correctly with proper item counts
Images: All product images load from Wix CDN (wixstatic.com)
Prices: Correctly shows single price or 'From $X.XX' for variant-priced items
Add to Order button: Opens item detail lightbox or navigates to ordering flow
📊 Menu Summary (Current Data)
COOKKIESSSS!!!! — 15 items (13 visible): Chocolate Chip, Butter, Snickerdoodle, Pecan Sandies, Salted Caramel, Peanut Butter, PB Chocolate, Macadamia White Choc, Oatmeal, S'mores, Cinnamon Roll, Fudge Mint, Stuffed Red Velvet
Boogie Bites — 4 items
Let Them Eat Cake!! — 9 items
Bars on Bars on Bars — 9 items
Who Wants Pie? — 8 items
The Wonderful World of Cupcakes!! — 2 items
This content was generated by AI.




Comments