@xenterprises/nuxt-x-restaurants
v0.9.0
Published
Nuxt layer for building restaurant directory websites with listing, search, filtering, and detailed profile pages.
Readme
@xenterprises/nuxt-x-restaurants
Nuxt layer for building restaurant directory websites with listing, search, filtering, and detailed profile pages.
📖 Full documentation: Docus site · CHANGELOG · v0.8.0 release notes
What's new in v0.8.0
A major Yelp-class update — 27 new components, 8 composables, 4 new page types. Highlights:
- Open Now badge + filter (live "open now / closed" on every card)
- Map / List / Grid view modes on
/restaurants - Distance from user with geolocation
- Vibe filter (Good For / Atmosphere / Noise — 12 standardized ids)
- Hours graph (visual weekly bar chart, today highlighted, current-time dot)
- Similar restaurants + Popular in your area sections
- Owner responses in reviews
- "Mentioned by reviewers" tags (auto-extracted via word-frequency)
- Cuisine + neighborhood landing pages with
ItemListschema for SEO - Cover photo carousel on profile hero
- Index pages, loading skeletons, error states, dynamic sitemap
No breaking changes. See CHANGELOG.md for the full list.
Quick Start (5 minutes)
Get a working restaurant directory with search, filters, and detail pages in five minutes:
# 1. Install
npm install @xenterprises/nuxt-x-restaurants// 2. nuxt.config.ts — extend the layer
export default defineNuxtConfig({
extends: ['@xenterprises/nuxt-x-restaurants'],
runtimeConfig: {
public: {
apiEndpoint: process.env.NUXT_PUBLIC_API_ENDPOINT, // e.g. https://api.yoursite.com
},
},
})# 3. .env — point at your API
NUXT_PUBLIC_API_ENDPOINT=https://api.yoursite.com// 4. app.config.ts — brand it
export default defineAppConfig({
xRestaurants: {
name: 'My Restaurant Directory',
domain: 'mysite.com',
logo: '/logos/my-logo.webp',
},
})<!-- 5. app/app.vue — mount -->
<template>
<UApp>
<NuxtLayout><NuxtPage /></NuxtLayout>
</UApp>
</template>That's it — your directory is live at /, /restaurants, and /restaurants/:slug. Override defaults in app.config.ts to customize the homepage, filters, menu card, and brand.
Running Without an API (Mock Mode)
Want to demo or develop the UI before your API is ready? The bundled playground uses mock data:
git clone https://gitlab.com/x-enterprises/xlayers/nuxt-x-restaurants.git
cd nuxt-x-restaurants
npm install
npm run dev # → http://localhost:3000 (mock data)The playground reads from .playground/content/articles/data/restaurants.ts and renders the full UI without any API calls. Useful for design iteration.
Installation
npm install @xenterprises/nuxt-x-restaurantsAdd to your nuxt.config.ts:
export default defineNuxtConfig({
extends: ['@xenterprises/nuxt-x-restaurants'],
})Minimal Usage
<template>
<UApp>
<NuxtLoadingIndicator />
<NuxtLayout>
<NuxtPage />
</NuxtLayout>
</UApp>
</template>The layer provides pages, components, composables, and a default layout out of the box. Once extended, the restaurant directory is available at /, /restaurants, /restaurants/:slug, and more.
Components
All components use the XRD prefix and are auto-imported.
Layout
| Component | Description |
|-----------|-------------|
| XRDNavbar | Site navigation with configurable links from app.config.ts |
| XRDFooter | Footer with brand name from app.config.ts, quick links, newsletter signup |
Homepage (13 components)
| Component | Description |
|-----------|-------------|
| XRDHomePageHero | Hero with background image, search form for cuisine/location |
| XRDHomePageFeaturedRestaurants | Featured restaurant cards with "View All" link |
| XRDHomePageNewRestaurants | Recently added restaurants |
| XRDHomePagePopularThisWeek | Trending restaurants this week |
| XRDHomePageSpecialOffers | Promotions and deals |
| XRDHomePageLatestStories | Blog/article integration (Nuxt Content) |
| XRDHomePageLocalDiningGuide | Location-based recommendations |
| XRDHomePageShowcase | Restaurant showcase grid |
| XRDHomePageGrid | General grid layout |
| XRDHomePageStats | Directory statistics (restaurant count, cities, etc.) |
| XRDHomePageTestimonials | User testimonials carousel |
| XRDHomePageFAQ | Frequently asked questions accordion |
| XRDHomePageFeatures | Feature highlights |
Filters (9 components)
| Component | Description |
|-----------|-------------|
| XRDFilters | Main filter container with mobile drawer support |
| XRDFiltersAsideFilters | Sidebar filter panel |
| XRDFiltersActiveFilters | Active filter pills with clear buttons |
| XRDFiltersCuisineFilter | Cuisine type checkbox filter |
| XRDFiltersPriceFilter | Price level filter ($ to $$$$) |
| XRDFiltersRatingFilter | Star rating minimum filter |
| XRDFiltersLocationFilter | Neighborhood/location filter |
| XRDFiltersAmenitiesFilter | Amenities checkbox filter |
| XRDFiltersDietaryFilter | Dietary options filter |
Restaurant Profile (22 components)
| Component | Description |
|-----------|-------------|
| XRDProfileHero | Profile hero with cover image and rating |
| XRDProfileCard | Restaurant summary card for listing pages |
| XRDProfileBreadcrumb | Navigation breadcrumb |
| XRDProfileNavigation | Tab navigation (Home, Menu, Reviews, Photos, Articles) |
| XRDProfileAbout | About section with description |
| XRDProfileDescription | Full description display |
| XRDProfileContact | Contact information card |
| XRDProfileContactInfo | Contact details (phone, email, website) |
| XRDProfileHours | Operating hours table |
| XRDProfileMap | Location map display |
| XRDProfileCuisine | Cuisine type tags |
| XRDProfileDietary | Dietary options display |
| XRDProfileAmenities | Amenities list with icons |
| XRDProfileMenuSection | Menu category section with items |
| XRDProfileMenuItem | Individual menu item display |
| XRDProfileReviews | Reviews section |
| XRDProfileReviewsItem | Single review with rating and comment |
| XRDProfileSidebar | Profile sidebar (hours, contact, map) |
| XRDProfileSocial | Social media links |
| XRDProfileFAQ | Restaurant FAQ accordion |
| XRDProfilePromotions | Special offers display |
| XRDProfileNewsletter | Newsletter signup form |
Utility Components
| Component | Description |
|-----------|-------------|
| XRDStarRating | Star rating display with half-star support |
| XRDMenuCard | Menu item card with default, compact, and horizontal variants |
Composables
| Composable | Description |
|------------|-------------|
| useDomain() | API endpoint management. Returns methods: getInfo(), getRestaurants(), getRestaurantBySlug(), getRestaurantMenuBySlug(), getRestaurantReviewsBySlug(), getRestaurantPhotosBySlug(), getRestaurantsSearch(), getRestaurantsFeatured(), getRestaurantsNew(), getRestaurantsRandom(), getRestaurantsTopRated(), getSitemap(), and more. |
| useRestaurantFilters() | Filter state management with URL sync. Provides filteredRestaurants, toggle methods for cuisine/location/price/amenity/dietary/rating, clearAllFilters(), hasActiveFilters, activeFilterCount. |
| useFilters() | Generic filter logic with built-in handlers for search, category, dietary, and sort. Supports custom filter handler registration. |
| useMenuCard() | Menu card configuration from app.config.ts. Returns config, getDietaryTag(), getItemTags(), formatPrice(). |
| useRestaurant(slug) | Individual restaurant data fetching. Returns getRestaurant(), getRestaurantSchema(), getRestaurantReviews(), getRestaurantFAQs(), getRestaurantMenu(), getRestaurantPhotos(). |
Pages
The layer provides these routes:
| Route | Description |
|-------|-------------|
| / | Homepage with hero, featured, popular, stories, FAQ |
| /restaurants | Restaurant listing with sidebar filters and pagination |
| /restaurants/:slug | Restaurant profile layout (provides data to child pages) |
| /restaurants/:slug/ | Profile overview (about, promotions, FAQ, contact) |
| /restaurants/:slug/menu | Restaurant menu with dietary accommodations |
| /restaurants/:slug/reviews | Reviews with load-more pagination |
| /restaurants/:slug/photos | Photo gallery with lightbox |
| /restaurants/:slug/articles | Related articles |
| /articles | Blog/articles listing |
| /articles/:slug | Article detail |
| /features | Features listing |
| /features/:slug | Feature detail |
| /popular | Popular restaurants |
| /popular/:slug | Popular restaurant detail |
| /explore | Explore page |
| /about | About page |
| /list-restaurant | Submit a restaurant form |
Configuration
app.config.ts
export default defineAppConfig({
xRestaurants: {
name: 'My Restaurant Directory', // Brand name (used in footer, navbar)
domain: 'mysite.com', // Domain for API calls
logo: '/logos/my-logo.webp', // Logo path
navbar: {
links: [ // Navigation links
{ label: 'Explore', to: '/restaurants' },
{ label: 'Articles', to: '/articles' },
],
},
homePage: {
hero: {
title: 'Find the Best Dining',
description: 'Explore top-rated restaurants...',
backgroundImage: 'https://...',
searchButtonLabel: 'Search',
cuisinePlaceholder: 'Cuisine',
locationPlaceholder: 'Neighborhood',
},
featured: {
title: 'Featured Places',
description: 'Hand-picked selections.',
viewAllLink: '/restaurants',
viewAllLabel: 'View All',
},
// latestStories, popular, localGuide, faq - all configurable
},
menuCard: {
showImage: true,
showDescription: true,
showTags: true,
showSpiceLevel: false,
showCalories: false,
showPrepTime: false,
imageAspect: 'video', // 'square' | 'video' | 'wide'
variant: 'default', // 'default' | 'compact' | 'horizontal'
dietaryTags: [ // Custom dietary tag definitions
{ id: 'vegetarian', label: 'Vegetarian', icon: 'i-heroicons-leaf', color: 'green' },
],
},
filters: {
title: 'Filters',
showClearAll: true,
mobileBreakpoint: 'lg',
},
},
})nuxt.config.ts
The layer configures these runtime settings:
runtimeConfig: {
public: {
apiEndpoint: '', // Base URL for restaurant API
siteUrl: '', // Public site URL
siteName: '', // Site name
},
},
site: {
url: '', // For @nuxtjs/seo
name: '',
description: '',
defaultLocale: 'en',
},Environment Variables
| Variable | Required | Description |
|----------|----------|-------------|
| NUXT_PUBLIC_API_ENDPOINT | Yes | Base URL for the restaurant API (e.g., https://api.example.com) |
| NUXT_PUBLIC_SITE_URL | No | Public site URL for meta tags |
| NUXT_PUBLIC_SITE_NAME | No | Site name for meta tags |
| NUXT_SITE_URL | No | Site URL for @nuxtjs/seo module |
| NUXT_SITE_NAME | No | Site name for @nuxtjs/seo module |
How It Works
This layer extends @xenterprises/nuxt-x-marketing for shared marketing components, then adds restaurant-specific functionality:
API Integration:
useDomain()builds API URLs fromruntimeConfig.public.apiEndpoint+ the domain configured inapp.config.ts. All restaurant data (listings, menus, reviews, photos) is fetched from this API.Client-Side Filtering:
useRestaurantFilters()manages filter state viauseState(SSR-safe) with URL query parameter sync. It filters therestaurantsmock data array for the listing page. Filters are applied as AND across groups, OR within groups (except dietary which is AND).Profile Pages: The
restaurants/[slug].vuelayout fetches restaurant data once viauseAsyncDataand provides it to child pages via Vue'sprovide/inject, avoiding duplicate API calls for menu, reviews, and photos sub-pages.Content Integration: Articles and features use Nuxt Content v3 with markdown files in
content/articles/andcontent/features/.Components: All 48+ components are in
app/components/X/RD/and auto-imported by Nuxt. They follow the XRD prefix convention and use Nuxt UI v4 primitives.
Layer Architecture
nuxt.config.ts- Extends nuxt-x-marketing, registers modules (@nuxt/ui, @nuxt/content, @nuxtjs/seo, nuxt-easy-lightbox), sets runtime configapp.config.ts- UI theme (colors, component defaults), xRestaurants config (brand, navbar, homepage, menu card, filters), xMarketing config (header, footer)app/composables/- 5 composables for domain API, filtering, menu cards, and restaurant dataapp/components/X/RD/- 48+ auto-imported components organized in HomePage/, Filters/, Profile/ subdirectoriesapp/pages/- 19 page routes for homepage, listings, profiles, articles, featuresapp/types/- TypeScript interfaces for Restaurant, MenuItem, Filters, etc.app/data/restaurants.ts- Mock restaurant data for local development/demoapp/layouts/default.vue- Default layout with Navbar and Footerapp/assets/css/main.css- Custom CSS styles
Dependencies
| Package | Version | Purpose |
|---------|---------|---------|
| @nuxt/content | ^3.9.0 | Content management for articles/features |
| @nuxt/ui | ^4.2.1 | UI component library |
| @nuxtjs/seo | ^3.3.0 | SEO meta tags, sitemap, robots |
| @xenterprises/nuxt-x-marketing | ^1.0.1 | Shared marketing components |
| better-sqlite3 | ^12.5.0 | Required by @nuxt/content |
| nuxt-easy-lightbox | ^1.1.0 | Photo gallery lightbox |
Development
# Install dependencies
npm install
# Start playground dev server
npm run dev
# Build playground
npm run build
# Run tests
npx vitest runLicense
UNLICENSED
