Markdown Converter
Agent skill for markdown-converter
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Sign in to like and favorite skills
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
A comprehensive Muslim dating and matchmaking platform built with Laravel 12, emphasizing cultural values, family involvement, and serious relationships. The platform modernizes traditional matchmaking while respecting Islamic cultural and religious values.
Tech Stack: Laravel 12, PHP 8.2+, Tailwind CSS 4.0, Laravel Reverb (WebSocket), Laravel Sanctum (API), PostgreSQL
Core Purpose: Islamic/Cultural Dating & Matchmaking with family involvement and serious commitment to marriage.
# Start all services (Laravel server + queue worker + logs + Vite) composer dev # Individual services php artisan serve # Laravel server (port 8000) php artisan reverb:start # WebSocket server (port 8080) php artisan queue:listen --tries=1 # Queue worker php artisan pail --timeout=0 # Real-time logs npm run dev # Vite dev server
# Run migrations php artisan migrate # Fresh database with seeders php artisan migrate:fresh --seed # Create new migration php artisan make:migration create_table_name # Rollback last migration php artisan migrate:rollback
# Run all tests (Pest) php artisan test # Run specific test file php artisan test tests/Feature/AuthTest.php # Run tests with coverage php artisan test --coverage # Code formatting (Laravel Pint) ./vendor/bin/pint
# Clear all caches php artisan optimize:clear # Production optimization php artisan optimize php artisan config:cache php artisan route:cache php artisan view:cache
# Access Laravel Telescope (development debugging) # http://localhost:8000/telescope # Access Laravel Pulse (performance monitoring) # http://localhost:8000/pulse # Access Laravel Horizon (queue monitoring) php artisan horizon # http://localhost:8000/horizon # Access API documentation (Swagger) # http://localhost:8000/api/documentation
YorYor follows a strict layered architecture:
Service Layer Pattern:
AuthService, MediaUploadService, VerificationServiceExample Service Usage:
// Controller only orchestrates public function __construct( private AuthService $authService, private NotificationService $notificationService ) {} public function register(Request $request) { $validated = $request->validate([...]); $result = $this->authService->register($validated); $this->notificationService->sendWelcomeEmail($result['user']); return response()->json($result); }
Real-Time with Laravel Reverb:
private-chat.{chatId}, private-user.{userId}resources/js/echo.jsShouldBroadcast interfaceDB::beginTransaction()routes/api.php - Mobile/API endpoints (Sanctum auth)routes/web.php - Landing pages (public)routes/user.php - Authenticated user routes (web middleware)routes/admin.php - Admin dashboard routes (admin middleware)Database: PostgreSQL (default connection configured)
Core Pattern: User → Profile → Extended Profiles
users (authentication, basic info - password varchar(255) for future-proof hashing)profiles (core profile data with soft deletes)user_cultural_profiles, user_career_profiles, user_physical_profiles, user_family_preferences, user_location_preferencesCommunication: Chat → Messages → Reads
chats (conversations)chat_users (pivot: participants with indexes)messages (chat messages)message_reads (read receipts)calls (video/voice calls linked to messages)Matching: Likes → Matches
likes (one-way interest)dislikes (pass/reject)matches (mutual likes - created automatically, with soft deletes)Reporting System:
user_reports (comprehensive reporting with severity, priority, evidence)report_evidence (file attachments for reports)report_categories (report categorization)Key Model Names:
UserMatch model → matches table (renamed from Match to avoid PHP 8+ reserved keyword)UserReport model → user_reports table (consolidated from duplicate tables)Key Relationships:
User hasOne Profile User hasOne UserPreference User hasMany UserPhoto User belongsToMany Chat (via chat_users) User hasMany UserMatch (self-referencing via user_id/matched_user_id) Chat hasMany Message Message belongsTo Call UserReport belongsTo User (reporter_id) UserReport belongsTo User (reported_user_id) UserReport hasMany ReportEvidence
Soft Deletes Enabled:
profiles - Data retention for deleted profilesmatches - Track match history even after deletionuser_blocks - Audit trail for blocking historyuser_photos - Photo history preservation2025_09_24_999999_add_foreign_key_constraints.phpcreate_user_reports_table (old basic version), create_pulse_tables (empty placeholder)AuthController::authenticate() generates OTP via OtpServiceTwoFactorAuthService)AdminMiddleware, custom Authenticate (redirects to /start not /login)$this->authorize('update', $profile))role_user, permission_role pivot tablesUser::active(), User::online())ApiRateLimit: Dynamic rate limiting per endpoint type (15+ action types)ChatRateLimit: Separate limits for chat operations (create, send, read, edit, delete)SecurityHeaders: Inject security headers (CSP, HSTS, X-Frame-Options)UpdateLastActive: Track user activity for presencePerformanceMonitor: Log slow requests (dev only, disabled in production)LanguageMiddleware: Locale detection from session/headerSetLocale: Set app locale for translations (supports: en, uz, ru)Laravel App (port 8000) → Broadcasts Event → Reverb (port 8080) → Pushes to Clients
// 1. Create event class NewMessageEvent implements ShouldBroadcast { public function broadcastOn(): array { return [new PrivateChannel("chat.{$this->chatId}")]; } } // 2. Dispatch event event(new NewMessageEvent($message)); // 3. Listen in JavaScript (resources/js/messages.js) Echo.private(`chat.${chatId}`) .listen('NewMessageEvent', (e) => { // Update UI });
routes/channels.phpprivate-chat.{chatId}{ type, id, attributes, relationships, included }app/Http/Resources/: UserResource, MessageResource, MatchResource (uses UserMatch model)/api/v1//api/v2/ (maintain backwards compatibility)Different limits per action type (enforced at middleware level):
auth_action: 10/min (login, register, check email)like_action: 100/hour (likes, dislikes, matches)message_action: 500/hour (send messages)call_action: 50/hour (initiate, join, end calls)panic_activation: 5/day (emergency button)profile_update: 30/hour (profile modifications)block_action: 20/hour (block/unblock users)report_action: 10/hour (report users)verification_submit: 3/day (verification requests)password_change: 5/houremail_change: 3/dayaccount_deletion: 1/daydata_export: 2/weeklocation_update: 100/hourstory_action: 20/day (create/delete stories)Applied via middleware:
->middleware('api.rate.limit:action_type')
Chat-specific rate limits (via
ChatRateLimit middleware):
create_chat: 50/hoursend_message: 500/hourmark_read: 1000/houredit_message: 100/hourdelete_message: 100/hourAuthentication Services:
AuthService: Registration, login, logoutOtpService: OTP generation/verificationTwoFactorAuthService: 2FA with Google AuthenticatorValidationService: Business validation rulesMedia Services:
MediaUploadService: File upload to Cloudflare R2ImageProcessingService: Resize, crop, thumbnail generationCommunication Services:
NotificationService: Push notifications via ExpoPresenceService: Online status, typing indicatorsCallMessageService: Call-related chat messagesVideo Services:
VideoSDKService: Primary video calling (VideoSDK.live)AgoraService: Backup video calling (Agora RTC)AgoraTokenBuilder: Token generation for AgoraAdvanced Services:
VerificationService: Identity verification (5 types: identity, photo, employment, education, income)PanicButtonService: Emergency panic button with GPS, contact alerts, admin notificationsMatchmakerService: Professional matchmaker features (consultations, introductions, reviews)FamilyApprovalService: Family involvement features (family members, approval workflows)UsageLimitsService: Subscription limit enforcement (likes, messages, profile views)PaymentManager: Payment processing (transactions, subscriptions, refunds)PrayerTimeService: Islamic prayer time notifications and preferencesEnhancedReportingService: Advanced user reporting with evidence attachmentsPrivacyService: Privacy controls and data protectionCacheService: Cache management and optimizationErrorHandlingService: Centralized error tracking and loggingServices must use transactions for multi-model operations:
public function createMatch($userId, $likedUserId) { DB::beginTransaction(); try { $match = Match::create([...]); $chat = Chat::create([...]); $chat->users()->attach([$userId, $likedUserId]); event(new NewMatchEvent($match)); DB::commit(); return $match; } catch (\Exception $e) { DB::rollBack(); throw $e; } }
Modules (resources/js/):
app.js: Entry point, Alpine initializationecho.js: WebSocket client configurationauth.js: Authentication flowsmessages.js: Chat real-time updatesvideo-call.js: Video calling (VideoSDK integration)videosdk.js: VideoSDK wrappertheme.js: Dark/light modecountry-data.js: Country selection dataregistration-store.js: Multi-step registration stateAlpine.js Integration:
x-show, x-transition for UI animationsVideoSDKService::getToken()VideoSDKService::createMeeting()resources/js/videosdk.jscalls tableAgoraService::generateToken()config/filesystems.php disk r2MediaUploadService::upload()device_tokens tableExpoPushService::send()DeviceTokenController::store()Must Configure for Basic Operation:
APP_KEY= # Generate: php artisan key:generate APP_URL=http://localhost # Production: https://yourdomain.com DB_CONNECTION=mysql # Use MySQL in production (SQLite for dev) BROADCAST_CONNECTION=reverb # WebSocket broadcasting QUEUE_CONNECTION=database # Use Redis in production # Laravel Reverb (WebSocket) REVERB_APP_ID=yoryor-app REVERB_APP_KEY=yoryor-key-123456 REVERB_APP_SECRET=yoryor-secret-123456 REVERB_HOST=localhost # Production: your domain REVERB_PORT=8080 REVERB_SCHEME=http # Production: https # Vite (for WebSocket client) VITE_REVERB_APP_KEY="${REVERB_APP_KEY}" VITE_REVERB_HOST="${REVERB_HOST}" VITE_REVERB_PORT="${REVERB_PORT}" VITE_REVERB_SCHEME="${REVERB_SCHEME}"
Must Configure for Full Functionality:
# Video Calling (Primary) VIDEOSDK_API_KEY= VIDEOSDK_SECRET_KEY= VIDEOSDK_API_ENDPOINT=https://api.videosdk.live/v2 # Media Storage (Cloudflare R2) CLOUDFLARE_R2_ACCESS_KEY_ID= CLOUDFLARE_R2_SECRET_ACCESS_KEY= CLOUDFLARE_R2_DEFAULT_REGION=auto CLOUDFLARE_R2_BUCKET= CLOUDFLARE_R2_URL=https://your-account.r2.cloudflarestorage.com CLOUDFLARE_R2_ENDPOINT=https://your-account.r2.cloudflarestorage.com CLOUDFLARE_R2_USE_PATH_STYLE_ENDPOINT=true
Optional but Recommended:
# Backup Video Calling AGORA_APP_ID= AGORA_APP_CERTIFICATE= # Social Authentication GOOGLE_CLIENT_ID= GOOGLE_CLIENT_SECRET= GOOGLE_REDIRECT_URI= # Email (Production) MAIL_MAILER=smtp MAIL_HOST=smtp.mailtrap.io MAIL_PORT=2525 MAIL_USERNAME= MAIL_PASSWORD= [email protected] MAIL_FROM_NAME="${APP_NAME}" # Cache & Queue (Production - Use Redis) REDIS_HOST=127.0.0.1 REDIS_PASSWORD=null REDIS_PORT=6379 CACHE_STORE=redis QUEUE_CONNECTION=redis
The app supports 3 languages: English (en), Uzbek (uz), Russian (ru)
// config/app.php 'locale' => env('APP_LOCALE', 'en'), 'available_locales' => ['en', 'uz', 'ru'],
Language files location:
resources/lang/{locale}/
database (development), redis (production recommended)SendEmergencyNotificationJob: Panic button emergency alertsProcessVerificationDocumentsJob: Async document verification processingphp artisan queue:listen --tries=1php artisan horizon (requires Redis)jobs table in databasefailed_jobs table, retry with php artisan queue:retry allLocal Development:
local (storage/app/)php artisan storage:linkProduction:
r2 (Cloudflare R2)config/filesystems.phproutes/api.php in appropriate sectionapp/Http/Controllers/Api/V1/app/Services/app/Http/Resources/->middleware('api.rate.limit:action_type')php artisan make:migration create_table_nameup() methodphp artisan migratephp artisan make:model ModelNamephp artisan make:event EventNameShouldBroadcastbroadcastOn() returning channelsevent(new EventName($data))Echo.private('channel').listen('EventName', callback)Never create files in these locations without understanding impact:
bootstrap/cache/ - Auto-generated cache filesstorage/framework/ - Framework storage (sessions, cache, compiled views)public/build/ - Vite compiled assets (auto-generated)Configuration files:
config/app.php - App settings, localesconfig/services.php - Third-party API credentialsconfig/filesystems.php - Storage disks (local, r2)config/broadcasting.php - Reverb configurationbootstrap/app.php - Middleware, routing configurationCritical startup files:
bootstrap/app.php - Application bootstrap, middleware aliasesroutes/channels.php - WebSocket channel authorizationapp/Providers/AppServiceProvider.php - Service container bindingshttp://localhost:8000/telescopephp artisan telescope:clearphp artisan tinker # Query users User::with('profile')->first() # Test service $authService = app(AuthService::class) $authService->register([...]) # Fire event event(new NewMessageEvent($message))
WebSocket not connecting:
php artisan reverb:start.env has correct REVERB_* varsresources/js/echo.js configurationQueue jobs not processing:
php artisan queue:listen --tries=1jobs table for pending jobsphp artisan queue:failedphp artisan queue:retry allImages not uploading/displaying:
.envphp artisan storage:linkpublic disk accessiblestorage/ and public/ should be writableGD or Imagick PHP extensionDatabase migration errors:
2025_09_24_999999_add_foreign_key_constraints.php lastmigrate:fresh only in development (destroys data)Multilingual features not working:
session()->get('locale')resources/lang/{locale}/__('key') or @lang('key') in BladeApp::setLocale($locale)/locale/{locale} to switch languagesComprehensive documentation available in
/docs/:
Main Documentation Hub:
/docs/README.md - Complete navigation and overview
API Documentation (
/docs/api/):
ENDPOINTS.md - Complete API reference with 100+ endpointsAUTHENTICATION.md - Auth flows, 2FA, OTP, token managementWEBSOCKETS.md - Laravel Reverb WebSocket setup and eventsMOBILE_INTEGRATION.md - React Native/Expo integration guideWeb Documentation (
/docs/web/):
FRONTEND_ARCHITECTURE.md - Frontend structure and patternsTHEMING.md - Dark/light mode, icons, design tokensDevelopment (
/docs/development/):
GETTING_STARTED.md - Installation, setup, workflowARCHITECTURE.md - System architecture, design patternsDATABASE.md - Complete schema for 70+ tablesSERVICES.md - All 25+ services documentationTESTING.md - Pest PHP testing guideDeployment (
/docs/deployment/):
PRODUCTION.md - Complete production deployment guideSECURITY.md - Security hardening and infrastructureFeatures (
/docs/features/):
OVERVIEW.md - All 30+ features overviewPROFILES.md - Multi-section profile systemMATCHING.md - AI-powered matching algorithmCHAT.md - Real-time messaging systemVIDEO_CALLING.md - VideoSDK integrationSAFETY.md - Safety and privacy featuresMaintenance (
/docs/maintenance/):
CODE_QUALITY_ISSUES.md - Code quality and refactoringSECURITY_AUDIT.md - Security audit findingsPERFORMANCE_IMPROVEMENTS.md - Performance optimizationsUser, UserPhoto, UserMatch, UserReport)
UserMatch not Match, UserEnum not EnumUsersController, ChatsController)AuthService, MediaUploadService)create_users_table, add_foreign_keys)NewMessageEvent, CallInitiatedEvent)protected $table when model name differs from table (e.g., UserMatch → matches)belongsTo(), hasMany(), belongsToMany()withTimestamps() on pivot tables that have timestamps{ type, id, attributes, relationships }{ status: 'error', message: '...', errors: {...} }api.v1.resource.action (e.g., api.v1.users.show)resource.action (e.g., profile.edit)route('name', ['param' => $value])registration_completed flag tracks onboarding statuslikes tablematch record createdpublic: Visible to all active usersmatches_only: Only visible to matched usersprivate: Hidden from discovery (searchable only by username/ID)DataExportRequest/privacy/terms===
The Laravel Boost guidelines are specifically curated by Laravel maintainers for this application. These guidelines should be followed closely to enhance the user's satisfaction building Laravel applications.
This application is a Laravel application and its main Laravel ecosystems package & versions are below. You are an expert with them all. Ensure you abide by these specific packages & versions.
isRegisteredForDiscounts, not discount().npm run build, npm run dev, or composer run dev. Ask them.=== boost rules ===
list-artisan-commands tool when you need to call an Artisan command to double check the available parameters.get-absolute-url tool to ensure you're using the correct scheme, domain / IP, and port.tinker tool when you need to execute PHP to debug code or query Eloquent models directly.database-query tool when you only need to read from the database.browser-logs Toolbrowser-logs tool from Boost.search-docs tool you should use before any other approaches. This tool automatically passes a list of installed packages and their versions to the remote Boost API, so it returns only version-specific documentation specific for the user's circumstance. You should pass an array of packages to filter on if you know you need docs for particular packages.['rate limiting', 'routing rate limiting', 'routing'].test resource table, not filament 4 test resource table.=== php rules ===
__construct().
__construct() methods with zero parameters.FavoritePerson, BestLake, Monthly.=== laravel/core rules ===
php artisan make: commands to create new files (i.e. migrations, controllers, models, etc.). You can list available Artisan commands using the list-artisan-commands tool.artisan make:class.--no-interaction to all Artisan commands to ensure they work without user input. You should also pass the correct --options to ensure correct behavior.DB::; prefer Model::query(). Generate code that leverages Laravel's ORM capabilities rather than bypassing them.list-artisan-commands to check the available options to php artisan make:model.ShouldQueue interface.route() function.env() function directly outside of config files. Always use config('app.name'), not env('APP_NAME').$this->faker->word() or fake()->randomDigit(). Follow existing conventions whether to use $this->faker or fake().php artisan make:test [options] <name> to create a feature test, and pass --unit to create a unit test. Most tests should be feature tests.npm run build or ask the user to run npm run dev or composer run dev.=== laravel/v12 rules ===
search-docs tool to get version specific documentation.app/Http/Middleware/.bootstrap/app.php is the file to register middleware, exceptions, and routing files.bootstrap/providers.php contains application specific service providers.bootstrap/app.php or routes/console.php for console configuration.app/Console/Commands/ are automatically available and do not require manual registration.$query->latest()->limit(10);.casts() method on a model rather than the $casts property. Follow existing conventions from other models.=== pint/core rules ===
vendor/bin/pint --dirty before finalizing changes to ensure your code matches the project's expected style.vendor/bin/pint --test, simply run vendor/bin/pint to fix any formatting issues.=== pest/core rules ===
php artisan make:test --pest <name>.tests/Feature and tests/Unit directories.it('is true', function () { expect(true)->toBeTrue(); });
php artisan test.php artisan test tests/Feature/ExampleTest.php.php artisan test --filter=testName (recommended after making a change to a related file).assertForbidden and assertNotFound instead of using assertStatus(403) or similar, e.g.:
it('returns all', function () { $response = $this->postJson('/api/docs', []);
$response->assertSuccessful();
});
Pest\Laravel\mock Pest function, but always import it via use function Pest\Laravel\mock; before using it. Alternatively, you can use $this->mock() if existing tests do.=== tailwindcss/core rules ===
search-docs tool to get exact examples from the official documentation when needed.When listing items, use gap utilities for spacing, don't use margins.
dark:.=== tailwindcss/v4 rules ===
corePlugins is not supported in Tailwind v4.@theme directive — no separate tailwind.config.js file is needed.
@theme { --color-brand: oklch(0.72 0.11 178); }
@import statement, not using the @tailwind directives used in v3:| Deprecated | Replacement | |------------+--------------| | bg-opacity-* | bg-black/* | | text-opacity-* | text-black/* | | border-opacity-* | border-black/* | | divide-opacity-* | divide-black/* | | ring-opacity-* | ring-black/* | | placeholder-opacity-* | placeholder-black/* | | flex-shrink-* | shrink-* | | flex-grow-* | grow-* | | overflow-ellipsis | text-ellipsis | | decoration-slice | box-decoration-slice | | decoration-clone | box-decoration-clone |
=== tests rules ===
php artisan test with a specific filename or filter.