Restaurant floors run on state: which tables are free, which orders are firing, who is logged in. Restauceo manages that state with a Vue 3 and Vite single-page app talking to a Laravel API — reactivity on the screen, transactions on the server, and a clean contract between them.
Stores, services, views — in that order
The frontend splits by responsibility: stores hold
Pinia state, services own the Axios calls,
views render, composables share logic.
API knowledge lives in exactly one layer, so when an endpoint
changes, one file changes. Components stay gloriously dumb about
HTTP.
Sanctum draws the line
Authentication follows the proven Laravel pattern — public login and registration, everything else behind Sanctum:
Route::post('/login', [AuthController::class, 'login']);
Route::post('register', [AuthController::class, 'register']);
Route::middleware('auth:sanctum')->group(function () {
Route::post('logout', [AuthController::class, 'logout']);
Route::get('/me', ...);
Route::get('/tables', ...);
Route::post('/tables', ...);
Public doors stay minimal and explicit; the moment a request touches business data, it carries a token. No exceptions, no special cases to audit later.
Tables are the domain
A restaurant app revolves around tables — list them, inspect one, open new ones. Modeling the domain object directly as REST resources keeps the frontend predictable: one resource, one store module, one set of views. When the business thinks in tables, the API should too.
Skeletons beat spinners
The client ships a dedicated skeleton stylesheet so loading states mirror the real layout instead of flashing generic spinners. Perceived performance is a design decision: show the shape of the answer while the answer travels.
Takeaway
Line up the seams — stores to services, services to resources, resources to the business — and a two-sided app stays boring in the best way: each side changes without breaking the other.