Architecture
Omega Social Media is a Laravel 12 application that serves several front ends from one codebase: two Vue 3 single-page apps (desktop and mobile web), Livewire-based business and authentication pages, a Blade admin panel, and a Sanctum-protected JSON API consumed by the Expo mobile app. Real-time features run on Laravel Reverb, background work runs on Horizon, and money flows through Stripe, Stripe Connect, and an internal credits ledger.
Overview
- One backend, several clients —
bootstrap/app.phpregisters separate route groups with their own middleware: web pages, the admin panel underAPP_ADMIN_PREFIX,/businesspages,/apiroutes, and payment webhooks that run without middleware. - Dual SPA — Vite builds separate entry points for the desktop and mobile web apps (
resources/js/spa/apps/desktopandresources/js/spa/apps/mobile), both using Vue 3, Vue Router, Pinia, and PrimeVue. - Livewire — Business account, ads, jobs, marketplace, onboarding, linker, and withdrawal pages are Livewire components under
app/Livewire/. - Mobile-first API — The mobile app uses
/api/mobile, a dedicated route file whose responses follow{"status": true/false, "message": "...", "data": ...}. - Queue-based media processing — Video and audio conversion and compression run as queued jobs using FFmpeg.
- Driver-based payments — A payment gateway interface, factory, and per-purpose payment handlers keep Stripe-specific code in one driver.
Web Application
Route Groups
bootstrap/app.php
- Admin routes (
routes/admin/web.php) under the admin prefix withweb,auth, andadminmiddleware. - Public and authenticated web routes (
routes/web.php,routes/social.php,routes/document.php,routes/downloads.php) behindrestrict.ip,device.identifier, andterminatormiddleware. - Business routes (
routes/business.php) under/business, requiring authentication anduser.status. - API routes (
routes/api.php) under/apiwith request logging. - Payment webhooks (
routes/webhooks/payment_webhooks.php) registered without middleware.
Middleware
app/Http/Middleware/
Aliases include user.status, device.identifier, terminator, restrict.ip, sided.layout, api.key, admin, log.request, and mobile.redirect, plus Spatie role, permission, and role_or_permission. Language and online-presence middleware are appended to both web and API stacks.
Controllers
app/Http/Controllers/
Grouped into Admin, Api (with Ad, Admin, Mobile, User), Business, Downloads, and User (auth, language, onboarding, theme).
Services
app/Services/
Domain services: Ad, Agora, Auth, Blacklist, Censor, Credits, Currency, Discover, Donations, Feedback, Filesystem, Geolocation, Language, Payment, Reaction, Sms, Text, Translation, World.
Models & Enums
app/Models/, app/Enums/
Models include User, Post, Story, StoryFrame, Comment, Chat, Message, Media, Product, JobListing, Ad, BusinessAccount, LiveStream, LiveStreamMessage, Donation, CreditPack, CreditTransaction, Payment, WithdrawalRequest, Report, and more. Enums are grouped by domain (Ad, Chat, LiveStream, Payment, Wallet, and others).
Mobile API
All mobile endpoints are registered in routes/api/mobile.php under the mobile prefix of the API (final path /api/mobile/...) with a throttle:120,1 limiter. Auth routes are public; all other groups require auth:sanctum.
- Name
/auth- Type
- Authentication
- Description
login,social-login,register,forgot-password,reset-password, andlogout(authenticated). Login and registration issue a Sanctum plain-text token.
- Name
/user- Type
- Users & Social Graph
- Description
Fetch and update user details, username availability, followers and followings, follow/unfollow, block/unblock, and user search.
- Name
/post- Type
- Posts, Comments & Stories
- Description
Discover, following, nearby, by-id, user, saved, hashtag, explore, and reel feeds; like, save, pin, delete; text, image, video, and reel creation; comments and replies; stories (fetch, create, view, like, delete).
- Name
/chat- Type
- Messaging
- Description
List, create, send, fetch messages, mark as read, delete message, and delete chat.
- Name
/live- Type
- Live Streaming
- Description
List active streams, start, join, leave, end, chat, messages, details, donate, leaderboard, and earnings.
- Name
/credits- Type
- Credits
- Description
Balance, packs, purchase, create payment intent, Stripe config, and transaction history.
- Name
/stripe-connect, /withdrawal- Type
- Creator Payouts
- Description
Connect status, onboarding, refresh, dashboard link, and disconnect; withdrawal dashboard, request, credit conversion, and history.
- Name
/marketplace, /jobs, /campaigns, /ads- Type
- Commerce
- Description
CRUD, bookmark, and publish/unpublish for products and job listings; campaign CRUD, publish, pause, and payment; ad fetch and click tracking.
- Name
/account-settings, /settings, /push, /misc- Type
- Account & Utilities
- Description
Account, credentials, email/phone confirmation, password, notification and privacy settings, sessions, language, social links, personal info, verification status; app settings and file upload; push token register/unregister; notifications and reports;
/broadcasting/authfor WebSocket channels.
routes/api.php also exposes /sanctum/token (email, password, and device_name return a token) and Sanctum-protected groups for the web SPA (timeline, reels, stories, profile, follows, marketplace, jobs, messenger, explore, recommendations, and more).
Real-time and Queues
WebSockets (Reverb)
Broadcasting uses Laravel Reverb. Channels are defined in routes/channels.php:
App.Models.User.{id}— private to the matching user.App.Models.Chat.{chatId}— authorized only for participants of the chat.live-stream.{uuid}— authorized while the stream status is Live.
Live stream events are StreamChatMessageEvent, DonationReceivedEvent, ViewerCountUpdatedEvent, and StreamEndedEvent. The web client uses Laravel Echo with pusher-js, configured through the VITE_REVERB_* variables. The mobile app builds its Echo instance from reverb_app_key, reverb_host, reverb_port, and reverb_scheme returned by the app settings endpoint, and authenticates private channels against /broadcasting/auth with its bearer token.
Queues (Horizon)
Horizon is configured in config/horizon.php with one supervisor consuming the default, high, and low queues on the redis connection, with auto balancing. It allows up to 15 processes by default, 10 in production, and 3 locally. The Horizon dashboard path defaults to omegalab/horizon (HORIZON_PATH).
Queued work includes:
ConvertAndCompressPostVideoandConvertAndCompressPostAudio(post media)ProcessStoryVideo(story videos)RegisterResourceViews(view counting)ProcessWithdrawalTransferJob(Stripe Connect transfers for withdrawals)
.env.example ships with QUEUE_CONNECTION=sync. Switch it to redis and run Horizon for real background processing.
Payments
Stripe & Cashier
The app uses Laravel Cashier 16 and the Stripe PHP SDK. A StripeEventListener listens for Cashier's WebhookReceived event. Payments go through PaymentIntentService, PaymentProcessService, and PaymentCaptureService, with a StripeDriver implementing the gateway interface and handlers for credit purchases (CreditPurchasePaymentHandler) and advertising (AdvertisingPaymentHandler).
Adding a Provider
app/Services/Payment/README.txt describes the steps: add a driver implementing PaymentGatewayInterface, register it in the gateway factory, add a logo and config entry in config/payment.php, create a webhook controller, and add its route to routes/webhooks/payment_webhooks.php.
Stripe Connect
StripeConnectService creates connected accounts, onboarding links, dashboard links, refreshes account status, creates transfers, and disconnects accounts. It is enabled with STRIPE_CONNECT_ENABLED. The README describes the integration as Stripe Connect with destination charges, and PLATFORM_COMMISSION_RATE (default 20) sets the platform commission.
Credits & Withdrawals
CreditService buys credit packs, adds and deducts credits inside database transactions, converts credits to cash, and lists transaction history. config/credits.php holds the cash-out rate (CREDITS_CASHOUT_RATE_CENTS, default 100 cents per credit), the minimum cash-out (CREDITS_MIN_CASHOUT, default 10 credits), and the cash-out commission (CREDITS_CASHOUT_COMMISSION_RATE, default 20). WithdrawalService and ProcessWithdrawalTransferJob handle withdrawal requests.
Live Streaming
Live streaming uses Agora. AgoraTokenService generates RTC tokens for a channel and uid, with a publisher role for the host and a configurable lifetime (AGORA_TOKEN_EXPIRY, default 3600 seconds). The LiveStreamController in the mobile API starts, joins, leaves, and ends streams. Chat messages, donations, viewer counts, and stream-ended notices are pushed to viewers over Reverb. DonationService spends credits on donations inside a database transaction and exposes the per-stream leaderboard and earnings. The web client uses agora-rtc-sdk-ng; the mobile app uses react-native-agora.
Mobile App
The Expo app in mobile/ is organized as:
Routing
mobile/app/
Expo Router file-based routes: (auth) (login, register, forgot password), (tabs) (home, explore, reels, create, live, marketplace, messages, notifications, profile), and stacks for chat, comments, followers, hashtag, jobs, live, marketplace, campaigns, credits, post, profile, settings, stories, Stripe Connect, and withdrawal.
API Layer
mobile/src/api/
An axios client (client.ts) that reads EXPO_PUBLIC_API_URL and attaches the bearer token stored in expo-secure-store, plus one module per backend area (auth, feed, posts, comments, stories, chat, live, credits, marketplace, jobs, campaigns, stripe-connect, withdrawal, and others).
State & Providers
mobile/src/store/, mobile/src/providers/
Zustand stores for auth and notifications. Providers for auth, TanStack Query, realtime (Echo), and Stripe.
Services & Hooks
mobile/src/services/, mobile/src/hooks/
websocket.ts (Laravel Echo over Reverb), pushNotifications.ts (Expo push registration), and hooks for Agora, infinite scroll, refresh, and Stripe payments.
UI
mobile/src/components/, mobile/src/theme/, mobile/src/i18n/
Shared components, NativeWind theme, and i18next translations.
Scheduled Tasks and Monitoring
Defined in routes/console.php:
story:cleardaily at 00:00 andchat:invite-clearweeklybackup:clean(Fridays 04:00) andbackup:run(Fridays 04:30) via Spatie Backup- Spatie Health schedule heartbeat every minute and daily pruning of old health check history
- Demo schedule registration via
DemoSchedule
Monitoring is provided by Horizon, Spatie Health, Sentry, Laravel Nightwatch, and the Opcodes log viewer. The application exposes a /up health route.