GithubHelp home page GithubHelp logo

mo-nomz's People

Contributors

dfithian avatar

Stargazers

 avatar

Watchers

 avatar  avatar

mo-nomz's Issues

Edit/Merge behavior

When adding or removing new items (link/blob/list), existing edits and merges are forgotten.

  • When adding, don't refresh the list just update it.
  • When removing, remove all items in that recipe
    • Warn when merging that if you delete or deactivate a recipe it'll delete merged items if they're in the deleted recipe. To avoid this don't merge until you're done.

UX/UI feedback

  • Make circle selection buttons bigger
  • Don't know what the + sign means when adding new ingredients
  • Clicking "save" on add new ingredients page doesn't use the in-progress ingredients
  • Icons are weird for adding
    • The link should be a plus
    • The clipboard should be a pencil
    • The plus should be a ???
  • "Save" is a weird word
  • When adding new ingredients, make the picker taller so that you can see the other options
    • Make all the pickers the same height
  • When adding a blob, tell people they can add multiple
  • Instead of having two buttons for adding items, have one button and a toggle for structured/unstructured input
  • In structured input, ingredient before unit
  • Export should prepend a title
  • Reordering drag and drop

Structured ingredient input

Be able to input an ingredient at a time with structured input instead of pasting. User should be able to submit multiple at once. Get rid of the pasting view entirely.

UI Feedback

  • Deleting a recipe doesn't delete from the grocery list
  • Better icon for "bulk remove"
  • Weird symbols in recipe/ingredient list after parsing - see #16
  • Keyboard goes over text input so you can't see it
  • Word wrap on recipe titles

Better backend scraping and parsing

Better backend scraping and parsing which will scrape more fields from the HTML and eagerly parse. Refactor parser types. Add tests.

  • Add a bunch of links
  • Paste
  • Link -> export -> paste?
  • Platform detection instead of probability based

Sharing bugs

  • Safari doesn't work - you can share, but does not make API call
  • Notes doesn't work - you can't share

Group ingredients

A way to group ingredients so that you can add them to the list together

Check for duplicated recipe links

When adding a recipe link, check to make sure there's not already one that matches.

Do this on the backend and just set the existing one to active.

V2 improvements

  • App name doesn't match the art
  • Add better keywords
  • Remove lines between rows in list view
  • Landing page in app for marketing
  • Move privacy policy and support page over to static HTML

Release the app

  • Heroku uptime - Hobby ($7/month)
  • Test on all different size simulators and portrait/landscape mode
  • Promotional materials like screenshots for the App Store
  • Run the test plan
  • Pull the trigger

Add back merge

  • Dedicated database actions (like Database.hs)
  • Automerge
  • Unmerge
  • Merge on purpose
  • Dismissable merge tip
  • Fix existing actions

Bug report

  • Export is not ordered correctly
  • Automerge is not working correctly
  • Create recipe blob is not dismissing window and reloading
  • Reorder broken
  • Cancel after selecting item keeps it selected
  • Top margin when keyboard shows
  • Manual add opacity change

Decide on pricing scheme

A few options:

  1. Sell it for $1 or $2
  2. Link to venmo/square/patreon
  3. In app purchases which is just a "thank you"
  4. In app purchases which guard a feature

Decide on one and then do it

Write blog post on the experience of creating an app

Nomz

I created the iOS app Nomz (link to it). The app functions as a meal planner. You add links to recipes; the backend parses the ingredient list and adds them to a grocery list. You can also add freeform groceries to your list, say if you know you need eggs or milk. It integrates with other apps like Reminders, Notes, and Safari. You can save recipes for later if you want to make them at some point in the future.

For years, I've been interested in the idea of passive income and financial independence. I don't want to retire early, but rather have the freedom to pursue interests irrespective of being tied to a tech salary. I decided to create an app to see what the challenges would be. The point would not to make money, though a requirement was that the app would be able to generate revenue. My goal was research, with the hope that down the line I could set up a few modest income sources based off of apps.

My fiancee at the time (now wife) came up with the idea. We used to grocery shop by going down each aisle and buying whatever looked good. The result was a large bill and lots of wasted food. A few months ago, we switched to planning our meals using recipes we wanted to cook and buying the ingredients for 4 or 5 of them per week depending on how many times we wanted to get take out. Our spending instantly fell 25%, we stopped wasting as much food, and we started eating healthier. The biggest issue was that my wife was finding recipe links online and transcribing the ingredients to a grocery list by hand. She saved the links in a note on her phone.

Naturally, when I asked my wife what she wanted in an app, she had a very clear idea.

I started Easter weekend, working nights and weekends for 6 weeks until I got to the point at which I had a working prototype. I had 5 testers, the most important being my wife who, every week, would download the most recent version, add the recipes we planned to make that week, and then provide the feedback which I worked on addressing the next week. This continued 6 weeks until my wife decided that all her needs were addressed. The following are the features we decided on.

Features

  • Parse an ingredient list from a recipe link
  • Supply freeform groceries
  • Merge two groceries together
    • "Auto merge" groceries with the same name
    • Merge groceries manually (say, "cubed butter" and "butter" on its own)
  • Reordering items
    • Allow users to group groceries based on where they are in the store
  • Save recipes for later
  • Mark groceries as bought
    • Allow users to re-add them to the list later if desired
  • Export to other apps
    • Notes, Reminders, copy to clipboard, etc
  • Import from other apps
    • Links from Safari, freeform text from Notes, etc
  • Clear the list
    • Delete freeform groceries and save all recipes for later
  • Revenue generation
    • Pay for the app, provide ads, or use the "freemium" model

Takeaways

Cost

To date, I've spent $100 on the apple developer license for 1 year, and $7 per month (1 month in) on the lowest paid Heroku tier (what is its name). If the app gets popular it's possible I'll have to start paying $25 per month for additional instances. I used the one free private repository afforded to my GitHub account.

Effort

I underestimated how much effort it would take. That's coming from a software developer with years of experience! In truth, I did correctly estimate how much time it would take to make a proof of concept (about 2 weeks), but I didn't understand how much iteration would be needed. The app is exceedingly simple, and I can't really think of any way to make it simpler, but getting it into its simplistic state took a lot of time and effort. The next time I go down this route, I'll be more prepared to iterate.

Monetization

Monetizing an app is about maximizing dollars per download. The least amount of effort would have been to charge a flat fee in the app store ($1 or $2). However, nobody would have bought my app for two reasons. First, because of all the free options out there. Second, this isn't the sort of app which is going to become ubiquitous on all phones. It solves a very niche problem, easily solvable with pen and paper, so the barrier to download needed to be low.

Another option would have been to provide a "freemium" model, with some features available for free and others available after paying a modest fee. This struck me as a bad idea because the app is already so simple, removing any features would basically make it useless.

Eventually, I decided to provide the app for free with ads. I decided against going with a freemium model (pay to remove ads) from the outset in the interest of spending more time providing core features. If the app gets popular I may add a paid tier.

In exploring all these options it struck me how much time I spent monetizing the app as opposed to adding features. Initially it seemed ironic that in order to make less money per download (offering ads instead of upfront cost in the app store) I had to do more work, but I know that monetization is the core of every business so I'm happy to have gone through the process of weighing the tradeoffs.

Technical challenges

Parsing the ingredient lists was more difficult than I thought. So much so that I'll be writing another blog post on the challenges I faced making a robust scraper and parser. Stay tuned!

Rate recipes

Ability to rate recipes out of 5 stars so you know which ones you liked

Store recipes and ingredients on phone

So now I’m off to the grocery store with my list. My phone automatically connected to the store’s wifi and the connection is bad so when I opened Nomz I got a loading icon that just spun and eventually got an error that said it couldn’t connect to Nomz. And now I’m about to be real mad because I don’t understand why I need internet access for a grocery list.

Rename the app

Give it a better name and rebrand for competition with other grocery list apps

Marketing materials

  • Release blog post
  • Link to blog post in app store and website
  • Share with food bloggers
  • Add images and gifs to website and blog posts
  • Nutritionists and dietitians

Better UX for reordering (plus merge)

I wanted to reorder the items to be in the grocery store order. For my store dairy is first, produce is last and then cereal and canned goods are in the middle.
That took a bit to figure out. There were up/down icons that indicated I could reorder things but if I tapped them nothing happened.
Then I tried tap and hold and then worked once so I thought I had figured it out but on subsequent tries it tried to merge items (which I don’t understand why that’s a thing you’d want to do) but I think where you click and hold on the item determines what it does.

FAQ page

Add an FAQ page for explanations of features like sharing

HTML status page

Make a status page you can load in the browser

Should it do ekg?

Write blog posts on technical limitations

Ingredient Representation

This post is part 2 of 3 in a series on the Nomz Meal Planner
for iOS. Original post is [here]({% post_url 2021-05-31-nomz-meal-planner %}).

Recipe ingredients are tricky. Some quick examples:

  • 1 cup milk (name, unit, and quantity)
  • 1 egg (no unit)
  • Salt and pepper (no unit or quantity)
  • 1 slice of bread (nonstandard unit)

In creating a model for an app with a core feature dedicated to auto merging items, it's imperative to be able to
capture all different combinations. I made the quantity and unit optional, and provided a conversion table where
complementary units were concerned (both imperial and metric units, in addition to singular and plural forms of the same
unit).

Conversion table

I wrote a companion function to grab all possible conversions for a unit - inputting "ounce" outputs a map containing
[(ounce, 1), (cup, 8), (tablespoon, 128), (teaspoon, 384), (pinch, 1536)].

Merging items

In the case where items share a name and unit, or had complementary units (teaspoon and tablespoon, milliliter and
liter, etc), the backend automatically merges those items using the conversion table.

Fractions

Recipes typically deal with fractions with denominators of 2, 3, or 4. I made a simplifying assumption to enumerate
these values: 1/4, 1/3, 1/2, 2/3, and 3/4. After applying the conversion math between complementary units, I constrained
the decimal portion of each computed quantity to the nearest enumerated value.

User input

In the app, I used the enumeration indices as identifiers in the picker view. Using modular arithmetic, it also made it
easy to infer the quantity when the user merged two items. Instead of doing complicated fractional addition, I was able
to simply add the enumerated indices!

Conclusion

Simplifying assumptions around quantities based on the data available worked out great. Conversions between
complementary units were a crucial step towards implementing auto merge, but didn't quite achieve the elegance I
desired.

Stay tuned for the next post in the series, on scraping recipe websites!

Parsing

This post is part 3 of 3 in a series on the Nomz Meal Planner
for iOS. Original post is [here]({% post_url 2021-06-01-nomz-ingredient-representation %}).

An app that parses recipe ingredients requires both a robust parser and a powerful HTML scraper.

Parsing

Attempting to write a parser for real world data, especially when hosted on webpages, is difficult. A robust parser for
lists of recipe ingredients needs to:

  • Parse fractions in many forms (1/2 and 1/2)
  • Parse written quantities ("five")
  • Parse decimals
  • Understand abbreviations ("T", "tbsp", and "tablespoon" are the same)
  • Understand ranges of quantities ("1-2 cups")
  • Understand that sometimes a dash ("-") means a range and sometimes it means add two quantities ("1-1/2")
  • Understand that sometimes quantities and units are missing
  • Probably some other things I missed

I'll spare the boring details about the actual Haskell code in this part.

Scraping

Turns out there are a few recipe blog vendors in addition to the common brand names like Betty Crocker, Pillsbury, and
Food Network, and I implemented the scraping logic to dispatch based on domain name and/or a test in the HTML.

Integration

After writing a robust parser and scraper, hooking the two components up was easy.

Testing

I wrote unit tests for both the parser and scraper. Some tests are highly specific, inputting a recipe link and testing
the output matches exactly what's on the page, but since I needed hundreds of tests (for hundreds of websites and blogs)
I ended up writing most tests using a few heuristics:

  • At least 5 ingredients parsed
  • At least one ingredient parsed with both quantity and unit
  • No duplicate ingredients
  • Similar seeming ingredients are allowed (like "butter" and "butter, cubed") but only up to 3 of them

Ideally, I'd run these tests every night and alert if one of them broke. After all, HTML scraping is extremely brittle
and I'd want to know ASAP if something was broken, especially in production.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.