Last thing I did for mealplanner was to create the CI/CD pipeline so I can automatically test and create binaries to distribute the app. Which is great, but if someone actually did download it, they’d have an empty app w/ no recipes. Not particularly useful. So before people can use the app, there has to be a way for people to get some recipes, specifically a collection of already-vetted Plated recipes.


Recipe bundles! What are they?

“Recipe bundles are a collection of recipes” might work as a general description, but if I’m going to code some features around them I’d need to figure out more:

Where do they come from?

Right now there’s just one recipe bundle: the database of Plated recipes I created specifically for the app. But in the future there will ideally be plenty more. And none of them should be created, managed or vetted by a central authority, like a company. Instead, I want users to be able to create their own bundles and distribute them to whoever wants them.

That is … a long term goal, but certainly something I want to keep in mind.

What is their format?

This is easy to answer… because I’ve already done the work for it! I knew from the get-go that I’d need to support more than just one database of recipes. The app already supports storing recipes in a central SQLite database, the one that’s setup when the app is initialized, and storing recipes in secondary, read-only databases. These secondary databases are the underlying format of recipe bundles.

How are they identified?

If recipe bundles were distributed through a central authority, like a company with a centralized webapp, the authority could determine what names/identifiers each bundle has. mealplanner will never have such a centralized structure, so a simple name won’t cut it. Different users could easily give their bundles the same name and there won’t be a way to prevent this. (Though I suppose it might be possible to have this, I think it would be a complicated and altogether worthless feature.)

Anyway, so a recipe bundle can’t be given a simple identifier (and that includes a username/bundle name pairing for the same reason). And the situation is further complicated by the fact that there is no decentralized network of mealplanner users right now. So I need an identifier that works for now when the app cannot connect to other instances of the app, and can still be made to work for my vision of the app in the future.

My choice for the moment was to use a URI which I’m calling the bundle’s “authoritative URI”. The URI has to resolve to the recipe bundle’s database file itself, so entering it in a browser would just download the bundle. In the future, this could be a special URI that resolves to a bundle defined by another person (something p2p for instance).

I think this is a relatively good choice for now, buuuuut… there’s one pretty big unanswered question here: what happens if the URI needs to change? Right now I’m hosting the plated bundle on dropbox, but what happens if I need to move it? If I just change the URI, everyone that downloaded it would suddenly see a different recipe bundle in the search that they apparently don’t have access to. Then there’s the issue of giving up a URI only to have someone else, possibly an attacker, start distributing something else through that URI.

There’s some serious problems w/ this approach that I’ll have to fix, but for now it’s good enough for the “minimum usability” goal I’m working on.

How do users find them?

There needs to be a way to search for them in the app. For this I decided to put an “Add” dropdown with a “Recipe Bundle” item. Clicking it opens up the recipe bundle search.

The search itself is a sort of placeholder code for the moment. It’s looks like it’s searching, but there’s only one recipe bundle in existence, so it’s really just searching through a hard-coded list.

In the future, when the app networks with itself, there’ll need to be a way to search through the bundles published by every user. I have no idea how this will work, but I’m sure it’ll be fun to figure it out :)

How do users get them?

Once a user picks a bundle to download (via a download button), it needs to be downloaded locally, unzipped if needed, then registered with the primary database so the recipes will become visible. For the moment this means just downloading via a plain ol’ HTTP request to the bundle’s authoritative URI.

In the networked future of mealplanner, there will need to be a p2p distribution method, probably w/ an embedded bittorrent client. This might seem unnecessary, but given I am not a rich, investor funded company supporting this app, I would never be able to serve recipe bundles that can be hundreds of megabytes to a ton of users.


With enough of the details worked out, it was possible to actually start working on the features I need to add, namely searching for and downloading bundles.

Searching for bundles

As I said above, for starting the ‘search -> download bundle’ workflow I put in an ‘Add’ dropdown button:

screenshot of a small portion of mealplanner, a dropdown is expanded, the dropdown name is "Add" and the dropdown item is labeled "Recipe Bundle"

At the moment there is only one way to add new recipes, by downloading the one available recipe bundle. Sooner or later, however, I’ll add an “import from website” option and a way to manually enter recipe details.

Clicking on it launches the (bare bones) bundle search modal:

a screenshot of a modal in mealplanner, the modal title is "Recipe Bundles", underneath is a text input for searching through bundles. in the search results area there is only one recipe bundle titled "Plated". The description for the "Plated" recipe bundle reads "Recipes from the now defunct Plated meal kit service". An image for the recipe bundle shows a meal next to a Plated shipping box. Under the Plated bundle is a "Download" button.

And you CAN search through the bundles, but, again, since there’s only one there’s no point.

Downloading bundles

Clicking the download link, downloads the bundle and sets it up:

another screenshot of the recipe bundles modal, this time with the "Plated" recipe bundle download in progress. The title, description and image are greyed out and underneath is a progress bar indicating the download is a little more than half complete. The Download button is greyed out as well and the text displayed says "Downloading...".

This part looks simple, but took a while to for me to code. If mealplanner were an electron app, that wouldn’t have been the case. Electron uses node.js to run code outside of a browser context, and asynchronously streaming data from a URI to a file (ie, downloading something) has been supported there since node was created. Implementing the download in electron would have been a handful of lines of code.

Unfortunately, I am using tauri instead which is a relatively new platform that uses different, less resource intensive technologies to provide the same result as electron. The “backend” for tauri apps are written in rust and mapped to the JavaScript in the browser.

Sending HTTP requests asynchronously in rust isn’t particularly difficult, but since I’m pretty inexperienced with rust, it took quite a while to implement it, and took longer to integrate that code with the current alpha release of tauri, which is not 100% working or documented.

But, I did it and it got done… so I win! I guess.

Anyway, other than downloading, I also made sure mealplanner would try to resume downloads if an error occurs in the middle of a download or if the user just quits the app before it finished. I guess I didn’t have to do this, but I don’t know how much bandwidth dropbox will let me burn w/o making me pay…


Woo, slowly getting my way to a minimally usable app! Next I need to do a security review of the release process, then I think I can just make a very early release :)

Anyway, if you’d like to see all the code I wrote for this change and berate me for it, you now can! Enjoy?