Retour au blog

Million Dollar Homepage: 21 Ans Apres, Ce Qu'une Page de 2005 Apprend sur le Link Rot

Salut HaWkers, le 26 aout 2026, la Million Dollar Homepage a fete ses 21 ans en ligne. Un etudiant de 21 ans appele Alex Tew, de Cricklade en Angleterre, a mis en ligne le 26 aout 2005 une page avec une grille de 1000 par 1000 pixels et a vendu chaque pixel 1 dollar, par blocs minimum de 10 par 10 a 100 dollars. En janvier 2006, il a mis aux encheres les 1.000 derniers pixels sur eBay: l'enchere a ouvert le 1er janvier, s'est cloturee le 11 janvier avec une offre de 38.100 dollars et a porte le total brut a 1.037.100 dollars.

La partie qui interesse ceux qui ecrivent du code, ce n'est pas l'argent. Au moment ou j'ecris cet article, milliondollarhomepage.com a repondu HTTP 200. La page est la, sur la meme URL, 21 ans apres. Et les liens qu'elle a vendus, eux, sont morts. Combien de vos URLs de 2019 repondent encore aujourd'hui? Et combien des liens que vous avez cites dans vos dix derniers articles menent encore quelque part?

La page qui a vendu un million de pixels

Le modele etait ridiculement simple et c'est pour ca qu'il a marche. Tew avait besoin d'argent pour ses etudes, il a monte une page avec un <img> geant de 1000 par 1000, une image map par-dessus, et il a vendu de l'espace publicitaire au pixel. Chaque annonceur envoyait le visuel du bloc et l'URL de destination. En cinq mois, d'aout 2005 a janvier 2006, le tout s'est cloture a 1.037.100 dollars bruts.

Techniquement, ce qui existe la-bas, c'est le minimum possible:

  • Du HTML statique servi directement.
  • Une grande image avec une <map> et des centaines d'elements <area>.
  • Aucune base de donnees devant, aucun framework, aucune etape de build.

Ce choix n'etait pas visionnaire, c'etait juste ce qu'on pouvait faire en 2005. Mais c'est exactement pour cela que la page a traverse trois decennies de changements de stack sans avoir besoin de maintenance. Pas de dependance a mettre a jour, pas de runtime a migrer, pas de version de Node a monter. Si vous aimez ce genre d'archeologie, j'ai deja ecrit sur la facon de recreer cette esthetique dans l'article sur le style retro en web design avec CSS et JavaScript.

Le paradoxe: la page vit, ses liens sont morts

Voila le retournement. Le contenant a survecu, le contenu vers lequel il pointe, non.

En 2014, quand la page avait neuf ans, une analyse citee par le Guardian et par Gizmodo a trouve 22% de liens morts, l'equivalent de 221.900 pixels. Parmi eux, 23.200 pixels sont nes casses, parce que l'annonceur n'a jamais fourni l'URL de destination. Autrement dit: environ 20% des liens sont morts en huit ans. En 2017, l'estimation enregistree sur Wikipedia parlait deja d'environ 40% des liens touches par le link rot.

Regardez bien ce qui s'est passe. Alex Tew a fait sa part: il a garde l'URL en vie pendant deux decennies. Ceux qui ont rompu le contrat, ce sont les centaines d'entreprises qui ont achete du pixel, change de domaine, ete rachetees, refait tout leur site ou tout simplement disparu. La durabilite de votre page ne depend pas que de vous. Elle depend de tous ceux que vous citez.

Le link rot n'est pas une anecdote, c'est une statistique

Le Pew Research Center a publie le 17 mai 2024 le rapport "When Online Content Disappears", et les chiffres sont brutaux:

  • 38% des pages qui existaient en 2013 n'etaient plus accessibles en octobre 2023.
  • 25% de toutes les pages ayant existe a un moment entre 2013 et 2023 avaient deja disparu.
  • 8% des pages qui existaient en 2023 avaient deja disparu la meme annee. La decomposition commence vite.
  • 23% des pages d'actualite ont au moins un lien casse.
  • 21% des pages de sites gouvernementaux aussi.
  • 54% des pages de Wikipedia ont au moins un lien mort dans la section des references.

Et sur les reseaux, la date de peremption est encore plus courte: en suivant un echantillon de tweets pendant trois mois, presque 1 sur 5 a cesse d'etre visible publiquement. Dans 60% des cas, le compte est passe en prive, a ete suspendu ou supprime; dans les 40% restants, l'auteur a supprime seulement ce post. Pour les tweets en turc ou en arabe, plus de 40% ont disparu en trois mois.

Traduit pour votre blog: si vous publiez depuis cinq ans, une part non negligeable de vos sources est deja de la fiction. Le texte continue d'affirmer quelque chose avec un lien qui ne prouve plus rien.

Cool URIs don't change: la regle de 1998 qui tient toujours

En 1998, Tim Berners-Lee a ecrit un court document appele "Cool URIs don't change", heberge sur w3.org/Provider/Style/URI. La these tient en une ligne: une fois que vous creez une URI, c'est votre obligation de la maintenir fonctionnelle pour toujours; si le document change de place, l'ancienne URL devient une redirection.

Pendant que j'ecrivais cet article, j'ai teste cette adresse. Elle a repondu HTTP 200. Vingt-huit ans sur la meme URL, a pratiquer ce qu'elle preche.

Ce que la plupart des equipes ignorent, c'est qu'une URL n'est pas un detail d'implementation, c'est un contrat public. Les erreurs classiques:

  • Mettre la technologie dans l'URL: /article.php, /posts.aspx. La technologie change, l'URL reste coincee.
  • Mettre une date ou un statut dans l'URL: /2024/nouveau/produit. L'annee prochaine, plus rien de tout cela n'est vrai.
  • Restructurer le site et laisser le 404 regler le probleme. Il ne le regle pas: vous perdez le lien externe, le classement et la citation.

Regle pratique: URL courte, sans extension, sans etat, et chaque ancien chemin devient un 301 permanent.

Auditer les liens de votre propre site

Assez de theorie. La premiere etape, c'est de savoir combien de liens de votre contenu sont deja morts. On peut le faire avec du Node pur, sans rien installer:

// scripts/check-links.mjs
// Parcourt les markdown du contenu et teste chaque lien externe.
import { readdir, readFile } from 'node:fs/promises'
import { join } from 'node:path'

const CONTENT_DIR = 'content/blog'
const CONCURRENCY = 8
const TIMEOUT_MS = 10000

async function collectLinks(dir) {
  const files = await readdir(dir, { withFileTypes: true })
  const found = new Map() // url -> fichiers ou il apparait

  for (const file of files) {
    if (!file.isFile() || !file.name.endsWith('.md')) continue

    const raw = await readFile(join(dir, file.name), 'utf8')
    // Capture uniquement les liens markdown vers http/https
    const matches = raw.matchAll(/\]\((https?:\/\/[^)\s]+)\)/g)

    for (const [, url] of matches) {
      if (!found.has(url)) found.set(url, [])
      found.get(url).push(file.name)
    }
  }

  return found
}

async function probe(url) {
  const controller = new AbortController()
  const timer = setTimeout(() => controller.abort(), TIMEOUT_MS)

  try {
    // HEAD est moins couteux, mais beaucoup de serveurs repondent 405
    let res = await fetch(url, { method: 'HEAD', redirect: 'follow', signal: controller.signal })
    if (res.status === 405 || res.status === 501) {
      res = await fetch(url, { method: 'GET', redirect: 'follow', signal: controller.signal })
    }
    return { url, status: res.status, ok: res.ok }
  } catch (error) {
    return { url, status: 0, ok: false, error: error.name }
  } finally {
    clearTimeout(timer)
  }
}

const links = await collectLinks(CONTENT_DIR)
const queue = [...links.keys()]
const broken = []

// Pool de concurrence manuel: ne fait tomber ni le serveur des autres ni le votre
await Promise.all(
  Array.from({ length: CONCURRENCY }, async () => {
    while (queue.length) {
      const url = queue.shift()
      const result = await probe(url)
      if (!result.ok) broken.push({ ...result, files: links.get(url) })
    }
  })
)

console.log(`Liens uniques verifies: ${links.size}`)
console.log(`Casses: ${broken.length}`)
for (const item of broken) {
  console.log(`${item.status || item.error}\t${item.url}\t${item.files.slice(0, 3).join(', ')}`)
}

process.exit(broken.length > 0 ? 1 : 0)

Lancez ca une fois sur votre ancien contenu. Le resultat fait mal, en general.

Mettre le check dans la CI toutes les semaines

L'audit manuel, c'est celui que vous faites une fois et plus jamais. Planifiez-le:

# .github/workflows/link-check.yml
name: link-check

on:
  schedule:
    # Tous les lundis a 06:00 UTC
    - cron: '0 6 * * 1'
  workflow_dispatch:

jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
      # Le job echoue quand un lien mort apparait, et l'alerte arrive par e-mail
      - run: node scripts/check-links.mjs

Rediriger au lieu de supprimer

Quand vous changez un slug, le lien externe qui pointait vers l'ancien ne change pas avec lui. La seule issue honnete, c'est la redirection permanente. Dans un projet Nuxt, ca vit dans les routeRules:

// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    // 301: permanent. Google transfere l'autorite de l'ancien lien.
    '/blog/ancien-post': { redirect: { to: '/blog/nouveau-post', statusCode: 301 } },

    // Section entiere qui a change de place
    '/articles/**': { redirect: { to: '/blog/**', statusCode: 301 } },
  },
})

Trois details qui font la difference:

  1. 301, pas 302. Le 302 est temporaire et dit au moteur de recherche de continuer a indexer l'ancienne URL. Si le changement est definitif, utilisez 301.
  2. N'enchainez pas les redirections. A -> B -> C marche dans le navigateur et gaspille le budget de crawl. Pointez A -> C directement.
  3. Ne redirigez jamais tout vers la home. Pour le moteur de recherche, rediriger un contenu disparu vers la home est traite comme un 404 deguise. S'il n'existe pas de destination equivalente, renvoyez un 410 honnete.

Sauvegarder ce que vous citez avant que ca disparaisse

Vous controlez vos URLs. Vous ne controlez pas les URLs que vous citez. La defense, c'est d'archiver la source au moment ou vous ecrivez, et pas le jour ou elle casse.

// scripts/archive-sources.mjs
// Envoie chaque source vers la Wayback Machine et garde le snapshot.
const SAVE_ENDPOINT = 'https://web.archive.org/save/'
const AVAILABILITY = 'https://archive.org/wayback/available?url='

export async function ensureArchived(url) {
  // 1. Un snapshot existe deja?
  const check = await fetch(`${AVAILABILITY}${encodeURIComponent(url)}`)
  const data = await check.json()
  const snapshot = data?.archived_snapshots?.closest

  if (snapshot?.available) {
    return { url, archived: snapshot.url, created: false }
  }

  // 2. Il n'existe pas: on demande l'archivage maintenant
  const saved = await fetch(`${SAVE_ENDPOINT}${url}`, { method: 'GET', redirect: 'follow' })

  if (!saved.ok) {
    throw new Error(`Echec de l'archivage de ${url}: HTTP ${saved.status}`)
  }

  return { url, archived: saved.url, created: true }
}

Avec ca, quand la source meurt, votre article continue de prouver ce qu'il affirme. Pour les citations les plus importantes, ca vaut le coup de lier directement le snapshot et de laisser l'original comme reference secondaire.

Une checklist pour des pages qui traversent la decennie

Ce que la Million Dollar Homepage a reussi sans le vouloir, vous pouvez le faire expres:

  • Une sortie statique chaque fois que possible. Du HTML qui ne depend pas d'un runtime ne casse pas quand le runtime est abandonne. Un site genere statiquement survit a un changement d'hebergeur avec un rsync.
  • Moins de dependances. Chaque paquet dans le package.json est une chance que le build de demain ne tourne pas. La page de 2005 en a zero.
  • Aucun contenu prisonnier d'une API tierce. Si le texte de votre article n'existe qu'a l'interieur d'un CMS SaaS, votre archive est entre les mains de la grille tarifaire de cette entreprise.
  • Des URLs sans technologie et sans date. /blog/nom-du-sujet survit a n'importe quelle migration.
  • Les assets sur votre domaine. Une image hebergee sur un service gratuit tiers, c'est du link rot avec une date de peremption.
  • Un sitemap et des lastmod corrects. Ca aide le moteur de recherche a voir ce qui est encore vivant.
  • Une sauvegarde du contenu en texte brut, versionnee dans Git. Du Markdown dans un depot est le format le plus durable qui existe aujourd'hui: du texte simple, lisible sans aucun outil.

Rien de tout cela n'est exotique. C'est l'inverse: c'est choisir l'ennuyeux et le simple plutot que l'impressionnant et le fragile.

Ce que ca change pour ceux qui publient en 2026

Il y a une bonne ironie ici. En 2005, publier une page qui dure etait la norme accidentelle, parce que la stack etait pauvre. En 2026, avec tout l'outillage que nous avons, publier quelque chose qui dure est devenu une decision deliberee, qui exige de la discipline contre la tentation d'ajouter une couche de plus.

Et la pression a augmente. Avec des moteurs de recherche et des assistants IA qui resument le contenu au lieu d'envoyer du clic, la citation qui reste, c'est le lien. Quand ce lien meurt, disparait aussi la preuve que votre travail a existe en premier. Garder une URL en vie a cesse d'etre une bonne pratique SEO pour devenir de la preservation de paternite.

La Million Dollar Homepage n'est pas un cas de succes de marketing viral, ou pas seulement. Elle est la preuve que la chose la plus difficile sur le web n'est pas de publier. C'est de rester publie. Alex Tew a fait sa part pendant 21 ans: lancez le script d'audit sur votre contenu aujourd'hui et decouvrez combien d'annees vous avez deja perdues.

Allez, on y va! 🦅

📚 Vous Voulez Suivre Ce Qui Arrive?

Cet article a couvert le link rot, les URLs permanentes et comment auditer son propre contenu, mais l'ecosysteme change chaque semaine et tout ne devient pas un article ici.

Sur X, je partage ce que je teste, les coulisses des projets et les nouveautes qui apparaissent avant de devenir un post.

Suivez-Moi La-Bas

👉 Suivre @jeffbruchado sur X

💡 Du contenu quotidien sur le developpement, la carriere et les outils que j'utilise vraiment

Commentaires (0)

Cet article n'a pas encore de commentaires. Soyez le premier!

Ajouter des commentaires