Rage Against the COGs — Manual ✕
Manual

Rage Against the COGs — user manual

A calculator for what a plate costs to make and what it should sell for. It runs entirely in your browser: no account, no server, nothing uploaded.

You add ingredients with what you paid for them, and it keeps a running total, divides it into portions, and works out a menu price at the margin you want. Change the price of eggs once and every dish that uses them re-costs.

Read this first. Your recipes live in one browser on one device. They are not backed up anywhere, and browsers do delete storage — Safari clears it for sites you have not opened in about a week. Press Export all every so often and keep the file somewhere real. See Keeping your work.

Contents

  1. Costing your first dish
  2. Reading the ingredient list
  3. The pantry: one price, everywhere
  4. Batches: things you make ahead
  5. Menu price, GP and COGS
  6. Measures and what converts
  7. Keeping your work
  8. Signing in, and a second device
  9. Quick reference

1. Costing your first dish

Everything starts in the Add ingredient panel. The trick to it is the price field: you enter the price the way the label reads, not converted to some per-gram figure.

  1. Name it. Type what you call it — Beef mince. If you have bought it before, the price fills itself in.
  2. Say how much the dish uses. 750, and pick g.
  3. Say what you paid. The label on the bag says $8.90 for a kilo, so type 8.90 for 1 kg. If instead you bought a 500 g pack for $4.50, type 4.50 for 500 g — the pack size box is there so you never have to do that division yourself.
  4. Press Add ingredient. The row appears costed at $6.68, and the price goes into your pantry for next time.
Price  [ 8.90 ]  for  [ 1 ]  [ kg ]     reads as: eight ninety, per kilo
Price  [ 4.50 ]  for  [500]  [ g  ]     reads as: four fifty, for a 500 g pack

Then tell it how far the dish goes

In the Cost panel, set Portions to the number of plates the recipe makes. Cost per portion is the number the whole app is built around — it is what the menu price is worked out from.

Amounts can be fractional: half an onion is 0.5 unit, two and a half grams of yeast is 2.5 g. Only portions have to be whole numbers — you cannot sell half a plate.

2. Reading the ingredient list

Each row shows what it costs the dish and what share of the total that is — so the thing worth renegotiating with your supplier is obvious at a glance.

Beef mince  [pantry]     750 g          $8.90 / kg      $6.68   79%
Onion       [pantry]     2 units        $0.50 / unit    $1.00   12%
Parsley                  0.5 bunches    $1.60 / bunch   $0.80    9%

The marks on a row

A tag beside the name tells you where that row's price comes from. Hover any of them in the app for the long version.

MarkWhat it means
pantryPriced from the pantry. Change it there — or here — and every recipe following it moves too.
no tagThis row has a price of its own. Nothing else is affected when you change it.
batchThis row is another recipe you made ahead. Its price is whatever that recipe currently costs.
own priceIt follows a pantry entry, but that entry is priced per a measure this amount cannot convert to — per litre against an amount in grams. The row is using its own price instead. Fix it by putting both on the same kind of measure.
pantry goneThe entry it followed has been deleted. Still costed, at the last price it had.

When a row shows no cost

Instead of quietly costing something wrong, the app refuses and says why in the cost column:

  • — measures don't match — the amount and the price are in different families, such as grams priced per litre. There is no conversion without knowing the density, so nothing is guessed. Edit the row and put both in the same family.
  • — batch deleted — the batch this row drew on no longer exists. Common after importing a recipe on its own.
  • — circular batch — this recipe ends up containing itself. Only possible in a hand-edited file; remove the offending row.

Still to do

Under the ingredient list is a short list of anything the recipe is still missing. It appears only when there is something in it, and every line names one thing:

  • a row with no usable price — the same mismatch the cost column marks, said in words;
  • a row priced at $0.00 — most often typed in before the invoice was to hand. If it really is free, ignore the line;
  • a batch that still says it makes 1 g — see section 4. Where the app can work the figure out from the ingredients it offers a button, and pressing it sets the yield on the batch, so every dish drawing on that batch is re-costed. A notice says how many.

It looks inside the batches a dish is built from, which is the part that matters most: a dish using a batch whose yield has never been set shows nothing wrong on any of its own rows — the measures agree and a cost appears — and is wrong by however far the real yield is from 1 g. This list is the only place that says so.

There is no score and no percentage, on purpose. A completeness score is raised fastest by changing ml to g until the warnings go away, which would make the one feature protecting your costing the thing standing in your way. A count of what is outstanding can only be cleared by supplying a real number.

The bar at the bottom carries the same idea across the whole menu: 9 of 14 dishes costed counts the dishes with nothing left on this list. Batches are not counted — they are components rather than things you sell, and they reach the number through the dishes that use them.

And when that count reaches every dish — when the last thing on the last list is cleared — the cards cascade down the screen, the way Solitaire has since

  1. Tap anywhere, press any key, or wait: it goes on its own after eight

seconds, it never covers a field you are typing in, and every button on the page keeps working underneath it. If your device is set to reduce motion you get a Task Complete dialog instead.

Save Dish

Everything is saved as you go, so Save Dish (Save Batch on a batch) has two small jobs: it finishes a row you left open for editing, and it sends your recipes to the server straight away rather than a couple of seconds later.

Then, for a moment, the button itself says how the recipe stands:

  • a line like Yes Chef or COGs Crushed, flashing green — nothing is left on this recipe's Still to do list, and a dish is making its target margin;
  • Saved — 2 still to do — the list under the ingredients says what;
  • Saved — under target — fully costed, but the menu price you set is below your target margin.

It will not cheer a costing it knows is wrong. A batch gets lines of its own — it has no margin to beat.

3. The pantry: one price, everywhere

The pantry is your price list. Every ingredient you add records what it cost, under its name — Beef Mince and beef mince are the same entry.

A recipe row can follow its pantry entry, and new rows do by default. A following row takes its price from the entry every time the page draws. So the day eggs go up, you change the number once and every dish using them re-costs.

Two ways to change a price — they are the same change

  • On the recipe — what you reach for mid-service. Edit the row, type the new price, and leave Pantry price pressed on the line under it. What you typed goes to the pantry and out to every other recipe following it.
  • In the pantry panel — what you reach for with an invoice in front of you. Open Pantry, press Edit on the entry, type the new price. The row tells you how many recipes it is about to move before you save.

Both open the price the way an invoice reads — 25 for 1 kg, not 0.025 per g — with the same pack box as the add form, so a price typed in as "25 for 1000 g" can be put right without doing the division.

Either way the app says where the price landed, so nothing moves behind your back:

Eggs is now $0.60 / unit in the pantry, and in 3 recipes that follow it.

The note clears itself after fifteen seconds, or press its ×.

Keeping a price to one dish

Sometimes one dish genuinely costs something different — the bulk bag, a different supplier, the good butter. Edit the row and press Own price on the line under it. That row keeps the price you give it, for that recipe only, and the pantry is left exactly as it was. The pantry tag disappears.

Eggs  [ 3 ] [unit]  [ 0.60 ] for [ 1 ] [unit]   [Save] [Cancel]
[Pantry price][Own price]   <- the pressed one decides whose price it is

If Pantry price is pressed with a red note beside it, the row still asks to follow, but the entry has been forgotten or is priced per a measure this amount cannot convert to. The row costs at the price shown until that is sorted out. The link is kept — saving the row does not quietly throw it away.

What the pantry panel tells you

Every entry says what depends on it, always. Press the count to list the recipes — each one is a way straight into it.

Eggs            $0.60 / unit        [Use] [Edit] [Delete]
  v used in 3 recipes   1 on their own price   [Follow here too]
      Omelette
      Carbonara
      Aioli   own price
  • Use — fills the add-ingredient form with this name and price. You type the amount and nothing else.
  • Follow here too — puts every row that still carries its own price onto this one. Appears only when there is something to take on.
  • Delete — forgets the entry. Nothing is zeroed: the price it was costing at is written onto the rows that followed it first, so they carry on at the number they had, now as their own.

Nothing starts following on its own. Recipes you costed before any of this keep their prices exactly as they were. When you are ready, press Follow the pantry everywhere at the bottom of the panel — it says how many rows it will take on and how many of them change price.

Two things worth knowing

  • Renaming is shared too. Rename a following row and you rename the entry, so every recipe following it shows the new name. Rename onto a name already in the pantry and the two merge, keeping the newer price — every row that pointed at the old one moves across.
  • A price you typed is never overwritten. The autocomplete only fills the price field when it is empty, or still holds a value the pantry put there.

4. Batches: things you make ahead

Every recipe is one of two things, and the Recipe panel says which:

  • a Dish — sold on the menu, divides into portions, carries a menu price;
  • a Batch — made ahead and used inside dishes (stock, sauce, pastry, pickle), with no menu price of its own.

The difference is what it makes. A dish makes portions, because a portion is what gets sold. A batch makes whatever it actually makes: set Makes to 1200 ml and your romesco has a known cost per millilitre, so a dish can take 80 ml of it and be costed properly. Nobody has to invent a portion size for a sauce or guess what fraction of the pot went on the plate.

Once a recipe is marked as a batch, an Add batch panel appears in your other recipes. Pick it, say how much you use, and it lands as a row priced at what that batch currently costs to make.

That price is live. Edit the batch — a new stock price, a different quantity — and every dish built on it re-costs, however many levels deep. You cannot give a batch row a price of its own, because a batch is the other recipe.

Scaling and changing what a batch makes

  • Scaling is safe. Double the ingredients and double what it makes; every dish drawing on it keeps the 80 ml it asked for, at the same cost.
  • Correcting the amount — 1200 ml to 1000 ml — moves nothing else. Dishes still take the 80 ml they asked for, now at the higher price that less sauce from the same ingredients is worth.
  • Changing the measure across families — a batch first written as 15 portions, later declared as the 1200 ml it always was — re-expresses every row that uses it as the same share of the batch, so one portion becomes 80 ml. You are shown exactly what will move before anything does, and every dish ends up costing precisely what it did.

Loops are prevented, not survived

A batch that would end up containing the recipe you are editing is simply not offered in the picker. Deleting a recipe, or turning it back into a dish, is refused while another recipe uses it — and it names which ones.

5. Menu price, GP and COGS

Every recipe is priced from the moment it has a cost. It starts at 80% GP, and a dish is always in one of two states:

  • Tracking a target (the default). The price is worked out from the cost, so adding an ingredient moves the price and your margin holds. The note reads Suggested from 80% GP.
  • Pinned to a price. You typed a price, so it stays put and the margin gives instead. A rising cost shows up as a falling GP — which is exactly what you want to see. The note reads Price set by you.

Typing a target hands the recipe back to tracking. Typing a price pins it. Clearing the price field releases it again. The target is stored per recipe, so one dish at 65% does not disturb the rest.

The arrows beside the price move it in 50c steps, to the next round half rather than adding half a dollar to whatever is there: press up on $8.37 and you get $8.50, not $8.87. The keyboard's up and down arrows do the same thing. Nudging a price pins it, exactly as typing one does. You can still type any price you like, to the cent.

GP or COGS — the same fact, two ways

UK kitchens quote gross profit; Australian ones quote cost of goods sold. They are complements:

GP% + COGS% = 100

70% GP is 30% COGS. Quote as switches which half you are looking at — it never moves a price you have set, it restates the same margin from the other end.

GP here is the hospitality sense: gross profit as a share of the selling price, not a markup on cost.

price = cost / (1 - GP/100)

$3 of food sold at $10 is 70% GP. Suggested prices round up to the next cent, so the margin you actually achieve is never below the one you asked for. A price you type is kept exactly as typed.

Selling at a loss is shown, not blocked: a price below cost gives a negative GP in red and says what you are losing per portion. Sometimes that is the decision — it should just never be a surprise.

GST and VAT

Tick Menu prices include n % GST / VAT and the menu price is treated as what the customer pays, with GP figured on the revenue left after tax:

revenue = price / (1 + GST/100)

A $7.50 dish at 10% GST is $6.82 of revenue, so a $2.12 portion is 68.9% GP — not the 71.7% the tax-inclusive figure suggests. The rate is yours to set.

It is off by default, because turning it on changes what every existing recipe reports. Toggling it never moves a price you have set: the customer pays what the menu says; what changes is how much of it is yours.

Ingredient costs are taken as entered. If you claim GST credits on your inputs, enter what you pay ex GST so the two sides line up.

6. Measures and what converts

An amount and its price do not have to be in the same measure — 750 g of mince priced at $8.90/kg is normal shopping. They do have to belong to the same family:

FamilyMeasuresConverts within itself
Countunit—
Bunchbunch—
Massg, kg1 kg = 1000 g
Volumeml, L1 L = 1000 ml

The price-per selector only ever offers you compatible measures, so grams can be priced per kilo but never per unit.

Three deliberate refusals

  • Mass and volume never convert into each other. That needs a density for every ingredient, which this app does not track. 100 g of flour priced per litre is refused outright — not estimated, and not quietly rewritten into a measure that happens to parse.
  • A bunch is not a unit. Half a bunch of parsley is not half a stem, so the two sit in separate families and the app will not guess a rate between them.
  • No spoons, cups or imperial weights. Their sizes differ by country — a tablespoon is 15 ml in the US and UK but 20 ml in Australia — and a recipe costed with the wrong one is wrong without ever looking wrong. Metric only, by choice.

On money: costs are kept at full precision and rounded to cents only when shown. Rounding each ingredient first would lose real money on fine measures — flour at $0.0018/g rounds to $0.00 a gram, but 500 g is $0.90.

The currency picker is a display symbol only. There is no conversion attached, so $ serves for Australian dollars as it stands.

7. Keeping your work

Everything saves itself as you type, into the storage of the browser you are using. That is the whole database. There is no server, so nothing is uploaded — which cuts both ways.

The only copy is on one device. Browsers evict storage. Safari clears it for sites you have not interacted with for about a week, though adding the page to your Home Screen generally exempts it. Clearing your browsing data will take your recipes with it. Export all now and again, and keep the file somewhere that gets backed up.

  • Export all — the backup. One file with every recipe and batch, the whole pantry, and your tax and margin settings. The links survive it: a dish still knows which batch it draws on, and a row that follows the pantry still follows it, because the batch and the pantry are in the same file.
  • Export JSON — saves the current recipe on its own, for sending one dish to someone. Prices are today's, resolved, and the links are left behind: a pantry entry's id means nothing on another machine, so the recipe arrives on prices of its own.
  • Export CSV — a spreadsheet of the ingredient list, the total, the cost per portion, and the menu price with both GP and COGS. For sending to someone who wants numbers, not the app.
  • Import JSON… — reads either kind of file. A single recipe is added alongside your others; put it on the pantry with Follow the pantry everywhere if you want it to track. An Export all file is a restore, so it replaces everything you have here — it asks first, and says how much of each it is about to swap.

Moving to a new device or address

Recipes belong to the exact web address you were using, so they do not travel with you. On the old one, press Export all. On the new one, Import JSON… and pick that file: recipes, batches, pantry and settings all arrive together.

To move one dish rather than the lot, Export JSON on the old one and Import JSON… on the new. That one arrives without its batches or its pantry links, which is why it is the wrong tool for moving house.

One thing not to do: never put exported recipes in a public web folder. The app itself is harmless to publish; an exported costing would be readable by anyone with the link.

8. Signing in, and a second device

Signing in keeps a copy of your recipes on the server as well as in this browser, so a phone in the kitchen and a laptop in the office see the same list. It is optional. Everything works without it, exactly as before.

The Sign in button is in the grey bar at the bottom. Beside it, a word says where things stand:

It saysWhat that means
Saved in this browserNot signed in. Nothing leaves this device.
SyncedEverything here is on the server too.
Saving…A change is on its way up.
Saved here — server unreachableOffline. Your work is safe locally and will go up next time.
Changed on another deviceTwo copies disagree. See below.

Your recipes are still saved the instant you type them, signed in or not. Nothing waits for the network, and there is never a login screen in front of a working app.

Signing in does not appear on a phone using the kitchen's local address (one that looks like 192.168.…). That connection is not private enough to carry a password, so the app stays local there. Use the ratcogs.com address to sign in.

When two devices disagree

Change a dish on your phone while the laptop is offline, then bring the laptop back, and both copies have moved. There is no safe way to merge that automatically — the two can differ by a deleted recipe and a re-priced ingredient at once — so the app stops and asks, with a bar at the top:

Your recipes were also changed on another device.
[ Keep this device's ]  [ Use the other device's ]

Nothing is sent anywhere while that bar is showing, so neither copy can be overwritten by accident. Whichever one you do not keep is saved in this browser first, so a wrong click is recoverable rather than final.

The bar says which situation you are in, because they are not the same question:

The bar saysWhat happenedWhat to do
Changed on another deviceBoth copies moved since they last agreedKeep whichever has the work you want
The copy on the server is older — restored from a backupSomeone put an earlier version backKeep this device's only if the restore was a mistake
No longer on the serverThe server's copy is gonePut this device's back re-seeds it

That middle one is worth reading twice. If the older copy was restored on purpose, choosing Keep this device's undoes the restore.

Signing out

Your recipes stay in this browser. The server keeps its copy, and signing back in reunites them.

9. Quick reference

The Recipe panel

ButtonWhat it does
New DishStarts an empty dish and asks for a name. A dish is sold on the menu and yields portions.
New BatchStarts an empty batch and asks for a name. A batch is made ahead and used inside dishes.
RenameRenames the recipe you are looking at.
DuplicateCopies it, ingredients and all — the fastest way to a variant.
DeleteRemoves it, after asking. Refused while another recipe uses it as a batch.

Why does this row…

SymptomWhat to do
…show — measures don't match?Its amount and price are in different families. Edit it and put both in mass, or both in volume.
…say own price when I asked it to follow?The pantry entry is priced per a measure this amount cannot convert to. Change one of them so both are in the same family.
…not update on my other device?Check the bar at the bottom says Synced. If it says server unreachable, the change is safe here and will go up when the connection returns.
…not change when I re-priced the pantry?It is not following. Edit the row and press Pantry price, or use Follow here too on the pantry entry.
…change in a dish I wasn't editing?It follows the pantry, which is the point. The notice after each change says how many recipes it reached. Press Own price on any row that should be independent.
…appear under Still to do when it looks fine?It draws on a batch that has a gap of its own — most often a yield still set to 1 g. The line names the batch.
…show no menu price panel?The recipe is marked as a batch. A component is not sold, so it has no price of its own.
…reject a decimal I typed?It should not — every number field accepts fractions. Check for a stray character rather than reaching for a whole number.

Where the numbers come from

FigureWorked out as
Ingredient costamount converted into the price's measure × price
Cost per portiontotal cost ÷ portions
Suggested pricecost ÷ (1 − GP/100), tax added, rounded up to the cent
Actual GP(revenue − cost) ÷ revenue × 100
Revenue, with tax onmenu price ÷ (1 + rate/100)
User manual Calculator