app->singleton(PostTemplateRegistry::class); if ($this->app->environment('local') && class_exists(\Laravel\Telescope\TelescopeServiceProvider::class)) { $this->app->register(\Laravel\Telescope\TelescopeServiceProvider::class); $this->app->register(TelescopeServiceProvider::class); } } /** * Bootstrap any application services. */ public function boot(): void { $this->configureDefaults(); $this->configureMorphMap(); $this->configurePostHog(); $this->configureRateLimiting(); $this->configureSocialite(); $this->configureStripeWebhooks(); Cashier::useCustomerModel(Account::class); Cashier::useSubscriptionModel(Subscription::class); Cashier::useSubscriptionItemModel(SubscriptionItem::class); Cashier::keepPastDueSubscriptionsActive(); $this->configurePassport(); } protected function configurePassport(): void { Passport::useTokenModel(AccessToken::class); Passport::tokensCan([ 'mcp:use' => 'Use MCP server', ]); Passport::authorizationView('mcp.authorize'); } protected function configureMorphMap(): void { Relation::enforceMorphMap([ 'accessToken' => AccessToken::class, 'account' => Account::class, 'aiUsageLog' => AiUsageLog::class, 'automation' => Automation::class, 'automationNodeRun' => AutomationNodeRun::class, 'automationNodeState' => AutomationNodeState::class, 'automationRun' => AutomationRun::class, 'automationTriggerItem' => AutomationTriggerItem::class, 'invite' => Invite::class, 'media' => Media::class, 'notification' => Notification::class, 'notificationPreference' => NotificationPreference::class, 'plan' => Plan::class, 'post' => Post::class, 'postComment' => PostComment::class, 'postPlatform' => PostPlatform::class, 'socialAccount' => SocialAccount::class, 'subscription' => Subscription::class, 'subscriptionItem' => SubscriptionItem::class, 'user' => User::class, 'workspace' => Workspace::class, 'workspaceInvite' => WorkspaceInvite::class, 'workspaceLabel' => WorkspaceLabel::class, 'workspaceSignature' => WorkspaceSignature::class, ]); } protected function configurePostHog(): void { if (! PostHogService::isEnabled()) { return; } PostHog::init(config('services.posthog.api_key'), [ 'host' => config('services.posthog.host'), ]); } protected function configureRateLimiting(): void { RateLimiter::for('api', function (Request $request) { if ($this->app->environment('local')) { return Limit::none(); } return Limit::perMinute(60)->by($request->workspace?->id ?: $request->ip()); }); } protected function configureStripeWebhooks(): void { Event::listen(WebhookReceived::class, StripeEventListener::class); } protected function configureSocialite(): void { // Google Auth (login/signup) - separate from YouTube OAuth Socialite::extend('google-auth', function ($app) { $config = $app['config']['services.google-auth']; return Socialite::buildProvider(GoogleProvider::class, $config); }); // Instagram Business Login Socialite::extend('instagram', function ($app) { $config = $app['config']['services.instagram']; return Socialite::buildProvider(InstagramProvider::class, $config); }); Socialite::extend('discord', function ($app) { $config = $app['config']['services.discord']; return Socialite::buildProvider(DiscordProvider::class, $config); }); Event::listen(SocialiteWasCalled::class, FacebookExtendSocialite::class); Event::listen(SocialiteWasCalled::class, LinkedInExtendSocialite::class); Event::listen(SocialiteWasCalled::class, LinkedInPageExtendSocialite::class); Event::listen(SocialiteWasCalled::class, PinterestExtendSocialite::class); Event::listen(SocialiteWasCalled::class, TikTokExtendSocialite::class); } protected function configureDefaults(): void { Date::use(CarbonImmutable::class); // Disable wrapping of JSON resources JsonResource::withoutWrapping(); Model::shouldBeStrict(! $this->app->isProduction()); DB::prohibitDestructiveCommands( app()->isProduction(), ); Password::defaults(fn (): ?Password => app()->isProduction() ? Password::min(12) ->mixedCase() ->letters() ->numbers() ->symbols() ->uncompromised() : null ); Nightwatch::rejectCacheEvents(function (CacheEvent $cacheEvent) { return in_array($cacheEvent->key, [ 'illuminate:foundation:down', 'illuminate:queue:restart', 'illuminate:schedule:interrupt', ]); }); // Custom email verification template VerifyEmail::toMailUsing(function (User $user, string $url) { return (new MailMessage) ->from(config('mail.from.address'), config('mail.from.name')) ->subject('Verify your email address') ->view('mail.email-verification', [ 'title' => 'Verify your email address', 'previewText' => 'Please verify your email address.', 'user' => $user, 'url' => $url, ]); }); // Custom password reset template ResetPassword::toMailUsing(function (User $user, string $token) { $url = url(route('password.reset', [ 'token' => $token, 'email' => $user->getEmailForPasswordReset(), ], false)); return (new MailMessage) ->from(config('mail.from.address'), config('mail.from.name')) ->subject('Reset your password') ->view('mail.password-reset', [ 'title' => 'Reset your password', 'previewText' => 'Reset your password.', 'user' => $user, 'url' => $url, ]); }); } }