Resto · version 1.0

Restaurant point of sale & management

Everything you need to run a restaurant from one install: a touch till that works offline, a kitchen screen, recipe-level stock, a QR menu your customers order from, payroll, and books that balance. This guide covers installing it and running it.

In a hurry? Upload the files, open your domain, and follow the installer. Then read Your first hour — it is the shortest path from an empty install to ringing up a real sale.

Welcome

Resto is a single-restaurant system. One install runs one business, which can have several branches — each with its own stock, prices, staff, tables and reports.

What is in the box

Touch POS

Dine-in, takeaway, delivery and drive-thru. Splits, holds, voids, refunds, cash-up. Keeps taking orders when the internet drops.

Kitchen display

Tickets routed per station, timed against a target, with a bump screen and a recall.

Dining room

A floor plan you draw once, table sessions, transfers, merges and a waiter app for phones.

Inventory

Recipes down to the gram, moving-average costing, batches, wastage, stocktakes and transfers.

Purchasing

Suppliers, purchase orders, partial deliveries, landed cost and what you owe.

Online store

A QR menu search engines can read, guest checkout, order tracking, delivery zones and riders.

Customers

Loyalty points, gift cards, coupons with real rules, and moderated feedback.

Staff

PIN clock-in at the terminal, timesheets, leave, and payroll that reads the clock.

Accounting

Double-entry books that post themselves from sales, deliveries, expenses and payroll.

How to read this guide

Sections follow the order you will actually need them: set the place up, build the menu, open the till, then everything else. Every screen named here exists in the product — where something is planned but not built, it is listed under Not built yet rather than described as if it were.

Server requirements

Resto runs on ordinary shared hosting. There is nothing to compile, no Node on the server, no Redis, no websockets and no Supervisor.

WhatNeedsNotes
PHP8.3 or newer8.3 and 8.4 are both tested.
DatabaseMySQL 8.0+ or MariaDB 10.6+The installer creates the database for you if the user is allowed to.
Extensionspdo_mysql, mbstring, openssl, tokenizer, xml, ctype, json, bcmath, fileinfo, curl, gdAll standard. The installer checks each one and tells you which is missing.
Optionalzip, intlNice to have; nothing fails without them.
Writable.env, storage/, bootstrap/cache/, public/uploads/Usually 755 on folders, 644 on files.
Web rootPoint the domain at public/See the warning below if your host will not let you.

Point the domain at public/, not at the folder above it. If the document root is the project folder, anyone can download your .env — which contains the database password and the application key. On cPanel this is Domains → Document Root. If your host truly will not allow it, move the contents of public/ into the web root and edit the two require paths at the top of index.php.

What you do not need

No cron job. No queue worker. No Node or npm on the server — the compiled CSS and JavaScript ship inside the ZIP in public/build/. Nothing in Resto is queued or scheduled: the kitchen and dispatch screens poll every few seconds rather than holding a socket open, precisely so it runs on hosting that forbids long-running processes.

Installing

Resto installs itself in a browser. You do not need shell access, phpMyAdmin or a command line.

  1. Upload and unzip

    Put the contents of the ZIP on your server and point the domain at the public/ folder. Everything is included — you do not need to run composer install.

  2. Open your domain

    Any address on the site redirects to /setup until the install is finished. You will land on the requirements check.

  3. Requirements

    Every required row must be green. If one is not, enable the extension or fix the folder permission on the server and press Re-check. Nothing has been written yet.

  4. Restaurant

    The name, currency and timezone, plus the environment and URL. The currency decides how every price in the system is displayed, and the timezone decides which business day a 1 a.m. order lands on. Leave Debug mode off on a live server.

  5. Database

    Host, database name, username and password. Press Test connection before continuing. If the database does not exist yet, Resto creates it — as long as your database user is allowed to. Leave Drop existing tables off unless you are re-installing over a failed attempt.

  6. Owner

    Your name, email, password and a terminal PIN. The PIN is what the till asks for — clocking in, approving a void, applying a discount. Nobody types an email address on a busy Friday.

    Leave Install sample data off for a real restaurant. It fills the system with a demo menu, floor plan, staff and a week of fake orders, which is a lot to delete afterwards.

  7. Review and install

    Check the summary, then press Install now. This writes .env, creates the tables and your account. It usually takes under a minute; the log tells you exactly what happened, and exactly where it stopped if something went wrong.

The installer seals itself. Once it finishes, /setup redirects to the site and cannot be re-run. The seal is a file: storage/app/installed. Delete it to open the wizard again — and if /setup is ever reachable when it should not be, that file is the first thing to check.

If the install fails

The log on screen stops at the step that failed and shows the reason. Nothing after that point was changed. The usual causes:

Message mentionsWhat to do
Access denied for userWrong database username or password. Go back a step and re-test.
Unknown databaseYour database user may not create databases. Create an empty one in your hosting panel and use that name.
Permission denied / failed to open stream.env or storage/ is not writable. Set folders to 755 and files to 644.
Maximum execution timeRare, and only with sample data on slow hosting. Re-run with Drop existing tables on and sample data off.

Your first hour

An empty Resto cannot ring up a sale, because nothing has a price yet. This is the shortest route from installed to trading.

  1. Check your currency and timezone

    Settings → General Settings. The installer set both from what you typed; this is where you correct them, add your logo and set your receipt header.

  2. Set your taxes

    Settings → Taxes & Charges. Create the rates you charge and put them in a tax group. Decide now whether your prices include tax — the switch is on General Settings → Money & tax. It changes what every number on the menu means, and changing it later does not restate the sales you have already taken.

  3. Create a price book

    Menu → Price Books. One book marked as the default is enough to start. Prices live in a book, not on the item, which is what lets a takeaway price differ from a dine-in one later.

  4. Build the menu

    Menu → Categories, then Menu Items. Each item needs at least one size (a variant) and a price in your default book. An item with no price in any book cannot be sold — the till and the online menu both hide it rather than sell it for nothing.

  5. Add your staff

    Staff. Give everyone a role and a terminal PIN. The role sets a sensible starting set of permissions; tick and untick from there.

  6. Draw the floor, if you seat people

    Tables & Floor. Add a floor, drop tables onto it and set the seats. Skip this entirely if you are takeaway only.

  7. Open the till

    POS Terminal. Pick a terminal, open a shift with the cash in the drawer, and take an order. That is the whole loop.

Everything else — stock, suppliers, the online shop, loyalty, payroll, the books — can wait until you are trading. None of it is required to take money.

Command-line install

If you have shell access and would rather not use the wizard:

composer install --no-dev --optimize-autoloader
cp .env.example .env
php artisan key:generate

# edit .env: APP_URL, APP_TIMEZONE and the DB_ settings

php artisan migrate --force
php artisan db:seed --force        # branch, owner, payment methods, chart of accounts

npm install && npm run build       # only if you changed the CSS or JS

# tell the installer it has nothing left to do
echo OK > storage/app/installed

The seed creates a placeholder owner, owner@resto.test, with the password password.

Change or delete that account before you go live. It has a published email and a published password. The browser installer deletes it automatically once you create your own owner; a command-line install does not.

Sample data

Optional, and never part of a real install. Run them in this order:

php artisan db:seed --class=DemoRestaurantSeeder   # staff with terminal PINs
php artisan db:seed --class=DemoMenuSeeder         # a small bistro menu
php artisan db:seed --class=DemoFloorSeeder        # a dining room and a terrace
php artisan db:seed --class=DemoInventorySeeder    # ingredients, recipes, opening stock
php artisan db:seed --class=DemoChannelSeeder      # customers, coupons, delivery zones
php artisan db:seed --class=DemoHrSeeder           # timesheets and pay terms
php artisan db:seed --class=DemoSalesSeeder        # a fortnight of trading
Demo accountRolePIN
manager@resto.testManager1234
cashier@resto.testCashier4821
waiter@resto.testWaiter5150
chef@resto.testChef7788
store@resto.testStorekeeper3030

All demo accounts use the password password. Delete them before going live.

Settings

Settings → General Settings. Resto stores its settings in the database, not in .env, so nothing here needs a file editor. The installer writes the important ones; the rest have sensible defaults and can be left alone.

Six tabs, each saving only its own keys — changing the receipt footer cannot reset your currency. The key names below are what the tables store, given here because they are also what the API and the seeders use.

TabCovers
RestaurantName, timezone, logo and browser icon, footer text, languages.
Money & taxCurrency, symbol position, cash rounding, tax-inclusive pricing, service charge, tax number.
Orders & serviceOrder numbering, the trading-day start, kitchen target time, stock deduction, PIN approvals.
ReceiptsPaper width, header and footer, auto-print — with a live preview of the paper.
ReservationsTurn time, slot spacing, auto-confirm.
APIRate limit.

Three things keep their own screens, because each is a set of records rather than a set of switches: tax rates under Settings → Taxes & Charges, the loyalty scheme under Loyalty, and opening hours and delivery under Delivery → Online Store — those differ per branch.

Money

KeyDefaultWhat it does
currency_codeUSDThree-letter code. Used by the API and by every exported file.
currency_symbol$What is printed beside the number.
currency_decimals2Set to 0 for currencies with no minor unit.
currency_positionbeforebefore or after the number.
cash_rounding_increment0Rounds cash totals to the nearest increment — 0.05 where the smallest coin is five cents. The difference is recorded, not hidden.
tax_inclusive01 if your menu prices already contain tax.
service_charge_percent0Added to dine-in orders.
service_charge_taxable1Whether tax applies to the service charge.

Orders and receipts

KeyDefaultWhat it does
order_number_prefixORD-Prefix on every order number.
order_number_daily_reset01 restarts the sequence each day.
business_day_start_hour4The hour a trading day begins. A shift that finishes at 2 a.m. belongs to the night it started, not to the next morning.
receipt_width80Paper width in millimetres — 58 or 80.
receipt_header / receipt_footer—Free text above and below the receipt.
auto_print_receipt0Prints the receipt as soon as an order is paid.
print_methodbrowserapp prints through the Resto Print app instead of the browser.
kot_enabled1Prints kitchen tickets at all. Off for a kitchen that works only from screens.
kot_auto_print0Browser printing: kitchen screens print each new ticket as it arrives.
tax_number—Your VAT / tax registration number, printed on receipts.
kds_default_sla_minutes15Target time for a kitchen ticket. Colours the ticket amber, then red.
inventory_deduct_on_sale1Takes ingredients out of stock when a sale closes. Turn off until your recipes are built.

Branding

KeyWhat it does
app_nameShown in the back office, on receipts and on the online menu.
logo_path / favicon_pathPaths under public/uploads/.
show_site_nameWhether the name appears next to the logo.
dashboard_footer_textSmall print at the bottom of the back office.
default_languageen. Resto ships English and Arabic, with a full right-to-left stylesheet.

Branches

Settings → Branches. One Resto install runs one business. A business can have several branches, and almost everything is scoped to one: stock, tables, terminals, shifts, staff, orders and reports. The menu, ingredients and customers are shared.

A single-site restaurant can ignore this screen entirely — the installer creates one branch and names it after the restaurant.

Adding one

A new branch gets a main store automatically, because one with nowhere to hold stock cannot receive a delivery. After that it needs its own floor plan, opening hours and delivery zones — the branch form links to all three.

Two rules

A staff member with no branch set can work at any of them. Set a branch on somebody who only ever works at one, and their screens default to it.

A staff member with no branch set can work at any of them. Set a branch on somebody who only ever works at one, and their screens default to it.

Staff, roles & permissions

Staff in the sidebar. Every person is one row, whether they log into the back office, clock in at the till, or both.

Roles

A role is a starting point, not a cage: it fills in a sensible set of permissions which you then tick and untick per person.

RoleStarts with
OwnerEverything, always. The permission list does not apply.
ManagerPOS, orders, discounts, voids & refunds, tables, kitchen, menu, inventory, purchasing, customers, reservations, delivery, staff, reports
CashierPOS, orders, discounts, voids & refunds, tables, customers
WaiterPOS, orders, tables, reservations
ChefKitchen, orders, inventory
StorekeeperInventory, purchasing
AccountantAccounting, reports, purchasing
RiderDelivery

Permissions

Sixteen sections: pos, orders, discounts, refunds, tables, kitchen, menu, inventory, purchasing, customers, reservations, delivery, staff, accounting, reports, settings.

Two of them govern money leaving the business rather than a screen: discounts is Apply discounts, and refunds is Voids & refunds. Both are separate from orders, so somebody can be trusted to look at every sale without being able to give one away. See Who may discount, void and refund.

A link somebody cannot use is dimmed in the sidebar, and the route behind it refuses them as well — pasting an admin URL into a cashier's browser gets a 403, not a page.

Passwords and PINs

Two separate credentials, deliberately. The password signs into the back office. The PIN is what the terminal asks for: clocking in, switching user mid-shift, approving a void, a refund or a discount. Four to eight digits.

A PIN only approves if the person it belongs to is a manager or an owner. A cashier's PIN clocks them in; it never signs off their own discount.

People who leave

Deleting a member of staff would orphan every order they rang up and every line they approved, so Resto marks them as left instead: the account is deactivated, dated, and hidden from the staff list unless you tick Include leavers. Their history stays intact.

Taxes & charges

Settings → Taxes & Charges. A tax is one rate. A tax group is the set of taxes that apply together — most restaurants need one group with one rate in it, but the structure handles a state tax plus a city tax without inventing a combined percentage.

Every menu item points at a tax group. Items with none use the default group.

Inclusive or exclusive

The single most important decision on this screen.

Set this before you take your first order. Changing it later does not restate sales already recorded — every order stores the totals it was rung up with, on purpose, so a settings change next month cannot rewrite what last month's revenue was.

Service charge

A percentage added to dine-in orders, set with service_charge_percent. Whether it is itself taxable is a separate setting, because the answer differs by country. It is never added to takeaway or delivery.

Categories

Menu → Categories. Categories group items on the till grid and on the online menu, and they can nest one level. Each one can carry a colour and a default kitchen station, which items inherit unless they override it.

Drag to reorder — the order here is the order on the till, so put what sells most first.

Items & variants

Menu → Menu Items. An item is a thing on the menu. A variant is a size or version of it — Regular and Large, or a single default variant for something that only comes one way.

Prices are not on the item. A price is the intersection of a variant and a price book. That is what lets delivery cost more than dine-in without duplicating the menu.

What an item carries

FieldWhy it matters
CategoryWhere it appears on the grid and the online menu.
Kitchen stationWhich screen the ticket prints to. Falls back to the category's station.
Tax groupOverrides the default group for this item.
ChannelsWhere it may be sold: till, QR, online, delivery. An item absent from a channel is not merely hidden there — the order service refuses it.
ScheduleAvailable from / until, and on which days. Breakfast stops at 11.
Prep timeFeeds the kitchen timer and the online ETA.
Dietary tags & allergensPrinted on the online menu; several markets require it.
ImageUsed on the till grid and the QR menu.

Combos

An item of type combo carries choice groups instead of a plain price — a meal deal where the customer picks a main, a side and a drink. Combo groups are edited inside the combo item itself, on the item form.

Import and export

The item list exports to CSV and imports back. The export is the template: change it, re-upload it. Useful for a first bulk load and for a price review.

Modifiers

Menu → Modifiers. A modifier group is a question the till asks — "How would you like it cooked?", "Any extras?" — and the modifiers are the answers.

Attach a group to as many items as you like. Each item can override the group's rules, so Extras can allow three free choices on a burger and none on a salad.

RuleEffect
RequiredThe order cannot be sent until something is picked.
Min / max selectHow many answers are allowed.
Free countHow many are included before charging. Spent in units, so "extra bacon ×2" uses two of three free picks.
Max quantityHow many times one modifier may be repeated.
Price & costWhat it adds to the bill, and what it takes out of stock.

Combos

Menu → Combos. A combo is a meal deal: one price, and the customer picks a main, a side and a drink.

Making one

  1. Create a menu item of type Combo

    It gets a price like any other item — that is what the customer pays.

  2. Add its choice groups

    On the item's own page. "Choose a main", "Choose a drink". Each group says how many the customer picks.

  3. Put options in each group

    Any variant on the menu can be an option.

How it prices

The combo carries the price and the choices are free — unless an option sets an upgrade charge, the "large fries, +1.00" case. A negative charge is allowed, for a cheaper swap.

A combo with no choice groups cannot be ordered — the till has nothing to ask for. The Combos screen flags those at the top so they do not sit unsellable on the menu.

The Combos screen exists because the item list can tell you a combo is there but not what is in it, which is the only thing about a combo that matters. Groups are still edited inside the item, because a group has no meaning away from the combo it belongs to.

Price books

Menu → Price Books. A price book is a named set of prices. One book is the default and is used whenever nothing more specific applies.

A book can be limited by branch, channel, order type, day and time. Resto picks the first book whose conditions match the sale, and falls back to the default for any item that book does not price.

What that buys you

An item that no book prices cannot be sold. The till hides it and the online menu leaves it out, rather than offering it for nothing.

Availability (86)

Menu → Availability (86). "86" is kitchen shorthand for we have run out. This screen takes an item off the menu without deleting anything.

86-ed items grey out on the till and drop off the online menu immediately.

The POS terminal

POS Terminal in the sidebar, or go straight to /pos. Built for a finger on a tablet: large targets, no hover, no double-tap.

Terminals

A terminal is a named till — Front counter, Bar. Each has its own shift, its own drawer and its own receipt numbering. Pick one the first time you open the POS on a device; it is remembered.

Taking an order

  1. Choose the order type

    Dine-in, takeaway, delivery, drive-thru or room service. This decides the price book, whether a service charge applies and whether a table is needed.

  2. Tap items

    Tap a category, tap an item. If it has sizes or required choices, the till asks. The running total is on the right.

  3. Adjust the line

    Quantity up and down on the line itself, Discount for money off that one dish, and the bin to take it off the order.

  4. Add the customer

    Optional for a walk-in, and the point of the order for a delivery. See The customer on the order.

  5. Send to the kitchen

    Sends only the lines that have not been sent yet — adding a round sends the round, not the whole table again.

  6. Take payment

    One tender or several. See Payments.

Holds

Park an order with a label and recall it later. A held order has not been sent to the kitchen and owes nothing.

The customer on the order

Add a customer in the order panel searches by phone number or by name. Two characters are enough, and a partial number matches — people read their number out from the end as often as the start.

Choosing somebody puts their name on the order, their allergy note on every kitchen ticket for it, their customer-group discount on the total, and their saved addresses one tap away. New customer in the same panel adds one without leaving the order: name, phone, and an address if it is going out. A number already on file returns that person rather than an error — the intent was to put them on the order, and they already exist.

A delivery order at the till

Choose Delivery as the order type and the order panel asks for an address. A saved address is one tap. A new one is typed in and, for a customer who is on the order, kept for next time.

The zone fee and the promised time appear on the total as soon as there is a postcode to go on, and the order reaches the dispatch board with the address, the number to ring and the cash to collect. An address outside every zone is still accepted: the cashier has already said yes to the person on the phone, so the order lands on the board with no fee and no promised time rather than being refused. Paying at the till leaves the rider nothing to collect.

Customer lookup needs a connection. Offline the till still sells — see Working offline — but as a walk-in sale.

Discounts

Discount under the totals takes money off the whole order; the same button on a line takes it off that dish. Either way it is one pad: a percentage or a fixed amount, with quick keys for the shares a restaurant actually uses, and the amount it comes to shown before you apply it.

Every discount takes a reason and records who approved it. The till offers a short list — staff meal, manager comp, loyalty, complaint, promotion — because a free-text box gets "asdf" typed into it mid-rush while a short list gets used and turns into a report an owner can act on. Anything not on the list can still be typed.

An order-level discount is spread across the lines in proportion to what each contributes, before tax; taking it off the total afterwards would quietly reduce the tax owed on a sale that already happened.

A customer group's standing discount is not this. It applies on its own when that customer is on the order, because it is the owner's decision rather than the cashier's, and a discount keyed in by hand replaces it rather than stacking on top.

Who may discount, void and refund

Two permissions decide who: Apply discounts and Voids & refunds, set per person under Staff. Three settings under Settings → Orders decide when a manager has to lean over:

SettingWhat it does
A manager PIN is needed to apply a discountOn by default. Off, anyone holding the permission discounts on their own authority.
A manager PIN is needed to void or refundOn by default, and the same rule.
Discount ceiling without a PINA discount worth more than this share of the order asks for a PIN whatever the toggles say. Blank for no ceiling.

Only a manager or an owner PIN approves. A cashier's own PIN proving their own discount would be no approval at all, so their PIN is never checked here. Whoever keys theirs in is written onto the order or the refund and into the activity log, whether or not a PIN was asked for.

The ceiling is measured on what the order actually lost, not on the number typed: a fixed amount off a small order can be a far bigger share than any percentage box would show.

Changing an order after it is placed

Orders on the till lists today's sales plus anything still open, searchable by order number, customer name or phone. Open one and the screen offers only what applies to it.

The order is…What to do
Still on screen, not sentChange the quantity or take the line off. Nothing has happened yet.
Sent, nothing paidVoid the line, or the whole order, with a reason.
PaidRefund the lines coming back. A paid order is never edited.
Paid, and the guest wants something different insteadRefund the original line, then ring the replacement as a new order.

Voids

Voiding takes a reason and cancels an order that has not been paid. The order number stays on file marked cancelled rather than deleted — several tax regimes require the number to stay allocated — every line is voided, and stock already taken out goes back as its own movement, so the stock card still shows it leaving and returning.

Once money has changed hands, voiding is refused and the till says so: taking a line off a settled sale would leave the order paid for more than it says. That is a refund.

Shifts & cash-up

A shift is one session on one terminal: opened with the cash in the drawer, closed by counting it.

  1. Open

    Enter the opening float. Nothing can be rung up on a terminal with no open shift.

  2. During service

    Cash in and cash out — a supplier paid from the drawer, a float top-up — are recorded as they happen, each with a reason.

  3. Close

    Count the drawer and enter the figure. Resto shows what it expected, what you counted and the difference.

Expected cash is derived from the movements ledger, never from a running total anybody can edit. The Z-report is stored on the shift, so a cash-up can be re-read months later.

Staff → Shifts & Cash-up lists every shift with its variance. A small shortage that repeats is a different problem from one large one, and the list is sorted so you can see which you have.

Payments & refunds

Payment methods are set up in the foundation seed: cash, card, wallet, gift card and account. Each carries whether it counts in the drawer, whether it can give change and whether it needs a reference.

Splitting a bill

A bill split four ways is four payment rows, not one payment with a note — that is the only shape a payment-method report and a cash-up can be built from.

Change

Calculated on what was tendered, and only for methods that can give change. Handing cash back against a card tap is not a rounding error, it is a hole in the drawer.

Refunds

A closed order is never edited. A refund is a new record that quotes the original, picks the lines being returned, records who approved it and why, and puts the stock back if you say so. The original order still says what it said.

  1. Find the order

    Orders on the till, or Orders in the back office. Search by number, customer name or phone.

  2. Say what is coming back

    Set a quantity on each line — one of the two burgers, not the whole bill — or Everything on the order. Lines left at zero are not refunded.

  3. Choose how, and why

    The tender the money goes back on, and a reason from the list or typed in.

  4. Restock, or not

    Only tick it when the dish actually came back. A guest refunded because the dish was wrong is not returning it, and putting it back would inflate the stock on hand.

  5. Approve

    A manager PIN if the settings ask for one. See Who may discount, void and refund.

Each line tracks how much of it has already been given back, so a second refund cannot return the same food twice, and the total is capped at what was actually paid. Cash refunds come out of the drawer as their own movement, so the cash-up still balances. A refund on a card or another non-cash tender never touches the drawer.

Changing one item on a completed order is a refund of that line followed by a fresh sale, not an edit. It leaves two documents that add up, which is what a tax inspector and a cash-up both need — and what an edit would quietly destroy.

Printing

Settings → Printers & Receipts.

Resto prints in one of two ways. Choose under How Resto prints at the top of the screen. You can switch at any time. The receipt and the kitchen ticket look the same either way.

Through the browserThrough the Resto Print app
Install anythingNothingOne small Windows app, on the computer the printers are plugged into
Printers per deviceOne: the device's default printerAs many as are plugged in
Kitchen ticketsPrinted by a kitchen screen left open beside each kitchen printerSent straight to each station's printer
Tickets from QR orders and the waiter appPrint only while a kitchen screen is openAlways print
Print dialogYes, unless the browser is started for kiosk printingNever
Cash drawerNoYes, opened after a receipt
Best forA counter with one printer, or a kitchen that works from screensA cashier printer and kitchen printers in the same restaurant

The customer receipt

Paper width (58 or 80 mm), a header under the restaurant name, a footer at the bottom, and whether it prints itself the moment an order is paid. The screen shows a live preview of the paper, because "58 or 80" means nothing until you see how much of your address fits on it.

After every sale the till shows a Receipt button that prints that sale's receipt, even when printing on payment is switched off. Older receipts are printed from Orders → the order → Reprint, marked as a copy.

The kitchen ticket

For kitchens with a printer rather than a screen — a docket in a rail is still the fastest way to run a pass. Bigger type than a receipt, quantities and item names in capitals, modifiers indented, notes boxed and allergies boxed heavily: it is read at arm's length, in a hurry, through steam.

One order becomes one ticket per station: the grill gets the steaks and the bar gets the drinks. A kitchen can use screens, printers, or a screen on the grill and a printer at the pass.

Testing it

Both documents have a test print button that uses a real order or a real ticket — not a mock-up, so what you see is what a customer gets. Save the settings first; the test reads them as stored.

Each device prints to its own default printer. Set the printer as the default in Windows, and in the browser's print settings turn off headers and footers and set the margins to None.

  1. Receipts at the till

    Make the receipt printer the till computer's default printer. Switch on Print automatically when an order is paid if every sale should print.

  2. Kitchen tickets

    Switch on Print kitchen tickets and Print as soon as an order is sent. Put a tablet or small PC beside each kitchen printer, make that printer its default, and open the station's screen: the Screen button under Where tickets go, or Kitchen Display and choose the station.

  3. Check the printer icon

    The printer icon at the top of a kitchen screen turns printing on or off for that device. Turn it off on a screen that has no printer beside it. The Pass screen, which shows every station, prints only when its icon is switched on.

A ticket prints once, whichever screen prints it first: reloading the page, or a second tablet at the same station, does not print it again. Only new tickets print by themselves, so switching a screen on mid-service does not reprint the whole rail. The printer button at the bottom of each ticket prints it again by hand.

No print dialog. Start Chrome or Edge with --kiosk-printing (add it to the end of the shortcut's Target) and it prints straight to the default printer without asking.

A browser cannot choose a printer. One device means one printer, and a kitchen screen has to stay open for its tickets to print. When the receipt and the kitchen tickets must come out of different printers on the same computer, or tickets must print with no screen open, use the Resto Print app.

Settings → Print App. A small Windows app that runs on the computer the printers are plugged into. One computer drives every printer: receipts to the cashier printer, each station's tickets to its kitchen printer, with no print dialog. Tickets from QR orders and the waiter app print even when no screen is open anywhere.

What you need

Setting it up

  1. Add your printers in Resto

    Settings → Print App → New printer. One for each real printer. Give it a name, choose the paper width, and choose what it prints: Customer receipts and table bills for the cashier printer, and the stations whose tickets it prints for a kitchen printer. On the one kitchen printer of a small kitchen, also tick Every other kitchen ticket, so items with no station still print.

  2. Download and install the app

    On the computer the printers are plugged into, open Settings → Print App and press Download Resto Print for Windows. Run the installer.

  3. Create a key

    Under Print app connections, name the computer (Cashier PC), choose its branch and press Create key. The address and the key are shown once. Copy them now.

  4. Connect the app

    Open Resto Print, paste the address and the key, and press Connect. Your printers from step 1 appear in the app, and the computer shows as online in Resto.

  5. Match the printers

    For each Resto printer, choose the printer on this computer it should print to, then press Test print in the app. A test page shows the printer's name, its paper width and a line in several scripts.

  6. Start with Windows

    Tick Start with Windows in the app, so it is running in the tray whenever the computer is on.

  7. Switch Resto over

    Settings → Printers & Receipts → How Resto prints, choose Through the Resto Print app and save. Then press Test print beside a printer in Settings → Print App: the test page now comes out through the app, which proves the whole path.

"Windows protected your PC". If Windows shows this when the installer starts, press More info and then Run anyway. Windows shows it for installers it has not seen often. It does not mean anything is wrong with the file.

What prints where

DocumentPrinterWhen
Kitchen ticketThe station's printer, or the printer for every other kitchen ticketAs soon as the order is sent: from the till, the waiter app, a QR order or the API
Kitchen ticket againThe station's printerThe printer button on a ticket on the kitchen screen
Customer receiptThe printer for receipts and billsOn payment, if Print automatically when an order is paid is on; the Receipt button after a sale; Reprint under Orders
Table billThe printer for receipts and billsPrint bill on a table
Test pageThe printer you testTest print under Settings → Print App

A station's printer can also be chosen on the station itself, under Settings → Kitchen Stations.

The same ticket on two printers

In the app, choose a second printer under Also print on, for example a copy of every grill ticket for the pass. Each Resto printer can print on up to two printers on the computer.

The cash drawer

For a drawer plugged into the receipt printer, tick Open the cash drawer after a receipt on that printer in Resto. The app opens it after each receipt, but not after a reprint. The app's Open drawer button tests it.

More than one computer or branch

When something did not print

Look at Recent print jobs at the bottom of Settings → Print App first:

StatusMeaning
WaitingNo app has collected it. Check the computer is on and the app is running: Print app connections shows it as online.
PrintingThe app has it. If it stays there for more than two minutes, the app lost touch, and the job is handed out again.
PrintedThe printer accepted it. If nothing came out, check the paper and the printer's own queue in Windows.
FailedTried three times. The reason is shown under the status, for example a printer that is not matched in the app, or out of paper. Fix it and press Retry.

The app keeps its own log, shown in its window. Open log folder opens the files.

Keys and safety

Shipping the installer

The Windows installer ships in public/downloads/resto-print/, and the Download button offers the newest version found there. If that folder is empty, for example on a host that will not serve .exe files, set RESTO_PRINT_DOWNLOAD_URL in .env to where the installer can be downloaded instead.

Working offline

The till keeps working when the internet drops. This is not a bonus feature — a restaurant that stops taking money because a router rebooted has a serious problem.

How it works

What it will not do

OfflineBehaviour
Cash salesWork normally.
Card terminalsDepend on your card provider, not on Resto.
Kitchen ticketsQueue, and arrive when the connection returns.
Stock deductionHappens on the server when the order syncs.
A brand-new itemNot on the device until it next syncs the menu.
Customer lookupNeeds a connection. The sale goes through as a walk-in.
Discounts needing approvalRefused while offline, and the till says so. A manager PIN is never written to the queue, so a discount that needed one would sync into a rejection — after the guest has left.
Voids and refundsNeed a connection: both act on an order the server already holds.

Do not close the browser tab while orders are still queued. The badge on the POS shows how many are waiting to send.

Dining room

Tables & Floor to draw the room, Service → Floor to work it.

The plan

Add a floor — Dining room, Terrace — then drop tables onto a grid, set the seats and the shape, and drag them where they really are. The grid is in units rather than pixels, so the same layout renders on a phone and on a desktop.

During service

Each table shows its state at a glance: free, seated, ordered, food served, bill asked for, needs clearing. From a table you can seat a party, open its order, transfer it to another table, merge two tables for a large group, or clear it down.

A table that still owes money cannot be cleared. Settle or transfer the bill first.

QR codes

Delivery → Online Store → QR codes prints a sheet of table cards. Each carries a stable token, so reprinting the sheet does not invalidate the codes already stuck to the tables. Scanning one opens the menu and remembers which table it came from.

Kitchen display

Kitchen Display, or /kitchen. Designed for a screen on a wall, seen from two metres away with steam in between.

Stations

Settings → Kitchen Stations. Grill, fryer, cold, bar. Items route to a station; the station's screen shows only its own tickets. A screen can also watch several stations at once for a small kitchen.

The board

The board refreshes itself every few seconds. It does not need a websocket, and it does not redraw unless something has actually changed.

Waiter app

Waiter App, or /waiter. A phone-sized view for the floor: your tables, what is ready to run, and what is still coming.

It is the same login and the same permissions as everything else — no separate app to install and no separate account to manage.

Ingredients & units

Inventory → Ingredients. An ingredient is something you buy and hold: flour, chicken thigh, a bottle of tonic.

Units

Every ingredient has a base unit — the unit it is counted in. Purchase units convert to it, so you can buy a 25 kg sack and use 180 g without doing the arithmetic yourself.

Costing

Resto uses moving average cost. Each delivery blends its price into the existing stock, so the cost of a portion reflects what you actually paid rather than the last invoice. Ingredients marked track batches also carry batch codes and expiry dates, and are drawn oldest first.

Preps

An ingredient marked is prep is something you make: a sauce, a dough, a stock. It has a recipe of its own and can be held in stock like anything else.

Recipes

Inventory → Recipes. A recipe says what one portion of a menu item consumes. Build them and two things start working: food cost on every report, and stock that goes down when you sell.

Sub-recipes do the right thing. If a burger uses your own barbecue sauce and you hold that sauce in stock, selling a burger takes sauce out — not flour, sugar and tomato. If you do not hold it, Resto explodes the recipe down to raw ingredients instead. Costing always explodes to raw, so the number is honest either way.

Recipes attach to a variant, so a Large can use more than a Regular. Modifiers carry their own cost, so extra cheese takes cheese out of the walk-in.

Stock, wastage & stocktakes

Stores

A store is a place stock sits: the kitchen, the bar, the dry store. Every movement names one.

The ledger

Stock is an append-only ledger of movements, with the on-hand figure derived from it. Nothing writes a level directly. That means every number can be explained: tap a level to see exactly what made it.

Wastage

Inventory → Wastage. Record what was thrown away and why. It comes off stock and lands in the books as a cost, separate from a stocktake difference — one is a kitchen problem and the other is a counting problem, and you need to know which you have.

Stocktakes

Inventory → Stocktake. Open a count, enter what is physically there, and close it. Resto shows the variance per line — expected against counted, in units and in money — and posts the difference when you commit.

Transfers

Inventory → Transfers. Move stock between stores or between branches. One movement out, one movement in, both recorded.

Purchasing

Suppliers

Purchasing → Suppliers. Contact details, payment terms, lead time and a running balance of what you owe. Each supplier can carry its own price per ingredient.

Purchase orders

Purchasing → Purchase Orders. Draft, approve, send. The reorder suggestion reads what is below its reorder level and which supplier is cheapest per base unit, so a weekly order is mostly a matter of checking a list.

Goods receipts

Purchasing → Goods Receipts. Booking in a delivery is the only document that touches stock. It handles what actually happens at a back door:

What you owe goes up with the delivery, not with the order — an order is a promise, a delivery is a debt.

Customers

Customers. One row per person, whether they were added at the counter or signed up on the website. Phone number is the practical identity: people give a number at a till and an email only when a form insists.

Each customer carries their order history, what they usually order, saved addresses, points, gift cards, and an allergy note that appears on every kitchen ticket for them.

Segments

Worked out from the order count and the last order date, not stored: New, Active, Slipping away, Lost. The filter on the list uses the same definition, so the regular who has not been in for four months is one click away.

Loyalty & gift cards

Customers → Loyalty.

Points ship switched off. A loyalty scheme is a real liability — every point is something a customer can walk in and spend — so Resto does not start accruing one until you decide to. Turn it on at the bottom of the Loyalty screen.

How it earns

SettingMeaning
Points per unitHow many points one unit of currency earns.
Point valueWhat one point is worth when spent.
Minimum to redeemStops a two-point redemption at the till.
ExpiryIn months. Zero means never — check your local rules.

Points are earned on the net of an order, not the gross. Paying points on tax is giving the taxman's money away twice. Earning is recorded once per order, so a replayed payment cannot pay out again.

Gift cards

Customers → Gift Cards. Issue a card for an amount; it gets a code and a balance. Spending one is a payment method at the till. A card cannot be overspent — it pays what it has and the rest is settled another way.

Both points and gift cards are ledgers with a derived balance. Nobody types a balance in, and the Loyalty screen shows the total liability so you always know what you owe.

Coupons

Customers → Coupons. Four kinds: a percentage off, a fixed amount off, a free item, or free delivery.

The rules are deliberately expressive, because "10% off" is the easy half. Every restaurant eventually wants free delivery over 25, Tuesdays only, first order, one per customer:

RuleWhat it does
Cap the discountOn a percentage. Without it, a percentage off a party of twenty costs whatever they ordered.
Minimum spendBelow it the code is refused — with a message that says how much more is needed, not just "invalid".
Channels & order typesOnline only, delivery only, and so on.
Days & timesTuesdays, or between 3 and 5.
Date windowFrom and until.
Total usesHow many times in all.
Uses per customerThe one that actually stops abuse.
First order onlyFor a welcome code.
Branch / customer groupLimit it to one site or one group.

A code is only spent when an order exists, so an abandoned basket never burns a single-use code. A code that has been used cannot be deleted — it is switched off instead, because deleting it would orphan the discount on somebody's receipt.

Online store & QR menu

Delivery → Online Store configures it; the shop itself lives at /shop.

The menu page

Server-rendered, not a JavaScript app. A QR menu a search engine cannot read is a marketing asset thrown away, and somebody standing outside your door on a weak signal should get text before they get a framework.

Ordering

Guest checkout by default. Forcing a stranger to register before they can buy a pizza is the most reliable way to lose the sale. An account is offered — it saves an address and counts points — never required.

Online orders are ordinary orders. They appear on the same list, print the same kitchen tickets and land in the same reports as anything rung up at the till. Prices come from the same price engine, so an integration cannot sell at a price you never set.

Order tracking

Every order gets a tracking page at /shop/order/{id}. The unguessable id is the whole authorisation — a guest has no account to log into. The page polls for progress and asks for a rating once the order is finished.

The controls that matter mid-service

ControlWhen you reach for it
Busy mode8 p.m. on a Friday, kitchen drowning. Adds minutes to every quoted time without closing the shop.
Pause online ordersStops new orders entirely. Existing ones carry on.
Opening hoursPer day, per branch. A closing time before the opening time means service runs past midnight.
Prep timeThe normal quote when things are calm.

Delivery

Zones

Delivery → Delivery Zones. A zone is either a list of postcodes or a radius from the branch. Each carries a fee, a minimum order, an optional free-over threshold and an ETA.

Zones are checked in order, so a specific postcode zone can sit in front of a catch-all radius. Postcodes match on the outward part and ignore case and spacing — an entry of SW1 covers everything in SW1.

Without at least one zone the shop refuses every delivery order. A radius zone also needs the branch latitude and longitude, set on the Online Store screen.

Where the orders come from

Two places, and they land on the same board: a customer ordering on the online store, and a cashier taking it at the counter or over the phone — choose Delivery as the order type at the till and the order panel asks for the address. See A delivery order at the till.

The difference is what each does with an address no zone covers. The shop refuses it, because nobody is there to make a judgement. The till takes it and puts it on the board with no fee and no promised time, because the cashier has already said yes to the person on the phone.

The dispatch board

Delivery → Dispatch Board. What is waiting, who is out, and how late it is. Assign a run to a rider or let Resto pick whoever has fewest in progress, mark it picked up, then delivered or failed.

Riders and cash

Cash collected on a doorstep moves onto the rider and stays there until they hand it in. The board shows what each is holding, and settling it is one button. Without that, the money is missing from the drawer and nobody can say where it went.

The fee is snapshotted onto the order when it is placed, so changing your delivery charge on Friday does not retroactively change what Thursday's customer was quoted.

Reservations

Front of House → Reservations. One day at a time, because that is how a host reads the book.

Availability is worked out from capacity and turn time rather than from a fixed grid of slots: six four-tops seat rather more than six parties across an evening, and a booking system that pretends otherwise turns away money.

Waitlist

On the same screen. Add a walk-in with a party size, and Resto quotes a wait based on the queue in front of them rather than a flat guess. Call them when a table frees, then seat them straight onto it.

Feedback

Customers → Feedback. Customers are asked to rate an order on the tracking page once it is finished.

Nothing is published until you publish it — an unmoderated review widget on a restaurant website is a liability, not a feature. The point of this screen is not the five-star ones; it is finding Saturday's two-star before the customer gives up and puts it somewhere public. The Needs an answer filter shows exactly those.

Attendance & leave

The clock

Staff clock in at the terminal: /pos/clock, a keypad and a PIN. It is built for a doorway, with wet hands and a coat still on.

Breaks are unpaid and are subtracted from the shift. A break left running is closed with the shift rather than quietly paid for. Nobody can be clocked in twice — two taps a second apart would otherwise pay one shift twice.

A shift that starts at 10 p.m. and ends at 2 a.m. belongs to the night it started, controlled by business_day_start_hour.

Timesheets

Staff → Attendance. Who is in the building right now, hours per person for the period, and every entry with the ability to correct one. Corrections record who made them and when — an edited timesheet that does not say who edited it is worth nothing in a dispute.

Leave

Staff → Leave. Holiday, sick, unpaid or other. Days are counted as working days, so Monday to Friday is five and not seven. Approved paid leave appears on the payslip at the person's normal rate, and the panel on the right shows who is off in the next fortnight — which is what the rota actually needs.

Payroll

Staff → Payroll. A pay run reads the timesheets for a period and draws up a payslip for everyone.

Resto does not calculate payroll tax. It changes by country and by year, and getting it subtly wrong is worse than not offering it. Deductions are entered as a figure your accountant gives you.

What it works out

Draft, approve, pay

A draft rebuilds from the clock as often as you like — somebody always forgets to clock out and the timesheet gets fixed afterwards. Approving freezes the payslips and posts the cost to the books. After that a correction is a fresh run, not an edit: the point of a payroll record is that it says what was actually paid.

Rate and pay type are copied onto each payslip, so a rise next month does not rewrite last month's.

Accounting

Double-entry books that keep themselves. Everything the restaurant already records — a sale, a delivery, an expense, a pay run — posts itself as a balanced journal. Nothing is typed in twice.

Chart of accounts

Finance → Chart of Accounts. The installer creates a short default chart. It is deliberately small: a restaurant needs to know what it sold, what the food cost, what it spent and what it owes. Anything longer is a chart nobody maintains and every posting lands in "Miscellaneous".

Rename or renumber anything freely — the automatic postings look accounts up by a hidden key, not by name or code. Accounts marked system cannot be deleted for that reason.

What posts automatically

WhenThe books record
A sale closesCash or card in, revenue out, tax owed, tips owed, discounts given — plus the food leaving stock at cost.
A delivery is booked inStock up, supplier owed.
A supplier is paidSupplier owed down, bank or cash down.
An expense is recordedThe category's account up, bank or cash down.
Stock is wasted or countedWastage or variance, against stock.
A pay run is approvedWages, tips discharged, net owed to staff.

Tax and tips are never revenue. Tax collected is money held for the authority; tips belong to the staff. Both are debts, and booking either as income overstates the profit built on it.

Four rules

  1. Debits equal credits. An unbalanced journal cannot be saved.
  2. A journal is never edited. A mistake is corrected by a reversing journal that quotes it, so the books show both the error and the correction.
  3. One posting per source. A replayed sale is a no-op, not double books.
  4. Nothing lands in a closed period.

Statements

Trial Balance, Profit & Loss and Balance Sheet all read the same journal lines, so they agree with each other by construction. Each says plainly whether it balances rather than leaving you to add it up.

Period close

Finance → Period Close. Closing a month stops anything being posted or backdated into it, so the figures you gave your accountant in March cannot quietly change in June. A correction after a close is a journal dated today. Reopening a month is possible and is written to the activity log.

Expenses

Finance → Expenses. Rent, power, wages, card fees. Food is not entered here — a goods receipt already records what was spent on ingredients, and entering it twice is the fastest way to produce a profit figure that disagrees with the bank.

Reports

ReportAnswers
SalesRevenue by day, by hour, by order type, by channel, by payment method and by staff member. Average check, covers, and the exceptions worth a second look — voids, discounts, refunds.
Food costGross margin per item, and the menu-engineering quadrants: what sells and makes money, what sells and does not, and what does neither.
InventoryStock valuation, what is below its reorder level, wastage, and the variance a stocktake found.
FinancialProfit and loss from the operational data, expenses by group, and a tax summary for a return.

Every report takes a period and a branch, compares against the previous period, exports to CSV, and prints. Printing uses the browser, which means a PDF on every platform without Resto shipping a PDF engine.

Charts are drawn in CSS rather than canvas: they print, they follow the theme, they need no JavaScript, and they survive being saved as a PDF.

Activity log

Staff → Activity Log. Every void, discount, price override, refund, timesheet correction, reversed journal and reopened period, with who did it, when, from which address.

This is the trail restaurant owners buy POS software for. Filter by person, by action type and by period.

REST API

For a delivery aggregator, a self-order kiosk, a dashboard of your own.

Tokens

Settings → API Tokens. Create a token, choose which member of staff it acts as, and optionally limit it to particular sections. The token is shown once — only a hash is stored, and a token list that can show you the secret is a token list that leaks every secret.

A token can never do more than its owner. Take a permission away from somebody and their integrations lose it too.

Calling it

curl https://yourdomain.com/api/v1/ping \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Accept: application/json"

Every response has the same shape — data under data, pagination under meta — so a client never has to guess where the payload is.

Endpoints

MethodPathNeedsWhat it does
GET/api/v1/pingany tokenConfirms the token works and reports what it may reach.
GET/api/v1/menumenuThe menu priced for a channel and order type, with modifiers and availability.
GET/api/v1/ordersordersOrders, filterable by branch, status, channel and date.
POST/api/v1/ordersordersCreates an order.
GET/api/v1/orders/{uuid}ordersOne order in full, with lines, payments and delivery.
PATCH/api/v1/orders/{uuid}/statusordersMoves an order along.
GET/api/v1/stockinventoryLevels and values, optionally only what is low.
GET/api/v1/ingredientsinventoryThe ingredient list.
GET/api/v1/customerscustomersCustomers, searchable by name or phone.
GET/api/v1/reservationsreservationsBookings for a date.
GET/api/v1/summaryreportsThe day's numbers for a dashboard.

Creating an order

POST /api/v1/orders
{
  "uuid": "8f14e45f-ceea-467a-9e4c-3b1d2a5f7b90",
  "type": "delivery",
  "customer": { "name": "Sam", "phone": "07700 900001" },
  "lines": [
    { "variant_id": 12, "qty": 2, "modifiers": [{ "modifier_id": 5 }] }
  ]
}

Send a uuid and retries are free. Replaying the same one returns the existing order instead of creating a second. Prices are always taken from your database, never from the payload — a request claiming a steak costs a penny gets a steak at the menu price.

Rate limits and errors

120 requests a minute per token by default (api_rate_limit), counted per token rather than per address so several integrations behind one office connection do not throttle each other.

StatusMeans
401Missing, unknown, disabled or expired token.
403The token may not reach that section.
422The payload was rejected; errors says which field.
429Rate limited.
503This copy of Resto has not been installed yet.

Payment gateways

Settings → Payment Gateways. Two halves: what the till accepts, and whether the website can take a card.

At the till

Cash, card, store credit, gift card and on-account are set up for you. You can add your own — a meal voucher, a local wallet — and the flags are behaviour, not decoration:

FlagWhat it changes
Counts in the cash drawerWhether it reaches the cash-up. Tick it only for money that physically ends up in the till, or the drawer will never balance.
Can give changeHanding cash back against a card tap is a hole in the drawer, not a feature.
Pops the drawerOpens the till on payment.
Asks for a referenceAn auth code, a voucher number, a card serial.

Methods are switched off, never deleted — every payment ever taken names one, and removing it would leave old orders unable to say how they were settled. Cash cannot be switched off at all.

Card payments online

Through Stripe Checkout. The customer is handed to Stripe's own payment page and comes back afterwards, so the card number never touches your server — which keeps your PCI obligation to the shortest questionnaire there is. Installing a till should not hand you a compliance project.

  1. Create a Stripe account

    Copy the two API keys from its dashboard. Start with the test keys — they begin sk_test and pk_test.

  2. Paste them in and save

    Then press Test the connection. It asks Stripe whether the keys work, so you find out now rather than when a customer does.

  3. Add the webhook

    The screen shows the address. In Stripe, add it as an endpoint and subscribe it to checkout.session.completed. Stripe gives you a signing secret; paste that in too.

  4. Switch it on, and place a test order

    Stripe's test card is 4242 4242 4242 4242 with any future expiry. Check the order marks itself paid.

  5. Swap in the live keys

    Only once a test order has gone all the way through.

Without the signing secret, no payment will ever be recorded. That is deliberate. The browser is never allowed to say a payment succeeded — anyone can open the page it comes back to. Only a webhook that Stripe signed marks an order paid, and an unsigned, forged or stale one is refused before a single row is read.

What the customer sees

With it switched on, online checkout offers Pay now by card alongside paying on collection or to the rider. The order is created before the payment page opens, so a customer who abandons it leaves you an order to chase rather than nothing at all — and the tracking page carries a Pay by card button so they can come back and finish.

The confirmation comes from Stripe, not from the customer's browser, so an order can read as unpaid for a second or two after they return. It settles itself.

Refunds

Refund a card payment in the Stripe dashboard, then record the refund in Resto as usual so the books and the stock agree. Resto does not push refunds to Stripe — a refund issued by accident from a POS screen is very hard to take back.

Languages

Settings → Languages. Resto ships English, and can be translated into any of the languages listed there — including Arabic, which loads a full right-to-left stylesheet automatically.

There is no template to fill in. Every string in Resto is its own key — the English sentence itself — so the untranslated product reads as English by construction, and a string you have not got to yet falls back to English rather than going blank or showing you messages.save.

Translating

Open a language and you get every string the product uses, in pages of a hundred, with the English on the left and a box on the right. Filter to not translated yet to work through the gap, or search for a phrase you saw on screen.

Each page saves on its own and merges into what is already there, so translating page four does not wipe pages one to three.

Translating offline

Download gives you a JSON file with every string, translated or not — which is also the template to hand to a translator. Import takes it back. Anything in the file that this version does not use is ignored rather than stored, so an edited file cannot fill the table with junk.

Placeholders

Some strings contain a placeholder like :count or :name. Keep them exactly as they are, in whatever position the sentence needs — the value is substituted at the placeholder, so moving it is fine and renaming it is not.

Switching one on

A language has to be turned on before it appears in the language menu. The default language is always available whatever its switch says — otherwise the menu would offer a language the site will not serve. Change the default on General Settings.

Backups

Two things need backing up:

  1. The database. Everything is in it. Use whatever your host provides — cPanel, a scheduled mysqldump, your provider's snapshots.
  2. public/uploads/. Logos and menu images live here, not on a storage disk.
mysqldump -u USER -p DATABASE > resto-$(date +%F).sql
tar -czf resto-uploads-$(date +%F).tar.gz public/uploads

Keep a copy of .env somewhere safe too. It holds APP_KEY, and restoring a database without the key it was encrypted alongside will sign everybody out and invalidate saved sessions.

Updating

A release is a ZIP. There are two ways to install it: let Resto do it from Settings → Backup & Update, or copy the files yourself and run the database step afterwards. Both keep your data, and neither needs a shell. The version you are on is in the footer of every back-office page, and in version.txt at the root of the install.

Pick a quiet moment. While an update runs the site is offline for everyone else — tills, kitchen screens and the online shop included — usually for a minute or two.

Before you start

From the browser

  1. Open the updater

    Settings → Backup & Update → Install an update. The page is /system-update, and it needs the Settings permission.

  2. Upload the release ZIP

    Drop it on the page. A marketplace download sometimes wraps the release in a second ZIP next to this documentation — upload that as it is, and Resto finds the release inside.

  3. Read the checks

    Before anything changes, the page confirms the package is complete and newer than what is installed, the server's PHP version and extensions are enough, the application folders are writable, there is disk space, the database answers, and no other run is in progress. A failed check blocks the update and says why.

  4. Press Install

    The run is a chain of short steps you can watch: a backup of the database and the files, the new release unpacked to one side, the site put into maintenance, the files swapped in one move, the migrations, your translation edits carried over, caches cleared, and a health check of the result. Keep the tab open.

  5. Hard-refresh

    Ctrl + Shift + R (Cmd on a Mac) once the page says it is done. If anything looks unstyled, the browser is still holding the old files.

If something fails after the files are swapped, the updater rolls itself back: the previous files and the database come back from the backup it just took, and the page says so. If the run stops part-way — a closed tab, a server timeout — nothing is lost. Return to the same page and press Continue where it stopped, or Roll back to the previous version. The page stays reachable while the rest of the site is in maintenance, so it doubles as the way out of an interrupted run.

Backups taken by the updater are listed at the bottom of the same page. Each holds the database, the replaced files and .env, stored under storage/app/updater/ where the web cannot reach them. The newest three are kept by default; change the number there. Any of them can be restored from the page, which puts both the files and the database back as they were before that update.

.env, storage/ and public/uploads/ are never touched, in either direction. Translation edits made in Settings → Languages survive too: an edited string keeps your wording, an untouched one takes the release's, and a language the release does not ship stays as it was.

By hand

The route to take when the browser updater cannot run — a 1.0 install, a package that fails its checks, a host you would rather do by FTP.

  1. Back up first

    Database and public/uploads/. Every time.

  2. Copy the new release over the old one

    Keep your own .env, public/uploads/ and storage/. Everything else can be replaced.

  3. Update the database

    Open /update and press Update database. It runs the outstanding migrations and clears the caches; a large database can take a few minutes, so keep the tab open.

  4. Hard-refresh

    Ctrl + Shift + R, as above.

The install marker stays where it is, so the wizard does not reappear.

A hand copy replaces lang/, and with it any translation edits. Download each language you have edited from Settings → Languages first, and upload it again afterwards — or use the browser updater, which carries the edits over by itself.

Coming from 1.0

1.0 has no updater page, so the first upgrade is by hand. Copy the new files, then open /update — the page arrives with them. After that:

Troubleshooting

SymptomCause and cure
Every page redirects to /setupstorage/app/installed is missing. Finish the wizard, or create the file if the install is genuinely complete.
/setup loads on a live siteSame file, missing. Anyone reaching it could reinstall over you — create it immediately.
Blank white pageAlmost always a permission problem. Make storage/ and bootstrap/cache/ writable, then check storage/logs/.
500 after an updateStale cache. Open /update and press Update database, or run php artisan optimize:clear.
The updater refuses the ZIPRead the check that failed. Most often the package is the version already installed, or older — only a newer release goes in.
An update stopped part-wayOpen /system-update and press Continue where it stopped, or roll back. The page works while the site is in maintenance. See Updating.
No styling anywherepublic/build/ is missing or the document root is wrong. Confirm the domain points at public/.
An item will not appear on the tillIt has no price in any book, it is off for that channel, it is outside its schedule, or it is 86-ed.
The online shop says it is closedOpening hours for today, accepts online orders switched off, or the branch is inactive. All three are on the Online Store screen.
The shop refuses every deliveryNo delivery zone covers the address — or no zones exist at all.
Stock is not movingThe item has no recipe, or inventory_deduct_on_sale is off.
The cash-up is shortCheck Staff → Shifts for cash movements out of the drawer, and the dispatch board for cash still on a rider.
An order has no journalThe chart of accounts was incomplete when it closed. Install the defaults on the Chart of Accounts screen; a posting failure is recorded in the activity log and never blocks a sale.
Kitchen screen not updatingIt polls; check the device actually has a connection. Nothing here needs websockets.
Nothing prints after paymentPrint automatically when an order is paid is off. Switch it on, or press Receipt on the till after the sale.
Kitchen tickets do not print (browser)No station screen is open beside the printer, or its printer icon is off. See Printing through the browser.
Tickets stay Waiting (Resto Print app)The app is not running, or the computer is off or asleep. Print app connections shows whether it is online.
Jobs Failed: "not matched to a printer"That Resto printer has no printer chosen in the app on the computer. Choose one, then Retry.
The app says the key was refusedThe connection was removed in Resto. Create a new key and connect again.
Receipts print a long blank tailSet the paper size in the printer's Windows driver to the roll (58 or 80 mm), not A4 or Letter.

Where the logs are

storage/logs/laravel.log. Turn APP_DEBUG on in .env only long enough to read an error, then turn it back off — a debug page on a live site leaks your configuration.

Deliberately not here

Every link in the sidebar opens a real screen. A few things a restaurant system could plausibly do are absent on purpose, and this guide would rather name them than let you find out:

Changelog

1.0

First release. POS with offline support, kitchen display and printed tickets, dining room and waiter app, recipe-level inventory, purchasing, QR menu and online ordering with card payments, delivery, reservations, customers with loyalty and coupons, staff with attendance and payroll, double-entry accounting, reports and a REST API — plus a browser installer, a translation manager and database backups.

Credits & support

Resto is built on Laravel 13 with Blade, Tabler UI and Alpine.js. QR codes are drawn by bacon/bacon-qr-code. Everything else is written for this product.

If something here does not match what you see on screen, the product is right and this document is wrong — please report it, and it will be corrected.

Resto documentation · version 1.0
Thank you for buying it.