ScanDine Docs

v1.0.0

1. Introduction & Features

ScanDine is a multi-tenant QR menu & ordering platform for restaurants. Diners scan a QR code at their table, browse the menu, place an order, and the order appears instantly on the kitchen display and can be forwarded to the restaurant's WhatsApp β€” no app to install for the customer.

  • Super-admin Manage restaurants, subscription plans, coupons, global settings and payment logs.
  • Owner Branches, menu categories & items, per-table QR codes, orders, staff, reports and billing.
  • Staff Live kitchen display with one-tap status changes (preparing β†’ ready β†’ served).
  • Customer Scan → menu → cart → order, with optional table number β€” no login.
  • Stripe and PayPal subscriptions with plan limits enforced in code.
  • Multi-language (English + Arabic RTL included), light/dark theme, currency per restaurant.
Customer Menu UI
The modern, intuitive customer ordering experience.

2. Server Requirements

ComponentMinimum
PHP8.2 or higher
DatabaseMySQL 8.0+ (or MariaDB 10.6+)
PHP extensionspdo_mysql, mbstring, openssl, tokenizer, xml, ctype, json, bcmath, fileinfo
Web serverApache or Nginx with URL rewriting
Node (build only)18+ β€” only needed if you recompile assets

Compiled CSS/JS ship in public/build, so you do not need Node on the production server unless you customise the design.

3. Installation (Web Wizard)

The easiest way to install ScanDine is the built-in wizard.

  1. Upload the contents of main-files/ to your server. Point your domain's web root at the public/ folder.
  2. Create an empty MySQL database and a database user with full privileges on it.
  3. Run composer install --no-dev --optimize-autoloader in the app folder.
  4. Visit https://your-domain.com/install in a browser.
  5. Step 1 β€” Requirements: the wizard checks PHP, extensions and folder permissions. Resolve any red items.
  6. Step 2 β€” Database: enter your DB host, name, user and password. The wizard tests the connection before continuing.
  7. Step 3 β€” Application: set the app name, URL, timezone, and create your super-admin account. Migrations run automatically.
  8. Step 4 β€” Payments (optional): paste Stripe / PayPal keys, or skip and add them later.
  9. Step 5 β€” Done: the installer locks itself and you can sign in.
Installer Wizard Step 1
The automated web installer wizard ensures your server meets all requirements.

After installation the wizard is permanently disabled by a lock file at storage/app/scandine_installed.lock. Delete that file only if you intend to reinstall.

4. Manual Installation (Advanced)

cp .env.example .env
composer install --no-dev --optimize-autoloader
php artisan key:generate
# edit .env: set DB_* and APP_URL
php artisan migrate --force
php artisan db:seed --class="Database\Seeders\PlanSeeder" --force
php artisan storage:link
# create your admin:
php artisan tinker
>>> \ScanDine\Models\User::create(['name'=>'Admin','email'=>'you@example.com','password'=>bcrypt('secret'),'role'=>'super_admin','is_active'=>true]);

To load the full demo dataset instead, run php artisan db:seed.

β˜… License & Activation

ScanDine uses your Envato purchase code to activate each installation, in line with Envato's licensing policy.

Where to find your purchase code

On CodeCanyon, open Downloads, find ScanDine, and click β€œLicense certificate & purchase code” β†’ PDF or text. The code looks like xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.

CodeCanyon Download Dropdown
Download your purchase code from your CodeCanyon account.

Entering it during installation

The installer's License step asks for the code. It is verified once against Envato; on success the install continues. After installation you can review it under Super-admin β†’ License.

β€œSupported until” β€” what it means

This is your Envato support period, not an app expiry. The application keeps working after this date β€” only your access to author support changes. The purchase code remains valid for the lifetime of the item license.

Moving to a new server / domain

Open Super-admin β†’ License β†’ Deactivate on the old domain, then run the installer (or the /license-required page) on the new domain and enter the same purchase code.

Offline behaviour

Activation is checked against a single local database row on every page load β€” no internet call is made during normal use. A courtesy re-verification runs at most once every 30 days and never blocks the app, so ScanDine continues to work offline or on poor connections.

β˜… Dynamic Settings (no .env edits)

After installation, every setting β€” SMTP, Stripe, PayPal, branding and logos β€” is configured at runtime from the UI. No file edits, no restarts. Settings resolve in this order, most specific wins:

Restaurant override  β†’  System default (super-admin)  β†’  .env / built-in default
  • Super Admin β†’ Settings sets global defaults for the whole platform.
  • Owner β†’ Settings sets per-restaurant overrides (branding, logo, and an optional SMTP override).
  • Secrets (SMTP password, API secret keys, webhook secrets) are encrypted at rest and shown masked as β€’β€’β€’β€’β€’β€’β€’β€’ with a one-click Reveal that re-masks after 30 seconds.

The .env / SCANDINE_* keys below are only a fallback for first boot. Once installed, manage everything from the in-app Settings screens.

5. Stripe Setup

The recommended way is Super Admin β†’ Settings β†’ Stripe: paste your keys, toggle Enable Stripe, and use Test connection to confirm. Keys are stored encrypted in the database. The .env values below are only a first-boot fallback.

  1. Create a Stripe account and open the Developers → API keys page.
  2. Copy the Publishable key and Secret key into the installer (or .env):
    SCANDINE_STRIPE_KEY=pk_live_xxx
    SCANDINE_STRIPE_SECRET=sk_live_xxx
    SCANDINE_STRIPE_WEBHOOK_SECRET=whsec_xxx
  3. In Developers → Webhooks, add an endpoint pointing to https://your-domain.com/webhooks/stripe.
  4. Subscribe to: checkout.session.completed, customer.subscription.created, customer.subscription.updated, customer.subscription.deleted, invoice.payment_succeeded, invoice.payment_failed.
  5. Copy the endpoint's signing secret into SCANDINE_STRIPE_WEBHOOK_SECRET.

Every webhook is signature-verified. Unsigned or tampered requests are rejected with HTTP 400.

6. PayPal Setup

  1. In the PayPal Developer Dashboard, create a REST API app and copy its Client ID and Secret.
  2. Set the credentials and mode:
    SCANDINE_PAYPAL_CLIENT_ID=xxx
    SCANDINE_PAYPAL_SECRET=xxx
    SCANDINE_PAYPAL_MODE=live        # or sandbox
    SCANDINE_PAYPAL_WEBHOOK_ID=xxx
  3. Add a webhook for https://your-domain.com/webhooks/paypal and subscribe to BILLING.SUBSCRIPTION.ACTIVATED, BILLING.SUBSCRIPTION.CANCELLED, PAYMENT.SALE.COMPLETED.
  4. Copy the webhook ID into SCANDINE_PAYPAL_WEBHOOK_ID β€” it is used to verify each event with PayPal.

As with Stripe, the preferred place to enter these is Super Admin β†’ Settings β†’ PayPal, where the client secret and webhook ID are stored encrypted and a Test connection button verifies the credentials.

β˜… SMTP Email Setup

ScanDine sends transactional emails (new-order alerts, payment receipts, expiry reminders, signup notices) through an SMTP server you configure entirely from the UI β€” no .env editing required.

  1. Open Super Admin β†’ Settings β†’ Email / SMTP.
  2. Enter your Host, Port (587 for TLS, 465 for SSL), Encryption, Username and Password, plus the From address and From name.
  3. Click Send test email, enter a recipient, and confirm it arrives. The result shows inline.

The password is stored encrypted. Mail is built from these database values at send time, so changes take effect immediately with no restart.

Per-restaurant override

An owner can send their own order emails from their own mailbox: Owner β†’ Settings β†’ Email, turn off β€œUse global SMTP settings”, and enter the restaurant's SMTP details. Leave it on to inherit the platform default.

If no SMTP host is configured, ScanDine falls back to the framework's default mailer (the MAIL_* driver in .env) so the app never errors on unset credentials.

β˜… Branding & Logo Setup

Branding is dynamic at two levels β€” global (super-admin) and per-restaurant (owner).

Global branding (Super Admin β†’ Settings β†’ Branding)

  • App name β€” used in page titles and the admin panel.
  • Logo & favicon β€” drag-and-drop upload (JPG, PNG, WebP, SVG Β· max 2 MB). The new logo appears in panel headers immediately.
  • Brand colour β€” pick from presets or a custom hex; used for accents.
  • Tagline, support email, support phone.

Per-restaurant branding (Owner β†’ Settings β†’ Branding)

  • Restaurant logo β€” shown on the customer menu header, order confirmation, kitchen display and the owner sidebar. If none is uploaded, a clean initials avatar is generated automatically.
  • Brand colour β€” applied only to the customer menu (buttons and active tabs) via a runtime CSS variable; it does not affect the admin panel.
  • Tagline β€” shown under the restaurant name on the menu.

Uploaded files are stored under storage/app/public/branding and served through the storage symlink β€” never from an executable path. Run php artisan storage:link once after install.

7. WhatsApp Setup

WhatsApp hand-off uses the free click-to-chat link β€” no paid WhatsApp Business API required.

  1. Set the restaurant's WhatsApp number in Owner → Settings (or per-branch).
  2. When a customer places an order, the confirmation screen shows a β€œSend order via WhatsApp” button that opens WhatsApp with the order pre-filled, addressed to the venue.

Disable the feature globally with SCANDINE_WHATSAPP_ENABLED=false.

8. Multi-language & RTL Setup

English and Arabic (RTL) ship out of the box. The UI language follows the restaurant's locale, and visitors can switch language using the toggle in the header.

Adding a language

  1. Create lang/<code>.json by copying lang/ar.json and translating the values.
  2. Register it in config/scandine.php under locales, setting dir to rtl or ltr.
RTL Dashboard in Arabic
The entire interface perfectly flips to support Right-to-Left languages natively.

9. Adding Your First Restaurant (Super-admin)

  1. Sign in with your super-admin account at /login.
  2. Create subscription Plans (or use the seeded Starter / Professional / Enterprise).
  3. Create the restaurant's owner account from tinker or let the owner self-onboard, assigning role = owner and the restaurant_id.
  4. From Restaurants you can view any tenant and activate / suspend it.

10. Owner Panel Guide

  • Branches β€” add each physical location.
  • Menu categories & items β€” build the menu; items support an image, tags, price and availability toggle.
  • Tables & QR β€” create tables and download a printable QR code for each (it links to a signed, tamper-proof menu URL).
  • Orders β€” filter by status, open an order, change its status.
  • Staff β€” create kitchen / waiter / manager accounts and assign them to branches.
  • Reports β€” 30-day orders and revenue, plus top-selling items.
  • Settings β€” currency, language, theme, timezone and logo.
Owner Dashboard UI
The comprehensive dashboard gives restaurant owners full control and insights.

11. Staff Kitchen Display Guide

The kitchen display (/kitchen) shows three live columns β€” Pending, Preparing, Ready. It refreshes every few seconds with no page reload and needs no websocket server. Tap a card to advance the order.

Kitchen Display System
The real-time Kitchen Display System syncs orders instantly.

12. Subscription Plans & Billing

Each plan defines limits: branches, menu items, monthly orders and staff. Limits are enforced in code β€” attempting to exceed one shows a friendly upgrade prompt. Owners subscribe from Billing, choosing Stripe or PayPal. Webhooks keep the local subscription in sync and log every payment event to the super-admin's Payment logs.

13. Troubleshooting

SymptomFix
Blank page / 500 errorCheck storage/logs/laravel.log; ensure storage and bootstrap/cache are writable.
β€œRoute [scandine.login] not defined”Run php artisan route:clear then php artisan optimize.
Assets not loadingConfirm public/build was uploaded and run php artisan storage:link.
QR opens β€œ403”The signed link expired or the domain changed; regenerate the QR after fixing APP_URL.
Installer keeps redirectingThe lock file is missing; finish the wizard or create storage/app/scandine_installed.lock.
Migrations failVerify MySQL 8+ and that the DB user can create tables.
Stripe webhook 400Wrong SCANDINE_STRIPE_WEBHOOK_SECRET; copy the exact signing secret.
Emails not sendingConfigure the MAIL_* settings in .env.
Wrong currency symbolSet the restaurant currency (ISO code) in Owner → Settings.
Cannot delete a planPlans with active subscriptions are protected; move tenants first.

14. FAQ

Do customers need an app?

No. They scan the QR and order in the browser.

Can one restaurant have several branches?

Yes β€” branch count is governed by the subscription plan.

Is my data isolated from other restaurants?

Yes. Every tenant query is automatically scoped to its own restaurant at three layers (global scope, middleware and policies).

Can I use only Stripe, or only PayPal?

Yes β€” configure whichever you want; only configured gateways appear at checkout.

Can I rebrand it?

Yes β€” entirely from the UI. Super Admin β†’ Settings β†’ Branding sets the app name, logo, favicon, colour and tagline at runtime. No code or .env changes needed.

Do I have to edit .env to change SMTP or payment keys?

No. After install, SMTP, Stripe, PayPal, branding and logos are all managed from the in-app Settings screens and stored (encrypted, for secrets) in the database. Changes apply instantly without a restart.

Can each restaurant have its own logo and colours?

Yes. Owners upload their own logo and pick a brand colour in Owner β†’ Settings β†’ Branding; it applies to that restaurant's customer menu only, fully isolated from other tenants.

Are my API keys and passwords stored safely?

All secrets (SMTP password, Stripe/PayPal secret keys, webhook secrets) are encrypted at rest with Laravel's encrypter and never rendered in HTML β€” they show masked with an authenticated, time-limited Reveal.

Does the app stop working if I go offline?

No. After the one-time activation, the licence check reads only the local database, so ScanDine keeps working offline and on unreliable connections. It is never silently disabled.

15. Changelog

v1.0.0 β€” Initial Release

  • Multi-tenant QR menu & ordering platform.
  • Super-admin, owner, staff and customer experiences.
  • Stripe & PayPal subscriptions with signature-verified webhooks.
  • Per-table QR generation, live kitchen display, WhatsApp hand-off.
  • English + Arabic (RTL), light/dark theme, per-restaurant currency.
  • Fully dynamic settings: SMTP, payment gateways, branding & logos configured at runtime from the UI β€” no .env edits or restarts.
  • Encrypted secret storage with masked reveal; cached settings resolver with per-tenant overrides.
  • Web installer wizard and rich demo data.