---
title: Marvel Archive
canonical: "https://presque.cool/projects/marvel-archive/"
description: "60 ans de comics Marvel en un site. 40 000+ numéros, navigation par année, série ou créateur — construit sur une API aujourd'hui disparue."
---

<div data-lang="fr">

## Le pitch

Marvel Archive est un catalogue de comics Marvel couvrant plus de 60 ans de publication (1965-2025). Plus de 40 000 single issues, navigables par année, série ou créateur, avec recherche plein texte. Le tout statique, offline, et construit sur les données d'une API aujourd'hui fermée.

**Consulter** : [presque.cool/marvel-archive/](https://presque.cool/marvel-archive/)

<div class="quick-overview">
  <div class="overview-item">
    <span class="overview-label">Durée</span>
    <span class="overview-value">~1 semaine</span>
  </div>
  <div class="overview-item">
    <span class="overview-label">Période</span>
    <span class="overview-value">Fév 2022 → Fév 2026</span>
  </div>
  <div class="overview-item">
    <span class="overview-label">Stack</span>
    <div class="tech-tags">
      <span class="tech-tag">Astro</span>
      <span class="tech-tag">Preact</span>
      <span class="tech-tag">Pagefind</span>
      <span class="tech-tag">PWA</span>
    </div>
  </div>
  <div class="overview-item">
    <span class="overview-label">Statut</span>
    <span class="overview-value accent">✓ En production</span>
  </div>
</div>

---

## Pourquoi ce projet

En février 2022, j'ai voulu expérimenter avec l'API Marvel Developer — une API REST officielle qui donnait accès au catalogue complet des comics Marvel. L'idée : construire un site de consultation élégant autour de cette base de données massive.

Le projet est pragmatique : seuls les **single issues** apparaissent. Pas de TPB, pas d'omnibus, pas de rééditions. L'objectif était de cartographier le catalogue de publication original, numéro par numéro.

---

## La mort de l'API

**Le 29 octobre 2025**, Marvel a fermé son API Developer. Du jour au lendemain, le site a cessé de fonctionner.

En février 2026, j'ai reconstruit Marvel Archive autour d'une **version locale des données** — un cache JSON organisé par année, récupéré avant la fermeture. Ce qui était un projet d'expérimentation API est devenu un véritable travail d'archivage : les données ne changeront plus, mais elles restent accessibles.

L'API disparue a donné au projet une raison d'être qu'il n'avait pas au départ. Il ne consomme plus un service, il en conserve la trace.

---

## L'architecture : 51 000 pages statiques

Le site génère environ **51 000 pages HTML** à la compilation. Chaque issue, chaque série, chaque créateur, chaque année, chaque page de pagination a sa propre URL statique. Le build pèse environ 1 Go et nécessite 8 Go de RAM (`--max-old-space-size=8192`) pour traiter ce volume.

Le pipeline de données :

```text
JSON par année (1965.json ... 2025.json)
  → Content Collections Astro (typage strict)
    → Index en mémoire (Map par série, créateur, année)
      → getStaticPaths() génère toutes les routes
        → 51 000 pages HTML statiques
```

Les index sont construits une seule fois au build et mis en cache : `Map<seriesId, Issue[]>`, `Map<creatorId, Issue[]>`, `Map<year, Issue[]>`. Chaque lookup est O(1).

---

## L'optimisation

Avec 51 000 pages et 40 000+ issues, l'optimisation n'est pas un luxe — c'est une contrainte structurelle. Le site doit être rapide à construire _et_ à consulter.

**Au build** :

- **8 Go de RAM** alloués via `--max-old-space-size=8192` — sans ça, Node.js plante avant d'avoir fini
- **Index pré-calculés en un seul passage** — les `Map` par série, créateur et année sont construites une fois au démarrage et réutilisées pour toutes les routes. Pas de re-parcours des données à chaque page
- **Projection minimale** — chaque issue est réduite à un résumé (titre, date, couverture, IDs) avant d'entrer dans le système de routes, limitant l'empreinte mémoire
- **Content Collections avec loaders inline** — les fichiers JSON par année sont fusionnés en une seule collection typée, évitant la duplication de parsing

**Au runtime** :

- **Preact (~3 Ko)** au lieu de React (~40 Ko) pour le seul composant interactif, hydraté en `client:idle`
- **Pagefind** — recherche plein texte entièrement côté client, sans serveur ni API. L'index est généré après le build et chargé à la demande
- **Cache Workbox** — images en cache 30 jours, fonts 1 an. Les pages visitées sont disponibles offline via le Service Worker
- **Lazy loading** des couvertures avec animation shimmer pendant le chargement
- **Script anti-flash** inline — le thème est appliqué avant le premier paint, zéro flash blanc
- **Prefetch automatique** — Astro précharge les liens visibles, rendant la navigation quasi instantanée
- **Zéro compute serveur** — tout est statique, servi depuis un simple hébergement de fichiers

---

## La navigation par année

L'entrée principale du site est une grille d'années (1965-2025). Cliquer sur une année affiche tous les numéros publiés cette année-là, paginés. C'est un mode de consultation qui invite à la sérendipité — on tombe sur des couvertures oubliées, des séries méconnues, des curiosités éditoriales.

Quatre chemins de navigation coexistent :

- **Par année** — exploration chronologique
- **Par série** — filtrage par titre
- **Par créateur** — bibliographie complète d'un auteur ou dessinateur
- **Recherche plein texte** — via Pagefind, un moteur de recherche statique recommandé par Astro, qui indexe les pages après le build sans serveur ni API

---

## Le choix Preact

Le site est construit avec Astro — zéro JavaScript par défaut, rendu statique. Mais la modale de paramètres (thème, langue) nécessite de l'interactivité côté client.

Utiliser React (~40 Ko) pour une seule modale était disproportionné. Preact (~3 Ko), avec une API quasi identique, était le bon compromis : même modèle de composants, fraction du poids. Le composant est chargé en `client:idle` — il n'est hydraté qu'une fois la page au repos.

---

## Le design Marvel

L'identité visuelle s'inspire directement de la charte officielle de Marvel.com :

- **Rouge Marvel** (`#ec1d25`) comme couleur d'accent
- **Dark-first** — fond sombre avec texte clair, mode light disponible
- **Couvertures en ratio 2:3** avec animation shimmer au chargement
- **Script anti-flash** — un snippet inline qui applique le thème avant le premier paint, évitant le flash blanc

---

## Stack technique

<ul class="tech-stack">
  <li><strong>Astro</strong> — Génération statique, Content Collections, prefetch automatique</li>
  <li><strong>Preact</strong> — Composant interactif (modale settings), chargé en <code>client:idle</code></li>
  <li><strong>Tailwind CSS</strong> — Variables CSS custom, dark/light mode</li>
  <li><strong>Pagefind</strong> — Recherche plein texte statique, indexation post-build</li>
  <li><strong>PWA</strong> via <code>@vite-pwa/astro</code> — Offline, cache Workbox (images 30j, fonts 1 an)</li>
  <li><strong>i18n</strong> maison — Français/anglais, détection navigateur</li>
  <li><strong>CSP</strong> — Content-Security-Policy avec hashes auto-générés</li>
</ul>

---

## Évolutions

| Date     | Version | Description                                                      |
| -------- | ------- | ---------------------------------------------------------------- |
| Fév 2022 | 1.0     | Version initiale — Consultation via API Marvel Developer         |
| Oct 2025 | —       | Fermeture de l'API Marvel — le site cesse de fonctionner         |
| Fév 2026 | 2.0     | Refonte complète — Données locales, Astro, Preact, Pagefind, PWA |

---

## Bilan

**Durée** : 1 semaine (février 2022, refondu en février 2026).

**Ce que j'ai appris** :

- Que la génération statique peut absorber des volumes de données massifs — 51 000 pages, à condition de pré-indexer et de gérer la mémoire
- Que la fermeture d'une API peut transformer un projet d'expérimentation en projet d'archivage avec une raison d'être plus forte

**Ce que je referais pareil** :

- L'approche pragmatique — ne montrer que les single issues donne une cohérence éditoriale au catalogue
- Preact plutôt que React pour un besoin d'interactivité minimal — le gain de poids est significatif

**Ce que je changerais** :

- Ajouter des filtres visuels plus poussés (par genre, par décennie, par popularité)
- Explorer une timeline visuelle interactive pour naviguer dans les 60 ans de publication

</div>

<div data-lang="en">

## The pitch

Marvel Archive is a Marvel comics catalog spanning over 60 years of publication (1965-2025). Over 40,000 single issues, browsable by year, series, or creator, with full-text search. Fully static, offline-capable, and built on data from a now-defunct API.

**Browse**: [presque.cool/marvel-archive/](https://presque.cool/marvel-archive/)

<div class="quick-overview">
  <div class="overview-item">
    <span class="overview-label">Duration</span>
    <span class="overview-value">~1 week</span>
  </div>
  <div class="overview-item">
    <span class="overview-label">Period</span>
    <span class="overview-value">Feb 2022 → Feb 2026</span>
  </div>
  <div class="overview-item">
    <span class="overview-label">Stack</span>
    <div class="tech-tags">
      <span class="tech-tag">Astro</span>
      <span class="tech-tag">Preact</span>
      <span class="tech-tag">Pagefind</span>
      <span class="tech-tag">PWA</span>
    </div>
  </div>
  <div class="overview-item">
    <span class="overview-label">Status</span>
    <span class="overview-value accent">✓ In production</span>
  </div>
</div>

---

## Why this project

In February 2022, I wanted to experiment with the Marvel Developer API — an official REST API that provided access to the full Marvel comics catalog. The idea: build an elegant browsing site around this massive database.

The project is pragmatic: only **single issues** are shown. No TPBs, no omnibuses, no reprints. The goal was to map the original publication catalog, issue by issue.

---

## The death of the API

**On October 29, 2025**, Marvel shut down its Developer API. Overnight, the site stopped working.

In February 2026, I rebuilt Marvel Archive around a **local version of the data** — a JSON cache organized by year, retrieved before the shutdown. What started as an API experiment became a genuine archival project: the data won't change anymore, but it remains accessible.

The defunct API gave the project a purpose it didn't have at the start. It no longer consumes a service, it keeps a record of one.

---

## The architecture: 51,000 static pages

The site generates approximately **51,000 HTML pages** at build time. Every issue, series, creator, year, and pagination page has its own static URL. The build weighs about 1 GB and requires 8 GB of RAM (`--max-old-space-size=8192`) to handle this volume.

The data pipeline:

```text
JSON per year (1965.json ... 2025.json)
  → Astro Content Collections (strict typing)
    → In-memory index (Map by series, creator, year)
      → getStaticPaths() generates all routes
        → 51,000 static HTML pages
```

Indexes are built once during the build and cached: `Map<seriesId, Issue[]>`, `Map<creatorId, Issue[]>`, `Map<year, Issue[]>`. Every lookup is O(1).

---

## Optimization

With 51,000 pages and 40,000+ issues, optimization isn't a luxury — it's a structural constraint. The site needs to be fast to build _and_ to browse.

**Build time**:

- **8 GB of RAM** allocated via `--max-old-space-size=8192` — without it, Node.js crashes before finishing
- **Pre-computed indexes in a single pass** — the `Map` structures for series, creators, and years are built once at startup and reused across all routes. No re-traversal per page
- **Minimal projection** — each issue is reduced to a summary (title, date, cover, IDs) before entering the routing system, limiting memory footprint
- **Content Collections with inline loaders** — yearly JSON files are merged into a single typed collection, avoiding redundant parsing

**Runtime**:

- **Preact (~3 KB)** instead of React (~40 KB) for the only interactive component, hydrated with `client:idle`
- **Pagefind** — fully client-side full-text search, no server or API. The index is generated after build and loaded on demand
- **Workbox caching** — images cached for 30 days, fonts for 1 year. Visited pages are available offline via Service Worker
- **Lazy loading** covers with shimmer animation during load
- **Anti-flash script** inline — theme is applied before first paint, zero white flash
- **Automatic prefetch** — Astro preloads visible links, making navigation near-instant
- **Zero server compute** — everything is static, served from simple file hosting

---

## Year-by-year navigation

The site's main entry point is a year grid (1965-2025). Clicking a year shows all issues published that year, paginated. It's a browsing mode that invites serendipity — you stumble upon forgotten covers, obscure series, editorial curiosities.

Four navigation paths coexist:

- **By year** — chronological exploration
- **By series** — filter by title
- **By creator** — an author's or artist's full bibliography
- **Full-text search** — via Pagefind, a static search engine recommended by Astro, which indexes pages after build with no server or API

---

## The Preact choice

The site is built with Astro — zero JavaScript by default, static rendering. But the settings modal (theme, language) requires client-side interactivity.

Using React (~40 KB) for a single modal was overkill. Preact (~3 KB), with a near-identical API, was the right trade-off: same component model, fraction of the weight. The component is loaded with `client:idle` — it's only hydrated once the page is idle.

---

## The Marvel design

The visual identity draws directly from the official Marvel.com brand guidelines:

- **Marvel red** (`#ec1d25`) as the accent color
- **Dark-first** — dark background with light text, light mode available
- **Cover images in 2:3 ratio** with shimmer loading animation
- **Anti-flash script** — an inline snippet that applies the theme before first paint, preventing white flash

---

## Tech stack

<ul class="tech-stack">
  <li><strong>Astro</strong> — Static generation, Content Collections, automatic prefetch</li>
  <li><strong>Preact</strong> — Interactive component (settings modal), loaded with <code>client:idle</code></li>
  <li><strong>Tailwind CSS</strong> — Custom CSS variables, dark/light mode</li>
  <li><strong>Pagefind</strong> — Static full-text search, post-build indexing</li>
  <li><strong>PWA</strong> via <code>@vite-pwa/astro</code> — Offline, Workbox caching (images 30d, fonts 1y)</li>
  <li><strong>i18n</strong> custom — French/English, browser detection</li>
  <li><strong>CSP</strong> — Content-Security-Policy with auto-generated hashes</li>
</ul>

---

## Timeline

| Date     | Version | Description                                             |
| -------- | ------- | ------------------------------------------------------- |
| Feb 2022 | 1.0     | Initial version — Browsing via Marvel Developer API     |
| Oct 2025 | —       | Marvel API shutdown — site stops working                |
| Feb 2026 | 2.0     | Full rewrite — Local data, Astro, Preact, Pagefind, PWA |

---

## Takeaways

**Duration**: 1 week (February 2022, rewritten February 2026).

**What I learned**:

- That static generation can absorb massive data volumes — 51,000 pages, provided you pre-index and manage memory
- That an API shutdown can transform an experiment into an archival project with a stronger purpose

**What I'd do the same**:

- The pragmatic approach — showing only single issues gives the catalog editorial coherence
- Preact over React for minimal interactivity needs — the weight savings are significant

**What I'd change**:

- Add more advanced visual filters (by genre, decade, popularity)
- Explore an interactive visual timeline to navigate 60 years of publication

</div>
