Files
MMM-NextcloudCookbook/README.md
T

7.2 KiB

MMM-NextcloudCookbook

A MagicMirror module that displays recipes from a read-only Nextcloud public share. It includes a phone-friendly control page for choosing a recipe, adjusting its number of portions, and entering or leaving recipe mode.

Create a public share for the folder configured as your Nextcloud Cookbook recipe directory. Read-only permission is sufficient. Copy the public share link; it should look like https://cloud.example.test/s/SHARE_TOKEN.

MagicMirror configuration

{
  module: "MMM-NextcloudCookbook",
  position: "bottom_right",
  config: {
    shareUrl: "https://cloud.example.test/s/SHARE_TOKEN",
    controlUrl: "http://mirror.example.test:8080/MMM-NextcloudCookbook/control",
    layout: "stacked"
  }
}

layout controls the full-screen recipe arrangement. Its default value, "stacked", displays the ingredients above the instructions. Set it to "side-by-side" to display ingredients and instructions in two columns. Both layouts automatically scale the ingredient and instruction sections to make the best use of the available screen while keeping all recipe content visible. The recipe title, timing metadata, yield, and QR controller remain at fixed sizes.

The configured position controls where the QR controller appears during the normal MagicMirror layout. When a recipe is activated, the module displays a fixed full-screen overlay regardless of that region. Exiting recipe mode removes the overlay and returns the QR controller to its configured position.

controlUrl is the complete address that should open when someone scans the QR code. Use the MagicMirror host name or IP address and port that your phone can reach. The module generates the QR image itself; it does not use an external QR code service.

controlUrl is optional. When omitted, the module attempts to construct it from the address used to load MagicMirror. Set it explicitly when MagicMirror runs as an app or service using an address such as localhost, or when phones reach it through a different host name, port, or reverse proxy.

When controlUrl is omitted, the module appends its default control path, /MMM-NextcloudCookbook/control, to the detected MagicMirror address. Most installations do not need to configure controlPath separately.

For a password-protected public share, add sharePassword:

config: {
  shareUrl: "https://cloud.example.test/s/SHARE_TOKEN",
  sharePassword: "PUBLIC_SHARE_PASSWORD"
}

Do not treat values in MagicMirror's config.js as private: someone who can load the MagicMirror display may be able to inspect them. A read-only public share URL is normally appropriate because its token is already limited to that share. Do not put a Nextcloud account password or app password in this configuration.

To keep even the share token out of the configuration delivered with the MagicMirror display, set SECRET_NEXTCLOUD_COOKBOOK_SHARE_URL and, if needed, SECRET_NEXTCLOUD_COOKBOOK_SHARE_PASSWORD in the MagicMirror process environment and omit the corresponding config values. Environment values take precedence over module configuration and are read only by node_helper.js. Read more here: https://docs.magicmirror.builders/configuration/secrets.html

Open the controller at:

http://mirror.example.test:8080/MMM-NextcloudCookbook/control

The share must contain Nextcloud Cookbook recipe folders with a recipe.json file in each folder. The module uses Nextcloud's token-scoped public DAV API; protected shares authenticate as Nextcloud's anonymous public-share user.

Data-source decision: public WebDAV instead of the Cookbook API

Nextcloud Cookbook provides a REST API, but its external API requires Nextcloud user credentials on every request. A read-only public-share token cannot authenticate to that API.

This module intentionally reads the recipe files through Nextcloud's public WebDAV interface because its job is limited to listing and displaying recipes. That gives the mirror a narrower security boundary:

  • access is scoped to the shared recipe folder;
  • the share can be read-only;
  • the mirror receives no general Nextcloud account credential; and
  • the module cannot create, update, or delete recipes.

Cookbook stores recipes as ordinary recipe.json files, so WebDAV provides the data required by this read-only display without relying on Cookbook's database index. Index synchronization and reindexing matter when an external tool writes recipe files; this module does not write them.

The Cookbook API would become preferable if the module later needs Cookbook-native search, categories, keywords, imports, or recipe editing. In that case, use a dedicated Nextcloud service user with read-only access to the recipe folder and a dedicated app password rather than credentials for a person's normal account.

References:

Future architecture: recipe sources and consumers

The current module both retrieves recipes and presents the full-screen recipe mode. A future version should separate those responsibilities using MagicMirror's notification system as a shared recipe data stream:

MMM-NextcloudCookbook ─┐
MMM-Paprika ───────────┼── recipe data notifications ──> MMM-RecipeMode
MMM-Mealime ───────────┘

In that model:

  • MMM-NextcloudCookbook is a source adapter. It reads recipes from Nextcloud Cookbook and publishes normalized recipe records.
  • MMM-RecipeMode is a consumer. It provides recipe selection, the phone control page, portion scaling, QR code, and full-screen cooking display.
  • Other source modules can publish recipes from Paprika, Mealime, local files, or other services without duplicating the presentation code.
  • Additional consumers can use the same recipe data for meal planning, search, shopping lists, dashboards, or other displays.

The shared notification contract should eventually define source-qualified stable recipe IDs, basic list metadata, complete recipe records, refresh and error states, and optional source capabilities. The normalized record should retain schema.org Recipe fields where practical. Exact notification names and payload schemas should be designed when a second source or consumer is implemented, rather than treating the current module's private HTTP API as the cross-module contract.

This separation is a future feature. The current combined behavior should remain functional until MMM-RecipeMode can replace its presentation and control responsibilities.

Future presentation option: preserve selected modules

Recipe mode currently hides every other MagicMirror module. A future MMM-RecipeMode configuration should accept an allowlist of modules to leave visible while cooking. For example, a user could preserve a calendar at the top of the display while the recipe occupies the remaining area. The option should support module names and, where multiple instances exist, specific instance identifiers. Hiding all other modules should remain the default.

Or maybe it should just be up to the mirror admin to specify a pane (most of the screen) which swaps content to recipe mode or not.

Development

npm install
npm test