ATX Resto Menu
Wordpress Restaurant menu plugin
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/siko001/atx-resto-menu/archive/refs/heads/main.zipDeclares an update source (https://github.com/siko001/atx-resto-menu), so updates arrive through the plugin's own updater.
Readme
ATX Resto Menu
An extensible WordPress restaurant-menu engine built on ACF PRO. It supports either one large menu containing every section or multiple focused menus such as Food, Wine, Cocktails, Morning, Lunch, and Evening.
Requirements and installation
- WordPress 6.2+
- PHP 8.1+
- ACF PRO (required and deliberately not bundled)
Activate ACF PRO first, then activate this plugin. Open Restaurant Menus → Settings & Allergens to set currency, image behavior, and the shared allergen library. Add one or more entries under Restaurant Menus and publish them. Use the Restaurant Menu block to select one or several menus.
For ready-made examples, click Seed demo menus on the Restaurant Menus index. The secure, idempotent action creates three published menus: a comprehensive standard menu, a three-course set menu, and a sharing menu. Running it again leaves existing demos unchanged.
From WP-CLI, seed all three demonstration menus:
wp atx seed menu
The command is idempotent. Use wp atx seed menu --force to refresh all generated demos, or wp atx seed menu --key=set-menu to seed only zest-style, set-menu, or sharing. The portable source data lives in fixtures/menus.json; atxRestoMenu/demo_fixture_file can point the seeder at another JSON fixture file without modifying the plugin.
The visual builder previews unsaved names, descriptions, allergens, prices, and newly appended rows while you type. Use Preview menu in the Menu navigator to open the full menu in a large, keyboard-accessible overlay; close it with the button, backdrop, or Escape. Sections, items, and variations use ACF's native drag-and-drop ordering.
Large menus also get a docked Menu navigator in WordPress's right-hand meta-box column, leaving the main builder at full width. It begins as a normal meta box and remains fixed to the viewport after scrolling beyond it, even after the other sidebar boxes end. Its section buttons jump directly to a section; search filters the builder live across section titles, item names, descriptions, and variations; matching rows expand automatically. Expand all, Collapse all, and Clear do not alter the saved order or menu data.
Use Duplicate on the Restaurant Menus index to copy a complete menu. The copy includes its ACF fields, images, allergens, service periods, and collections; it is created as a draft and opened for editing.
Menus are private data containers and do not create public single pages. Sections and items are ordered with ACF repeaters. A menu can be classified with any number of Service periods (for example morning or evening) and hierarchical Menu collections (for example food or drinks/wine).
Data model
Each menu contains a description and ordered sections. Each section has a title, description, and ordered items. Items support a simple price for the common case, plus optional labelled prices/portions, image, shared allergens, and variations. Technical section/item IDs are generated automatically from their titles and are not shown to editors.
The Menu format can be Standard, Set, or Sharing. Set and sharing menus reveal a minimum-guests field and repeatable menu-level price packages, so one menu can offer Three courses — €42 per person and With wine pairing — €60 per person. Each course/section can include all listed dishes or require the guest to choose a defined number. Multiple price points should remain packages on one menu; genuinely different menus remain separate Menu posts and can be selected together in the block or API.
Variation pricing has three modes:
- Same prices inherits all prices from the parent item.
- Adjust prices adds or subtracts one amount from every parent price. If 2 pieces costs €5 and 3 pieces costs €8, an adjustment of
1resolves to €6 and €9. - Custom prices defines an independent labelled price list for that variation.
Every variation returned by the full REST API includes resolved_prices, so consumers can render the final values directly. Variations may also override image, description, and allergens; empty variation allergens inherit from the parent item.
When an item has variations, the item remains the main heading and its shared prices are rendered beneath each variation rather than as an extra unnamed choice. For example, Tacos is the item while Pork, Chicken, and Beef are sibling variations. When an item has no variations, its prices render directly beneath the item.
REST API
All routes are read-only and return published menus only.
GET /wp-json/atx-resto-menu/v1/menus
GET /wp-json/atx-resto-menu/v1/menus?include=12,34&full=true
GET /wp-json/atx-resto-menu/v1/menus?service=evening&full=true
GET /wp-json/atx-resto-menu/v1/menus?collection=wine&full=true
GET /wp-json/atx-resto-menu/v1/menus/batch?ids=12,34
GET /wp-json/atx-resto-menu/v1/menus/12/menu
GET /wp-json/atx-resto-menu/v1/menus/12/sections
GET /wp-json/atx-resto-menu/v1/menus/12/sections/starters
GET /wp-json/atx-resto-menu/v1/menus/12/sections/starters/render
GET /wp-json/atx-resto-menu/v1/menus/12/items
GET /wp-json/atx-resto-menu/v1/menus/12/allergens
Use include when order matters: results preserve the requested ID order. full=true expands every selected menu. The batch route is a concise equivalent for fetching two or more complete menus.
The /render section route returns { id, title, html }. It is used by the interactive block layout and is also available to custom front ends that want server-rendered, escaped item markup. Optional currency_symbol and currency_position=before|after query parameters keep per-block currency overrides consistent when a tab loads another section.
Safe per-site extensions
Do not edit this plugin for a client. Put extensions in the child theme or a small site plugin. All public hooks intentionally use the atxRestoMenu/ prefix.
This example adds a global text-colour option and exposes it through every menu API response:
add_filter('atxRestoMenu/acf/settings_fields', function (array $fields): array {
$fields[] = [
'key' => 'field_my_site_menu_text_color',
'label' => 'Menu text colour',
'name' => 'my_site_menu_text_color',
'type' => 'color_picker',
'default_value' => '#222222',
];
return $fields;
});
add_filter('atxRestoMenu/settings_data', function (array $settings): array {
$settings['text_color'] = sanitize_hex_color(
(string) get_field('my_site_menu_text_color', 'option')
) ?: '#222222';
return $settings;
});
add_filter('atxRestoMenu/style_variables', function (array $variables, array $menu): array {
$variables['text-color'] = $menu['settings']['text_color'];
return $variables;
}, 10, 2);
For menu-specific custom data, append a field with atxRestoMenu/acf/menu_fields, then add its normalized value with atxRestoMenu/menu_data. Other extension points are:
atxRestoMenu/admin_capability— capability required to edit global settings.atxRestoMenu/acf/block_fields— append per-block ACF controls without editing the plugin.atxRestoMenu/block_category— block category slug; defaults towidgets.atxRestoMenu/menu_data— normalized full-menu data before REST/rendering.atxRestoMenu/settings_data— global settings included in each full menu response.atxRestoMenu/rendered_html— complete rendered HTML.atxRestoMenu/rendered_tabbed_html— complete interactive-layout HTML.atxRestoMenu/rendered_tabbed_section_html— one server-rendered tab panel.atxRestoMenu/style_variables— safe--atxrm-*variables on the menu wrapper.atxRestoMenu/tabbed_style_variables— safe--atxrm-tabs-*variables on the interactive wrapper.atxRestoMenu/before_menuandatxRestoMenu/after_menu— output actions.atxRestoMenu/before_tabbed_menuandatxRestoMenu/after_tabbed_menu— interactive-layout output actions.
Use globally unique ACF field keys and names in site extensions. Prefixing them with the client/site slug prevents collisions across installations.
Styling
The insertable Restaurant Menu block is an ACF Block in Preview mode. Its full-width ACF fields select one or several menus, choose Classic sections or Interactive section tabs, control the title and description independently, provide optional replacement title/description text, and override the currency symbol and its before/after position. Colour controls cover background, body, heading, muted, accent, and borders; the cards/surfaces colour appears only for the Classic layout. Reset block colours clears all colour overrides for that block in one action. Global layout, currency, visibility, and colour defaults live under Restaurant Menus → Settings & Allergens. Empty or reset per-block values inherit those global options.
The tabbed layout server-renders its first/selected section, loads later sections from the public read-only REST endpoint, caches successful responses in the browser, supports arrow-key tab navigation, and falls back to all sections when JavaScript is disabled. It uses a responsive two-column dark layout inspired by the interaction pattern of modern restaurant menus; on small screens the items collapse to one column and the section bar scrolls horizontally.
Previously saved atx-resto-menu/menu blocks continue to render, but are hidden from the inserter. New blocks use acf/atx-resto-menu, which prevents the legacy JavaScript editor and ACF field UI from competing for the same block instance.
The classic stylesheet uses .atx-resto-menu classes; the tabbed layout uses .atx-resto-menu-tabs classes and CSS custom properties such as --atxrm-tabs-accent, --atxrm-tabs-bg, and --atxrm-tabs-text. Override those selectors in the theme, dequeue the corresponding style for a completely custom presentation, or consume the REST API. The normalized data is also available in PHP:
$menu = (new \atxRestoMenu\MenuRepository())->get(12);
Block category
Change the block category without editing block.json:
add_filter('atxRestoMenu/block_category', static fn (): string => 'theme');
Releases and updates
The updater checks GitHub Releases for siko001/atx-resto-menu. Push a semantic tag such as v1.1.0; the included workflow lints PHP, builds atx-resto-menu.zip, and attaches it to the release. Change the repository values in config/github-updater.php if the final repository differs.
Security notes
The public API only exposes published menu content. WordPress and ACF enforce edit capabilities and nonces. The demo seeder requires edit_posts and a valid nonce. Output is escaped by context, descriptions permit only WordPress-safe markup where documented, remote updates use wp_safe_remote_get, and no uploaded executable content is handled by the plugin.