Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/astrxnomo/tourify/llms.txt

Use this file to discover all available pages before exploring further.

Tourify is a two-tier, cross-platform mobile tourism application. A React Native client built with Expo communicates exclusively over HTTP with a Laravel 13 REST API, which in turn persists data in a MySQL database. A Blade-based admin panel is served by the same Laravel application on the web routes, sharing all models and business logic with the API.

Mobile Client

Expo 54 / React Native 0.81.5 — runs on iOS, Android, and Web from a single codebase.

REST API

Laravel 13 with Sanctum 4.3 — stateless Bearer-token endpoints under /api/*.

Admin Panel

Blade web UI served on /admin/* routes — session-authenticated, protected by an is_admin middleware.

Database

MySQL — Eloquent ORM with polymorphic relationships for images, favorites, and reviews.

Request flow

1

Mobile app sends HTTP request

The Expo app calls a helper from services/post.js (e.g. get('/cities')). The helper reads the Bearer token from SecureStore and attaches it as an Authorization header together with Accept: application/json.
2

Laravel routes the request

Requests arriving at /api/* are handled by routes/api.php. Public routes (city list, place list, etc.) need no token. Protected routes are wrapped in middleware('auth:sanctum'), which validates the Sanctum personal-access token before the controller runs.
3

Controller processes and responds

API controllers under app/Http/Controllers/ query Eloquent models, apply any business logic, and return JSON responses. Validation errors return a 422 with an errors map; other failures return an appropriate HTTP status with a message key.
4

App consumes the JSON response

services/post.js inspects response.ok. On success it returns the parsed JSON; on failure it extracts json.message or the first validation error string and throws it so calling hooks can surface it to the UI.

Admin panel flow

Requests to /admin/* are handled by routes/web.php with the web, auth, and is_admin middleware stack. Authentication uses Laravel’s session/cookie mechanism rather than Sanctum tokens. The Blade views under resources/views/admin/ render server-side HTML — no separate API calls are needed.

Authentication layers

ContextMechanismGuard
Mobile APISanctum personal-access tokens (Bearer)auth:sanctum
Admin panelLaravel session + cookiesauth (web guard)
After a successful POST /api/auth/login, the API returns a token string. The mobile app persists it via storage.setItem('auth_token', token) (SecureStore on native, localStorage on web). Every subsequent request reads that token and attaches it as Authorization: Bearer <token>. The admin panel uses POST /admin/login which sets a session cookie. All admin routes require both the auth guard and the is_admin middleware, which checks that the authenticated user’s role is admin.

Push notifications

1

Request permission

usePushNotifications (called from Router.js) calls Notifications.requestPermissionsAsync(). On Android it also creates a default notification channel with MAX importance.
2

Obtain Expo push token

Notifications.getExpoPushTokenAsync() returns an ExpoToken[...] string unique to the device/user pair.
3

Register token with the API

The hook calls POST /api/push-token with { token }. The NotificationController stores the value in users.push_token for the authenticated user.
4

Admin triggers notification

From the admin panel (POST /admin/notifications), an admin selects a recipient and composes a title + message. The AdminNotificationController calls the Expo Push HTTP API with the stored push_token, creates a Notification record in the database, and the device displays the alert.
5

App receives and surfaces notification

Notifications.addNotificationReceivedListener fires in usePushNotifications, updating the local notification state. Users can also browse their notification history via GET /api/notifications in the Notifications screen.
Push token registration is treated as non-critical: if POST /api/push-token fails (e.g. the device is offline at startup), usePushNotifications silently swallows the error and the rest of the app continues to work normally.

Directory structure

tourify/
├── backend/
│   ├── app/Http/Controllers/        # API controllers
│   ├── app/Http/Controllers/Admin/  # Admin web controllers
│   ├── app/Models/                  # Eloquent models
│   ├── database/migrations/         # DB schema
│   ├── resources/views/admin/       # Blade admin views
│   └── routes/
│       ├── api.php                  # REST API routes
│       └── web.php                  # Admin panel routes
└── frontend/
    ├── views/public/                # Screen components
    ├── views/components/            # Reusable UI components
    ├── hooks/                       # Custom React hooks
    ├── services/                    # HTTP and storage services
    └── context/                     # AuthContext

API route map

MethodPathAuthDescription
POST/api/auth/registerRegister a new user
POST/api/auth/loginObtain a Sanctum token
POST/api/auth/forgot-passwordSend password-reset email
POST/api/auth/logoutRevoke current token
GET/api/auth/meReturn authenticated user
MethodPathDescription
GET/api/citiesList all cities
GET/api/cities/{city}Single city with places + events
GET/api/categoriesList all categories
GET/api/categories/{category}Single category with places
GET/api/placesList all places
GET/api/places/{place}Single place with reviews + images
GET/api/eventsList all events
GET/api/events/{event}Single event with reviews + images
MethodPathDescription
POST/api/push-tokenSave Expo push token for authenticated user
GET/api/favoritesList user’s favorites
POST/api/favoritesAdd a favorite (polymorphic)
DELETE/api/favorites/{favorite}Remove by ID
DELETE/api/favoritesRemove by morph type + ID
POST/api/places/{place}/reviewsReview a place
POST/api/events/{event}/reviewsReview an event
GET/api/my/registrationsList user’s event registrations
POST/api/events/{event}/registerRegister for an event
DELETE/api/events/{event}/registerCancel registration
GET/api/notificationsList user’s notifications
PATCH/api/notifications/read-allMark all notifications as read
PATCH/api/notifications/{notification}/readMark single notification as read

Dependency versions

LayerPackageVersion
Backend runtimePHP8.3
Backend frameworkLaravel13
API authenticationLaravel Sanctum4.3
Mobile frameworkExpo~54.0.33
Mobile runtimeReact Native0.81.5
NavigationReact Navigation7
Push notificationsexpo-notifications~0.29.0
Secure storageexpo-secure-store~15.0.8

Build docs developers (and LLMs) love