data: refresh romhack archive catalog

This commit is contained in:
ginnoir
2026-07-04 19:01:11 -05:00
parent 26cafb2681
commit ca1a1a21ac
3 changed files with 155 additions and 28 deletions
+141 -16
View File
@@ -1,10 +1,10 @@
{ {
"generated": "2026-06-26", "generated": "2026-07-04",
"count": 396, "count": 398,
"facets": { "facets": {
"platform": { "platform": {
"GBA": 201, "GBA": 202,
"PC": 77, "PC": 78,
"NDS": 50, "NDS": 50,
"GBC": 37, "GBC": 37,
"3DS": 15, "3DS": 15,
@@ -16,8 +16,8 @@
}, },
"base": { "base": {
"FireRed": 101, "FireRed": 101,
"Emerald": 85, "Emerald": 86,
"RPG Maker XP / Pokemon Essentials": 75, "RPG Maker XP / Pokemon Essentials": 76,
"Crystal": 27, "Crystal": 27,
"Ruby": 10, "Ruby": 10,
"HeartGold": 9, "HeartGold": 9,
@@ -63,9 +63,9 @@
"Ultra Sun": 1 "Ultra Sun": 1
}, },
"status": { "status": {
"Complete": 337, "Complete": 338,
"Ongoing": 30, "Ongoing": 30,
"Beta": 28, "Beta": 29,
"Complete (beta)": 1 "Complete (beta)": 1
}, },
"engine": { "engine": {
@@ -81,19 +81,21 @@
"pokeemerald (decomp, likely)": 1 "pokeemerald (decomp, likely)": 1
}, },
"type": { "type": {
"Expansion": 165, "New Experience": 167,
"New Experience": 165, "Expansion": 166,
"Difficulty": 126, "Difficulty": 126,
"QoL": 88, "QoL": 89,
"Vanilla+": 29, "Vanilla+": 29,
"Cosmetic": 13, "Cosmetic": 13,
"Demake": 11, "Demake": 11,
"Roguelite": 7 "Roguelite": 7,
"Crossover": 1
}, },
"play_status": { "play_status": {
"Unplayed": 391, "Unplayed": 391,
"Completed": 4, "Completed": 5,
"Dropped": 1 "Dropped": 1,
"Playing": 1
} }
}, },
"image_base": "https://romhacks-files.ginnoir.com", "image_base": "https://romhacks-files.ginnoir.com",
@@ -8065,6 +8067,7 @@
"type/newexperience", "type/newexperience",
"source/discord" "source/discord"
], ],
"rating": 4,
"summary": "Widely considered one of the best hacks ever: the Orbtus region, Gen 6 mechanics/Fairy type, an archaeology mystery, and Nintendo-grade polish.", "summary": "Widely considered one of the best hacks ever: the Orbtus region, Gen 6 mechanics/Fairy type, an archaeology mystery, and Nintendo-grade polish.",
"notability": "", "notability": "",
"story": "The storied Orbtus region was once populated by a prosperous civilization. They created several monuments for their gods and guardians. Their untimely demise was brought about by a series of disastrous earthquakes; all that remains of their society are their temples, idols, and story, as relics of the past.\nIn the present day, local archaeologist and Pokémon Professor, Professor Redwood, has noticed an increase in the region's seismic activity. Propelled by a growing concern for Orbtus' safety, he seeks the assistance of new Pokemon Trainers with a flair for adventure in the rural Celanto Town, a seaside town near the mysterious Totem Poles, and your home! Will you, along with the help of the Professor and your rival, be able to prevent the earth from consuming the region once more?", "story": "The storied Orbtus region was once populated by a prosperous civilization. They created several monuments for their gods and guardians. Their untimely demise was brought about by a series of disastrous earthquakes; all that remains of their society are their temples, idols, and story, as relics of the past.\nIn the present day, local archaeologist and Pokémon Professor, Professor Redwood, has noticed an increase in the region's seismic activity. Propelled by a growing concern for Orbtus' safety, he seeks the assistance of new Pokemon Trainers with a flair for adventure in the rural Celanto Town, a seaside town near the mysterious Totem Poles, and your home! Will you, along with the help of the Professor and your rival, be able to prevent the earth from consuming the region once more?",
@@ -9845,7 +9848,7 @@
"homepage": "https://pokemoninfinity.miraheze.org/wiki/Pokemon_Infinity_Wiki", "homepage": "https://pokemoninfinity.miraheze.org/wiki/Pokemon_Infinity_Wiki",
"source": "https://p-infinity.fandom.com/wiki/Pokemon_Infinity_Wiki", "source": "https://p-infinity.fandom.com/wiki/Pokemon_Infinity_Wiki",
"library_path": "roms/windows/Pokemon - Infinity 3.3.1 (Hack).zip", "library_path": "roms/windows/Pokemon - Infinity 3.3.1 (Hack).zip",
"play_status": "Unplayed", "play_status": "Playing",
"scrape_dir": "Pokemon_Infinity", "scrape_dir": "Pokemon_Infinity",
"generations": [ "generations": [
"Gen I", "Gen I",
@@ -13593,7 +13596,7 @@
"banner": "https://romhacks-files.ginnoir.com/_meta/Pok_mon_Odyssey/Pokemon-Odyssey-b9584b0f29a464cd.png", "banner": "https://romhacks-files.ginnoir.com/_meta/Pok_mon_Odyssey/Pokemon-Odyssey-b9584b0f29a464cd.png",
"source": "https://www.hackdex.app/hack/pokemon-odyssey", "source": "https://www.hackdex.app/hack/pokemon-odyssey",
"library_path": "roms/gba/Pokemon - Odyssey [Hack].gba", "library_path": "roms/gba/Pokemon - Odyssey [Hack].gba",
"play_status": "Unplayed", "play_status": "Completed",
"scrape_dir": "Pok_mon_Odyssey", "scrape_dir": "Pok_mon_Odyssey",
"generations": [ "generations": [
"Gen I", "Gen I",
@@ -13611,6 +13614,7 @@
"type/newexperience", "type/newexperience",
"source/discord" "source/discord"
], ],
"rating": 5,
"summary": "A highly-praised, atmospheric original adventure with a custom region, strong writing, and bespoke pixel art.", "summary": "A highly-praised, atmospheric original adventure with a custom region, strong writing, and bespoke pixel art.",
"notability": "", "notability": "",
"story": "", "story": "",
@@ -13773,6 +13777,69 @@
} }
] ]
}, },
{
"stem": "Omniversal Emerald",
"title": "Pokémon Omniversal Emerald",
"platform": "GBA",
"base": "Emerald",
"version": "0.3.2",
"status": "Beta",
"generation": "Gen III",
"fakemon": "Yes",
"developer": "Rioluwott, LuckyCapybara",
"release_date": "2026-06-27",
"banner": "https://romhacks.ginnoir.com/assets/banners/omniversal-emerald.jpg",
"homepage": "https://www.hackdex.app/hack/pokemon-omniversal-emerald",
"source": "https://www.hackdex.app/hack/pokemon-omniversal-emerald",
"library_path": "roms/gba/Pokemon - Omniversal Emerald [Hack].gba",
"play_status": "Unplayed",
"generations": [
"Gen I",
"Gen II",
"Gen III",
"Gen IV",
"Gen V",
"Gen VI",
"Gen VII",
"Gen VIII",
"Fakemon"
],
"type": [
"New Experience",
"Expansion",
"Crossover"
],
"tags": [
"hack",
"platform/gba",
"base/emerald",
"status/beta",
"type/expansion",
"type/vanilla+"
],
"summary": "A Ben 10 crossover hack where the Pokémon of the Hoenn region have been strangely mutated by a comet that flew over the region, creating over 400 new forms. Play as Ben or Gwen and catalog the transformed creatures—a fusion of Pokémon and Ben 10 aliens with QoL enhancements, difficulty options, and randomized encounters.",
"notability": "",
"story": "",
"features": [
"Ben 10 Crossover — Play as Ben or Gwen",
"400+ New Forms — Pokémon fused with aliens from across the Ben 10 series",
"DexNav — Including hidden \"normal\" Pokémon variants",
"Level Caps — With Cap Candy system for difficulty scaling",
"Randomized Trainers — Specialized pools for unique runs",
"New Abilities — Custom ability set",
"Innate System — Similar to Pokémon Elite Redux and PokéRogue",
"New Locations — Expanded Hoenn region",
"Multiple Starters — Choice between different starter Pokémon",
"New Lore — Expanded story around the comet mutation event",
"QoL Changes — Quality-of-life improvements for modern gameplay"
],
"links": [
{
"label": "Link",
"url": "https://www.hackdex.app/hack/pokemon-omniversal-emerald"
}
]
},
{ {
"stem": "Onyx Blue", "stem": "Onyx Blue",
"title": "Pokémon Onyx Blue", "title": "Pokémon Onyx Blue",
@@ -14407,6 +14474,63 @@
} }
] ]
}, },
{
"stem": "Plastic Pyrite",
"title": "Pokémon Plastic Pyrite",
"platform": "PC",
"base": "RPG Maker XP / Pokemon Essentials",
"version": "1.74.1",
"status": "Complete",
"generation": "Joiplay/RPGXP",
"fakemon": "Yes",
"developer": "NuclearOmega",
"release_date": "2026-07-01",
"banner": "https://i.postimg.cc/hPhvd4b2/title-screen.png",
"homepage": "https://eeveeexpo.com/threads/9579/",
"source": "https://eeveeexpo.com/threads/9579/",
"library_path": "roms/windows/Pokemon - Plastic Pyrite [Hack].zip",
"play_status": "Unplayed",
"generations": [
"Fakemon"
],
"type": [
"New Experience",
"QoL"
],
"tags": [
"hack",
"platform/pc",
"base/rpgmakerxp/pokemonessentials",
"status/complete",
"type/newexperience",
"type/qol",
"source/eeveeexpo"
],
"summary": "Pokémon Plastic Pyrite is NuclearOmega's RPG Maker XP / Pokémon Essentials fan game set in the Captoad region. The 1.74.1 release covers the full main game, eight gyms, Elite Four, and a postgame epilogue, with future updates planned for additional Battle Frontier-style postgame content.",
"notability": "",
"story": "The Captoadian Artifacts once brought peace to the region, but a group of miscreants now wants to use them for selfish ends. The player begins with a partner Pokémon from Professor Woody, then helps their grandfather Cleveland, a respected Pokéarcheologist, search for the artifacts before they fall into the wrong hands.",
"features": [
"Original Captoad region campaign with eight gyms, Elite Four, and postgame epilogue complete in the current public release.",
"All-original Fakemon Pokédex with more than 150 Pokémon to catch and battle.",
"Double-battle-focused design, with Gym Leaders built around battle styles rather than elemental types.",
"New Tiny Pokémon variant, Nightmare forms for selected Fakemon, and custom attacks, abilities, and items.",
"Gameplay mechanics up to Gen 9, HM items, Captoadian Artifacts, Nature Mints, Bottle Caps, daily events, and an Alt-key speed-up option."
],
"links": [
{
"label": "Eevee Expo",
"url": "https://eeveeexpo.com/threads/9579/"
},
{
"label": "Download",
"url": "https://drive.google.com/file/d/1HF2tPuoVWQQN2428IflGt_uH0d-aqXAH/"
},
{
"label": "Documentation",
"url": "https://docs.google.com/spreadsheets/d/1F7IJ3TbPwZMpIKl0kD-w3kTTTG3tqeV7FjMPwX0cyvg/edit?gid=1141822888"
}
]
},
{ {
"stem": "Platinum Kaizo", "stem": "Platinum Kaizo",
"title": "Pokémon Platinum Kaizo", "title": "Pokémon Platinum Kaizo",
@@ -19615,6 +19739,7 @@
"type/cosmetic", "type/cosmetic",
"source/discord" "source/discord"
], ],
"rating": 5,
"summary": "A Mario × Pokémon crossover: catch and battle Mario-universe characters as 'Mariomon'. A complete novelty hack.", "summary": "A Mario × Pokémon crossover: catch and battle Mario-universe characters as 'Mariomon'. A complete novelty hack.",
"notability": "", "notability": "",
"story": "", "story": "",
+2
View File
@@ -229,6 +229,7 @@
"odyssey": "/assets/banners/odyssey.png", "odyssey": "/assets/banners/odyssey.png",
"omega-paradox-v2": "/assets/banners/omega-paradox-v2.jpg", "omega-paradox-v2": "/assets/banners/omega-paradox-v2.jpg",
"omega-ruby-origins": "/assets/banners/omega-ruby-origins.webp", "omega-ruby-origins": "/assets/banners/omega-ruby-origins.webp",
"omniversal-emerald": "/assets/banners/omniversal-emerald.jpg",
"onyx-blue": "/assets/banners/onyx-blue.webp", "onyx-blue": "/assets/banners/onyx-blue.webp",
"opalo": "/assets/banners/opalo.jpg", "opalo": "/assets/banners/opalo.jpg",
"orange": "/assets/banners/orange.jpg", "orange": "/assets/banners/orange.jpg",
@@ -240,6 +241,7 @@
"photonic-sun-prismatic-moon": "/assets/banners/photonic-sun-prismatic-moon.png", "photonic-sun-prismatic-moon": "/assets/banners/photonic-sun-prismatic-moon.png",
"pisces": "/assets/banners/pisces.webp", "pisces": "/assets/banners/pisces.webp",
"pitch-black-pure-white": "/assets/banners/pitch-black-pure-white.png", "pitch-black-pure-white": "/assets/banners/pitch-black-pure-white.png",
"plastic-pyrite": "/assets/banners/plastic-pyrite.png",
"platinum-kaizo": "/assets/banners/platinum-kaizo.jpg", "platinum-kaizo": "/assets/banners/platinum-kaizo.jpg",
"platinum-red": "/assets/banners/platinum-red.jpg", "platinum-red": "/assets/banners/platinum-red.jpg",
"platinum-redux": "/assets/banners/platinum-redux.jpg", "platinum-redux": "/assets/banners/platinum-redux.jpg",
+12 -12
View File
@@ -11,22 +11,22 @@ test('homepage presents balanced navigation and facet summaries', async ({ page
await expect(primaryNav.getByRole('link', { name: 'Difficulty' })).toHaveCount(0); await expect(primaryNav.getByRole('link', { name: 'Difficulty' })).toHaveCount(0);
const heroStats = page.locator('.hero-stats'); const heroStats = page.locator('.hero-stats');
await expect(heroStats).toContainText('396'); await expect(heroStats).toContainText('398');
await expect(heroStats).toContainText('hacks'); await expect(heroStats).toContainText('hacks');
await expect(heroStats).toContainText('Platforms'); await expect(heroStats).toContainText('Platforms');
await expect(heroStats).toContainText('GBA 201'); await expect(heroStats).toContainText('GBA 202');
await expect(heroStats).toContainText('PC 77'); await expect(heroStats).toContainText('PC 78');
await expect(heroStats).toContainText('NDS 50'); await expect(heroStats).toContainText('NDS 50');
await expect(heroStats).toContainText('GBC 37'); await expect(heroStats).toContainText('GBC 37');
await expect(heroStats).toContainText('Types'); await expect(heroStats).toContainText('Types');
await expect(heroStats).toContainText('Expansion 165'); await expect(heroStats).toContainText('Expansion 166');
await expect(heroStats).toContainText('New Experience 165'); await expect(heroStats).toContainText('New Experience 167');
await expect(heroStats).toContainText('Difficulty 126'); await expect(heroStats).toContainText('Difficulty 126');
await expect(heroStats).toContainText('QoL 88'); await expect(heroStats).toContainText('QoL 89');
await expect(heroStats).toContainText('Status'); await expect(heroStats).toContainText('Status');
await expect(heroStats).toContainText('Complete 337'); await expect(heroStats).toContainText('Complete 338');
await expect(heroStats).toContainText('Ongoing 30'); await expect(heroStats).toContainText('Ongoing 30');
await expect(heroStats).toContainText('Beta 28'); await expect(heroStats).toContainText('Beta 29');
}); });
test('homepage stat cards are polished and responsive', async ({ page }) => { test('homepage stat cards are polished and responsive', async ({ page }) => {
@@ -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' }); const browse = page.getByRole('region', { name: 'Browse by catalog facets' });
await expect(browse.getByRole('heading', { name: 'Browse the archive' })).toBeVisible(); await expect(browse.getByRole('heading', { name: 'Browse the archive' })).toBeVisible();
await expect(browse.getByRole('link', { name: /GBA\s+201/ })).toHaveAttribute('href', '/browse/platform/gba/'); await expect(browse.getByRole('link', { name: /GBA\s+202/ })).toHaveAttribute('href', '/browse/platform/gba/');
await expect(browse.getByRole('link', { name: /Difficulty\s+126/ })).toHaveAttribute( await expect(browse.getByRole('link', { name: /Difficulty\s+126/ })).toHaveAttribute(
'href', 'href',
'/browse/type/difficulty/', '/browse/type/difficulty/',
); );
await expect(browse.getByRole('link', { name: /Complete\s+337/ })).toHaveAttribute( await expect(browse.getByRole('link', { name: /Complete\s+338/ })).toHaveAttribute(
'href', 'href',
'/browse/status/complete/', '/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).toHaveTitle(/ROM Hack Archive/);
await expect(page.getByRole('heading', { name: 'ROM Hack Archive' })).toBeVisible(); await expect(page.getByRole('heading', { name: 'ROM Hack Archive' })).toBeVisible();
const catalogCards = page.locator('[data-card-grid] [data-card]:visible'); const catalogCards = page.locator('[data-card-grid] [data-card]:visible');
await expect(catalogCards).toHaveCount(396); await expect(catalogCards).toHaveCount(398);
await page.getByPlaceholder('Search hacks').fill('Radical Red'); await page.getByPlaceholder('Search hacks').fill('Radical Red');
await expect(catalogCards).toHaveCount(5); 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.getByPlaceholder('Search hacks').fill('');
await page.getByLabel('GBA').check(); await page.getByLabel('GBA').check();
await expect(catalogCards).toHaveCount(201); await expect(catalogCards).toHaveCount(202);
await page.getByLabel('Difficulty').check(); await page.getByLabel('Difficulty').check();
await expect(catalogCards.first()).toBeVisible(); await expect(catalogCards.first()).toBeVisible();