Case Study
Bazar
Laravel 10 classifieds marketplace from the FreeLancer/bazar_P tree (same project as bazar_p on case-insensitive systems): Blade storefront with Laravel UI authentication, deep category navigation (sub through sub4), listings and product detail pages, mazad (auction listing) browsing, and an `/admin` dashboard for countries, cities, nested taxonomies, advertisements, sliders, contacts, and notifications. Parallel mobile JSON API under `/api` split into `guest-api.php` (login, register, password reset, catalog, home search, advertisements by geography) and `auth-api.php` (token-guarded profile, favourites, balance, post or list user ads, Firebase device token) with shared `lang` and `InitRequest` middleware.

Impact
One Laravel codebase the business could operate: staff manage taxonomy and ads in `/admin`, sellers use web or app against the same core tables.
Problem
A classifieds product has to serve both casual web visitors and mobile apps without duplicating business rules: category trees, listing quality, user balances, and staff moderation must stay consistent whether the client is Blade or JSON.
Solution
`RouteServiceProvider` wires four concerns: authenticated API controllers (`routes/auth-api.php` behind `auth:api` and the `api` token guard), public API controllers (`routes/guest-api.php`), an admin namespace under prefix `admin` with `admin` middleware, and the main `routes/web.php` site plus `Auth::routes()` from Laravel UI. Controllers stay namespaced under `App\Http\Controllers\Api`, `Admin`, and `Site` so web, admin, and mobile surfaces share the same models and validation.
Highlighted implementation
Route groups (RouteServiceProvider)
PHP$this->routes(function () {
Route::middleware(['api', 'auth:api', 'lang', 'InitRequest'])
->prefix('api')
->namespace($this->Api_namespace)
->group(base_path('routes/auth-api.php'));
Route::middleware(['api', 'lang', 'InitRequest'])
->prefix('api')
->namespace($this->Api_namespace)
->group(base_path('routes/guest-api.php'));
Route::middleware(['web', 'admin', 'lang'])
->prefix('admin')
->namespace($this->Admin_namespace)
->group(base_path('routes/admin.php'));
Route::middleware(['web', 'site', 'lang'])
->namespace($this->Site_namespace)
->group(base_path('routes/site.php'));
Route::middleware(['web', 'lang'])
->namespace('App\Http\Controllers')
->group(base_path('routes/web.php'));
});Testing & quality
PHPUnit 10 in the project for automated checks where written; manual passes on add-listing, search, and admin taxonomy edits after Laravel upgrades.
Architecture
API Structure
Guest API uses POST endpoints for home, search, hierarchical categories, and `Advertisement` queries (country, city, single ad, offers). Authenticated API posts cover profile updates, favourites, user advertisements, notifications, and Firebase token updates. CORS config includes `api/*` paths for mobile origins.
Data Flow
Listing publish or edit flows through form or API controllers into advertisement rows tied to category and geography keys; admin CRUD updates taxonomy and homepage sliders that both web and API readers consume on next request.
Backend Decisions
Chose Laravel’s built-in `token` API guard instead of bolting on Passport for this scope; centralized `InitRequest` on API groups for shared mobile headers or context; kept admin routes prefix-isolated from public URLs to reduce accidental exposure.
Challenges
Very deep category trees (four sub-levels) complicate admin AJAX endpoints and mobile payloads—keeping N+1 queries under control matters on listing grids. Web and API must agree on soft-deletes or visibility flags so an item hidden in admin does not still appear in cached mobile responses.
Technical Decisions
Laravel 10 baseline with `laravel/ui` for rapid auth scaffolding and `laravelcollective/html` where forms benefit from helpers; Guzzle available for outbound HTTP when integrations land; PHPUnit 10 for regression safety on critical paths.