Writing

Food halls, festivals, and the bits nobody demos.

Written from inside a working food hall. Problems we have hit, arithmetic we got wrong the first time, and the questions worth asking any supplier — including us.


The sitemap entry that was its own address twice

One of 558 addresses in a rival’s sitemap was their domain pasted after itself. It answered 404, and the honest count is 557 read, one excluded, not all.

Read it →

Three copies of every page and one read

A rival’s sitemap listed 1,611 addresses. They were 558 pages in three locale folders. Reading all three triples the work and makes a page count a lie.

Read it →

Paid out automatically, or recorded and owed

A rival pays every vendor out from the one transaction. Our payouts screen records what each kitchen is owed and says the transfer is yours. Both are ticks.

Read it →

The word was there and it meant the other thing

Three blank cells held after a whole-site read because the word turned up meaning something else: a rota that was a bookings brief, invoices sent to guests.

Read it →

We wrote no kitchen display, and they route to one

Our post about the QR ordering product we copy said it had no kitchen display. Their site routes orders to the venue’s own screen or printer. Corrected, dated.

Read it →

A topic heading with nothing under it

A rival’s help centre lists a topic called Kiosk, and opening it says no items found. Whether that is their site saying they sell one decides a cell.

Read it →

Printed at the pass is not silent about the kitchen

A rival’s orders print a ticket at each dispense point. Our table left their kitchen-screen cell blank, as if their site said nothing. It says something else.

Read it →

The opening paragraph already said click and collect

Our post on one rival listed order-ahead slots as something they lack. Its own first paragraph named their click and collect. One post, two records at odds.

Read it →

Sold out is not a stock count

A rival’s site says a sold-out item is instantly removed from the menu. That is availability. Three different things get called stock, and only one is this.

Read it →

A labour figure sourced from somebody else’s tool

A rival’s case study reports an eighteen percent labour cost and credits another rota product for it. A result measured elsewhere is not a feature.

Read it →

The claim was the whole site. The check was six pages

A comparison post said a rival described no stock management anywhere. Two re-reads agreed, both from the same six pages. The proof was in the other 73.

Read it →

The blank cell that was ours, not theirs

In our comparison table a dash means the rival’s own site does not say. Four of one rival’s dashes were wrong, in the direction easiest to miss.

Read it →

A rival’s tick is a pointer, not a source

Another comparison site ticked five features for a company we also compare. Checked against that company’s own pages, four held and one did not.

Read it →

Two halves facing opposite ways

Two rivals are a half on recipe costing. One counts stock without recipes; the other has recipes and variance with no costing. One letter cannot say which.

Read it →

Our row says the till cannot trade offline

The last row of our comparison table is a cross in our own column. What it means, what the kitchen screen keeps when the wifi goes, and what to ask a supplier.

Read it →

A number about somebody else has a date on it

Our comparison post said a rival had twenty-seven case studies. Their sitemap now lists twenty-eight. The claim carried a date, so the re-read was the job.

Read it →

Modified today, said twenty-six pages at once

A rival sitemap stamped today on its home, pricing and terms pages together. That is a build date, not a change. Ours moves a date only when the page does.

Read it →

The filler page your sitemap told the crawler about

A rival sitemap lists thirteen pages whose addresses are Latin filler left by the site builder. A sitemap generated from the route table cannot leak one.

Read it →

One date cannot speak for seven rivals

Our comparison pages once shared one read date. Re-reading one rival found two wrong cells; re-dating all seven would have claimed reads that never happened.

Read it →

Blocked is not dead, and it is not ok either

Our nightly check of the shop links called three working links dead and one bot wall fine. A status code has two answers. The question needed a third.

Read it →

Four recordings, and a length that read as infinite

Our demos page hosts four real screen recordings and told crawlers nothing about them. Each clip now has an address and a description, every number measured.

Read it →

A text-receipt button the venue could not honour

The till offered to text a receipt on every deployment, including ones with no way to send a text. The button now appears only where a text can actually go.

Read it →

A Back button that does not add a page

The tester asked for a Back on every page reached from inside the app. We added one that steps back through history, so Back, Back, Back never builds a stack.

Read it →

A dated deal is not a permanent one

Eight findings on one discount sheet: a deal with dates told it had none, a start in the past, a save that said nothing, and paused rows that looked disabled.

Read it →

Signing in should land you where you were going

Open a link to a report, sign in, and the office dropped you on the dashboard. The address bar lied while the form showed. Both fixed; the link now lands.

Read it →

A glossary nobody could point into

Our glossary held twenty-six definitions and none had an address, so a link could only reach the top of the list. Every term has one now; five pages link them.

Read it →

The menu that offered pages a kitchen could not open

A kitchen’s avatar menu listed two owner-only pages, and tapping either dropped you on the dashboard you were already on. Three rows on one screen, one filter.

Read it →

Total paid £12, and the five that went back unsaid

After a part refund the receipt still read Total paid £12.00, and the till’s refunds list never showed it because it filtered by status. Both read the sum now.

Read it →

The dropdown styled before dark mode existed

A rule written for one old finding forced white option lists, and on Windows a fixed background beats the colour scheme. Two rows honestly marked not fixed.

Read it →

The language pill that sat on the title

Open the office in a Hindi browser and the offer to switch language sat over the Menu screen’s heading. The page now moves down by the pill’s measured height.

Read it →

The logo that centred itself off the top of the screen

A short browser window cut the sign-in logo in half and nothing could scroll to it. One centring rule was the cause; three more sign-in rows went with it.

Read it →

A typed zero added one, and the till said nothing

Type 0 then tap a dish and the till added one. A seventh digit vanished. 150% off took the whole bill. Three silent clamps, now three sentences.

Read it →

Wasting a basket now asks why

Wasting an unpaid basket on the till was one tap and no record. It asks for a reason now, from the nine the kitchen logbook uses, so the report can count it.

Read it →

Two open tabs called Table four

The till let two open tabs share a name, and the Open tabs screen listed unpaid orders instead of tabs. One naming rule and one card fixed both.

Read it →

The snippet that compared seven and named none

Our comparison page’s search snippet said “seven hospitality systems” and named none. A searcher types a name, so the description carries all seven now.

Read it →

The question mark, and the number you typed over it

A dish with no recipe showed an orange ? instead of a cost. There is a box to type one now, and the recipe still wins the moment a line is linked.

Read it →

Paid out £500 from a drawer holding £40

The till’s cash route took any amount while the Money screen put the drawer at £40. One sum feeds both now; a pay-out above the count is refused, quoting it.

Read it →

The arrow that moved both dates

Two findings: the forward arrow changed both pickers, and the P&L jumped to a random date. One control, drawn to look like part of the boxes beside it.

Read it →

A FAQ block for questions the page never asked

Structured data lets a page tell a search engine which questions it answers. Ours would have named four the page never posed. So the page asks them now.

Read it →

Saved, said the screen, for the rest of the afternoon

A confirmation that never leaves stops confirming anything. Four rows on one settings page: messages that stayed too long, said too little or described no save.

Read it →

The allowlist that was a date, not a rule

Twelve findings read “Your account doesn’t have access to this”. One list in the gate named fourteen settings a kitchen may change, and nothing added since.

Read it →

The section you removed stayed on the menu

Remove a menu section in the back office and the till and the QR menu went on showing it, dishes and all. The sections table was never where the grouping lived.

Read it →

Check your inbox, it said, and nothing could reach it

The password reset said the email was on its way. The mail service had refused every one for days. A route that cannot know the answer should not pretend to.

Read it →

The QR code one mail app drew and the other left blank

The receipt email carried its QR code as inline vector art. One mail client drew it; the one most guests use drew nothing. A PNG is what every client draws.

Read it →

The form whose only save button was the Enter key

Type a new menu section, tap Done, and nothing was created. Adding only happened on Enter, and the one visible button threw the typed name away.

Read it →

The screen that said you had no kitchens

Sign in, land on Store, and the office told seven live venues they had no kitchens yet. The list it read had not arrived. An empty answer is not an answer.

Read it →

A requisition filed under another company’s supplier

Raise a stock request naming a neighbour’s ingredient and the purchase order landed in their order book. Receiving it would have moved their buying price.

Read it →

The error that quoted the database back at you

An unexpected fault answered with the raw database statement and its values, on a route open to anybody. A chosen sentence stays; an accident gets one line.

Read it →

Does dish 1,234 exist? Answered by a status code

Put a dish on a menu by its number and a real dish answered differently from a made-up one, so ids could be counted. Two obvious fixes broke meal deals.

Read it →

The fix that moved the gap instead of closing it

We fixed one of two places a refund figure was built, and for a release the receipt greyed out a refund the server would allow. The sweep is now a test.

Read it →

Two screens, one drawer, and £44 between them

The till said the drawer should hold £60, the office said £16, and the drawer held £56. Each screen had counted what the other never read. Now they agree.

Read it →

Full refund, part refund, two different card totals

Our card reconciliation took a full refund off the day’s card total twice and a partial one off once. Right on the common case, so it lasted.

Read it →

The preview showed fifty instalments. It saved twelve

A payout preview had no ceiling on instalments and the raise capped at twelve, then dropped the dates it was given. Now both refuse the same things.

Read it →

A discount on one line stranded money on the others

Refund a discounted dish and the till then refused to return the rest of the bill, short by exactly the discount. The sum had three homes. Now it has one.

Read it →

The sold-out sheet read other people’s stock lists

Marking a dish sold out answered with its name whatever kitchen owned it, and the same route walked another company’s stock list by number. Three fences now.

Read it →

The honest count was the one that looked wrong

A refunded cash sale left the drawer twice: once when the order stopped counting, once when the refund arrived. The manager who counted right read as over.

Read it →

One statement, four payouts, four lots of commission

A monthly delivery statement was billed in every weekly payout it touched. The fix put it in one week, then showed the hole that opens when it arrives late.

Read it →

The journal balanced and was still wrong

Our bookkeeping export posted VAT on £4 a customer had been handed back. Both sides agreed to the penny, so the balance check missed it. Now it refuses.

Read it →

The helper kept every failure, the callers kept one

Save ten rows, two refused. The pool collected both; three screens threw all but the first away and showed one bare message. Now they say how many landed.

Read it →

The gate checked the venue the request named

A vendor could zero-rate another kitchen’s dish or rename its menu section, because the shared check only read venues a request named. Two routes named none.

Read it →

The gate blocked a venue over work that did not exist

Our go-live worklist counted a hidden dish and a box of gloves as menu items, raised three blocking jobs over them, and held a venue back from trading.

Read it →

Test the two screens against each other, not the query

The hub said 64 dishes on sale, the Photos screen said 59, same venue, same minute. The fix was one import. The test now compares the two screens.

Read it →

The file it learned from had the same bug

The nudge that burned seventeen weeks learned its rules from an older file. That file had it too, found with one shift on the rota and nothing lost.

Read it →

One cap, three right answers

Three reports totalled their newest rows and called it everything. One now sums in the database, one refuses the window, one says it is capped.

Read it →

Saved, it said, and one row kept the old rate

Set two VAT rates, one of them not a UK rate. The route dropped it, saved the other, and said saved. Found three times in one morning, then made a rule.

Read it →

The stamp that ate a closing tag

Our build stamps every script address with a hash. Written inside a sentence, one address matched too far and the page shipped with an unclosed tag.

Read it →

Nothing was expensive, it was all waiting

Seven purchase orders took two seconds to list. Three reads each, one after another, is twenty-one round trips. Read each thing once: seventy milliseconds.

Read it →

A search found one button. The screen found the bug

A source search for unguarded buttons found one of hundreds. Opening the screen and pressing twice found a supplier created twice, and totals that split.

Read it →

Seventeen weeks marked asked, and nobody was asked

Our availability nudge stamped a week as asked before checking it could send. With no text provider, every week burned quietly, seventeen on the live venue.

Read it →

Their chef on my rota, at their pay rate

Four rota routes named a person in the body, where our venue gate never looks. A manager of one kitchen could log a shift for another company's chef.

Read it →

Two taps, two codes, both spendable

A double press on Issue voucher made two vouchers with two codes, each worth money. The fix went into the one place all fifty-eight dialogs pass through.

Read it →

The list had a lid, and the busy screens fell off it

Eight of fourteen slow screens gave no reason at all. The browser keeps 250 resource timings and silently drops the rest, so the deepest screens went blank.

Read it →

A call nobody waits for is not a wait

The hub reported 856 of its 860 milliseconds as API time, naming a call the screen never waits for. A background report had been counted as the user’s wait.

Read it →

The gate was one hop, and it still read as three

The way in cost up to 73% of server time on six screens, in steps that read like one, two or three database hops. Measured three ways, it was always one.

Read it →

It said it stopped, and three lanes were still writing

A bulk save ran four writers at once and said it stopped on the first refusal. Three lanes kept going, so the count was wrong and the sentence false.

Read it →

The courier was already on the road

A courier is on the road the moment the partner says yes. Two writes after that were unguarded, so a failed write read as a failed booking, inviting another.

Read it →

A question beats a debounce

Refund, void and cancel sit outside our double-tap guard on purpose. Each asks a question first, and a question stops a wrong first press, not only the second.

Read it →

The disable has to be the first line

The register’s forty buttons matched none of the office double-tap guard. Following the sale to the four buttons that send it found each one already safe.

Read it →

One browser’s good manners are not a lock

A disabled button is one browser being polite. Two tabs or a retry still interleaved a delete and its inserts and doubled a venue’s hours. One batch fixed it.

Read it →

One brace adrift, and two loops vanished

Our source scanner blanked the start of each interpolation but left its closing brace. A brace walk stopped early, and two long loops vanished from the count.

Read it →

Fix one route, then count its siblings

One venue route checked the row existed, then read it. Two like it were fixed months ago. Counting the family found eight more with the same two waits.

Read it →

One hop, whichever door you came through

A helper looked up the hall itself when nobody handed it one, costing a wait. The screen, the save, the crons and the webhooks all came through it.

Read it →

The seconds were the morning’s; the shape was ours

One morning the database answered slowly and nine screens went red at once. The milliseconds belonged to the morning. The waits in a row were ours to fix.

Read it →

A probe that did not answer is not a no

We asked whether one page’s burst of calls queues inside the server. The probe landed on five different machines. Inconclusive was recorded as inconclusive.

Read it →

Zero diff lines before a byte shipped

A speed change to eight routes should alter nothing a screen receives. We captured every answer before and after on one seed and compared them byte for byte.

Read it →

The columns the screen never reads

The Menu screen was one hop deep and three reads wide, and still slow from London. It was carrying 197 KB of columns it reads four fields from.

Read it →

A screen that asked again after each draw

The commission page took nearly four seconds and its slowest call one and a half. The rest was the screen waiting to draw before asking its next question.

Read it →

Start it first, take it last

A card settlement route waited four times. One of the waits was for a vault that depends on nothing. Our first fix put it in the wrong wave and kept it slow.

Read it →

The second check a money screen pays for

Most routes wait once at the front door. Routes that touch money wait twice, because a venue may have held that action back from a role. That hop is deliberate.

Read it →

Awaited in the order it was written

The price watch read its rows, then counted them, because that is the order the lines were typed. Nothing needed the rows first. One wait became none.

Read it →

One hop deep and twenty-two wide

The till menu waited once for everything, and the tests said so. From London it still took nearly two seconds. Depth was fixed. Width was the cost.

Read it →

The fallback you hope never runs

We moved eleven reads into one request and kept the old path for the day the batch is refused. A spare path is only safe if it answers the same thing.

Read it →

The sweep that could only find what it guarded

A check walked every screen looking for unprotected Save buttons, using the protection own selector. By construction it could not find one outside it.

Read it →

The default no test was holding

Thirteen tests covered the write pool, each setting its lane count by hand. Set the default to one lane and all thirteen pass while the product goes serial.

Read it →

The warning that did not say which door

Two comments said an API rejects a schema keyword. A third file still used it. We nearly removed it there before checking which API door the comments meant.

Read it →

The time scaled with the distance

One route timed from four cities. Beside the database it took 0.4 seconds; from Europe nearly three. A slow query does not do that. A chain of waits does.

Read it →

A question the screen never needed answered

The kitchen screen settings call asked which hall the venue is in. The front door had already answered that and handed it over. Three waits, two for nothing.

Read it →

The board named the screen; the count named the call

The speed board said the till first call was slow. Counting its statements said why: four reads in a line, each keyed on one venue, none needing another.

Read it →

Three hops on a wire costing two seconds each

One screen took five seconds, and two of them were a single trip to the database. We cannot shorten the wire. We can stop crossing it three times in a row.

Read it →

The fence first, then everything at once

A money export waited eight times for figures that all hung off one answer. The check on who may see them stayed first. Everything after it runs together.

Read it →

Two different pages, one line on the card

We named three screens the speed board had been merging, and the card showed two rows reading the same word. A tidy label had erased the difference.

Read it →

Five red rows and one job

The first morning anyone used a release, five screens went red on the speed board. Four had a reason already written down. One was a fix.

Read it →

The repeat read we kept

We removed a doubled read from one route and kept the same doubled read in the next. Whether a repeat is waste depends on what happened in between.

Read it →

Measure from where your customer stands

Our test machine sits beside the database and flatters every route. Today it routed through Europe and its numbers matched the customer for once.

Read it →

A rule the tool enforces beats a rule you remember

Fourteen descriptions rewritten to a limit, every one under-counted by twenty characters or more. The script that refused to save them was the fix.

Read it →

The page that had no row on the board

We track the load time of every screen. The guest ordering page had no line of its own, because it is served at the root of its own address.

Read it →

One supplier said no, and five never heard

A kitchen sent its week of orders to six suppliers. The second one refused, and the four behind it were never contacted — with nothing on screen to say so.

Read it →

A quiet night and a failed one look the same

A job that asks staff for their availability runs every hour. If the database refused, it returned the same result as a night with nobody to ask.

Read it →

A rate saved in pieces

Commission bands were cleared and rewritten one at a time. Anything reading in between saw a rate with no bands, and charged a different number.

Read it →

Six of seven findings were the tool

We wrote something to find a class of bug, it reported seven, and we had nearly fixed all seven before noticing that six of them were already correct.

Read it →

A fix that never reached the fourth screen

A shared button guard was wired onto three surfaces and never loaded on the fourth. Nothing was red. The screen that needed it most was the till.

Read it →

The invoice line that was not on that order

An invoice typed against the wrong purchase order. The line named belonged elsewhere, so nothing was written — and the screen still said saved.

Read it →

The screen was slow and the query was not

A dashboard measured 926ms against a 300ms budget. The route behind it answered in 250ms. Which page is slow and why it is slow are two questions.

Read it →

Asking the kitchen the same question every morning

Items switched off yesterday are not back on today. Somebody has to be asked — and the hard part is what the screen does with the answer.

Read it →

A push that half landed is worse than none

Changing a dish once and sending it to every kitchen is the point of a group menu. The hard part is what it says when only some of them took it.

Read it →

The number moved and no row explained it

A staff profile shows more hours than last time and nothing on the timesheet explains it. That is not rounding. Two screens are asking different questions.

Read it →

Cancelling an order you did not place

A purchase order is a promise to a supplier. We found nine ways a trader could reach another’s orders: cancel one, mark it received, or take it as theirs.

Read it →

Your company and your kitchen are two different fences

Multi-site traders have two boundaries: the business and the unit. A system can guard one and leave the other open, and from outside the two look identical.

Read it →

One key for the cupboard, not for every shelf

If you can open one ingredient, can you edit anyone's pack sizes? An address with two numbers in it asks that, and the answer must be checked at both levels.

Read it →

Prove the alarm by setting it off

We wrote a check to catch one mistake, then made that exact mistake on purpose. The check stayed green. An untested safeguard is a note saying one exists.

Read it →

Signing in is not the same as getting in

A new account signed in perfectly, and every screen behind it was empty. Two failures that look identical down a phone line, and they need different fixes.

Read it →

The upload worked and nothing after it did

A photographed invoice uploaded fine and then vanished from the list it had joined. A first step that succeeds is the most misleading kind of broken.

Read it →

The edit screen is the other front door

We checked who could create a supplier invoice and never who could change one. The edit screen is a second way in to the same record, and nobody audits it.

Read it →

The second check ran on the first one's mess

Three checks in a row on one till. The second measured nothing, because the first had changed what it was checking. It looked like a pass. It was a blank.

Read it →

A door that was never built also says no

Page not found means both you may not see this and there is no such thing. We nearly logged a missing feature as a working security check. They look alike.

Read it →

A count that is the same on every page

We counted links to one page across our site and every page scored one. The footer put it there. A number with a floor you forgot about is not a measurement.

Read it →

A caveat that stopped being true

The cash only sticker outlives the card machine by about two years. An honest limitation becomes a lie the day you fix the limitation, and nothing tells you.

Read it →

A price with a date on it

A figure nobody can re-verify should carry the day somebody last looked. Dated and honest beats fresh and invented. Refreshing the date is not checking.

Read it →

Renumbering a list hides the gap

Drop step four and renumber the rest, and every printed copy and trainer points at the wrong step. Numbers are addresses. A gap in them is information.

Read it →

Read the label, not your memory

We published a number from memory and it was six out. The figure had been on screen minutes earlier. A claim is as reliable as what it was copied from.

Read it →

The same row, read twice

Two parts of one job each fetched the same fact, and neither knew the other had it. The waste is invisible until you count the trips instead of the work.

Read it →

Checking again is not duplicated work

The second check on a till float looks like waste until the first one is skipped. The test is whether the checker would still catch the mistake on its own.

Read it →

Testing a fix where the problem cannot happen

A change that saves ninety milliseconds in the venue saves five on the bench, and the bench is where most people check. No difference is not no improvement.

Read it →

"Not found" and "could not look" are different answers

A failed lookup that returns an empty result reads like a real absence. One means try again, the other means stop. Your screens should not have to guess.

Read it →

"Slow" is three different problems

A screen that takes half a second is waiting on the work, the distance, or the drawing. They have three different fixes, and guessing which one costs a week.

Read it →

A cap that invents a number

Clamping an impossible value to a ceiling stores a figure nobody measured. One reading that should have been refused moved a page average a hundredfold.

Read it →

The average that one reading decides

Three readings of one screen: 341 ms, 526 ms, and one that was nonsense. The mean said forty seconds; the middle value had not moved. Averages are a choice.

Read it →

The demo on your website is not your venue

Our example menu sits in two marketing pages, loads in tabs nobody reads, and reports its speed into the same board as real ordering screens.

Read it →

Write down what you checked and found nothing

A number over budget got a proper investigation and had no fault behind it. Writing the dead end down took ten minutes and spares every later look at it.

Read it →

A filter that throws away good readings

Dropping bad data is easy to overdo. A screen drawn while nobody was looking is a meaningless number. One where the phone locked afterwards is not.

Read it →

The till was downloading the back office

One stylesheet for the whole product meant the register waited for rules about screens it cannot reach. Splitting it took 112 KB off a cold till.

Read it →

The chip that went grey and said nothing

The worst front-of-house bugs throw no error. A low-stock marker lost its colour and every screen still looked normal. What catches that is not a test suite.

Read it →

A lock that keeps everyone out is also broken

Testing that a stranger cannot read another kitchen's takings is half the test. The half people skip is checking the person who should get in still does.

Read it →

One basket, five kitchens, five different waits

A guest buying tacos and a matcha should queue once and pay once. What that means underneath, and the part no software fixes: five kitchens, five speeds.

Read it →

When the hall is open and the kitchen is not

A hall has opening hours, each kitchen its own, and a breakfast menu a third clock. Three clocks disagreeing is how a guest meets an empty page at 11:31.

Read it →

The upload that cancels what it left out

A delivery platform takes your offers as one file and removes anything it leaves out. Send four and you may have cancelled a fifth somebody else set up.

Read it →

The column no partner can fill

Somebody asked for a dashboard with impressions and return on ad spend. We looked across 145 pages of a delivery platform's documentation. They do not exist.

Read it →

A name your code makes up as it runs

We cut 112 KB off the register by removing styling it can never use. It nearly deleted the rule turning a low-stock chip amber, a name written down nowhere.

Read it →

The faster version that read before it asked

A screen asked the database three questions in a row. The quick fix asks them at once. It also fetched a venue’s data before checking you may see it.

Read it →

The tidy-up that took the wrong thing

Removing what nothing uses is good practice, until it is done by pattern rather than structure. Ours deleted seven working rules and the build said nothing.

Read it →

Every load of that screen was the first one

A till opens at eight and runs until close. A guest’s phone meets your menu once and never returns. Averaging the two gives a number that describes nobody.

Read it →

What a guest’s phone pays to see your menu

We measured our guest ordering page on production instead of guessing: about 239 KB over 30 requests, every scan paying it. The number and what we did.

Read it →

The page everyone mentions and nobody points at

Seventeen articles about QR ordering and not one linked to the page that explains it. Venues have the same gap between what staff say and what is written.

Read it →

Two covers is not a trend

Our speed board will not call anything a problem until it has three measurements. That floor is not pedantry. It stops a quiet Tuesday rewriting the menu.

Read it →

Last week’s average is about last week’s kitchen

A seven-day average across a Wednesday change blends two kitchens. Our speed board now shows the current one alone, and that changed what we worked on.

Read it →

Two taps, two tabs

A button that does nothing visible for a second is not a polish problem. On food hall wifi it is a second record you did not want, and the guest has no idea.

Read it →

An error should say what to do next

Your order didn’t go through. But was my card charged? Is my basket there? Do I try again? A message answering none of those creates a queue at the till.

Read it →

A screen that waits before it opens

Tap a button, nothing happens, then a panel appears. It waited for the server before showing itself, and every silent second reads as a broken button.

Read it →

A choice that waits for the server to agree

Staff tap the day they can work and the button waits for the server to agree. On one bar of signal that is two seconds of nothing, so they tap again.

Read it →

A guard that was never armed

The line said: if this button is disabled, do nothing. Nothing in the codebase ever disabled it. It sat for months looking like protection, never firing.

Read it →

The browser picks the picture by what you tell it

Offering a phone several sizes of one photo means labelling each with its width. We typed one wrong, every page looked perfect, and only the file showed it.

Read it →

Your logo is on every page, so its weight matters

Our brand mark left the drawing tool at 50 KB — 21.6 KB on the wire, every page’s header. Halving it changed nothing you can see; the proof was a rendering.

Read it →

The share button that copied nothing

Tap Share with clipboard permission unasked and the link is not copied, with nothing on screen to say so. Two refusals that look identical in code.

Read it →

A tab bar that scrolls away only works from the top

Tap the tab you are on to jump to the top; come back to a list where you left it. Both were impossible in our staff app until the tab bar stopped scrolling.

Read it →

Going back should not erase what you typed

Our sign-up asks a venue for its name, kitchens, hours and menu. A call comes, the tab closes — all gone. Now it is kept on their device for a week.

Read it →

The line that fenced nothing and broke everything

One line added to a purchasing screen was meant to scope it to the right company. It computed a value nothing used and read a thing that was not there.

Read it →

A rival's buying contacts are not your data

A hall holds kitchens from different businesses; the money is obviously kept apart. Less obvious is the supplier list: who they buy from, at what price.

Read it →

An empty screen should say which empty

Nothing to order, or nothing loaded? A purchasing screen that goes blank can mean either, and a manager cannot tell them apart. The fix is words, not spinners.

Read it →

"Not switched on" is not "broken"

A feature not yet set up and a feature that has fallen over look the same to whoever is standing there. They need different words and different colours.

Read it →

The check that locked itself out

A test fired four hundred operations and reported nothing broken. Most were refused at the door, and the reassuring number came from the handful let in.

Read it →

The column you forgot the table had

A back-office screen showed a live PIN and a security token, because its query asked for every column, not the ones it needed. A shortcut kept its promise.

Read it →

A fallback that fired every time

Our ideas board labelled every post with an email instead of a name. The code asked for a field that does not exist, so the fallback ran on every request.

Read it →

Asking again should not cost you the answer

Press again and the first answer vanished, even when the second try failed. An ordering bug in our allergen tool: nothing goes until its replacement exists.

Read it →

The error that blamed your dish

Four situations, one error message: the dish has changed since it was made. True in one. Naming the wrong cause is worse than admitting you do not know.

Read it →

Safe for a reason nobody wrote down

A line in our menu importer updates a dish without naming the venue. Safe only because of a function sixty lines away. Correct by accident of context.

Read it →

A screen that could never be late

Anything over 300ms gets made faster. Four back-office screens could never appear on the board, however slow. What a report cannot see is the danger.

Read it →

The phone till and the desktop till disagreed

The same register on two devices measured its speed two ways, and a code comment was true of three screens of nine. How a good-faith claim stops being true.

Read it →

Fix the gauge before the engine

An hour after the page-load numbers told the truth, they pointed at a screen making two round trips where one would do. Fix the gauge before the engine.

Read it →

When a report says nothing, suspect the report

A coverage check said none of our scheduled jobs had been tested. All of them had. It looked for the wrong shape; a real gap would read as the same zero.

Read it →

One probe is not a failed deploy

A release went out and the check said the old version was live. Four seconds on, it was fine. One reading is never enough to act on, in code or at a fridge.

Read it →

A floor measured on more than you can use

Our upsell engine waits for sixty baskets before it speaks. Six of them were ones it could not learn from. Why a refusal must name the real number.

Read it →

The pre-order that waits its turn

An order placed at midday for seven o’clock should not sit on the pass all afternoon. Ours waits off the screen and appears on each kitchen’s own lead time.

Read it →

The money balanced, and nobody had asked

A split bill should add up to the bill. We had the check, and for months nothing called it. Then we ran it across every paid order on the live database.

Read it →

Running the job, not just the clock

We proved our scheduled jobs fire at the right minute, every minute of a week. That is not proof they work. Two had never been executed by anything.

Read it →

Your menu photo is twenty-three megapixels

The photos behind one live menu: 134 images averaging 1.7 MB, the largest 4000 by 5739 pixels, one painted into a 34-pixel icon. What that costs on a phone.

Read it →

Who can approve your staff’s holiday

Our rota code let a manager approve time off for anybody, and never asked which venue that person worked at. Why approving a holiday is not a read.

Read it →

A PIN is not a record

Any office account could set any staff member’s till PIN, at any venue. A PIN is not information about somebody. Setting theirs hands over their till.

Read it →

Switching off a till that is not yours

The screen deciding what a venue has checked what kind of account you were, never which venue you named. One word, spelled two ways, made the difference.

Read it →

Eleven waits and a fast database

A screen took 4.5 seconds and every query behind it ran in under ten milliseconds. The fault was eleven questions asked one at a time across an ocean.

Read it →

The reason written next to the code

A comment explained why one database read had to wait for another. The line above it already did what the comment guarded against. A reason is a claim too.

Read it →

The feature nobody used was the broken one

Every write the system makes went to a database to check. One had twelve columns and eleven values: adding a supplier had failed for a month, unreported.

Read it →

A cancelled sale in someone else’s payout

A hall pays kitchens their takings. Ours counted cancelled sales: one kitchen read £470.10 for a month really at £448.60, and paid commission on the gap.

Read it →

Void and voided are not the same word

Three reports filtered out cancelled sales by matching the word void. The status is stored as voided, so nothing matched and one report tripled a promotion.

Read it →

Deleting the paperwork behind a bill

Archive, never delete. We read every delete in the system and found three that destroyed real records — including a delivery that left an invoice owing.

Read it →

Half a kilo you could count but not spill

Our stocktake accepted 2.5kg. Waste and transfers ran the same number through a whole-number step, so half a kilo was refused and 1.5kg took one kilo off.

Read it →

When a picture holds up the docket

We put the venue logo on printed receipts. The code handled every way to fail except one: the server accepts the connection and then says nothing at all.

Read it →

A deadline that turns "maybe" into "no"

A timeout on every outbound call is standard advice and wrong for half of them. On a payment it turns we do not know into it failed, and a retry pays twice.

Read it →

Your neighbour's order is not your order

In a food hall every kitchen is a separate business on one system, so every request must answer whose it is. A guard on the front door misses the window.

Read it →

A short bar is not a bad month

Open a monthly chart on the 13th and the last bar is thirteen days tall beside thirty-day neighbours. It reads as a collapse. It is a calendar.

Read it →

A busy hour built from two orders

A week-by-hour heatmap is the fastest way to see when a kitchen trades. It is also the fastest route to a conclusion drawn from two orders and a coincidence.

Read it →

Deleting a dish that is on last month's orders

Archive, never delete, is easy to write down. Our own Delete on a recipe ran one unconditional statement, and a dish sold a thousand times could go with it.

Read it →

A report with nowhere to appear

A weekly job, a table, an endpoint that answers correctly, and no screen anywhere. From either end it looks finished. Only the missing caller says otherwise.

Read it →

Seven doors and two handles

A staff availability feature with seven endpoints on the server and two reachable from the app. Half-built features look finished from outside.

Read it →

A check that could not see the question

We built a check to find endpoints nothing calls. It named four called constantly, because it could not see four of the five ways our pages ask for things.

Read it →

What a support account should never see

Ten families of endpoint, all a venue’s money, sat outside the list meant to keep support staff from financials. Hiding a menu item is not closing a door.

Read it →

A guard that only checked the first door

Our menu reader refuses private addresses. It checked the address you pasted and nothing after, so a public link redirecting elsewhere walked straight past.

Read it →

The commonest sale was the one that would have failed

Card payments on a tab carried a reference. Counter sales carried none, and the card company requires one. The rare path worked, the common one would not.

Read it →

A test that reads the code but never runs it

Two tests covered our card adapter. Both searched its source for forbidden words and never ran it. A green suite, and a bug on the second real test.

Read it →

An error log nothing was ever written to

Our card routes logged every provider failure to a table that does not exist. The write was caught, so it failed silently and the errors screen stayed blank.

Read it →

One card key for ten kitchens is one bank account

Our first card-reader integration used one platform-wide key, like the one we hold for email. Wrong for money: every venue would charge into one account.

Read it →

The number the chef acts on was the smallest on screen

A kitchen screen showed the quoted wait at 34px and the tickets still to make at 13px grey, dropped on a narrow phone. What a kitchen screen puts first.

Read it →

Popular is not a pairing

A drink in a third of baskets becomes the top goes-well-with for every dish. That is the bestseller list restated, not a pairing. What to measure instead.

Read it →

A report that will not tell you it made you money

Upsell reports love the phrase "extra revenue generated", and almost none can know it. What an honest report can claim, and the sentence ours will not write.

Read it →

A row that could only ever say zero

A report we shipped had a kiosk line that could never show anything but nought. Two different questions had been mixed into one list, a common fault.

Read it →

A setting that only half the screens obeyed

We added a switch to turn the add-on row off. The guest menu obeyed. The register kept offering them. Two screens read one setting from two places.

Read it →

The photo was fine. The label was not.

A manager photographs a contract and the system refuses it because a browser guessed the file type from its name. Read the file, not its label.

Read it →

An error message with a request id in it

A manager uploading a contract was shown a raw 400 from an API, JSON and all. It read as a broken product. It was a file that needed swapping.

Read it →

A long list should load before you reach the bottom

Our product list stopped at 100 of 131 items. Two things about long lists are easy to get almost right, and one looked correct in every test we had.

Read it →

A default that never applied, and a dish that stuck

A new dish failed a NOT NULL check, yet the column had a default. Defaults do not work as most assume. A second report was the same fault from the other end.

Read it →

An empty list proves nothing

We checked the past-orders screen scrolls. It did, on a venue with no orders. That is not a test. It is how a system passes its checks and fails on Saturday.

Read it →

Loco Lime is Loco Lime in every language

Which words are language and which a name? Twenty-six languages force it. Get it wrong and a guest orders a Beef Taco from a menu that says Taco de Birria.

Read it →

Zero errors, and the job had failed anyway

A bulk job finished cleanly, every line saying 0 errors. Each line also said 54 to 657 items were missing. Nobody read that number, and it happened twice.

Read it →

We measured ten screens and believed it about 105

A check said we sent none of our customers’ data to a translator. It was true of the ten screens we checked. Across all 105 screens it was nine per cent.

Read it →

Every page, in 26 languages, without the wait

We translated the whole product up front — 2,080 phrases into 26 languages — so switching language is a lookup, not a wait. Paid once, for everybody.

Read it →

One hall, ten kitchens, one way of showing them

A food hall’s landing page is a grid of its kitchens, and the grid is the hall’s shopfront. Three card formats, chosen once by the hall, for every kitchen.

Read it →

Under three seconds: the register got its own page

A phone opened our register cold in 11.8 seconds, for a back office it never uses. The till has its own page now: 2.8 seconds cold, 15 ms after that.

Read it →

Move it on screen first, save it after

Dragging a dish up the menu did nothing you could see, then redrew the page a second later. Now the row moves when you drop it, and that is what saves.

Read it →

A tick box that hid your dish from everyone

An unlabelled tick box on the menu screen took a dish off the guest menu, the kiosks and the till. What a control owes the person about to press it.

Read it →

A setting that is off by default is not a fact

Our own pages promised staff clock in with a photo. It is optional, and off until a venue switches it on. Eleven sentences fixed, and how we found them.

Read it →

Raw bytes are not the wire

We cut 70 KB of repeated modifier groups out of the till’s menu file. Over the wire it saved one kilobyte. What compression was already doing for us.

Read it →

A board that lists every page, slowest first

Every page is timed in the browser that loaded it — till, kitchen screen, guest menu, public site — and ranked slowest first against a 300 ms budget.

Read it →

A year in the cache, for a file that cannot change

Every script we ship carries a content hash in its address, so a browser could keep it a year. Ours re-checked all 138 on every screen. One file fixed it.

Read it →

The stylesheet that now arrives with the page

A first visit paid a second round trip before it could paint: the stylesheet. It now travels inside the page, with a check that the minifier changed nothing.

Read it →

A crawler is not a customer

Nine marketing pages, one visit each, hours apart, all near a second. That is a search engine rendering the site, not a reader. How we tell them apart.

Read it →

A tab opened in the background is not a slow page

Our load board said the home page took 7.4 seconds. It paints in half a second — the tab was behind another one. How a field measurement handles that.

Read it →

The report that said £0 to a kitchen that took £800

A sales report from the wrong table looks fine for months. Ours priced stock off the shelf at the ingredient’s selling price — zero. Nobody sells a tortilla.

Read it →

A tip is not turnover: how a venue asks for one

Tips at a QR checkout: fixed amounts, percentages, or both by bill size. What a venue may set, nothing pre-selected, the food as the base, where it lands.

Read it →

The venue table that cannot take one more column

A per-venue setting is the natural thing to add as a column on the venues table, until the table hits the database’s limit. What we found at one hundred.

Read it →

Nine round trips in series, and one slow till screen

The register’s Money tab asked the database nine questions one after another when most could go together. Found from the till’s own timing, fixed in a wave.

Read it →

The kitchen's own manager could not save its settings

A kitchen manager could see every venue setting and change none. Every save was refused. Which settings a manager holds, which stay with the owner, and why.

Read it →

When the crash report says nothing was thrown

Some errors arrive with no message and no stack. A short trail of what the screen just did turns a promise that failed silently into the step that broke.

Read it →

Festival till and food-hall till, sold as two things

Every POS company splits its site by venue: festivals, food halls, stadiums. Underneath it is the same three problems, so one system can serve all of them.

Read it →

Some settings belong to the vendor, some to the hall

A kitchen decides how its receipts read, not whether it charges the hall fee. Shared settings must know the difference and let the owner lock the hall ones.

Read it →

A till screen you never have to scroll

At a busy counter a scrollbar is a lost second, sometimes a wrong tap. The register fits any screen by scaling the layout to the glass, not by hiding half.

Read it →

Why your till should count in pennies, never pounds

Store £4.50 as a decimal and a rounding error will one day leave a five-kitchen split a penny out. Every figure here is whole pennies until it is shown.

Read it →

A meal in courses, without a fine-dining till

A table wants starters, mains, then pudding; a street-food bag goes out at once. Ask which course only when it matters, and band the ticket the same way.

Read it →

The best new till is one your staff have already used

Casual staff turn over fast and arrive knowing the big tills. A register with the layout already in their hands needs no training, so ours copies the best.

Read it →

Holiday that follows the contract, not a typed number

A kitchen porter on twenty hours and a salaried supervisor do not build up holiday the same way. When the contract changes, the entitlement should follow.

Read it →

The rota in the language your kitchen actually reads

Food hall staff rarely share one language. The staff app switches the moment they pick one. How a screen translates itself, and the catch on a first visit.

Read it →

When the till breaks mid-service, it should say what

A bare 500 tells the floor nothing. A good log names the screen, counts how often and puts the worst first, so the owner acts before a guest reports it.

Read it →

What a food hall till hides from the stall next door

Several businesses share one food hall system. A trader must never see the next kitchen’s takings, pay or supplier prices. What that covers and how it leaks.

Read it →

Cash up should read every order, not the last few

A cash-up that works its expected drawer from a capped list of orders understates what should be there, then records the wrong figure as proof. Read it all.

Read it →

A worst-first report can still hide your worst kitchen

A report capped at a few hundred rows and sorted worst-first drops the row you opened it for. How a cap on a summary lies, and gets quieter as you grow.

Read it →

Moving stock between kitchens, and who signs for it

When a kitchen lends stock to another, one update is not enough. A transfer is three moments — sent, in transit, received — and the sender never signs it in.

Read it →

A buzzer number on the ticket, and calling it back

A collection order needs one handle counter and customer both hold: a buzzer number on the ticket and the ready screen, where the person plating sees it.

Read it →

Your till thinks the day ends at 1am

British clocks run an hour ahead of most software’s clock from late March to late October. Work out “today” the easy way and the drawer is wrong twice a day.

Read it →

A drawer that balances and is still short

The cash-up says the till took £685 and there is £685 in the drawer. It took £849. Nothing is red, the count is signed off, and the shortfall is filed away.

Read it →

The worst counter was not on the list

A hall owner asks one thing of guest feedback: which kitchen are people unhappy with? Our report read the newest 500 answers, so the worst one was missing.

Read it →

Paying a kitchen twice for the same week

A payout screen works out which days are unpaid. Show it only the newest runs and the rest stop counting, so a settled year comes back as a priced gap.

Read it →

A percentage that quietly exonerates

On a report built to catch till fraud, every rate had a capped top and an uncapped bottom. Everyone looked better than they were, small discounts first.

Read it →

Ask your reports how many rows they read

Four wrong numbers in four days, one cause: a limit meant for a list, reused for a total. Why it hides in hospitality software, and how to flush it out.

Read it →

An item with no price is not a menu item

A live QR menu offered guests toilet roll, bin bags and cling film at nothing. Two ordinary settings met and made something nobody would type on purpose.

Read it →

Who tells the kitchen its allergens are blank?

Our guest pages are honest about a dish with no allergen answer. Nobody had built the other half: telling the operator, on the screen where they work.

Read it →

A stock photo under a brand name is a lie

Finding a decent photograph of "beef burger" is easy and fair. Finding one for Diet Coke, or a named champagne, is neither — so the honest answer is to refuse.

Read it →

Ten kitchens, one photograph

The tenth kitchen in a hall selling fries should not pay to look up a picture of fries. Keyed properly, a photo library gets cheaper the more people use it.

Read it →

When two numbers on one screen disagree

A dashboard that says six items are live while the menu shows five is worse than one that says nothing. Caught three releases running, always the same cause.

Read it →

An open tab should shout its age

A competitor's till showed twenty open checks, some a fortnight old. An unpaid bill that stops drawing attention to itself is money nobody collects.

Read it →

Cooking before the bill is paid

A bar tab means food starts before money changes hands. The kitchen needs the order now, and the accounts must not see a penny until somebody actually pays.

Read it →

The receipt switch that printed anyway

Our payment screen had a Print receipt toggle from day one. It was drawn, it flipped, it looked live, and nothing read it. The paper came out either way.

Read it →

A food hall is not one business

Kitchens under one roof share a landlord and opening hours, not a receipt policy, a PIN or a view on buzzers. A POS that assumes they do surprises somebody.

Read it →

A save that returns OK and writes the wrong row

The request succeeded. The screen said Saved. The value went to the wrong table entirely, and every test that checked the response was satisfied.

Read it →

A switch nobody hears is not a switch

The sold-out toggle worked. The database knew, payment refused, and the till kept selling the item in the gap between. Where availability state has to live.

Read it →

The telemetry that never measured a till

We built speed tracking to catch slow tills. Two separate silent failures meant it only ever measured the back office — and nothing anywhere said so.

Read it →

A till that updates itself, carefully

We ship many releases a day; a till is opened once and left for a shift. How the register notices a deploy and reloads, and the six reasons it refuses to.

Read it →

Fifteen seconds to take it back

Finishing a ticket is the only irreversible press on a kitchen screen. Why the card turns green and waits, and nothing reaches the server until it closes.

Read it →

The guest's menu is older than your shelf

A QR menu loads once and sits on a table while stock changes behind it. What has to happen when a guest orders a dish that sold out after their page loaded.

Read it →

What the first docket off a real printer taught us

The first paper off a real thermal printer failed three ways in one photo — mid-word breaks, code-page garble, two order numbers — and each fix made it honest.

Read it →

Order numbers a kitchen can shout

Five-digit references and platform codes make every handover a reading test. One three-digit number a day, reset overnight, is what a counter can shout.

Read it →

Sold out should warn the counter, not overrule it

The availability list can be wrong; the person at the shelf is not. A warning with an override and a nudge to fix the list beats a till that blocks the sale.

Read it →

Show the ticket's age, not the clock

A kitchen screen that stamps 14:07 on a ticket reads as fourteen minutes to a cook mid-rush. Age with units — 47s, 11m, 2d — is the number the pass runs on.

Read it →

A setting should show you what the guest will see

Every menu setting is a promise about someone else's screen. A live preview in the guest page's own layout shows the embarrassing pick before a customer does.

Read it →

Rank "popular" by takings, not by how many you sold

A most-popular rail sorted by units fills up with cheap sides. Sort it by what each item actually takes and the same shelf starts paying rent.

Read it →

A QR menu should offer the guest their language, once

The phone already says what language its owner reads. What a menu should do with that, and the two mistakes: switching automatically, and asking every visit.

Read it →

Splitting a bill is three jobs, not one button

Equal ways, by item, or by amount — each share with its own way of paying. What a till needs before "split" stops meaning "get a calculator".

Read it →

A second food hall: the settings that must split first

One building is a special case that hides everywhere. Receipt footers, buzzer rules and till PINs all have to belong to a hall before there are two of them.

Read it →

Your menu photos may be hosted by a system you left

Switch POS and the pictures often stay behind — hotlinked to the old supplier until their servers stop answering. How to check, and what moving them takes.

Read it →

HelchPOS vs DINES: payments-first, or kitchen-first

DINES is a payment company with a POS on top. HelchPOS is a kitchen system that does not touch your money. Honest, including what DINES does that we do not.

Read it →

HelchPOS vs NOQ: the event platform and the venue one

NOQ runs festivals and events at scale, and processes the payments. HelchPOS runs the building the rest of the year. By people who moved a food hall off NOQ.

Read it →

HelchPOS vs me&u: the guest experience and the rest

me&u is the QR ordering product we deliberately copy — and it has no POS, no stock system and no kitchen screen of its own. What that means for a food hall.

Read it →

HelchPOS vs peazi: the same QR menu, a different depth

peazi does QR ordering well and cheaply, and stops there. Where the two overlap, where they do not, and the one thing peazi has that we have refused.

Read it →

What a food hall owes its vendors, and when

Commission, recharges, VAT and the day the money actually lands. The arithmetic behind a vendor payout, and why the invoice matters more than the transfer.

Read it →

What "1.4%" actually costs you on a £5.90 pint

Card pricing is quoted as a percentage and charged as a percentage plus a fixed fee. At food hall basket sizes the fixed fee is most of the bill. Real numbers.

Read it →

Out of stock should never stop your till taking money

A stock count is a guess about the world; the person at the till can see it. How to show stock on a till without a wrong number turning a customer away.

Read it →

Your kitchen screen and your till should be one app

Two screens polling separately can disagree — that is the day a ticket goes missing. Why the pass belongs in the ordering app, and when a dedicated screen wins.

Read it →

Your gross profit is only as real as your recipe lines

Supplier price, product cost, recipe line, menu cost. Most kitchens have the first two and nothing in the third — so the margin on screen is a dressed-up guess.

Read it →

How a food hall takes one payment across five kitchens

A guest buys from three businesses and pays once. What has to happen underneath for each kitchen to be paid the right amount — and where it usually goes wrong.

Read it →

25 questions to ask before you buy a food hall POS

A buyer’s checklist for multi-vendor sites — settlement, offline trading, allergens, stock, and the contract questions that decide how you leave.

Read it →

What happens to a festival bar when the signal drops

A field with 40,000 people on it is the worst coverage you will ever trade in. What offline mode must mean, and what separates resilience from marketing.

Read it →

Allergens on a QR menu: what UK law actually requires

Natasha’s Law, the 14 allergens, and which food must carry a full ingredient label rather than the information given another way — on a digital menu.

Read it →

One QR code for the hall, or one per stall?

Does the code on the table open the whole hall or a single kitchen? What each does to spend per head, to queues, and to the kitchens not on the poster.

Read it →