diff --git a/data/catalog.json b/data/catalog.json index c52b180..bf27a59 100644 --- a/data/catalog.json +++ b/data/catalog.json @@ -1,9 +1,9 @@ { "generated": "2026-07-06", - "count": 404, + "count": 405, "facets": { "platform": { - "GBA": 203, + "GBA": 204, "PC": 83, "NDS": 50, "GBC": 37, @@ -50,6 +50,7 @@ "Brilliant Diamond / Shining Pearl": 1, "Conquest": 1, "Emerald (TrashMan)": 1, + "Fire Emblem: The Sacred Stones": 1, "FireRed / LeafGreen": 1, "Let's Go Pikachu / Eevee": 1, "Moon": 1, @@ -63,7 +64,7 @@ "Ultra Sun": 1 }, "status": { - "Complete": 341, + "Complete": 342, "Beta": 32, "Ongoing": 30, "Complete (beta)": 1 @@ -81,7 +82,7 @@ "pokeemerald (decomp, likely)": 1 }, "type": { - "New Experience": 173, + "New Experience": 174, "Expansion": 166, "Difficulty": 127, "QoL": 94, @@ -89,10 +90,10 @@ "Cosmetic": 13, "Demake": 11, "Roguelite": 7, - "Crossover": 1 + "Crossover": 2 }, "play_status": { - "Unplayed": 394, + "Unplayed": 395, "Completed": 5, "Backlog": 3, "Dropped": 1, @@ -15227,6 +15228,59 @@ } ] }, + { + "stem": "Pokemblem", + "title": "Pokemblem", + "platform": "GBA", + "base": "Fire Emblem: The Sacred Stones", + "version": "1.20", + "status": "Complete", + "generation": "Gen I", + "fakemon": "No", + "developer": "Vesly", + "release_date": "2025", + "banner": "https://romhacks-files.ginnoir.com/_meta/Pokemblem/banner.png", + "homepage": "https://feuniverse.us/t/pokemblem-complete-v1-20/8875", + "source": "https://feuniverse.us/t/pokemblem-complete-v1-20/8875", + "library_path": "roms/gba/Pokemblem [Hack].gba", + "play_status": "Unplayed", + "generations": [ + "Gen I" + ], + "type": [ + "New Experience", + "Crossover" + ], + "tags": [ + "hack", + "platform/gba", + "base/fireemblem", + "status/complete", + "type/newexperience", + "type/crossover", + "source/feuniverse" + ], + "summary": "Pokemblem is Vesly's completed crossover hack that reimagines Pokémon Generation 1 on top of Fire Emblem: The Sacred Stones (GBA). It swaps Pokémon's turn-based duels for Fire Emblem's grid-based tactical combat — you re-live the Kanto journey, catch Pokémon, and fight with your whole party at once, where positioning and team composition matter more than grinding. A genre-bending oddball and intentionally the only non-Pokémon-engine entry in the library.", + "notability": "", + "story": "Re-live your journey through Kanto in this reimagining of Pokémon. Battle with your whole party at once, and devise strategies to take down the toughest foes. The narrative is sparse and mostly optional — the focus is squarely on the tactics.", + "features": [ + "Grid-based Fire Emblem tactical combat with your full party fighting simultaneously.", + "Pokémon catching and an evolution system, with RPG-style overworld walking/exploration.", + "Type effectiveness/resistance, area-of-effect attacks, equippable accessories, and level-up moves, TMs, and Skill Scrolls.", + "Trainer battles, multiple playtested difficulty levels, and a Randomizer mode.", + "QoL: in-game learnset menu, fast-travel via route signs, experience capped to gym-leader levels, and nearly every Pokémon kept viable." + ], + "links": [ + { + "label": "FEUniverse thread", + "url": "https://feuniverse.us/t/pokemblem-complete-v1-20/8875" + }, + { + "label": "Trailer", + "url": "https://www.youtube.com/watch?v=hifN8fICsKs" + } + ] + }, { "stem": "Poketale", "title": "Pokémon Poketale", diff --git a/src/generated/banner-manifest.json b/src/generated/banner-manifest.json index bdd4939..4167de7 100644 --- a/src/generated/banner-manifest.json +++ b/src/generated/banner-manifest.json @@ -253,6 +253,7 @@ "platinum-redux": "/assets/banners/platinum-redux.jpg", "platinum-unlocked": "/assets/banners/platinum-unlocked.jpg", "pocket-gaiden": "/assets/banners/pocket-gaiden.webp", + "pokemblem": "/assets/banners/pokemblem.png", "poketale": "/assets/banners/poketale.png", "poketropolis": "/assets/banners/poketropolis.img", "pokerogue": "/assets/banners/pokerogue.jpg", diff --git a/tests/catalog.spec.ts b/tests/catalog.spec.ts index 33e2142..2a22feb 100644 --- a/tests/catalog.spec.ts +++ b/tests/catalog.spec.ts @@ -11,20 +11,20 @@ test('homepage presents balanced navigation and facet summaries', async ({ page await expect(primaryNav.getByRole('link', { name: 'Difficulty' })).toHaveCount(0); const heroStats = page.locator('.hero-stats'); - await expect(heroStats).toContainText('404'); + await expect(heroStats).toContainText('405'); await expect(heroStats).toContainText('hacks'); await expect(heroStats).toContainText('Platforms'); - await expect(heroStats).toContainText('GBA 203'); + await expect(heroStats).toContainText('GBA 204'); await expect(heroStats).toContainText('PC 83'); await expect(heroStats).toContainText('NDS 50'); await expect(heroStats).toContainText('GBC 37'); await expect(heroStats).toContainText('Types'); await expect(heroStats).toContainText('Expansion 166'); - await expect(heroStats).toContainText('New Experience 173'); + await expect(heroStats).toContainText('New Experience 174'); await expect(heroStats).toContainText('Difficulty 127'); await expect(heroStats).toContainText('QoL 94'); await expect(heroStats).toContainText('Status'); - await expect(heroStats).toContainText('Complete 341'); + await expect(heroStats).toContainText('Complete 342'); await expect(heroStats).toContainText('Ongoing 30'); await expect(heroStats).toContainText('Beta 32'); }); @@ -71,12 +71,12 @@ test('homepage browse summary links to grouped facet pages', async ({ page }) => const browse = page.getByRole('region', { name: 'Browse by catalog facets' }); await expect(browse.getByRole('heading', { name: 'Browse the archive' })).toBeVisible(); - await expect(browse.getByRole('link', { name: /GBA\s+203/ })).toHaveAttribute('href', '/browse/platform/gba/'); + await expect(browse.getByRole('link', { name: /GBA\s+204/ })).toHaveAttribute('href', '/browse/platform/gba/'); await expect(browse.getByRole('link', { name: /Difficulty\s+127/ })).toHaveAttribute( 'href', '/browse/type/difficulty/', ); - await expect(browse.getByRole('link', { name: /Complete\s+341/ })).toHaveAttribute( + await expect(browse.getByRole('link', { name: /Complete\s+342/ })).toHaveAttribute( 'href', '/browse/status/complete/', ); @@ -88,7 +88,7 @@ test('catalog search and filters update visible card count', async ({ page }) => await expect(page).toHaveTitle(/ROM Hack Archive/); await expect(page.getByRole('heading', { name: 'ROM Hack Archive' })).toBeVisible(); const catalogCards = page.locator('[data-card-grid] [data-card]:visible'); - await expect(catalogCards).toHaveCount(404); + await expect(catalogCards).toHaveCount(405); await page.getByPlaceholder('Search hacks').fill('Radical Red'); await expect(catalogCards).toHaveCount(5); @@ -96,7 +96,7 @@ test('catalog search and filters update visible card count', async ({ page }) => await page.getByPlaceholder('Search hacks').fill(''); await page.getByLabel('GBA').check(); - await expect(catalogCards).toHaveCount(203); + await expect(catalogCards).toHaveCount(204); await page.getByLabel('Difficulty').check(); await expect(catalogCards.first()).toBeVisible();