Skip to content

Commit 919b37b

Browse files
committed
deploy: 2fcfe43
1 parent 657968a commit 919b37b

74 files changed

Lines changed: 247 additions & 248 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

blog/01-my-approach-to-automating-grocery-shopping/index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
text-cooklang-gray-700 hover:bg-cooklang-gray-100">Blog
2525
</a><a href=/about/ class="block px-4 py-2 text-base font-medium rounded-md transition-colors duration-150
2626
text-cooklang-gray-700 hover:bg-cooklang-gray-100">About
27-
</a><a href=https://www.buymeacoffee.com/dubadub target=_blank rel="noopener noreferrer" class="block px-4 py-2 bg-yellow-400 text-gray-900 font-medium text-sm rounded-md">☕ Buy me a coffee</a></nav></div></header><main class=flex-1><article class=bg-white><div class="container mx-auto px-4 py-8 overflow-x-auto"><header class=mb-8><h1 class="text-4xl font-bold text-cooklang-gray-900 mb-4">How to Automate Grocery Shopping with Plain Text Recipes</h1><div class=text-cooklang-gray-600><time datetime=2026-04-09T00:00:00+00:00>April 9, 2026</time></div></header><div class="prose prose-lg max-w-none text-cooklang-gray-700 overflow-x-auto"><p>I used to buy groceries by wandering through the store, picking things up as I went. It worked when I could physically walk the aisles. When I switched to online ordering, I couldn't do that anymore. I had to know exactly what I needed before I started.</p><p>So I began writing meal plans on sticky notes, listing ingredients by hand, then combining them into an order. After a few weeks of this, the developer in me couldn't take it anymore. The process was repetitive and mechanical — exactly the kind of thing a computer should handle.</p><p>That's how <a href=/>Cooklang</a> was born.</p><h2 id=the-idea>The Idea</h2><p>What if recipes were plain text files where ingredients were tagged with <code>@</code>? Like this:</p><div class=code-toolbar><pre class=language-cooklang data-language=cooklang><code class=language-cooklang>Then add @salt and @ground black pepper{} to taste.
27+
</a><a href=https://www.buymeacoffee.com/dubadub target=_blank rel="noopener noreferrer" class="block px-4 py-2 bg-yellow-400 text-gray-900 font-medium text-sm rounded-md">☕ Buy me a coffee</a></nav></div></header><main class=flex-1><article class=bg-white><div class="container mx-auto px-4 py-8 overflow-x-auto"><nav class="text-sm text-cooklang-gray-600 mb-4" aria-label=Breadcrumb><ol class="flex flex-wrap items-center gap-x-2"><li><a href=/blog/ class=hover:text-cooklang-orange>Blog</a></li><li class=text-cooklang-gray-400 aria-hidden=true></li><li><a href=/blog/recipe-workflows/ class=hover:text-cooklang-orange>Recipe Workflows</a></li><li class=text-cooklang-gray-400 aria-hidden=true></li><li class="text-cooklang-gray-900 truncate max-w-xs" aria-current=page>How to Automate Grocery Shopping with Plain Text Recipes</li></ol></nav><script type=application/ld+json>{"@context":"https://schema.org","@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","item":"https://cooklang.org/blog/","name":"Blog","position":1},{"@type":"ListItem","item":"https://cooklang.org/blog/recipe-workflows/","name":"Recipe Workflows","position":2},{"@type":"ListItem","name":"How to Automate Grocery Shopping with Plain Text Recipes","position":3}]}</script><header class=mb-8><h1 class="text-4xl font-bold text-cooklang-gray-900 mb-4">How to Automate Grocery Shopping with Plain Text Recipes</h1><div class=text-cooklang-gray-600><time datetime=2026-04-09T00:00:00+00:00>April 9, 2026</time></div></header><div class="prose prose-lg max-w-none text-cooklang-gray-700 overflow-x-auto"><p>I used to buy groceries by wandering through the store, picking things up as I went. It worked when I could physically walk the aisles. When I switched to online ordering, I couldn't do that anymore. I had to know exactly what I needed before I started.</p><p>So I began writing meal plans on sticky notes, listing ingredients by hand, then combining them into an order. After a few weeks of this, the developer in me couldn't take it anymore. The process was repetitive and mechanical — exactly the kind of thing a computer should handle.</p><p>That's how <a href=/>Cooklang</a> was born.</p><h2 id=the-idea>The Idea</h2><p>What if recipes were plain text files where ingredients were tagged with <code>@</code>? Like this:</p><div class=code-toolbar><pre class=language-cooklang data-language=cooklang><code class=language-cooklang>Then add @salt and @ground black pepper{} to taste.
2828
Poke holes in @potato{2}.
2929
Place @bacon strips{1%kg} on a baking sheet and glaze with @syrup{1/2%tbsp}.</code></pre></div><p>The recipe stays readable — you can follow it as-is. But a computer can also parse it, extract every ingredient with its quantity, and build a shopping list automatically.</p><p>Because it's plain text, I can store recipes in Git, edit them in any text editor, and sync them across devices with whatever I already use. No database, no app subscription, no vendor lock-in.</p><h2 id=the-tools>The Tools</h2><p>A markup language alone isn't useful without tools to process it. I built <a href=/cli/>CookCLI</a> — a command-line program that reads <code>.cook</code> files and does practical things with them.</p><p>The one I use most is <code>shopping-list</code>. Point it at a few recipe files and it combines all ingredients, grouped by store aisle:</p><div class=code-toolbar><pre class=language- data-language><code class=language->$ cook shopping-list Neapolitan\ Pizza.cook Root\ Vegetable\ Tray\ Bake.cook
3030

@@ -47,5 +47,5 @@
4747

4848
TINNED GOODS AND BAKING
4949
chopped tomato 3 cans
50-
fresh yeast 1.6 g</code></pre></div><p>Output can be JSON or YAML for piping into other programs. CookCLI also includes a <a href=/cli/commands/server/>web server</a> for browsing recipes from a phone or tablet, and a <a href=/cli/commands/search/>search command</a> for finding recipes by ingredient.</p><h2 id=my-workflow>My Workflow</h2><p>I organize recipes into directories that represent meal plans. Generating a shopping list for the week is one command:</p><div class=code-toolbar><pre class=language-bash data-language=bash><code class=language-bash>cook shopping-list ./this-week/*.cook</code></pre></div><p>I cross off what I already have, then order the rest. The process takes about five minutes instead of the thirty-plus it used to take with sticky notes. More importantly, I buy exactly what I need — no forgotten ingredients, no impulse purchases.</p><p>I keep all my recipes in a <a href=https://github.com/dubadub/cookbook>Git repository</a>. They've been evolving for years — adjusting quantities, adding notes, trying variations. Git tracks every change.</p><p><strong>Update (2025):</strong> I've since built a <a href=https://github.com/dubadub/cookbook/tree/main/shop-automation>Rust script</a> that maps recipe ingredients to products on my grocery store's website, making the ordering process almost fully automatic. The ecosystem has also grown — there are now <a href=/app/>mobile apps</a>, an <a href=/blog/15-cooklang-obsidian-guide/>Obsidian plugin</a>, a <a href="https://marketplace.visualstudio.com/items?itemName=nicholasglazer.cooklang-vscode-support">VS Code extension</a>, and a <a href=https://recipes.cooklang.org>community recipe index</a>. Check the <a href=/docs/getting-started/>getting started guide</a> to try it yourself.</p><p>-Alexey</p></div></div></article></main><footer class="bg-cooklang-gray-900 text-white mt-auto"><div class="container mx-auto px-4 py-8"><div class="grid grid-cols-1 md:grid-cols-4 gap-8"><div><h4 class="font-semibold mb-4">Mobile Apps</h4><div class=space-y-2><a href="https://play.google.com/store/apps/details?id=md.cook.android" class=block><picture><source type=image/webp srcset=/google-play-badge.webp><img src=/google-play-badge.png alt="Download on Google Play" class="h-10 w-auto" width=394 height=128 loading=lazy>
50+
fresh yeast 1.6 g</code></pre></div><p>Output can be JSON or YAML for piping into other programs. CookCLI also includes a <a href=/cli/commands/server/>web server</a> for browsing recipes from a phone or tablet, and a <a href=/cli/commands/search/>search command</a> for finding recipes by ingredient.</p><h2 id=my-workflow>My Workflow</h2><p>I organize recipes into directories that represent meal plans. Generating a shopping list for the week is one command:</p><div class=code-toolbar><pre class=language-bash data-language=bash><code class=language-bash>cook shopping-list ./this-week/*.cook</code></pre></div><p>I cross off what I already have, then order the rest. The process takes about five minutes instead of the thirty-plus it used to take with sticky notes. More importantly, I buy exactly what I need — no forgotten ingredients, no impulse purchases.</p><p>I keep all my recipes in a <a href=https://github.com/dubadub/cookbook>Git repository</a>. They've been evolving for years — adjusting quantities, adding notes, trying variations. Git tracks every change.</p><p><strong>Update (2025):</strong> I've since built a <a href=https://github.com/dubadub/cookbook/tree/main/shop-automation>Rust script</a> that maps recipe ingredients to products on my grocery store's website, making the ordering process almost fully automatic. The ecosystem has also grown — there are now <a href=/app/>mobile apps</a>, an <a href=/blog/15-cooklang-obsidian-guide/>Obsidian plugin</a>, a <a href="https://marketplace.visualstudio.com/items?itemName=nicholasglazer.cooklang-vscode-support">VS Code extension</a>, and a <a href=https://recipes.cooklang.org>community recipe index</a>. Check the <a href=/docs/getting-started/>getting started guide</a> to try it yourself.</p><p>-Alexey</p></div><aside class="mt-12 pt-8 border-t border-cooklang-gray-200"><h3 class="text-lg font-semibold text-cooklang-gray-900 mb-4">Part of the <a href=/blog/recipe-workflows/ class="text-cooklang-orange hover:text-orange-600">Recipe Workflows</a> series →</h3><div class="grid gap-4 md:grid-cols-3"><article class="bg-white border border-cooklang-gray-200 rounded-lg p-4 hover:shadow-md transition-shadow"><h4 class="text-base font-semibold mb-1"><a href=/blog/02-practical-savings-on-groceries-with-cooklang/ class="text-cooklang-gray-900 hover:text-cooklang-orange">Automated Grocery List: Save Time and Money with Meal Planning</a></h4><p class="text-sm text-cooklang-gray-600">Build an automated grocery list from your meal plan using Cooklang. Practical tips for shopping list …</p></article><article class="bg-white border border-cooklang-gray-200 rounded-lg p-4 hover:shadow-md transition-shadow"><h4 class="text-base font-semibold mb-1"><a href=/blog/43-version-control-recipes-with-git/ class="text-cooklang-gray-900 hover:text-cooklang-orange">Version Control Your Recipes with Git</a></h4><p class="text-sm text-cooklang-gray-600">Every recipe app has a 'what if the company dies?' problem. If your recipes are plain text .cook …</p></article><article class="bg-white border border-cooklang-gray-200 rounded-lg p-4 hover:shadow-md transition-shadow"><h4 class="text-base font-semibold mb-1"><a href=/blog/26-how-to-scale-recipes-without-mistakes/ class="text-cooklang-gray-900 hover:text-cooklang-orange">How to Scale a Recipe Up or Down (Without Ruining It)</a></h4><p class="text-sm text-cooklang-gray-600">Scaling recipes sounds like simple math until your cookies come out flat or your soup is inedibly …</p></article></div></aside></div></article></main><footer class="bg-cooklang-gray-900 text-white mt-auto"><div class="container mx-auto px-4 py-8"><div class="grid grid-cols-1 md:grid-cols-4 gap-8"><div><h4 class="font-semibold mb-4">Mobile Apps</h4><div class=space-y-2><a href="https://play.google.com/store/apps/details?id=md.cook.android" class=block><picture><source type=image/webp srcset=/google-play-badge.webp><img src=/google-play-badge.png alt="Download on Google Play" class="h-10 w-auto" width=394 height=128 loading=lazy>
5151
</picture></a><a href="https://apps.apple.com/us/app/cooklangapp/id1598799259#?platform=iphone" class=block><picture><source type=image/webp srcset=/app-store-badge.webp><img src=/app-store-badge.png alt="Download on App Store" class="h-10 w-auto" width=394 height=129 loading=lazy></picture></a></div></div><div><h4 class="font-semibold mb-4">Resources</h4><ul class=space-y-2><li><a href=/docs/ class="text-cooklang-gray-300 hover:text-white transition-colors">Documentation</a></li><li><a href=/cli/ class="text-cooklang-gray-300 hover:text-white transition-colors">CLI Tool</a></li><li><a href=/app/ class="text-cooklang-gray-300 hover:text-white transition-colors">Mobile App</a></li><li><a href=https://cooklang.github.io/cooklang-rs/ class="text-cooklang-gray-300 hover:text-white transition-colors">Playground</a></li><li><a href=https://github.com/cooklang/spec/discussions class="text-cooklang-gray-300 hover:text-white transition-colors">Spec Discussions</a></li><li><a href=https://github.com/cooklang class="text-cooklang-gray-300 hover:text-white transition-colors">GitHub</a></li></ul></div><div><h4 class="font-semibold mb-4">Community</h4><ul class=space-y-2><li><a href=https://reddit.com/r/cooklang class="text-cooklang-gray-300 hover:text-white transition-colors">Reddit</a></li><li><a href=https://discord.gg/fUVVvUzEEK class="text-cooklang-gray-300 hover:text-white transition-colors">Discord</a></li><li><a href=https://x.com/cooklangorg class="text-cooklang-gray-300 hover:text-white transition-colors">X (Twitter)</a></li><li><a href=https://bsky.app/profile/cooklang.bsky.social class="text-cooklang-gray-300 hover:text-white transition-colors">Bluesky</a></li><li><a href=https://mas.to/@cooklang class="text-cooklang-gray-300 hover:text-white transition-colors">Mastodon</a></li><li><a href=https://www.youtube.com/channel/UCOZg3EJ1QsE_DqO-ZcMWblw class="text-cooklang-gray-300 hover:text-white transition-colors">YouTube</a></li><li><a href=/blog/index.xml class="text-cooklang-gray-300 hover:text-white transition-colors">RSS Feed</a></li></ul></div><div><h4 class="font-semibold mb-4">About</h4><p class="text-cooklang-gray-300 text-sm">Cooklang is a markup language for recipes that makes it easy to manage your personal recipe collection.</p></div></div><div class="mt-8 pt-8 border-t border-cooklang-gray-700 text-center text-cooklang-gray-400"><p>Copyright © 2021-2026 Cooklang. All rights reserved.</p></div></div></footer><script>document.addEventListener("DOMContentLoaded",function(){document.querySelectorAll("pre code, code").forEach(function(e){var t=e.textContent||e.innerText||"",t=t.replace(/&#34;/g,'"').replace(/&#39;/g,"'").replace(/&quot;/g,'"').replace(/&apos;/g,"'").replace(/&lt;/g,"<").replace(/&gt;/g,">").replace(/&amp;/g,"&");e.textContent=t}),typeof Prism!="undefined"&&Prism.highlightAll()})</script></body></html>

0 commit comments

Comments
 (0)