151 lines
6.3 KiB
Markdown
151 lines
6.3 KiB
Markdown
# 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
|
|
|
|
```js
|
|
{
|
|
module: "MMM-NextcloudCookbook",
|
|
position: "fullscreen_above",
|
|
config: {
|
|
shareUrl: "https://cloud.example.test/s/SHARE_TOKEN",
|
|
controlUrl: "http://mirror.example.test:8080/MMM-NextcloudCookbook/control"
|
|
}
|
|
}
|
|
```
|
|
|
|
`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`:
|
|
|
|
```js
|
|
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:
|
|
|
|
```text
|
|
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:
|
|
|
|
- [Cookbook API documentation](https://nextcloud.github.io/cookbook/dev/api/0.1.0/index.html)
|
|
- [Cookbook user documentation](https://nextcloud.github.io/cookbook/user/)
|
|
|
|
## 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:
|
|
|
|
```text
|
|
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.
|
|
|
|
## Development
|
|
|
|
```bash
|
|
npm install
|
|
npm test
|
|
```
|