firstWhere('email', 'newsroom@skinbase.local'); if (! $author) { $author = new User(); $author->forceFill([ 'name' => 'Skinbase Editorial', 'username' => 'skinbaseeditorial', 'email' => 'newsroom@skinbase.local', 'password' => Hash::make('password'), 'role' => 'moderator', ])->save(); $author = User::query()->firstWhere('email', 'newsroom@skinbase.local'); } if (! $author) { return; } $categories = [ 'platform' => $this->upsertCategory('Platform', 'platform', 'Product updates, roadmap notes, and feature launches.'), 'groups' => $this->upsertCategory('Groups', 'groups', 'Stories about collaborative publishing, teams, and shared identity.'), 'tutorials' => $this->upsertCategory('Tutorials', 'tutorials', 'Practical guides for getting more from Nova.'), 'spotlight' => $this->upsertCategory('Spotlight', 'spotlight', 'Featured creators, groups, and standout work.'), 'releases' => $this->upsertCategory('Releases', 'releases', 'Coverage for launches, drops, and project milestones.'), ]; $tags = [ 'nova' => $this->upsertTag('Nova', 'nova'), 'tutorial' => $this->upsertTag('Tutorial', 'tutorial'), 'groups' => $this->upsertTag('Groups', 'groups'), 'release' => $this->upsertTag('Release', 'release'), 'spotlight' => $this->upsertTag('Spotlight', 'spotlight'), 'platform-update' => $this->upsertTag('Platform Update', 'platform-update'), ]; $articles = [ [ 'slug' => 'welcome-to-skinbase-nova', 'title' => 'Welcome to Skinbase Nova', 'type' => NewsArticle::TYPE_PLATFORM_UPDATE, 'category' => $categories['platform'], 'excerpt' => 'A first look at the refreshed Skinbase experience and the editorial direction behind Nova.', 'content' => "# Welcome to Skinbase Nova\n\nSkinbase Nova brings publishing, discovery, Groups, and editorial storytelling into a single platform experience.\n\n## What is new\n\n- a dedicated newsroom\n- stronger creator identity surfaces\n- deeper internal linking across Groups, releases, and profiles\n- cleaner editorial publishing tools inside Studio\n\nNova is designed to feel active, curated, and connected to the people making the work.", 'tags' => [$tags['nova'], $tags['platform-update']], 'days_ago' => 10, 'featured' => true, 'pinned' => true, ], [ 'slug' => 'introducing-groups-in-nova', 'title' => 'Introducing Groups in Nova', 'type' => NewsArticle::TYPE_ANNOUNCEMENT, 'category' => $categories['groups'], 'excerpt' => 'Groups give collaborative identities a real home across publishing, releases, events, and project storytelling.', 'content' => "# Introducing Groups\n\nGroups let creators publish under a shared identity while still keeping contributor context visible.\n\n## Why it matters\n\nGroups are more than labels. They support:\n\n- shared publishing\n- releases and milestones\n- recruiting and discovery\n- public storytelling\n\nThat makes Nova feel much more alive than a simple profile-only platform.", 'tags' => [$tags['groups'], $tags['nova']], 'days_ago' => 9, 'featured' => true, 'pinned' => false, ], [ 'slug' => 'how-studio-works-in-nova', 'title' => 'How Studio Works in Nova', 'type' => NewsArticle::TYPE_TUTORIAL, 'category' => $categories['tutorials'], 'excerpt' => 'A practical walkthrough of drafts, scheduling, content editing, and publishing flow inside Studio.', 'content' => "# How Studio Works\n\nStudio is the control layer for publishing in Nova.\n\n## Start with drafts\n\nUse Studio to prepare content, tune metadata, and move work through review before publishing.\n\n## Move with intent\n\nThe best results come from treating Studio as a workflow, not just a form. Draft, refine, preview, then publish.", 'tags' => [$tags['tutorial'], $tags['nova']], 'days_ago' => 7, 'featured' => false, 'pinned' => false, ], [ 'slug' => 'how-to-upload-your-first-artwork', 'title' => 'How to Upload Your First Artwork', 'type' => NewsArticle::TYPE_TUTORIAL, 'category' => $categories['tutorials'], 'excerpt' => 'A short guide to cleaner uploads, stronger metadata, and better first impressions.', 'content' => "# Upload Your First Artwork\n\nA strong upload starts with the basics:\n\n- a clear title\n- a readable description\n- accurate categories and tags\n- a polished thumbnail or cover\n\nGood publishing habits make discovery, search, and editorial coverage work better for you.", 'tags' => [$tags['tutorial']], 'days_ago' => 6, 'featured' => false, 'pinned' => false, ], [ 'slug' => 'creator-spotlight-building-a-recognizable-profile', 'title' => 'Creator Spotlight: Building a Recognizable Profile', 'type' => NewsArticle::TYPE_SPOTLIGHT, 'category' => $categories['spotlight'], 'excerpt' => 'Profiles work better when identity, consistency, and a clear body of work all point in the same direction.', 'content' => "# Creator Spotlight\n\nGreat profiles are memorable because they feel intentional.\n\n## Strong profile signals\n\n- consistent visual identity\n- complete bio and links\n- a curated set of standout uploads\n- a clear publishing rhythm\n\nNova rewards clarity and consistency.", 'tags' => [$tags['spotlight']], 'days_ago' => 4, 'featured' => false, 'pinned' => false, ], [ 'slug' => 'release-roundup-whats-new-this-week', 'title' => 'Release Roundup: What\'s New This Week', 'type' => NewsArticle::TYPE_RELEASE, 'category' => $categories['releases'], 'excerpt' => 'A compact editorial roundup of recent launches, notable drops, and community momentum.', 'content' => "# Release Roundup\n\nThis week\'s standout launches show why Nova needs editorial context alongside uploads.\n\nRelease coverage helps people discover:\n\n- the work itself\n- the team behind it\n- related projects and collections\n- where the story continues next", 'tags' => [$tags['release'], $tags['spotlight']], 'days_ago' => 2, 'featured' => false, 'pinned' => false, ], ]; foreach ($articles as $article) { $record = NewsArticle::query()->firstOrNew(['slug' => $article['slug']]); $record->forceFill([ 'title' => $article['title'], 'slug' => $article['slug'], 'excerpt' => $article['excerpt'], 'content' => $article['content'], 'author_id' => $author->id, 'category_id' => $article['category']->id, 'type' => $article['type'], 'status' => 'published', 'editorial_status' => NewsArticle::EDITORIAL_STATUS_PUBLISHED, 'published_at' => Carbon::now()->subDays($article['days_ago'])->setTime(10, 0), 'is_featured' => $article['featured'], 'is_pinned' => $article['pinned'], 'meta_title' => $article['title'], 'meta_description' => $article['excerpt'], 'deleted_at' => null, ])->save(); $record->tags()->sync(array_map(static fn (NewsTag $tag): int => (int) $tag->id, $article['tags'])); } } private function upsertCategory(string $name, string $slug, string $description): NewsCategory { return NewsCategory::query()->updateOrCreate( ['slug' => $slug], [ 'name' => $name, 'description' => $description, 'position' => 0, 'is_active' => true, ] ); } private function upsertTag(string $name, string $slug): NewsTag { return NewsTag::query()->updateOrCreate( ['slug' => $slug], ['name' => $name] ); } }