getMemes($request->input('search')); } public function search(string $search): Response { // Convert + back to spaces for search $searchTerm = str_replace('+', ' ', $search); return $this->getMemes($searchTerm); } private function getMemes(?string $search = null): Response { $query = MemeMedia::query() ->where('is_enabled', true) ->orderBy('id', 'desc'); // Search functionality if ($search) { $query->where(function ($q) use ($search) { $q->where('name', 'ilike', "%{$search}%") ->orWhere('description', 'ilike', "%{$search}%") ->orWhereJsonContains('keywords', $search) ->orWhereJsonContains('action_keywords', $search) ->orWhereJsonContains('emotion_keywords', $search) ->orWhereJsonContains('misc_keywords', $search); }); } $memes = $query->cursorPaginate(24); // Set up SEO meta tags $title = $search ? ucfirst($search) . " Memes in MEMEFA.ST" : 'Meme Library - Thousands of Video Meme Templates'; if ($search) { // Get SEO descriptions from config $descriptions = config('platform.seo_descriptions.search_descriptions', []); // Use deterministic selection based on search term hash $searchHash = crc32($search); $descriptionIndex = abs($searchHash) % count($descriptions); $descriptionTemplate = $descriptions[$descriptionIndex]; // Replace keyword placeholder $description = str_replace('__KEYWORD__', $search, $descriptionTemplate); } else { $description = 'Browse thousands of video meme templates ready for TikTok, Instagram Reels, Threads and YouTube Shorts. Create viral content in minutes with our meme editor.'; } SEOMeta::setTitle($title, false); SEOMeta::setDescription($description); SEOMeta::setCanonical(request()->url()); // Add pagination rel links if ($memes->previousPageUrl()) { SEOMeta::addMeta('link:prev', $memes->previousPageUrl(), 'rel'); } if ($memes->nextPageUrl()) { SEOMeta::addMeta('link:next', $memes->nextPageUrl(), 'rel'); } // OpenGraph tags OpenGraph::setTitle($title); OpenGraph::setDescription($description); OpenGraph::setUrl(request()->url()); OpenGraph::addProperty('type', 'website'); // Twitter Card TwitterCard::setTitle($title); TwitterCard::setDescription($description); TwitterCard::setType('summary_large_image'); // Get available types for filter $types = MemeMedia::where('is_enabled', true) ->distinct() ->pluck('type') ->filter(); // Get popular keywords for filter $popularKeywords = MemeMedia::where('is_enabled', true) ->get() ->pluck('keywords') ->flatten() ->countBy() ->sort() ->reverse() ->take(20) ->keys(); return Inertia::render('memes/index', [ 'memes' => $memes, 'types' => $types, 'popularKeywords' => $popularKeywords, 'filters' => [ 'search' => $search, ], 'dynamicDescription' => $search ? $description : null, ]); } public function show(string $slug): Response { $meme = MemeMedia::where('slug', $slug) ->where('is_enabled', true) ->firstOrFail(); // Get related memes based on similar keywords $relatedMemes = MemeMedia::where('is_enabled', true) ->where('id', '!=', $meme->id) ->where(function ($query) use ($meme) { if ($meme->keywords) { foreach ($meme->keywords as $keyword) { $query->orWhereJsonContains('keywords', $keyword) ->orWhereJsonContains('action_keywords', $keyword) ->orWhereJsonContains('emotion_keywords', $keyword) ->orWhereJsonContains('misc_keywords', $keyword); } } }) ->limit(6) ->get(); // If we have less than 6 related memes, fill up with random ones if ($relatedMemes->count() < 6) { $excludeIds = $relatedMemes->pluck('id')->push($meme->id)->toArray(); $needed = 6 - $relatedMemes->count(); $randomMemes = MemeMedia::where('is_enabled', true) ->whereNotIn('id', $excludeIds) ->inRandomOrder() ->limit($needed) ->get(); $relatedMemes = $relatedMemes->merge($randomMemes); } // Set up SEO meta tags for individual meme page $title = "{$meme->name} - Make Video Memes with MEMEFA.ST"; $description = $meme->description ? "This meme is about: {$meme->description}." : "Create {$meme->name} video memes with our online editor. Perfect for TikTok, Instagram Reels, and YouTube Shorts."; SEOMeta::setTitle($title, false); SEOMeta::setDescription($description); SEOMeta::setCanonical(request()->url()); SEOMeta::addKeyword(collect([$meme->keywords, $meme->action_keywords, $meme->emotion_keywords, $meme->misc_keywords])->flatten()->filter()->implode(', ')); // OpenGraph tags OpenGraph::setTitle($title); OpenGraph::setDescription($description); OpenGraph::setUrl(request()->url()); //OpenGraph::addProperty('type', 'video.other'); //OpenGraph::addImage($meme->webp_url); // Twitter Card TwitterCard::setTitle($title); TwitterCard::setDescription($description); //TwitterCard::setType('summary_large_image'); //TwitterCard::setImage($meme->webp_url); return Inertia::render('memes/show', [ 'meme' => $meme, 'relatedMemes' => $relatedMemes, ]); } }