Every contribution is welcome. The most useful one, by far: writing the analysis of a hero who does not have one yet.
Two kinds of data, which must not be confused.
| Where | Who writes it | |
|---|---|---|
| Factual data: heroes, skins, items, patches, visuals | src/data/game/, public/visuels/ |
Nobody: npm run sync extracts it from the wiki and the stats API |
| Analysis: commentary, written skills, counters, builds | src/data/heroes/ |
You |
| Articles: guides, news, patch notes | content/fr/ |
You |
| Tier list notes, emblems | src/data/tier-list.ts, src/data/emblems.ts |
You |
Never edit
src/data/game/orpublic/visuels/by hand. The next sync will overwrite your changes. If some game data is wrong, it comes from the wiki: fixing it there solves the problem for everyone, for good.
npm install
cp .env.example .env.local
npm run dev # http://localhost:3001The data and the visuals are already in the repository: nothing to sync before you start working.
The full guide (every field explained, the annotated template, the style rules and the review) is also online, in the site's four languages: mlbbdex.com/en/contribute.
- Copy the exact
slugfromsrc/data/game/heroes.json. - Open the role file in
src/data/heroes/(tanks.ts,fighters.ts,assassins.ts,mages.ts,marksmen.ts,supports.ts). - Copy the annotated template
docs/analysis-template.tsto the end of the list, fill it in, then remove its comments. The template follows theAnalyseHerostype fromsrc/lib/types.ts:npm run typecheckchecks it on every run, so it cannot go stale.
Do not add the role, lane, release date or difficulty: all of that already comes from the sync.
- Analyses are written in French, with their accents: this is text shown to visitors, not code.
- Game terms stay in English: items, skills, talents and spells keep the name players see in a match ("Winter Crown", "Flicker").
- Nothing copied: not from the wiki, a guide or a video. An analysis taken from elsewhere, even closely reworded, is rejected.
resume: one sentence. It is also used as the meta description.analyse: two paragraphs separated by a blank line: what the hero actually does, then their limits. No superlatives. "He is strong" is not an analysis; "he wins long fights as long as the enemy does not buy healing reduction" is.competences: the description, the cooldowns and the cost. The name is no longer displayed: it comes from the wiki, in the game's language, so that readers recognize the skill in a match. Keep the order passive, skill 1, skill 2, ultimate: that order is what matches your description to the right skill. Do not copy damage values: they change almost every patch.fortContre/faibleContre(strong against / weak against):slugs, not names.builds: thecontextefield explains when to pick the build. A build without context teaches nobody anything.
A Markdown file in content/fr/news/ or content/fr/patch-notes/,
named YYYY-MM-DD-title-as-slug.md. The date is used for sorting and is dropped
from the URL. npm run translate produces the English, Italian and Spanish
versions.
---
title: "Article title"
date: "2026-09-09"
category: "Guide" # News | Patch | Esports | Guide
author: "your-username"
summary: "A one-sentence summary, reused as the meta description and in the RSS feed."
keywords: ["keyword", "another"]
---
The article body, in Markdown.The ranking itself is not written by hand: it is computed from the win and ban
rates reported by the game, and updated at every sync (src/lib/tier-list.ts).
What you write is the note for a hero in notesTierList
(src/data/tier-list.ts): what the numbers do not say, why the hero sits
where they do at the current patch. A note is optional; a hero without one is
shown with their numbers only.
A note without an argument is not accepted.
It runs by itself every night (full sync on Mondays) and pushes its data straight to production. To run it by hand:
npm run sync -- --imagesdevelop: ongoing work. Every pull request targets it, and is merged by rebase or squash: never a merge commit.main: production, deployed on every push. To publish, once CI is green ondevelop:git push origin develop:main(fast-forward only), or the Publish to production button in Actions.
git switch develop && git pull --rebase
git switch -c my-contribution
# ... commits ...
git push -u origin my-contribution # then a pull request to developThe sync data lands on main every night and is carried over to develop,
which is replayed on top of it if needed: always pull it with
git pull --rebase (or git config pull.rebase true, once and for all).
npm run lint
npm run typecheck
npm test
npm run buildAll of them must pass: the automated checks will run them again anyway, along
with the browser tests (npm run test:e2e) and the content smoke check.
If you changed pages, messages or API responses, also run the smoke check
against your build: it reads the pages and the JSON the client relies on, and
lists every raw {placeholder}, empty page, missing translation or wrong key.
PORT=3009 npm start # after npm run build
node scripts/smoke-check.mjs http://127.0.0.1:3009 # in another terminalA new page or a moved route belongs in the table of
scripts/smoke-check-rules.mjs.
A few automations then follow the pull request:
- it fails automatically if it changes
src/data/game/orpublic/visuels/, which the sync regenerates; - if it conflicts with its target branch, it gets the
merge conflictlabel: rebase it; - if changes are requested, it goes back to draft with the
changes requestedlabel; mark it "Ready for review" again once it is fixed, and it gets theready for reviewlabel.
Every contribution goes through a pull request on GitHub. It can only be merged once the tests pass and after approval from the repository owner, who reviews both substance and form: accuracy at the current patch, style, originality. If something needs to change, they say so in a comment on the pull request; once merged, the analysis goes live at the next release to production.
Commit messages are in English, in the imperative: "Add the Ling analysis", "Fix Khufra's cooldown".
The site was written in French first: the French interface catalogue and the analyses are the reference text, and they keep their accents.
The code itself is written in English: identifiers, file names, comments, log
and error messages. Text shown to visitors never lives in the code: it goes
through the message catalogues (src/i18n/messages/). Comments explain
why, not what. If a comment paraphrases the next line, it is better
removed.